--- loncom/interface/lonwishlist.pm 2012/05/16 11:26:03 1.13
+++ loncom/interface/lonwishlist.pm 2014/12/15 17:36:22 1.23
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Utility-routines for wishlist
#
-# $Id: lonwishlist.pm,v 1.13 2012/05/16 11:26:03 bisitz Exp $
+# $Id: lonwishlist.pm,v 1.23 2014/12/15 17:36:22 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -50,7 +50,7 @@ use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
-use LONCAPA;
+use LONCAPA qw(:DEFAULT :match);
use Tree;
@@ -94,10 +94,10 @@ my $foldersOption;
sub getWishlist {
my @keys = &Apache::lonnet::getkeys('wishlist');
my %wishlist = &Apache::lonnet::get('wishlist',\@keys);
- foreach my $i ( keys %wishlist) {
+ foreach my $i (keys(%wishlist)) {
#File not found. This appears at the first time using the wishlist
#Create file and put 'root' into it
- if ($i =~m/^error:No such file/) {
+ if ($i =~m/^\Qerror:No such file\E/) {
&Apache::lonnet::logthis($i.'! Create file by putting in the "root" of the directory tree.');
&Apache::lonnet::put('wishlist', {'root' => ''});
my $options = '';
@@ -113,7 +113,7 @@ sub getWishlist {
# if we got no keys in hash returned by get(), return error.
# wishlist will not be loaded, instead the user will be asked to try again later
- if ((keys %wishlist) == 0) {
+ if ((keys(%wishlist)) == 0) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: no keys retrieved!');
return 'error';
}
@@ -197,7 +197,7 @@ sub newEntry() {
my $date = gmtime();
# Create Entry-Object
my $entry = Entry->new(title => $title, path => $path, note => $note, date => $date);
- # Create Tree-Object, this correspones a node in the wishlist-tree
+ # Create Tree-Object, this corresponds a node in the wishlist-tree
my $tree = Tree->new($entry);
# Add this node to wishlist-tree
my $folderIndex = $env{'form.folders'};
@@ -466,11 +466,13 @@ sub getNodesToArray {
Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
-=item * &wishlistImport(nodes)
+=item * &wishlistImport(nodes, numskipped)
Returns the table-HTML-markup for the wishlist in mode "import".
- Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
-
+ Recursive call starting with all children of the root of the tree (parameter nodes is reference to an array containing the nodes of the current level).
+ Side effect: increments the scalar ref: numskipped with a count of items in
+ Stored Links unavailable for selection, (e.g., now marked obsolete or
+ inaccessible in Community context).
=item * &makePage(mode, marked)
@@ -528,14 +530,16 @@ sub JSforWishlist {
# that means that it is checked wether a path contains .problem, .quiz, .exam etc.
# this is good for most cases but crashes as soon as a real external website contains one of this pattern in its URL.
# so maybe there's a better way to find out wether a given URL belongs to a LON-CAPA-server or not ...?
- my $warningLinkNotAllowed1 = &mt('You can only insert links to LON-CAPA resources from the resource-pool '.
- 'or to external websites. Paths to LON-CAPA resources must be of the form /res/dom/usr... . '.
- 'Paths to external websites must contain the network protocol (e.g. http://...).');
- my $warningLinkNotAllowed2 = &mt('The following link is not allowed: ');
+ my $warningLinkNotAllowed1 =
+ &mt('You can only insert links to LON-CAPA resources from the resource-pool'.
+ ' or to external websites.'.
+ ' Paths to LON-CAPA resources must be of the form /res/domain/user/...'.
+ ' Paths to external websites must contain the network protocol, e.g. http://...');
+ my $warningLinkNotAllowed2 = &mt('The following link is not allowed:').' ';
my $warningLink = &mt('You must insert a title and a path!');
my $warningFolder = &mt('You must insert a title!');
my $warningDelete = &mt('Are you sure you want to delete the selected entries? Deleting a folder also deletes all entries within this folder!');
- my $warningSave = &mt('You have unsaved changes. You can either save these changes now by clicking "ok" or click "cancel" if you do not want to save your changes.');
+ my $warningSave = &mt('You have unsaved changes. You can either save these changes now by clicking "OK" or click "Cancel" if you do not want to save your changes.');
my $warningMoveS = &mt('You must select at minimum one entry to move!');
my $warningMoveD = &mt('You must select a destination folder!');
$foldersOption = '';
@@ -808,7 +812,9 @@ sub JSforWishlist {
function setChecked(row,checked) {
var childCHECK = document.getElementById(row.id.replace('row','check'));
- childCHECK.checked = checked;
+ if (!childCHECK.disabled) {
+ childCHECK.checked = checked;
+ }
}
function getPreviousFolderRows(row) {
@@ -1008,14 +1014,18 @@ sub JSforWishlist {
function checkAll() {
var checkboxes = document.getElementsByName('check');
for (var i = 0; i < checkboxes.length; i++) {
- checkboxes[i].checked = "checked";
+ if (!checkboxes[i].disabled) {
+ checkboxes[i].checked = "checked";
+ }
}
}
function uncheckAll() {
var checkboxes = document.getElementsByName('check');
for (var i = 0; i < checkboxes.length; i++) {
- checkboxes[i].checked = "";
+ if (!checkboxes[i].disabled) {
+ checkboxes[i].checked = "";
+ }
}
}
@@ -1032,6 +1042,12 @@ sub JSforImport{
function finish_import() {
opener.document.forms.simpleedit.importdetail.value='';
for (var num = 0; num < document.forms.groupsort.fnum.value; num++) {
+ try {
+ eval("document.forms.groupsort.filelink"+num+".value");
+ }
+ catch(err) {
+ continue;
+ }
if (eval("document.forms.groupsort.check"+num+".checked") && eval("document.forms.groupsort.filelink"+num+".value") != '') {
opener.document.forms.simpleedit.importdetail.value+='&'+
eval("document.forms.groupsort.title"+num+".value")+'='+
@@ -1088,7 +1104,7 @@ JAVASCRIPT
# HTML-Markup for table if in view-mode
my $wishlistHTMLview;
-my $indent = $indentConst;
+my $indent_view = $indentConst;
sub wishlistView {
my $nodes = shift;
@@ -1107,7 +1123,7 @@ sub wishlistView {
# entry is a folder
if ($n->value()->path() eq '') {
- $wishlistHTMLview .= '
';
@@ -1145,9 +1161,9 @@ sub wishlistView {
# if the entry is a folder, it could have other entries as content. if it has, call wishlistView for those entries
my @children = $n->children();
if ($#children >=0) {
- $indent += 20;
+ $indent_view += 20;
&wishlistView(\@children);
- $indent -= 20;
+ $indent_view -= 20;
}
}
}
@@ -1155,7 +1171,7 @@ sub wishlistView {
# HTML-Markup for table if in edit-mode
my $wishlistHTMLedit;
-my $indent = $indentConst;
+my $indent_edit = $indentConst;
sub wishlistEdit {
my $nodes = shift;
my $curNode = 1;
@@ -1190,7 +1206,7 @@ sub wishlistEdit {
if ($n->value()->path() eq '') {
$wishlistHTMLedit .= '
';
@@ -1232,9 +1248,9 @@ sub wishlistEdit {
# if the entry is a folder, it could have other entries as content. if it has, call wishlistEdit for those entries
my @children = $n->children();
if ($#children >=0) {
- $indent += 20;
+ $indent_edit += 20;
&wishlistEdit(\@children);
- $indent -= 20;
+ $indent_edit -= 20;
}
}
}
@@ -1244,7 +1260,7 @@ sub wishlistEdit {
# HTML-Markup for table if in move-mode
my $wishlistHTMLmove ='
'.
'
'.&mt('Top level').'
';
-my $indent = $indentConst;
+my $indent_move = $indentConst;
sub wishlistMove {
my $nodes = shift;
my $marked = shift;
@@ -1268,12 +1284,12 @@ sub wishlistMove {
# display a radio-button, if the folder was not selected to be moved
if (!$isIn) {
$wishlistHTMLmove .= '
'.
- '
';
+ '
';
}
- # higlight the title, if the folder was selected to be moved
+ # highlight the title, if the folder was selected to be moved
else {
$wishlistHTMLmove .= '
'.
- '
';
}
#arrow- and folder-image, all folders are open, and title
@@ -1290,7 +1306,7 @@ sub wishlistMove {
}
# link-image and title
$wishlistHTMLmove .= '
';
@@ -1320,9 +1336,9 @@ sub wishlistMove {
# if the entry is a folder, it could have other entries as content. if it has, call wishlistMove for those entries
my @children = $n->children();
if ($#children >=0) {
- $indent += 20;
+ $indent_move += 20;
&wishlistMove(\@children, $marked);
- $indent -= 20;
+ $indent_move -= 20;
}
}
}
@@ -1331,14 +1347,48 @@ sub wishlistMove {
# HTML-Markup for table if in import-mode
my $wishlistHTMLimport;
-my $indent = $indentConst;
+my $indent_imp = $indentConst;
my $form = 1;
sub wishlistImport {
- my $nodes = shift;
+ my ($nodes,$numskipped) = @_;
+
+ my ($is_community,%nopick);
+ if ($env{'request.course.id'}) {
+ if (&Apache::loncommon::course_type() eq 'Community') {
+ $is_community = 1;
+ }
+ }
foreach my $n (@$nodes) {
my $index = $n->value()->nindex();
+ #
+ # Determine which resources in stored links may be imported into a course/community.
+ # (a) Import of directories in /res space is not supported.
+ # (b) Import of a resource into a community requires user has 'bro' privilege for resource
+ # (i.e., user has author or co-author role for corresponcding Authoring Space).
+ # (c) Import of a resource into a course requires user has 'be' privilege for resource.
+ #
+
+ if ($n->value()->path() =~ m{^(/res/$match_domain/$match_username/)}) {
+ if ($n->value()->path() =~ m{/$}) {
+ $nopick{$n->value()->path()} = $n->value()->title();
+ $$numskipped ++;
+ } else {
+ if ($is_community) {
+ unless (&Apache::lonnet::allowed('bro',$n->value()->path())) {
+ $nopick{$n->value()->path()} = $n->value()->title();
+ $$numskipped ++;
+ }
+ } else {
+ unless (&Apache::lonnet::allowed('bre',$n->value()->path())) {
+ $nopick{$n->value()->path()} = $n->value()->title();
+ $$numskipped ++;
+ }
+ }
+ }
+ }
+
# start row, use data_table routines to set class to LC_even or LC_odd automatically. this row contains a checkbox, the title and the note-icon.
# only display the top level entries on load
$wishlistHTMLimport .= ($n->parent()->value() eq 'root')?&Apache::loncommon::start_data_table_row('','row'.$index)
@@ -1346,17 +1396,26 @@ sub wishlistImport {
# checkboxes
- $wishlistHTMLimport .= '
';
$form++;
}
@@ -1395,11 +1456,12 @@ sub wishlistImport {
# if the entry is a folder, it could have other entries as content. if it has, call wishlistImport for those entries
my @children = $n->children();
if ($#children >=0) {
- $indent += 20;
- &wishlistImport(\@children);
- $indent -= 20;
+ $indent_imp += 20;
+ &wishlistImport(\@children,$numskipped);
+ $indent_imp -= 20;
}
}
+ return;
}
# Returns the HTML-Markup for wishlist
@@ -1421,7 +1483,7 @@ sub makePage {
'onload' => 'javascript:onLoadAction('."'".$mode."'".');',
'onunload' => 'javascript:window.name = '."'loncapaclient'"}});
- my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Stored Links').&Apache::loncommon::help_open_topic('Wishlist'));
+ my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Stored Links'),'Wishlist');
# get javascript-code for wishlist-interactions
my $js = &JSforWishlist();
@@ -1591,9 +1653,11 @@ sub makePopUpNewLink {
'bgcolor' => '#FFFFFF',});
my $warningLink = &mt('You must insert a title!');
- my $warningLinkNotAllowed1 = &mt('You can only insert links to LON-CAPA resources from the resource-pool '.
- 'or to external websites. Paths to LON-CAPA resources must be of the form /res/dom/usr... . '.
- 'Paths to external websites must contain the network protocol (e.g. http://...).');
+ my $warningLinkNotAllowed1 =
+ &mt('You can only insert links to LON-CAPA resources from the resource-pool'.
+ ' or to external websites.'.
+ ' Paths to LON-CAPA resources must be of the form /res/domain/user/...'.
+ ' Paths to external websites must contain the network protocol, e.g. http://...');
my $inPageWishlistlink1 = '
'.&mt('Save to Stored Links').'
';
# If no title is delivered, 'New Link' is called up from the wishlist-interface, so after
@@ -1623,7 +1687,7 @@ sub makePopUpNewLink {
''.
- ''.
+ ''.
'';
$options = '';
@@ -1742,25 +1806,28 @@ SCRIPT
# Returns the HTML-Markup for the page, shown when a link was set
sub makePageSet {
- # start_page
- my $startPage = &Apache::loncommon::start_page('Stored Links',undef,
- {'only_body' => 1});
+ my $title = 'Stored Links';
+
+ # start_page
+ my $output =
+ &Apache::loncommon::start_page($title,undef,
+ {'only_body' => 1})
+ .'
'.&mt($title).'
';
# confirm success and offer link to wishlist
- my $message = &Apache::lonhtmlcommon::confirm_success(&mt('Link successfully saved!'));
- $message = &Apache::loncommon::confirmwrapper($message);
-
- my $inner .= ' '.$message.'
'.
- ''.&mt('Go to Stored Links').''.(' ' x 3).
- ''.&mt('Close this window').'';
+ $output .=
+ &Apache::loncommon::confirmwrapper(
+ &Apache::lonhtmlcommon::confirm_success(
+ &mt('Link successfully saved!')))
+ .&Apache::lonhtmlcommon::actionbox(
+ [''.&mt('Go to Stored Links').'',
+ ''.&mt('Close this window').''
+ ]);
# end_page
- my $endPage = &Apache::loncommon::end_page();
-
- # put all page-elements together
- my $page = $startPage.$inner.$endPage;
+ $output .= &Apache::loncommon::end_page();
- return $page;
+ return $output;
}
@@ -1781,27 +1848,34 @@ sub makePageImport {
my $inner = '
'.&mt('Import Resources from Stored Links').'
';
if (!$rat) {
- $inner .= '
'.&mt("Please note that you can use the checkboxes corresponding to a folder to ".
- "easily check all links within this folder. The folder structure itself can't be imported. ".
- "All checked links will be imported into the current folder of your course.").'
';
+ $inner .=
+ '
'.
+ '
'.&mt('Use the checkboxes corresponding to a folder to '.
+ 'easily check all links within the folder.').'
'.
+ '
'.&mt('The folder structure itself cannot be imported.').'
'.
+ '
'.&mt('All checked links will be imported into the current folder of your course.').'
'.
+ '
';
}
else {
- $inner .= '
'.&mt("Please note that you can use the checkboxes corresponding to a folder to ".
- "easily check all links within this folder. The folder structure itself can't be imported. ")
- .'
';
+ $inner .=
+ '
'.
+ '
'.&mt('Use the checkboxes corresponding to a folder to '.
+ 'easily check all links within this folder.').'
'.
+ '
'.&mt('The folder structure itself cannot be imported.').'
'.
+ '
';
}
my %wishlist = &getWishlist();
#FIXME Saved string containing all folders in wishlist.db-file (key 'folders') in first version of lonwishlist
#After splitting lonwishlist into two modules, this is not necessary anymore. So, dependent from when the wishlist
#was first called (i.e. when wishlist.db was created), there might be an entry 'folders' or not. Number of links in
- #wishlist.db depends on wether this entry exists or not...JW
+ #wishlist.db depends on whether this entry exists or not...JW
my $fnum;
if (defined $wishlist{'folders'}) {
- $fnum = (keys %wishlist)-2;
+ $fnum = (keys(%wishlist))-2;
}
else {
- $fnum = (keys %wishlist)-1;
+ $fnum = (keys(%wishlist))-1;
}
$inner .= '';
@@ -1839,14 +1917,14 @@ sub makeErrorPage {
# breadcrumbs and start_page
&Apache::lonhtmlcommon::add_breadcrumb(
{ href => '/adm/wishlist',
- text => 'Wishlist'});
+ text => 'Stored Links'});
my $startPage = &Apache::loncommon::start_page('Stored Links');
- my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Stored Links').&Apache::loncommon::help_open_topic('Wishlist'));
+ my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Stored Links'),'Wishlist');
&Apache::lonhtmlcommon::clear_breadcrumbs();
# error-message
- my $inner .= ''.&mt('An error occurred! Please try again later.').'';
+ my $inner .= '
'.&mt('An error occurred! Please try again later.').'
';
# end_page
my $endPage = &Apache::loncommon::end_page();
@@ -2047,7 +2125,7 @@ sub HashToTree {
my @TreeNodes = ();
my $root;
- foreach my $key (keys %$TreeHash) {
+ foreach my $key (keys(%$TreeHash)) {
if ($key eq 'root') {
$root = Tree->new("root");
}