1: # The LearningOnline Network with CAPA
2: # Edit Handler for RAT Maps
3: #
4: # $Id: lonratedt.pm,v 1.13 2002/05/13 19:23:52 www 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: # (TeX Content Handler
29: #
30: # 05/29/00,05/30 Gerd Kortemeyer)
31: # 7/1,6/30 Gerd Kortemeyer
32:
33: package Apache::lonratedt;
34:
35: use strict;
36: use Apache::Constants qw(:common);
37: use Apache::lonnet;
38: use Apache::lonratsrv;
39:
40: my @order=();
41: my @resources=();
42:
43:
44: # Mapread read maps into global arrays @links and @resources, determines status
45: # sets @order - pointer to resources in right order
46: # sets @resources - array with the resources with correct idx
47: #
48: sub mapread {
49: my $fn=shift;
50:
51: my @links;
52: undef @links;
53: undef @resources;
54: undef @order;
55:
56: my ($outtext,$errtext)=&Apache::lonratsrv::loadmap($fn,'');
57: if ($errtext) { return ($errtext,2); }
58:
59: # -------------------------------------------------------------------- Read map
60: foreach (split(/\<\&\>/,$outtext)) {
61: my ($command,$number,$content)=split(/\<\:\>/,$_);
62: if ($command eq 'objcont') {
63: $resources[$number]=$content;
64: }
65: if ($command eq 'objlinks') {
66: $links[$number]=$content;
67: }
68: }
69: # ------------------------------------------------------- Is this a linear map?
70: my @starters=();
71: my @endings=();
72: undef @starters;
73: undef @endings;
74:
75: foreach (@links) {
76: if (defined($_)) {
77: my ($start,$end,$cond)=split(/\:/,$_);
78: if ((defined($starters[$start])) || (defined($endings[$end]))) {
79: return
80: ('Map has branchings. Use advanced editor.',1);
81: }
82: $starters[$start]=1;
83: $endings[$end]=1;
84: if ($cond) {
85: return
86: ('Map has conditions. Use advanced editor.',1);
87: }
88: }
89:
90: }
91: for (my $i=0; $i<=$#resources; $i++) {
92: if (defined($resources[$i])) {
93: unless (($starters[$i]) || ($endings[$i])) {
94: return
95: ('Map has unconnected resources. Use advanced editor.',1);
96: }
97: }
98: }
99:
100: # -------------------------------------------------- This is a linear map, sort
101:
102: my $startidx=0;
103: my $endidx=0;
104: for (my $i=0; $i<=$#resources; $i++) {
105: if (defined($resources[$i])) {
106: my ($title,$url,$ext,$type)=split(/\:/,$resources[$i]);
107: if ($type eq 'start') { $startidx=$i; }
108: if ($type eq 'finish') { $endidx=$i; }
109: }
110: }
111: my $k=0;
112: my $currentidx=$startidx;
113: $order[$k]=$currentidx;
114: for (my $i=0; $i<=$#resources; $i++) {
115: foreach (@links) {
116: my ($start,$end)=split(/\:/,$_);
117: if ($start==$currentidx) {
118: $currentidx=$end;
119: $k++;
120: $order[$k]=$currentidx;
121: last;
122: }
123: }
124: if ($currentidx==$endidx) { last; }
125: }
126: return $errtext;
127: }
128:
129: # --------------------------------------------------------- Build up RAT screen
130: sub ratedt {
131: my ($r,$url)=@_;
132: $r->print(<<ENDDOCUMENT);
133:
134: <html>
135: <head>
136: <script language="JavaScript">
137: var flag=0;
138: </script>
139: </head>
140: <frameset rows="1,50,*" border=0>
141: <frame name=server src="$url/loadonly/ratserver" noresize noscroll>
142: <frame name=code src="/adm/rat/code.html">
143: <frame name=mapout src="/adm/rat/map.html">
144: </frameset>
145: </html>
146:
147: ENDDOCUMENT
148: }
149:
150: # ---------------------------------------------------------------- Make buttons
151:
152: sub buttons {
153: my $adv=shift;
154: my $output='<form method=post>';
155: if ($adv==1) {
156: $output.='<input type=submit name=forceadv value="Edit">';
157: } else {
158: unless ($adv==2) {
159: $output.='<input type=submit name=forcesmp value="Simple Edit">';
160: }
161: $output.='<input type=submit name=forceadv value="Advanced Edit">';
162: }
163: return $output.'</form><hr>';
164: }
165:
166: sub smpedt {
167: my ($r,$errtext)=@_;
168: my $buttons=&buttons(2);
169:
170: # ---------------------------------------------------------- Process form input
171:
172: my @importselect=();
173: my @targetselect=();
174: undef @importselect;
175: undef @targetselect;
176: if (defined($ENV{'form.import'})) {
177: if (ref($ENV{'form.import'})) {
178: @importselect=sort($ENV->{'form.import'});
179: } else {
180: @importselect=($ENV{'form.import'});
181: }
182: }
183: if (defined($ENV{'form.target'})) {
184: if (ref($ENV{'form.target'})) {
185: @targetselect=sort($ENV->{'form.target'});
186: } else {
187: @targetselect=($ENV{'form.target'});
188: }
189: }
190: # ============================================================ Process commands
191:
192: my $targetdetail='';
193: my $importdetail='';
194:
195: # ---------------------------------------------------- Importing from groupsort
196: if ($ENV{'form.importdetail'}) {
197:
198: my @curimport=split(/\&/,$ENV{'form.curimpdetail'});
199:
200: my $lastsel;
201:
202: if (defined($importselect[-1])) {
203: $lastsel=$importselect[-1];
204: } else {
205: $lastsel=$#curimport;
206: }
207:
208: for (my $i=0;$i<=$lastsel;$i++) {
209: my ($name,$url)=split(/\=/,$curimport[$i]);
210: if ($url) {
211: $importdetail.='&'.&Apache::lonnet::escape($name).'='.
212: &Apache::lonnet::escape($url);
213: }
214: }
215:
216: $importdetail.='&'.$ENV{'form.importdetail'};
217:
218: for (my $i=$lastsel+1;$i<=$#curimport;$i++) {
219: my ($name,$url)=split(/\=/,$curimport[$i]);
220: if ($url) {
221: $importdetail.='&'.&Apache::lonnet::escape($name).'='.
222: &Apache::lonnet::escape($url);
223: }
224: }
225: $importdetail=~s/\&+/\&/g;
226: $importdetail=~s/^\&//;
227:
228: # --------------------------------------------------------
229: }
230:
231: # ------------------------------------------------------------ Assemble windows
232:
233: my $idx=-1;
234: my $importwindow=join("\n",map {
235: $idx++;
236: if ($_) {
237: my ($name)=split(/\=/,$_);
238: unless ($name) { $name='UNKNOWN'; }
239: '<option value="'.$idx.'">'.&Apache::lonnet::unescape($name).
240: '</option>';
241: }
242: } split(/\&/,$importdetail));
243:
244: $idx=0;
245: my $targetwindow=join("\n",map {
246: my ($name,$url)=split(/\:/,$resources[$_]);
247: unless ($name) { $name='UNKNOWN'; }
248: $targetdetail.='&'.&Apache::lonnet::escape($name).'='.
249: &Apache::lonnet::escape($url);
250: $idx++;
251: '<option value="'.$idx.'_'.$_.'">'.$name.'</option>';
252: } @order);
253:
254: # ----------------------------------------------------- Start simple RAT screen
255: $r->print(<<ENDSMPHEAD);
256: <html>
257: <head>
258: <script>
259: var srch;
260: var srchflag=-1; // 1 means currently open
261: // 0 means closed (but has been open)
262: // -1 means never yet opened/defined
263: var srchmode='';
264:
265: var idx;
266: var idxflag=-1; // 1 means currently open
267: // 0 means closed (but has been open)
268: // -1 means never yet opened/defined
269: var idxmode='';
270:
271: // ------------------------------------------------------ Clears indexer window
272: function idxclear() {
273: idx.document.clear();
274: }
275:
276: // ------------------------------------------------------- Clears search window
277: function srchclear() {
278: srch.document.clear();
279: }
280:
281: // ------------------------------------------------------ Closes indexer window
282: function idxclose() {
283: if (idx && !idx.closed) {
284: idxflag=0;
285: idx.close();
286: }
287: }
288:
289: // ------------------------------------------------------- Closes search window
290: function srchclose() {
291: if (srch && !srch.closed) {
292: srchflag=0;
293: srch.close();
294: }
295: }
296:
297: // -------------------------------------------------------- Open indexer window
298: function idxopen(mode) {
299: var options="scrollbars=1,resizable=1,menubar=0";
300: idxmode=mode;
301: idxflag=1;
302: idx=open("/res/?launch=1&mode=simple&catalogmode="+mode,"idxout",options);
303: idx.focus();
304: }
305:
306: // --------------------------------------------------------- Open search window
307: function srchopen(mode) {
308: var options="scrollbars=1,resizable=1,menubar=0";
309: srchmode=mode;
310: srchflag=1;
311: srch=open("/adm/searchcat?launch=1&mode=simple&catalogmode="+mode,"srchout",options);
312: srch.focus();
313: }
314: // ----------------------------------------------------- launch indexer browser
315: function groupsearch() {
316: srchcheck('groupsearch');
317: }
318:
319: function groupimport() {
320: idxcheck('groupimport');
321: }
322: // ------------------------------------------------------- Do srch status check
323: function srchcheck(mode) {
324: if (!srch || srch.closed || srchmode!=mode) {
325: srchopen(mode);
326: }
327: srch.focus();
328: }
329:
330: // -------------------------------------------------------- Do idx status check
331: function idxcheck(mode) {
332: if (!idx || idx.closed || idxmode!=mode) {
333: idxopen(mode);
334: }
335: idx.focus();
336: }
337: </script>
338: </head>
339: <body bgcolor='#FFFFFF'>
340: $buttons
341: <font color=red>$errtext</font>
342: <form name=simpleedit method=post>
343: <input type=hidden name=forcesmp value=1>
344: <table>
345: <tr><th width="40%">Import</th>
346: <th> </th>
347: <th width="40%">Target</th></tr>
348: <tr><td bgcolor="#FFFFCC">
349: <input type=button onClick="javascript:groupsearch()" value="Group Search">
350: <input type=button onClick="javascript:groupimport();" value="Group Import">
351: <input type=button onClick="javascript:viewimport()" value="View">
352: </td><td> </td><td bgcolor="#FFFFCC">
353: <input type=button onClick="javascript:viewtarget()" value="View">
354: </td></tr>
355: <tr><td bgcolor="#FFFFCC"><select name="import" multiple>
356: $importwindow
357: </select>
358: </td>
359: <td bgcolor="#FFFFAA" align="center">
360: Cut selected<br>
361: <input type=submit name=cut value='<<<'><p>
362: <hr>
363: Paste after selected<br>
364: <input type=submit name=paste value='>>>'>
365: </td>
366: <td bgcolor="#FFFFCC"><select name="target" multiple>
367: $targetwindow
368: </select>
369: </table>
370: <input type=hidden name=importdetail value="">
371: <input type=hidden name=curimpdetail value="$importdetail">
372: <input type=hidden name=targetdetail value="$targetdetail">
373: </form>
374: </body></html>
375: ENDSMPHEAD
376: }
377:
378: # ----------------------------------------------------------------- No such dir
379: sub nodir {
380: my ($r,$dir)=@_;
381: $dir=~s/^\/home\/\w+\/public\_html//;
382: $r->print(<<ENDNODIR);
383: <html>
384: <body bgcolor='#FFFFFF'>
385: <h1>No such directory: $dir</h1>
386: </body>
387: </html>
388: ENDNODIR
389: }
390:
391: # ---------------------------------------------------------------- View Handler
392:
393: sub viewmap {
394: my ($r,$adv,$errtext)=@_;
395: $r->print('<html><body bgcolor="#FFFFFF">'.&buttons($adv));
396: if ($errtext) {
397: $r->print($errtext.'<hr>');
398: }
399: foreach (@resources) {
400: if (defined($_)) {
401: my ($title,$url)=split(/\:/,$_);
402: $title=~s/\&colon\;/\:/g;
403: $url=~s/\&colon\;/\:/g;
404: unless ($title) { $title='<i>Unknown</i>'; }
405: if ($url) {
406: $r->print('<a href="'.&Apache::lonratsrv::qtescape($url).'">');
407: }
408: $r->print(&Apache::lonratsrv::qtescape($title));
409: if ($url) { $r->print('</a>'); }
410: $r->print('<br>');
411: }
412: }
413: $r->print('</body></html>');
414: }
415:
416: # ================================================================ Main Handler
417:
418: sub handler {
419: my $r=shift;
420: $r->content_type('text/html');
421: $r->send_http_header;
422:
423: return OK if $r->header_only;
424:
425: my $url=$r->uri;
426: my $fn=&Apache::lonnet::filelocation('',$url);
427:
428: my ($dir)=($fn=~/^(.+)\/[^\/]+$/);
429: unless (-e $dir) {
430: &nodir($r,$dir);
431: return OK;
432: }
433:
434: # ------------------------------------------- Determine which tools can be used
435: my $adv=0;
436:
437: unless ($ENV{'form.forcesmp'}) {
438: if ($ENV{'form.forceadv'}) {
439: $adv=1;
440: } elsif (my $fh=Apache::File->new($fn)) {
441: my $allmap=join('',<$fh>);
442: $adv=($allmap=~/\<map[^\>]+mode\s*\=\s*(\'|\")rat/is);
443: }
444: }
445:
446: my $errtext='';
447: my $fatal=0;
448:
449: # -------------------------------------------------------------------- Load map
450: ($errtext,$fatal)=&mapread($fn,$errtext);
451:
452: if ($fatal==1) { $adv=1; }
453:
454: # ----------------------------------- adv==1 now means "graphical MUST be used"
455:
456: if ($ENV{'form.forceadv'}) {
457: &ratedt($r,$url);
458: } elsif ($ENV{'form.forcesmp'}) {
459: &smpedt($r,$errtext);
460: } else {
461: &viewmap($r,$adv,$errtext);
462: }
463: return OK;
464: }
465:
466: 1;
467: __END__
468:
469:
470:
471:
472:
473:
474:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>