Diff for /loncom/interface/lonwishlist.pm between versions 1.3 and 1.8

version 1.3, 2010/08/16 13:37:41 version 1.8, 2010/08/25 12:38:45
Line 26 Line 26
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
   
   =pod
   
   =head1 NAME
   
   Apache::lonwishlist - Wishlist-Module
     
   =head1 SYNOPSIS
   
   The wishlist offers a possibility to store links to resources from the resource-pool and external websites in a hierarchical list.
   It is only available for user with access to the resource-pool. The list can be structured by folders.
   
   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.
   
   =cut
   
 package Apache::lonwishlist;  package Apache::lonwishlist;
   
Line 48  my %TreeToHash; Line 61  my %TreeToHash;
 my @allFolders;  my @allFolders;
 my @allNodes;  my @allNodes;
 my $indentConst = 20;  my $indentConst = 20;
   my $foldersOption;
   
   =pod
   
   =head2 Routines for getting and putting the wishlist data from and accordingly to users data.
   
   =over 4
   
   =item * &getWishlist()
   
        Get the wishlist-data via lonnet::getkeys() and lonnet::get() and returns the got data in a hash.
   
   
   =item * &putWishlist(wishlist)
   
        Parameter is a reference to a hash. Puts the wishlist-data contained in the given hash via lonnet::put() to user-data.
   
   
   =item * &deleteWishlist()
   
        Deletes all entries from the user-data for wishlist. Do this before putting in new data.
   
   
   =back
   
   =cut
   
   
 # Read wishlist from user-data  # Read wishlist from user-data
 sub getWishlist {  sub getWishlist {
     my %wishlist = &Apache::lonnet::dump('wishlist');      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          #File not found. This appears at the first time using the wishlist
         #Create file and put 'root' into it          #Create file and put 'root' into it
        if ($i =~m/^error:No such file/) {         if ($i =~m/^error:No such file/) {
            &Apache::lonnet::logthis($i.'! Create file by putting in the "root" of the directory tree.');             &Apache::lonnet::logthis($i.'! Create file by putting in the "root" of the directory tree.');
            &Apache::lonnet::put('wishlist', {'root' => ''});             &Apache::lonnet::put('wishlist', {'root' => ''});
            %wishlist = &Apache::lonnet::dump('wishlist');             my $options = '<option value="" selected="selected">('.&mt('Top level').')</option>';
              &Apache::lonnet::put('wishlist', {'folders' => $options});
              @keys = &Apache::lonnet::getkeys('wishlist');
              %wishlist = &Apache::lonnet::get('wishlist',\@keys);
        }         }
        elsif ($i =~ /^(con_lost|error|no_such_host)/i) {         elsif ($i =~ /^(con_lost|error|no_such_host)/i) {
            &Apache::lonnet::logthis('ERROR while attempting to get wishlist: '.$i);             &Apache::lonnet::logthis('ERROR while attempting to get wishlist: '.$i);
Line 67  sub getWishlist { Line 110  sub getWishlist {
        }         }
     }      }
   
     # if we got no keys in hash returned by dump(), return error.      # 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      # 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!');          &Apache::lonnet::logthis('ERROR while attempting to get wishlist: no keys retrieved!');
Line 81  sub getWishlist { Line 124  sub getWishlist {
 # Write wishlist to user-data  # Write wishlist to user-data
 sub putWishlist {  sub putWishlist {
     my $wishlist = shift;      my $wishlist = shift;
       $foldersOption = '';
       &getFoldersForOption(\@childrenRt);
       my $options = '<option value="" selected="selected">('.&mt('Top level').')</option>'.$foldersOption;
       $foldersOption = '';
       $$wishlist{'folders'} = $options;
     &Apache::lonnet::put('wishlist',$wishlist);      &Apache::lonnet::put('wishlist',$wishlist);
 }  }
   
Line 92  sub deleteWishlist { Line 140  sub deleteWishlist {
 }  }
   
   
   =pod
   
   =head2 Routines for changing the directory struture of the wishlist.
   
   =over 4
   
   =item * &newEntry(title, path, note)
   
        Creates a new entry in the wishlist containing the given informations. Additionally saves the date of creation in the entry.  
   
   
   =item * &deleteEntries(marked)
   
        Parameter is a reference to an array containing the indices of all nodes that should be removed from the tree. 
   
   
   =item * &sortEntries(indexNode, at)
   
        Changes the position of a node given by indexNode within its siblings. New position is given by at.
   
   
   =item * &moveEntries(indexNodesToMove, indexParent)
   
        Parameter is a reference to an array containing the indices of all nodes that should be moved. indexParent specifies the node that will become the new Parent for these nodes. 
   
   
   =item * &setNewTitle(nodeindex, newTitle)
   
        Sets the title for the node given by nodeindex to newTitle.
   
   
   =item * &setNewPath(nodeindex, newPath)
   
        Sets the path for the node given by nodeindex to newPath.
   
   
   =item * &setNewNote(nodeindex, newNote)
   
        Sets the note for the node given by nodeindex to newNote.     
   
   
   =item * &saveChanges()
   
        Prepares the wishlist-hash to save it via &putWishlist(wishlist).   
   
   
   =back
   
   =cut
   
   
 # Create a new entry  # Create a new entry
 sub newEntry() {  sub newEntry() {
     my ($title, $path, $note) = @_;      my ($title, $path, $note) = @_;
Line 226  sub saveChanges { Line 325  sub saveChanges {
 }  }
   
   
   =pod
   
   =head2 Routines for handling the directory structure
   
   =over 4
   
   =item * &getFoldersForOption(nodes)
   
        Return the titles for all exiting folders in an option-tag, used to offer the users a possibility to create a new link or folder in an existing folder.
        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 * &getFoldersToArray(children)
   
        Puts all nodes that represent folders in the wishlist into an array. 
        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 * &getNodesToArray(children)
   
        Puts all existing nodes into an array (apart from the root node, because this one does not represent an entry in the wishlist).
        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
   
   =cut
   
   
 # Return the names for all exiting folders in option-tags, so  # Return the names for all exiting folders in option-tags, so
 # a new link or a new folder can be created in an existing folder  # a new link or a new folder can be created in an existing folder
 my $indent = 0;  my $indent = 0;
 my $foldersOption;  
 sub getFoldersForOption {  sub getFoldersForOption {
     my $nodes = shift;      my $nodes = shift;
   
Line 250  sub getFoldersForOption { Line 377  sub getFoldersForOption {
 }  }
   
   
 sub getfoldersOption {  
    if (&getWishlist ne 'error') {  
        %TreeHash = &getWishlist();  
        $root = &Tree::HashToTree();  
        @childrenRt = $root->children();  
        &getFoldersForOption(\@childrenRt);  
        my $options = '<option value="" selected="selected">('.&mt('Top level').')</option>'.$foldersOption;  
        $foldersOption = '';  
        return $options;  
    }  
    else {  
        return '';  
    }  
 }  
   
   
 # Put all folder-nodes to an array  # Put all folder-nodes to an array
 sub getFoldersToArray {  sub getFoldersToArray {
     my $children = shift;      my $children = shift;
Line 294  sub getNodesToArray { Line 405  sub getNodesToArray {
 }  }
   
   
   =pod
   
   =head2 Routines for the user-interface of the wishlist
   
   =over 4
   
   =item * &JSforWishlist()
   
        Returns JavaScript-functions needed for wishlist actions like open and close folders.
   
   
   =item * &wishlistView(nodes)
   
        Returns the table-HTML-markup for the wishlist in mode "view".
        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 * &wishlistEdit(nodes)
   
        Returns the table-HTML-markup for the wishlist in mode "edit".
        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 * &wishlistMove(nodes, marked)
   
        Returns the table-HTML-markup for the wishlist in mode "move". Highlights all entry "selected to move" contained in marked (reference to array).
        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)
   
        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).     
    
   
   =item * &makePage(mode, marked)
   
        Returns the HTML-markup for the whole wishlist depending on mode. If mode is "move" we need the marked entries to be highlighted a "selected to move". 
        Calls &wishlistView(nodes), &wishlistEdit(nodes) or &wishlistMove(nodes, marked).
    
   
   =item * &makePageSet()
   
        Returns the HTML-Markup for the page shown when a link was set by using the icon when viewing a resource.
   
   
   =item * &makePageImport()
   
        Returns the HTML-Markup for the page shown when links should be imported into courses.
    
   
   =item * &makeErrorPage ()
   
        Returns the HTML-Markup for an error-page shown if the wishlist could not be loaded.
    
   
   =back
   
   =cut
   
   
 # Return a script-tag containing Javascript-function  # Return a script-tag containing Javascript-function
 # needed for wishlist actions like 'new link' ect.  # needed for wishlist actions like 'new link' ect.
 sub JSforWishlist {  sub JSforWishlist {
Line 453  sub JSforWishlist { Line 625  sub JSforWishlist {
         else if (action == 'saveOK') {          else if (action == 'saveOK') {
             r = linksOK();              r = linksOK();
         }          }
           else if (action == 'move') {
               r = selectDestinationFolder();
           }
         document.getElementsByName('list')[0].setAttribute("action", "/adm/wishlist?mode="+mode);           document.getElementsByName('list')[0].setAttribute("action", "/adm/wishlist?mode="+mode); 
         if (r) {          if (r) {
             document.getElementsByName('list')[0].submit();               document.getElementsByName('list')[0].submit(); 
Line 879  sub JSforWishlist { Line 1054  sub JSforWishlist {
        newWin.focus();         newWin.focus();
     }      }
   
     function finish_import() {  
         opener.document.forms.simpleedit.importdetail.value='';  
         for (var num = 0; num < document.forms.groupsort.fnum.value; num++) {  
             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")+'='+  
                 eval("document.forms.groupsort.filelink"+num+".value")+'='+  
                 eval("document.forms.groupsort.id"+num+".value");  
             }  
         }  
         opener.document.forms.simpleedit.submit();  
         self.close();  
     }  
   
     function checkAll() {      function checkAll() {
         var checkboxes = document.getElementsByName('check');          var checkboxes = document.getElementsByName('check');
         for (var i = 0; i < checkboxes.length; i++) {          for (var i = 0; i < checkboxes.length; i++) {
Line 911  JAVASCRIPT Line 1072  JAVASCRIPT
    return $js;     return $js;
 }  }
   
   sub JSforImport{
       my $rat = shift;
   
       my $js;
       if ($rat eq 'simple' || $rat eq '') {
           $js = &Apache::lonhtmlcommon::scripttag(<<JAVASCRIPT);
           function finish_import() {
               opener.document.forms.simpleedit.importdetail.value='';
               for (var num = 0; num < document.forms.groupsort.fnum.value; num++) {
                   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")+'='+
                       eval("document.forms.groupsort.filelink"+num+".value")+'='+
                       eval("document.forms.groupsort.id"+num+".value");
                   }
               }
               opener.document.forms.simpleedit.submit();
               self.close();
           }
   JAVASCRIPT
       }
       else {
           $js = &Apache::lonhtmlcommon::scripttag(<<JAVASCRIPT);
           function finish_import() {
               var linkflag=false;
               for (var num=0; num<document.forms.groupsort.fnum.value; num++) {
                   if (eval("document.forms.groupsort.check"+num+".checked") && eval("document.forms.groupsort.filelink"+num+".value") != '') {
                       insertRowInLastRow();
                       placeResourceInLastRow(
                           eval("document.forms.groupsort.title"+num+".value"),
                           eval("document.forms.groupsort.filelink"+num+".value"),
                           eval("document.forms.groupsort.id"+num+".value"),
                           linkflag
                           );
                       linkflag=true;
                   }
               }
               opener.editmode=0;
               opener.notclear=0;
               opener.linkmode=0;
               opener.draw();
               self.close();
           }
   
           function insertRowInLastRow() {
               opener.insertrow(opener.maxrow);
               opener.addobj(opener.maxrow,'e&2');
           }
   
           function placeResourceInLastRow (title,url,id,linkflag) {
               opener.mostrecent=opener.newresource(opener.maxrow,2,opener.unescape(title),
                                 opener.unescape(url),'false','normal',id);
               opener.save();
               if (linkflag) {
                   opener.joinres(opener.linkmode,opener.mostrecent,0);
               }
               opener.linkmode=opener.mostrecent;
           }
   JAVASCRIPT
       }
       return $js;
   }
   
 # HTML-Markup for table if in view-mode  # HTML-Markup for table if in view-mode
 my $wishlistHTMLview;  my $wishlistHTMLview;
Line 1243  sub makePage { Line 1466  sub makePage {
                                                         'onload' => 'javascript:onLoadAction('."'".$mode."'".');',                                                          'onload' => 'javascript:onLoadAction('."'".$mode."'".');',
                                                         'onunload' => 'javascript:window.name = '."'loncapaclient'"}});                                                          'onunload' => 'javascript:window.name = '."'loncapaclient'"}});
   
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.      my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Wishlist').&Apache::loncommon::help_open_topic('Wishlist'));
                            '<a title="Online-Hilfe" href="/adm/help/Wishlist.hlp" target="_top">'.  
                            '<img src="/adm/help/help.png" alt="'.&mt('Help').'" '.  
                            'title="'.&mt('Help').'" class="LC_icon" /></a>');  
   
     # get javascript-code for wishlist-interactions      # get javascript-code for wishlist-interactions
     my $js = &JSforWishlist();      my $js = &JSforWishlist();
Line 1364  sub makePage { Line 1584  sub makePage {
                                                    'Now choose the new destination folder.').'</span></p>';                                                     'Now choose the new destination folder.').'</span></p>';
             &wishlistMove(\@childrenRt, $marked);              &wishlistMove(\@childrenRt, $marked);
             $inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLmove.'</table><br/><br/>';              $inner .= '<table class="LC_data_table LC_tableOfContent">'.$wishlistHTMLmove.'</table><br/><br/>';
             $inner .= '<input type="button" value="'.&mt('Move').'" onclick="setFormAction('."'','view'".'); selectDestinationFolder()"/>'.              $inner .= '<input type="button" value="'.&mt('Move').'" onclick="setFormAction('."'move','view'".');"/>'.
                       '<input type="button" value="'.&mt('Cancel').'" onclick="go('."'/adm/wishlist'".')"/>';                        '<input type="button" value="'.&mt('Cancel').'" onclick="go('."'/adm/wishlist'".')"/>';
   
             $wishlistHTMLmove ='<tr id="root" class="LC_odd_row"><td><input type="radio" name="mark" id="radioRoot" value="root" /></td>'.              $wishlistHTMLmove ='<tr id="root" class="LC_odd_row"><td><input type="radio" name="mark" id="radioRoot" value="root" /></td>'.
Line 1415  sub makePageSet { Line 1635  sub makePageSet {
   
 # Returns the HTML-Markup for the page, shown when links should be imported into a course  # Returns the HTML-Markup for the page, shown when links should be imported into a course
 sub makePageImport {  sub makePageImport {
       my $rat = shift;
     # start_page       # start_page 
     my $startPage = &Apache::loncommon::start_page('Wishlist',undef,      my $startPage = &Apache::loncommon::start_page('Wishlist',undef,
                                                    {'only_body' => 1});                                                     {'only_body' => 1});
           
     # get javascript-code for wishlist-interactions      # get javascript-code for wishlist-interactions
     my $js = &JSforWishlist();      my $js = &JSforWishlist();
       $js .= &JSforImport($rat);
   
     my $inner = '<h1>'.&mt('Import Resources from Wishlist').'</h1>';      my $inner = '<h1>'.&mt('Import Resources from Wishlist').'</h1>';
     $inner .= '<p><span class="LC_info">'.&mt("Please note that you  can use the checkboxes corresponding to a folder to ".      if (!$rat) {
                                               "easily check all links within this folder. The folder structure itself can't be imported. ".          $inner .= '<p><span class="LC_info">'.&mt("Please note that you  can use the checkboxes corresponding to a folder to ".
                                               "All checked links will be imported into the current folder of your course.").'</span></p>';                                                    "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.").'</span></p>';
       }
       else {
           $inner .= '<p><span class="LC_info">'.&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. ")
                                                     .'</span></p>';
       }
     my %wishlist = &getWishlist();      my %wishlist = &getWishlist();
     my $fnum = (keys %wishlist)-1;      my $fnum = (keys %wishlist)-1;
   
Line 1468  sub makeErrorPage { Line 1696  sub makeErrorPage {
                 text => 'Wishlist'});                  text => 'Wishlist'});
     my $startPage = &Apache::loncommon::start_page('Wishlist');      my $startPage = &Apache::loncommon::start_page('Wishlist');
           
     my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs('Wishlist '.      my $breadcrumbs = &Apache::lonhtmlcommon::breadcrumbs(&mt('Wishlist').&Apache::loncommon::help_open_topic('Wishlist'));
                            '<a title="Online-Hilfe" href="/adm/help/Wishlist.hlp" target="_top">'.  
                            '<img src="/adm/help/help.png" alt="'.&mt('Help').'" '.  
                            'title="'.&mt('Help').'" class="LC_icon" /></a>');  
     &Apache::lonhtmlcommon::clear_breadcrumbs();      &Apache::lonhtmlcommon::clear_breadcrumbs();
   
     # error-message      # error-message
Line 1504  sub handler { Line 1729  sub handler {
         }          }
   
         # get unprocessed_cgi (i.e. marked entries, mode ...)           # get unprocessed_cgi (i.e. marked entries, mode ...) 
         &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['action','mark','markedToMove','mode','newtitle','note']);          &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          # change the order of entries within a level, that means sorting the entries
         my $changeOrder = 0;          my $changeOrder = 0;
Line 1591  sub handler { Line 1816  sub handler {
             $page = &makePage("move", \@marked);              $page = &makePage("move", \@marked);
         }          }
         elsif ($env{'form.mode'} eq 'import') {          elsif ($env{'form.mode'} eq 'import') {
             $page = &makePageImport();              $page = &makePageImport($env{'form.rat'});
         }          }
         elsif ($env{'form.mode'} eq 'set') {          elsif ($env{'form.mode'} eq 'set') {
             $page = &makePageSet();              $page = &makePageSet();
Line 1614  sub handler { Line 1839  sub handler {
 # Extend CPAN-Module Tree by function like 'moveNode' or 'deleteNode'  # Extend CPAN-Module Tree by function like 'moveNode' or 'deleteNode'
 package Tree;  package Tree;
   
   =pod
   
   =head2 Routines from package Tree
   
   =over 4
   
   =item * &getNodeByIndex(index, nodes)
   
        Searches for a node, specified by the index, in nodes (reference to array) and returns it. 
    
   
   =item * &moveNode(node, at, newParent)
   
        Moves a given node to a new parent (if new parents is defined) or change the position from a node within its siblings (means sorting, at must be defined).
   
   
   =item * &removeNode(node)
   
        Removes a node given by node from the tree.
   
   
   =item * &TreeIndex(children)
   
        Sets an index for every node in the tree, beginning with 0.
        Recursive call starting with all children of the root of the tree (parameter children is reference to an array containing the nodes of the current level).     
   
   
   =item * &setCountZero()
   
        Resets index counter.
   
   
   =item * &RootToHash(childrenRt)
   
        Converts the root-node to a hash-entry: the key is root and values are just the indices of root's children.
      
   
   =item * &TreeToHash(childrenRt)
   
        Converts all other nodes in the tree to hash. Each node is one hash-entry where the keys are the index of a node and the values are all other attributes (containing tile, path, note, date and indices for all direct children).
        Recursive call starting with all children of the root of the tree (parameter childrenRT is reference to an array containing the nodes of the current level).     
   
   
   =item * &HashToTree()
   
        Converts the hash to a tree. Builds a tree-object for each entry in the hash. Afterwards call &buildTree(node, childrenIn, TreeNodes, TreeHash) to connect the tree-objects.
   
   
   =item * &buildTree(node, childrenIn, TreeNodes, TreeHash)
   
        Joins the nodes to a tree.
        Recursive call starting with root and all children of root (parameter childrenIn is reference to an array containing the nodes indices of the current level).
      
   
   =back
   
   =cut
   
   
 # returns the node with a given index from a list of nodes  # returns the node with a given index from a list of nodes
 sub getNodeByIndex {  sub getNodeByIndex {
     my $index = shift;      my $index = shift;
Line 1743  sub HashToTree { Line 2027  sub HashToTree {
         if ($key eq 'root') {          if ($key eq 'root') {
             $root = Tree->new("root");              $root = Tree->new("root");
         }          }
         else {          elsif ($key ne 'folders') {
         my @attributes = @{ $TreeHash{$key} };          my @attributes = @{ $TreeHash{$key} };
         my $tmpNode;          my $tmpNode;
             $tmpNode = Tree->new(Entry->new(title=>$attributes[0],              $tmpNode = Tree->new(Entry->new(title=>$attributes[0],

Removed from v.1.3  
changed lines
  Added in v.1.8


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>