--- loncom/interface/lonwishlist.pm 2010/08/10 14:30:20 1.1
+++ loncom/interface/lonwishlist.pm 2010/08/16 13:37:41 1.3
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Routines to control the wishlist
#
-# $Id: lonwishlist.pm,v 1.1 2010/08/10 14:30:20 wenzelju Exp $
+# $Id: lonwishlist.pm,v 1.3 2010/08/16 13:37:41 wenzelju Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -36,6 +36,7 @@ use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon;
use Apache::lonlocal;
+use LONCAPA;
use Tree;
@@ -51,16 +52,14 @@ my $indentConst = 20;
# Read wishlist from user-data
sub getWishlist {
- my @wishlistkeys = &Apache::lonnet::getkeys('wishlist');
- my %wishlist = &Apache::lonnet::get('wishlist',\@wishlistkeys);
- foreach my $i (%wishlist) {
+ my %wishlist = &Apache::lonnet::dump('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/) {
&Apache::lonnet::logthis($i.'! Create file by putting in the "root" of the directory tree.');
&Apache::lonnet::put('wishlist', {'root' => ''});
- @wishlistkeys = &Apache::lonnet::getkeys('wishlist');
- %wishlist = &Apache::lonnet::get('wishlist',\@wishlistkeys);
+ %wishlist = &Apache::lonnet::dump('wishlist');
}
elsif ($i =~ /^(con_lost|error|no_such_host)/i) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: '.$i);
@@ -68,7 +67,8 @@ sub getWishlist {
}
}
- #If hash is empty, put 'root' into it, so we got a node to start the tree
+ # if we got no keys in hash returned by dump(), return error.
+ # wishlist will not be loaded, instead the user will be asked to try again later
if ((keys %wishlist) == 0) {
&Apache::lonnet::logthis('ERROR while attempting to get wishlist: no keys retrieved!');
return 'error';
@@ -148,6 +148,7 @@ sub moveEntries {
my $indexParent = shift;
my @nodesToMove = ();
+ # get all nodes that should be moved
&getNodesToArray(\@childrenRt);
foreach my $index (@$indexNodesToMove) {
my $foundNode = &Tree::getNodeByIndex($index, \@allNodes);
@@ -188,6 +189,20 @@ sub setNewTitle {
}
+# Set a new path for an entry
+sub setNewPath {
+ my ($nodeindex, $newPath) = @_;
+ &getNodesToArray(\@childrenRt);
+ my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes);
+ if ($found->value()->path()) {
+ $found->value()->path($newPath);
+ return 1;
+ }
+ @allNodes = ();
+ return 0;
+}
+
+
# Set a new note for an entry
sub setNewNote {
my ($nodeindex, $newNote) = @_;
@@ -241,7 +256,7 @@ sub getfoldersOption {
$root = &Tree::HashToTree();
@childrenRt = $root->children();
&getFoldersForOption(\@childrenRt);
- my $options = ''.$foldersOption;
+ my $options = ''.$foldersOption;
$foldersOption = '';
return $options;
}
@@ -321,7 +336,7 @@ sub JSforWishlist {
'
'.
''.
''.
''.
@@ -351,6 +366,17 @@ sub JSforWishlist {
$inPageNewLink =~ s/\n//g;
$inPageNewFolder =~ s/\n//g;
+ # it is checked, wether a path links to a LON-CAPA-resource or an external website. links to course-contents are not allowed
+ # because they probably will return a kind of 'no access' (unless the user is already in the course, the path links to).
+ # also importing these kind of links into a course does not make much sense.
+ # to find out if a path (not starting with /res/...) links to course-contents, the same filter as in lonwrapper is used,
+ # 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 $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!');
@@ -369,6 +395,15 @@ sub JSforWishlist {
+'if (!path || !title) {'
+'alert("$warningLink");'
+'return false;}'
+ +'var linkOK = (path.match(/^http:(\\\\/\\\\/)/) || path.match(/^https:(\\\\/\\\\/)/))'
+ +'&& !(path.match(/\\.problem/) || path.match(/\\.exam/)'
+ +'|| path.match(/\\.quiz/) || path.match(/\\.assess/)'
+ +'|| path.match(/\\.survey/) || path.match(/\\.form/)'
+ +'|| path.match(/\\.library/) || path.match(/\\.page/)'
+ +'|| path.match(/\\.sequence/));'
+ +'if (!path.match(/^(\\\\/res\\\\/)/) && !linkOK) {'
+ +'alert("$warningLinkNotAllowed1");'
+ +'return false;}'
+'else {'
+'window.close();'
+'return true;}}'
@@ -408,12 +443,18 @@ sub JSforWishlist {
if (d) {
if (!confirm('$warningSave')) {
setAction('noSave');
+ r = true;
+ }
+ else {
+ r = linksOK();
}
}
- r = true;
+ }
+ else if (action == 'saveOK') {
+ r = linksOK();
}
document.getElementsByName('list')[0].setAttribute("action", "/adm/wishlist?mode="+mode);
- if(r){
+ if (r) {
document.getElementsByName('list')[0].submit();
}
}
@@ -432,6 +473,15 @@ sub JSforWishlist {
return true;
}
}
+ var newpath = document.getElementsByName('newpath');
+ var i = 0;
+ for (i=0;i'.
+ 'value()->path()."'".');">'.
''.
- ''.$n->value()->title().'';
+ $n->value()->title().'';
}
# note-icon, different icons for an entries with note and those without
@@ -910,7 +1019,9 @@ sub wishlistEdit {
'
';
}
# entry is a link
@@ -918,12 +1029,11 @@ sub wishlistEdit {
$wishlistHTMLedit .= '
'.
'
'.
- '';
+ ''.
+ '
'.
+ '
';
}
-
- # input-field for title
- $wishlistHTMLedit .= '';
-
+
# note-icon, different icons for an entries with note and those without
my $noteIMG = 'anot.png';
@@ -939,7 +1049,7 @@ sub wishlistEdit {
# start row containing the textarea for the note
$wishlistHTMLedit .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
- '
'.
+ '
'.
'
';
@@ -999,19 +1109,17 @@ sub wishlistMove {
}
# entry is a link
else {
- if (!$isIn) {
- $wishlistHTMLmove .= '
'.
- '
';
- }
# higlight the title, if the link was selected to be moved
- else {
- $wishlistHTMLmove .= '
'.
- '
';
+ my $highlight = '';
+ if ($isIn) {
+ $highlight = 'style="color:red;"';
}
# link-image and title
- $wishlistHTMLmove .= ''.
- $n->value()->title().'
';
}
# note-icon, different icons for an entries with note and those without
@@ -1045,6 +1153,81 @@ sub wishlistMove {
}
}
+
+
+# HTML-Markup for table if in import-mode
+my $wishlistHTMLimport;
+my $indent = $indentConst;
+my $form = 1;
+sub wishlistImport {
+ my $nodes = shift;
+
+ foreach my $n (@$nodes) {
+ my $index = $n->value()->nindex();
+
+ # 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)
+ :&Apache::loncommon::continue_data_table_row('LC_hidden','row'.$index);
+
+
+ # checkboxes
+ $wishlistHTMLimport .= '
'.
+ ''.
+ ''.
+ ''.
+ ''.
+ '
';
+
+ # entry is a folder
+ if ($n->value()->path() eq '') {
+ $wishlistHTMLimport .= '
';
+ $form++;
+ }
+
+ # note-icon, different icons for an entries with note and those without
+ my $noteIMG = 'anot.png';
+
+ if ($n->value()->note() ne '') {
+ $noteIMG = 'anot2.png';
+ }
+
+ $wishlistHTMLimport .= '
';
+
+ $wishlistHTMLimport .= &Apache::loncommon::end_data_table_row();
+
+ # start row containing the textarea for the note, do not display note on default, readonly in import-mode
+ $wishlistHTMLimport .= &Apache::loncommon::continue_data_table_row('LC_hidden','note'.$index).
+ '
'.
+ '
';
+ $wishlistHTMLimport .= &Apache::loncommon::end_data_table_row();
+
+ # 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;
+ }
+ }
+}
+
# Returns the HTML-Markup for wishlist
sub makePage {
my $mode = shift;
@@ -1084,7 +1267,7 @@ sub makePage {
# icon for edit-mode, display when in view-mode
if ($mode eq 'view') {
$functions .= &Apache::lonhtmlcommon::add_item_funclist(''.
+ 'onclick="setFormAction('."'save','edit'".');" class="LC_menubuttons_link">'.
' '.
''.$lt{'ed'}.'');
@@ -1092,7 +1275,7 @@ sub makePage {
# icon for view-mode, display when in edit-mode
else {
$functions .= &Apache::lonhtmlcommon::add_item_funclist(''.
+ 'onclick="setFormAction('."'save','view'".');" class="LC_menubuttons_link">'.
' '.
''.$lt{'vw'}.'');
@@ -1128,7 +1311,7 @@ sub makePage {
# icon for saving changes
$functions .= &Apache::lonhtmlcommon::add_item_funclist(''.
+ 'onclick="setFormAction('."'saveOK','".$mode."'".'); " class="LC_menubuttons_link">'.
''.
''.$lt{'sv'}.'');
@@ -1142,7 +1325,7 @@ sub makePage {
'';
# only display subbox in view- or edit-mode
- if ($mode ne 'move') {
+ if ($mode eq 'view' || $mode eq 'edit') {
$inner .= $subbox;
}
@@ -1155,7 +1338,7 @@ sub makePage {
$inner .= &Apache::loncommon::end_data_table();
}
else {
- $inner .= ''.&mt("Your wihlist ist currently empty.").'';
+ $inner .= ''.&mt("Your wishlist ist currently empty.").'';
}
$wishlistHTMLedit = '';
}
@@ -1165,7 +1348,7 @@ sub makePage {
$inner .= '
'.$wishlistHTMLview.'
';
}
else {
- $inner .= ''.&mt("Your wihlist ist currently empty.").'';
+ $inner .= ''.&mt("Your wishlist ist currently empty.").'';
}
$wishlistHTMLview = '';
}
@@ -1177,8 +1360,8 @@ sub makePage {
if ($markStr) {
$markStr = substr($markStr, 0, length($markStr)-1);
$inner .= '';
- $inner .= ''.&mt('You have selected the red marked entries to be moved to another folder. '.
- 'Now choose the new destination folder.').'
';
+ $inner .= '
'.&mt('You have selected the red marked entries to be moved to another folder. '.
+ 'Now choose the new destination folder.').'
';
}
else {
- $inner .= ''.&mt("You haven't marked any entry to move.").' '.
+ $inner .= '
'.&mt("You haven't marked any entry to move.").'
'.
'';
}
}
@@ -1199,7 +1382,7 @@ sub makePage {
# end_page
my $endPage = &Apache::loncommon::end_page();
- # put all page-elements togther
+ # put all page-elements together
my $page = $startPage.$breadcrumbs.$js.$inner.$endPage;
return $page;
@@ -1223,13 +1406,60 @@ sub makePageSet {
# end_page
my $endPage = &Apache::loncommon::end_page();
- # put all page-elements togther
+ # put all page-elements together
my $page = $startPage.$inner.$endPage;
return $page;
}
+# Returns the HTML-Markup for the page, shown when links should be imported into a course
+sub makePageImport {
+ # start_page
+ my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
+ {'only_body' => 1});
+
+ # get javascript-code for wishlist-interactions
+ my $js = &JSforWishlist();
+
+ my $inner = '
'.&mt('Import Resources from Wishlist').'
';
+ $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.").'
';
+
+ my %wishlist = &getWishlist();
+ my $fnum = (keys %wishlist)-1;
+
+ $inner .= '';
+
+ # end_page
+ my $endPage = &Apache::loncommon::end_page();
+
+ # put all page-elements together
+ my $page = $startPage.$js.$inner.$endPage;
+
+ return $page;
+}
+
+
# Returns the HTML-Markup for error-page
sub makeErrorPage {
# breadcrumbs and start_page
@@ -1250,7 +1480,7 @@ sub makeErrorPage {
# end_page
my $endPage = &Apache::loncommon::end_page();
- # put all page-elements togther
+ # put all page-elements together
my $page = $startPage.$breadcrumbs.$inner.$endPage;
return $page;
@@ -1324,9 +1554,12 @@ sub handler {
# only save, if user wants to save changes
# do not save, when current action is 'delete' or 'sort' or 'move'
my @newTitles = ();
+ my @newPaths = ();
my @newNotes = ();
- if ((defined $env{'form.newtitle'} || defined $env{'form.newnote'}) && ($env{'form.action'} ne 'noSave') && ($env{'form.action'} ne 'delete') && !$changeOrder) {
+ if ((defined $env{'form.newtitle'} || defined $env{'form.newpath'} || defined $env{'form.newnote'})
+ && ($env{'form.action'} ne 'noSave') && ($env{'form.action'} ne 'delete') && !$changeOrder) {
@newTitles = &Apache::loncommon::get_env_multiple('form.newtitle');
+ @newPaths = &Apache::loncommon::get_env_multiple('form.newpath');
@newNotes = &Apache::loncommon::get_env_multiple('form.newnote');
my $node = 0;
foreach my $t (@newTitles) {
@@ -1334,6 +1567,14 @@ sub handler {
$node++;
}
$node = 0;
+ my $path = 0;
+ for (my $i = 0; $i < ($#newTitles+1); $i++ ) {
+ if (&setNewPath($node, $newPaths[$path])) {
+ $path++;
+ }
+ $node++;
+ }
+ $node = 0;
foreach my $n (@newNotes) {
&setNewNote($node, $n);
$node++;
@@ -1349,6 +1590,9 @@ sub handler {
elsif ($env{'form.mode'} eq 'move') {
$page = &makePage("move", \@marked);
}
+ elsif ($env{'form.mode'} eq 'import') {
+ $page = &makePageImport();
+ }
elsif ($env{'form.mode'} eq 'set') {
$page = &makePageSet();
}
@@ -1518,7 +1762,7 @@ sub HashToTree {
}
}
# if there are nodes, build up the tree-structure
- if (defined $TreeHash{'root'}) {
+ if (defined $TreeHash{'root'} && $TreeHash{'root'} ne '') {
my @childrenRtIn = @{ $TreeHash{'root'} };
&buildTree(\$root, \@childrenRtIn,\@TreeNodes,\%TreeHash);
}