The Monash Unit Description Avatar

A.J.Hurst

Version

Table of Contents

1 Global Constants
2 Overview
2.1 The Manifest
2.2 User Issues
2.3 Pedagogic Issues
2.4 Legacy Issues
2.5 Directories and files
3 The MonAtar Main cgi script and Authentication
3.1 avatar initialization
3.2 avatar main control branches
3.2.1 re-entering the avatar
3.2.2 Logging in to the Avatar
3.2.3 Perform avatar authentication
3.2.4 Handle Illegal Parameters
3.3 avatar subroutines
3.4 getLatestApproved: subroutine to find most recent approved version
4 The Unit Selection Page
5 View a Unit Description
5.1 doView: view a unit description
5.2 getDocument: retrieve a unit description file
6 Edit a Unit Description
6.1 doEdit: Generate an Edit Markup of the Unit Description
6.2 doChange: Generate an Editable Text of the specified Field
6.3 doUpdate: Incorporate changes into the Unit Description
6.4 doSave: Incorporate changes into the Unit Description
6.5 doSubmit: Incorporate changes into the Unit Description
7 Compare Unit Decriptions
8 Show Unit Descriptions
9 doApprove: Approve a Unit Description
9.1 doApprove: What Approvals are Possible for this User?
9.2 doApprove: Select Unit(s) to Approve
9.3 doApprove: Give Approval to Unit
9.4 The Approval XML Translation Rules
10 Review a Unit Description
10.1 doReview: start a review template
10.2 doReviewSubmit: submit a unit review
11 XSL Stylesheets and Transformers
11.1 MakeReviewForm.xsl An XSL script to Generate a Review Form
11.2 mergexml.xsl Merge Updates with Description
11.3 MonAtar-appr.xsl Merge Approval Information with Description
11.4 V1toV2.xsl Converter Script
11.5 xml2html.xsl Convert XML Description to HTML
11.6 xml2txt.xsl Convert XML Description to Plain Text
12 TODO
13 DONE
14 Indices
14.1 Files
14.2 Chunks
14.3 Identifiers


<version 1> = 2.8.5
Chunk referenced in 15 18 20 22 30

1. Global Constants

<context variables 2> =
my $TESTING = 0;
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11

Define whether we are running in test mode

<context variables 3> =
my $WEBPAGE = "/u/homes1/ajh"; my $SERVER = "http://www.csse.monash.edu.au";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11

Define the location of the home web page, and the base server address

<context variables 4> =
#my $TestingVersion = "<B> Test Version! </B>"; my $TestingVersion = ""; my $SUBMISSIONS = "$WEBPAGE/units";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11

Set this to the name of the unit descriptions directory. There is one of these directories for each faculty using the avatar

<context variables 5> =
my $CGIPAGE = "$SERVER/cgi-bin/cgiwrap/ajh";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11

Define the base page for any cgi scripts.

<context variables 6> =
my $XMLPAGE = "$WEBPAGE/cgi-bin";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11

Define where all XML and XSL support scripts and files are stored.

<context variables 7> =
my $APPROVALS = "$XMLPAGE/MonAtar-IT.appr";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11
<context variables 8> =
my $TMP = "$WEBPAGE/tmp";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11
<context variables 9> =
my $GRAPHICS = "$SERVER/~ajh/graphics";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11
<context variables 10> =
# Set this to the name of the CGI on your web server $SCRIPT = "$CGIPAGE/MonAtar";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11
<context variables 11> =
# Define the xslt processor and options $XSLTOPTS = "XML_CATALOG_FILES=$XMLPAGE/catalog"; $XSLTPROC = "$XSLTOPTS /usr/local/bin/xsltproc"; $XP = "--param";
Chunk referenced in 13
Chunk defined in 2,3,4,5,6,7,8,9,10,11

2. Overview

This document describes Version 2 of the Infotech Subject Avatar, now know as MonAtar (MONash AvaTAR).

The purpose of the system is to maintain on-line documentation associated with course and unit offerings, originally within the Faculty of Information Technology at Monash, but recently extended to other faculties (Business and Economics, Medicine). The system is built using XML technology, while the actual Common Gateway Interface (CGI) components are written in Perl. This document details the main Perl component MonAtar, with links to the other components.

The XML components of the system include document type definitions (dtds), XML templates, and eXtensible Stylesheet Language Transformations (XSLT). The latter perform significant amounts of processing within the system, and are invoked from within the main Perl cgi script, the MonAtar program itself. These documents are defined separately, as defining XSLT documents within an XML document can get a bit bizarre!

2.1 The Manifest

Files used in this system are described below. In general, XSL files are maintained separately, because of the editing issues mentioned above.

a2x.w
The literate program (old style) to convert text to XML markup. This is actually uploaded to the cgi web site as the derived file a2x.pl.
basic2html.xsl
XSLT transformer for basic markup items
maketest.pl
A hastily cobbled together perl script to generate a test version for running on the local host.
monatar.xlp
The source form of this document. This is a literate program, translated to the output file MonAtar by a suite of XSLT scripts. MonAtar is a perl cgi script.
UnitDescriptionV2.dtd
The document type definition for the unit description itself.
UnitTemplateV2.xml
This defines the initial form of a freshly created unit decription.
V1toV2.xsl
XSLT script to convert unit description documents from Version 1 to Version 2 format
V2Guidelines.xml
An XML file that is converted to V2Guidelines.html and uploaded to the web site. This file contains helpful instructions on how to edit the various parts of the unit description file.
xml2html.xsl
XSLT script to convert unit description documents from Version 2 to HTML, presented as a viewable document or editable document, depending upon the value of the parameter ViewOrEdit (View or Edit respectively).
xml2txt.xsl
XSLT script to translate XML markup to formatted plain text, for editing by novice editors.
xmlextract.xsl
xslt.dtd
A link to the document type definition for all the XSLT scripts that form part of this package.
MakeReviewForm.xsl
mergexml.xsl
MonAtar-appr.xsl
Merge approval information with an XML unit description.
MonAtar-version.xsl
Review2html.xsl
ReviewV1.dtd
sanitiseV2.xsl
stylesheet.dtd

2.2 User Issues

  1. Have separate edit buttons for each section.
  2. Incorporate a2x.pl into monatar litprog
  3. Design Version Control interface
  4. Create a lock file on the no version comment page. Delete this lock file when edits are saved or submitted. Good question is what happens if the user doesn't save or submit. Should the lock be removed say after 24 hours? (The edits are saved, but not in the archive.)
  5. add StartPoint mechanism to always display description at edit point.
  6. Generate the prohibitions matrix; change wording of submit statement; include subject description in email; define interest groups

2.3 Pedagogic Issues

Ainslie Ellis writes:

I have looked at the new format. It looks fine.

Is it possible to provide a sample outline that has a brief comment under each heading (or a link to an html page if a longer comment is needed) that indicates what should be thought of at each stage. I already have a lot of this information. and am happy to write up a checklist for each item if you think this would be useful.

Also in the objectives part, I would prefer this to commence with At the completion of a unit a student should be able to:

followed by perhaps a comment like

with a link to an html document (see attachment for this email) for more detail.

2.4 Legacy Issues

  1. Write a conversion xsl script from old format to new. Complete, called V1toV2.xsl
  2. Create copy of units directory and archive wherein all descriptions can be converted. Keep this up-to-date until change-over. Done.
  3. The new cgi script will be cookie based, to avoid reauthentication. Done.
  4. The new cgi script will be monolithic, to eliminate a majority security hole in the previous version. Done.

2.5 Directories and files

There are various locations where the files are to be stored, defined symbolically within this script as:

XMLPAGE
The directory containing all xml and xsl files required for MonAtar use. On shelob this is $WEBPAGE/cgi-bin, while on ararat it is $WEBPAGE/xml
basic2html.xsl
XSL script included by xml2html.xsl
canonical.pl
perl script to convert an XML file into canonical form. I'm not sure this is required any longer, since sanitise.xsl has been written?

3. The MonAtar Main cgi script and Authentication

"MonAtar" 12 =
#!/usr/bin/perl <initialization 13,14> <subroutines 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106> <get parameters 15,16,17> if ($auth->param('UnitCode') && @params==1) { &doView($auth->param('UnitCode')); } elsif ($auth->param('compare')) { &doCompare; } elsif ($auth->param('authaction') =~ /Authenticate/) { <perform avatar authentication 20> } elsif ($auth->param('authenticate') || (!$cookie)) { <login to avatar 19> } elsif (!$auth->param && $cookie) { <re-enter avatar 18> } elsif ($auth->param('reenter')) { <re-enter avatar 18> } elsif ($auth->param('view')) { &doView($auth->param('UnitCode')); } elsif ($auth->param('create')) { &doEdit(1); } elsif ($auth->param('edit')) { &doEdit(0); } elsif ($auth->param('change')) { &doChange(); } elsif ($auth->param('update')) { &doUpdate(); } elsif ($auth->param('Save')) { &doSave(); } elsif ($auth->param('Submit')) { &doSubmit(); } elsif ($auth->param('compare')) { &doCompare; } elsif ($auth->param('show')) { &doShow; } elsif ($auth->param('approve')) { &doApprove; } elsif ($auth->param('review')) { &doReview; } elsif ($auth->param('reviewSubmit')) { &doReviewSubmit; } else { <illegal parameters 21> } &printBottom; close DEBUG; close LOG; exit;

The order of tests in here is very important, and controls the security of the system. Do not reorder these tests without obeying the following rules! The key issue is that the avatar can be used without authentication for viewing or comparing unit descriptions, but for all other purposes, the user must be authenticated. A cookie is issued once the user has authenticated, and this avoids having to re-authenticate on repeat visits to the home avatar page.

Two pages generated by the avatar have special significance. They are the login page and authenticating page. The login page requires the user to enter details of their AuthCate userid and password, while the authenticating page performs the authentication of these details by looking up the Monash Directory Pages, and returning information about what is found. This page also sets a cookie, to avoid the user having to re-authenticate.

The first test therefore checks to see if the desired display is to view a unit description. This is prompted by a single parameter UnitCode=unitcode. Any additional parameters and this non-authenticated display will fall through to require authentication.

The next page that can be viewed without authentication is the authenticating page itself. This is the second test, and is driven by the parameter authaction=Authenticate, generated by the login page. It must appear before the login page itself, since no cookie has yet been issued, and we want all attempts to visit pages without cookies to trap to the login page. If authentication is successful, we move to the Unit Selection Page.

If the avatar is invoked with an explicit request to authenticate, or no cookie has yet been issued, we generate the login page.

If the avatar is invoked with no explicit parameters, but a cookie has been issued, then this is a revisit to the avatar, and we generate the Welcome (Back) Page.

Subsequent tests branch into other sections of the avatar for handling.

The final step, if no tests succeed, is to issue a warning about illegal parameters to the avatar.

3.1 avatar initialization

<initialization 13> =
my @additions=("/local/lib/perl5/site_perl/5.6.0"); push(@INC,@additions); #print join(',',@INC),"\n"; require Net::LDAP; use Carp; use CGI qw(:standard :html3); $auth = new CGI; <context variables 2,3,4,5,6,7,8,9,10,11> my $ldap_server = 'directory.monash.edu'; my $ldap_port = 389; my $ldap_basedn = 'o=Monash University, c=AU'; my $dn; # set to 1 for various debugging information my $debug = 1; # cleared once HTML headers have been printed my $needHeaders = 1; # This is the displayed title... $TITLE = "InfoTech Unit Avatar: Authentication";
Chunk referenced in 12
Chunk defined in 13,14
<initialization 14> =
$TimeStamp = `/bin/date "+%Y%m%d:%H%M%S"`; chop $TimeStamp; $timestamp = $TimeStamp; $timestamp=~s/://;
Chunk referenced in 12
Chunk defined in 13,14

This is my timestamp. I use a contraction of the ISO standard, where the date and time are in most significant order, with a colon separating the day of the month from the hour of the day. The year is 4 digits, all others are 2 digits with a leading zero if required.

