Index: openacs-4/packages/curriculum-tracker/curriculum-tracker.info
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/curriculum-tracker.info,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/curriculum-tracker.info	4 Apr 2006 06:50:02 -0000	1.1
@@ -0,0 +1,27 @@
+<?xml version="1.0"?>
+<!-- Generated by the OpenACS Package Manager -->
+
+<package key="curriculum-tracker" url="http://openacs.org/repository/apm/packages/curriculum-tracker" type="apm_application">
+    <package-name>Curriculum Tracker</package-name>
+    <pretty-plural>Curriculum Trackers</pretty-plural>
+    <initial-install-p>f</initial-install-p>
+    <singleton-p>f</singleton-p>
+    
+    <version name="0.1d" url="http://openacs.org/repository/download/apm/curriculum-tracker-0.1d.apm">
+        <owner url="mailto:ncarroll@ee.usyd.edu.au">Nick Carroll</owner>
+        <summary>Application for tracking your progress through a curriculum.</summary>
+        <description format="text/html">This application imports an XML document from Curriculum Central that contains all courses for a degree.  The user will then be able to tick off completed courses, and manage their progress through a degree.
+
+This package is intended as a package for dotFOLIO.  When used with dotFOLIO, the user will be able to clip blog postings and files to a course.  Thereby giving context to work that had been completed for a course.</description>
+        <maturity>0</maturity>
+
+        <provides url="curriculum-tracker" version="0.1d"/>
+
+        <callbacks>
+        </callbacks>
+        <parameters>
+            <parameter datatype="string"  min_n_values="1"  max_n_values="1"  name="CurriculumTrackerCSS"  default="/resources/curriculum-tracker/main-portal.css" description="Specify the location of a CSS file to use for Curriculum Tracker's colour scheme."/>
+        </parameters>
+
+    </version>
+</package>
Index: openacs-4/packages/curriculum-tracker/catalog/curriculum-tracker.en_US.ISO-8859-1.xml
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/catalog/curriculum-tracker.en_US.ISO-8859-1.xml,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/catalog/curriculum-tracker.en_US.ISO-8859-1.xml	4 Apr 2006 06:50:02 -0000	1.1
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<message_catalog package_key="curriculum-tracker" package_version="0.1d" locale="en_US" charset="ISO-8859-1">
+
+  <msg key="key">Key</msg>
+  <msg key="level">Level</msg>
+  <msg key="description">Description</msg>
+  <msg key="very_low">Very Low</msg>
+  <msg key="low">Low</msg>
+  <msg key="moderate">Moderate</msg>
+  <msg key="high">High</msg>
+  <msg key="very_high">Very High</msg>
+  <msg key="uos_details">Unit of Study Details</msg>
+  <msg key="accumulated_development_of_graduate_attributes">Accumulated development of graduate attributes.</msg>
+  <msg key="graduate_attributes_progress_caption">Chart conveys your progress in developing graduate attributes from completed Units of Study (UoS).</msg>
+  <msg key="view_progress">View Progress</msg>
+  <msg key="status_of_completed_uos_key">The following colour coded boxes indicate whether a Unit of Study (UoS) has been completed or not.</msg>
+  <msg key="status_changed_to_complete">Status changed to Complete</msg>
+  <msg key="status_changed_to_incomplete">Status changed to Incomplete</msg>
+  <msg key="change_to_complete">Change to Complete</msg>
+  <msg key="change_to_incomplete">Change to Incomplete</msg>
+  <msg key="status_complete">Status: Complete</msg>
+  <msg key="status_incomplete">Status: Incomplete</msg>
+  <msg key="complete">Complete</msg>
+  <msg key="incomplete">Incomplete</msg>
+  <msg key="requirement">Requirement</msg>
+  <msg key="name">Name</msg>
+  <msg key="code">Code</msg>
+  <msg key="year_offered">Year Offered</msg>
+  <msg key="session">Session</msg>
+  <msg key="lecturer">Lecturer</msg>
+  <msg key="objectives">Aims and Objectives</msg>
+  <msg key="outcomes">Learning Outcomes</msg>
+  <msg key="syllabus">Syllabus</msg>
+  <msg key="view_details">View Details</msg>
+  <msg key="confirm_delete_degree">Are you sure you want to delete the degree from the list?</msg>
+  <msg key="degree_deleted">Degree deleted.</msg>
+  <msg key="delete">Delete</msg>
+  <msg key="no_file_found_for_upload">No file found for upload.</msg>
+  <msg key="import_succeeded">Import succeeded.</msg>
+  <msg key="import_failed">Import failed.</msg>
+  <msg key="upload_curriculum_file">Upload curriculum file.</msg>
+  <msg key="help_upload_curriculum_file">Upload a curriculum file that was exported from Curriculum Central.</msg>
+  <msg key="import_degree">Import Degree</msg>
+  <msg key="select_a_curriculum_to_view">Select a curriculum to view:</msg>
+  <msg key="degree">Degree</msg>
+  <msg key="degrees">Degrees</msg>
+  <msg key="unit_of_study">Unit of Study</msg>
+  <msg key="units_of_study">Units of Study</msg>
+  <msg key="graduate_attribute">Graduate Attribute</msg>
+  <msg key="graduate_attributes">Graduate Attributes</msg>
+
+</message_catalog>
Index: openacs-4/packages/curriculum-tracker/sql/postgresql/curriculum-tracker-create.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/sql/postgresql/curriculum-tracker-create.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/sql/postgresql/curriculum-tracker-create.sql	4 Apr 2006 06:50:02 -0000	1.1
@@ -0,0 +1,499 @@
+--
+-- packages/curriculum-tracker/sql/curriculum-tracker-create.sql
+--
+-- @author Nick Carroll (nick.c@rroll.net)
+-- @creation-date 2006-03-31
+-- @cvs-id $Id: curriculum-tracker-create.sql,v 1.1 2006/04/04 06:50:02 ncarroll Exp $
+--
+--
+
+--
+-- Degree
+--
+create function inline_0 ()
+returns integer as '
+begin
+    PERFORM acs_object_type__create_type (
+    ''ct_degree'',                    	-- object_type
+    ''#curriculum-tracker.degree#'',    -- pretty_name
+    ''#curriculum-tracker.degrees#'',   -- pretty_plural
+    ''acs_object'',                	-- supertype
+    ''ct_degree'', 	                -- table_name
+    ''degree_id'',	                -- id_column
+    null,              		        -- package_name
+    ''f'',                         	-- abstract_p
+    null,                          	-- type_extension_table
+    ''ct_degree_stream__name''         	-- name_method
+    );
+
+    return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0 ();
+
+
+create table ct_degree (
+    degree_id    	integer 
+                   	constraint ct_degree_degree_id_fk
+                   	references acs_objects(object_id) 
+                   	constraint ct_degree_degree_id_pk
+                   	primary key,
+    owner_id       	integer
+                   	constraint ct_degree_owner_id_fk
+                   	references users(user_id)
+                   	constraint ct_degree_owner_id_nn
+                   	not null,
+    faculty_name   	varchar (512),
+    department_name 	varchar (512),
+    stream_name		varchar (512),
+    package_id     	integer
+                   	constraint ct_degree_package_id_fk
+                   	references apm_packages(package_id)
+                   	constraint ct_degree_package_id_nn
+                   	not null
+);
+
+
+select define_function_args('ct_degree__new','degree_id,owner_id,faculty_name,department_name,stream_name,package_id,creation_date;now,creation_user,creation_ip,context_id');
+
+create function ct_degree__new (integer,integer,varchar,varchar,varchar,integer,timestamptz,integer,varchar,integer)
+returns integer as '
+declare
+    p_degree_id                  alias for $1;        -- default null
+    p_owner_id                   alias for $2;
+    p_faculty_name               alias for $3;
+    p_department_name            alias for $4;
+    p_stream_name                alias for $5;
+    p_package_id		 alias for $6;
+    p_creation_date              alias for $7;        -- default now()
+    p_creation_user              alias for $8;        -- default null
+    p_creation_ip                alias for $9;        -- default null
+    p_context_id                 alias for $10;        -- default null
+
+    v_degree_id                ct_degree.degree_id%TYPE;
+begin
+
+    v_degree_id := acs_object__new (
+        p_degree_id,
+        ''ct_degree'',
+        p_creation_date,
+        p_creation_user,
+        p_creation_ip,
+        p_context_id
+    );
+
+    insert into ct_degree (
+        degree_id,
+        owner_id,
+        faculty_name,
+        department_name,
+        stream_name,
+        package_id
+    ) values (
+        v_degree_id,
+        p_owner_id,
+        p_faculty_name,
+	p_department_name,
+	p_stream_name,
+        p_package_id
+    );
+
+    PERFORM acs_permission__grant_permission(
+          v_degree_id,
+          p_creation_user,
+          ''read''
+    );
+
+    PERFORM acs_permission__grant_permission(
+          v_degree_id,
+          p_creation_user,
+          ''write''
+    );
+
+    return v_degree_id;
+
+end;' language 'plpgsql';
+
+
+select define_function_args('ct_degree__del','degree_id');
+
+create function ct_degree__del (integer)
+returns integer as '
+declare
+    p_degree_id                alias for $1;
+    v_rec                      record;
+begin
+    -- Delete all UoS associated with degree.
+    for v_rec in
+        select uos_id from ct_degree_uos_map where degree_id = p_degree_id
+    loop
+        PERFORM ct_uos__del (v_rec.uos_id);
+    end loop;
+
+    delete from acs_permissions
+           where object_id = p_degree_id;
+
+    delete from ct_degree
+           where degree_id = p_degree_id;
+
+    raise NOTICE ''Deleting degree...'';
+    PERFORM acs_object__delete(p_degree_id);
+
+    return 0;
+
+end;' language 'plpgsql';
+
+
+select define_function_args('ct_degree_stream__name','degree_id');
+
+create function ct_degree_stream__name (integer)
+returns varchar as '
+declare
+    p_degree_id      alias for $1;
+    v_stream_name    ct_degree.stream_name%TYPE;
+begin
+    select stream_name into v_stream_name
+        from ct_degree
+        where degree_id = p_degree_id;
+
+    return v_stream_name;
+end;
+' language 'plpgsql';
+
+
+--
+-- UoS
+--
+create function inline_0 ()
+returns integer as '
+begin
+    PERFORM acs_object_type__create_type (
+    ''ct_uos'',                    	-- object_type
+    ''#curriculum-tracker.unit_of_study#'',    -- pretty_name
+    ''#curriculum-tracker.units_of_study#'',   -- pretty_plural
+    ''acs_object'',                	-- supertype
+    ''ct_uos'', 	                -- table_name
+    ''uos_id'',  	                -- id_column
+    null,              		        -- package_name
+    ''f'',                         	-- abstract_p
+    null,                          	-- type_extension_table
+    ''ct_uos__name''             	-- name_method
+    );
+
+    return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0 ();
+
+
+create table ct_uos (
+    uos_id      	integer 
+                   	constraint ct_uos_uos_id_fk
+                   	references acs_objects(object_id) 
+                   	constraint ct_uos_uos_id_pk
+                   	primary key,
+    name		varchar (512),
+    code		varchar (512),
+    year		varchar (512),
+    session             varchar (512),
+    requirement         varchar (512),
+    lecturer		varchar (512),
+    objectives	  	text,
+    outcomes		text,
+    syllabus		text,
+    completed_p		boolean,
+    package_id     	integer
+                   	constraint ct_uos_package_id_fk
+                   	references apm_packages(package_id)
+                   	constraint ct_uos_package_id_nn
+                   	not null
+);
+
+
+select define_function_args('ct_uos__new','uos_id,name,code,year,session,requirement,lecturer,objectives,outcomes,syllabus,completed_p,package_id,creation_date;now,creation_user,creation_ip,context_id');
+
+create function ct_uos__new (integer,varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,varchar,integer,timestamptz,integer,varchar,integer)
+returns integer as '
+declare
+    p_uos_id                     alias for $1;        -- default null
+    p_name                       alias for $2;
+    p_code                       alias for $3;
+    p_year                       alias for $4;
+    p_session                    alias for $5;
+    p_requirement		 alias for $6;
+    p_lecturer			 alias for $7;
+    p_objectives	   	 alias for $8;
+    p_outcomes			 alias for $9;
+    p_syllabus			 alias for $10;
+    p_package_id		 alias for $11;
+    p_creation_date              alias for $12;        -- default now()
+    p_creation_user              alias for $13;        -- default null
+    p_creation_ip                alias for $14;        -- default null
+    p_context_id                 alias for $15;        -- default null
+
+    v_uos_id                	 ct_uos.uos_id%TYPE;
+    v_completed_p	    	 ct_uos.completed_p%TYPE;
+begin
+
+    v_uos_id := acs_object__new (
+        p_uos_id,
+        ''ct_uos'',
+        p_creation_date,
+        p_creation_user,
+        p_creation_ip,
+        p_context_id
+    );
+
+    -- Set completed_p to 0 by default.
+    v_completed_p := 0;
+
+    insert into ct_uos (
+        uos_id,
+	name,
+	code,
+	year,
+	session,
+	requirement,
+	lecturer,
+	objectives,
+	outcomes,
+	syllabus,
+	completed_p,
+        package_id
+    ) values (
+        v_uos_id,
+        p_name,
+        p_code,
+        p_year,
+	p_session,
+	p_requirement,
+	p_lecturer,
+	p_objectives,
+	p_outcomes,
+	p_syllabus,
+	v_completed_p,
+        p_package_id
+    );
+
+    PERFORM acs_permission__grant_permission(
+          v_uos_id,
+          p_creation_user,
+          ''read''
+    );
+
+    PERFORM acs_permission__grant_permission(
+          v_uos_id,
+          p_creation_user,
+          ''write''
+    );
+
+    return v_uos_id;
+
+end;' language 'plpgsql';
+
+
+select define_function_args('ct_uos__del','uos_id');
+
+create function ct_uos__del (integer)
+returns integer as '
+declare
+    p_uos_id                alias for $1;
+    v_rec                   record;
+begin
+    -- Delete all GA associated with UoS.
+    for v_rec in
+        select ga_id from ct_uos_ga_map where uos_id = p_uos_id
+    loop
+        PERFORM ct_ga__del (v_rec.ga_id);
+    end loop;
+
+    -- Delete degree to uos mapping.
+    delete from ct_degree_uos_map where uos_id = p_uos_id;
+
+    delete from acs_permissions
+           where object_id = p_uos_id;
+
+    delete from ct_uos
+           where uos_id = p_uos_id;
+
+    raise NOTICE ''Deleting UoS...'';
+    PERFORM acs_object__delete(p_uos_id);
+
+    return 0;
+
+end;' language 'plpgsql';
+
+
+select define_function_args('ct_uos__name','uos_id');
+
+create function ct_uos__name (integer)
+returns varchar as '
+declare
+    p_uos_id      alias for $1;
+    v_name    ct_uos.name%TYPE;
+begin
+    select name into v_name
+        from ct_uos
+        where uos_id = p_uos_id;
+
+    return v_name;
+end;
+' language 'plpgsql';
+
+
+create table ct_degree_uos_map (
+    degree_id		integer,
+    uos_id		integer
+);
+
+--
+-- Graduate Attributes
+--
+create function inline_0 ()
+returns integer as '
+begin
+    PERFORM acs_object_type__create_type (
+    ''ct_ga'',                    	-- object_type
+    ''#curriculum-tracker.graduate_attribute#'',    -- pretty_name
+    ''#curriculum-tracker.graduate_attributes#'',   -- pretty_plural
+    ''acs_object'',                	-- supertype
+    ''ct_ga'',   	                -- table_name
+    ''ga_id'',  	                -- id_column
+    null,              		        -- package_name
+    ''f'',                         	-- abstract_p
+    null,                          	-- type_extension_table
+    ''ct_ga__name''             	-- name_method
+    );
+
+    return 0;
+end;' language 'plpgsql';
+
+select inline_0 ();
+drop function inline_0 ();
+
+
+create table ct_ga (
+    ga_id      	        integer 
+                   	constraint ct_ga_ga_id_fk
+                   	references acs_objects(object_id) 
+                   	constraint ct_ga_ga_id_pk
+                   	primary key,
+    name		varchar (512),
+    level		integer,
+    description		text,
+    package_id     	integer
+                   	constraint ct_ga_package_id_fk
+                   	references apm_packages(package_id)
+                   	constraint ct_ga_package_id_nn
+                   	not null
+);
+
+
+select define_function_args('ct_ga__new','ga_id,name,level,description,package_id,creation_date;now,creation_user,creation_ip,context_id');
+
+create function ct_ga__new (integer,varchar,integer,varchar,integer,timestamptz,integer,varchar,integer)
+returns integer as '
+declare
+    p_ga_id                      alias for $1;        -- default null
+    p_name                       alias for $2;
+    p_level                      alias for $3;
+    p_description                alias for $4;
+    p_package_id		 alias for $5;
+    p_creation_date              alias for $6;        -- default now()
+    p_creation_user              alias for $7;        -- default null
+    p_creation_ip                alias for $8;        -- default null
+    p_context_id                 alias for $9;        -- default null
+
+    v_ga_id                ct_ga.ga_id%TYPE;
+begin
+
+    v_ga_id := acs_object__new (
+        p_ga_id,
+        ''ct_ga'',
+        p_creation_date,
+        p_creation_user,
+        p_creation_ip,
+        p_context_id
+    );
+
+    insert into ct_ga (
+        ga_id,
+	name,
+	level,
+	description,
+        package_id
+    ) values (
+        v_ga_id,
+        p_name,
+        p_level,
+        p_description,
+        p_package_id
+    );
+
+    PERFORM acs_permission__grant_permission(
+          v_ga_id,
+          p_creation_user,
+          ''read''
+    );
+
+    PERFORM acs_permission__grant_permission(
+          v_ga_id,
+          p_creation_user,
+          ''write''
+    );
+
+    return v_ga_id;
+
+end;' language 'plpgsql';
+
+
+select define_function_args('ct_ga__del','ga_id');
+
+create function ct_ga__del (integer)
+returns integer as '
+declare
+    p_ga_id                alias for $1;
+begin
+    -- Delete uos to ga mapping.
+    delete from ct_uos_ga_map where ga_id = p_ga_id;
+
+    delete from acs_permissions
+           where object_id = p_ga_id;
+
+    delete from ct_ga
+           where ga_id = p_ga_id;
+
+    raise NOTICE ''Deleting Graduate Attribute...'';
+    PERFORM acs_object__delete(p_ga_id);
+
+    return 0;
+
+end;' language 'plpgsql';
+
+
+select define_function_args('ct_ga__name','ga_id');
+
+create function ct_ga__name (integer)
+returns varchar as '
+declare
+    p_ga_id      alias for $1;
+    v_name       ct_ga.name%TYPE;
+begin
+    select name into v_name
+        from ct_ga
+        where ga_id = p_ga_id;
+
+    return v_name;
+end;
+' language 'plpgsql';
+
+
+--
+-- Map Graduate Attribute to UoS.
+--
+create table ct_uos_ga_map (
+    uos_id		integer,
+    ga_id		integer
+);
Index: openacs-4/packages/curriculum-tracker/sql/postgresql/curriculum-tracker-drop.sql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/sql/postgresql/curriculum-tracker-drop.sql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/sql/postgresql/curriculum-tracker-drop.sql	4 Apr 2006 06:50:02 -0000	1.1
@@ -0,0 +1,80 @@
+--
+-- packages/curriculum-tracker/sql/curriculum-tracker-create.sql
+--
+-- @author Nick Carroll (nick.c@rroll.net)
+-- @creation-date 2006-03-31
+-- @cvs-id $Id: curriculum-tracker-drop.sql,v 1.1 2006/04/04 06:50:02 ncarroll Exp $
+--
+
+
+drop table ct_uos_ga_map;
+
+drop function ct_ga__name (integer);
+
+drop function ct_ga__del (integer);
+
+drop function ct_ga__new (
+	integer,
+	varchar,
+	integer,
+	varchar,
+	integer,
+	timestamptz,
+	integer,
+	varchar,
+integer);
+
+drop table ct_ga;
+
+drop table ct_degree_uos_map;
+
+drop function ct_uos__name (integer);
+
+drop function ct_uos__del (integer);
+
+drop function ct_uos__new (
+	integer,
+	varchar,
+	varchar,
+	varchar,
+	varchar,
+	varchar,
+	varchar,
+	varchar,
+	varchar,
+	varchar,
+	integer,
+	timestamptz,
+	integer,
+	varchar,
+	integer
+);
+
+drop table ct_uos;
+
+drop function ct_degree_stream__name (integer);
+
+drop function ct_degree__del (integer);
+
+drop function ct_degree__new (
+	integer,
+	integer,
+	varchar,
+	varchar,
+	varchar,
+	integer,
+	timestamptz,
+	integer,
+	varchar,
+	integer
+);
+
+drop table ct_degree;
+
+DELETE FROM acs_objects WHERE object_type='ct_ga';
+DELETE FROM acs_objects WHERE object_type='ct_uos';
+DELETE FROM acs_objects WHERE object_type='ct_degree';
+
+select acs_object_type__drop_type ('ct_ga', 'f');
+select acs_object_type__drop_type ('ct_uos', 'f');
+select acs_object_type__drop_type ('ct_degree', 'f');
Index: openacs-4/packages/curriculum-tracker/tcl/curriculum-tracker-procs-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/tcl/curriculum-tracker-procs-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/tcl/curriculum-tracker-procs-postgresql.xql	4 Apr 2006 06:50:02 -0000	1.1
@@ -0,0 +1,19 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="curriculum_tracker::parse_degree_file.map_uos_to_degree">
+     <querytext>
+       INSERT INTO ct_degree_uos_map (degree_id, uos_id) 
+       VALUES (:degree_id, :uos_id);
+     </querytext>
+   </fullquery>
+
+   <fullquery name="curriculum_tracker::parse_degree_file.map_ga_to_uos">
+     <querytext>
+       INSERT INTO ct_uos_ga_map (uos_id, ga_id) VALUES (:uos_id, :ga_id);
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/tcl/curriculum-tracker-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/tcl/curriculum-tracker-procs.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/tcl/curriculum-tracker-procs.tcl	4 Apr 2006 06:50:02 -0000	1.1
@@ -0,0 +1,125 @@
+ad_library {
+
+    Curriculum Tracker Library
+
+    @creation-date 2006-04-02
+    @author Nick Carroll <ncarroll@ee.usyd.edu.au>
+    @cvs-id bug-tracker-procs.tcl,v 1.13.2.7 2003/03/05 18:13:39 lars Exp
+
+}
+
+namespace eval curriculum_tracker {}
+
+
+ad_proc curriculum_tracker::parse_degree_file {
+    -xmlfile
+    {-package_id {}}
+    {-user_id {}}
+} {
+    Parses a degree file, and imports the curriculum information into the
+    database.
+
+    @param file_location Location of the degree file.
+    @param package_id The package ID for an instance of Curriculum Tracker.
+    @return Returns 1 if import succeeded, otherwise 0 is returned.
+} {
+    db_transaction {
+	if { $package_id == "" } {
+	    set package_id [ad_conn package_id]
+	}
+	
+	if { $user_id == "" } {
+	    set user_id [ad_conn user_id]
+	}
+	
+	# Parser
+	dom parse [::tDOM::xmlReadFile $xmlfile] document
+	
+	# DOM document = DOM root
+	$document documentElement root
+	
+	# Get degree details
+	set faculty [[$root selectNodes {/degree/faculty[1]}] text]
+	set department [[$root selectNodes {/degree/department[1]}] text]
+	set stream [[$root selectNodes {/degree/stream[1]}] text]
+	
+	set degree_id [package_instantiate_object \
+			   -var_list [list [list package_id $package_id] \
+					  [list owner_id $user_id] \
+					  [list faculty_name $faculty] \
+					  [list department_name $department] \
+					  [list stream_name $stream]] \
+			   ct_degree]
+	
+	# Parse uos node
+	foreach uos_node [$root selectNodes {/degree/uos}] {
+	    set requirement [$uos_node getAttribute requirement]
+	    set year [$uos_node getAttribute year]
+	    set session [$uos_node getAttribute session]
+	    
+	    set name [[$uos_node selectNodes {name[1]}] text]
+	    set code [[$uos_node selectNodes {code[1]}] text]
+	    set objectives [[$uos_node selectNodes {objectives[1]}] text]
+	    set outcomes [[$uos_node selectNodes {outcomes[1]}] text]
+	    set syllabus [[$uos_node selectNodes {syllabus[1]}] text]
+	    set lecturer [[$uos_node selectNodes {lecturer[1]}] text]
+	    
+	    set uos_id [package_instantiate_object \
+			    -var_list [list [list package_id $package_id] \
+					   [list name $name] \
+					   [list code $code] \
+					   [list year $year] \
+					   [list session $session] \
+					   [list requirement $requirement] \
+					   [list lecturer $lecturer] \
+					   [list objectives $objectives] \
+					   [list outcomes $outcomes] \
+					   [list syllabus $syllabus]] \
+			    ct_uos]
+	    
+	    # Map uos_id to degree_id
+	    db_dml map_uos_to_degree {}
+	    
+	    # Parse graduateAttributes node
+	    foreach ga_node [$uos_node selectNodes \
+				 {graduateAttributes/attribute}] {
+		set name [[$ga_node selectNodes {name[1]}] text]
+		set level [[$ga_node selectNodes {level[1]}] text]
+		set description [[$ga_node selectNodes {description[1]}] text]
+		
+		set ga_id [package_instantiate_object \
+			       -var_list [list [list package_id $package_id] \
+					  [list name $name] \
+					  [list level $level] \
+					  [list description $description]] \
+			       ct_ga]
+		
+		# Map ga_id to uos_id
+		db_dml map_ga_to_uos {}
+	    }
+	}
+	
+	return 1
+    }
+}
+
+ad_proc curriculum_tracker::ga_level_pretty_name {
+    -level
+} {
+    Returns the pretty name for a given graduate attribute.
+
+    @param level The graduate attribute level.
+    @return Returns the pretty name for the given graduate attribute level.
+} {
+    if { $level == 1 } {
+	return [_ curriculum-tracker.very_low]
+    } elseif { $level == 2 } {
+	return [_ curriculum-tracker.low]
+    } elseif { $level == 3 } {
+	return [_ curriculum-tracker.moderate]
+    } elseif { $level == 4 } {
+	return [_ curriculum-tracker.high]
+    }
+
+    return [_ curriculum-tracker.very_high]
+}
\ No newline at end of file
Index: openacs-4/packages/curriculum-tracker/www/degree-progress-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/degree-progress-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/degree-progress-postgresql.xql	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,26 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="distinct_ga_name">
+     <querytext>
+       SELECT DISTINCT name FROM ct_ga WHERE package_id = :package_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="sum_level">
+     <querytext>
+       SELECT SUM(ga.level)
+       FROM ct_ga ga, ct_uos_ga_map ug, ct_degree_uos_map du, ct_uos u
+       WHERE ga.ga_id = ug.ga_id
+       AND du.uos_id = ug.uos_id
+       AND du.degree_id = :degree_id
+       AND u.uos_id = du.uos_id
+       AND ga.name = :name
+       AND u.completed_p
+       AND ga.package_id = :package_id
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/www/degree-progress.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/degree-progress.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/degree-progress.adp	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,40 @@
+<master src="resources/main-portal">
+<property name="title">@page_title;noquote@</property>
+<property name="context">@context;noquote@</property>
+<property name="header_stuff">
+<link rel="stylesheet" type="text/css" href="/resources/curriculum-tracker/curriculum-tracker.css" media="all">
+</property>
+
+
+<center>
+<div id="ct-barchart-container">
+
+<table cellspacing="0" cellpadding="0">
+      <caption align="top">#curriculum-tracker.graduate_attributes_progress_caption#<br /><br /></caption>
+      <tr>
+        <th scope="col"><span >#curriculum-tracker.graduate_attribute#</span> </th>
+        <th scope="col"><span >#curriculum-tracker.accumulated_development_of_graduate_attributes#</span> </th>
+
+      </tr>
+
+      <multiple name="graduate_attributes">
+      <tr>
+	<if @graduate_attributes.rownum@ eq 1>
+	<td class="first">@graduate_attributes.name@</td>
+        <td class="value first"><img src="/resources/curriculum-tracker/images/bar.png" alt="" width="@graduate_attributes.width@" height="16" />@graduate_attributes.level@</td>
+	</if>
+	<elseif @graduate_attributes.rownum@ eq @graduate_attributes:rowcount@>
+	<td>@graduate_attributes.name@</td>
+        <td class="value last"><img src="/resources/curriculum-tracker/images/bar.png" alt="" width="@graduate_attributes.width@" height="16" />@graduate_attributes.level@</td>
+	</elseif>
+	<else>
+	<td>@graduate_attributes.name@</td>
+        <td class="value"><img src="/resources/curriculum-tracker/images/bar.png" alt="" width="@graduate_attributes.width@" height="16" />@graduate_attributes.level@</td>
+	</else>
+      </tr>
+      </multiple>
+
+    </table>
+
+</div>
+</center>
Index: openacs-4/packages/curriculum-tracker/www/degree-progress.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/degree-progress.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/degree-progress.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,34 @@
+ad_page_contract {
+    Page for displaying progress for a specific degree.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2005-11-20
+    @cvs-id $Id: degree-progress.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    degree_id:integer
+}
+
+set package_id [ad_conn package_id]
+
+set page_title "[_ curriculum-tracker.progress]"
+set context $page_title
+
+template::multirow create graduate_attributes name level width
+
+db_foreach distinct_ga_name {} {
+    set sum_level [db_string sum_level {} -default "0"]
+    
+    # Use a multiplier to scale the results.
+    set multiplier 10
+
+    if { $sum_level == ""} {
+	set sum_level 0
+    }
+    set width [expr {$sum_level * $multiplier}]
+
+    template::multirow append graduate_attributes $name $sum_level $width
+}
+
+template::multirow sort graduate_attributes -increasing name
+
+ad_return_template
Index: openacs-4/packages/curriculum-tracker/www/del-degree-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/del-degree-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/del-degree-postgresql.xql	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,48 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="select_uos">
+     <querytext>
+       SELECT uos_id FROM ct_degree_uos_map WHERE degree_id = :degree_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="select_ga">
+     <querytext>
+       SELECT ga_id FROM ct_uos_ga_map WHERE uos_id = :uos_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="delete_uos">
+     <querytext>
+       SELECT ct_uos__del (:uos_id)
+     </querytext>
+   </fullquery>
+
+   <fullquery name="delete_uos_map">
+     <querytext>
+       DELETE FROM ct_degree_uos_map WHERE uos_id = :uos_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="delete_ga">
+     <querytext>
+       SELECT ct_ga__del (:ga_id)
+     </querytext>
+   </fullquery>
+
+   <fullquery name="delete_ga_map">
+     <querytext>
+       DELETE FROM ct_uos_ga_map WHERE ga_id = :ga_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="delete_degree">
+     <querytext>
+       SELECT ct_degree__del (:degree_id)
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/www/del-degree.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/del-degree.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/del-degree.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,24 @@
+ad_page_contract {
+    Page for importing a degree.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2006-04-02
+    @cvs-id $Id: del-degree.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    degree_id
+    {return_url "."}
+}
+
+auth::require_login
+
+set package_id [ad_conn package_id]
+set user_id [ad_conn user_id]
+
+permission::require_write_permission -object_id $degree_id -party_id $user_id
+
+db_transaction {
+    # Delete the degree.
+    db_exec_plsql delete_degree {}
+}    
+
+ad_returnredirect -message "[_ curriculum-tracker.degree_deleted]" $return_url
Index: openacs-4/packages/curriculum-tracker/www/import-degree-2.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/import-degree-2.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/import-degree-2.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,29 @@
+ad_page_contract {
+    Page for importing a degree.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2006-04-02
+    @cvs-id $Id: import-degree-2.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    curriculum_file
+    {curriculum_file.tmpfile}
+    return_url
+}
+
+set package_id [ad_conn package_id]
+set owner_id [ad_conn user_id]
+
+if { $curriculum_file == ""} {
+    ad_returnredirect -message [_ curriculum-tracker.no_file_found_for_upload] $return_url
+}
+
+set failed_p [ catch {curriculum_tracker::parse_degree_file -xmlfile ${curriculum_file.tmpfile}} errMsg]
+
+if { $failed_p } {
+    set message "[_ curriculum-tracker.import_failed]: $errMsg"
+    ns_log Error "Curriculum Tracker: $errMsg"
+} else {
+    set message [_ curriculum-tracker.import_succeeded]
+}
+
+ad_returnredirect -message $message $return_url
Index: openacs-4/packages/curriculum-tracker/www/import-degree.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/import-degree.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/import-degree.adp	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,5 @@
+<master src="resources/main-portal">
+<property name="title">@page_title;noquote@</property>
+<property name="context">@context;noquote@</property>
+
+<formtemplate id="import_degree"></formtemplate>
\ No newline at end of file
Index: openacs-4/packages/curriculum-tracker/www/import-degree.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/import-degree.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/import-degree.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,27 @@
+ad_page_contract {
+    Page for importing a degree.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2006-04-02
+    @cvs-id $Id: import-degree.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    {return_url "."}
+}
+
+set page_title "[_ curriculum-tracker.import_degree]"
+set context [list]
+set package_id [ad_conn package_id]
+set owner_id [ad_conn user_id]
+
+ad_form -cancel_url . -name import_degree -action {import-degree-2} -html {enctype multipart/form-data} -form {
+    {return_url:text(hidden) {value $return_url}}
+    {curriculum_file:file
+	{label "[_ curriculum-tracker.upload_curriculum_file]"}
+	{help_text "[_ curriculum-tracker.help_upload_curriculum_file]"}
+	{html "size 30"}
+    }
+} -after_submit {
+    ad_script_abort
+}
+
+ad_return_template
Index: openacs-4/packages/curriculum-tracker/www/index-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/index-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/index-postgresql.xql	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,14 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="degrees">
+     <querytext>
+       SELECT degree_id, stream_name FROM ct_degree
+       WHERE owner_id = :owner_id
+       AND package_id = :package_id
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/www/index.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/index.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/index.adp	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,26 @@
+<master src="resources/main-portal">
+<property name="title">@page_title;noquote@</property>
+<property name="context">@context;noquote@</property>
+<property name="header_stuff">
+<link rel="stylesheet" type="text/css" href="/resources/curriculum-tracker/curriculum-tracker.css" media="all">
+</property>
+
+<if @imported_degrees_p@>
+#curriculum-tracker.select_a_curriculum_to_view#
+<p />
+<div id="ct-degree-container">
+
+  <ul id="degrees">
+    <multiple name="degrees">
+    <li><span class="label"><a href="@degrees.view_degree_url@">@degrees.stream_name@</a></span><span class="options">[<a href="@degrees.progress_url@">#curriculum-tracker.view_progress#</a>] [<a href="@degrees.del_degree_url@" onclick="return confirm('#curriculum-tracker.confirm_delete_degree#');">#curriculum-tracker.delete#</a>]</span><div class="spacer"></div></li>
+    </multiple>
+  </ul>
+
+</div>
+</if>
+<else>
+No degrees have been imported.
+</else>
+<p />
+
+<a href="import-degree">#curriculum-tracker.import_degree#</a>
Index: openacs-4/packages/curriculum-tracker/www/index.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/index.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/index.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,26 @@
+ad_page_contract {
+    Page for viewing a list of imported curricula.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2006-04-02
+    @cvs-id $Id: index.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+}
+
+set page_title [ad_conn instance_name]
+set context [list]
+set package_id [ad_conn package_id]
+set owner_id [ad_conn user_id]
+
+# Get list of degrees.
+db_multirow -extend { view_degree_url del_degree_url progress_url } degrees degrees {} {
+    set view_degree_url [export_vars -url -base view-degree {degree_id}]
+    set del_degree_url [export_vars -url -base del-degree {degree_id}]
+    set progress_url [export_vars -url -base degree-progress {degree_id}]
+}
+
+set imported_degrees_p 0
+if { [template::multirow size degrees] > 0 } {
+    set imported_degrees_p 1
+}
+
+ad_return_template
Index: openacs-4/packages/curriculum-tracker/www/toggle-uos-status-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/toggle-uos-status-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/toggle-uos-status-postgresql.xql	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,18 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="change_to_incomplete">
+     <querytext>
+       UPDATE ct_uos SET completed_p = 'false' WHERE uos_id = :uos_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="change_to_complete">
+     <querytext>
+       UPDATE ct_uos SET completed_p = 'true' WHERE uos_id = :uos_id
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/www/toggle-uos-status.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/toggle-uos-status.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/toggle-uos-status.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,31 @@
+ad_page_contract {
+    Toggles 
+
+    @param uos_id The ID for the UoS that we want to toggle the status value
+    for.
+    @param completed_p The current status of the given UoS.
+    @param return_url The URL to return to after toggling the UoS status.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2006-04-02
+    @cvs-id $Id: toggle-uos-status.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    uos_id
+    completed_p
+    return_url
+}
+
+set package_id [ad_conn package_id]
+set owner_id [ad_conn user_id]
+
+if { $completed_p } {
+    # Change to incomplete
+    db_dml change_to_incomplete {}
+    set message "[_ curriculum-tracker.status_changed_to_incomplete]"
+} else {
+    # Change to complete
+    db_dml change_to_complete {}
+    set message "[_ curriculum-tracker.status_changed_to_complete]"
+}
+
+ad_returnredirect -message $message $return_url
Index: openacs-4/packages/curriculum-tracker/www/view-degree-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/view-degree-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/view-degree-postgresql.xql	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,23 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="select_degree">
+     <querytext>
+       SELECT stream_name FROM ct_degree WHERE degree_id = :degree_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="select_curriculum">
+     <querytext>
+       SELECT u.uos_id, u.year, u.session, u.code, u.name, u.completed_p
+       FROM ct_degree_uos_map dumap
+       left outer join ct_uos u on (dumap.uos_id = u.uos_id)
+       WHERE dumap.degree_id = :degree_id
+       AND u.package_id = :package_id
+       ORDER BY u.year ASC, u.session ASC, u.code ASC
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/www/view-degree.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/view-degree.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/view-degree.adp	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,55 @@
+<master src="resources/main-portal">
+<property name="title">@page_title;noquote@</property>
+<property name="context">@context;noquote@</property>
+<property name="header_stuff">
+<link rel="stylesheet" type="text/css" href="/resources/curriculum-tracker/curriculum-tracker.css" media="all">
+</property>
+
+
+<div id="ct-map-container">
+
+  <div class="spacer">&nbsp;</div>
+
+  <div id="key">
+    #curriculum-tracker.status_of_completed_uos_key#
+    <ul>
+      <li class="complete">#curriculum-tracker.complete#</li>
+      <li class="incomplete">#curriculum-tracker.incomplete#</li>
+    </ul>
+    <h3>#curriculum-tracker.key#</h3>
+  </div>
+
+  <multiple name="curriculum">
+  <ul class="years">
+    <li>@curriculum.year@</li>
+
+    <ul class="sessions">
+    <group column="year">
+      <li>@curriculum.session@</li>
+
+      <ul id="uos">
+        <group column="ys_group">
+        <if @curriculum.completed_p@>
+	<div class="float complete">
+        </if>
+        <else>
+        <div class="float incomplete">
+        </else>
+          <ul class="info">
+	    <li class="uos-code">@curriculum.code@</li>
+            <li class="uos-name">@curriculum.name@</li>
+          </ul>
+          <ul class="options">
+            <li class="info"><a href="@curriculum.view_uos_url@" class="button">#curriculum-tracker.view_details#</a></li>
+          </ul>
+        </div>
+        </group>
+
+	<div class="spacer">&nbsp;</div>
+      </ul>
+    </group>
+    </ul>
+  </ul>
+  </multiple>  
+
+</div>
Index: openacs-4/packages/curriculum-tracker/www/view-degree.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/view-degree.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/view-degree.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,24 @@
+ad_page_contract {
+    Page for viewing the curriculum for a specific degree.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2006-04-02
+    @cvs-id $Id: view-degree.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    degree_id
+}
+
+set package_id [ad_conn package_id]
+set owner_id [ad_conn user_id]
+
+
+db_multirow -extend { ys_group view_uos_url } curriculum select_curriculum {} {
+    set ys_group "${year}${session}"
+    set view_uos_url [export_vars -url -base view-uos { uos_id }]
+}
+
+set stream_name [db_string select_degree {}]
+set page_title $stream_name
+set context [list $page_title]
+
+ad_return_template
Index: openacs-4/packages/curriculum-tracker/www/view-uos-postgresql.xql
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/view-uos-postgresql.xql,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/view-uos-postgresql.xql	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,38 @@
+<?xml version="1.0"?>
+
+<queryset>
+   <rdbms><type>postgresql</type><version>7.4</version></rdbms>
+
+   <fullquery name="uos_details">
+     <querytext>
+       SELECT uos_id, name, code, year, session, lecturer, objectives,
+           outcomes, syllabus, requirement, completed_p
+       FROM ct_uos
+       WHERE uos_id = :uos_id
+       AND package_id = :package_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="attributes">
+     <querytext>
+       SELECT ga.name AS ga_name, ga.description AS ga_description,
+           ga.level AS ga_level
+       FROM ct_ga ga, ct_uos_ga_map ug
+       WHERE ga.ga_id = ug.ga_id
+       AND uos_id = :uos_id
+       AND package_id = :package_id
+     </querytext>
+   </fullquery>
+
+   <fullquery name="degree_info">
+     <querytext>
+       SELECT DISTINCT d.stream_name AS stream_name, d.degree_id
+       FROM ct_degree d, ct_degree_uos_map du
+       WHERE d.degree_id = du.degree_id
+       AND du.uos_id = :uos_id
+       AND package_id = :package_id
+       LIMIT 1
+     </querytext>
+   </fullquery>
+
+</queryset>
Index: openacs-4/packages/curriculum-tracker/www/view-uos.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/view-uos.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/view-uos.adp	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,56 @@
+<master src="resources/main-portal">
+<property name="title">@page_title;noquote@</property>
+<property name="context">@context;noquote@</property>
+<property name="displayed_object_id">@uos_id;noquote@</property>
+<property name="header_stuff">
+<link rel="stylesheet" type="text/css" href="/resources/curriculum-tracker/curriculum-tracker.css" media="all">
+</property>
+
+
+<div id="ct-status-container">
+
+<if @completed_p@>
+<div class="complete">
+<ul>
+<li>#curriculum-tracker.status_complete#</li>
+<li><a href="@toggle_completed_url@" class="button">#curriculum-tracker.change_to_incomplete#</a></li>
+</ul>
+</div>
+</if>
+<else>
+<div class="incomplete">
+<ul>
+<li>#curriculum-tracker.status_incomplete#</li>
+<li><a href="@toggle_completed_url@" class="button">#curriculum-tracker.change_to_complete#</a></li>
+</ul>
+</div>
+</else>
+</div>
+
+<div id="ct-list-container">
+  <h3>#curriculum-tracker.uos_details#</h3>
+  <table>
+    <multiple name="details">
+    <tr>
+      <td class="label">@details.label;noquote@</td>
+      <td class="value"><if @details.value@ ne "">@details.value;noquote@</if><else>&nbsp;</else></td>
+    </tr>
+    </multiple>
+  </table>
+
+  <h3>#curriculum-tracker.graduate_attributes#</h3>
+  <table>
+    <tr>
+      <th>#curriculum-tracker.name#</th>
+      <th>#curriculum-tracker.level#</th>
+      <th>#curriculum-tracker.description#</th>
+    </tr>
+    <multiple name="attributes">
+    <tr>
+      <td class="label">@attributes.ga_name;noquote@</td>
+      <td class="value"><if @attributes.ga_level@ ne "">@attributes.ga_level;noquote@</if><else>&nbsp;</else></td>
+      <td class="value"><if @attributes.ga_description@ ne "">@attributes.ga_description;noquote@</if><else>&nbsp;</else></td>
+    </tr>
+    </multiple>
+  </table>
+</div>
Index: openacs-4/packages/curriculum-tracker/www/view-uos.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/view-uos.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/view-uos.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,44 @@
+ad_page_contract {
+    Page for displaying details for a specific Unit of Study.
+
+    @author Nick Carroll (nick.c@rroll.net)
+    @creation-date 2005-11-20
+    @cvs-id $Id: view-uos.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+    uos_id:integer
+}
+
+set package_id [ad_conn package_id]
+
+# Retrieve Unit of Study details.
+db_1row uos_details {}
+
+# Create a multirow containing all the UoS details.
+template::multirow create details label value
+
+template::multirow append details [_ curriculum-tracker.name] $name
+template::multirow append details [_ curriculum-tracker.code] $code
+template::multirow append details [_ curriculum-tracker.year_offered] $year
+template::multirow append details [_ curriculum-tracker.session] $session
+template::multirow append details [_ curriculum-tracker.requirement] \
+    $requirement
+template::multirow append details [_ curriculum-tracker.lecturer] $lecturer
+template::multirow append details [_ curriculum-tracker.objectives] $objectives
+template::multirow append details [_ curriculum-tracker.outcomes] $outcomes
+template::multirow append details [_ curriculum-tracker.syllabus] $syllabus
+
+db_multirow attributes attributes {} {
+    set ga_level [curriculum_tracker::ga_level_pretty_name -level $ga_level]
+}
+
+set return_url [export_vars -url -base view-uos { uos_id }]
+set toggle_completed_url [export_vars -url -base toggle-uos-status \
+			      { uos_id completed_p return_url }]
+
+
+db_1row degree_info {}
+set degree_return_url [export_vars -url -base view-degree { degree_id }]
+set page_title "${code} ${name}"
+set context [list [list $degree_return_url $stream_name] $page_title]
+
+ad_return_template
Index: openacs-4/packages/curriculum-tracker/www/resources/curriculum-tracker.css
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/curriculum-tracker.css,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/resources/curriculum-tracker.css	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,261 @@
+.spacer {
+	clear: both;
+}
+
+
+/* Status box */
+
+#ct-status-container {
+	text-align: center;
+	margin: 0px auto;
+	width: 200px;
+	margin-top: 2em;
+	padding-bottom: 1em;
+}
+
+#ct-status-container .complete ul {
+	color: #128812;
+	list-style-type: none;
+	padding: 5px;
+	border: 1px solid #000;
+	font-weight: bold;
+}
+
+#ct-status-container .complete ul li {
+	padding-top: 3px;
+	padding-bottom: 3px;
+}
+
+#ct-status-container .incomplete ul {
+	color: #B91309;
+	list-style-type: none;
+	padding: 5px;
+	border: 1px solid #000;
+	font-weight: bold;
+}
+
+#ct-status-container .incomplete ul li {
+	padding-top: 3px;
+	padding-bottom: 3px;
+}
+
+/* Map Container */
+#ct-map-container {
+
+}
+
+#ct-map-container .spacer {
+	clear: both;
+}
+
+#ct-map-container ul {
+	list-style-type: none;
+	margin-left: 1em;
+	padding: 0px;
+}
+
+#ct-map-container .float {
+	float: left;
+  	width: 120px;
+	height: 113px;
+  	padding: 10px;
+	margin: 1em;
+	border: 1px solid #000;
+}
+
+#ct-map-container .float ul {
+	margin-left: 0;
+}
+
+#ct-map-container .float ul.info {
+	height: 80px;
+	background-color:white;
+}
+
+#ct-map-container .float ul.options {
+	height: 30px;
+}
+
+#ct-map-container .float ul li.uos-code {
+	color: #E88000;
+	text-align: center;
+	font-weight: bold;
+	font-size: 12px;
+	padding: 0px;
+}
+
+#ct-map-container .float ul li.uos-name {
+	margin-top: 5px;
+	color: #4B832E;
+	font-size: 12px;
+	text-align: center;
+	padding: 0px;
+}
+
+#ct-map-container .float ul li.info {
+	color: blue;
+	font-size: 12px;
+	text-align: center;
+	padding: 2px;
+}
+
+#ct-map-container ul.years li {
+	list-style-type: none;
+	color: #686868;
+	font-size: 18px;
+        font-weight: bold;
+}
+
+#ct-map-container ul.sessions li {
+	list-style-type: none;
+	color: #9B9B9B;
+        font-size: 16px;
+        padding-top: 10px;
+        padding-bottom: 6px;
+}
+
+#ct-map-container #key {
+	border: 1px solid #000;
+	width: 60%;
+	margin-bottom: 1em;
+	text-align: center;
+	margin-left: auto;
+	margin-right: auto;
+	padding: 5px;
+}
+
+#ct-map-container #key ul {
+        margin-left: auto;
+        margin-right: auto;
+}
+
+#ct-map-container #key ul li {
+	list-style-type: none;
+	border: 1px solid #000;
+	padding: 3px;
+	margin: 0px;
+	font-size: 10px;
+	font-weight: bold;
+	display: inline;
+}
+
+#ct-map-container #key h3 {
+	clear: left;
+}
+
+#ct-map-container .incomplete {
+	background-color: #FF6666;
+}
+
+#ct-map-container .complete {
+	background-color: #99CCFF;
+}
+
+/* Stream Container */
+#ct-degree-container {
+	margin-left: 30px;
+}
+
+#ct-degree-container ul {
+	margin: 0;
+	padding: 0;
+	list-style-type: none;
+	font-family: verdana, arial, sans-serif;
+}
+
+#ct-degree-container li {
+	margin: 0;
+}
+
+/* Degree */
+#ct-degree-container ul li {
+	color: #000;
+	font-size: 12px;
+	display: block;
+	border-left: 1em solid #686868;
+	border-bottom: 1px solid #686868;
+	padding: 4px 8px;
+	width: 50em;
+	margin-bottom: 5px;
+}
+
+#ct-degree-container ul li span.label {
+	margin-left: 3em;
+	float:left;
+}
+
+#ct-degree-container ul li span.options {
+	float: right;
+}
+
+/* Styles for lists */
+#ct-list-container table {
+	width: 100%;
+}
+
+#ct-list-container table tr td {
+	font-weight: bold;
+	font-size: 12px;
+	padding: 5px 10px 5px 10px;
+	margin: 1px;
+	vertical-align: top;
+}
+
+#ct-list-container table tr td.label {
+	background-color: #CCCCCC;
+	width: 160px;
+}
+
+#ct-list-container table tr td.value {
+	background-color: #F0F0F0;
+}
+
+/* Bar chart */
+/* CSS taken from http://www.standards-schmandards.com/exhibits/barchart/ */
+#ct-barchart-container td.value {
+	background-image: url(/resources/curriculum-tracker/images/gridline58.gif);
+	background-repeat: repeat-x;
+	background-position: left top;
+	border-left: 1px solid #e5e5e5;
+	border-right: 1px solid #e5e5e5;
+	padding:0;
+	border-bottom: none;
+	background-color:transparent;
+}
+
+#ct-barchart-container td {
+	padding: 4px 6px;
+	border-bottom:1px solid #e5e5e5;
+	border-left:1px solid #e5e5e5;
+	background-color:#fff;
+}
+
+#ct-barchart-container td.value img {
+	vertical-align: middle;
+	margin: 5px 5px 5px 0;
+}
+
+#ct-barchart-container th {
+	text-align: left;
+	vertical-align:top;
+}
+
+#ct-barchart-container td.last {
+	border-bottom:1px solid #e5e5e5;
+}
+
+#ct-barchart-container td.first {
+	border-top:1px solid #e5e5e5;
+}
+
+#ct-barchart-container table {
+	background-image:url(/resources/curriculum-tracker/images/bg_fade.png);
+	background-repeat:repeat-x;
+	background-position:left top;
+	width: 33em;
+}
+
+#ct-barchart-container caption {
+	font-size:90%;
+	font-style:italic;
+}
Index: openacs-4/packages/curriculum-tracker/www/resources/main-portal.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/main-portal.adp,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/resources/main-portal.adp	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,34 @@
+<master>
+<property name="title">@title@</property>
+<property name="context">@context;noquote@</property>
+<property name="header_stuff">
+@header_stuff;noquote@
+<link rel="stylesheet" type="text/css" href="@curriculum_tracker_css@" media="all"/>
+</property>
+
+<P>
+<div class="visualClear"></div>
+
+<table id="portal-columns">
+  <tbody>
+    <tr>
+      <td id="portal-column-content">
+        <div class="visualPadding">
+          <div class="documentBorder">
+            <if @admin_p@ eq "1">
+            <div class="portletOptions">
+              @admin_options;noquote@
+            </div>
+	    </if>
+            <div class="portletOptions">
+              @user_options;noquote@
+            </div>
+            <div class="documentContent">
+              <slave>
+            </div>
+          </div>
+        </div>
+      </td>
+    </tr>
+  </tbody>
+</table>
Index: openacs-4/packages/curriculum-tracker/www/resources/main-portal.css
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/main-portal.css,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/resources/main-portal.css	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,39 @@
+.portletOptions {
+    display: inline;
+    font-size: 10px;
+    font-weight: normal;
+    float:right;
+    padding: 1px;
+}
+
+.visualClear {
+    display: block;
+    clear: both;
+}
+
+#portal-columns {
+    width: 100% !important;
+    border-collapse: collapse;
+    border-spacing: 0;
+}
+
+#portal-column-content {
+    vertical-align: top;
+    margin: 0;
+    padding: 0;
+}
+
+/* Padding for the columns */
+#portal-column-content .visualPadding {
+    /*padding: 0em 2em 1em 2em;*/
+    padding: 0em 1em 1em 1em;
+}
+
+.documentBorder {
+    border: 1px solid #666;
+    background: White;
+}
+
+.documentContent {
+    padding: 1em !important;
+}
Index: openacs-4/packages/curriculum-tracker/www/resources/main-portal.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/main-portal.tcl,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ openacs-4/packages/curriculum-tracker/www/resources/main-portal.tcl	4 Apr 2006 06:50:03 -0000	1.1
@@ -0,0 +1,48 @@
+ad_page_contract {
+
+    Simple portal page featuring a main portlet.
+
+    @author  Nick Carroll (nick.c@rroll.net)
+    @creation-date 2005-03-24
+    @cvs-id  $Id: main-portal.tcl,v 1.1 2006/04/04 06:50:03 ncarroll Exp $
+} {
+
+}
+
+
+if { ![info exists title] } {
+    set title {}
+}
+
+if { ![info exists context] } {
+    set context {}
+}
+
+if { ![info exists header_stuff] } {
+    set header_stuff {}
+}
+
+if { ![info exists admin_options] } {
+    set admin_options {}
+}
+
+if { ![info exists staff_options] } {
+    set staff_options {}
+}
+
+if { ![info exists user_options] } {
+    set user_options {}
+}
+
+set user_id [ad_conn user_id]
+
+set package_id [ad_conn package_id]
+
+set admin_p [permission::permission_p -object_id $package_id -privilege admin]
+
+set curriculum_tracker_css [parameter::get_from_package_key \
+				-parameter "CurriculumTrackerCSS" \
+				-package_key "curriculum-tracker" \
+			       -default "/resources/curriculum-tracker/main-portal.css"]
+
+ad_return_template
\ No newline at end of file
Index: openacs-4/packages/curriculum-tracker/www/resources/images/bar.png
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/images/bar.png,v
diff -u
Binary files differ
Index: openacs-4/packages/curriculum-tracker/www/resources/images/bg_fade.png
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/images/bg_fade.png,v
diff -u
Binary files differ
Index: openacs-4/packages/curriculum-tracker/www/resources/images/gridline58.gif
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/curriculum-tracker/www/resources/images/gridline58.gif,v
diff -u
Binary files differ