![]() ![]() | ![]() |
The HTML entity for " is ", not &quod;
1: # The LearningOnline Network with CAPA 2: # Metadata display handler 3: # 4: # $Id: lonmeta.pm,v 1.77 2004/05/07 17:17:58 matthew 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: package Apache::lonmeta; 30: 31: use strict; 32: use LONCAPA::lonmetadata(); 33: use Apache::Constants qw(:common); 34: use Apache::lonnet(); 35: use Apache::loncommon(); 36: use Apache::lonhtmlcommon(); 37: use Apache::lonmsg; 38: use Apache::lonpublisher; 39: use Apache::lonlocal; 40: use Apache::lonmysql; 41: use Apache::lonmsg; 42: 43: 44: # Fetch and evaluate dynamic metadata 45: sub dynamicmeta { 46: my $url=&Apache::lonnet::declutter(shift); 47: $url=~s/\.meta$//; 48: my ($adomain,$aauthor)=($url=~/^(\w+)\/(\w+)\//); 49: my $regexp=$url; 50: $regexp=~s/(\W)/\\$1/g; 51: $regexp='___'.$regexp.'___'; 52: my %evaldata=&Apache::lonnet::dump('nohist_resevaldata',$adomain, 53: $aauthor,$regexp); 54: my %DynamicData = &LONCAPA::lonmetadata::process_reseval_data(\%evaldata); 55: my %Data = &LONCAPA::lonmetadata::process_dynamic_metadata($url, 56: \%DynamicData); 57: # 58: # Deal with 'count' separately 59: $Data{'count'} = &access_count($url,$aauthor,$adomain); 60: # 61: # Debugging code I will probably need later 62: if (0) { 63: &Apache::lonnet::logthis('Dynamic Metadata'); 64: while(my($k,$v)=each(%Data)){ 65: &Apache::lonnet::logthis(' "'.$k.'"=>"'.$v.'"'); 66: } 67: &Apache::lonnet::logthis('-------------------'); 68: } 69: return %Data; 70: } 71: 72: sub access_count { 73: my ($src,$author,$adomain) = @_; 74: my %countdata=&Apache::lonnet::dump('nohist_accesscount',$adomain, 75: $author,$src); 76: if (! exists($countdata{$src})) { 77: return &mt('Not Available'); 78: } else { 79: return $countdata{$src}; 80: } 81: } 82: 83: # Try to make an alt tag if there is none 84: sub alttag { 85: my ($base,$src)=@_; 86: my $fullpath=&Apache::lonnet::hreflocation($base,$src); 87: my $alttag=&Apache::lonnet::metadata($fullpath,'title').' '. 88: &Apache::lonnet::metadata($fullpath,'subject').' '. 89: &Apache::lonnet::metadata($fullpath,'abstract'); 90: $alttag=~s/\s+/ /gs; 91: $alttag=~s/\"//gs; 92: $alttag=~s/\'//gs; 93: $alttag=~s/\s+$//gs; 94: $alttag=~s/^\s+//gs; 95: if ($alttag) { 96: return $alttag; 97: } else { 98: return &mt('No information available'); 99: } 100: } 101: 102: # Author display 103: sub authordisplay { 104: my ($aname,$adom)=@_; 105: return &Apache::loncommon::aboutmewrapper 106: (&Apache::loncommon::plainname($aname,$adom), 107: $aname,$adom,'preview').' <tt>['.$aname.'@'.$adom.']</tt>'; 108: } 109: 110: # Pretty display 111: sub evalgraph { 112: my $value=shift; 113: if (! $value) { 114: return ''; 115: } 116: my $val=int($value*10.+0.5)-10; 117: my $output='<table border="0" cellpadding="0" cellspacing="0"><tr>'; 118: if ($val>=20) { 119: $output.='<td width="20" bgcolor="#555555">  </td>'; 120: } else { 121: $output.='<td width="'.($val).'" bgcolor="#555555"> </td>'. 122: '<td width="'.(20-$val).'" bgcolor="#FF3333"> </td>'; 123: } 124: $output.='<td bgcolor="#FFFF33"> </td>'; 125: if ($val>20) { 126: $output.='<td width="'.($val-20).'" bgcolor="#33FF33"> </td>'. 127: '<td width="'.(40-$val).'" bgcolor="#555555"> </td>'; 128: } else { 129: $output.='<td width="20" bgcolor="#555555">  </td>'; 130: } 131: $output.='<td> ('.sprintf("%5.2f",$value).') </td></tr></table>'; 132: return $output; 133: } 134: 135: sub diffgraph { 136: my $value=shift; 137: if (! $value) { 138: return ''; 139: } 140: my $val=int(40.0*$value+0.5); 141: my @colors=('#FF9933','#EEAA33','#DDBB33','#CCCC33', 142: '#BBDD33','#CCCC33','#DDBB33','#EEAA33'); 143: my $output='<table border="0" cellpadding="0" cellspacing="0"><tr>'; 144: for (my $i=0;$i<8;$i++) { 145: if ($val>$i*5) { 146: $output.='<td width="5" bgcolor="'.$colors[$i].'"> </td>'; 147: } else { 148: $output.='<td width="5" bgcolor="#555555"> </td>'; 149: } 150: } 151: $output.='<td> ('.sprintf("%3.2f",$value).') </td></tr></table>'; 152: return $output; 153: } 154: 155: 156: # The field names 157: sub fieldnames { 158: return &Apache::lonlocal::texthash 159: ( 160: 'title' => 'Title', 161: 'author' =>'Author(s)', 162: 'authorspace' => 'Author Space', 163: 'modifyinguser' => 'Last Modifying User', 164: 'subject' => 'Subject', 165: 'keywords' => 'Keyword(s)', 166: 'notes' => 'Notes', 167: 'abstract' => 'Abstract', 168: 'lowestgradelevel' => 'Lowest Grade Level', 169: 'highestgradelevel' => 'Highest Grade Level', 170: 'standards' => 'Standards', 171: 'mime' => 'MIME Type', 172: 'language' => 'Language', 173: 'creationdate' => 'Creation Date', 174: 'lastrevisiondate' => 'Last Revision Date', 175: 'owner' => 'Publisher/Owner', 176: 'copyright' => 'Copyright/Distribution', 177: 'customdistributionfile' => 'Custom Distribution File', 178: 'obsolete' => 'Obsolete', 179: 'obsoletereplacement' => 'Suggested Replacement for Obsolete File', 180: 'count' => 'Network-wide number of accesses (hits)', 181: 'course' => 'Network-wide number of courses using resource', 182: 'course_list' => 'Network-wide courses using resource', 183: 'sequsage' => 'Number of resources using or importing resource', 184: 'sequsage_list' => 'Resources using or importing resource', 185: 'goto' => 'Number of resources that follow this resource in maps', 186: 'goto_list' => 'Resources that follow this resource in maps', 187: 'comefrom' => 'Number of resources that lead up to this resource in maps', 188: 'comefrom_list' => 'Resources that lead up to this resource in maps', 189: 'clear' => 'Material presented in clear way', 190: 'depth' => 'Material covered with sufficient depth', 191: 'helpful' => 'Material is helpful', 192: 'correct' => 'Material appears to be correct', 193: 'technical' => 'Resource is technically correct', 194: 'avetries' => 'Average number of tries till solved', 195: 'stdno' => 'Total number of students who have worked on this problem', 196: 'difficulty' => 'Degree of difficulty', 197: 'disc' => 'Degree of discrimination', 198: ); 199: } 200: 201: # Pretty printing of metadata field 202: 203: sub prettyprint { 204: my ($type,$value)=@_; 205: if (! defined($value)) { 206: return ' '; 207: } 208: # Title 209: if ($type eq 'title') { 210: return '<font size="+1" face="arial">'.$value.'</font>'; 211: } 212: # Dates 213: if (($type eq 'creationdate') || 214: ($type eq 'lastrevisiondate')) { 215: return ($value?&Apache::lonlocal::locallocaltime( 216: &Apache::lonmysql::unsqltime($value)): 217: &mt('not available')); 218: } 219: # Language 220: if ($type eq 'language') { 221: return &Apache::loncommon::languagedescription($value); 222: } 223: # Copyright 224: if ($type eq 'copyright') { 225: return &Apache::loncommon::copyrightdescription($value); 226: } 227: # MIME 228: if ($type eq 'mime') { 229: return '<img src="'.&Apache::loncommon::icon($value).'" /> '. 230: &Apache::loncommon::filedescription($value); 231: } 232: # Person 233: if (($type eq 'author') || 234: ($type eq 'owner') || 235: ($type eq 'modifyinguser') || 236: ($type eq 'authorspace')) { 237: $value=~s/(\w+)(\:|\@)(\w+)/&authordisplay($1,$3)/gse; 238: return $value; 239: } 240: # Gradelevel 241: if (($type eq 'lowestgradelevel') || 242: ($type eq 'highestgradelevel')) { 243: return &Apache::loncommon::gradeleveldescription($value); 244: } 245: # Only for advance users below 246: if (! $ENV{'user.adv'}) { 247: return '<i>- '.&mt('not displayed').' -</i>'; 248: } 249: # File 250: if (($type eq 'customdistributionfile') || 251: ($type eq 'obsoletereplacement') || 252: ($type eq 'goto_list') || 253: ($type eq 'comefrom_list') || 254: ($type eq 'sequsage_list')) { 255: return join('<br />',map { 256: my $url = &Apache::lonnet::clutter($_); 257: my $title = &Apache::lonnet::gettitle($url); 258: if ($title eq '') { 259: $title = 'Untitled'; 260: if ($url =~ /\.sequence$/) { 261: $title .= ' Sequence'; 262: } elsif ($url =~ /\.page$/) { 263: $title .= ' Page'; 264: } elsif ($url =~ /\.problem$/) { 265: $title .= ' Problem'; 266: } elsif ($url =~ /\.html$/) { 267: $title .= ' HTML document'; 268: } elsif ($url =~ m:/syllabus$:) { 269: $title .= ' Syllabus'; 270: } 271: } 272: $_ = '<b>'.$title.'</b> '. 273: '<a href="'.$url.'" target="preview">'. 274: '<font size="-1">'.$url.'</font>'. 275: '</a>' 276: } split(/\s*\,\s*/,$value)); 277: } 278: # Evaluations 279: if (($type eq 'clear') || 280: ($type eq 'depth') || 281: ($type eq 'helpful') || 282: ($type eq 'correct') || 283: ($type eq 'technical')) { 284: return &evalgraph($value); 285: } 286: # Difficulty 287: if ($type eq 'difficulty' || $type eq 'disc') { 288: return &diffgraph($value); 289: } 290: # List of courses 291: if ($type=~/\_list/) { 292: my @Courses = split(/\s*\,\s*/,$value); 293: my $Str; 294: foreach my $course (@Courses) { 295: my %courseinfo = &Apache::lonnet::coursedescription($course); 296: if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { 297: next; 298: } 299: if ($Str ne '') { $Str .= '<br />'; } 300: $Str .= '<a href="/public/'.$courseinfo{'domain'}.'/'. 301: $courseinfo{'num'}.'/syllabus" target="preview">'. 302: $courseinfo{'description'}.'</a>'; 303: } 304: return $Str; 305: } 306: # No pretty print found 307: return $value; 308: } 309: 310: # Pretty input of metadata field 311: sub direct { 312: return shift; 313: } 314: 315: sub selectbox { 316: my ($name,$value,$functionref,@idlist)=@_; 317: if (! defined($functionref)) { 318: $functionref=\&direct; 319: } 320: my $selout='<select name="'.$name.'">'; 321: foreach (@idlist) { 322: $selout.='<option value=\''.$_.'\''; 323: if ($_ eq $value) { 324: $selout.=' selected>'.&{$functionref}($_).'</option>'; 325: } 326: else {$selout.='>'.&{$functionref}($_).'</option>';} 327: } 328: return $selout.'</select>'; 329: } 330: 331: sub relatedfield { 332: my ($show,$relatedsearchflag,$relatedsep,$fieldname,$relatedvalue)=@_; 333: if (! $relatedsearchflag) { 334: return ''; 335: } 336: if (! defined($relatedsep)) { 337: $relatedsep=' '; 338: } 339: if (! $show) { 340: return $relatedsep.' '; 341: } 342: return $relatedsep.'<input type="checkbox" name="'.$fieldname.'_related"'. 343: ($relatedvalue?' checked="1"':'').' />'; 344: } 345: 346: sub prettyinput { 347: my ($type,$value,$fieldname,$formname, 348: $relatedsearchflag,$relatedsep,$relatedvalue,$size)=@_; 349: if (! defined($size)) { 350: $size = 80; 351: } 352: # Language 353: if ($type eq 'language') { 354: return &selectbox($fieldname, 355: $value, 356: \&Apache::loncommon::languagedescription, 357: (&Apache::loncommon::languageids)). 358: &relatedfield(0,$relatedsearchflag,$relatedsep); 359: } 360: # Copyright 361: if ($type eq 'copyright') { 362: return &selectbox($fieldname, 363: $value, 364: \&Apache::loncommon::copyrightdescription, 365: (&Apache::loncommon::copyrightids)). 366: &relatedfield(0,$relatedsearchflag,$relatedsep); 367: } 368: # Gradelevels 369: if (($type eq 'lowestgradelevel') || 370: ($type eq 'highestgradelevel')) { 371: return &Apache::loncommon::select_level_form($value,$fieldname). 372: &relatedfield(0,$relatedsearchflag,$relatedsep); 373: } 374: # Obsolete 375: if ($type eq 'obsolete') { 376: return '<input type="checkbox" name="'.$fieldname.'"'. 377: ($value?' checked="1"':'').' />'. 378: &relatedfield(0,$relatedsearchflag,$relatedsep); 379: } 380: # Obsolete replacement file 381: if ($type eq 'obsoletereplacement') { 382: return '<input type="text" name="'.$fieldname. 383: '" size="60" value="'.$value.'" /><a href="javascript:openbrowser'. 384: "('".$formname."','".$fieldname."'". 385: ",'')\">".&mt('Select').'</a>'. 386: &relatedfield(0,$relatedsearchflag,$relatedsep); 387: } 388: # Customdistribution file 389: if ($type eq 'customdistributionfile') { 390: return '<input type="text" name="'.$fieldname. 391: '" size="60" value="'.$value.'" /><a href="javascript:openbrowser'. 392: "('".$formname."','".$fieldname."'". 393: ",'rights')\">".&mt('Select').'</a>'. 394: &relatedfield(0,$relatedsearchflag,$relatedsep); 395: } 396: # Dates 397: if (($type eq 'creationdate') || 398: ($type eq 'lastrevisiondate')) { 399: return 400: &Apache::lonhtmlcommon::date_setter($formname,$fieldname,$value). 401: &relatedfield(0,$relatedsearchflag,$relatedsep); 402: } 403: # No pretty input found 404: $value=~s/^\s+//gs; 405: $value=~s/\s+$//gs; 406: $value=~s/\s+/ /gs; 407: $value=~s/\"/\"\;/gs; 408: return 409: '<input type="text" name="'.$fieldname.'" size="'.$size.'" '. 410: 'value="'.$value.'" />'. 411: &relatedfield(1,$relatedsearchflag,$relatedsep,$fieldname, 412: $relatedvalue); 413: } 414: 415: # Main Handler 416: sub handler { 417: my $r=shift; 418: # 419: my $uri=$r->uri; 420: # 421: # Set document type 422: &Apache::loncommon::content_type($r,'text/html'); 423: $r->send_http_header; 424: return OK if $r->header_only; 425: # 426: my ($resdomain,$resuser)= 427: (&Apache::lonnet::declutter($uri)=~/^(\w+)\/(\w+)\//); 428: $r->print('<html><head><title>'. 429: 'Catalog Information'. 430: '</title></head>'); 431: if ($uri=~m:/adm/bombs/(.*)$:) { 432: $r->print(&Apache::loncommon::bodytag('Error Messages')); 433: # Looking for all bombs? 434: &report_bombs($r,$uri); 435: } elsif ($uri=~/^\/\~/) { 436: # Construction space 437: $r->print(&Apache::loncommon::bodytag 438: ('Edit Catalog Information','','','',$resdomain)); 439: &present_editable_metadata($r,$uri); 440: } else { 441: $r->print(&Apache::loncommon::bodytag 442: ('Catalog Information','','','',$resdomain)); 443: &present_uneditable_metadata($r,$uri); 444: } 445: $r->print('</body></html>'); 446: return OK; 447: } 448: 449: ##################################################### 450: ##################################################### 451: ### ### 452: ### Report Bombs ### 453: ### ### 454: ##################################################### 455: ##################################################### 456: sub report_bombs { 457: my ($r,$uri) = @_; 458: # Set document type 459: $uri =~ s:/adm/bombs/::; 460: $uri = &Apache::lonnet::declutter($uri); 461: $r->print('<h1>'.&Apache::lonnet::clutter($uri).'</h1>'); 462: my ($domain,$author)=($uri=~/^(\w+)\/(\w+)\//); 463: if (&Apache::loncacc::constructaccess('/~'.$author.'/',$domain)) { 464: my %brokenurls = 465: &Apache::lonmsg::all_url_author_res_msg($author,$domain); 466: foreach (sort(keys(%brokenurls))) { 467: if ($_=~/^\Q$uri\E/) { 468: $r->print 469: ('<a href="'.&Apache::lonnet::clutter($_).'">'.$_.'</a>'. 470: &Apache::lonmsg::retrieve_author_res_msg($_). 471: '<hr />'); 472: } 473: } 474: } else { 475: $r->print(&mt('Not authorized')); 476: } 477: return; 478: } 479: 480: ##################################################### 481: ##################################################### 482: ### ### 483: ### Uneditable Metadata Display ### 484: ### ### 485: ##################################################### 486: ##################################################### 487: sub present_uneditable_metadata { 488: my ($r,$uri) = @_; 489: # 490: my %content=(); 491: # Read file 492: foreach (split(/\,/,&Apache::lonnet::metadata($uri,'keys'))) { 493: $content{$_}=&Apache::lonnet::metadata($uri,$_); 494: } 495: # Render Output 496: # displayed url 497: my ($thisversion)=($uri=~/\.(\d+)\.(\w+)\.meta$/); 498: $uri=~s/\.meta$//; 499: my $disuri=&Apache::lonnet::clutter($uri); 500: # version 501: my $currentversion=&Apache::lonnet::getversion($disuri); 502: my $versiondisplay=''; 503: if ($thisversion) { 504: $versiondisplay=&mt('Version').': '.$thisversion. 505: ' ('.&mt('most recent version').': '. 506: ($currentversion>0 ? 507: $currentversion : 508: &mt('information not available')).')'; 509: } else { 510: $versiondisplay='Version: '.$currentversion; 511: } 512: # crumbify displayed URL uri target prefix form size 513: $disuri=&Apache::lonhtmlcommon::crumbs($disuri,undef, undef, undef,'+1'); 514: $disuri =~ s:<br />::g; 515: # obsolete 516: my $obsolete=$content{'obsolete'}; 517: my $obsoletewarning=''; 518: if (($obsolete) && ($ENV{'user.adv'})) { 519: $obsoletewarning='<p><font color="red">'. 520: &mt('This resource has been marked obsolete by the author(s)'). 521: '</font></p>'; 522: } 523: # 524: my %lt=&fieldnames(); 525: my $table=''; 526: my $title = $content{'title'}; 527: if (! defined($title)) { 528: $title = 'Untitled Resource'; 529: } 530: foreach ('title', 531: 'author', 532: 'subject', 533: 'keywords', 534: 'notes', 535: 'abstract', 536: 'lowestgradelevel', 537: 'highestgradelevel', 538: 'standards', 539: 'mime', 540: 'language', 541: 'creationdate', 542: 'lastrevisiondate', 543: 'owner', 544: 'copyright', 545: 'customdistributionfile', 546: 'obsolete', 547: 'obsoletereplacement') { 548: $table.='<tr><td bgcolor="#AAAAAA">'.$lt{$_}. 549: '</td><td bgcolor="#CCCCCC">'. 550: &prettyprint($_,$content{$_}).'</td></tr>'; 551: delete $content{$_}; 552: } 553: # 554: $r->print(<<ENDHEAD); 555: <h2>$title</h2> 556: <p> 557: $disuri<br /> 558: $obsoletewarning 559: $versiondisplay 560: </p> 561: <table cellspacing=2 border=0> 562: $table 563: </table> 564: ENDHEAD 565: if ($ENV{'user.adv'}) { 566: &print_dynamic_metadata($r,$uri,\%content); 567: } 568: return; 569: } 570: 571: sub print_dynamic_metadata { 572: my ($r,$uri,$content) = @_; 573: # 574: my %content = %$content; 575: my %lt=&fieldnames(); 576: # 577: my $description = 'Dynamic Metadata (updated periodically)'; 578: $r->print('<h3>'.&mt($description).'</h3>'. 579: &mt('Processing')); 580: $r->rflush(); 581: my %items=&fieldnames(); 582: my %dynmeta=&dynamicmeta($uri); 583: &Apache::lonnet::logthis('dynamic metadata keys:'.$/. 584: join("\n",keys(%dynmeta))); 585: # 586: # General Access and Usage Statistics 587: if (exists($dynmeta{'count'}) || 588: exists($dynmeta{'sequsage'}) || 589: exists($dynmeta{'comefrom'}) || 590: exists($dynmeta{'goto'}) || 591: exists($dynmeta{'course'})) { 592: $r->print('<h4>'.&mt('Access and Usage Statistics').'</h4>'. 593: '<table cellspacing=2 border=0>'); 594: foreach ('count', 595: 'sequsage','sequsage_list', 596: 'comefrom','comefrom_list', 597: 'goto','goto_list', 598: 'course','course_list') { 599: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. 600: '<td bgcolor="#CCCCCC">'. 601: &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); 602: } 603: $r->print('</table>'); 604: } else { 605: $r->print('<h4>'.&mt('No Access or Usages Statistics are available for this resource.').'</h4>'); 606: } 607: # 608: # Assessment statistics 609: if ($uri=~/\.(problem|exam|quiz|assess|survey|form)$/) { 610: if (exists($dynmeta{'stdno'}) || 611: exists($dynmeta{'avetries'}) || 612: exists($dynmeta{'difficulty'}) || 613: exists($dynmeta{'disc'})) { 614: # This is an assessment, print assessment data 615: $r->print('<h4>'. 616: &mt('Overall Assessment Statistical Data'). 617: '</h4>'. 618: '<table cellspacing=2 border=0>'); 619: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{'stdno'}.'</td>'. 620: '<td bgcolor="#CCCCCC">'. 621: &prettyprint('stdno',$dynmeta{'stdno'}). 622: '</td>'."</tr>\n"); 623: foreach ('avetries','difficulty','disc') { 624: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. 625: '<td bgcolor="#CCCCCC">'. 626: &prettyprint($_,sprintf('%5.2f',$dynmeta{$_})). 627: '</td>'."</tr>\n"); 628: } 629: $r->print('</table>'); 630: } 631: if (exists($dynmeta{'stats'})) { 632: # 633: # New assessment statistics 634: $r->print('<h4>'. 635: &mt('Detailed Assessment Statistical Data'). 636: '</h4>'); 637: my $table = '<table cellspacing=2 border=0>'. 638: '<tr>'. 639: '<th>Course</th>'. 640: '<th>Section(s)</th>'. 641: '<th>Num Students</th>'. 642: '<th>Mean Tries</th>'. 643: '<th>Degree of Difficulty</th>'. 644: '<th>Degree of Discrimination</th>'. 645: '<th>Time of computation</th>'. 646: '</tr>'.$/; 647: foreach my $identifier (sort(keys(%{$dynmeta{'stats'}}))) { 648: my $data = $dynmeta{'stats'}->{$identifier}; 649: my $course = $data->{'course'}; 650: my %courseinfo = &Apache::lonnet::coursedescription($course); 651: if (! exists($courseinfo{'num'}) || $courseinfo{'num'} eq '') { 652: &Apache::lonnet::logthis('lookup for '.$course.' failed'); 653: next; 654: } 655: $table .= '<tr>'; 656: $table .= 657: '<td><nobr>'.$courseinfo{'description'}.'</nobr></td>'; 658: $table .= 659: '<td align="right">'.$data->{'sections'}.'</td>'; 660: $table .= 661: '<td align="right">'.$data->{'stdno'}.'</td>'; 662: foreach ('avetries','difficulty','disc') { 663: $table .= '<td align="right">'; 664: if (exists($data->{$_})) { 665: $table .= sprintf('%.2f',$data->{$_}).' '; 666: } else { 667: $table .= ''; 668: } 669: $table .= '</td>'; 670: } 671: $table .= 672: '<td><nobr>'. 673: &Apache::lonlocal::locallocaltime($data->{'timestamp'}). 674: '</nobr></td>'; 675: $table .= 676: '</tr>'.$/; 677: } 678: $table .= '</table>'.$/; 679: $r->print($table); 680: } else { 681: $r->print('No new dynamic data found.'); 682: } 683: } else { 684: $r->print('<h4>'. 685: &mt('No Assessment Statistical Data is available for this resource'). 686: '</h4>'); 687: } 688: 689: # 690: # 691: if (exists($dynmeta{'clear'}) || 692: exists($dynmeta{'depth'}) || 693: exists($dynmeta{'helpful'}) || 694: exists($dynmeta{'correct'}) || 695: exists($dynmeta{'technical'})){ 696: $r->print('<h4>'.&mt('Evaluation Data').'</h4>'. 697: '<table cellspacing=2 border=0>'); 698: foreach ('clear','depth','helpful','correct','technical') { 699: $r->print('<tr><td bgcolor="#AAAAAA">'.$lt{$_}.'</td>'. 700: '<td bgcolor="#CCCCCC">'. 701: &prettyprint($_,$dynmeta{$_})."</td></tr>\n"); 702: } 703: $r->print('</table>'); 704: } else { 705: $r->print('<h4>'.&mt('No Evaluation Data is available for this resource.').'</h4>'); 706: } 707: $uri=~/^\/res\/(\w+)\/(\w+)\//; 708: if ((($ENV{'user.domain'} eq $1) && ($ENV{'user.name'} eq $2)) 709: || ($ENV{'user.role.ca./'.$1.'/'.$2})) { 710: if (exists($dynmeta{'comments'})) { 711: $r->print('<h4>'.&mt('Evaluation Comments').' ('. 712: &mt('visible to author and co-authors only'). 713: ')</h4>'. 714: '<blockquote>'.$dynmeta{'comments'}.'</blockquote>'); 715: } else { 716: $r->print('<h4>'.&mt('There are no Evaluation Comments on this resource.').'</h4>'); 717: } 718: my $bombs = &Apache::lonmsg::retrieve_author_res_msg($uri); 719: if (defined($bombs) && $bombs ne '') { 720: $r->print('<a name="bombs" /><h4>'.&mt('Error Messages').' ('. 721: &mt('visible to author and co-authors only').')'. 722: '</h4>'.$bombs); 723: } else { 724: $r->print('<h4>'.&mt('There are currently no Error Messages for this resource.').'</h4>'); 725: } 726: } 727: # 728: # All other stuff 729: $r->print('<h3>'. 730: &mt('Additional Metadata (non-standard, parameters, exports)'). 731: '</h3>'); 732: foreach (sort(keys(%content))) { 733: my $name=$_; 734: if ($name!~/\.display$/) { 735: my $display=&Apache::lonnet::metadata($uri, 736: $name.'.display'); 737: if (! $display) { 738: $display=$name; 739: }; 740: my $otherinfo=''; 741: foreach ('name','part','type','default') { 742: if (defined(&Apache::lonnet::metadata($uri, 743: $name.'.'.$_))) { 744: $otherinfo.=' '.$_.'='. 745: &Apache::lonnet::metadata($uri, 746: $name.'.'.$_).'; '; 747: } 748: } 749: $r->print('<b>'.$display.':</b> '.$content{$name}); 750: if ($otherinfo) { 751: $r->print(' ('.$otherinfo.')'); 752: } 753: $r->print("<br />\n"); 754: } 755: } 756: return; 757: } 758: 759: ##################################################### 760: ##################################################### 761: ### ### 762: ### Editable metadata display ### 763: ### ### 764: ##################################################### 765: ##################################################### 766: sub present_editable_metadata { 767: my ($r,$uri) = @_; 768: # Construction Space Call 769: # Header 770: my $disuri=$uri; 771: my $fn=&Apache::lonnet::filelocation('',$uri); 772: $disuri=~s/^\/\~/\/priv\//; 773: $disuri=~s/\.meta$//; 774: my $target=$uri; 775: $target=~s/^\/\~/\/res\/$ENV{'request.role.domain'}\//; 776: $target=~s/\.meta$//; 777: my $bombs=&Apache::lonmsg::retrieve_author_res_msg($target); 778: if ($bombs) { 779: if ($ENV{'form.delmsg'}) { 780: if (&Apache::lonmsg::del_url_author_res_msg($target) eq 'ok') { 781: $bombs=&mt('Messages deleted.'); 782: } else { 783: $bombs=&mt('Error deleting messages'); 784: } 785: } 786: my $del=&mt('Delete Messages'); 787: $r->print(<<ENDBOMBS); 788: <h1>$disuri</h1> 789: <form method="post" name="defaultmeta"> 790: <input type="submit" name="delmsg" value="$del" /> 791: <br />$bombs 792: ENDBOMBS 793: } else { 794: my $displayfile='Catalog Information for '.$disuri; 795: if ($disuri=~/\/default$/) { 796: my $dir=$disuri; 797: $dir=~s/default$//; 798: $displayfile= 799: &mt('Default Cataloging Information for Directory').' '. 800: $dir; 801: } 802: my $bodytag= 803: &Apache::loncommon::bodytag('Edit Catalog Information'); 804: %Apache::lonpublisher::metadatafields=(); 805: %Apache::lonpublisher::metadatakeys=(); 806: &Apache::lonpublisher::metaeval(&Apache::lonnet::getfile($fn)); 807: $r->print(<<ENDEDIT); 808: <html><head><title>Edit Catalog Information</title></head> 809: $bodytag 810: <h1>$displayfile</h1> 811: <form method="post" name="defaultmeta"> 812: ENDEDIT 813: $r->print('<script language="JavaScript">'. 814: &Apache::loncommon::browser_and_searcher_javascript. 815: '</script>'); 816: my %lt=&fieldnames(); 817: foreach ('author','title','subject','keywords','abstract','notes', 818: 'copyright','customdistributionfile','language', 819: 'standards', 820: 'lowestgradelevel','highestgradelevel', 821: 'obsolete','obsoletereplacement') { 822: if (defined($ENV{'form.new_'.$_})) { 823: $Apache::lonpublisher::metadatafields{$_}= 824: $ENV{'form.new_'.$_}; 825: } 826: if (! $Apache::lonpublisher::metadatafields{'copyright'}) { 827: $Apache::lonpublisher::metadatafields{'copyright'}= 828: 'default'; 829: } 830: $r->print('<p>'.$lt{$_}.': '. 831: &prettyinput 832: ($_,$Apache::lonpublisher::metadatafields{$_}, 833: 'new_'.$_,'defaultmeta').'</p>'); 834: } 835: if ($ENV{'form.store'}) { 836: my $mfh; 837: if (! ($mfh=Apache::File->new('>'.$fn))) { 838: $r->print('<p><font color=red>'. 839: &mt('Could not write metadata').', '. 840: &mt('FAIL').'</font>'); 841: } else { 842: foreach (sort keys %Apache::lonpublisher::metadatafields) { 843: next if ($_ =~ /\./); 844: my $unikey=$_; 845: $unikey=~/^([A-Za-z]+)/; 846: my $tag=$1; 847: $tag=~tr/A-Z/a-z/; 848: print $mfh "\n\<$tag"; 849: foreach (split(/\,/, 850: $Apache::lonpublisher::metadatakeys{$unikey}) 851: ) { 852: my $value= 853: $Apache::lonpublisher::metadatafields{$unikey.'.'.$_}; 854: $value=~s/\"/\'\'/g; 855: print $mfh ' '.$_.'="'.$value.'"'; 856: } 857: print $mfh '>'. 858: &HTML::Entities::encode 859: ($Apache::lonpublisher::metadatafields{$unikey}, 860: '<>&"'). 861: '</'.$tag.'>'; 862: } 863: $r->print('<p>'.&mt('Wrote Metadata')); 864: } 865: } 866: $r->print('<br /><input type="submit" name="store" value="'. 867: &mt('Store Catalog Information').'">'); 868: } 869: $r->print('</form>'); 870: return; 871: } 872: 873: 1; 874: __END__