--- loncom/interface/lonwishlist.pm 2010/08/25 12:38:45 1.8 +++ loncom/interface/lonwishlist.pm 2011/01/27 14:38:44 1.9 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA -# Routines to control the wishlist +# Utility-routines for wishlist # -# $Id: lonwishlist.pm,v 1.8 2010/08/25 12:38:45 wenzelju Exp $ +# $Id: lonwishlist.pm,v 1.9 2011/01/27 14:38:44 wenzelju Exp $ # # Copyright Michigan State University Board of Trustees # @@ -39,12 +39,13 @@ It is only available for user with acces The wishlist-module uses the CPAN-module "Tree" for easily handling the directory-structure of the wishlist. Each node in the tree has an index to be referenced by. +=back + =cut package Apache::lonwishlist; use strict; -use Apache::Constants qw(:common); use Apache::lonnet; use Apache::loncommon(); use Apache::lonhtmlcommon; @@ -124,11 +125,6 @@ sub getWishlist { # Write wishlist to user-data sub putWishlist { my $wishlist = shift; - $foldersOption = ''; - &getFoldersForOption(\@childrenRt); - my $options = ''.$foldersOption; - $foldersOption = ''; - $$wishlist{'folders'} = $options; &Apache::lonnet::put('wishlist',$wishlist); } @@ -193,7 +189,11 @@ sub deleteWishlist { # Create a new entry sub newEntry() { - my ($title, $path, $note) = @_; + my ($rootgiven, $title, $path, $note) = @_; + + $root = $rootgiven; + @childrenRt = $root->children(); + my $date = gmtime(); # Create Entry-Object my $entry = Entry->new(title => $title, path => $path, note => $note, date => $date); @@ -204,53 +204,69 @@ sub newEntry() { if ($folderIndex ne '') { @allFolders = (); &getFoldersToArray(\@childrenRt); - my $folderToInsertOn = &Tree::getNodeByIndex($folderIndex,\@allFolders); + my $folderToInsertOn = &Apache::Tree::getNodeByIndex($folderIndex,\@allFolders); $folderToInsertOn->add_child($tree); } else { $root->add_child($tree); } - &saveChanges(); + return &saveChanges(); } # Delete entries sub deleteEntries { + my $rootgiven = shift; my $marked = shift; - &getNodesToArray(\@childrenRt); + $root = $rootgiven; + @childrenRt = $root->children(); + + &getNodesToArray(\@childrenRt); foreach my $m (@$marked) { - my $found = &Tree::getNodeByIndex($m, \@allNodes); - &Tree::removeNode($found); + my $found = &Apache::Tree::getNodeByIndex($m, \@allNodes); + # be sure, that entry exists (may have been deleted before, e.g. in an other browsertab) + if (defined $found) { + &Apache::Tree::removeNode($found); + } } @allNodes = (); - &saveChanges(); + return &saveChanges(); } # Sort entries sub sortEntries { + my $rootgiven = shift; my $indexNode = shift; my $at = shift; + + $root = $rootgiven; + @childrenRt = $root->children(); &getNodesToArray(\@childrenRt); - my $foundNode = &Tree::getNodeByIndex($indexNode, \@allNodes); + my $foundNode = &Apache::Tree::getNodeByIndex($indexNode, \@allNodes); - &Tree::moveNode($foundNode,$at,undef); + &Apache::Tree::moveNode($foundNode,$at,undef); @allNodes = (); + return &saveChanges(); } # Move entries sub moveEntries { + my $rootgiven = shift; my $indexNodesToMove = shift; my $indexParent = shift; my @nodesToMove = (); + $root = $rootgiven; + @childrenRt = $root->children(); + # get all nodes that should be moved &getNodesToArray(\@childrenRt); foreach my $index (@$indexNodesToMove) { - my $foundNode = &Tree::getNodeByIndex($index, \@allNodes); + my $foundNode = &Apache::Tree::getNodeByIndex($index, \@allNodes); push(@nodesToMove, $foundNode); } @@ -266,36 +282,46 @@ sub moveEntries { } if (!$parentIsIn) { if ($indexParent ne "root") { - $foundParent = &Tree::getNodeByIndex($indexParent, \@allNodes); - &Tree::moveNode($node,undef,$foundParent); + $foundParent = &Apache::Tree::getNodeByIndex($indexParent, \@allNodes); + &Apache::Tree::moveNode($node,undef,$foundParent); } else { - &Tree::moveNode($node,undef,$root); + &Apache::Tree::moveNode($node,undef,$root); } } } @allNodes = (); + return &saveChanges(); } # Set a new title for an entry sub setNewTitle { - my ($nodeindex, $newTitle) = @_; + my ($rootgiven, $nodeindex, $newTitle) = @_; + + $root = $rootgiven; + @childrenRt = $root->children(); + &getNodesToArray(\@childrenRt); - my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes); + my $found = &Apache::Tree::getNodeByIndex($nodeindex, \@allNodes); $found->value()->title($newTitle); @allNodes = (); + return &saveChanges(); } # Set a new path for an entry sub setNewPath { - my ($nodeindex, $newPath) = @_; + my ($rootgiven, $nodeindex, $newPath) = @_; + + $root = $rootgiven; + @childrenRt = $root->children(); + &getNodesToArray(\@childrenRt); - my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes); + my $found = &Apache::Tree::getNodeByIndex($nodeindex, \@allNodes); if ($found->value()->path()) { $found->value()->path($newPath); - return 1; + return &saveChanges(); } @allNodes = (); return 0; @@ -304,23 +330,29 @@ sub setNewPath { # Set a new note for an entry sub setNewNote { - my ($nodeindex, $newNote) = @_; + my ($rootgiven, $nodeindex, $newNote) = @_; + + $root = $rootgiven; + @childrenRt = $root->children(); + &getNodesToArray(\@childrenRt); - my $found = &Tree::getNodeByIndex($nodeindex, \@allNodes); + my $found = &Apache::Tree::getNodeByIndex($nodeindex, \@allNodes); $found->value()->note($newNote); @allNodes = (); + return &saveChanges(); } # Save all changes sub saveChanges { @childrenRt = $root->children(); - &Tree::TreeIndex(\@childrenRt); - &Tree::setCountZero(); - &Tree::RootToHash(\@childrenRt); - &Tree::TreeToHash(\@childrenRt); + &Apache::Tree::TreeIndex(\@childrenRt); + &Apache::Tree::setCountZero(); + &Apache::Tree::RootToHash(\@childrenRt); + &Apache::Tree::TreeToHash(\@childrenRt); &deleteWishlist(); &putWishlist(\%TreeToHash); + return $root; } @@ -349,7 +381,7 @@ sub saveChanges { 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). - =back +=back =cut @@ -553,7 +585,8 @@ sub JSforWishlist { 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 $warningMove = &mt('You must select a destination folder!'); + my $warningMoveS = &mt('You must select at minimum one entry to move!'); + my $warningMoveD = &mt('You must select a destination folder!'); $foldersOption = ''; my $js = &Apache::lonhtmlcommon::scripttag(<('.&mt('Top level').')'.$foldersOption; + $foldersOption = ''; + @allFolders = (); + + # HTML-Markup for 'Set a link for this resource to wishlist' + # this is written via JavaScript document.write (function set_wishlistlink) + # it is split into 3 parts and the inputfields for title and path are left out + # these fields are inserted later to set the values for title and path + # automatically via JavaScript (document.title and location.pathname) + + my $start_page_wishlistlink = + &Apache::loncommon::start_page('Set link to wishlist',undef, + {'only_body' => 1, + 'js_ready' => 1, + 'bgcolor' => '#FFFFFF',}); + + my $warningLink = &mt('You must insert a title!'); + + my $in_page_wishlistlink1 = '

