File:  [LON-CAPA] / rat / lonratedt.pm
Revision 1.94.2.1: download - view: text, annotated - select for diffs
Fri Aug 14 02:16:31 2009 UTC (14 years, 8 months ago) by raeburn
Branches: version_2_9_X
CVS tags: version_2_9_1, version_2_9_0, version_2_8_99_1, version_2_8_99_0, GCI_2
- Backport parts of 1.95, 1.97.

    1: # The LearningOnline Network with CAPA
    2: # Edit Handler for RAT Maps
    3: #
    4: # $Id: lonratedt.pm,v 1.94.2.1 2009/08/14 02:16:31 raeburn Exp $
    5: #
    6: # Copyright Michigan State University Board of Trustees
    7: #
    8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    9: #
   10: # LON-CAPA is free software; you can redistribute it and/or modify
   11: # it under the terms of the GNU General Public License as published by
   12: # the Free Software Foundation; either version 2 of the License, or
   13: # (at your option) any later version.
   14: #
   15: # LON-CAPA is distributed in the hope that it will be useful,
   16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   18: # GNU General Public License for more details.
   19: #
   20: # You should have received a copy of the GNU General Public License
   21: # along with LON-CAPA; if not, write to the Free Software
   22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   23: #
   24: # /home/httpd/html/adm/gpl.txt
   25: #
   26: # http://www.lon-capa.org/
   27: #
   28: 
   29: 
   30: package Apache::lonratedt;
   31: 
   32: use strict;
   33: use Apache::Constants qw(:common);
   34: use Apache::lonnet;
   35: use Apache::lonsequence();
   36: use Apache::loncommon();
   37: use Apache::lonlocal;
   38: use LONCAPA::map();
   39: use File::Copy;
   40: use LONCAPA;
   41: use HTML::Entities();
   42: 
   43: # --------------------------------------------------------- Build up RAT screen
   44: sub ratedt {
   45:   my ($r,$url)=@_;
   46:   my %layout = ('border' => "0");
   47:     if ($env{'environment.remote'} eq 'off') {
   48:       $layout{'rows'} = "1,250,*";
   49:   } else {
   50:       $layout{'rows'} = "1,70,*";
   51:   }
   52:   my $js ='
   53: <script type="text/javascript">
   54:     var flag=0;
   55: </script>';
   56: 
   57:   my $start_page = 
   58:       &Apache::loncommon::start_page('Edit Sequence',$js,
   59: 				     {'frameset'    => 1,
   60: 				      'add_entries' => \%layout});
   61:   my $end_page = 
   62:       &Apache::loncommon::end_page({'frameset' => 1});
   63: 
   64:   $r->print(<<ENDDOCUMENT);
   65: $start_page
   66: <frame name="server" src="$url/loadonly/ratserver" noresize="noresize"
   67:        noscroll="noscroll" />
   68: <frame name="code" src="$url/loadonly/adveditmenu" />
   69: <frame name="mapout" src="/adm/rat/map.html" />
   70: $end_page
   71: ENDDOCUMENT
   72: }
   73: 
   74: # ---------------------------------------------------------------- Make buttons
   75: 
   76: sub buttons {
   77:     my $adv=shift;
   78:     my $output='<form method="post">';     
   79:     if ($adv==1) {
   80: 	$output.='<input type="submit" name="forceadv" value="'.&mt('Edit').'" />'.
   81: 	    &Apache::loncommon::help_open_topic('Sequence_Advanced_Editor_Creation');
   82:     } else {
   83:         unless ($adv==2) {
   84:            $output.='<input type="submit" name="forcesmp" value="'.&mt('Simple Edit').'" />'.
   85: 	    &Apache::loncommon::help_open_topic('Sequence_Simple_Editor_Creation');
   86:         }
   87: 	$output.='<input type="submit" name="forceadv" value="'.&mt('Advanced Edit').'" />'.
   88: 	    &Apache::loncommon::help_open_topic('Sequence_Advanced_Editor_Creation');
   89:     }
   90:     return $output.'</form><hr />';
   91: }
   92: 
   93: # ----------------------------------------------------------------- Edit script
   94: sub editscript {
   95:     my $mode=shift;
   96:     my $resurl=
   97: 	&Apache::loncommon::escape_single(&Apache::loncommon::lastresurl());
   98:     return(<<ENDSCRIPT);
   99: var srch;
  100: var srchflag=-1; // 1 means currently open
  101:                  // 0 means closed (but has been open)
  102:                  // -1 means never yet opened/defined
  103: var srchmode='';
  104: 
  105: var idx;
  106: var idxflag=-1; // 1 means currently open
  107:                  // 0 means closed (but has been open)
  108:                  // -1 means never yet opened/defined
  109: var idxmode='';
  110: 
  111: // ------------------------------------------------------ Clears indexer window
  112: function idxclear() {
  113:   idx.document.clear();
  114: }
  115: 
  116: // ------------------------------------------------------- Clears search window
  117: function srchclear() {
  118:   srch.document.clear();
  119: }
  120: 
  121: // ------------------------------------------------------ Closes indexer window
  122: function idxclose() {
  123:   if (idx && !idx.closed) {
  124:     idxflag=0;
  125:     idx.close();
  126:   }
  127: }
  128: 
  129: // ------------------------------------------------------- Closes search window
  130: function srchclose() {
  131:   if (srch && !srch.closed) {
  132:     srchflag=0;
  133:     srch.close();
  134:   }
  135: }
  136: 
  137: // -------------------------------------------------------- Open indexer window
  138: function idxopen(mode) {
  139:    var options="scrollbars=1,resizable=1,menubar=0,location=1,toolbar=1";
  140:    idxmode=mode;
  141:    idxflag=1;
  142:    idx=open('$resurl/?inhibitmenu=yes&launch=1&mode=$mode&catalogmode='+mode,'idxout',options);
  143:    idx.focus();
  144: }
  145: 
  146: // ------------------------------------------------------ Open groupsort window
  147: function groupopen(url,recover,bookmarks) {
  148:    var options="scrollbars=1,resizable=1,menubar=0";
  149:    idxflag=1;
  150:    idx=open("/adm/groupsort?inhibitmenu=yes&mode=$mode&recover="+recover+"&readfile="+url+"&bookmarks="+bookmarks,"idxout",options);
  151:    idx.focus();
  152: }
  153: 
  154: // --------------------------------------------------------- Open search window
  155: function srchopen(mode) {
  156:    var options="scrollbars=1,resizable=1,menubar=0";
  157:    srchmode=mode;
  158:    srchflag=1;
  159:    srch=open("/adm/searchcat?inhibitmenu=yes&launch=1&mode=$mode&catalogmode="+mode,"srchout",options);
  160:    srch.focus();
  161: }
  162: // ----------------------------------------------------- launch indexer browser
  163: function groupsearch() {
  164:    srchcheck('import');
  165: }
  166: 
  167: function groupimport() {
  168:    idxcheck('import');
  169: }
  170: 
  171: // ------------------------------------------------------- Do srch status check
  172: function srchcheck(mode) {
  173:    if (!srch || srch.closed || srchmode!=mode) {
  174:       srchopen(mode);
  175:    }
  176:    srch.focus();
  177: }
  178: 
  179: // -------------------------------------------------------- Do idx status check
  180: function idxcheck(mode) {
  181:    if (!idx || idx.closed || idxmode!=mode) {
  182:       idxopen(mode);
  183:    }
  184:    idx.focus();
  185: }
  186: 
  187: 
  188:     var editbrowser;
  189:     function openbrowser(formname,elementname,only,omit) {
  190:         var url = '$resurl/?';
  191:         if (editbrowser == null) {
  192:             url += 'launch=1&';
  193:         }
  194:         url += 'inhibitmenu=yes&';
  195:         url += 'catalogmode=interactive&';
  196:         url += 'mode=edit&';
  197:         url += 'form=' + formname + '&';
  198:         if (only != null) {
  199:             url += 'only=' + only + '&';
  200:         } 
  201:         if (omit != null) {
  202:             url += 'omit=' + omit + '&';
  203:         }
  204:         url += 'element=' + elementname + '';
  205:         var title = 'Browser';
  206:         var options = 'scrollbars=1,resizable=1,menubar=0,toolbar=1,location=1';
  207:         options += ',width=700,height=600';
  208:         editbrowser = open(url,title,options,'1');
  209:         editbrowser.focus();
  210:     }
  211: ENDSCRIPT
  212: }
  213: # ------------------------------------------------------- Simple edit processor
  214: 
  215: sub smpedt {
  216:    my ($r,$url,$errtext)=@_;
  217:    my $buttons=&buttons(2);
  218:    my $tmpfn=&Apache::lonnet::filelocation('',$url).'.tmp';
  219:    my $targetmsg='';
  220:    if ($env{'form.save'}) {
  221:        copy($tmpfn,&Apache::lonnet::filelocation('',$url));
  222:        unlink($tmpfn);
  223:        my ($errtext,$fatal)=
  224: 	   &LONCAPA::map::mapread(&Apache::lonnet::filelocation('',$url),'');
  225:        unless ($fatal) {
  226: 	   $targetmsg='<b>'.&mt('Saved.').'</b><br />';
  227:        } else {
  228: 	   $targetmsg='<b>'.&mt('An error occurred while saving.').'</b><br />';
  229:        }
  230:    }
  231:    if ($env{'form.revert'}) {
  232:        $targetmsg='<b>'.&mt('Reverted.').'</b><br />';
  233:        unlink($tmpfn);
  234:        my ($errtext,$fatal)=
  235: 	   &LONCAPA::map::mapread(&Apache::lonnet::filelocation('',$url),'');
  236:    }
  237:    if (-e $tmpfn) {
  238:       $targetmsg=
  239:         '<span class="LC_warning">'.&mt('You are working with an unsaved version of your map.').'</span><br />';
  240:       my ($errtext,$fatal)=&LONCAPA::map::mapread($tmpfn,'');
  241:    }
  242: # ---------------------------------------------------------- Process form input
  243: 
  244:    my @importselect=&Apache::loncommon::get_env_multiple('form.importsel');
  245:    my @targetselect=&Apache::loncommon::get_env_multiple('form.target');
  246: # ============================================================ Process commands
  247: 
  248:    my $targetdetail=$env{'form.targetdetail'};
  249:    my $importdetail=$env{'form.curimpdetail'};
  250: 
  251: # ---------------------------------------------------- Importing from groupsort
  252:    if (($env{'form.importdetail'}) && (!$env{'form.impfortarget'})) {
  253: 
  254:        $importdetail='';
  255:        my @curimport=split(/\&/,$env{'form.curimpdetail'});
  256: 
  257:        my $lastsel;
  258: 
  259:        if (defined($importselect[-1])) {
  260: 	   $lastsel=$importselect[-1];
  261:        } else {
  262:            $lastsel=$#curimport;
  263:        }
  264: 
  265:        for (my $i=0;$i<=$lastsel;$i++) {
  266:            my ($name,$url)=split(/\=/,$curimport[$i]);
  267:            if ($url) {
  268:               $importdetail.='&'.$name.'='.$url;
  269: 	   }
  270:        }
  271: 
  272:       $importdetail.='&'.$env{'form.importdetail'};
  273: 
  274:        for (my $i=$lastsel+1;$i<=$#curimport;$i++) {
  275:            my ($name,$url)=split(/\=/,$curimport[$i]);
  276:            if ($url) {
  277:               $importdetail.='&'.$name.'='.$url;
  278: 	  }
  279:        }
  280:        $importdetail=~s/\&+/\&/g;
  281:        $importdetail=~s/^\&//;
  282: 
  283: # ------------------------------------------------------------------- Clear all
  284:    } elsif ($env{'form.clear'}) {
  285:        $importdetail='';
  286: # ------------------------------------------------------------ Discard selected
  287:    } elsif ($env{'form.discard'}) {
  288:        $importdetail='';
  289:        my @curimport=split(/\&/,$env{'form.curimpdetail'});
  290:        foreach (@importselect) {
  291: 	   $curimport[$_]='';
  292:        }
  293:        for (my $i=0;$i<=$#curimport;$i++) {
  294:            my ($name,$url)=split(/\=/,$curimport[$i]);
  295:            if ($url) {
  296:               $importdetail.='&'.$name.'='.$url;
  297: 	   }
  298:        }
  299: # --------------------------------------------------------- Loading another map
  300:    } elsif ($env{'form.loadmap'}) {
  301:        $importdetail='';
  302:        my @curimport=split(/\&/,$env{'form.curimpdetail'});
  303: 
  304:        my $lastsel;
  305: 
  306:        if (defined($importselect[-1])) {
  307: 	   $lastsel=$importselect[-1];
  308:        } else {
  309:            $lastsel=$#curimport;
  310:        }
  311: 
  312:        for (my $i=0;$i<=$lastsel;$i++) {
  313:            my ($name,$url)=split(/\=/,$curimport[$i]);
  314:            if ($url) {
  315:               $importdetail.='&'.$name.'='.$url;
  316: 	   }
  317:        }
  318: 
  319:        foreach (
  320:     &Apache::lonsequence::attemptread(&Apache::lonnet::filelocation('',$env{'form.importmap'}))) {
  321: 	   my ($name,$url)=split(/\:/,$_);
  322:            if ($url) {
  323:               $importdetail.='&'.&escape($name).'='.
  324: 		 	         &escape($url);
  325: 	  }
  326:        }
  327: 
  328:        for (my $i=$lastsel+1;$i<=$#curimport;$i++) {
  329:            my ($name,$url)=split(/\=/,$curimport[$i]);
  330:            if ($url) {
  331:               $importdetail.='&'.$name.'='.$url;
  332: 	  }
  333:        }
  334:        $importdetail=~s/\&+/\&/g;
  335:        $importdetail=~s/^\&//;
  336: 
  337: # ------------------------------------------------ Groupimport/search to target
  338:    } elsif ($env{'form.importdetail'}) {
  339:        my $lastsel;
  340:        if (defined($targetselect[-1])) {
  341: 	   $lastsel=$targetselect[-1];
  342:        } else {
  343:            $lastsel=$#LONCAPA::map::order+1;
  344:        }
  345:        &LONCAPA::map::pastetarget($lastsel,split(/\&/,$env{'form.importdetail'}));
  346:        &LONCAPA::map::storemap(&Apache::lonnet::filelocation('',$url));
  347: # ------------------------------------------------------------------------- Cut
  348:    } elsif (($env{'form.cut'}) || ($env{'form.copy'})) {
  349:        $importdetail='';
  350:        my @curimport=split(/\&/,$env{'form.curimpdetail'});
  351: 
  352:        my $lastsel;
  353: 
  354:        if (defined($importselect[-1])) {
  355: 	   $lastsel=$importselect[-1];
  356:        } else {
  357:            $lastsel=$#curimport;
  358:        }
  359: 
  360:        for (my $i=0;$i<=$lastsel;$i++) {
  361:            my ($name,$url)=split(/\=/,$curimport[$i]);
  362:            if ($url) {
  363:               $importdetail.='&'.$name.'='.$url;
  364: 	   }
  365:        }
  366: 
  367:        foreach (@targetselect) {
  368: 	   my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$LONCAPA::map::order[$_-1]]);
  369:            if ($url) {
  370:               $importdetail.='&'.&escape($name).'='.
  371: 		 	         &escape($url);
  372: 	  }
  373:        }
  374: 
  375:        for (my $i=$lastsel+1;$i<=$#curimport;$i++) {
  376:            my ($name,$url)=split(/\=/,$curimport[$i]);
  377:            if ($url) {
  378:               $importdetail.='&'.$name.'='.$url;
  379: 	  }
  380:        }
  381:        $importdetail=~s/\&+/\&/g;
  382:        $importdetail=~s/^\&//;
  383: 
  384:        if ($env{'form.cut'}) {
  385:            my @neworder=();
  386:            for (my $i=0;$i<=$#LONCAPA::map::order;$i++) {
  387:                my $include=1;
  388:                foreach (@targetselect) {
  389: 		   if ($_-1==$i) { $include=0; }
  390:                }
  391:                if ($include) { 
  392: 		   $neworder[$#neworder+1]=$LONCAPA::map::order[$i]; 
  393: 	       } else {
  394: 		   &LONCAPA::map::makezombie($LONCAPA::map::order[$i]);
  395: 	       }
  396:            }
  397:            @LONCAPA::map::order=@neworder;
  398:            &LONCAPA::map::storemap(&Apache::lonnet::filelocation('',$url));      
  399:        }
  400: 
  401: # ----------------------------------------------------------------------- Paste
  402:    } elsif ($env{'form.paste'}) {
  403:        my $lastsel;
  404:        if (defined($targetselect[-1])) {
  405: 	   $lastsel=$targetselect[-1];
  406:        } else {
  407:            $lastsel=$#LONCAPA::map::order+1;
  408:        }
  409:        my @newsequence;
  410:        my @curimport=split(/\&/,$env{'form.curimpdetail'});
  411:        foreach (@importselect) {
  412:           $newsequence[$#newsequence+1]=$curimport[$_];
  413:        }
  414:        &LONCAPA::map::pastetarget($lastsel,@newsequence);
  415:        &LONCAPA::map::storemap(&Apache::lonnet::filelocation('',$url));
  416: # -------------------------------------------------------------------- Move up 
  417:    } elsif ($env{'form.moveup'}) {
  418:        foreach (sort @targetselect) {
  419:            if ($_-1>0) {
  420:               my $movethis=$LONCAPA::map::order[$_-1];
  421:               $LONCAPA::map::order[$_-1]=$LONCAPA::map::order[$_-2];
  422:               $LONCAPA::map::order[$_-2]=$movethis;
  423: 	  }
  424:        }
  425:        &LONCAPA::map::storemap(&Apache::lonnet::filelocation('',$url));
  426: # ------------------------------------------------------------------ Move down
  427:    } elsif ($env{'form.movedown'}) {
  428:        foreach (reverse sort @targetselect) {
  429:            if ($_-1<$#LONCAPA::map::order) {
  430:               my $movethis=$LONCAPA::map::order[$_-1];
  431:               $LONCAPA::map::order[$_-1]=$LONCAPA::map::order[$_];
  432:               $LONCAPA::map::order[$_]=$movethis;
  433: 	   }
  434:        }
  435:        &LONCAPA::map::storemap(&Apache::lonnet::filelocation('',$url));
  436: # --------------------------------------------------------------------- Rename
  437:    } elsif ($env{'form.renameres'}) {
  438:        my $residx=$LONCAPA::map::order[$env{'form.renameidx'}-1];
  439:        my ($name,@resrest)=split(/\:/,$LONCAPA::map::resources[$residx]);
  440:        $name=$env{'form.renametitle'};
  441:        $name=~s/\:/\&colon\;/g;
  442:        $LONCAPA::map::resources[$residx]=$name.':'.join(':',@resrest);
  443:        &LONCAPA::map::storemap(&Apache::lonnet::filelocation('',$url));
  444:    }
  445: # ------------------------------------------------------------ Assemble windows
  446:    
  447:    my $idx=-1;
  448:    $importdetail='&'.$importdetail;
  449:    $importdetail=~s/^\&+/\&/;
  450:    my $importwindow=
  451:        '<option value="-1"> ---- '.&mt('Import and Paste Area').' ---- </option>'.
  452:      join("\n",map {
  453:        $idx++;
  454:        if ($_) { 
  455:           my ($name,$url)=split(/\=/,$_);
  456:           unless ($name) { $name=(split(/\//,$url))[-1]; }
  457:           unless ($name) { $name='EMPTY'; }
  458:           '<option value="'.$idx.'">'.&unescape($name).
  459:                                     '</option>';
  460:       }
  461:    } split(/\&/,$importdetail));
  462: 
  463:    $idx=0;
  464:    $targetdetail='';
  465:    my $targetwindow=       
  466:        '<option value="0"> ------- '.&mt('Target Edit Map').' ------- </option>'.
  467:      join("\n",map { 
  468:        my ($name,$url)=split(/\:/,$LONCAPA::map::resources[$_]);
  469:        unless ($name) {  $name=(split(/\//,$url))[-1]; }
  470:        unless ($name) { $name='EMPTY'; }
  471:        $name = &LONCAPA::map::qtescape($name);
  472:        $url  = &LONCAPA::map::qtescape($url);
  473:        $targetdetail.='&'.&escape($name).'='.
  474: 	                  &escape($url);
  475:        $idx++;
  476:        $name = &HTML::Entities::encode($name,'\'"<>&');
  477:        '<option value="'.$idx.'">'.$name.'</option>';
  478:    } @LONCAPA::map::order);
  479: 
  480: # ----------------------------------------------------- Start simple RAT screen
  481:    my $editscript=&editscript('simple');
  482: 
  483:    my %lt=&Apache::lonlocal::texthash(
  484: 				      'sa' => 'Save',
  485: 				      'nt' => 'New Title',
  486: 				      'se' => 'Search',
  487: 				      'im' => 'Import',
  488:                                       'bk' => 'Import Bookmarks',
  489: 				      'vi' => 'View',
  490: 				      'lm' => 'Load Map',
  491: 				      'ds' => 'Discard Selected',
  492: 				      'ca' => 'Clear All',
  493: 				      'ta' => 'Temporary Assembly Workspace',
  494: 				      'rv' => 'Revert to Last Saved',
  495:                                       'sa' => 'Save',
  496:                                       'mu' => 'Move Up',
  497:                                       'md' => 'Move Down',
  498:                                       're' => 'Rename',
  499:                                       'as' => 'after selected',
  500:                                       'cs' => 'Cut selected',
  501:                                       'ps' => 'Copy selected',
  502:                                       'pas' => 'Paste after selected',
  503:                                       'reco' => 'Recover Deleted'
  504: 				      );
  505:    my $js=<<ENDJS;
  506: <script type="text/javascript">
  507: 
  508:    $editscript
  509: 
  510:    function openview(entry) {
  511:        var url=unescape((entry.split('='))[1]);
  512:        var parts=new Array;
  513:        if (url) { open(url,'cat'); }
  514:    }
  515: 
  516:    function viewtarget() {
  517:        openview((document.forms.simpleedit.targetdetail.value.split('&'))
  518:                 [document.forms.simpleedit.target.selectedIndex]);
  519:    }
  520: 
  521:    function viewimport() {
  522:        openview((document.forms.simpleedit.curimpdetail.value.split('&'))
  523:                 [document.forms.simpleedit.importsel.selectedIndex]);
  524:    }
  525: 
  526:    function renametarget() {
  527:        var selidx=document.forms.simpleedit.target.selectedIndex;
  528:        var entry=(document.forms.simpleedit.targetdetail.value.split('&'))
  529:                 [selidx];
  530:        var oldname=unescape((entry.split('='))[0]);
  531:        newtitle=prompt('$lt{'nt'}',oldname);
  532:        if (newtitle) {
  533:            document.forms.simpleedit.renameres.value=1;
  534:            document.forms.simpleedit.renameidx.value=selidx;
  535:            document.forms.simpleedit.renametitle.value=newtitle;
  536: 	   document.forms.simpleedit.submit();
  537:        }
  538:    }
  539: 
  540: </script>
  541: ENDJS
  542: 
  543:     my $start_page = &Apache::loncommon::start_page(undef,$js).
  544:         &Apache::loncommon::help_open_menu('Sequence_Simple_Editor_Creation',
  545: 					   'Sequence_Simple_Editor_Creation',
  546: 					   6,'RAT');    
  547:     my $end_page = &Apache::loncommon::end_page();
  548: 
  549:     $r->print(<<ENDSMPHEAD);
  550: $start_page
  551: $buttons
  552: <span class="LC_error">$errtext</span>
  553: <form name="simpleedit" method="post">
  554: <input type="hidden" name="forcesmp" value="1" />
  555: <input type="hidden" name="renameres" value="0" />
  556: <input type="hidden" name="renametitle" value="" />
  557: <input type="hidden" name="renameidx" value="0" />
  558: <table>
  559:     <tr><th width="40%">$lt{'ta'}</th>
  560: <th>&nbsp;</th>
  561: <th width="40%">File: $url</th></tr>
  562: <tr><td bgcolor="#FFFFCC">
  563: <input type="button" onClick="javascript:groupsearch()" value="$lt{'se'}" />
  564: <input type="button" onClick="javascript:groupimport();" value="$lt{'im'}" />
  565: $lt{'as'}
  566: <hr />
  567: <input type="text" size="20" name="importmap" />
  568: <input type="button" 
  569: onClick="javascript:openbrowser('simpleedit','importmap','sequence,page','')"
  570: value="Select Map" /><input type="submit" name="loadmap" value="$lt{'lm'}" /><hr />
  571: <input type="submit" name="discard" value="$lt{'ds'}" />
  572: <input type="submit" name="clear" value="$lt{'ca'}" />
  573: <input type="button" onClick="javascript:viewimport()" value="$lt{'vi'}" />
  574: 
  575:     </td><td>&nbsp;</td><td bgcolor="#FFFFCC">
  576: 
  577: <input type="button" onClick=
  578: "javascript:impfortarget.value=1;groupsearch()" value="$lt{'se'}" />
  579: <input type="button" onClick=
  580: "javascript:impfortarget.value=1;groupimport();" value="$lt{'im'}" />
  581: <input type="button" onClick=
  582: "javascript:impfortarget.value=1;groupopen(0,1,1);" value="$lt{'bk'}" />
  583: <input type="button" onClick=
  584: "javascript:impfortarget.value=1;groupopen('$url',1,0);" value="$lt{'reco'}" />
  585: $lt{'as'}
  586: <hr />
  587: <input type="submit" name="moveup" value="$lt{'mu'}" />
  588: <input type="submit" name="movedown" value="$lt{'md'}" />
  589: <input type="button" onClick="javascript:renametarget()" value="$lt{'re'}" />
  590: <hr />$targetmsg
  591: <input type="submit" name="revert" value="$lt{'rv'}" />
  592: <input type="submit" name="save" value="$lt{'sa'}" />
  593: <input type="button" onClick="javascript:viewtarget()" value="$lt{'vi'}" />
  594: </td></tr>
  595: 
  596: <tr><td bgcolor="#FFFFCC"><select name="importsel" size="10" multiple="multiple">
  597: $importwindow
  598: </select>
  599: </td>
  600: <td bgcolor="#FFFFAA" align="center">
  601: $lt{'cs'}<br />
  602: <input type="submit" name="cut" value="<<<" /><p>
  603: <hr />
  604: $lt{'ps'}<br />
  605: <input type="submit" name="copy" value="<--" /><p>
  606: <h /r>
  607: $lt{'pas'}<br />
  608: <input type="submit" name="paste" value="-->" />
  609: </td>
  610: <td bgcolor="#FFFFCC"><select name="target" size="10" multiple="multiple">
  611: $targetwindow
  612: </select>
  613: </table>
  614: <input type="hidden" name="importdetail" value="" />
  615: <input type="hidden" name="curimpdetail" value="$importdetail" />
  616: <input type="hidden" name="targetdetail" value="$targetdetail" />
  617: <input type="hidden" name="impfortarget" value="0" />
  618: </form>
  619: $end_page
  620: ENDSMPHEAD
  621: }
  622: 
  623: # ----------------------------------------------------------------- No such dir
  624: sub nodir {
  625:    my ($r,$dir)=@_;
  626:    $dir=~s{^/home/$LONCAPA::username_re/public_html}{};
  627:    $r->print(&Apache::loncommon::start_page(undef,undef,
  628: 					    {'only_body' => 1,
  629: 					     'bgcolor'   => '#FFFFFF',}).
  630:              '<p class="LC_error">'.
  631:              &mt('No such directory: [_1]','<span class="LC_filename">'.$dir.'</span>').
  632:              '</p>'.
  633: 	     &Apache::loncommon::end_page());
  634: }
  635: 
  636: # ---------------------------------------------------------------- View Handler
  637: 
  638: sub viewmap {
  639:     my ($r,$url,$adv,$errtext)=@_;
  640:     $r->print(
  641: 	      &Apache::loncommon::start_page('Edit Content of a Map').
  642: 	      &Apache::loncommon::help_open_menu('','',6,'RAT').
  643: 	      &buttons($adv));
  644:     if ($errtext) {
  645: 	$r->print('<div class="LC_error">'
  646:                  .$errtext
  647:                  .'</div>'
  648:                  .'<hr />'
  649:         );
  650:     }
  651:     my $idx=0;
  652:     $r->print('<p><span class="LC_filename">'.$url.'</span></p>');
  653:     if ($adv) {
  654: 	$r->print('<p class="LC_warning">'
  655:                  .&mt('Map contents are not shown in order.')
  656:                  .'</p><br />'
  657:         );
  658:     }
  659:     $r->print(&Apache::loncommon::start_data_table()
  660:              .&Apache::loncommon::start_data_table_header_row()
  661:              .'<th>'.&mt('Type').'</th>'
  662:              .'<th>'.&mt('Title in map').'</th>'
  663:              .'<th>'.&mt('Filename of resource').'</th>'
  664:              .'<th>'.&mt('Link to published resource').'</th>'
  665:              .'<th>'.&mt('Link to resource in Construction Space').'</th>'
  666:              .&Apache::loncommon::end_data_table_header_row()
  667:     );
  668:     foreach (&LONCAPA::map::attemptread(&Apache::lonnet::filelocation('',$url))) {
  669: 	if (defined($_)) {
  670:             $idx++;
  671: 	    my ($title,$url,$cond)=split(/\:/,$_);
  672: 	    if ($cond eq 'cond') { next; }
  673:             $title= &LONCAPA::map::qtescape($title);
  674:             $url  = &LONCAPA::map::qtescape($url);
  675:             unless ($title) { $title=(split(/\//,$url))[-1] };
  676:             unless ($title) { $title='<i>'.&mt('Empty').'</i>'; }
  677:             my $resurl = $url;
  678:             my $resfilepath = $Apache::lonnet::perlvar{'lonDocRoot'}.$resurl;
  679:             my $filename; 
  680:             if ($resurl =~ m#/([^/]+)$#) {
  681:                 $filename = $1;
  682:             }
  683:             my $cstrurl = $resurl;
  684:             $cstrurl =~ s#^/res/[^/]+/([^/]+)/#/priv/$1/#;
  685:             $r->print(&Apache::loncommon::start_data_table_row()
  686:                      .'<td>'
  687:                      .'<img src="'.&Apache::loncommon::icon($resfilepath).'" />'
  688:                      .'</td>'
  689:                      .'<td>'
  690:                      .&HTML::Entities::encode(&LONCAPA::map::qtescape($title))
  691:                      .'</td>'
  692:                      .'<td>'.$filename.'</td>'
  693:                      .'<td>'
  694:             );
  695:             if ($url) {
  696: 		$r->print('<a href="'.$resurl.'">'.&mt('Resource space').'</a>');
  697:             } else {
  698:                 $r->print('&nbsp;');
  699:             }
  700:             $r->print('</td><td>');
  701:             if ($url) {
  702:                $r->print('<a href="'.$cstrurl.'">'.
  703:                          &mt('Construction space').'</a>');
  704:             } else {
  705:                 $r->print('&nbsp;');
  706:             }
  707:             $r->print('</td>'
  708:                      .&Apache::loncommon::end_data_table_row()
  709:             );
  710:         }
  711:     }
  712:     $r->print(&Apache::loncommon::end_data_table());
  713:     $r->print(&Apache::loncommon::end_page());
  714: }
  715: 
  716: # ================================================================ Main Handler
  717: 
  718: sub handler {
  719:   my $r=shift;
  720:   &Apache::loncommon::content_type($r,'text/html');
  721:   $r->send_http_header;
  722: 
  723:   return OK if $r->header_only;
  724:   my $target = $env{'form.grade_target'};
  725:   if ($target eq 'meta') {
  726:       &Apache::loncommon::content_type($r,'text/html');
  727:       $r->send_http_header;
  728:       return OK;
  729:   }
  730:   
  731:   my $url=$r->uri;
  732:   my $fn=&Apache::lonnet::filelocation('',$url);
  733: 
  734:   my ($dir)=($fn=~/^(.+)\/[^\/]+$/);
  735:   unless (-e $dir) {
  736:       &nodir($r,$dir);
  737:       return OK;
  738:   }
  739: 
  740: # ------------------------------------------- Determine which tools can be used
  741:   my $adv=0;
  742: 
  743:   unless ($env{'form.forcesmp'}) {
  744:      if ($env{'form.forceadv'}) {
  745:         $adv=1;
  746:      } elsif (my $fh=Apache::File->new($fn)) {
  747: 	 my $allmap=join('',<$fh>);
  748:          $adv=($allmap=~/\<map[^\>]+mode\s*\=\s*(\'|\")rat/is);
  749:      }
  750:   }
  751: 
  752:   my $errtext='';
  753:   my $fatal=0;
  754: 
  755: # -------------------------------------------------------------------- Load map
  756:   ($errtext,$fatal)=&LONCAPA::map::mapread($fn,$errtext);
  757: 
  758:   if ($fatal==1) { $adv=1; }
  759: 
  760: # ----------------------------------- adv==1 now means "graphical MUST be used"
  761: 
  762:   if ($env{'form.forceadv'}) {
  763:       &ratedt($r,$url);
  764:   } elsif ($env{'form.forcesmp'}) {
  765:       &smpedt($r,$url,$errtext);
  766:   } else {
  767:       &viewmap($r,$url,$adv,$errtext);
  768:   }
  769:   return OK;
  770: }
  771: 
  772: 1;
  773: __END__
  774: 
  775: 
  776: 
  777: =pod
  778: 
  779: =head1 NAME
  780: 
  781: Apache::lonratedt: simple resource assembly tool
  782: 
  783: =head1 SYNOPSIS
  784: 
  785: lonratedt provides the routines and the handler for the Advanced
  786:     Resource Assembly Tool (RAT), and ties the various pieces together
  787:     with Javascript.
  788: 
  789: =head1 OVERVIEW
  790: 
  791: =head2 Map Representation
  792: 
  793: =begin latex
  794: 
  795: %
  796: \begin{figure}
  797: \begin{center}\includegraphics[%
  798:   width=0.55\paperwidth,bb = 0 0 200 100, draft, type=eps]{Map_Example}\end{center}
  799: 
  800: 
  801: \caption{\label{Map_In_Advanced_Editor}Example of a Map in the Advanced Editor}
  802: \end{figure}
  803: %
  804: \begin{figure}
  805: \begin{lyxcode}
  806: <map>
  807: 
  808: ~~<resource~id=\char`\"{}1\char`\"{}
  809: 
  810: ~~~~src=\char`\"{}/res/msu/korte/phy231welcome.html\char`\"{}
  811: 
  812: ~~~~type=\char`\"{}start\char`\"{}
  813: 
  814: ~~~~title=\char`\"{}Start\char`\"{}>
  815: 
  816: ~~~~</resource>
  817: 
  818: ~~<resource~id=\char`\"{}2\char`\"{}
  819: 
  820: ~~~~src=\char`\"{}\char`\"{}~type=\char`\"{}finish\char`\"{}
  821: 
  822: ~~~~title=\char`\"{}Finish\char`\"{}>
  823: 
  824: ~~~~</resource>
  825: 
  826: ~~<resource~id=\char`\"{}6\char`\"{}
  827: 
  828: ~~~~src=\char`\"{}/res/msu/korte/tests/units.problem\char`\"{}
  829: 
  830: ~~~~type=\char`\"{}mandatory\char`\"{}
  831: 
  832: ~~~~title=\char`\"{}Physical~Units~Test\char`\"{}>
  833: 
  834: ~~~~</resource>
  835: 
  836: ~~<resource~id=\char`\"{}9\char`\"{}
  837: 
  838: ~~~~src=\char`\"{}/res/msu/korte/chapters/onedim.sequence\char`\"{}
  839: 
  840: ~~~~title=\char`\"{}Motion~in~One~Dimension\char`\"{}>
  841: 
  842: ~~~~</resource>
  843: 
  844: ~~<resource~id=\char`\"{}11\char`\"{}
  845: 
  846: ~~~~src=\char`\"{}/res/msu/bauer/bridges/units.sequence\char`\"{}
  847: 
  848: ~~~~title=\char`\"{}Physical~Units~Refresher\char`\"{}>
  849: 
  850: ~~~~</resource>
  851: 
  852: ~~<condition~id=\char`\"{}19\char`\"{}
  853: 
  854: ~~~~type=\char`\"{}stop\char`\"{}
  855: 
  856: ~~~~value=\char`\"{}user.assessments{[}this./res/msu/korte/tests/units.problem{]}.status=solved\char`\"{}>
  857: 
  858: ~~~~</condition>
  859: 
  860: ~~<link~from=\char`\"{}1\char`\"{}~to=\char`\"{}6\char`\"{}></link>
  861: 
  862: ~~<link~from=\char`\"{}6\char`\"{}~to=\char`\"{}9\char`\"{}~condition=\char`\"{}19\char`\"{}></link>
  863: 
  864: ~~<link~from=\char`\"{}6\char`\"{}~to=\char`\"{}11\char`\"{}></link>
  865: 
  866: ~~<link~from=\char`\"{}11\char`\"{}~to=\char`\"{}6\char`\"{}></link>
  867: 
  868: ~~</map>
  869: \end{lyxcode}
  870: 
  871: \caption{\label{XML}XML for Map in Figure \ref{Map_In_Advanced_Editor}}
  872: \end{figure}
  873: 
  874: =end latex
  875: 
  876: Fig. "XML for Map in Figure" shows the XML representation of the
  877: resource map shown in Fig. "Example of a Map in the Advanced Editor",
  878: which is the format in which maps are stored. In the figure, however,
  879: additional graphical map layout information generated by the Advanced
  880: Resource Assembly Tool is not displayed. This graphical information is
  881: optional to re-generate the same graphical layout when the map is
  882: brought up again in the Resource Assembly Tool, and is not needed for
  883: any other system functionality.
  884: 
  885: Maps can be generated by tools other than the Resource Assembly
  886: Tool. In particular, an author might have some other representation of
  887: a course sequence, which can be converted into a map using scripts. If
  888: this map then were to be brought up in the Resource Assembly Tool, the
  889: Tool would automatically generate a graphical layout for it. Each
  890: entry of the map (resources, conditions and links) is stored in a
  891: separate tag.
  892: 
  893: Resources and conditionsX<conditions> have to have unique ID
  894: numbers. These numbers are automatically generated by the Resource
  895: Assembly Tool when the entry is first created, or added to the entries
  896: when a map generated outside the Resource Assembly Tool is first
  897: retrieved. They can also be assigned by custom scripts or added in by
  898: hand.
  899: 
  900: In the XML example, entry 1 is the start resource of the map. When
  901: this map is accessed, the source (src) URL of this tag will be the
  902: first resource rendered. Entry 2 is the finish resource of this
  903: map. This resource will be the last resource in the sequence of
  904: resources. Entry 6 is a problem resource with the given URL and title,
  905: as well as the priority "mandatory". Entry 19 is a condition, which is
  906: used by the link between entries 6, the problem, and 9, a
  907: sequence. I<The final syntax for conditions has not yet been
  908: determined.>
  909: 
  910: =cut
  911: 
  912: 
  913: 

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