<get parameters 15> =
@params = $auth->param; unless(open LOG,">>$SUBMISSIONS/log") { printError('NoLog',"Cannot open log file $SUBMISSIONS/log"); exit; } $School = "(No School)"; $Faculty = "(No Faculty)"; $Staff = "(No Staff Info)"; $rawCookie=$ENV{'HTTP_COOKIE'}; @rawCookies = split(/;/,$rawCookie); foreach(@rawCookies){ m/([^=]*)=(.*)$/; my ($key,$val) = ($1,$2); print LOG $TimeStamp,' <version 1> (key,val)=',"($key,$val)\n"; $cookies{$key} = $val; } if ($cookies{'AVATAR'}) { $cid = $cookies{'AVATAR'}; $cid=~s/\+/ /g; $cookie="AVATAR=".$cid; $cid =~ s/--/=/g; grabPersonData($cid); } my $logindata = 0; foreach $name (@params) { if ($name eq 'myuid') {$logindata++;} if ($name eq 'mypass') {$logindata++;} my $value = $auth->param($name); $value =~ s/</&lt;/g; #if ($name ne 'mypass') { # print LOG $name,"=",$value," "; #} } $UnitCode = $auth->param('UnitCode'); $UnitCode =~ tr/a-z/A-Z/;
Chunk referenced in 12
Chunk defined in 15,16,17
<get parameters 16> =
$EditExpert = $auth->param('EditExpert');
Chunk referenced in 12
Chunk defined in 15,16,17

Does this editor want to edit the XML markup directly, or does she prefer to use plain text? Set to 1 (in doEdit) if the former.

<get parameters 17> =
# This is the debugging file $debugfile = "dummy.dbg"; if ($UnitCode) {$debugfile = "$UnitCode.dbg"}; open DEBUG,">$TMP/$debugfile"; print DEBUG "rawCookie=$rawCookie\n"; print DEBUG "Cookie=$cookie\n"; print DEBUG "cid=$cid\n"; print DEBUG "School=$School\n"; print DEBUG "Faculty=$Faculty\n";
Chunk referenced in 12
Chunk defined in 15,16,17

3.2 avatar main control branches

3.2.1 re-entering the avatar

<re-enter avatar 18> =
$TITLE="Infotech Unit Avatar: Home Page (Version <version 1>)"; &printHtmlHeaders; $cid=~s/--/=/g; &grabPersonData($cid); print "<P></P><h1 align=\"center\" style=\"color:#339933;". "background-color:#99ffcc\">Welcome back, $given!</h1>"; &doUnitSelection;
Chunk referenced in 12

We have cookie data, so the user has already authenticated and re-entered the avatar. Convert the flattened equals signs back to equals, and extract the given name as the first word in the common name or cn field. Print the Welcome Back heading, and then generate the Unit Selection Page.

3.2.2 Logging in to the Avatar

<login to avatar 19> =
&printHtmlHeaders; print start_form(-action=>"$SCRIPT"), h2("Please supply your AuthCate username and password"), "Username: ",textfield('myuid'),p, "Password: ",password_field('mypass'),p, submit('authaction','Authenticate me!'), hidden('UnitCode',$auth->param('UnitCode')), end_form; print "<em>It may take a minute or so to process</em>"; print " - <b>PLEASE MAKE SURE YOU HAVE COOKIES ENABLED</b>"; print "<p>(If you have already authenticated, click your browser "; print "RELOAD/REFRESH button to go to the Unit Selection Page)</p>";
Chunk referenced in 12

No parameters supplied to avatar, or authentication forced, so print the login page.

3.2.3 Perform avatar authentication

<perform avatar authentication 20> =
&doAuthenticate; if ($dn) { unless(open LOG,">>$SUBMISSIONS/log") { printError('NoLog',"Cannot open log file $SUBMISSIONS/log"); exit; } print LOG $TimeStamp,' <version 1> ',$dn,"\n"; &grabPersonData($dn); my $cookie = $dn; $cookie=~s/=/--/g; $cookie=~s/ /\+/g; print "Set-Cookie: AVATAR=$cookie\n"; print LOG $TimeStamp,' <version 1> ',"Set-Cookie: AVATAR=$cookie\n"; close LOG; $TITLE="Welcome to the Infotech Unit Avatar Home Page (V<version 1>)"; &printHtmlHeaders; # could put first time information in here? if ($UnitCode) { &doEdit(0); } else { &doUnitSelection; } }
Chunk referenced in 12

Handle the authentication process. I am very grateful to Nate Bailey for the original code upon which this subroutine is based, but as it has been significantly altered, all responsibility rests with me!

If authentication succeeds, we get back a domain name dn, which is analyzed to extract the user's given name, and then encoded to avoid problems with internal equal signs, before being returned to the client as a cookie for subsequent authentication purposes.

Finally, we generate the Unit Selection Page.

3.2.4 Handle Illegal Parameters

<illegal parameters 21> =
$TITLE="Infotech Unit Avatar: Error Page"; &printHtmlHeaders; $_=$auth->p."These are the parameters and values:"; $_=$_."<P STYLE=\"margin-left:20pt\">"; foreach $name (@params) { $_=$_.$name.'='.$auth->param($name).'<BR>'; } $_=$_.'</P>'; &printError("Illegal Parameters",$_);
Chunk referenced in 12

Note that we should not normally enter this code. If we do, it is because the avatar has been called with unknown parameters, so we print that fact, together with a synopsis of the parameters in error.

3.3 avatar subroutines

<subroutines 22> =
sub doLogOperation { my($location)=(shift); print LOG $TimeStamp,' <version 1> ',"$Editor calls $location\n"; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 23> =
sub doAuthenticate { my($uid,$passwd) = (param('myuid'),param('mypass')); if (!($uid.$passwd)) { &printHtmlHeaders(); &printError('Insufficient information', "You left one or more of the fields blank -- ". "you must fill out all the fields."); } elsif ($uid eq 'sjoy' && $passwd eq '*****') { $dn = "cn=Sally Joy2, ou=Department of Racketeering, ". "ou=Faculty of Business and Economics, ou=Staff, ". "o=Monash University, c=au"; } elsif ($uid eq 'ajh' && $passwd eq '*****') { $dn = "cn=John Hurst2, ou=School of Microsoftware Imagineering, ". "ou=Faculty of Information Technology, ou=Staff, ". "o=Monash University, c=au"; } elsif ($uid eq 'luff' && $passwd eq '*****') { $dn = "cn=Tony Luff2, ou=Department of Immaculate Conception, ". "ou=Faculty of Medicine, ou=Staff, o=Monash University, c=au"; } elsif ($uid eq 'dnh' && $passwd eq '*****') { $dn = "cn=David Hurst, ou=Department of Students, ". "ou=Faculty of Information Technology, ou=Student, o=Monash University, c=au"; } else { $dn = doLDAP(undef,$uid,$passwd); } }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doAuthenticate collects username and password parameters from the call, checks that they are non-empty, and calls the LDAP authentication routine.

<subroutines 24> =
sub doLDAP { my ($dn,$uid,$pass) = @_; my $mesg; if ($pass eq "") { $pass = $uid; $uid = $dn; $dn = undef; } my $ld = Net::LDAP->new($ldap_server, port => $ldap_port); unless ($ld) { carp "ldap_open to $ldap_server failed!"; return undef; } if ($pass eq '') { carp "ldap bind for $uid failed: no password!"; return undef; } unless ($dn) { unless (($mesg=$ld->bind) && $mesg->code==LDAP_SUCCESS) { carp "ldap anon bind to $ldap_server failed"; return undef; } my $filter = "(uid=$uid)"; unless ($mesg = $ld->search(base=>$ldap_basedn, filter=>$filter)) { carp "ldap search for $uid failed"; return undef; } my @entries = $mesg->all_entries; unless (scalar(@entries) == 1) { &printError("not exactly one ldap entry for $uid"); return undef; } $dn = $entries[0]->dn(); } ###################################################### ### WARNING!!! If we don't have '$pass', this will ### ### successfully make an _anonymous_ bind. ### ###################################################### unless (($mesg=$ld->bind($dn, password=>$pass)) && $mesg->code==LDAP_SUCCESS) { $ld->unbind; printError("LDAP bind failed", "I could not connect to the LDAP server. ". "It returned an error code of ".$mesg->code. ", which means: ".$mesg->error.""); return undef; } unless ($mesg = $ld->search(base=>$dn, filter=>'(objectclass=*)')) { $ld->unbind; carp "Search with $uid 's basedn ($dn) failed"; return undef; } return $dn; } sub doProcessDescription { print start_html(), h1('Calling propose('.$auth->param('propose').', '.$auth->param('UnitCode').')'), end_form; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 25> =
sub printBottom { return; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 26> =
sub printHtmlHeaders { #if (!$needheaders) {return;} print header('text/html'); my $ADT = "$SERVER/~ajh/adt"; print <<"END"; <html> <head> <meta content="text/html; charset=ASCII" http-equiv="Content-Type"> <title> $TITLE </title> <link rel="stylesheet" href="$SERVER/~ajh/styles/monash.css" type="text/css"> </head> <body> <div class="spacer"></div> <div id="global-header"> <div id="global-images"> <table width="100%" bgcolor="white"> <tr width="100%"> <td align="left"> <table> <tr> <td align="left"> <a href="http://www.monash.edu.au"> <span style="font-family:sans-serif; font-size:+160%;font-weight:bold; background-color:#ffffff;color:black"> MONASH UNIVERSITY </span> </a> </td> </tr> <tr> <td align="left"> <a href="http://www.infotech.monash.edu.au" COLOR="black"> <span style="font-family:sans-serif; font-size:+140%;font-weight:bold; background-color:#ffffff; color:black"> INFORMATION TECHNOLOGY</span> </a> </td> </tr> <tr> <td align="left"> <a href="http://www.csse.monash.edu.au" COLOR="black"> <span style="font-family:sans-serif; font-size:+120%;font-weight:bold; background-color:#ffffff;color:black"> Computer Science and Software Engineering</span> </a> </td> </tr> </table> </td> <td align="right"> <img id="banner-image" SRC="$SERVER/~ajh/images/banner/4472=R761-11.jpg" height="79" alt="steam loco"> </td> </tr> </table> </div> <div class="spacer"></div> <table id="global-nav" summary="Layout for site-wide navigation"><tr> <td align="left"><span style="font-size:+140%"> M O N A T A R $TestingVersion </span> </td><td> $TITLE </td> </tr></table> <table id="global-utils" summary="Layout for utility navigation"> <tr><td align="left"> <a HREF="$ADT/../index.html" accesskey="4">John Hurst</a> | <a HREF="$ADT/index.html" accesskey="4">InfoTech AD(T)</a> | <a HREF="$ADT/quality/index.html">Quality</a> | <a HREF="$ADT/quality/V2Guidelines.html">Completing an Avatar Entry</a> | </td> </tr> </table> </div> <div class="spacer"></div> <div style="background-color:#99ffcc"> END # If the person has authenticated, let them know we know who they are. if (defined $dn) { @splitdn = split(/,/,$dn); $name = $splitdn[0]; $name =~ s/.*=//; } $needHeaders = 0; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 27> =
sub printLDAPError { if ($needHeaders) {&printHtmlHeaders();} $lderr = ldap_get_lderrno($ld,$blah1,$blah2); $errmsg = ldap_err2string($lderr); print p,"\nError: $errmsg\n",p,hr; &printBottom; return; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 28> =
sub printError { my ($type, $info) = @_; $TITLE="InfoTech Unit Avatar: Sorry!"; if ($needHeaders) {&printHtmlHeaders();} print h2("$type"); print "<FONT SIZE=\"+1\">$info<BR>"; print "<P>Click this link to return to the Welcome page: "; print "<A HREF=\"$SCRIPT\">Infotech Unit Avatar</A></P></FONT>"; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 29> =
sub printBadAuth { if ($needHeaders) {&printHtmlHeaders();} print p,"The login/password you have supplied is incorrect.",p; print "Return to <a href=\"$SCRIPT\">authentication screen</a>."; &printBottom; exit; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<subroutines 30> =
sub grabPersonData { my $dn = shift; #print LOG $TimeStamp,' <version 1> ',"grabPersonData($dn)\n"; $dn =~ /cn *= *([^,]*),/; $Editor = $1; $Editor =~ /([\w]*) ([\w]*)/; $EscEditor = $Editor; $EscEditor =~ s/'/&quote;/g; ($given,$surname) = ($1,$2); if ($dn =~ /ou *= *([\w\s]*School[\w\s]*)/) {$School = $1}; if ($dn =~ /ou *= *([\w\s]*Department[\w\s]*)/) {$School = $1}; if ($dn =~ /ou *= *([\w\s]*Faculty[\w\s]*)/) {$Faculty = $1}; if ($dn =~ /ou *= *((Staff|Student)[\w\s]*)/) {$Staff = $1}; #if ($Staff=~/^Student$/) {$School=""; $Faculty="";} if ($Faculty=~/Information/) { <grabPersonData: set submission details for InfoTech 31> } elsif ($Faculty=~/Business/) { $SUBMISSIONS="$WEBPAGE/units-buseco"; $APPROVALS = "$XMLPAGE/MonAtar-Bus.appr"; $FECEADR="John.Hurst\@infotech.monash.edu.au"; $FECEOFF="John.Hurst\@infotech.monash.edu.au"; } elsif ($Faculty=~/Medicine/) { $SUBMISSIONS="$WEBPAGE/units-med"; $APPROVALS = "$XMLPAGE/MonAtar-Med.appr"; $FECEADR="John.Hurst\@infotech.monash.edu.au"; $FECEOFF="John.Hurst\@infotech.monash.edu.au"; } else { <grabPersonData: set submission details for no Faculty 32> } print LOG $TimeStamp,' <version 1> ', "editor=$Editor,expert=$EditExpert,unitcode=$UnitCode,". "given=$given,surname=$surname,school=$School,faculty=$Faculty,". "staff=$Staff,unitsfile=$SUBMISSIONS\n"; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

(Bug 20031009:115255) When extraction the school, department or faculty information, we must allow for leading words before the school/department/faculty key word, so that places like Peninsula School of Network Computing are not discriminated against.

<grabPersonData: set submission details for InfoTech 31> =
$SUBMISSIONS="$WEBPAGE/units"; $APPROVALS = "$XMLPAGE/MonAtar-IT.appr"; $FECEADR="fecvote\@infotech.monash.edu.au"; $FECEOFF="Ralph.Gillon\@infotech.monash.edu.au". ",Geraldine.DCosta\@infotech.monash.edu.au";
Chunk referenced in 30
<grabPersonData: set submission details for no Faculty 32> =
print LOG "No units database for $Faculty\n"; $SUBMISSIONS="$WEBPAGE/units"; $APPROVALS = "$XMLPAGE/MonAtar-IT.appr"; $FECEADR="fecvote\@infotech.monash.edu.au"; $FECEOFF="Ralph.Gillon\@infotech.monash.edu.au";
Chunk referenced in 30

If the faculty is not one of those directly handled, print log message and use InfoTech as default.

3.4 getLatestApproved: subroutine to find most recent approved version

<subroutines 33> =
sub getLatestApproved { my $unitcode = shift; my $dir="$SUBMISSIONS/archive"; my @units; opendir(ARCHIVE,$dir); my @archfiles=grep(!/^\.\.?$/,readdir(ARCHIVE)); foreach $f (@archfiles) { if ($f =~ /^$UnitCode-[0-9]+-A/) { unshift(@units,$f); } } closedir ARCHIVE; @units=sort(@units); if ($TESTING) {print join(', ',@units);} $ApprovedVersion=""; if (@units) {$ApprovedVersion=$units[$#ApprovedVersion];} if ($TESTING) {print "[",$ApprovedVersion,"]";} }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

4. The Unit Selection Page

<subroutines 34> =
sub doUnitSelection { print $auth->start_html(), $auth->start_form(-method=>"post", -action=>"$SCRIPT", -target=>"_blank"); if (($Staff !~ /^Staff|Student$/)) { print "Sorry, but you are not authorised to use this form, $given"; } else { <selection page text 35> } print $auth->endform,$auth->hr; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

Collect the domain name from the parameter, and analyse it for school and faculty data. If the person identified is not staff, then they cannot use the avatar.

<selection page text 35> =
my %hints = ( 'review'=>"May be completed by staff or students. ". "(See the <A HREF=\"$SERVER/~ajh/". "adt/quality/index.html#Using%20the%20Review". "%20System\">ADT Quality Page</A> for help)", 'compare'=>'Compare two unit descriptions (under development)', 'show'=>"Show summary of unit descriptions matching the above ". "prefix. <B>This can also be used to compare changes since ". "the last approval of a unit.</B>", 'showall'=>"Show a list of <B>all</B> unit descriptions ". "matching the above prefix", 'showapproval'=>"Show the approval work flow of unit ". "descriptions matching the above prefix", 'view'=>"Generate a read-only view of the unit description" ); if ($Staff=~/^Staff$/) { print $auth->p, textfield(-name=>'UnitCode',-default=>$UnitCode,-size=>10), " Enter unit code here, please $given", $auth->hidden('Editor',$Editor); print $auth->p, $auth->table({-cellpadding=>0,-cellspacing=>0}, Tr(td({-'colspan'=>"2"},"<B>USER functions</B>"),td()), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'review', -value=>'REVIEW Unit')), td($hints{'review'}."\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'view', -value=>'VIEW Description')), td($hints{'view'}."\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}), td(textfield(-name=>'DisplayDate',-size=>10), "Enter date YYYYMMDDHHMMSS (or prefix) to restrict view\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'edit', -value=>'EDIT Existing Description')), td("Generate an editable view of the current unit description")), Tr(td({-'bgcolor'=>"#99ffcc"}, $auth->submit(-name=>'create', -value=>'CREATE New Description')), td("Create a new unit description")), Tr(td(),td()), Tr(td({-'colspan'=>"2"},"<B>MANAGEMENT functions</B>"),td()), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'compare', -value=>'COMPARE Descriptions')), td($hints{'compare'}."\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'show', -value=>'SHOW Descriptions')), td($hints{'show'}."\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'show', -value=>'SHOW ALL Descriptions')), td($hints{'showall'}."\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'show', -value=>'SHOW APPROVAL Profile')), td($hints{'showapproval'}."\n")), Tr(td({-'bgcolor'=>"#99ffcc",-align=>"center"}, $auth->submit(-name=>'approve', -value=>'APPROVE Description')), td("(Only available for authorised users)"."\n")), ); } elsif ($Staff=~/^Student$/) { print "<P>What unit do you wish to view or review, $given? ", textfield('UnitCode',$UnitCode), "</P>", $auth->hidden('Editor',$Editor); print $auth->p, $auth->table( Tr(td("<B>USER functions</B>"),td()), Tr(td($auth->submit('review','REVIEW Unit')),td($hints{'review'})), Tr(td($auth->submit('view','VIEW Description')), td("View the unit description")), ); } print $auth->p, "Note: If you enter a partial unit code (such as BUS), ", "the SHOW (ALL) DESCRIPTIONS button will limit its search to just ", "those units starting with that prefix. The prefix can be ", "as long or as short as you desire. An empty unit code ", "will show all units.</P>"; print $auth->p, "<B>NB: If when using the back button you do not see the page ", "you expect, click reload/refresh to refresh the actual contents</B>"; print $auth->p, "<B>Version 2.7.0 has a new work-flow for approvals.</B>", "<BR/>\n", "<B>Version 2.6.15 adds date-restricted sub-view.</B>", "<BR/>\n", "<B>Version 2.6.12 adds change dates to fields.</B>", "<BR/>\n", "<B>Version 2.6.5 restructures the submit and approve processes.</B>";
Chunk referenced in 34

Generate the main content of the Unit Selection Page. The purpose of this page is to allow the user to choose between a range of options for the unit description document. These options are specified by buttons on the page, and cause reinvocation of the avatar with appropriate parameters.

5. View a Unit Description

5.1 doView: view a unit description

doView is responsible for collecting the nominated unit description document, and formatting it using xsltproc under the stylesheet xml2html.xsl, the standard html view of a unit description for version 2 descriptions. (If a version 1 description is encountered, use FECSA-html.xsl instead.) Since this page is intended for printing, it uses a standard text/html header, and does not call printHtmlHeaders!

Parms: /---------\ see list ---------->| MonAtar | below \---------/ | V getDocument: result in $TMP/$UnitCode.xml +--------------------+ | $TMP/$UnitCode.xml | +--------------------+ | V +--------------+ /----------\ | xml2html.xsl |---->| xsltproc | (If V1, use FECSA-html.xsl instead) +--------------+ \----------/ | V / \ /OK?\ no \ /------> Error, Translation \ / | yes V display this file delete TMP files

The following parameters are passed to MonAtar.

UnitCode
The unit code
Editor
If present, an authenticated user
EditExpert
If present, a boolean indicating the expert status of the user
<subroutines 36> =
sub doView { doLogOperation("doView"); $UnitCode=~tr/a-z/A-Z/; &getDocument(1,0); $DisplayDate = $auth->param('DisplayDate'); if ($DisplayDate) { $DisplayDate .= "00000000000000"; $DisplayDate = substr($DisplayDate,0,14); } print header('text/html'); # plain header! <doView: set xsltproc parameters 37> $cmd="$XSLTPROC $parms -o $dest $xsl $src 2>$erf"; `$cmd`; $err = ""; open ERR,"<$erf"; while (<ERR>) {$err.=$_}; close ERR; if ($err) { <doView: handle errors 39> } else { # use the resultant HTML file as returned page open NEW,"<$dest"; while (<NEW>) {print;} close NEW; } unlink $src,$dest,$erf; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

Force the unit code to be upper case. Get the document. Set xslt processing parameters, and process the description to html. Gather the error output, and if that is non-empty, display in an error page, otherwise the output of the translation is used. Discard all temporary files.

<doView: set xsltproc parameters 37> =
$src="$TMP/$UnitCode.xml"; <doView: set stylesheet according to version 38> $dest="$TMP/$UnitCode$destmod.html"; $erf="$TMP/$UnitCode-edit.stderr"; $datetime=$TimeStamp; #`/bin/date "+%d %b %Y %H:%M"`; chop($datetime); $datetime="$XP DateAndTime \"'$datetime'\""; if (defined($Editor)) {$editor="$XP Editor \"'$EscEditor'\""} else {$editor=""}; $unit="$XP UnitCode \"'$UnitCode'\""; $expert="$XP EditExpert \"\'$EditExpert\'\""; $parms="$datetime $editor $unit $expert"; if ($DisplayDate) { $parms .= " $XP DisplayDate \"\'$DisplayDate\'\""; }
Chunk referenced in 36

xsltproc requires 2 parameters, the stylesheet $xsl defining the translations, and the source xml document $src. In addition, we specify the destination html document $dest, an error file for stderr $erf, a date and time parameter $datetime, an editor parameter $Editor, and a unit code parameter $UnitCode. The latter three are used within the xsl stylesheet.

<doView: set stylesheet according to version 38> =
open XML,"<$src" or print "Cannot open $src!<BR>"; $xsl = ""; while (<XML>) { if (/<UnitDescription>/) { $xsl = "$XMLPAGE/FECSA-html.xsl"; last; } elsif (/UnitDescriptionV2/) { $xsl = "xml2html.xsl"; last; } } close XML; if (!$xsl) { printError("Document Type","unable to determine document type for $UnitCode"); return; }
Chunk referenced in 37

This avatar may be called upon to handle version 1 documents. Read the first few lines of the document to see what version it is, and set the xsl stylesheet appropriately.

<doView: handle errors 39> =
$err=~s/&/&amp;/g; $err=~s/</&lt;/g; print "<P>doView: There was an error in translating the source file \n"; print "<TT>$TMP/$UnitCode.xml</TT>.\n"; print "Here is the output that was generated.\n"; print "If you cannot interpret this, please contact John Hurst.<P>\n"; print "<P><B>Command:</B></P>\n"; print "<PRE>\n"; print "$EditOrView\n"; print "$cmd\n"; print "<PRE>\n"; print "<P><B>Output:</B></P>\n"; print "</PRE>\n"; print "$err\n"; print "</PRE>\n"; print "\n";
Chunk referenced in 36 106

There were errors. Before we display the error file, we munge out all ampersands into ampersand entities, and all less than signs into less than entities.

5.2 getDocument: retrieve a unit description file

<subroutines 40> =
sub getDocument { my $readonly = shift; my $createOK = shift; $getDoc="<P>Getting Document $UnitCode\n"; my $erf="$TMP/$UnitCode-new.stderr"; if (-f "$SUBMISSIONS/$UnitCode.xml") { # previous submission available, copy it into $TMP $source="$SUBMISSIONS/$UnitCode.xml"; $getDoc .= "<P>previous submission available, copy it into $TMP\n"; } elsif ($readonly && -f "$SUBMISSIONS/archive/$UnitCode") { $source="$SUBMISSIONS/archive/$UnitCode"; $getDoc .= "<P>using $UnitCode, copy it into $TMP\n"; $UnitCode =~ s/-[0-9]+-.$//; } elsif ($createOK) { my $cmd; my $src="$XMLPAGE/UnitTemplateV2.xml"; my $xsl="$XMLPAGE/mergexml.xsl"; my $tmp="$TMP/$UnitCode-new1.xml"; my $p1 = "$XP FieldA \"'UnitCode'\""; my $p2 = "$XP NewText \"'$UnitCode'\""; my $parms="$p1 $p2"; $getDoc .= "New $UnitCode document, grabbing $src\n"; $cmd="$XSLTPROC $parms -o $tmp $xsl $src 2>$erf"; $getDoc.="New $UnitCode, merging Unit Code ($cmd)\n"; `$cmd`; $source="$TMP/$UnitCode-new.xml"; $p1 = "$XP FieldA \"'FacultyInformation'\""; $p2 = "$XP FieldB \"'FIProposer'\""; my $p3 = "$XP NewText \"'$EscEditor'\""; $parms="$p1 $p2 $p3"; $cmd="$XSLTPROC $parms -o $source $xsl $tmp 2>>$erf"; $getDoc .= "New $UnitCode, setting Proposer ($cmd)\n"; `$cmd`; # must do this to make persistent copy `cp $source "$SUBMISSIONS/$UnitCode.xml"`; unlink $tmp; } else { printError('Missing Document', "I couldn't find the Unit Description for $UnitCode. ". "Do you need to CREATE a new one?"); exit; } <getDocument: and sanitise it 41> unlink $erf; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

The getDocument subroutine retrieves the XML unit description document for the unit $UnitCode. There are two parameters to the routine:

readonly
A boolean which hen true indicates that the document is to be accessed read only.
createOK
A boolean which when true indicates that the document can be created if it does not already exist.

If the document is to be created, the template UnitTemplateV2.xml is retrieved, and the new unit code merged into it using the XSLT transformation mergexml.xsl.

<getDocument: and sanitise it 41> =
$tmp="$TMP/$UnitCode.xml"; $cmd="$XSLTPROC -o $tmp $XMLPAGE/sanitiseV2.xsl $source 2>$erf"; $getDoc .= "Sanitise $UnitCode ($cmd)"; `$cmd`; if (! -z $erf) { open ERRS,$erf; while (<ERRS>) {$getDoc .= $_;} close ERRS; } $getDoc .= "<P>closed $tmp\n"; print DEBUG $getDoc,"\n";
Chunk referenced in 40

We used to just copy the document here, with the only alteration being to force the DOCTYPE line. However, a transformer sanitiseV2.xsl is now used to render the current document into a canonical form.

6. Edit a Unit Description

There are three stages to editing the unit description, each of which is handled by a separate invocation of the avatar.

Before anything else, ensure that we have a Version Comment.

Next, doEdit generates a rendered version of the unit description, marked up with buttons to change the various editable fields of the document. Each of these buttons forces a call on the next stage of the avatar, with parameters indicating the unit, the field, and the user.

The next stage doChange renders the selected field in an editable text window. The XML of the selected field is extracted from the master document, and converted to ascii text according to the markup. This is done so that naive users are not required to edit XML text directly.

The final stage doUpdate converts the ascii text back into XML, and replaces the original field of the master document with this new text.

6.1 doEdit: Generate an Edit Markup of the Unit Description

<subroutines 42> =
sub doEdit { doLogOperation("doEdit"); my $createOK = shift; my $StartPoint = $auth->param('StartPoint'); my $VersionComment = $auth->param('VersionComment'); $UnitCode=~tr/a-z/A-Z/; if ($UnitCode=~/^$/) { printError('No Unit Code', "You need to enter a unit code in the form ABC1234. ". "Please return to the Welcome page and try again"); exit; } if ($createOK & !$VersionComment) { $VersionComment="Initial Draft"; } getDocument(0,$createOK); <doEdit: parameter debugging 43> $TITLE="InfoTech Unit Avatar: Edit $UnitCode"; &printHtmlHeaders; if ($auth->param('edit')=~/Expert/) {$EditExpert=1;} if ($auth->param('edit')=~/Novice/) {$EditExpert=0;} my $myself=$auth->self_url; if ($StartPoint) { print $auth->p, "Go To <A HREF=\"$myself#$StartPoint\">$StartPoint</A>\n"; } if (! -f "$TMP/$UnitCode.xml") { print "<P>No $TMP/$UnitCode.xml!\n"; print $getDoc; return; } if (!$Editor) { if ($cookie =~ /cn--([^,]+),/) { $Editor = $1; print "<P>Editor = $Editor</P>\n"; $auth->param('Editor',$Editor); } else { print "<P><B>DO NOT HAVE AN EDITOR</B>"; print "<P>Cookie = $cookie\n"; return; } } <doEdit: have a Version Comment 45> }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doEdit is responsible for collecting the nominated unit description document, and formatting it using xsltproc under the stylesheet xml2html.xsl, the standard html view of a unit description. Gather the error output, and if that is non-empty, we display that in an error page, otherwise the output of the translation is used.

Now (v2.6.13) that there are auto version comments, the final macro call has been reduced from a choice (which depended on a non-null $VersionComment) between the two <doEdit: do NOT have a Version Comment 44> and <doEdit: have a Version Comment 45> macros.

<doEdit: parameter debugging 43> =
if ($debug) { $_=$TimeStamp." doEdit:These are the parameters and values:\n"; foreach $name (@params) { $_=$_." ".$name.'='.$auth->param($name)."\n"; } $_=$_." ".$field.'='.$newtext."\n"; $_=$_."\n"; print DEBUG; }
Chunk referenced in 42
<doEdit: do NOT have a Version Comment 44> =
print $auth->p, "Please enter a comment to describe the changes being made.", "This comment will be recorded in the document version history.", "Click 'edit' when done"; print $auth->start_form(-action=>"$SCRIPT"), $auth->hidden('UnitCode',$UnitCode), $auth->hidden('Editor',$Editor,), $auth->hidden('StartPoint',$StartPoint), $auth->hidden('EditExpert',$EditExpert), $auth->textarea(-name=>'VersionComment', -default=>$VersionComment, -override=>1, -rows=>10, -columns=>80), $auth->p, $auth->submit('edit'), $auth->end_form;

The routine was invoked with no Version Comment parameter. This is essential for version control, so we first invoke a simple textarea screen for the user to enter a version comment. This will be passed around on all subsequent updates following this doEdit call, but discarded once out of the edit-change-update cycle. This allows users to edit multiple fields on the one version comment.

(20031020:152839) omitted. Now that there is an automatic version history comment added, this is no longer essential. The user can still edit the field in the final edit pane.

<doEdit: have a Version Comment 45> =
print "<P>Note: Clicking on Headings and SubHeadings below will take ", "you to the corresponding place in the <A HREF=\"", "$SERVER/~ajh/adt/quality/V2Guidelines.html", "\">Guidelines Document</A></P>\n"; $VersionComment=~s/'/&apos;/g; $VersionComment=~s/"/&quot;/g; <doEdit: change Editor level 46> print $auth->p,"<B>Reason for Document Update:</B> $VersionComment"; <doEdit: set xsltproc parameters 48> $cmd="$XSLTPROC $parms -o $dest $xsl $src 2>$erf"; `$cmd`; $err = ""; open ERR,"<$erf"; while (<ERR>) {$err.=$_}; close ERR; if ($err) { <doEdit: handle errors 49> } else { print $auth->hr; print "<div style=\"background-color:#fff\">"; # use the resultant HTML file as returned page open NEW,"<$dest"; while (<NEW>) {print;} close NEW; print $auth->hr, $auth->p, "Is the version comment below still accurate after all your changes?", " If not, correct it below and click 'edit'", $auth->p, $auth->start_form(-action=>"$SCRIPT"), $auth->hidden('UnitCode',$UnitCode), $auth->hidden('Editor',$Editor), $auth->hidden('StartPoint',$StartPoint), $auth->hidden('EditExpert',$EditExpert), $auth->textarea(-name=>'VersionComment', -default=>$VersionComment, -override=>1, -rows=>10, -columns=>80), $auth->p, $auth->submit('edit'), $auth->end_form, $auth->hr, $auth->p, $auth->start_form(-action=>"$SCRIPT"), $auth->hidden('UnitCode',$UnitCode), $auth->hidden('Editor',$Editor), $auth->hidden('StartPoint',$StartPoint), $auth->hidden('EditExpert',$EditExpert), $auth->hidden('VersionComment',$VersionComment), $auth->submit('Save'), "Click this button to save your edits and return ", "to the Avatar Home Page. ", $auth->end_form, $auth->p, $auth->start_form(-action=>"$SCRIPT"), $auth->hidden('UnitCode',$UnitCode), $auth->hidden('Editor',$Editor), $auth->hidden('StartPoint',$StartPoint), $auth->hidden('EditExpert',$EditExpert), $auth->hidden('VersionComment',$VersionComment), $auth->submit('Submit'), "Click this button to submit your unit description for ", "<B STYLE=\"color:red\">SCHOOL</B> ", "approval and return to the Avatar Home Page. ", $auth->p, "<B STYLE=\"color:red\">NOTE THAT DIRECT SUBMISSION TO FEC IS NO LONGER POSSIBLE</B> ", $auth->end_form; print "</div>\n"; }
Chunk referenced in 42
<doEdit: change Editor level 46> =
if ($EditExpert) { print "<P>You are currently an <B>Expert</B> editor, $Editor!</P>\n"; } else { print "<P>You are currently a <B>Novice</B> editor, $Editor!</P>\n"; } print $auth->p,<doEdit: helpful text 47> print $auth->start_form(-action=>"$SCRIPT"), $auth->hidden('UnitCode',$UnitCode), $auth->hidden('Editor',$Editor,), $auth->hidden('VersionComment',$VersionComment), $auth->hidden('StartPoint',$StartPoint), $auth->p, $auth->submit('edit','Novice'), $auth->submit('edit','Expert'), $auth->hidden('EditExpert',$EditExpert), $auth->end_form; print $auth->hr;
Chunk referenced in 45

The first part of this part asks the user to nominate whether they wish to edit plain text ('Novice' user) or XML ('Expert' user). The value of $EditExpert is set on entry to the doEdit subroutine (see above).

<doEdit: helpful text 47> =
"<P>When editing your Unit Description, you can choose to ", "edit plain text (with some markup), or XML.</P><P>Plain ", "text is more user friendly, but less powerful; while editing ", "the XML requires strict discipline in tag closing and nesting. ", "Also please bear in mind that editing plain text may lose some ", "document formatting. (If you do not understand this message, ", "you can safely ignore it and proceed straight to the 'edit' box.)</P>", "<P>Click the Expert button if you want to edit the XML directly</P>";
Chunk referenced in 46

We have to sanitise the version comment for passing as a parameter into xsltproc. The call on xsltproc renders the XML unit description document into HTML, with clickable buttons to change the various editable fields.

Question: what should be done with the version comment at this stage?. One option is to insert it into the XML document as soon as possible, another is to defer it until the document is saved and/or archived, yet another is to add it as an editable field (but not yet part of the XML).

<doEdit: set xsltproc parameters 48> =
$xsl = "xml2html.xsl"; $src="$TMP/$UnitCode.xml"; $dest="$TMP/$UnitCode$destmod.html"; $erf="$TMP/$UnitCode-edit.stderr"; $datetime=$TimeStamp; #`/bin/date "+%d %b %Y %H:%M"`; chop($datetime); $datetime="$XP DateAndTime \"'$datetime'\""; if (defined($Editor)) {$editor="$XP Editor \"'$EscEditor'\""} else {$editor=""}; $unit="$XP UnitCode \"'$UnitCode'\""; $expert="$XP EditExpert \"\'$EditExpert\'\""; $change="$XP ViewOrEdit \"'Edit'\""; $version="$XP VersionComment \"'$VersionComment'\""; $server="$XP Server \"'$SCRIPT'\""; $parms="$datetime $editor $unit $expert $change $version $server";
Chunk referenced in 45

xsltproc requires 2 parameters, the stylesheet $xsl defining the translations, and the source xml document $src. In addition, we specify the destination html document $dest, an error file for stderr $erf, a date and time parameter $datetime, an editor parameter $Editor, and a unit code parameter $UnitCode. The latter three are used within the xsl stylesheet.

<doEdit: handle errors 49> =
$err=~s/&/&amp;/g; $err=~s/</&lt;/g; print "<P>doEdit: There was an error in translating the source file \n"; print "<TT>$TMP/$UnitCode.xml</TT>.\n"; print "Here is the output that was generated.\n"; print "If you cannot interpret this, please contact John Hurst.<P>\n"; print "<P><B>Command:</B></P>\n"; print "<PRE>\n"; print "$EditOrView\n"; print "$cmd\n"; print "<PRE>\n"; print "<P><B>Output:</B></P>\n"; print "</PRE>\n"; print "$err\n"; print "</PRE>\n"; print "\n";
Chunk referenced in 45

There were errors. Before we display the error file, we munge out all ampersands into ampersand entities, and all less than signs into less than entities.

6.2 doChange: Generate an Editable Text of the specified Field

Parms: /---------\ see list ---------->| MonAtar | below \---------/ | V getDocument: result in $TMP/$UnitCode.xml +--------------------+ | $TMP/$UnitCode.xml | +--------------------+ | V +-------------+ /----------\ | xml2txt.xsl |---->| xsltproc |<---- Param FieldA "fieldA value" +-------------+ \----------/ Param FieldB "fieldB value" | Param EditExpert "Novice|Expert" V / \ /OK?\ no \ /------> Error, Cannot happen! \ / | yes V +---------------------------+ text if EditExpert = Novice | $TMP/$UnitCode$suffix.txt | +---------------------------+ xml if EditExpert = Expert use this file to build default value in form delete TMP files

The following parameters are passed to MonAtar.

change
a value passed in from the doEdit generated form, with the structure Change FieldA/FieldB, where FieldA and FieldB are hierarchical field tags from the Unit Description document. These are used to extract the original value from the document for setting the default editing value.
UnitCode
The unit code
Editor
an authenticated user
EditExpert
a boolean indicating the expert status of the user
<subroutines 50> =
sub doChange { doLogOperation("doChange"); $change = $auth->param('change'); $VersionComment = $auth->param('VersionComment'); $UnitCode=~tr/a-z/A-Z/; $change=~s#^Change ([^/]*)(/(.*))?$#\1\2#; $FieldA=$1; $FieldB=$3; $suffix=$FieldA.$FieldB; getDocument(0,0); $TITLE="Infotech Avatar: Updating $UnitCode"; &printHtmlHeaders; if ($EditExpert) { print "<P>You are currently an <B>Expert</B> editor!</P>\n"; } else { print "<P>You are currently a <B>Novice</B> editor!</P>\n"; } if ($debug) { $_=$auth->p."doChange($UnitCode,$Editor,$FieldA,$FieldB)=>$change\n"; $_=$_.$auth->p."These are the parameters and values:\n"; $_=$_."<P STYLE=\"margin-left:20pt\">"; foreach $name (@params) { $_=$_.$name.'='.$auth->param($name).'<BR>'; } $_=$_.'</P>'; print DEBUG $_; } print $auth->h2("Editing $UnitCode $change field ..."), $auth->p, "Edit the following text, then click this 'Update' ", "button."; <doChange: print helpful hints 51> my $xsl = "$XMLPAGE/xml2txt.xsl"; if ($EditExpert) {$xsl = "$XMLPAGE/xmlextract.xsl"}; my $src = "$TMP/$UnitCode.xml"; my $dst = "$TMP/$UnitCode$suffix.txt"; my $prm = "$XP FieldA \"\'$FieldA\'\" $XP FieldB \"\'$FieldB\'\""; $prm .= " $XP EditExpert \"\'$EditExpert\'\""; my $ers = "$TMP/$UnitCode-change.ers"; my $cmd = "$XSLTPROC $prm $xsl $src >$dst 2>$ers"; my $res = `$cmd`; if ($debug) { print DEBUG "doChange: $cmd\n"; } my $val = ""; open XML,$dst; while (<XML>) {$val=$val.$_;} close XML; unlink $dst; print $auth->start_form(-action=>"$SCRIPT"), $auth->submit('update',"Update the $change"); <doChange: warn about editing ObjText 52> print $auth->p, $auth->textarea(-name=>$change, -default=>$val, -override=>1, -rows=>50, -columns=>80), $auth->p, $auth->hidden(-name=>'UnitCode',-default=>$UnitCode), $auth->hidden(-name=>'Editor',-default=>$Editor), $auth->hidden('EditExpert',$EditExpert), $auth->hidden(-name=>'VersionComment',-default=>$VersionComment), $auth->hidden(-name=>'FieldA',-default=>$FieldA), $auth->hidden(-name=>'FieldB',-default=>$FieldB), $auth->hidden(-name=>'value',-default=>$val), $auth->end_form; unlink $ers; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<doChange: print helpful hints 51> =
if (!$EditExpert) { print "Some helpful hints:"; print $auth->p, "<P>Text in this window should be formatted to reflect its logical ", "structure, and is used to build the document structure of the ", "XML fragment.</P>", "<UL><LI>Blank lines represent paragraph breaks. ", "<B>DON'T put blank lines between items in an (un)numbered list, ", "otherwise each item will be a separate list!</B></LI>", "<LI>(Carriage) returns or enters are ignored if the next line ", "has the same indentation as the previous line.</LI>", "<LI>Itemized text should be consistently indented, and flagged ", "with a leading '+', '-' or 'o' character, followed by at least ", "one blank.</LI>", "<LI>Numbered text should be consistently indented, and flagged ", "with one or more leading digits, followed by a full stop and at ", "least one blank.</LI>", "<LI>Nested itemized or numbered paragraphs can be shown by ", "increasing the indentation.</LI>", "<LI>{\\b bold}, {\\i italic}, and {\\ul underline} can be used to ", "markup highlighted text</LI></UL>\n"; }
Chunk referenced in 50
<doChange: warn about editing ObjText 52> =
if ($change=~m^UnitObjectives/ObjText^) { print $auth->p,'<span style="color:red"><b><blink>'. 'IF YOU CONTINUE TO EDIT THIS FIELD, IT WILL BE DELETED.'. '</blink> USE YOUR BACK BUTTON NOW TO CANCEL!</b></span>'; }
Chunk referenced in 50

6.3 doUpdate: Incorporate changes into the Unit Description

<subroutines 53> =
sub doUpdate { doLogOperation("doUpdate"); my $FieldA = $auth->param('FieldA'); my $FieldB = $auth->param('FieldB'); my $VersionComment = $auth->param('VersionComment'); my $field = $FieldA; if ($FieldB) {$field="$FieldA/$FieldB";} my $suffix = $FieldA.$FieldB; my $newtext = $auth->param($field); $UnitCode=~tr/a-z/A-Z/; getDocument(0,0); <doUpdate: parameter debugging 54> $newtext =~ s/\r/ /g; if ($auth->param('update')=~/Change Classification/) { $FieldA = "Classification"; $field=$FieldA; $Attribute = "BOK"; $newtext = $auth->param("BOK"); $newtext =~ s/.*\((.*)\)/\1/; } elsif ($auth->param('update')=~m^Update the UnitObjectives/ObjText^) { $newtext=""; } else { if (!$EditExpert) { <doUpdate: convert plain text to XML 55> } <doUpdate: sanitise newtext 56> } <doUpdate: call the xslt processor 57> if (-s $ers && $debug) {print DEBUG "doUpdate: failed on merge\n";} if (-z $ers) { <doUpdate: check revised document 59> if (-s $ers && $debug) {print DEBUG "doUpdate: failed on check\n";} } if (-s $ers) { <doUpdate: error reporting 58> } else { rename "$TMP/$UnitCode-new.xml","$SUBMISSIONS/$UnitCode.xml"; if ($VersionComment) {$VersionComment.="; ";} $VersionComment.="modified $field"; $auth->param(-name=>'StartPoint',-values=>[$field]); $auth->param(-name=>'VersionComment',-values=>[$VersionComment]); &doEdit(0); } unlink $ers; return; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doUpdate is called when the user has edited a field of the description, and clicks the "Update the ...." button. The avatar is invoked with the following set of parameters:

UnitCode
The unit code
Editor
The editor of the document
field
The element name of the field being edited.
tag
(This parameter varies with the tag of the field being edited.) The new value of the field.
value
The original value of the field (not used)

We grab the new text to replace the field. This is the raw ascii text, as edited by the user. Write this text into a file, for conversion by the ascii to xml translator, a2x. Call the translator, and read the translated text (now in XML markup) back into $newtext.

<doUpdate: parameter debugging 54> =
if ($debug) { $_=$TimeStamp." doUpdate:These are the parameters and values:\n"; foreach $name (@params) { $_=$_." ".$name.'='.$auth->param($name)."\n"; } $_=$_." ".$field.'='.$newtext."\n"; $_=$_."\n"; print DEBUG; print DEBUG "doUpdate($UnitCode,$Editor,$field,$newtext)=>$suffix\n"; print DEBUG "Opening $TMP/$UnitCode$suffix.txt\n"; }
Chunk referenced in 53 60 61
<doUpdate: convert plain text to XML 55> =
my $txt = "$TMP/$UnitCode$suffix.txt"; open FIELD,">$txt"; print FIELD $newtext; close FIELD; $newtext=""; $cmd="$XMLPAGE/a2x.pl $txt"; if ($debug) { print DEBUG "doUpdate: $cmd\n"; } `$cmd`; unlink $txt; my $xml = "$TMP/$UnitCode$suffix.xml"; open FIELD,$xml; while (<FIELD>) {s#<p></p>##; $newtext=$newtext.$_;} close FIELD; unlink $xml; #print "<P>Finished translation to XML\n";
Chunk referenced in 53
<doUpdate: sanitise newtext 56> =
$newtext=~s/\n/ /g; $newtext=~s/ +/ /g; $newtext=~s/"/&quot;/g; $newtext=~s/'/&apos;/g; $newtext=~tr/[\x80-\xff]/?/; if ($debug) { print DEBUG $newtext; print DEBUG "<P>End of translated text\n"; }
Chunk referenced in 53

sanitise the new text to be inserted by

  1. removing all new lines and replacing them with spaces
  2. replacing multiple spaces with a single space
  3. changing double quotes (which foul up the parameter passing at the command line level) to XML entities
  4. ditto for single quotes
  5. ensuring that all characters are 7-bit ASCII
For debugging purposes, print the new sanitised text.

<doUpdate: call the xslt processor 57> =
$proc="$XSLTPROC"; $xsl="$XMLPAGE/mergexml.xsl"; $src="$TMP/$UnitCode.xml"; $dst="$TMP/$UnitCode-new.xml"; $ers="$TMP/$UnitCode-new.ers"; $prms="$XP FieldA \"\'$FieldA\'\" $XP FieldB \"\'$FieldB\'\""; $prms.=" $XP NewText \"\'$newtext\'\" $XP Attribute \"\'$Attribute\'\""; $prms.=" $XP DateTime \"\'$timestamp\'\""; $cmd="$proc $prms -o $dst $xsl $src 2>$ers"; if ($debug) {print DEBUG "$cmd\n"}; `$cmd`;
Chunk referenced in 53

We add the edited field into the unit description with the aid of the mergexml.xsl XSLT transform. This script takes an existing XML unit description and merges the NexText parameter into the field FieldA/FieldB. This is a two level addressing operation, since many fields of the unit description are subfields of top-level fields. See the mergexml.xsl documentation for further details of this transformation.

<doUpdate: error reporting 58> =
$TITLE="Infotech Avatar: Error in Updating $UnitCode"; &printHtmlHeaders; print "<P>doUpdate: There was an error in adding your edits to \n"; print "<TT>$TMP/$UnitCode.xml</TT>.\n"; print "Here is the output that was generated.\n"; print "If you cannot interpret this, please contact John Hurst.<P>\n"; print "<P><B>Command:</B></P>\n"; print "<PRE>\n"; print "$cmd\n"; print "<PRE>\n"; print "<P><B>Output:</B></P>\n"; print "</PRE>\n"; $err=""; open ERR,"<$ers";while(<ERR>){$err.=$_;} close ERR; $err=~s/&/&amp;/g; $err=~s/</&lt;/g; print "$err\n"; print "</PRE>\n"; print "\n";
Chunk referenced in 53 60 61
<doUpdate: check revised document 59> =
$proc="$XSLTPROC"; $xsl="xml2html.xsl"; $src="$TMP/$UnitCode-new.xml"; $dst="$TMP/$UnitCode-new.html"; $ers="$TMP/$UnitCode-new.ers"; $prms="$XP UnitCode \"\'$UnitCode\'\" "; $cmd="$proc $prms -o $dst $xsl $src 2>$ers"; print DEBUG "doUpdate: check revised document ($cmd)\n"; `$cmd`;
Chunk referenced in 53
We have a new document, UnitCode-new.xml, which we should check for well-formedness before proceding further. Do this by running it through the view stylesheet.

6.4 doSave: Incorporate changes into the Unit Description

<subroutines 60> =
sub doSave { doLogOperation("doSave"); my $VersionComment = $auth->param('VersionComment'); my @Classification = $auth->param('BOK'); $UnitCode=~tr/a-z/A-Z/; getDocument(0,0); $TITLE="Infotech Unit Avatar: Save Document"; &printHtmlHeaders; $src="$TMP/$UnitCode.xml"; print $auth->p,"<P>Timestamp=$timestamp</P>\n"; $k="V"; $FullUnitCode="$UnitCode-$timestamp-$k"; $dest="$SUBMISSIONS/archive/$FullUnitCode"; <doUpdate: parameter debugging 54> $proc="$XSLTPROC"; $xsl="$XMLPAGE/MonAtar-version.xsl"; $src="$TMP/$UnitCode.xml"; $dst="$TMP/$UnitCode-new.xml"; $ers="$TMP/$UnitCode-new.ers"; $prms="$XP Date \"\'$timestamp\'\" ". "$XP Editor \"\'$EscEditor\'\" ". "$XP VersionComment \"\'$VersionComment\'\""; $cmd="$proc $prms -o $dst $xsl $src 2>$ers"; #print "<P>$cmd\n"; `$cmd`; $err=""; open ERR,"<$ers";while(<ERR>){$err.=$_;} close ERR; if ($err) { <doUpdate: error reporting 58> } else { `cp "$TMP/$UnitCode-new.xml" "$dest"`; rename "$TMP/$UnitCode-new.xml","$SUBMISSIONS/$UnitCode.xml"; print $auth->p,"Save successful! Click to reenter avatar, ". "or view edited description"; print $auth->start_form(-action=>"$SCRIPT"), $auth->submit('reenter',"Reenter Avatar"), $auth->submit('view',"View Updated Unit"), $auth->hidden('UnitCode',$UnitCode), $auth->end_form; } unlink $ers; return; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doSave is called when the user clicks the final "Save" button on the doEdit page. The avatar is invoked with the following set of parameters:

UnitCode
The unit code
Editor
The editor of the document
VersionComment
The comment to insert in the version history, along with Editor, Date and Time information.

6.5 doSubmit: Incorporate changes into the Unit Description

<subroutines 61> =
sub doSubmit { doLogOperation("doSubmit"); my $VersionComment = $auth->param('VersionComment'); $UnitCode=~tr/a-z/A-Z/; getDocument(0,0); $TITLE="Infotech Unit Avatar: Submit Document"; &printHtmlHeaders; $src="$TMP/$UnitCode.xml"; print $auth->p,"<P>Timestamp=$timestamp</P>\n"; $k="M"; $FullUnitCode="$UnitCode-$timestamp-$k"; $dest="$SUBMISSIONS/archive/$FullUnitCode"; <doUpdate: parameter debugging 54> $proc="$XSLTPROC"; $xsl="$XMLPAGE/MonAtar-version.xsl"; $src="$TMP/$UnitCode.xml"; $dst="$TMP/$UnitCode-new.xml"; $ers="$TMP/$UnitCode-new.ers"; $prms="$XP Date \"\'$timestamp\'\" ". "$XP Editor \"\'$EscEditor\'\" ". "$XP VersionComment \"\'$VersionComment\'\""; $cmd="$proc $prms -o $dst $xsl $src 2>$ers"; #print "<P STYLE=\"margin-left:20pt\">$cmd</P>\n"; `$cmd`; <doSubmit: get document values 62> $err=""; open ERR,"<$ers";while(<ERR>){$err.=$_;} close ERR; if ($err) { <doUpdate: error reporting 58> } else { `cp "$TMP/$UnitCode-new.xml" "$dest"`; rename "$TMP/$UnitCode-new.xml","$SUBMISSIONS/$UnitCode.xml"; <doSubmit: send mail to SEC members 63> print $auth->p,"<B>Submit successful!</B>"; print $auth->p, "Click to reenter avatar, ", "or simply delete this window and reuse original window."; print $auth->start_form(-action=>"$SCRIPT"), $auth->submit('reenter',"Avatar"), $auth->hidden('UnitCode',$UnitCode), $auth->end_form; } return; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doSubmit is called when the user clicks the final "Submit" button on the doEdit page. The avatar is invoked with the following set of parameters:

UnitCode
The unit code
Editor
The editor of the document
VersionComment
The comment to insert in the version history, along with Editor, Date and Time information.
The document is also archived with the extension "M" (for unit subMission to the school level).

<doSubmit: get document values 62> =
open DOCVALS,"<$TMP/$UnitCode.msgs"; while (<DOCVALS>) {$docvals.=$_}; close DOCVALS; $docvals=~s/UnitName = (.*)\$\n//s; $UnitName = $1; $docvals=~s/UnitSummary = (.*)\$\n//s; $UnitSummary = $1;
Chunk referenced in 61
<doSubmit: send mail to SEC members 63> =
my $mode = "submitted"; getLatestApproved($UnitCode); $mailmsg="A unit description (for a new or existing unit)\n"; $mailmsg.=" $UnitCode $UnitName\n"; $mailmsg.="has been $mode at URL:\n\n"; $mailmsg.=" $SCRIPT?UnitCode=$FullUnitCode\n\n"; if ($ApprovedVersion) { $mailmsg.="You can compare this with the latest (Faculty) approved"; $mailmsg.=" version by clicking\n\n"; $mailmsg.=" $SCRIPT?". "compare=compare&BaseCode=$ApprovedVersion". "&UnitCode=$FullUnitCode\n\n"; } if ($mode=~/saved/) { $mailmsg.="WARNING: This revision has not been notified to SEC\n"; $mailmsg.="******** You must explicitly SUBMIT the description "; $mailmsg.="for that to happen!\n\n"; } $mailmsg.="Author of Revisions: $Editor\n"; $mailmsg.="Unit Synopsis: $UnitSummary\n"; if ($UnitCode) { $esub="[MonAtar] $UnitCode $UnitName ($mode) "; <doSubmit: get submission data 64> # send each of the school SEC members an email foreach $eadr (@adrs) { $recipients.=$eadr."\n"; &sendmail($eadr,$esub,$mailmsg); } # Send the ADT a copy $eadr="John.Hurst\@infotech.monash.edu.au"; $recipients.=$eadr."\n"; &sendmail($eadr,$esub,$mailmsg); # sanitise the ProposerEmail field(s) $ProposerEMail=~tr/\r\n /,,,/; $ProposerEMail =~s/,,+/,/g; @emails = split(',',$ProposerEMail); # chop at commas foreach $email (@emails) { $email =~ s/[\s;]//g; if ($email =~ /^[\w\.-@<>"]+$/) { $recipients.=$email."\n"; &sendmail($email,$esub,$mailmsg); } else { print "<P>$email not emailed as it contains illegal characters</P>\n"; } } # sanitise the ContactEmail field(s) $ContactEMail=~tr/\r\n /,,,/; $ContactEMail =~s/,,+/,/g; @emails = split(',',$ContactEMail); # chop at commas foreach $email (@emails) { $email =~ s/[\s;]//g; if ($email =~ /^[\w\.-@<>"]+$/) { $recipients.=$email."\n"; &sendmail($email,$esub,$mailmsg); } else { print "<P>$email not emailed as it contains illegal characters</P>\n"; } } print "<P>The following email addresses have been notified of your submission</P>\n"; print "<PRE STYLE=\"margin-left:20pt\">$recipients</PRE>\n"; print "with the following message:\n"; print "<PRE STYLE=\"margin-left:20pt\">$mailmsg</PRE>\n"; if ($debug) { print DEBUG "Submit: emailed the following recipients:\n$recipients\n"; } }
Chunk referenced in 61
<doSubmit: get submission data 64> =
my ($fac,$sch); print DEBUG "doSubmit: Faculty=$Faculty, School=$School\n"; if ($Faculty=~/Information Technology/) { $fac="IT"; if ($School=~/Gippsland/) {$sch="gscit"} elsif ($School=~/Business Systems/) {$sch="sbs"} elsif ($School=~/Computer Science/) {$sch="csse"} elsif ($School=~/Network/) {$sch="snc"} elsif ($School=~/Information Management/) {$sch="sims"} elsif ($School=~/Multimedia/) {$sch="sms"} elsif ($School=~/Business and Information Technology/) {$sch="mum"} elsif ($School=~/South Africa/) {$sch="sa"} else { printError("No School","No school code $School to receive submission"); } } elsif ($Faculty=~/Medicine/) { printError("No Faculty","$Faculty not currently receiving submissions"); } elsif ($Faculty=~/Business/) { printError("No Faculty","$Faculty not currently receiving submissions"); } else { printError("No Faculty","$Faculty not currently receiving submissions"); } my $submitdataname = "MonAtar-$fac-$sch.adr"; open ADRS,$submitdataname or printError("No Addresses","I couldn't find the addresses $submitdataname to email"); my @adrs; while (<ADRS>) { chop; push(@adrs,$_); } close ADRS; # Here a kludge to check if editor's school is the same # as the proposing school for the unit. If not, send to both. my ($propsch) = $UnitCode; $propsch =~ s/[0-9]+.*$//; if ($propsch=~/GCO/) {$propsch="gscit"} elsif ($propsch=~/BUS/) {$propsch="sbs"} elsif ($propsch=~/CSE/) {$propsch="csse"} elsif ($propsch=~/CPE/) {$propsch="snc"} elsif ($propsch=~/IMS/) {$propsch="sims"} elsif ($propsch=~/MIS/) {$propsch="sims"} elsif ($propsch=~/MMS/) {$propsch="sms"}; if ($propsch ne $sch) { # schools differ, do the proposing school as well my $submitdataname = "MonAtar-$fac-$propsch.adr"; open ADRS,$submitdataname or printError("No Addresses","I couldn't find the ". "addresses $submitdataname to email"); while (<ADRS>) { chop; push(@adrs,$_); } close ADRS; }
Chunk referenced in 63
<subroutines 65> =
use Socket; sub sendmail { my ($adr) = shift; #my ($repl) = shift; my ($sub) = shift; my ($msg) = shift; my ($remote,$port, $iaddr, $paddr, $proto, $line); open MSG,">$TMP/msg-Avatar"; print MSG "To: $adr\n"; print MSG "From: MonAtar\@csse.monash.edu.au\n"; my $repl = "$Editor\@infotech.monash.edu.au"; $repl =~ s/ /\./g; print MSG "Reply-to: $repl\n"; print MSG "Subject: $sub\n\n"; print MSG $msg; close MSG; $cmd="/usr/lib/sendmail -t <$TMP/msg-Avatar"; `$cmd`; return; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

20030228:170657 removed the -ba flag from the sendmail line. This now seems to stop transmission (reason why is obscure).

7. Compare Unit Decriptions

<subroutines 66> =
sub doCompare { doLogOperation("doCompare"); my $BaseCode = $auth->param('BaseCode'); <doCompare: set xsltproc parameters 67> $cmd="$XSLTPROC $parms -o $dest $xsl $src 2>$erf"; `$cmd`; $err = ""; open ERR,"<$erf"; while (<ERR>) {$err.=$_}; close ERR; print $auth->header(); print $auth->start_html(-title=>"Compare Unit Descriptions", -BGCOLOR=>"#ddffdd"); if ($err) { <doCompare: handle errors 68> } else { # use the resultant HTML file as returned page open NEW,"<$dest"; while (<NEW>) {print;} close NEW; } #unlink $src,$dest,$erf; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<doCompare: set xsltproc parameters 67> =
my $fileA="$SUBMISSIONS/archive/$BaseCode"; my $fileB="$SUBMISSIONS/archive/$UnitCode"; my $dest="$TMP/$UnitCode-compare.html"; my $src="$XMLPAGE/dummy.xml"; my $erf="$TMP/$UnitCode.stderr"; my $parms="$XP UnitA \"'$fileA'\""; $parms.=" $XP UnitB \"'$fileB'\""; $xsl = "$XMLPAGE/compare.xsl";
Chunk referenced in 66
<doCompare: handle errors 68> =
$err=~s/&/&amp;/g; $err=~s/</&lt;/g; print "<P>doCompare: There was an error in comparing the files \n"; print "<TT>$fileA</TT>.\n"; print "Here is the output that was generated.\n"; print "If you cannot interpret this, please contact John Hurst.<P>\n"; print "<P><B>Command:</B></P>\n"; print "<PRE>\n"; print "$EditOrView\n"; print "$cmd\n"; print "<PRE>\n"; print "<P><B>Output:</B></P>\n"; print "</PRE>\n"; print "$err\n"; print "</PRE>\n"; print "\n";
Chunk referenced in 66

There were errors. Before we display the error file, we munge out all ampersands into ampersand entities, and all less than signs into less than entities.

8. Show Unit Descriptions

<subroutines 69> =
sub doShow { doLogOperation("doShow"); my $ShowAll = $auth->param('show'); $UnitCode =~ s/( |\n|\r)*//g; $UnitCode=~tr/a-z/A-Z/; my (%units); my (%SaveLateTime,%SaveLateLink); my (%SubmitLateTime,%SubmitLateLink); my (%OKLateTime,%OKLateLink); my (%EndorseLateTime,%EndorseLateLink); my (%ApproveLateTime,%ApproveLateLink); my $Since = $auth->param('Since') || '20000101'; my $Until = $auth->param('Until') || '20041231'; $yearrequired='t'; $Since=~/([\d]{4})/; my $syr = $1; $Until=~/([\d]{4})/; my $uyr = $1; if ($syr eq $uyr) {$yearrequired=''}; print $auth->header(); print $auth->start_html(-title=>"Summary of All Descriptions", -BGCOLOR=>"#ddffdd"); <doShow: generate form components 70> getLatestApproved($UnitCode); my $dir="$SUBMISSIONS/archive"; if ($TESTING) {print "directory=$dir<P>\n";} opendir(ARCHIVE,$dir); @archfiles=grep(!/^\.\.?$/,readdir(ARCHIVE)); closedir ARCHIVE; @archfiles=sort(@archfiles); $Until.="240001"; # make last date inclusive, i.e., up till midnight. <doShow: compute time ranges 71> <doShow: generate table of units 72> <doShow: version differences 73> print $auth->end_html(); exit 0; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doShow is responsible for collecting the nominated unit description document, and formatting it using xsltproc under the stylesheet xml2html.xsl, the standard html view of a unit description. Gather the error output, and if that is non-empty, we display that in an error page, otherwise the output of the translation is used. This output used to be saved, but there seems little point now.

<doShow: generate form components 70> =
print $auth->startform("post","$SCRIPT"); print $auth->h1('Unit Description Summary: '.$ShowAll), $auth->p,"<P><B>For </B>", $auth->textfield('UnitCode',$UnitCode,8), "(Entering a (part) unit code in this field will ", "limit the search to units matching this prefix)", $auth->p,"<P><B>Since ", $auth->textfield('Since',$Since,10)," and Until </B>", $auth->textfield('Until',$Until,10), $auth->submit('show',$auth->param('show')), " (Dates are inclusive)"; print $auth->endform();
Chunk referenced in 69
<doShow: compute time ranges 71> =
foreach $f (@archfiles) { if ($f =~ /^$UnitCode/) { if ($f=~/([A-Za-z]+[0-9]+[A-Za-z]?)-([0-9]+)(-[VMSEA])?/) { my ($s,$t,$m) = ($1,$2,$3); if ($t gt $Since && $t le $Until) { $units{$s}++; if (!$m || $m=~/V/) { if (!$SaveLateTime{$s}) { $SaveLateTime{$s} = $t; $SaveLateLink{$s}=$f; } elsif ($t gt $SaveLateTime{$s}) { $SaveLateTime{$s} = $t; $SaveLateLink{$s}=$f; } } elsif ($m=~/M/) { if (!$SubmitLateTime{$s}) { $SubmitLateTime{$s} = $t; $SubmitLateLink{$s}=$f; } elsif ($t gt $SubmitLateTime{$s}) { $SubmitLateTime{$s} = $t; $SubmitLateLink{$s}=$f; } } elsif ($m=~/S/) { if (!$OKLateTime{$s}) { $OKLateTime{$s} = $t; $OKLateLink{$s}=$f; } elsif ($t gt $OKLateTime{$s}) { $OKLateTime{$s} = $t; $OKLateLink{$s}=$f; } } elsif ($m=~/E/) { if (!$EndorseLateTime{$s}) { $EndorseLateTime{$s} = $t; $EndorseLateLink{$s}=$f; } elsif ($t gt $EndorseLateTime{$s}) { $EndorseLateTime{$s} = $t; $EndorseLateLink{$s}=$f; } } elsif ($m=~/A/) { if (!$ApproveLateTime{$s}) { $ApproveLateTime{$s} = $t; $ApproveLateLink{$s}=$f; } elsif ($t gt $ApproveLateTime{$s}) { $ApproveLateTime{$s} = $t; $ApproveLateLink{$s}=$f; } } } } } }
Chunk referenced in 69
<doShow: generate table of units 72> =
if ($ShowAll=~/SHOW Descriptions/) { print "<P><B>Clicking on any link will generate a comparison ". "for that unit description against the latest (Faculty) ". "approved version of the unit.</B></P>\n"; print "<P>If there is no previously approved version, only ". "the unit code-time stamp is shown (no links).</P>\n"; print "<P>Links are arranged most recent first. The current ". "approved version is highlighted in green. ". "The suffixes for each link indicate the level of ". "approval:<BR>". " V - saved only<BR>". " M - submitted to SEC<BR>". " S - OKed by School<BR>". " E - Endorsed by FEC<BR>". " A - Approved by Faculty Board</P>\n"; print "<TABLE BGCOLOR=\"white\" BORDER=\"1\">\n"; print "<TR><TH>Unit</TH><TH>Times</TH><TH>". "Approved</TH>"; foreach $s (sort(keys(%units))) { print "<TR><TD>$s</TD>","<TD ALIGN=\"center\">", $units{$s},"</TD>"; print "<TD>",$ApproveLateTime{$s},"</TD>"; my $line=""; my (@links); foreach $f (@archfiles) { if ($f =~ /^$s-/) { if ($f=~/([A-Za-z]+[0-9]+[A-Za-z]?)-([0-9]+)(-[VCM])?/) { my ($s,$t,$m) = ($1,$2,$3); if ($t gt $Since && $t le $Until) { push(@links,$f); } } } } @links = sort(@links); foreach $f (@links) { my $bg = ""; if ($ApprovedVersion=~/$f/) {$bg=" BGCOLOR=\"lightgreen\"";} my $linkage="<A HREF=\"$SCRIPT?". "compare=compare&BaseCode=$ApprovedVersion&". "UnitCode=".$f."\"><TT>". $f."</TT></A>"; if (!$ApprovedVersion) { $linkage="$f"; } $line="<TD$bg>$linkage</TD>".$line; } print $line; print "</TR>\n"; } print "\n</TABLE>\n"; } elsif ($ShowAll=~/SHOW ALL Descriptions/) { print "<TABLE BGCOLOR=\"white\" BORDER=\"1\">\n"; print "<TR><TH>Unit</TH><TH>Times</TH>"; foreach $s (sort(keys(%units))) { print "<TR><TD>$s</TD>", "<TD ALIGN=\"center\">",$units{$s}; my $line=""; my (@links); foreach $f (@archfiles) { if ($f =~ /^$s/) { if ($f=~/([A-Za-z]+[0-9]+[A-Za-z]?)-([0-9]+)(-.)?/) { my ($s,$t,$m) = ($1,$2,$3); if ($t gt $Since && $t le $Until) { push(@links,$f); } } } } @links = sort(@links); foreach $f (@links) { $f=~/([A-Za-z]+[0-9]+[A-Za-z]?)-([0-9]+)(-.)?/; my ($t) = ($2); $line="<TD>".dispDate($t,$f,' ')."</TD>".$line; } print $line; print "</TR>"; } print "\n</TABLE>\n"; } elsif ($ShowAll=~/SHOW APPROVAL Profile/) { <doShow: print Approval page explanation 75> print "<TABLE BGCOLOR=\"white\" BORDER=\"1\">\n"; print "<TR><TH>Unit</TH><TH>Times</TH>"; print "<TH>Latest Save</TH><TH>Latest Submit</TH>"; print "<TH>School OK given</TH><TH>FEC Endorsed</TH>\n"; print "<TH>FacBoard Approved</TH></TR>\n"; foreach $s (sort(keys(%units))) { print "<TR><TD>$s</TD>", "<TD ALIGN=\"center\">",$units{$s}; my $col = 'lightgreen'; if ($SubmitLateTime{$s} < $SaveLateTime{$s}) { $col = 'yellow';} print "</TD><TD ALIGN=\"center\" BGCOLOR=\"".$col."\">", dispDate($SaveLateTime{$s},$SaveLateLink{$s},'Not Saved'); $col='lightgreen'; if (!$SubmitLateTime{$s}) {$col = 'pink';} print "</TD><TD ALIGN=\"center\" BGCOLOR=\"".$col."\">", dispDate($SubmitLateTime{$s},$SubmitLateLink{$s},'Not Submitted'); if ($col=~/lightgreen/ && $OKLateTime{$s} < $SubmitLateTime{$s}) { $col = 'pink';} print "</TD><TD ALIGN=\"center\" BGCOLOR=\"".$col."\">", dispDate($OKLateTime{$s},$OKLateLink{$s},'Not OK'); if ($col=~/lightgreen/ && $EndorseLateTime{$s} < $OKLateTime{$s}) { $col = 'pink';} print "</TD><TD ALIGN=\"center\" BGCOLOR=\"".$col."\">", dispDate($EndorseLateTime{$s},$EndorseLateLink{$s},'Not Endorsed'); if ($col=~/lightgreen/ && $ApproveLateTime{$s} < $EndorseLateTime{$s}) { $col = 'pink';} print "</TD><TD ALIGN=\"center\" BGCOLOR=\"".$col."\">", dispDate($ApproveLateTime{$s},$ApproveLateLink{$s},'Not Approved'), "</TD></TR>\n"; } print "\n</TABLE>\n"; }
Chunk referenced in 69
<doShow: version differences 73> =
if ($ShowAll=~/SHOW Descriptions/) { if (scalar(keys(%units)) eq 1) { my @sc = keys(%units); my $sc = $sc[0]; print $auth->h2( "List of Saves and Differences for $sc over this Period"); my $last="$XMLPAGE/UnitTemplate.xml"; foreach $f (@archfiles) { if ($f=~/^$UnitCode/) { if ($f=~/([A-Z]+[0-9]+)-([0-9]+)(-[VCM])?/) { my ($s,$t,$m) = ($1,$2,$3); if ($t gt $Since && $t le $Until) { print dispDate($t,$f,"Error"),"<PRE>\n"; $diffs=`/usr/bin/diff -w $last $dir/$f`; $diffs=~s/\n</\nREMOVE/g; $diffs=~s/\n>/\nINSERT/g; $diffs=~s/&/&amp;/g; $diffs=~s/</&lt;/g; $diffs=~s#\nREMOVE#\n<B>REMOVE</B>#g; $diffs=~s#\nINSERT#\n<B>INSERT</B>#g; print $diffs; print "\n</PRE><BR>"; $last="$dir/$f"; } } } } } }
Chunk referenced in 69
<subroutines 74> =
sub dispDate { my ($date,$link,$nodate)=(shift,shift,shift); my ($displaydate,$linkage); if (!defined($date)) {return $nodate;} if ($date =~ /([\d]{4})([\d]{2})([\d]{2})([\d]{2})([\d]{2})/) { my ($yr,$mon,$day,$hr,$min)=($1,$2,$3,$4,$5); @Month = ('Jan','Feb','Mar','Apr','May','Jun', 'Jul','Aug','Sep','Oct','Nov','Dec'); if ($yearrequired) { $displaydate = $day.' '.$Month[$mon-1].' '.$yr.' '.$hr.':'.$min; } else { $displaydate = $day.' '.$Month[$mon-1].' '.$hr.':'.$min; } if ($link) { $linkage="<A HREF=\"$SCRIPT?". "UnitCode=".$link."\"><TT>". $displaydate."</TT></A>"; return $linkage; } else { return $displaydate; } } else { return $nodate; } }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106
<doShow: print Approval page explanation 75> =
print <<' FINIS'; <P>The colour code used is as follows:</P> <DL> <DT>yellow</DT><DD>Saves are current that have not been approved</DD> <DT>green</DT><DD>Approval process complete to this stage</DD> <DT>pink</DT><DD>Approval process not yet completed to this stage</DD> </DL> FINIS
Chunk referenced in 72

Warning! The use of the here document is a kluge. Note the explicit inclusion of indentation space, which cannot be elided in this literate program structure.

9. doApprove: Approve a Unit Description

doApprove is responsible for handling the process of approving unit descriptions. There are a range of different approvals, and the work flow for these approvals must be maintained. Firstly we identify which level of approval is sought, then find which unit description is to be approved, and finally stamp the unit approval. There are three separate pages to handle each of these steps, and consequently three entry points to this routine, corresponding to the approve parameter on entry.

The workflow is handled by the flag attached to the file. This is a single letter flag, with the following meanings:

V
a saVed file: generated by an arbitrary (authenticated) user saving the file.
M
a subMitted file: when a user submits a file for school approval.
S
a School approved file: when the school SEC approves the proposal. Schools can only approve a file with the M flag
E
an Endorsed file: when the proposal is approved by the FEC. FEC can only approve files with the S flag.
A
an Approved file: finally approved by Faculty Board. FB can only approve files with the E flag.
<subroutines 76> =
sub doApprove { doLogOperation("doApprove"); $UnitCode =~ s/( |\n|\r)*//g; $UnitCode =~ tr/a-z/A-Z/; if ($auth->param('approve')=~/APPROVE Description/) { <doApprove: show approvals options 77> } elsif ($auth->param('approve')=~/SELECT (.*)$/) { <doApprove: select unit for approval 90> } elsif ($auth->param('approve')=~/APPROVE (.*)$/) { <doApprove: give approval to unit 92,93,94,95,96,97> } else { printError('dudApprove',"No doApprove branch for ". $auth->param('approve')); } exit; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

On entering doApprove, the approve parameter is set to either APPROVE Description, indicating first time entry, or APPROVE parameter, indicating the choice of approval option, or SELECT parameter, indicating which unit or units is to be approved. In the latter two cases, the second part of the parameter is set to one of the following two groups:

  1. ADT, DAC, FacMan, FacultyBoard, FEC, FRC,
  2. CPE, CSE, FIT, GCO, IMS, ITW, MMS, SBS
indicating for the first group, the appropriate approval authority, and for the second group, the appropriate school approval authority.

9.1 doApprove: What Approvals are Possible for this User?

<doApprove: show approvals options 77> =
print $auth->header(), $auth->start_html(-title=>'Infotech Unit Approvals', -BGCOLOR=>'#f0fff0'), $auth->h1('Infotech Unit Avatar: Approvals Page'), $auth->startform('post',"$SCRIPT"), $auth->p; if (-f "$SUBMISSIONS/$UnitCode.xml") { <doApprove: collect approvals data 78> if (%posn || %subj) { <doApprove: items can be approved 79> } else { print "Hello, $Editor. "; print "There are no items you have authority to approve"; } } else { print "There is no description for unit $UnitCode"; } print $auth->endform, $auth->end_html;
Chunk referenced in 76

Generate the stub form that identifies what approvals may be given by this person (the Editor) for this unit (UnitCode). The permissions are given by the file $APPROVALS, specified below.

The two parameters passed to the approval script proper are the approval capability, and the date. See below for why.

<doApprove: collect approvals data 78> =
open APPRO,"<$APPROVALS" or die "No Approvals file"; my %posn; my %subj; while (<APPRO>) { s/(.*)://; my $person = $1; if ($person eq $Editor) { foreach $posn (split(' ',$_)) { if ($posn=~s/^=//) {$subj{$posn} = 't';} else {$posn{$posn} = "t";} } } } if ($TESTING) {print DEBUG %subj,",",%posn,"\n";} close APPRO;
Chunk referenced in 77

Read the following file in to determine who has what approvals capabilities. Build a hash array indexed on approval capability for just the person identified as the Editor. The actual value stored in this hash is irrelevant, it is the keys that are the important data.

If the line in the approvals file contains an entry preceded by an equals sign, then this person is also able to give school approval for units prefixed by the value following the equals sign. For example, the =CSE flag gives authority to give school approval for all CSE units.

<doApprove: items can be approved 79> =
print "$Editor, you are able to approve ", "the following items for unit ", $UnitCode,":",$auth->p; my $SchoolCode = 0; foreach $posn (keys(%subj)) { if ($UnitCode=~/$posn/) { print $auth->submit('approve','SELECT '.$posn.' School'); print $auth->textfield('school','School Information',60); $SchoolCode = $posn; print "<P>If giving School approval, "; print "you must replace `School Information' with the date, "; print "meeting number or URL of the relevant School approval "; print "process</P>"; } } foreach $posn (keys(%posn)) { print $auth->p; print $auth->submit('approve','SELECT '.$posn); } $Date=$TimeStamp; #`/bin/date "+%d %b %Y"`; print $auth->hidden('date',$Date), $auth->hidden('school',$SchoolCode), $auth->hidden('Editor',$Editor), $auth->hidden('UnitCode',$UnitCode);
Chunk referenced in 77

We have some valid items that can be approved by this person. Generate welcome message, and list all the approval options.

School approval is the first to be processed. This is indicated by finding entries in the subj hash array (The 3 letter school/unit prefix is used as the key.)

Then each non-school approval is listed. These are simpler in the sense that they do not require any ancillary information, and hence are just buttons with no text fields.

If school approval was indicated, print some help text.

Finally generated hidden fields to pass over essential data to the approval script. Invoke the next stage, which is selection of the unit to approve.

Show the unit descriptions links that can be approved.

"MonAtar-IT.appr" 80 =
Annabelle McDougall:FacultyBoard Christopher Avram:ADT FEC DAC FacultyBoard =CSE =FIT Christabel Gonsalvez:=IMS =MIS Geraldine D'Costa:FEC FacultyBoard Des Casey:=CPE Don Schauder:FRC Guojun Lu:=GCO =FIT John Betts:=BUS John Hurst:ADT FEC DAC FacultyBoard FRC Resources =CSE =FIT Kerry Tanner:=IMS =MIS Kim Styles:=GCO Leisa McGuinness:=CPE Lindsay Smith:=MMS Liz Kendall:FRC =CPE Madhusudan Chetty:=GCO Marguerite Jones-Roberts:FRC Muhamed Bekir:Resources Pang Hiew:=CSE =BUS =ITW Ralph Gillon:FEC FacultyBoard FRC Ronald Pose:=CSE =FIT Sue Gleeson:FEC FacMan FacultyBoard Trudi Robinson:=IMS =MIS Velika Raicevic:FRC
"MonAtar-Bus.appr" 81 =
Sally Joy2:ADT FEC DAC FacultyBoard FRC
"MonAtar-Med.appr" 82 =
Tony Luff2:ADT FEC DAC FacultyBoard FRC

The name of each person able to give approvals appears first on each line, separated from the approval level indicators by a colon. Multiple approval indicators are blank separated.

"MonAtar-IT-sbs.adr" 83 =
John.Betts@infotech.monash.edu.au Kate.Smith@infotech.monash.edu.au Anne.Parr@infotech.monash.edu.au Peter.Lawrence@infotech.monash.edu.au Dineli.Mather@infotech.monash.edu.au Caitlin.Slattery@infotech.monash.edu.au Judy.Backhouse@infotech.monash.edu Hiew.Pang.Leang@busit.monash.edu.my Elsa.Phung@busit.monash.edu.my Grace.Bol@infotech.monash.edu.au
"MonAtar-IT-csse.adr" 84 =
education@csse.monash.edu.au
"MonAtar-IT-gscit.adr" 85 =
ml-edu@www.gscit.monash.edu.au
"MonAtar-IT-mum.adr" 86 =
sec@infotech.monash.edu.my
"MonAtar-IT-sims.adr" 87 =
simsedco@sims.monash.edu.au
"MonAtar-IT-sms.adr" 88 =
smseduc@infotech.monash.edu.au
"MonAtar-IT-snc.adr" 89 =
Des.Casey@infotech.monash.edu.au Liz.Kendall@infotech.monash.edu.au Leisa.McGuinness@infotech.monash.edu.au

I haven't worked out how best to handle school level approvals yet, since these will require some way of working from unit code to school, and from school to person. The latter part is more straightforward - I expect to be able to use a list of FEC voting members to determine that.

9.2 doApprove: Select Unit(s) to Approve

<doApprove: select unit for approval 90> =
my $approvaltype = $1; my $flag="V"; print $auth->header(), $auth->start_html(-title=>'Infotech Unit Approvals', -BGCOLOR=>'#f0fff0'), $auth->h1('Infotech Unit Avatar: Approvals Page'), $auth->startform('post',"$SCRIPT"), $auth->p; print $auth->p, "$Editor, you can give $approvaltype ". "approval to the following units (most recent first)"; print $auth->p; if ($approvaltype=~/^(.*) School/) { $flag = "M"; $SchoolCode = $1; if ($TESTING) { print $auth->p,"Got SchoolCode of $SchoolCode in select"; } } elsif ($approvaltype=~/FEC/) { $flag="S" } elsif ($approvaltype=~/FacultyBoard/) { $flag="E" } else { $flag="*" } print $auth->p; <doApprove: list valid units 91> print $auth->hidden('date',$Date), $auth->hidden('school',$SchoolCode), $auth->hidden('Editor',$Editor), $auth->hidden('UnitCode',$UnitCode); print $auth->p; print $auth->submit('approve','APPROVE '.$approvaltype); print $auth->endform, $auth->end_html;
Chunk referenced in 76

At this stage, the user has clicked a button indicating what approval they wish to offer, so now we must find out what unit or units they wish to give that approval to. Run through all the units they can approve, marking them all available to approve. The user can then deselect any not approved, and then completes the process by clicking the final approve button.

<doApprove: list valid units 91> =
my $dir="$SUBMISSIONS/archive"; my @units; opendir(ARCHIVE,$dir); @archfiles=grep(!/^\.\.?$/,readdir(ARCHIVE)); foreach $f (@archfiles) { if ($f =~ /^$UnitCode-[0-9]+-$flag/) { unshift(@units,$f); } } closedir ARCHIVE; print $auth->radio_group(-name=>'whichUnit', -values=>\@units, -linebreak=>'true'); print $auth->p,"\n";
Chunk referenced in 90

9.3 doApprove: Give Approval to Unit

<doApprove: give approval to unit 92> =
my $approve=$1; my $schoolinfo=$auth->param('school'); my $other=""; my $VersionComment="$approve Approval"; my $fullunit = $auth->param('whichUnit'); print $auth->header(); print $auth->start_html('test'), $auth->h1("Approvals Information for $fullunit"); if ($approve=~/School/) {$approve='School';} if ($approve=~/FRC/) { $approve='Other'; $other="FRC Approved/Noted "; $VersionComment="$other"; } getDocument(0,0);
Chunk referenced in 76
Chunk defined in 92,93,94,95,96,97

Collect the parameters and setup the approval information. FRC approval is treated as a special case, since it does not have a separate unit description field. Then get the unit description document to operate upon. This creates a working copy in the temporary directory.

<doApprove: give approval to unit 93> =
$xsl="$XMLPAGE/MonAtar-appr.xsl"; $src="$SUBMISSIONS/archive/$fullunit"; $dest="$TMP/$UnitCode-appr.xml"; $erf="$TMP/$UnitCode-appr.ers"; $date=$timestamp; $parms="$XP FIA$approve \"'$other$date ($EscEditor)'\""; $parms.=" $XP Approve \"'$approve'\""; $parms.=" $XP VersionComment \"'$VersionComment'\""; $parms.=" $XP Editor \"'$EscEditor'\""; #$date=`/bin/date "+%d %b %Y %H:%M"`; chop($date); $parms.=" $XP Date \"'$date'\""; $parms.=" $XP School \"'$schoolinfo'\""; $cmd="$XSLTPROC $parms $xsl $src >$dest 2>$erf"; `$cmd`;
Chunk referenced in 76
Chunk defined in 92,93,94,95,96,97

Setup all the xsltproc commands to process the document, and add the approval information. Then process the document, using the MonAtar-appr.xsl XSLT transformer script.

<doApprove: give approval to unit 94> =
print DEBUG $cmd,"\n"; open ERRS,"<$erf"; $errs=""; print "<PRE>\n$cmd\n"; while (<ERRS>) {print;$errs.=$_;} print "</PRE>\n"; close ERRS;
Chunk referenced in 76
Chunk defined in 92,93,94,95,96,97

Print any error messages generated.

<doApprove: give approval to unit 95> =
if ($approve=~/School/ && $schoolinfo=~/^School Information$/) { my $msg="<P><B>You haven't entered the school approval information.\n"; $msg.="Please click the back button and complete the ". "missing information.</B></P>"; print $msg; $errs.=$msg; }
Chunk referenced in 76
Chunk defined in 92,93,94,95,96,97

Check that school information has been entered, if giving school approval.

<doApprove: give approval to unit 96> =
if (!$errs) { my %approvalworkflow = ('School','S','FEC','E','FacultyBoard','A'); my $flag = $approvalworkflow{$approve}; if (!$flag) { $fullunit=~/.*-(.)$/; $flag=$1; } print $auth->p, "$approve Approval ($flag) given by $Editor on $date ", $auth->p; rename $dest,$src; `cp -p $src $SUBMISSIONS/$UnitCode.xml`; $FullUnitCode="$UnitCode-$timestamp-$flag"; my $arc = "$SUBMISSIONS/archive/$FullUnitCode"; $xsl = "$XMLPAGE/sanitiseV2.xsl"; $cmd = "$XSLTPROC $xsl $src >$arc 2>$erf"; print DEBUG $cmd,`$cmd`; print $auth->a({-href=>"$SCRIPT?UnitCode=$FullUnitCode"}, "View the approved unit"); my ($adr,$subj,$msg); # compute $adr by grabbing ProposerEMail field $subj = "[MonAtar] $UnitCode InfoTech Unit Submission (Approval)"; $msg = "$UnitCode has been given $approve Approval. View at\n\n"; $msg.= " $SCRIPT?UnitCode=$FullUnitCode\n\n"; if ($approve=~/School/) { $msg.= "The school comment is: $schoolinfo\n"; } getLatestApproved($UnitCode); if ($ApprovedVersion) { $msg.="You can compare this with the latest (Faculty) approved "; $msg.="version by clicking\n\n"; $msg.=" $SCRIPT?". "compare=compare&BaseCode=$ApprovedVersion". "&UnitCode=$FullUnitCode\n\n"; } print $auth->p; $adr = "ajh\@csse.monash.edu.au"; &sendmail($adr,$subj,$msg); print "Emailed $adr approval status\n"; my @adrs = split(',',$FECEOFF); foreach $adr (@adrs) { &sendmail($adr,$subj,$msg); print "Emailed $adr approval status
\n"; } }
Chunk referenced in 76
Chunk defined in 92,93,94,95,96,97

Stamp approved by copying approved document to base directory, and archiving a sanitised version.

<doApprove: give approval to unit 97> =
unlink $ers; print $auth->endform, $auth->end_html;
Chunk referenced in 76
Chunk defined in 92,93,94,95,96,97

And clean up.

The interface to this script is through the two parameters approve and date, supplied by the description-approval form described in the previous subsection.

9.4 The Approval XML Translation Rules

To add approvals to the master unit XML file, we run an XSLT translation over it, translating from XML to XML. Hence many of the templates in this ruleset are effectively idempotent, and the (currently) seven approval capabilities each have a CLI parameter to pass in any updated values.

The final template is a "catch-all" template. It copies through unchanged any other elements and their tags.

(File has been moved to a separate file.)

10. Review a Unit Description

10.1 doReview: start a review template

<subroutines 98> =
sub doReview { doLogOperation("doReview"); $UnitCode=~tr/a-z/A-Z/; $src="$SUBMISSIONS/$UnitCode.xml"; if (! -f $src) { <doReview: no unit description file 99> } else { <doReview: process unit description file 100> } }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doReview is responsible for collecting the nominated unit description document, and processing it using xsltproc under the stylesheet MakeReviewForm.xsl. This generates an html page that the user can edit and submit, using ReviewSubmit.

<doReview: no unit description file 99> =
$TITLE="Infotech Unit Avatar: Unit Review Failure"; printError('Missing Document', "<P>There is no Unit Description for \"<B>$UnitCode</B>\".</P>". "<P>You need to write one of these before you can complete ". "the review. Go to the avatar home page and click EDIT ". "Description and follow the instructions there.</P>");
Chunk referenced in 98
<doReview: process unit description file 100> =
$xsl = "$XMLPAGE/MakeReviewForm.xsl"; $dest="$TMP/$UnitCode-rev.xml"; $erf="$TMP/$UnitCode-rev.stderr"; $datetime=$TimeStamp; $datetime="$XP DateAndTime \"'$datetime'\""; $Editor="$given $surname"; $editor="$XP Editor \"'$EscEditor'\""; $unit="$XP UnitCode \"'$UnitCode'\""; $staff="$XP Staff \"'$Staff'\""; $school="$XP School \"'$School'\""; $parms="$datetime $editor $unit $staff $school"; $cmd="$XSLTPROC $parms -o $dest $xsl $src 2>$erf"; `$cmd`; print DEBUG $cmd; $err = ""; open ERR,"<$erf"; while (<ERR>) {$err.=$_}; close ERR; if ($err) { $TITLE="Infotech Unit Avatar: Unit Review Failure"; &printHtmlHeaders; <doReview: handle errors 102> } else { <doReview: make review edit page 101> }
Chunk referenced in 98
<doReview: make review edit page 101> =
$xsl = "$XMLPAGE/Review2html.xsl"; $src="$TMP/$UnitCode-rev.xml"; $dest="$TMP/$UnitCode-rev.html"; $change="$XP ViewOrEdit \"'Edit'\""; $server="$XP Server \"'$SCRIPT'\""; $parms="$datetime $editor $unit $change $server"; $cmd="$XSLTPROC $parms -o $dest $xsl $src 2>$erf"; `$cmd`; print DEBUG $cmd; $err = ""; open ERR,"<$erf"; while (<ERR>) {$err.=$_}; close ERR; if ($err) { $TITLE="Infotech Unit Avatar: Unit Review Failure"; &printHtmlHeaders; <doReview: handle errors 102> } else { $TITLE="Infotech Unit Avatar: Unit Review Page"; &printHtmlHeaders; print "$Editor,$School,$Staff,$Faculty<P>\n"; # use the resultant HTML file as returned page open NEW,"<$dest"; while (<NEW>) {print;} close NEW; } #unlink $src,$dest,$erf;
Chunk referenced in 100
<doReview: handle errors 102> =
$err=~s/&/&amp;/g; $err=~s/</&lt;/g; print "<P>doReview: There was an error in translating the source file \n"; print "<TT>$TMP/$UnitCode.xml</TT>.\n"; print "Here is the output that was generated.\n"; print "If you cannot interpret this, please contact John Hurst.<P>\n"; print "<P><B>Command:</B></P>\n"; print "<PRE>\n"; print "$EditOrView\n"; print "$cmd\n"; print "<PRE>\n"; print "<P><B>Output:</B></P>\n"; print "</PRE>\n"; print "$err\n"; print "</PRE>\n"; print "\n";
Chunk referenced in 100 101

There were errors. Before we display the error file, we munge out all ampersands into ampersand entities, and all less than signs into less than entities.

10.2 doReviewSubmit: submit a unit review

Parms: /---------\ see list ---------->| MonAtar | below \---------/ | V +-----------------------------------+ | $TMP/$UnitCode-$timestamp-rev.xml | +-----------------------------------+ | V +-----------------+ /----------\ | Review2html.xsl |---->| xsltproc | +-----------------+ \----------/ | V / \ /OK?\ no \ /------> Error, Translation \ / | yes V +------------------------------------+ | $TMP/$UnitCode-$timestamp-rev.html | +------------------------------------+ | V display this file copy $TMP/review.xml to | V +------------------------------+ | reviews/$UnitCode-$timestamp | +------------------------------+ delete TMP files

The following parameters are passed to MonAtar via the UnitCode-rev.html script generated in doReview. These are used to generate the temporary file $UnitCode-$timestamp-rev.xml. NOTE: We must avoid conflict with concurrent review instantiations. We try to do this by timestamping each review, but the conflict is still possible.

AssAccurate DelURL OutFeedbackData
AssAlign Editor OutIssues
AssFeedbackData GeneralCommentsData OutIssuesData
AssFeedback ObjCorrect OutMonitor
AssMarks ObjFit OutMonitorData
AssObjectives ObjGAAware ReviewFeedbackData
AssReliable ObjGAIdentified ReviewerRelation
AssSchemes ObjSpread School
AssValid ObjWkWeight Staff
DelInTime OutAddressed UnitCode
DelInTimeData OutAddressedData UnitCoordinator
DelTimeTable OutFeedback UnitName
<subroutines 103> =
sub revEntry1 { my ($ind,$el,$val)=(shift,shift,shift); my ($parm)=($auth->param($val)); $parm=~s/&/&amp;/g; print XML " ",'<',$el,'>'; print XML $parm; print XML " ",'</',$el,'>',"\n"; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

revEntry1 handles elements of the form:

<$el>$val<$el/>

Note the subtlety in the substitions into parm. The match is against raw ampersands, which must be replaced by escaped ampersands. But the code itself is in an ampersand sensitive environment, so the raw code must also escape ampersands! (This is not necessarily apparent in the document, due to the different escaping mechanisms for HTML and TeX.)

<subroutines 104> =
sub revEntry2 { my ($ind,$el,$val)=(shift,shift,shift); my ($parm)=($auth->param($val)); $parm=~s/&/&amp;/g; print XML " ",'<',$el," yesno=\""; print XML $parm; print XML "\"/>\n"; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

revEntry2 handles elements of the form:

<$el yesno="$val"/>

<subroutines 105> =
sub revEntry3 { my ($ind,$el,$val,$data)=(shift,shift,shift,shift); my ($parm1)=($auth->param($val)); $parm1=~s/&/&amp;/g; my ($parm2)=($auth->param($data)); $parm2=~s/&/&amp;/g; print XML " ",'<',$el," yesno=\""; print XML $parm1; print XML "\">"; print XML $parm2; print XML '</',$el,">\n"; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

revEntry3 handles elements of the form:

<$el yesno="$val">$data<$el/>

<subroutines 106> =
sub doReviewSubmit { doLogOperation("doReviewSubmit"); my $revsrc="$TMP/$UnitCode-$timestamp-rev.xml"; open XML,">$revsrc" or die "Cannot open review document"; print XML "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"; print XML "<!DOCTYPE ReviewV1 PUBLIC \"-//MONASH-CSSE//DTD ". "ReviewV1 1.0//EN\" \"/ReviewV1.dtd\">\n"; print XML "<ReviewV1 xmlns:xi=\"http://www.w3.org/2001/XInclude\">\n"; print XML " <DateAndTime>",$TimeStamp,"</DateAndTime>\n"; print XML " <ReviewerName relation=\"", $auth->param('ReviewerRelation'),"\">", $auth->param('Editor'),"</ReviewerName>\n"; revEntry1(2,'ReviewerStaff','Staff'); revEntry1(2,'ReviewerSchool','School'); revEntry1(2,'UnitCode','UnitCode'); revEntry1(2,'UnitName','UnitName'); print XML " <UnitCoordinator>",$auth->param('UnitCoordinator'), "</UnitCoordinator>\n"; print XML " <UnitCoordEMail/>\n"; print XML " <UnitObjectives>\n"; revEntry2(4,'ObjCorrect','ObjCorrect'); revEntry2(4,'ObjContent','ObjContent'); print XML " <ObjWorkload>\n"; revEntry2(6,'ObjWkWeight','ObjWkWeight'); revEntry2(6,'ObjSpread','ObjSpread'); revEntry2(6,'ObjFit','ObjFit'); print XML " </ObjWorkload>\n"; print XML " <ObjGradAttrs>\n"; print XML " <ObjGAIdentified yesno=\"", $auth->param('ObjGAIdentified'), "\"/>\n"; print XML " <ObjGAAware yesno=\"",$auth->param('ObjGAAware'),"\"/>\n"; print XML " </ObjGradAttrs>\n"; print XML " </UnitObjectives>\n"; print XML " <UnitOutcomes>\n"; revEntry3(2,'OutMonitor','OutMonitor','OutMonitorData'); revEntry3(2,'OutIssues','OutIssues','OutIssuesData'); revEntry3(2,'OutFeedback','OutFeedback','OutFeedbackData'); print XML " <OutFBAware yesno=\"", $auth->param('OutFBAware'),"\"/>\n"; revEntry3(2,'OutAddressed','OutAddressed','OutAddressedData'); print XML " </UnitOutcomes>\n"; print XML " <Delivery>\n"; print XML " <DelTeachMethods yesno=\"",$auth->param('DelTeachMethods'), "\"/>\n"; print XML " <DelContentExp yesno=\"",$auth->param('DelContentExp'), "\"/>\n"; print XML " <DelAssessExp yesno=\"",$auth->param('DelAssessExp'), "\"/>\n"; print XML " <DelTeachMethods yesno=\"",$auth->param('DelTeachMethods'), "\"/>\n"; print XML " <DelTimeTable yesno=\"",$auth->param('DelTimeTable'), "\"/>\n"; revEntry1(4,'DelURL','DelURL'); revEntry3(2,'DelInTime','DelInTime','DelInTimeData'); print XML " </Delivery>\n"; print XML " <Assessment>\n"; revEntry3(4,'AssFeedback','AssFeedback','AssFeedbackData'); print XML " <AssFeedUseful yesno=\"", $auth->param('AssFeedUseful'),"\"/>\n"; print XML " <AssObjectives yesno=\"",$auth->param('AssObjectives'), "\"/>\n"; print XML " <AssAlign yesno=\"",$auth->param('AssAlign'),"\"/>\n"; print XML " <AssValid yesno=\"",$auth->param('AssValid'),"\"/>\n"; print XML " <AssReliable yesno=\"",$auth->param('AssReliable'),"\"/>\n"; print XML " <AssSchemes yesno=\"",$auth->param('AssSchemes'),"\"/>\n"; print XML " <AssMarks yesno=\"",$auth->param('AssMarks'),"\"/>\n"; print XML " <AssAccurate yesno=\"", $auth->param('AssAccurate'),"\"/>\n"; print XML " <Satisfaction yesno=\"", $auth->param('Satisfaction'),"\"/>\n"; print XML " </Assessment>\n"; print XML " <General>\n"; revEntry1(4,'Comments','GeneralCommentsData'); revEntry1(4,'ReviewFeedback','ReviewFeedbackData'); print XML " </General>\n"; print XML " <ResourceReqs/>\n"; print XML "</ReviewV1>\n"; close XML; print header('text/html'); $xsl="$XMLPAGE/Review2html.xsl"; $dest="$TMP/$UnitCode-$timestamp-rev.html"; $erf="$TMP/$UnitCode-$timestamp-rev.stderr"; $datetime=$TimeStamp; $datetime="$XP DateAndTime \"'$datetime'\""; if (defined($Editor)) {$editor="$XP Editor \"'$EscEditor'\""} else {$editor=""}; $unit="$XP UnitCode \"'$UnitCode'\""; $view="$XP ViewOrEdit \"'View'\""; $parms="$datetime $editor $unit $view"; $cmd="$XSLTPROC $parms -o $dest $xsl $revsrc 2>$erf"; `$cmd`; $err = ""; open ERR,"<$erf"; while (<ERR>) {$err.=$_}; close ERR; if ($err) { <doView: handle errors 39> } else { print "<P>Your review has been succesfully submitted. ". "Here is what you have entered:</P>\n"; my $reviewpage="reviews"; if ($Staff=~/Student/) {$reviewpage="reviews/students";} $cmd="cp $revsrc $SUBMISSIONS/$reviewpage/$UnitCode-$timestamp"; `$cmd`; # use the resultant HTML file as returned page open NEW,"<$dest"; while (<NEW>) {print;} close NEW; } #unlink $revsrc,$dest,$erf; }
Chunk referenced in 12
Chunk defined in 22,23,24,25,26,27,28,29,30,33,34,36,40,42,50,53,60,61,65,66,69,74,76,98,103,104,105,106

doReviewSubmit is responsible for building a completed review from data supplied through parameters to this avatar call. This is done by building the xml document from scratch.

11. XSL Stylesheets and Transformers

11.1 MakeReviewForm.xsl An XSL script to Generate a Review Form

The script creates an XML review form from the data supplied in a unit description document.

The MakeReviewForm.xsl documentation is maintained separately.

11.2 mergexml.xsl Merge Updates with Description

Combine edited field and Old XML to make new a XML Description file.

The mergexml.xsl documentation is maintained separately.

11.3 MonAtar-appr.xsl Merge Approval Information with Description

Combine edited field and Old XML to make new a XML Description file.

The MonAtar-appr.xsl documentation is maintained separately.

11.4 V1toV2.xsl Converter Script

This XSLT transformer script converts unit descriptions from version 1 format to version 2. It has been renamed from old2new.xsl to V1toV2.xsl.

The V1toV2.xsl documentation is maintained separately.

11.5 xml2html.xsl Convert XML Description to HTML

Converts an XML description file to HTML. There are two main forms: view and edit. View gives plain HTML, suitable for printing; Edit gives buttons to click to update the various editable fields. The choice is set by a parameter.

This has been moved to a separate file.

11.6 xml2txt.xsl Convert XML Description to Plain Text

This has been moved to a separate file.

12. TODO

20041119:103111
Add a disestablishment field with date
20041112:110259
Add a "Date to Take Effect" popup when submitting for approval.
20040730:145937
When an edit is made to a description that is part way through the approval process, there needs to be some sort of warning. Such edits should only be made by the approving authority to update the latest version.
20040519:143534
Add item to unit review about addition of Inclusive Practices awareness in unit contexts.
20040512:081040
(Chris Gonsalvez) Some way of defining the 700 character limit for unit summaries. Also a section called Resources or Notes (not subject to the approval process), which the School could use for more detailed information about the unit. This would help with trying to keep all the information about a unit in one central source. Email reply to Chris, 20040512:

The second one is easy, and I'll add it asap. The monatar is currently undergoing testing for the new approval process, so it will need to wait until that is finished (no promises on ETA, I'm afraid).

The first will require a little more thought, and possibly input from other users. I'm reluctant to add another field to do this, because it then becomes a source of potential inconsistency, if edited without due regard to the open length field. Possibilities that occur to me include:

  1. separate field (potential inconsistencies)
  2. limit current field (transition issues)
  3. warn user when field is longer than 700 chars (my pref)
  4. XML markup in current field to show what is omitted in short version (ideal, but needs user training)
  5. other suggestions?
20040503:135320
Auto inform library whenever a reading list is changed.
20030616:223549
Need better change mechanism: check out sanitising that highlights differences
20030616:223244
Mode for single section edit, which does auto version history
20030605:170128
Move the version history stuff on home page to end of home page
20030326:112216
Follow through on the six areas identified in CHEQ Unit Review Guidelines. In broad terms, Units will be evaluated in relation to 6 key areas
Content
Content and objectives
Teaching
Teaching methods
Assessment
Assessment procedures
Workloads
Student workload and study behaviour
Evaluation
Routine evaluation
Expertise
Expertise of teaching staff
20020124:083406
Design Version Control interface
20020124:083539
add StartPoint mechanism to always display description at edit point.
20020322:125308
Generate the prohibitions matrix; change wording of submit statement; include subject description in email; define interest groups
20020516:155005
Add Telecommunications and Networks to classification
20020522:094705
Fix home page so that code,enter does a view rather than give an error

13. DONE

14. Indices

14.1 Files

File Name Defined in
MonAtar 12
MonAtar-Bus.appr 81
MonAtar-IT-csse.adr 84
MonAtar-IT-gscit.adr 85
MonAtar-IT-mum.adr 86
MonAtar-IT-sbs.adr 83
MonAtar-IT-sims.adr 87
MonAtar-IT-sms.adr 88
MonAtar-IT-snc.adr 89
MonAtar-IT.appr 80
MonAtar-Med.appr 82

14.2 Chunks

Chunk Name Defined in Used in
context variables 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 13
doApprove: collect approvals data 78 77
doApprove: give approval to unit 92, 93, 94, 95, 96, 97 76
doApprove: items can be approved 79 77
doApprove: list valid units 91 90
doApprove: select unit for approval 90 76
doApprove: show approvals options 77 76
doChange: print helpful hints 51 50
doChange: warn about editing ObjText 52 50
doCompare: handle errors 68 66
doCompare: set xsltproc parameters 67 66
doEdit: change Editor level 46 45
doEdit: do NOT have a Version Comment 44
doEdit: handle errors 49 45
doEdit: have a Version Comment 45 42
doEdit: helpful text 47 46
doEdit: parameter debugging 43 42
doEdit: set xsltproc parameters 48 45
doReview: handle errors 102 100, 101
doReview: make review edit page 101 100
doReview: no unit description file 99 98
doReview: process unit description file 100 98
doShow: compute time ranges 71 69
doShow: generate form components 70 69
doShow: generate table of units 72 69
doShow: print Approval page explanation 75 72
doShow: version differences 73 69
doSubmit: get document values 62 61
doSubmit: get submission data 64 63
doSubmit: send mail to SEC members 63 61
doUpdate: call the xslt processor 57 53
doUpdate: check revised document 59 53
doUpdate: convert plain text to XML 55 53
doUpdate: error reporting 58 53, 60, 61
doUpdate: parameter debugging 54 53, 60, 61
doUpdate: sanitise newtext 56 53
doView: handle errors 39 36, 106
doView: set stylesheet according to version 38 37
doView: set xsltproc parameters 37 36
get parameters 15, 16, 17 12
getDocument: and sanitise it 41 40
grabPersonData: set submission details for InfoTech 31 30
grabPersonData: set submission details for no Faculty 32 30
illegal parameters 21 12
initialization 13, 14 12
login to avatar 19 12
perform avatar authentication 20 12
re-enter avatar 18 12, 12
selection page text 35 34
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12
subroutines 22, 23, 24, 25, 26, 27, 28, 29, 30, 33, 34, 36, 40, 42, 50, 53, 60, 61, 65, 66, 69, 74, 76, 98, 103, 104, 105, 106 12

14.3 Identifiers

Identifier Defined in Used in

Document History

20020208:074656 ajh 2.0 First documented version: basic (edit, change, update) profile working
20020322:125406 ajh 2.1 many updates; add prohibitions matrix (et al) TODOs
20020322:171540 ajh 2.1.1 Added button to bottom of view page to enter avatar
20020325:152654 ajh 2.2.0 Dual editing mode installed
20020327:221227 ajh 2.2.1 added Classification in View and Edit modes
20020331:214023 ajh 2.2.2 updated MonAtar-version.xsl (not in this litprog) to handle save of attributes
20020403:170511 ajh 2.2.3 first on-line version 2
20020416:175300 ajh 2.2.4 fix mergexml.xsl: not copying attributes
20020506:124920 ajh 2.3.0 fix xml2txt.xsl to use new markup rules (rtf based)
20020531:090141 ajh 2.3.1 fix Proposer insertion, and chopping last char bug
20020612:090340 ajh 2.3.2 remove xml2html.xsl file from this document
20020613:095104 ajh 2.3.3 remove mergexml.xsl file from this document
20020624:115207 ajh 2.3.4 reformat date in Version History
20020805:122352 ajh 2.3.5 add non-ASCII exclusion
20020805:150916 ajh 2.3.6 remove ajh from submission emailing
20020815:095048 ajh 2.3.7 Change Objective titles
20020816:154511 ajh 2.3.8 Add direct jump link on edit page
20020905:160429 ajh 2.3.9 Add check in doUpdate to ensure xml errors not saved
20020925:163831 ajh 2.3.10 Add sanitise stage in getDocument
20021011:103207 ajh 2.3.11 Add check in approve that Unit Description exists, and Add ability for all approvers to approve FIT units (done by adding fields to MonAtar-appr.txt)
20021016:161838 ajh 2.4.0 Adds the unit review capability
20021021:171541 ajh 2.4.1 Adds general cooments and review comments sections
20021022:094714 ajh 2.4.2 Add separate create description button
20021022:120546 ajh 2.4.3 Add student authentication and functions
20021024:151538 ajh 2.4.4 Remove multiple update conflict in routine doReviewSubmit, and document
20021028:103902 ajh 2.4.5 Add link to Review explanations
20021030:110244 ajh 2.4.6 Add field about effect of unit change upon credit assessments
20030228:170810 ajh 2.4.7 remove -ba flag from sendmail
20030311:151932 ajh 2.4.8 add XMLPAGE to ReviewV1.dtd address
20030315:170519 ajh 2.5.0 Add image buttons to home page, and obsolete Objective Text field (which gets deleted if it is edited).
20030324:172248 ajh 2.5.1 Restructured editing page to separate version comment from expert/novice selection.
20030417:143818 ajh 2.5.2 fix bug in email extraction of UnitName and UnitSummary
20030430:093852 ajh 2.5.3 remove temporary files where possible (mainly in doUpdate)
20030430:151559 ajh 2.5.4 Added IS classifications to xml2html.xsl (no change to this file)
20030515:105345 ajh 2.5.5 fixed bug with saving cookie for reentry (must trim blanks)
20030515:114212 ajh 2.5.6 added Don't Know buttons to review page (not in this file)
20030525:163936 ajh 2.6.0 First version under xlp, start to add multi-faculty mechanisms
20030605:163847 ajh 2.6.1 basic multi-faculty mechanisms working
20030805:092750 ajh 2.6.2 add FEC review WP recommendations
20030806:090112 ajh 2.6.3 clean up new format; fix bugs in sanitiseV2 and xml2html
20030807:095606 ajh 2.6.4 add reasons for change
20030807:161730 ajh 2.6.5 revise submission process
20030811:094615 ajh 2.6.6 change approval time stamp to exclude colon
20030815:141937 ajh 2.6.7 updated school approvals and circulation data
20030826:113513 ajh 2.6.8 updated school approvals and circulation data
20030916:124251 ajh 2.6.9 replaced Monash Identity under instruction from Brand Police
20030924:134126 ajh 2.6.10 allow multiple FEC EOs, separated by commas
20031009:115201 ajh 2.6.11 Fix bug with School information extraction in grabPersonData
20031017:083126 ajh 2.6.12 Change xsl access through catalog, add changedate, start altering xml2html.xsl to use streamlined call templates and add change dates
20031020:152619 ajh 2.6.13 automatically add version history comment about fields modified
20031021:170158 ajh 2.6.14 fix bug where approved descriptions not getting -A timestamp
20031023:113838 ajh 2.6.15 Add view date restriction
20031024:121538 ajh 2.6.16 Add approval unit list
20031125:101329 ajh 2.6.17 reply-to field in sent email now points to editor (but note: it will not work yet for non-infotech users)
20040319:085013 ajh 2.6.18 update date fields in show all descriptions
20040322:092152 ajh 2.7.0 revise approval work flow, add new SHOW APROVALS
20040516:145812 ajh 2.7.1 add button on successful save to view edited unit (thanks to Shane Moore for this suggestion)
20040517:114008 ajh 2.7.2 Changed SHOW APPROVAL latest save colour to yellow
20040524:203146 ajh 2.7.3 Add compare link to submit mailouts
20040525:155453 ajh 2.7.4 Add student reviews
20040526:101132 ajh 2.7.5 Fix double question mark bug in email message for doSubmit
20040526:160202 ajh 2.7.6 sort compare list
20040526:160240 ajh 2.7.7 doCompare does not require authentication
20040531:162734 ajh 2.7.8 First working version with student reviews
20040602:142027 ajh 2.7.9 Fix bug with sorted lists of units
20040611:082134 ajh 2.7.10 remove Denise Martin from mailing list, minor edits, including IT.appr list to remove obsolete school codes
20040728:132457 ajh 2.7.11 Add MIS to school codes, and change link display in SHOW descriptions when no previously approved unit.
20040730:084412 ajh 2.7.12 Change Roger Silberberg to Judy Backhouse in SBS list
20040812:151420 ajh 2.7.13 make email subject line consistent with approval
20040814:172839 ajh 2.7.14 add logging of operations
20040823:095412 ajh 2.8.0 add processing of recommended reading field
20040920:125031 ajh 2.8.1 add Geraldine D'Costa to mailing list
20041015:114520 ajh 2.8.2 fix bug that did not escape quotes in Editor name
20041019:125409 ajh 2.8.3 make sure data entered in reviews has ampersands escaped
20041026:171548 ajh 2.8.4 fixed bug in SHOW descriptions that appended line info from previous line
20041201:114325 ajh 2.8.5 minor changes for migration to faculty server