'.&mt('Set a link to wishlist').'

'. + '
'. + &Apache::lonhtmlcommon::start_pick_box(). + &Apache::lonhtmlcommon::row_title(&mt('Link Title')); + + my $in_page_wishlistlink2 = &Apache::lonhtmlcommon::row_closure(). + &Apache::lonhtmlcommon::row_title(&mt('Path')); + + my $in_page_wishlistlink3 = &Apache::lonhtmlcommon::row_closure(). + &Apache::lonhtmlcommon::row_title(&mt('Note')). + ''. + &Apache::lonhtmlcommon::row_closure(1). + &Apache::lonhtmlcommon::end_pick_box(). + '

'. + ''. + ''. + ''. + '
'; + $options = ''; + + # remove all \n for inserting on javascript document.write + $in_page_wishlistlink1 =~ s/\n//g; + $in_page_wishlistlink2 =~ s/\n//g; + $in_page_wishlistlink3 =~ s/\n//g; + + my $end_page_wishlistlink = + &Apache::loncommon::end_page({'js_ready' => 1}); + + # Add JavaScript-function to set link for a ressource to wishlist + my $js.=<' + +'function newlinksubmit(){' + +'var title = document.getElementsByName("title")[0].value;' + +'if (!title) {' + +'alert("$warningLink");' + +'return false;}' + +'return true;}' + +'<\/scr'+'ipt>' + +'$in_page_wishlistlink1' + +'' + +'$in_page_wishlistlink2' + +'' + +'$in_page_wishlistlink3' + +'$end_page_wishlistlink' ); + wishlistlink.document.close(); +SCRIPT + + return $js; +} + # Returns the HTML-Markup for the page, shown when a link was set sub makePageSet { # start_page @@ -1635,7 +1774,11 @@ sub makePageSet { # Returns the HTML-Markup for the page, shown when links should be imported into a course sub makePageImport { + my $rootgiven = shift; my $rat = shift; + + $root = $rootgiven; + @childrenRt = $root->children(); # start_page my $startPage = &Apache::loncommon::start_page('Wishlist',undef, {'only_body' => 1}); @@ -1656,7 +1799,18 @@ sub makePageImport { .'

'; } my %wishlist = &getWishlist(); - my $fnum = (keys %wishlist)-1; + + #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 + my $fnum; + if (defined $wishlist{'folders'}) { + $fnum = (keys %wishlist)-2; + } + else { + $fnum = (keys %wishlist)-1; + } $inner .= '
'. ''. @@ -1711,133 +1865,10 @@ sub makeErrorPage { return $page; } -# ----------------------------------------------------- Main Handler, package lonwishlist -sub handler { - my ($r) = @_; - &Apache::loncommon::content_type($r,'text/html'); - $r->send_http_header; - - if (&getWishlist() ne 'error') { - # get wishlist entries from user-data db-file and build a tree out of these entries - %TreeHash = &getWishlist(); - $root = &Tree::HashToTree(); - @childrenRt = $root->children(); - - # greate a new entry - if ($env{'form.title'}) { - &newEntry($env{'form.title'}, $env{'form.path'}, $env{'form.note'}); - } - - # get unprocessed_cgi (i.e. marked entries, mode ...) - &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['action','mark','markedToMove','mode','newtitle','note','rat']); - - # change the order of entries within a level, that means sorting the entries - my $changeOrder = 0; - if (defined $env{'form.sel'}) { - my @sel = &Apache::loncommon::get_env_multiple('form.sel'); - my $indexNode; - my $at; - for (my $s=0; $s<($#sel+1); $s++) { - if ($sel[$s] ne '') { - $indexNode = $s; - $at = $sel[$s]-1; - } - } - if ($at ne '') { - $changeOrder = 1; - &sortEntries($indexNode,$at); - &saveChanges(); - } - } - - # get all marked (checkboxes) entries - my @marked = (); - if (defined $env{'form.mark'}) { - @marked = &Apache::loncommon::get_env_multiple('form.mark'); - } - - # move entries from one folder to another - if (defined $env{'form.markedToMove'}) { - my $markedToMove = $env{'form.markedToMove'}; - my @ToMove = split(/\,/,$markedToMove); - my $moveTo = $env{'form.mark'}; - if (defined $moveTo){ - &moveEntries(\@ToMove,$moveTo); - &saveChanges(); - } - $changeOrder = 1; - - } - - # delete entries - if ($env{'form.action'} eq 'delete') { - &deleteEntries(\@marked); - } - - - # get all titles and notes and save them - # 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.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) { - &setNewTitle($node, $t); - $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++; - } - &saveChanges(); - } - - # Create HTML-markup - my $page; - if ($env{'form.mode'} eq 'edit') { - $page = &makePage("edit"); - } - elsif ($env{'form.mode'} eq 'move') { - $page = &makePage("move", \@marked); - } - elsif ($env{'form.mode'} eq 'import') { - $page = &makePageImport($env{'form.rat'}); - } - elsif ($env{'form.mode'} eq 'set') { - $page = &makePageSet(); - } - else { - $page = &makePage("view"); - } - @marked = (); - $r->print($page); - } - # An error occured, print an error-page - else { - my $errorPage = &makeErrorPage(); - $r->print($errorPage); - } - return OK; -} # ----------------------------------------------------- package Tree # Extend CPAN-Module Tree by function like 'moveNode' or 'deleteNode' -package Tree; +package Apache::Tree; =pod @@ -1904,9 +1935,9 @@ sub getNodeByIndex { my $nodes = shift; my $found; - for my $n (@$nodes) { + foreach my $n (@$nodes) { my $curIndex = $n->value()->nindex(); - if ($n->value()->nindex() == $index) { + if ($curIndex == $index) { $found = $n; } } @@ -2020,15 +2051,16 @@ sub TreeToHash { # build a tree-object for each entry in the hash # afterwards call &buildTree to connect the tree-objects sub HashToTree { + my $TreeHash = shift; my @TreeNodes = (); my $root; - foreach my $key (keys %TreeHash) { + foreach my $key (keys %$TreeHash) { if ($key eq 'root') { $root = Tree->new("root"); } elsif ($key ne 'folders') { - my @attributes = @{ $TreeHash{$key} }; + my @attributes = @{ $$TreeHash{$key} }; my $tmpNode; $tmpNode = Tree->new(Entry->new(title=>$attributes[0], path=>$attributes[1], @@ -2042,13 +2074,13 @@ sub HashToTree { shift(@attributes); shift(@attributes); shift(@attributes); - $TreeHash{$key} = [ @attributes ]; + $$TreeHash{$key} = [ @attributes ]; } } # if there are nodes, build up the tree-structure - if (defined $TreeHash{'root'} && $TreeHash{'root'} ne '') { - my @childrenRtIn = @{ $TreeHash{'root'} }; - &buildTree(\$root, \@childrenRtIn,\@TreeNodes,\%TreeHash); + if (defined $$TreeHash{'root'} && $$TreeHash{'root'} ne '') { + my @childrenRtIn = @{ $$TreeHash{'root'} }; + &buildTree(\$root, \@childrenRtIn,\@TreeNodes,$TreeHash); } return $root; }