Index: openacs-4/packages/project-manager/project-manager.info =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/project-manager.info,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/project-manager.info 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,52 @@ + + + + + Project Manager + Project Managers + f + f + + + Jade Rubick + Project management tool for OpenACS + 2005-01-13 + Integrated Bakery Resources + Track tasks, estimates and actual progress for a project. See the <a href="http://openacs.org/projects/dotwrk/project_management/">project page</a> for more information. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Index: openacs-4/packages/project-manager/catalog/project-manager.de_DE.ISO-8859-1.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/catalog/project-manager.de_DE.ISO-8859-1.xml,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/catalog/project-manager.de_DE.ISO-8859-1.xml 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,160 @@ + + + + Aktion + Aktionen + Hinzuf�gen + Subprojekt hinzuf�gen + Beauftragte + Durchschnitt + abbrechen, nicht l�schen + Kategorien + Code + Kommentar: + Kommentar + abgeschlossen: + Kunde + Datum + Daten + Abgabetermin: + Vordefinierte Rollen + L�schen + Abh�ngigkeiten + Abh�ngigkeit: + Abh�ngigkeitstypen + Beschreibung + Beschreibung: + Erledigt. + Fr�hestes Ende + Fr�hester Beginn + �ndern + Beauftragte �ndern + Kategorien �ndern + Fehler + Ziel + Stunden + Std. + Schl�ssel + Sp�testes Ende + Sp�tester Beginn + Aufwandserfassung Eintrag: + Aufwandserfassung + Aufwandserfassung Integration + . Der Projektmanager erfordert es, zumindestens eine Instanz der Aufwandserfassung zu installieren und zu "mounten", da das Package die Aufwandserfassung dazu nutzt, Zeit und andere Aufw�nde gegen�ber den Projekten und Aufgaben zu erfassen. Sie k�nnen aber auch variierende Integrationslevels mit der Aufwandserfassung definieren. In dieser Sektion richten Sie ein, welche Instanz der Aufwandserfassung mit dem Projektmanager voll integriert sein soll, so dass neue Projektmanager Projekte in der Aufwandserfassungsinstanz erscheinen. + . Der Projektmanager erfordert es, zumindestens eine Instanz der Aufwandserfassung zu installieren und zu "mounten", da das Package die Aufwandserfassung dazu nutzt, Zeit und andere Aufw�nde gegen�ber den Projekten und Aufgaben zu erfassen. Sie k�nnen aber auch variierende Integrationslevels mit der Aufwandserfassung definieren. In dieser Sektion richten Sie ein, welche Instanz der Aufwandserfassung mit dem Projektmanager voll integriert sein soll, so dass neue Projektmanager Projekte in der Aufwandserfassungsinstanz erscheinen. + Nachdem sie dies getan haben, k�nnen Sie zur vorherigen Seite zur�ckgehen, sie neu laden und dann Studen erfassen oder bereits erfasste Stunden ver�ndern. + M�chten Sie jetzt mit diesen URLS synchronisieren? + Sind Sie sich sicher, dass sie diesen Prozess l�schen wollen: %one_line% + Sind Sie sich sicher, dass Sie diese %task_term_lower% l�schen wollen? + (Seien Sie geduldig, es dauert einige Zeit. Sie k�nnen die log files lesen, um zu sehen was geschieht.) + Synchronsierung starten + Klicken Sie auf eines der folgenden Wahlm�glichkeiten, um den Setup zu starten: + Abgeschlossen: %task_info.percent_complete%% + Datum: %entries.time_stamp_pretty% + Ist von einer anderen %task_term_lower% abh�ngig + Geben Sie 100% ein, um diese %task_term_lower% zu schliessen, oder weniger um anzulegen. + Verbliebende Stunden: %task_info.hours_remaining% + @import "%package_url%style-logger.css"; @import "%package_url%style.css"; + Die Aufwandserfassung ist ein Package, das es Ihnen erlaubt, die in dem Projekt geleisteten Stunden, Kosten etc. zu erfassen. + Die Aufwandserfassung ist ein Package, das es Ihnen erlaubt, die in dem Projekt geleisteten Stunden, Kosten etc. zu erfassen. + &nbsp;%num.rownum%&nbsp;&nbsp; + (nicht aktuell, w�hlen Sie die live Version aus + Sobald Sie INstanzen der Aufwandserfassung in den Projektmanager integriert haben, k�nnten Sie viele �ltere Projekte in Ihrem Projektmanager haben, die nicht mit der Aufwandserfassung synchronisiert sind. Diese Seite erlaubt es Ihnen, �ltere Projekte im Projektmanager mit der Aufwandserfassung zu synchronisieren, so dass alle korrekt mit der Instanz verbunden sind. <br>[Originalanmerkung: This does not add in logger projects to project-manager (although someone can certainly add that functionality if they wish).] + Projekt: %entries.project_name% + %project.actual_hours_completed% von %project.estimated_hours_total% + Projekte k�nnen gem�� unterschiedlicher Kategorieb�ume kategorisiert werden. Die serlaubt es Ihnen, Ihre Projekte auf verschiedene Arten zu kategorisieren. Diese Abschnitt richtet Ihre Kategorien ein und erlaubt Ihnen, diese zu Projekten zu verkn�pfen. [Engl. Originalanmerkung: Currently, there is a bug in the categories package that prevents the context bar at the top of the screen from returning you to the project-manager pages.] + e-Mail an Beaufragte schicken? + gem�� den Aufgabenzuteilungen setzen + Setup Integration mit der Aufwandserfassung + �berspringen der Hinzuf�gung von Abh�ngigkeiten + Verbliebene Zeit: %task_info.slack_time% + Verbliebene Zeit: %task_info.slack_time% + %task_info.estimated_hours_work_min% - %task_info.estimated_hours_work_max% gesch�tzte Stunden + %task_info.percent_complete%% abgeschlossen + %task_term% die von %task_term% abh�ngen + %task_term% die von %task_term% abh�ngen + %task_term% von der diese abh�ngt. + %task_term% von der diese abh�ngt. + Der Administrator muss + Das Datenmodell ber�cksichtigt vordefinierte Rollen, obwohl es zurzeit nicht genutzt wird. Die zeigt, welche vordefinierten Rollen in der Datenbank gespeichert sind. Zurzeit noch nicht implementiert. + Diese Parameter erlauben es Ihnen, t�gliche Erinnerungsmails aufzusetzen, die anzuzeigenden Felder in einer Projekt�bersicht zu ver�ndern etc. Sehr empfehlenswert, wenn Sie den Projektmanager aufsetzen! + Die Rollen, die einzelne User in einem Projekt annehmen k�nnen , wie Manager, Ansprechpartner f�r den Techn. Support etc. Zurzeit k�nnen diese leider nur direkt in der Datenbank ver�ndert werden. + Es existieren keine passenden erfassten Aufw�nde + Es existiert ein Datenmodell f�r Workgroups, aber dieses ist nicht Teil des User Interfaces. Zeigt was alles in der Datenbank ist (zurzeit nichts!) + [Originalanmerkung: There is currently a bug in this page where it will not allow you to remove values. You will have to do that through the parameters section.] + Diese Seite erlaubt es Ihnen, die Abgabetermine aller Ihrer Projekte in Ihrer Installation zu aktualisieren. Das wird eine Weile dauern. + Diese Seite wird Ihnen irgendwann einmal erlauben, Ihre Stunden zu mehreren Aufgaben auf einmal zu erfassen. + Zu diesem Prozess %task_term_lower%. Abh�ngigkeiten beschreiben die Reihenfolge, in der die einzelnen Teile abgeschlossen werden m�ssen, z.B. &quot;die Bretter m�ssen geliefert werden bevor die Konstruktion beginnen kann&quot;. Es ist wichtig, Abh�ngigkeiten einzugeben, da es dem System erlaubt, Terminpl�ne automatisch zu erzeugen. + Unbekannte Gruppe nach Spalte %group_by% + Diesen Prozess benutzen: %use_link;noquote% + User: %entries.user_chunk;noquote% + G�ltige Status Codes, z.B. "Offen" und "Abgeschlossen" + Woche: %entries.time_stamp_week% + Wenn implementiert, erlaubt diese Seite Ihnen, die Beschreibung von unterschiedlichen Abh�ngigkeiten (wie "endet vor dem Start von ..) anzusehen und zu ver�ndern. Zurzeit wird lediglich die Abh�ngigkeit "endet vor dem Start von" genutzt, weswegen diese nicht in der UI erscheint. + Optional k�nnen Sie die gearbeitete Zeit auch hier erfassen. + Sie k�nnen eine %task_term_lower% einf�gen, die vor dieser %task_term_lower% abgeschlossen sein muss + Optional k�nnen Sie ein fixen Abgabetermin eingeben + Sie m�ssen eine Instanz der Aufwandserfassung w�hlen, in der die prim�re Erfassung in dem Projektmanager geschehen soll. Diese ist eng mit dem Projektmanager verbunden, so dass Sie sich Berichte zu einem Projekt etc. ansehen k�nnen. + Sie m�ssen hier eine Zahl eingeben (sch�tzen Sie) + Max.: + Min.: + name + &nbsp;&nbsp;%project_term% + Kein User Interface + Jetzt + Ein Prozess + laufend + Reihenfolge + Seite) + Parameter + Prozess Aufgaben: + Prozess Aufgaben + Prozesse + Projekt: + Projektkategorien + Projektinformation + Projektsuche: + %project_term;noquote%e + %project_term%s + Vorausschau + Projekte + Verbundene %task_term% + Mich selber entfernen + Rollen + Suche: + Suche: + Abschnitt + Prozess ausw�hlen: + Set up + Diese Aufgabe �berspringen? + Verbliebene Zeit: + Verbliebene Zeit: n/a + Beginn + Statustyp + Thema: + Subprojekte + Zwischensumme + Zwischensumme Durchschnitt + Synchronisieren + Aufgabe + Aufgaben�nderung + Aufgabe, erfasste Stunden + %task_term%s + AUFGABEN + Aufgaben + Zeit: + Gesamt + Gesamte ben�tigte Arbeitszeit: + Alle aktualisieren + User + Anzusehende User + Variablen + Ansicht + Optionen ansehen + Projekt�nderungen ansehen + Aufgaben�nderungen ansehen + Arbeit + Notwendige Arbeit: + Arbeitsgruppen + Sie k�nnen nun hinzuf�gen + Index: openacs-4/packages/project-manager/catalog/project-manager.en_US.ISO-8859-1.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/catalog/project-manager.en_US.ISO-8859-1.xml,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/catalog/project-manager.en_US.ISO-8859-1.xml 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,214 @@ + + + + Action + Actions + Add + Add subproject + Assignees + Average + Cancel, do not delete + Categories + Code + Comment: + Comments + Complete: + Customer + Date + Dates + Deadline: + Default roles + Delete + dependencies + Dependency: + Dependency types + Description + Description: + Done. + Earliest finish + Earliest start + Edit + Edit assignees + Edit categories + Error + Goal + hours + hrs + Key + Latest finish + Latest start + Log entry: + Logger + Logger integration + . Project manager requires you to + install and mount at least one instance of logger, because it + uses logger to log time and other variables against projects + and tasks. However, you can have varying levels of integration + with logger. This section sets up which logger instances you + want to be fully integrated with project-manager, so that new + project-manager projects appear in the logger instance. + . Project manager requires you to + install and mount at least one instance of logger, because it + uses logger to log time and other variables against projects + and tasks. However, you can have varying levels of integration + with logger. This section sets up which logger instances you + want to be fully integrated with project-manager, so that new + project-manager projects appear in the logger instance. + After they have done this, you can go back to the previous page, + refresh it, and then add and edit logged hours. + Are you ready to sync with these URLs? + Are you sure you want to delete this process: %one_line% + Are you sure you'd like to delete these %task_term_lower%s? + (be patient, + this takes a long time, you can read the log files to see what's + happening if you like.) + Begin synchronization + Click on one of the following items to set it up: + Complete: %task_info.percent_complete%% + Date: %entries.time_stamp_pretty% + depends on another %task_term_lower% + Enter 100% to close the %task_term_lower%, or less + to open it. + Hours remaining: %task_info.hours_remaining% + @import "%package_url%style-logger.css"; + @import "%package_url%style.css"; + Logger is a package that lets you log time, expenses, and + other + Logger is a package that lets you log time, expenses, and + other + &nbsp;%num.rownum%&nbsp;&nbsp; + (not current, select live version from the + Once you have chosen logger instances to be integrated + with project-manager, you may have a lot of older + project-manager projects that are not synchronized with + logger. This page lets you synchronize older project-manager + projects with logger, so that they are all linked in correctly + with that instance. This does not add in logger projects to + project-manager (although someone can certainly add that + functionality if they wish). + Project: %entries.project_name% + %project.actual_hours_completed% of %project.estimated_hours_total% + Projects can be categorized according to multiple 'trees' + of categories. What this means is you can have multiple ways + of categorizing your projects. This section sets up your + categories and allows you to link them to projects. Currently, + there is a bug in the categories package that prevents the + context bar at the top of the screen from returning you to the + project-manager pages. + Send email to assignees? + set according to task assignments + set up integration with logger + skip adding dependencies + Slack: %task_info.slack_time% + Slack time: %task_info.slack_time% + %task_info.estimated_hours_work_min% - %task_info.estimated_hours_work_max% hrs estimated + %task_info.percent_complete%% complete + %task_term%s depending on this %task_term% + %task_term%(s) depending on this %task_term% + %task_term%s this depends on. + %task_term%(s) this depends on. + The administrator needs to + The data model has a facility for default roles, although + it is not currently used at all. This shows what is in the + database for default roles. Currently unimplemented. + The parameters allow you to do things such as set up daily + reminder emails, change what fields are shown in the project + view and edit pages, and so on. Highly recommended if you're + setting up project-manager. + The roles people can take on projects and tasks, such as + manager, sales contact, tech support person, etc.. Currently, + can only be edited directly in the database. + There are no matching log entries + There is a data model for workgroups, but it is not a part + of the UI. Shows what is in the database (currently, nothing!) + There is currently a bug in this page where it will not allow you to + remove values. You will have to do that through the parameters section. + This page allows you to update the deadlines of all the + projects in your installation. It will take a while. + This page will eventually allow you to log hours against multiple +tasks at once. + to these process +%task_term_lower%s. Dependencies describe the order in which items must +be completed. For example, &quot;the boards must be delivered before +construction can begin&quot;. Entering dependencies is important because it +allows the system to automatically compute schedules. However, you can + Unknown group by column %group_by% + Use this process: %use_link;noquote% + User: %entries.user_chunk;noquote% + Valid status codes, for example, 'Open' and 'Closed' + Week: %entries.time_stamp_week% + When implemented, this page will allow you to view and + edit the descriptions given to various dependency types (such + as finish before start, etc..) Currently, the only dependency + used is finish before start, so it's not exposed in the UI + You can optionally log time worked here. + You may enter a %task_term_lower% that needs to + be completed before this %task_term_lower% + You may optionally enter a hard deadline + You must choose a logger instance to be the primary + logger linked in with project-manager. This is closely linked + in with project-manager, so you can view reports of a project, etc. + You must enter a number here (make your best + guess) + Max: + Min: + Name + &nbsp;&nbsp;%project_term% + No UI + Now + One process + Ongoing + Order + page) + Parameters + Process tasks: + process tasks + Processes + Project: + Project categories + Project information + Project Search: + %project_term;noquote%s + %project_term%s + Projection + Projects + Related %task_term%s + Remove myself + Roles + Search: + Search: + Section + Select process: + Set up + Skip this task? + Slack: + Slack: n/a + Start + Status types + Subject: + Subprojects + Subtotal + Subtotal Average + Sync + Task + task change + Task hours completed + %task_term%s + TASKS + Tasks + Time: + Total + Total work required: + Update all + User + Users to view + variables + View + View options + View project changes + View task changes + Work + Work required: + Workgroups + You may now add + Index: openacs-4/packages/project-manager/lib/process-instances-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/lib/process-instances-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/lib/process-instances-postgresql.xql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,44 @@ + + + + + + + + + + + postgresql + 7.3 + + + + + SELECT + i.name || ' (' || i.instance_id || ')' as name, + i.project_item_id as my_project_id, + i.instance_id, + pr.title as project_name + FROM + pm_process_instance i, + cr_items pi, + cr_revisions pr + WHERE + i.project_item_id = pi.item_id and + pi.live_revision = pr.revision_id and + i.instance_id in + (select + t.process_instance + from + pm_tasks_active t, + pm_task_status s + where + t.status = s.status_id and + t.process_instance is not null and + s.status_type = 'o') + ORDER BY + name + + + + Index: openacs-4/packages/project-manager/lib/process-instances.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/lib/process-instances.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/lib/process-instances.adp 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,10 @@ + + + + + + +
+ @instances.name@ +
+ Index: openacs-4/packages/project-manager/lib/process-instances.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/lib/process-instances.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/lib/process-instances.tcl 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,29 @@ +# +# +# Displays a table of active process instances +# +# @author Jade Rubick (jader@bread.com) +# @creation-date 2004-10-21 +# @arch-tag: 21a71f70-73cb-4152-9f1b-a32932ef2f9b +# @cvs-id $Id: process-instances.tcl,v 1.1 2005/04/29 17:43:36 timoh Exp $ + +foreach required_param {} { + if {![info exists $required_param]} { + return -code error "$required_param is a required parameter." + } +} +foreach optional_param {} { + if {![info exists $optional_param]} { + set $optional_param {} + } +} + +# get open processes + +db_multirow -extend {url} instances instances { } { + set url [pm::process::url \ + -process_instance_id $instance_id \ + -project_item_id $my_project_id \ + -fully_qualified_p "f"] + +} Index: openacs-4/packages/project-manager/sql/oracle/project-manager-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,12 @@ +-- +-- packages/project-manager/sql/postgresql/project-manager-create.sql +-- +-- @author jade@bread.com +-- @creation-date 2003-05-15 +-- @cvs-id $Id: project-manager-create.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- +-- + +@@ project-manager-table-create.sql +@@ project-manager-functions-create.sql +@@ project-manager-notifications-create.sql Index: openacs-4/packages/project-manager/sql/oracle/project-manager-custom-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-custom-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-custom-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,45 @@ +-- +-- packages/project-manager/sql/postgresql/project-manager-customize.sql +-- +-- @author jader@bread.com +-- @creation-date 2003-12-05 +-- + +-- this file is used to add custom columns to the projects table. +-- you can then customize the columns shown + +-- if you do set this up, you need to set the parameter in the admin +-- UI, so that the add-edit page will know that there is custom code, +-- You'll need to create an add-edit-custom page, filling in the skeleton there + +-- you should use the content_type__create_attribute procedure to add +-- in columns so that the views are correctly recreated. + +-- PROJECTS + +-- example, using customer +-- this is actually done in the table-create script + +-- this adds in the customer column. This is an example of how +-- the custom columns are added in. I put this here as a reminder +-- that other columns can be added in as well. These custom items +-- are in the custom-create.sql script + +declare + attribute_id integer; +begin + attribute_id := content_type.create_attribute ( + content_type => 'pm_project', + attribute_name => 'customer_id', + datatype => 'integer', + pretty_name => 'Customer', + pretty_plural => 'Customers', + sort_order => null, + default_value => null, + column_spec => 'integer constraint pm_project_customer_fk references organizations' + ); +end; +/ + +show errors + Index: openacs-4/packages/project-manager/sql/oracle/project-manager-custom-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-custom-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-custom-drop.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,12 @@ +-- packages/project-manager/sql/project-manager-drop.sql +-- drop script +-- +-- @author jade@bread.com +-- @creation-date 2003-12-05 +-- @cvs-id $Id: project-manager-custom-drop.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- + +-- drop any custom tables here. + +select content_type__drop_attribute ('pm_project', 'customer_id', 't'); + Index: openacs-4/packages/project-manager/sql/oracle/project-manager-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-drop.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,212 @@ +-- packages/project-manager/sql/project-manager-drop.sql +-- drop script +-- +-- @author jade@bread.com +-- @creation-date 2003-05-15 +-- @cvs-id $Id: project-manager-drop.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- + +-------- +-- TASKS +-------- + +\i project-manager-custom-drop.sql +\i project-manager-notifications-drop.sql + +drop table pm_task_logger_proj_map; + +create function inline_0 () +returns integer as ' +declare + v_item RECORD; + +begin + for v_item in select + item_id + from + cr_items + where + content_type = ''pm_task'' + LOOP + PERFORM pm_task__delete_task_item(v_item.item_id); + end loop; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +-- unregister content_types from folder +create function inline_0 () +returns integer as ' +declare + v_folder_id cr_folders.folder_id%TYPE; + v_item_id cr_items.item_id%TYPE; + v_item_cursor RECORD; +begin + + -- delete all contents of projects folder + FOR v_item_cursor IN + select + item_id + from + cr_items + where + content_type = ''pm_task'' + LOOP + PERFORM pm_project__delete_task_item(v_item_cursor.item_id); + END LOOP; + + -- this table must not hold reference to ''pm_tasks'' type + delete from cr_folder_type_map where content_type = ''pm_tasks''; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +-- unregister content_types from folder +create function inline_0 () +returns integer as ' +declare + v_folder_id cr_folders.folder_id%TYPE; + v_item_id cr_items.item_id%TYPE; + v_item_cursor RECORD; +begin + + -- delete all contents of projects folder + FOR v_item_cursor IN + select + item_id + from + cr_items + where + content_type = ''pm_project'' + LOOP + PERFORM pm_project__delete_project_item(v_item_cursor.item_id); + END LOOP; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +-- unregister content_types from folder +create function inline_0 () +returns integer as ' +declare + v_folder_id cr_folders.folder_id%TYPE; + v_item_id cr_items.item_id%TYPE; + v_item_cursor RECORD; +begin + + FOR v_item_cursor IN + select folder_id from cr_folders where description=''Project Repository'' + LOOP + PERFORM content_folder__unregister_content_type ( + v_item_cursor.folder_id, -- folder_id + ''pm_project'', -- content_type + ''t'' -- include_subtypes + ); + PERFORM content_folder__delete(v_item_cursor.folder_id); + END LOOP; + + -- this table must not hold reference to ''pm_project'' type + delete from cr_folder_type_map where content_type = ''pm_project''; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + + +-- task dependency types +drop table pm_task_dependency_types cascade; +drop table pm_task_dependency cascade; +drop sequence pm_task_dependency_seq; +drop sequence pm_tasks_number_seq; + +select content_type__drop_attribute ('pm_task', 'end_date', 't'); +select content_type__drop_attribute ('pm_task', 'percent_complete', 't'); +select content_type__drop_attribute ('pm_task', 'estimated_hours_work', 't'); +select content_type__drop_attribute ('pm_task', 'estimated_hours_work_min', 't'); +select content_type__drop_attribute ('pm_task', 'estimated_hours_work_max', 't'); +select content_type__drop_attribute ('pm_task', 'actual_hours_worked', 't'); +select content_type__drop_attribute ('pm_task', 'earliest_start', 't'); +select content_type__drop_attribute ('pm_task', 'earliest_finish', 't'); +select content_type__drop_attribute ('pm_task', 'latest_start', 't'); +select content_type__drop_attribute ('pm_task', 'latest_finish', 't'); + +------------- +-- WORKGROUPS +------------- + +drop sequence pm_workgroup_seq; +drop table pm_workgroup_parties; +drop table pm_workgroup; + +------------ +-- PROCESSES +------------ + +drop sequence pm_process_seq; +drop sequence pm_process_task_seq; +drop sequence pm_process_task_dependency_seq; + +drop table pm_process_task_assignment; +drop table pm_process_task_dependency; +drop table pm_process_task; +drop table pm_process; + +--------- +-- OTHERS +--------- +drop table pm_default_roles; +drop table pm_project_assignment; +drop table pm_task_assignment; +drop table pm_roles; +drop sequence pm_role_seq; + + +select drop_package('pm_task'); + + +----------- +-- PROJECTS +----------- + +--drop permissions +delete from acs_permissions where object_id in (select project_id from pm_projects); + + +-- drop package, which drops all functions created with define_function_args +select drop_package('pm_project'); + +--drop table +drop table pm_projects cascade; + +drop sequence pm_project_status_seq; +drop table pm_project_status cascade; + + + +drop sequence pm_task_status_seq; +drop table pm_task_status cascade; + +drop table pm_tasks cascade; +drop table pm_tasks_revisions cascade; + +select content_type__drop_type('pm_task', 't', 'f'); + +select content_type__drop_type('pm_project', 't', 'f'); + +-- note that the Project Repository folder is not deleted + Index: openacs-4/packages/project-manager/sql/oracle/project-manager-functions-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-functions-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-functions-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,610 @@ +-- +-- packages/project-manager/sql/postgresql/project-manager-functions-create.sql +-- +-- @author jade@bread.com, ncarroll@ee.usyd.edu.au +-- @creation-date 2003-05-15 +-- @cvs-id $Id: project-manager-functions-create.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- +-- + +-- When we created the acs object type above, we specified a +-- 'name_method'. This is the name of a function that will return the +-- name of the object. This is a convention ensuring that all objects +-- can be identified. Now we have to build that function. In this case, +-- we'll return a field called title as the name. + + +create or replace package pm_project as + + function name ( p_pm_project_id in pm_projects.project_id%TYPE + ) return varchar2; + + function new_root_folder (p_package_id in apm_packages.package_id%TYPE + ) return integer; + + function get_root_folder (p_package_id in apm_packages.package_id%TYPE , + p_create_if_not_present_p in char + ) return integer; + + function new_project_item ( + p_project_name in varchar2 , + p_project_code in pm_projects.project_code%TYPE, + p_parent_id in integer , + p_goal in pm_projects.goal%TYPE, + p_description in varchar2 , + p_mime_type in varchar2 , + p_planned_start_date in pm_projects.planned_start_date%TYPE , + p_planned_end_date in pm_projects.planned_end_date%TYPE , + p_actual_start_date in pm_projects.actual_start_date%TYPE , + p_actual_end_date in pm_projects.actual_end_date%TYPE, + p_logger_project in pm_projects.logger_project%TYPE , + p_ongoing_p in pm_projects.ongoing_p%TYPE , + p_status_id in pm_projects.status_id%TYPE , + p_customer_id in pm_projects.customer_id%TYPE , + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer; + + procedure delete_project_item ( p_project_id in pm_projects.project_id%TYPE); + + function new_project_revision ( + p_item_id in integer , + p_project_name in varchar2 , + p_project_code in pm_projects.project_code%TYPE, + p_parent_id in integer , + p_goal in pm_projects.goal%TYPE, + p_description in varchar2 , + p_planned_start_date in pm_projects.planned_start_date%TYPE , + p_planned_end_date in pm_projects.planned_end_date%TYPE , + p_actual_start_date in pm_projects.actual_start_date%TYPE , + p_actual_end_date in pm_projects.actual_end_date%TYPE, + p_logger_project in pm_projects.logger_project%TYPE , + p_ongoing_p in pm_projects.ongoing_p%TYPE , + p_status_id in pm_projects.status_id%TYPE , + p_customer_id in pm_projects.customer_id%TYPE , + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer; + + function new_unique_name (p_package_id in integer + ) return varchar; + +end pm_project; +/ + +show errors + +create or replace package body pm_project as + function name ( p_pm_project_id in pm_projects.project_id%TYPE + ) return varchar2 + is + v_pm_project_name varchar2(500); + begin + select name || '_' || p_pm_project_id + into v_pm_project_name + from pm_projectsx + where item_id = p_pm_project_id; + + return v_pm_project_name; + end name; + + function new_root_folder (p_package_id in apm_packages.package_id%TYPE + ) return integer + is + v_folder_id cr_folders.folder_id%TYPE; + v_folder_name cr_items.name%TYPE; + begin + v_folder_name := new_unique_name (p_package_id); + + v_folder_id := content_folder.new ( + name => v_folder_name, + label => 'Projects', + description => 'Project Repository', + parent_id => null, + context_id => p_package_id, + folder_id => null, + creation_date => sysdate, + creation_user => null, + creation_ip => null + ); + + -- Register the standard content types + content_folder.register_content_type ( + folder_id => v_folder_id, + content_type => 'pm_project', + include_subtypes => 'f' + ); + + -- there is no facility in the API for adding in the package_id, + -- so we have to do it ourselves + + update cr_folders + set package_id = p_package_id + where folder_id = v_folder_id; + + -- TODO: Handle Permissions here for this folder. + + return v_folder_id; + end new_root_folder; + + function get_root_folder (p_package_id in apm_packages.package_id%TYPE , + p_create_if_not_present_p char + ) return integer + is + v_folder_id cr_folders.folder_id%TYPE; + v_count integer; + begin + select count(*) into v_count + from cr_folders + where package_id = p_package_id; + + -- raise notice 'count is % for package_id %', v_count, p_package_id; + + if v_count > 1 then + raise_application_error(-20001, 'More than one project repository for this application instance'); + elsif v_count = 1 then + select folder_id into v_folder_id + from cr_folders + where package_id = p_package_id; + else + if p_create_if_not_present_p = 't' then + -- Must be a new instance. Create a new root folder. + -- raise notice 'creating a new root repository folder'; + v_folder_id := new_root_folder(p_package_id); + else + -- raise notice 'setting to null'; + v_folder_id := null; + end if; + end if; + + return v_folder_id; + end get_root_folder; + + function new_project_item ( + p_project_name in varchar2 , + p_project_code in pm_projects.project_code%TYPE, + p_parent_id in integer , + p_goal in pm_projects.goal%TYPE, + p_description in varchar2 , + p_mime_type in varchar2 , + p_planned_start_date in pm_projects.planned_start_date%TYPE , + p_planned_end_date in pm_projects.planned_end_date%TYPE , + p_actual_start_date in pm_projects.actual_start_date%TYPE , + p_actual_end_date in pm_projects.actual_end_date%TYPE, + p_logger_project in pm_projects.logger_project%TYPE , + p_ongoing_p in pm_projects.ongoing_p%TYPE , + p_status_id in pm_projects.status_id%TYPE , + p_customer_id in pm_projects.customer_id%TYPE , + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer + is + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_parent_id cr_items.parent_id%TYPE; + begin + + select acs_object_id_seq.nextval into v_id from dual; + + v_parent_id := get_root_folder (p_package_id, 't'); + + -- raise notice 'v_parent_id (%) p_parent_id (%)', v_parent_id, p_parent_id; + + if p_parent_id is not null + then + v_parent_id := p_parent_id; + end if; + + -- raise notice 'v_parent_id (%) p_parent_id (%)', v_parent_id, p_parent_id; + + v_item_id := content_item.new ( + name => v_id, + parent_id => v_parent_id, + item_id => v_id , + locale => null, + creation_date => p_creation_date, + creation_user => p_creation_user, + context_id => p_parent_id, + creation_ip => p_creation_ip, + item_subtype => 'content_item', + content_type => 'pm_project', + title => p_project_name, + description => p_description, + mime_type => p_mime_type, + nls_language => null, + data => null + ); + + v_revision_id := content_revision.new ( + title => p_project_name, + description => p_description, + publish_date => sysdate, + mime_type => p_mime_type, + nls_language => NULL, + data => NULL, + item_id => v_item_id, + revision_id => NULL, + creation_date => p_creation_date, + creation_user => p_creation_user, + creation_ip => p_creation_ip + ); + + content_item.set_live_revision (v_revision_id); + + insert into pm_projects ( + project_id, project_code, + goal, planned_start_date, + planned_end_date, actual_start_date, actual_end_date, + logger_project, ongoing_p, estimated_finish_date, + earliest_finish_date, latest_finish_date, + actual_hours_completed, + estimated_hours_total, status_id, customer_id) + values ( + v_revision_id, p_project_code, + p_goal, p_planned_start_date, + p_planned_end_date, p_actual_start_date, + p_actual_end_date, p_logger_project, p_ongoing_p, + p_planned_end_date, + p_planned_end_date, p_planned_end_date, '0', + '0', p_status_id, p_customer_id + ); + + acs_permission.grant_permission( + v_revision_id, + p_creation_user, + 'admin' + ); + + return v_revision_id; + end new_project_item; + + procedure delete_project_item ( p_project_id in pm_projects.project_id%TYPE) + is + v_child_item_id cr_items.item_id%TYPE; + begin + -- raise NOTICE 'Deleting pm_project...'; + + for v_child in (select item_id + from cr_items + where parent_id = p_project_id and + content_type = 'pm_project') + loop + delete_project_item(v_child_item_id); + end loop; + + delete from pm_projects where project_id in (select revision_id from pm_projectsx where item_id = p_project_id); + + content_item.del(p_project_id); + end delete_project_item; + + + function new_project_revision ( + p_item_id in integer , + p_project_name in varchar2 , + p_project_code in pm_projects.project_code%TYPE, + p_parent_id in integer , + p_goal in pm_projects.goal%TYPE, + p_description in varchar2 , + p_planned_start_date in pm_projects.planned_start_date%TYPE , + p_planned_end_date in pm_projects.planned_end_date%TYPE , + p_actual_start_date in pm_projects.actual_start_date%TYPE , + p_actual_end_date in pm_projects.actual_end_date%TYPE, + p_logger_project in pm_projects.logger_project%TYPE , + p_ongoing_p in pm_projects.ongoing_p%TYPE , + p_status_id in pm_projects.status_id%TYPE , + p_customer_id in pm_projects.customer_id%TYPE , + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer + is + v_revision_id cr_revisions.revision_id%TYPE; + begin + + -- the item_id is the project_id + v_revision_id := content_revision.new ( + title => p_project_name, + description => p_description, + publish_date => sysdate, + mime_type => 'text/plain', + nls_language => NULL, + data => NULL, + item_id => p_item_id, + revision_id => NULL, + creation_date => p_creation_date, + creation_user => p_creation_user, + creation_ip => p_creation_ip + ); + + content_item.set_live_revision (v_revision_id); + + insert into pm_projects ( + project_id, project_code, + goal, planned_start_date, + planned_end_date, actual_start_date, actual_end_date, + logger_project, + ongoing_p, status_id, customer_id) + values ( + v_revision_id, p_project_code, + p_goal, p_planned_start_date, + p_planned_end_date, p_actual_start_date, + p_actual_end_date, + p_logger_project, p_ongoing_p, p_status_id, p_customer_id); + + acs_permission.grant_permission( + v_revision_id, + p_creation_user, + 'admin' + ); + + return v_revision_id; + + end new_project_revision; + + function new_unique_name (p_package_id in integer + ) return varchar + is + v_name cr_items.name%TYPE; + v_package_key apm_packages.package_key%TYPE; + v_id integer; + begin + select package_key into v_package_key from apm_packages + where package_id = p_package_id; + + select acs_object_id_seq.nextval into v_id from dual; + + -- Set the name + select v_package_key || '_' || + to_char(sysdate, 'YYYYMMDD') || '_' || + v_id into v_name + from dual; + + return v_name; + + end new_unique_name; +end pm_project; +/ +show errors + +---------------------------------- +-- Tasks +---------------------------------- + +-- When we created the acs object type above, we specified a +-- 'name_method'. This is the name of a function that will return the +-- name of the object. This is a convention ensuring that all objects +-- can be identified. Now we have to build that function. In this case, +-- we'll return a field called title as the name. +create or replace package pm_task +as + function name (p_pm_task_id in integer + ) return varchar2; + + function new_task_item ( + p_project_id in integer , + p_title in varchar2, + p_description in varchar2, + p_mime_type in varchar2, + p_end_date in date, + p_percent_complete in numeric, + p_estimated_hours_work in numeric, + p_estimated_hours_work_min in numeric, + p_estimated_hours_work_max in numeric, + p_status_id in integer, + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer; + + function new_task_revision ( + p_task_id in integer, + p_project_id in integer , + p_title in varchar2, + p_description in varchar2, + p_mime_type in varchar2, + p_end_date in date, + p_percent_complete in numeric, + p_estimated_hours_work in numeric, + p_estimated_hours_work_min in numeric, + p_estimated_hours_work_max in numeric, + p_actual_hours_worked in numeric, + p_status_id in integer, + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer; + + procedure delete_task_item (p_task_id in integer); + +end pm_task; +/ +show errors + + +create or replace package body pm_task +as + function name (p_pm_task_id in integer + ) return varchar2 + is + v_pm_task_name cr_items.name%TYPE; + begin + select i.name || '_' || p_pm_task_id into v_pm_task_name + from cr_items i + where i.item_id = p_pm_task_id; + + return v_pm_task_name; + end name; + + function new_task_item ( + p_project_id in integer , + p_title in varchar2, + p_description in varchar2, + p_mime_type in varchar2, + p_end_date in date, + p_percent_complete in numeric, + p_estimated_hours_work in numeric, + p_estimated_hours_work_min in numeric, + p_estimated_hours_work_max in numeric, + p_status_id in integer, + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer + is + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_task_number integer; + begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + -- create the task_number + + v_item_id := content_item.new ( + name => v_id, + parent_id => p_project_id, + item_id => v_id, + locale => null, + creation_date => sysdate, + creation_user => p_creation_user, + context_id => p_package_id, + creation_ip => p_creation_ip, + item_subtype => 'content_item', + content_type => 'pm_task', + title => p_title, + description => p_description, + mime_type => p_mime_type, + nls_language => null, + data => null + ); + + v_revision_id := content_revision.new ( + title => p_title, + description => p_description, + publish_date => sysdate, + mime_type => p_mime_type, + nls_language => NULL, + data => NULL, + item_id => v_item_id, + revision_id => NULL, + creation_date => sysdate, + creation_user => p_creation_user, + creation_ip => p_creation_ip + ); + + content_item.set_live_revision (v_revision_id); + + insert into pm_tasks ( + task_id, task_number, status) + values ( + v_item_id, v_task_number, p_status_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, '0'); + + acs_permission.grant_permission( + v_revision_id, + p_creation_user, + 'admin' + ); + + return v_revision_id; + + end new_task_item; + + function new_task_revision ( + p_task_id in integer, + p_project_id in integer , + p_title in varchar2, + p_description in varchar2, + p_mime_type in varchar2, + p_end_date in date, + p_percent_complete in numeric, + p_estimated_hours_work in numeric, + p_estimated_hours_work_min in numeric, + p_estimated_hours_work_max in numeric, + p_actual_hours_worked in numeric, + p_status_id in integer, + p_creation_date in date default sysdate, + p_creation_user in integer, + p_creation_ip in varchar2, + p_package_id in integer + ) return integer + is + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + update cr_items + set parent_id = p_project_id + where item_id = p_task_id; + + v_revision_id := content_revision.new ( + title => p_title, + description => p_description, + publish_date => sysdate, + mime_type => p_mime_type, + nls_language => NULL, + data => NULL, + item_id => p_task_id, + revision_id => NULL, + creation_date => sysdate, + creation_user => p_creation_user, + creation_ip => p_creation_ip + ); + + content_item.set_live_revision (v_revision_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, p_actual_hours_worked); + + update pm_tasks + set status = p_status_id + where task_id = p_task_id; + + acs_permission.grant_permission( + v_revision_id, + p_creation_user, + 'admin' + ); + + return v_revision_id; + end new_task_revision; + + procedure delete_task_item (p_task_id in integer) + is + begin + delete from pm_tasks_revisions + where task_revision_id in (select revision_id from pm_tasks_revisionsx where item_id = p_task_id); + + delete from pm_tasks + where task_id = p_task_id; + + content_item.del(p_task_id); + end delete_task_item ; +end pm_task; +/ + +show errors + + + + Index: openacs-4/packages/project-manager/sql/oracle/project-manager-notifications-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-notifications-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-notifications-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,66 @@ +-- Following directions at +-- http://openacs.org/doc/openacs-HEAD/tutorial-notifications.html + +-- using pm_task_notif_type instead of lars_blogger_notif_type +-- using project-manager instead of lars-blogger + +declare + impl_id integer; + v_foo integer; +begin + + -- the notification type impl + impl_id := acs_sc_impl.new ( + impl_contract_name => 'NotificationType', + impl_name => 'pm_task_notif_type', + impl_owner_name => 'project-manager' + ); + + v_foo := acs_sc_impl_alias.new ( + impl_contract_name => 'NotificationType', + impl_name => 'pm_task_notif_type', + impl_operation_name => 'GetURL', + impl_alias => 'pm::task::get_url', + impl_pl => 'TCL' + ); + + v_foo := acs_sc_impl_alias.new ( + impl_contract_name => 'NotificationType', + impl_name => 'pm_task_notif_type', + impl_operation_name => 'ProcessReply', + impl_alias => 'pm::task::process_reply', + impl_pl => 'TCL' + ); + + acs_sc_binding.new ( + contract_name => 'NotificationType', + impl_name => 'pm_task_notif_type' + ); + + v_foo:= notification_type.new ( + type_id => NULL, + sc_impl_id => impl_id, + short_name => 'pm_task_notif', + pretty_name => 'Task Notification', + description => 'Notifications of task changes', + creation_date => sysdate , + creation_user => null, + creation_ip => null, + context_id => NULL + ); + + -- enable the various intervals and delivery methods + insert into notification_types_intervals + (type_id, interval_id) + select v_foo, interval_id + from notification_intervals where name in ('instant','hourly','daily'); + + insert into notification_types_del_methods + (type_id, delivery_method_id) + select v_foo, delivery_method_id + from notification_delivery_methods where short_name in ('email'); + +end; +/ + +show errors Index: openacs-4/packages/project-manager/sql/oracle/project-manager-notifications-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-notifications-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-notifications-drop.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,92 @@ +-- +-- Project Manager +-- +-- @author jader@bread.com +-- @author gwong@orchardlabs.com,ben@openforce.biz +-- @creation-date 2002-05-16 +-- +-- This code is newly concocted by Ben, but with significant concepts and code +-- lifted from Gilbert's UBB forums. Thanks Orchard Labs. +-- Jade in turn lifted this from gwong and ben. +-- + +create function inline_0 () +returns integer as ' +declare + row record; +begin + for row in select nt.type_id + from notification_types nt + where nt.short_name in (''pm_task_notif'') + loop + perform notification_type__delete(row.type_id); + end loop; + + return null; +end;' language 'plpgsql'; + +select inline_0(); +drop function inline_0 (); + +-- +-- Service contract drop stuff was missing - Roberto Mello +-- + +create function inline_0() returns integer as ' +declare + impl_id integer; + v_foo integer; +begin + + -- the notification type impl + impl_id := acs_sc_impl__get_id ( + ''NotificationType'', -- impl_contract_name + ''pm_task_notif_type'' -- impl_name + ); + + PERFORM acs_sc_binding__delete ( + ''NotificationType'', + ''pm_task_notif_type'' + ); + + v_foo := acs_sc_impl_alias__delete ( + ''NotificationType'', -- impl_contract_name + ''pm_task_notif_type'', -- impl_name + ''GetURL'' -- impl_operation_name + ); + + v_foo := acs_sc_impl_alias__delete ( + ''NotificationType'', -- impl_contract_name + ''pm_task_notif_type'', -- impl_name + ''ProcessReply'' -- impl_operation_name + ); + + select into v_foo type_id + from notification_types + where sc_impl_id = impl_id + and short_name = ''pm_task_notif''; + + perform notification_type__delete (v_foo); + + delete from notification_types_intervals + where type_id = v_foo + and interval_id in ( + select interval_id + from notification_intervals + where name in (''instant'',''hourly'',''daily'') + ); + + delete from notification_types_del_methods + where type_id = v_foo + and delivery_method_id in ( + select delivery_method_id + from notification_delivery_methods + where short_name in (''email'') + ); + + return (0); +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); Index: openacs-4/packages/project-manager/sql/oracle/project-manager-table-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/oracle/project-manager-table-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/oracle/project-manager-table-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,638 @@ +-- packages/project-manager/sql/postgresql/project-manager-table-create.sql +-- +-- @author jader@bread.com +-- @author ncarroll@ee.usyd.edu.au was involved in creating the initial CR version +-- @author everyone else involved in this thread: http://openacs.org/forums/message-view?message_id=90742 +-- @creation-date 2003-05-15 +-- + +-- PROJECTS + +create sequence pm_project_status_seq start with 3; + +create table pm_project_status ( + status_id integer + constraint pm_project_status_pk + primary key, + description varchar(100), + -- closed or open + status_type char(1) default 'c' + constraint pm_projects_status_type_ck + check (status_type in ('c','o')) +); + +insert into pm_project_status (status_id, description, status_type) values +(1, 'Open', 'o'); +insert into pm_project_status (status_id, description, status_type) values +(2, 'Closed', 'c'); + + +-- project revisions, items are kept in cr_items + +create table pm_projects ( + project_id integer + constraint pm_proj_rev_fk + references cr_revisions on delete cascade + constraint pm_proj_rev_pk + primary key, + -- a user-specified project code + project_code varchar(255), + goal varchar(4000), + planned_start_date date, + planned_end_date date, + actual_start_date date, + actual_end_date date, + status_id integer + constraint pm_projects_status_id_nn + not null + constraint pm_projects_status_id_fk + references pm_project_status, + -- if ongoing_p is true, then actual_end_date must be null + ongoing_p char(1) default 'f' + constraint pm_projects_ongoing_p_ck + check (ongoing_p in ('t','f')), + estimated_finish_date date, + earliest_finish_date date, + latest_finish_date date, + -- denormalized, taken from logger + actual_hours_completed numeric, + estimated_hours_total numeric, + -- The logger package keeps its own projects table + logger_project integer + constraint pm_projects_logger_pj_nn + not null + constraint pm_projects_logger_pj_fk + references logger_projects +); + +-- create type +begin + content_type.create_type ( + content_type => 'pm_project', + supertype => 'content_revision', + pretty_name => 'Project', + pretty_plural => 'Projects', + table_name => 'pm_projects', + id_column => 'project_id', + name_method => 'pm_project.name' + ); +end; +/ +show errors + +-- other fields are added in too. See the -custom script. + + +-- ROLES + +create sequence pm_role_seq start with 4; + +create table pm_roles ( + role_id integer + constraint pm_role_id_pk + primary key, + one_line varchar(100) + constraint pm_role_one_line_uq + unique, + description varchar(2000), + sort_order integer, + is_observer_p char(1) default 'f' + constraint pm_role_is_observer_ck + check (is_observer_p in ('t','f')) +); + + +comment on table pm_roles is ' + Roles represent the way in which a party participates in a project + or task. For example, they could be a manager, or client, or + participant.. The sort order determines what order it is displayed + in. The is_observer_p specifies whether they are directly + responsible for the task, or are just observers on it. +'; + +insert into pm_roles (role_id, one_line, description, sort_order) values ('1','Lead','Team members who are responsible for the completion of the project','10'); +insert into pm_roles (role_id, one_line, description, sort_order) values ('2','Player','A person on the team responsible for completion of the project','20'); +insert into pm_roles (role_id, one_line, description, sort_order, is_observer_p) values ('3','Watcher','A person interested in developments, possibly helping out on it.','30','t'); + + +create table pm_default_roles ( + role_id integer + constraint pm_default_role_fk + references pm_roles + on delete cascade, + party_id integer + constraint pm_default_role_party_fk + references parties(party_id) + on delete cascade, + constraint pm_default_roles_uq + unique (role_id, party_id) +); + +comment on table pm_default_roles is ' + Specifies what role a person is a part of by default +'; + +-- PROJECT ASSIGNMENT + +create table pm_project_assignment ( + project_id integer + constraint pm_proj_role_map_project_fk + references cr_items + on delete cascade, + role_id integer + constraint pm_project_role_map_role_fk + references pm_roles, + party_id integer + constraint pm_project_role_map_user_id_fk + references parties(party_id) + on delete cascade, + constraint pm_project_assignment_uq + unique (project_id, role_id, party_id) +); + + +comment on table pm_project_assignment is ' + Maps who is a part of what project, and in what capacity +'; + + +-- TASKS + +-- we create two tables to store task information +-- the information that we keep revisions on is in the +-- pm_task_revisions table, the rest is in pm_task + +create sequence pm_task_status_seq start with 3; + +create table pm_task_status ( + status_id integer + constraint pm_task_status_pk + primary key, + description varchar(100), + -- closed or open + status_type char(1) default 'c' + constraint pm_task_status_type_ck + check (status_type in ('c','o')) +); + +insert into pm_task_status (status_id, description, status_type) values +(1, 'Open', 'o'); +insert into pm_task_status (status_id, description, status_type) values +(2, 'Closed', 'c'); + + +create sequence pm_tasks_number_seq; + +create table pm_tasks ( + task_id integer + constraint pm_tasks_task_id_fk + references cr_items + on delete cascade + constraint pm_task_task_id_pk + primary key, + task_number integer, + status integer + constraint pm_tasks_task_status_fk + references pm_task_status, + deleted_p char(1) default 'f' + constraint pm_tasks_deleted_p_ck + check (deleted_p in ('t','f')) +); + +CREATE OR REPLACE view +pm_tasks_active as + SELECT task_id, task_number, status FROM pm_tasks where deleted_p = 'f'; + + +create table pm_tasks_revisions ( + task_revision_id integer + constraint pm_task_revs_id_fk + references cr_revisions + on delete cascade + constraint pm_task_revs_id_pk + primary key, + -- dates are optional, because it may be computed in reference + -- to all other items, or simply not have a deadline + end_date date, + -- keep track of completion status + percent_complete numeric + constraint pm_task_per_complete_gt_ck + check(percent_complete >= 0) + constraint pm_task_per_complete_lt_ck + check(percent_complete <= 100), + estimated_hours_work numeric, + -- PERT charts require minimum and maximum estimates + -- these are optionally used + estimated_hours_work_min numeric, + estimated_hours_work_max numeric, + -- this should be computed by checking with logger? The actual + -- data should be in logger, logged by who did it, when etc.. + -- or we can create a separate table to keep track of task hours + -- and make sure its data model is similar to logger? + actual_hours_worked numeric, + -- network diagram stuff, computed + earliest_start date, + earliest_finish date, + latest_start date, + latest_finish date +); + +-- create the content type +begin + content_type.create_type ( + content_type => 'pm_task', + supertype => 'content_revision', + pretty_name => 'Task', + pretty_plural => 'Tasks', + table_name => 'pm_tasks_revisions', + id_column => 'task_revision_id', + name_method => 'pm_task__name' + ); +end; +/ +show errors + +-- add in attributes + +declare + attribute_id integer; +begin + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'end_date', + datatype => 'date', + pretty_name => 'End date', + pretty_plural => 'End dates', + sort_order => null, + default_value => null, + column_spec => 'date' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'percent_complete', + datatype => 'number', + pretty_name => 'Percent complete', + pretty_plural => 'Percents complete', + sort_order => null, + default_value => null, + column_spec => 'numeric' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'estimated_hours_work', + datatype => 'number', + pretty_name => 'Estimated hours work', + pretty_plural => 'Estimated hours work', + sort_order => null, + default_value => null, + column_spec => 'numeric' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'estimated_hours_work_min', + datatype => 'number', + pretty_name => 'Estimated minimum hours', + pretty_plural => 'Estimated minimum hours', + sort_order => null, + default_value => null, + column_spec => 'numeric' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'estimated_hours_work_max', + datatype => 'number', + pretty_name => 'Estimated maximum hours', + pretty_plural => 'Estimated maximum hours', + sort_order => null, + default_value => null, + column_spec => 'numeric' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'actual_hours_worked', + datatype => 'number', + pretty_name => 'Actual hours worked', + pretty_plural => 'Actual hours worked', + sort_order => null, + default_value => null, + column_spec => 'numeric' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'earliest_start', + datatype => 'date', + pretty_name => 'Earliest start date', + pretty_plural => 'Earliest start dates', + sort_order => null, + default_value => null, + column_spec => 'date' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'earliest_finish', + datatype => 'date', + pretty_name => 'Earliest finish date', + pretty_plural => 'Earliest finish dates', + sort_order => null, + default_value => null, + column_spec => 'date' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'latest_start', + datatype => 'date', + pretty_name => 'Latest start date', + pretty_plural => 'Latest start dates', + sort_order => null, + default_value => null, + column_spec => 'date' + ); + + attribute_id := content_type.create_attribute ( + content_type => 'pm_task', + attribute_name => 'latest_finish', + datatype => 'date', + pretty_name => 'Latest finish date', + pretty_plural => 'Latest finish dates', + sort_order => null, + default_value => null, + column_spec => 'date' + ); +end; +/ + +show errors + +create table pm_task_logger_proj_map ( + task_item_id integer + constraint pm_task_log_proj_map_t_nn + not null + constraint pm_task_log_proj_map_t_fk + references pm_tasks + on delete cascade, + logger_entry integer + constraint pm_task_log_proj_map_l_nn + not null + constraint pm_task_log_proj_map_l_fk + references logger_entries + on delete cascade, + constraint pm_task_logger_proj_map_uq + unique (task_item_id, logger_entry) +); + + +-- DEPENDENCIES + +-- dependency types +-- such as: +-- cannot start until Task X finishes +-- cannot start until Task X begins +-- cannot finish until Task X finishes +-- cannot finish until Task X begins + +create table pm_task_dependency_types ( + short_name varchar(100) + constraint pm_task_const_sn_pk + primary key, + description varchar(1000) +); + +insert into pm_task_dependency_types (short_name, description) values ('start_before_start','Starts before this starts'); +insert into pm_task_dependency_types (short_name, description) values ('start_before_finish','Starts before this finishes'); +insert into pm_task_dependency_types (short_name, description) values ('finish_before_start','Finishes before this starts'); +insert into pm_task_dependency_types (short_name, description) values ('finish_before_finish','Finishes before this finishes'); + + +create sequence pm_task_dependency_seq; + +create table pm_task_dependency ( + dependency_id integer + constraint pm_task_const_id_pk + primary key, + task_id integer + constraint pm_task_const_task_id_nn + not null + constraint pm_task_const_task_id_fk + references pm_tasks + on delete cascade, + parent_task_id integer + constraint pm_tasks_const_parent_id_nn + not null + constraint pm_tasks_const_parent_id_fk + references pm_tasks + on delete cascade, + dependency_type varchar(100) + constraint pm_tasks_const_type_nn + not null + constraint pm_tasks_const_type_fk + references pm_task_dependency_types, + constraint pm_task_dependency_uq unique (task_id, parent_task_id) +); + + +-- WORKGROUPS + +create sequence pm_workgroup_seq; + +create table pm_workgroup ( + workgroup_id integer + constraint pm_workgroup_id_pk + primary key, + one_line varchar(100) + constraint pm_workgroup_one_line_uq + unique, + description varchar(2000), + sort_order integer +); + +create table pm_workgroup_parties ( + workgroup_id integer + constraint pm_workgroup_parties_wg_id_fk + references pm_workgroup(workgroup_id) + on delete cascade, + party_id integer + constraint pm_workgroup_party_fk + references parties(party_id) + on delete cascade, + role_id integer + constraint pm_workgroup_role_id + references pm_roles, + constraint pm_workgroup_parties_uq + unique (workgroup_id, party_id, role_id) +); + + +-- TASK ASSIGNMENTS + +create table pm_task_assignment ( + task_id integer + constraint pm_task_assignment_task_fk + references pm_tasks(task_id) + on delete cascade, + role_id integer + constraint pm_task_assignment_role_fk + references pm_roles, + party_id integer + constraint pm_task_assignment_party_fk + references parties(party_id) + on delete cascade, + constraint pm_task_assignment_uq + unique (task_id, role_id, party_id) +); + + +comment on table pm_task_assignment is ' + Maps who is a part of what task, and in what capacity +'; + +create table pm_task_xref ( + task_id_1 integer + constraint pm_task_xref_task1_nn + not null + constraint pm_task_xref_task1_fk + references pm_tasks(task_id) + on delete cascade, + task_id_2 integer + constraint pm_task_xref_task2_nn + not null + constraint pm_task_xref_task2_fk + references pm_tasks(task_id) + on delete cascade, + constraint pm_task_xref_lt check (task_id_1 < task_id_2) +); + +comment on table pm_task_xref is ' + Maps related tasks. +'; + + +-- PROCESSES + +create sequence pm_process_seq; + +create table pm_process ( + process_id integer + constraint pm_process_id_pk + primary key, + one_line varchar(200) + constraint pm_process_one_line_nn + not null, + description varchar(1000), + party_id integer + constraint pm_process_party_fk + references parties + constraint pm_process_party_nn + not null, + creation_date date +); + +comment on table pm_process is ' + Processes are a set of templates for tasks, so that people can + create sets of tasks quickly. Their structure needs to match that of + tasks. The process holds the meta information, and is also an identifier + that is used by the user to select which process they''d like to copy or + use +'; + +create sequence pm_process_task_seq; + +create table pm_process_task ( + process_task_id integer + constraint pm_process_task_id_pk + primary key, + process_id integer + constraint pm_process_process_id_fk + references + pm_process + constraint pm_process_process_id_nn + not null, + one_line varchar(200) + constraint pm_process_task_one_line_nn + not null, + description varchar(4000), + -- dates are optional, because it may be computed in reference + -- to all other items, or simply not have a deadline + -- percent complete is always 0 + estimated_hours_work numeric, + -- PERT charts require minimum and maximum estimates + -- these are optionally used + estimated_hours_work_min numeric, + estimated_hours_work_max numeric, + ordering integer +); + +comment on table pm_process_task is ' + A template for the tasks that will be created by the process +'; + +create sequence pm_process_task_dependency_seq; + +create table pm_process_task_dependency ( + dependency_id integer + constraint pm_proc_task_dependcy_pk + primary key, + process_task_id integer + constraint pm_proc_task_proc_task_fk + references pm_process_task + on delete cascade, + parent_task_id integer + constraint pm_proc_task_parent_id_fk + references pm_process_task + on delete cascade, + dependency_type varchar(100) + constraint pm_process_task_dep_type + references pm_task_dependency_types, + constraint pm_proc_task_depend_uq + unique (process_task_id, parent_task_id) +); + +comment on table pm_process_task_dependency is ' + Keeps track of dependencies. Used to create the dependencies in the + new tasks. +'; + +create table pm_process_task_assignment ( + process_task_id integer + constraint pm_proc_task_assign_task_fk + references pm_process_task(process_task_id) + on delete cascade, + role_id integer + constraint pm_proc_task_assign_role_fk + references pm_roles, + party_id integer + constraint pm_proc_task_assign_party_fk + references parties(party_id) + on delete cascade, + constraint pm_proc_task_assgn_uq + unique (process_task_id, role_id, party_id) +); + + +comment on table pm_process_task_assignment is ' + Maps who is assigned to process tasks. These will be the default people + assigned to the new tasks +'; + +create table pm_users_viewed ( + viewing_user integer constraint + pm_usrs_viewed_viewing_user_fk + references parties, + viewed_user integer constraint + pm_usrs_viewed_viewed_user_fk + references parties +); + +comment on table pm_users_viewed is ' + Used to keep track of what users to see on the task calendar and other + views. +'; + +@@project-manager-custom-create.sql Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,12 @@ +-- +-- packages/project-manager/sql/postgresql/project-manager-create.sql +-- +-- @author jade@bread.com +-- @creation-date 2003-05-15 +-- @cvs-id $Id: project-manager-create.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- +-- + +\i project-manager-table-create.sql +\i project-manager-functions-create.sql +\i project-manager-notifications-create.sql Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-custom-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-custom-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-custom-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,38 @@ +-- +-- packages/project-manager/sql/postgresql/project-manager-customize.sql +-- +-- @author jader@bread.com +-- @creation-date 2003-12-05 +-- + +-- this file is used to add custom columns to the projects table. +-- you can then customize the columns shown + +-- if you do set this up, you need to set the parameter in the admin +-- UI, so that the add-edit page will know that there is custom code, +-- You'll need to create an add-edit-custom page, filling in the skeleton there + +-- you should use the content_type__create_attribute procedure to add +-- in columns so that the views are correctly recreated. + +-- PROJECTS + +-- example, using customer +-- this is actually done in the table-create script + +-- this adds in the customer column. This is an example of how +-- the custom columns are added in. I put this here as a reminder +-- that other columns can be added in as well. These custom items +-- are in the custom-create.sql script + +select content_type__create_attribute( + 'pm_project', + 'customer_id', + 'integer', + 'Customer', + 'Customers', + null, + null, + 'integer constraint pm_project_customer_fk references organizations' +); + Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-custom-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-custom-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-custom-drop.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,12 @@ +-- packages/project-manager/sql/project-manager-drop.sql +-- drop script +-- +-- @author jade@bread.com +-- @creation-date 2003-12-05 +-- @cvs-id $Id: project-manager-custom-drop.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- + +-- drop any custom tables here. + +select content_type__drop_attribute ('pm_project', 'customer_id', 't'); + Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-drop.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,217 @@ +-- packages/project-manager/sql/project-manager-drop.sql +-- drop script +-- +-- @author jade@bread.com +-- @creation-date 2003-05-15 +-- @cvs-id $Id: project-manager-drop.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- + +-------- +-- TASKS +-------- + +\i project-manager-custom-drop.sql +\i project-manager-notifications-drop.sql + +drop table pm_task_logger_proj_map; + +create function inline_0 () +returns integer as ' +declare + v_item RECORD; + +begin + for v_item in select + item_id + from + cr_items + where + content_type = ''pm_task'' + LOOP + PERFORM pm_task__delete_task_item(v_item.item_id); + end loop; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +-- unregister content_types from folder +create function inline_0 () +returns integer as ' +declare + v_folder_id cr_folders.folder_id%TYPE; + v_item_id cr_items.item_id%TYPE; + v_item_cursor RECORD; +begin + + -- delete all contents of projects folder + FOR v_item_cursor IN + select + item_id + from + cr_items + where + content_type = ''pm_task'' + LOOP + PERFORM pm_project__delete_task_item(v_item_cursor.item_id); + END LOOP; + + -- this table must not hold reference to ''pm_tasks'' type + delete from cr_folder_type_map where content_type = ''pm_tasks''; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +-- unregister content_types from folder +create function inline_0 () +returns integer as ' +declare + v_folder_id cr_folders.folder_id%TYPE; + v_item_id cr_items.item_id%TYPE; + v_item_cursor RECORD; +begin + + -- delete all contents of projects folder + FOR v_item_cursor IN + select + item_id + from + cr_items + where + content_type = ''pm_project'' + LOOP + PERFORM pm_project__delete_project_item(v_item_cursor.item_id); + END LOOP; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + +-- unregister content_types from folder +create function inline_0 () +returns integer as ' +declare + v_folder_id cr_folders.folder_id%TYPE; + v_item_id cr_items.item_id%TYPE; + v_item_cursor RECORD; +begin + + FOR v_item_cursor IN + select folder_id from cr_folders where description=''Project Repository'' + LOOP + PERFORM content_folder__unregister_content_type ( + v_item_cursor.folder_id, -- folder_id + ''pm_project'', -- content_type + ''t'' -- include_subtypes + ); + PERFORM content_folder__delete(v_item_cursor.folder_id); + END LOOP; + + -- this table must not hold reference to ''pm_project'' type + delete from cr_folder_type_map where content_type = ''pm_project''; + + return 0; +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); + + +-- task dependency types +drop table pm_task_dependency_types cascade; +drop table pm_task_dependency cascade; +drop sequence pm_task_dependency_seq; +drop sequence pm_tasks_number_seq; + +select content_type__drop_attribute ('pm_task', 'end_date', 't'); +select content_type__drop_attribute ('pm_task', 'percent_complete', 't'); +select content_type__drop_attribute ('pm_task', 'estimated_hours_work', 't'); +select content_type__drop_attribute ('pm_task', 'estimated_hours_work_min', 't'); +select content_type__drop_attribute ('pm_task', 'estimated_hours_work_max', 't'); +select content_type__drop_attribute ('pm_task', 'actual_hours_worked', 't'); +select content_type__drop_attribute ('pm_task', 'earliest_start', 't'); +select content_type__drop_attribute ('pm_task', 'earliest_finish', 't'); +select content_type__drop_attribute ('pm_task', 'latest_start', 't'); +select content_type__drop_attribute ('pm_task', 'latest_finish', 't'); + +------------- +-- WORKGROUPS +------------- + +drop sequence pm_workgroup_seq; +drop table pm_workgroup_parties; +drop table pm_workgroup; + +------------ +-- PROCESSES +------------ + +drop sequence pm_process_seq; +drop sequence pm_process_task_seq; +drop sequence pm_process_task_dependency_seq; + +drop table pm_process_task_assignment cascade; +drop table pm_process_task_dependency cascade; +drop table pm_process_task cascade; +drop table pm_process cascade; + +--------- +-- OTHERS +--------- +drop table pm_default_roles cascade; +drop table pm_project_assignment cascade; +drop table pm_task_assignment cascade; +drop table pm_roles cascade; +drop sequence pm_role_seq cascade; + + +select drop_package('pm_task'); + + +----------- +-- PROJECTS +----------- + +--drop permissions +delete from acs_permissions where object_id in (select project_id from pm_projects); + + +-- drop package, which drops all functions created with define_function_args +select drop_package('pm_project'); + +--drop table +drop table pm_projects cascade; + +drop sequence pm_project_status_seq; +drop table pm_project_status cascade; + + + +drop sequence pm_task_status_seq; +drop table pm_task_status cascade; + +drop table pm_tasks cascade; +drop table pm_tasks_revisions cascade; + +select content_type__drop_type('pm_task', 't', 'f'); + +select content_type__drop_type('pm_project', 't', 'f'); + +drop table pm_task_xref cascade; +drop table pm_users_viewed cascade; +drop sequence pm_process_instance_seq; +drop table pm_process_instance cascade; +drop table pm_process cascade; +-- note that the Project Repository folder is not deleted + Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-functions-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-functions-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-functions-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,641 @@ +-- +-- packages/project-manager/sql/postgresql/project-manager-functions-create.sql +-- +-- @author jade@bread.com, ncarroll@ee.usyd.edu.au +-- @creation-date 2003-05-15 +-- @cvs-id $Id: project-manager-functions-create.sql,v 1.1 2005/04/29 17:43:36 timoh Exp $ +-- +-- + +-- When we created the acs object type above, we specified a +-- 'name_method'. This is the name of a function that will return the +-- name of the object. This is a convention ensuring that all objects +-- can be identified. Now we have to build that function. In this case, +-- we'll return a field called title as the name. + +select define_function_args('pm_project__name', 'project_id'); + +create or replace function pm_project__name (integer) +returns varchar as ' +declare + p_pm_project_id alias for $1; + v_pm_project_name pm_projectsx.name%TYPE; +begin + select name || ''_'' || p_pm_project_id into v_pm_project_name + from pm_projectsx + where item_id = p_pm_project_id; + return v_pm_project_name; +end; +' language 'plpgsql'; + + +-- Create a new root folder + +select define_function_args('pm_project__new_root_folder', 'package_id'); + +create or replace function pm_project__new_root_folder (integer) +returns integer as ' +declare + p_package_id alias for $1; + + v_folder_id cr_folders.folder_id%TYPE; + v_folder_name cr_items.name%TYPE; +begin + + -- raise notice ''in new root folder''; + + -- Set the folder name + v_folder_name := pm_project__new_unique_name (p_package_id); + + v_folder_id := content_folder__new ( + v_folder_name, -- name + ''Projects'', -- label + ''Project Repository'', -- description + null, -- parent_id + p_package_id, -- context_id + null, -- folder_id + null, -- creation_date + null, -- creation_user + null -- creation_ip + ); + + -- Register the standard content types + PERFORM content_folder__register_content_type ( + v_folder_id, -- folder_id + ''pm_project'', -- content_type + ''f'' -- include_subtypes + ); + + -- there is no facility in the API for adding in the package_id, + -- so we have to do it ourselves + + update cr_folders + set package_id = p_package_id + where folder_id = v_folder_id; + + -- TODO: Handle Permissions here for this folder. + + return v_folder_id; +end;' language 'plpgsql'; + + +-- Returns the root folder corresponding to a particular package instance. +-- Creates a new root folder if one does not exist for the specified package +-- instance. + +select define_function_args('pm_project__get_root_folder', 'package_id,create_if_not_present_p'); + +create or replace function pm_project__get_root_folder (integer, boolean) +returns integer as ' +declare + p_package_id alias for $1; + p_create_if_not_present_p alias for $2; + + v_folder_id cr_folders.folder_id%TYPE; + v_count integer; +begin + + -- raise notice ''in get root folder p_create_if_not_present_p = %'',p_create_if_not_present_p; + + select count(*) into v_count + from cr_folders + where package_id = p_package_id; + + -- raise notice ''count is % for package_id %'', v_count, p_package_id; + + if v_count > 1 then + raise exception ''More than one project repository for this application instance''; + elsif v_count = 1 then + select folder_id into v_folder_id + from cr_folders + where package_id = p_package_id; + else + if p_create_if_not_present_p = true then + -- Must be a new instance. Create a new root folder. + raise notice ''creating a new root repository folder''; + v_folder_id := pm_project__new_root_folder(p_package_id); + else + -- raise notice ''setting to null''; + v_folder_id := null; + end if; + end if; + + -- raise notice ''v_folder_id is %'', v_folder_id; + + return v_folder_id; + +end; ' language 'plpgsql'; + + +-- Create a project item. + +-- A project item should be placed within a folder. Therefore a new project +-- item is associated with creating a new project folder that will contain +-- the project item. A new root project folder will be created if parent_id +-- is null. Otherwise a project folder will be created as a sub-folder +-- of an existing project folder. + +select define_function_args('pm_project__new_project_item', 'project_name, project_code, parent_id, goal, description, mime_type, planned_start_date, planned_end_date, actual_start_date, actual_end_date, logger_project, ongoing_p, status_id, customer_id, creation_date, creation_user, creation_ip, package_id'); + +create or replace function pm_project__new_project_item ( + varchar, -- project_name + varchar, -- project_code + integer, -- parent_id + varchar, -- goal + varchar, -- description + varchar, -- mime_type + timestamptz, -- planned_start_date + timestamptz, -- planned_end_date + timestamptz, -- actual_start_date + timestamptz, -- actual_end_date + integer, -- logger_project + char(1), -- ongoing_p + integer, -- status_id + integer, -- customer_id (organization_id) + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) returns integer +as ' +declare + p_project_name alias for $1; + p_project_code alias for $2; + p_parent_id alias for $3; + p_goal alias for $4; + p_description alias for $5; + p_mime_type alias for $6; + p_planned_start_date alias for $7; + p_planned_end_date alias for $8; + p_actual_start_date alias for $9; + p_actual_end_date alias for $10; + p_logger_project alias for $11; + p_ongoing_p alias for $12; + p_status_id alias for $13; + p_customer_id alias for $14; + p_creation_date alias for $15; + p_creation_user alias for $16; + p_creation_ip alias for $17; + p_package_id alias for $18; + + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_parent_id cr_items.parent_id%TYPE; +begin + select acs_object_id_seq.nextval into v_id from dual; + + v_parent_id := pm_project__get_root_folder (p_package_id, ''t''); + + -- raise notice ''v_parent_id (%) p_parent_id (%)'', v_parent_id, p_parent_id; + + if p_parent_id is not null + then + v_parent_id = p_parent_id; + end if; + + -- raise notice ''v_parent_id (%) p_parent_id (%)'', v_parent_id, p_parent_id; + + v_item_id := content_item__new ( + v_id::varchar, -- name + v_parent_id, -- parent_id + v_id, -- item_id + null, -- locale + now(), -- creation_date + p_creation_user, -- creation_user + p_parent_id, -- context_id + p_creation_ip, -- creation_ip + ''content_item'', -- item_subtype + ''pm_project'', -- content_type + p_project_name, -- title + p_description, -- description + p_mime_type, -- mime_type + null, -- nls_language + null -- data + ); + + v_revision_id := content_revision__new ( + p_project_name, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + v_item_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_projects ( + project_id, project_code, + goal, planned_start_date, + planned_end_date, actual_start_date, actual_end_date, + logger_project, ongoing_p, estimated_finish_date, + earliest_finish_date, latest_finish_date, + actual_hours_completed, + estimated_hours_total, status_id, customer_id) + values ( + v_revision_id, p_project_code, + p_goal, p_planned_start_date, + p_planned_end_date, p_actual_start_date, + p_actual_end_date, p_logger_project, p_ongoing_p, + p_planned_end_date, + p_planned_end_date, p_planned_end_date, ''0'', + ''0'', p_status_id, p_customer_id + ); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; + + +-- The delete function deletes a record and all related overhead. + +select define_function_args('pm_project__delete_project_item', 'project_id'); + +create or replace function pm_project__delete_project_item (integer) +returns integer as ' +declare + p_project_id alias for $1; + v_child cr_items%ROWTYPE; +begin + raise NOTICE ''Deleting pm_project...''; + + for v_child in select + item_id + from + cr_items + where + parent_id = p_project_id and + content_type = ''pm_project'' + LOOP + PERFORM pm_project__delete_project_item(v_child.item_id); + end loop; + + delete from pm_projects where project_id in (select revision_id from pm_projectsx where item_id = p_project_id); + + PERFORM content_item__delete(p_project_id); + return 0; +end;' language 'plpgsql'; + + +select define_function_args('pm_project__new_project_revision', 'item_id, project_name, project_code, parent_id, goal, description, planned_start_date, planned_end_date, actual_start_date, actual_end_date, logger_project, ongoing_p, status_id, organization_id, creation_date, creation_user, creation_ip, package_id'); + +create or replace function pm_project__new_project_revision ( + integer, -- item_id + varchar, -- project_name + varchar, -- project_code + integer, -- parent_id + varchar, -- goal + varchar, -- description + timestamptz, -- planned_start_date + timestamptz, -- planned_end_date + timestamptz, -- actual_start_date + timestamptz, -- actual_end_date + integer, -- logger_project + char(1), -- ongoing_p + integer, -- status_id + integer, -- organization_id (customer) + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) returns integer +as ' +declare + p_item_id alias for $1; + p_project_name alias for $2; + p_project_code alias for $3; + p_parent_id alias for $4; + p_goal alias for $5; + p_description alias for $6; + p_planned_start_date alias for $7; + p_planned_end_date alias for $8; + p_actual_start_date alias for $9; + p_actual_end_date alias for $10; + p_logger_project alias for $11; + p_ongoing_p alias for $12; + p_status_id alias for $13; + p_customer_id alias for $14; + p_creation_date alias for $15; + p_creation_user alias for $16; + p_creation_ip alias for $17; + p_package_id alias for $18; + + v_revision_id cr_revisions.revision_id%TYPE; +begin + + -- the item_id is the project_id + + v_revision_id := content_revision__new ( + p_project_name, -- title + p_description, -- description + now(), -- publish_date + ''text/plain'', -- mime_type + NULL, -- nls_language + NULL, -- data + p_item_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_projects ( + project_id, project_code, + goal, planned_start_date, + planned_end_date, actual_start_date, actual_end_date, + logger_project, + ongoing_p, status_id, customer_id) + values ( + v_revision_id, p_project_code, + p_goal, p_planned_start_date, + p_planned_end_date, p_actual_start_date, + p_actual_end_date, + p_logger_project, p_ongoing_p, p_status_id, p_customer_id); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; + + + +-- Creates and returns a unique name. + +select define_function_args('pm_project__new_unique_name', 'package_id'); + +create or replace function pm_project__new_unique_name (integer) +returns text as ' +declare + p_package_id alias for $1; + + v_name cr_items.name%TYPE; + v_package_key apm_packages.package_key%TYPE; + v_id integer; +begin + select package_key into v_package_key from apm_packages + where package_id = p_package_id; + + select acs_object_id_seq.nextval into v_id from dual; + + -- Set the name + select v_package_key || ''_'' || + to_char(current_timestamp, ''YYYYMMDD'') || ''_'' || + v_id into v_name; + + return v_name; +end;' language 'plpgsql'; + +---------------------------------- +-- Tasks +---------------------------------- + +-- When we created the acs object type above, we specified a +-- 'name_method'. This is the name of a function that will return the +-- name of the object. This is a convention ensuring that all objects +-- can be identified. Now we have to build that function. In this case, +-- we'll return a field called title as the name. + +select define_function_args('pm_task__name', 'task_id'); + +create or replace function pm_task__name (integer) +returns varchar as ' +declare + p_pm_task_id alias for $1; + v_pm_task_name cr_items.name%TYPE; +begin + select i.name || ''_'' || p_pm_task_id into v_pm_task_name + from cr_items i + where i.item_id = p_pm_task_id; + return v_pm_task_name; +end; +' language 'plpgsql'; + + +-- Create a task item. + +-- A task should be placed within a project or another task. +-- If it is not associated with a project, then it is placed in the root +-- project repository folder. + +select define_function_args('pm_task__new_task_item', 'project_id, title, description, html_p, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, status_id, process_instance_id, creation_date, creation_user, creation_ip, package_id, priority'); + +create or replace function pm_task__new_task_item ( + integer, -- project_id + varchar, -- title + varchar, -- description + varchar, -- html_p + timestamptz, -- end_date + numeric, -- percent_complete + numeric, -- estimated_hours_work + numeric, -- estimated_hours_work_min + numeric, -- estimated_hours_work_max, + integer, -- status_id + integer, -- process_instance_id + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer, -- package_id + integer -- priority +) returns integer +as ' +declare + p_project_id alias for $1; + p_title alias for $2; + p_description alias for $3; + p_mime_type alias for $4; + p_end_date alias for $5; + p_percent_complete alias for $6; + p_estimated_hours_work alias for $7; + p_estimated_hours_work_min alias for $8; + p_estimated_hours_work_max alias for $9; + p_status_id alias for $10; + p_process_instance_id alias for $11; + p_creation_date alias for $12; + p_creation_user alias for $13; + p_creation_ip alias for $14; + p_package_id alias for $15; + p_priority alias for $16; + + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_task_number integer; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + + -- create the task_number + + v_item_id := content_item__new ( + v_id::varchar, -- name + p_project_id, -- parent_id + v_id, -- item_id + null, -- locale + now(), -- creation_date + p_creation_user, -- creation_user + p_package_id, -- context_id + p_creation_ip, -- creation_ip + ''content_item'', -- item_subtype + ''pm_task'', -- content_type + p_title, -- title + p_description, -- description + p_mime_type, -- mime_type + null, -- nls_language + null -- data + ); + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + v_item_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks ( + task_id, task_number, status, process_instance) + values ( + v_item_id, v_task_number, p_status_id, p_process_instance_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, priority) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, ''0'', p_priority); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; + + +select define_function_args('pm_task__new_task_revision', 'task_id, project_id, title, description, mime_type, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, creation_date, creation_user, creation_ip, package_id, priority'); + +create or replace function pm_task__new_task_revision ( + integer, -- task_id (the item_id) + integer, -- project_id + varchar, -- title + varchar, -- description + varchar, -- mime_type + timestamptz, -- end_date + numeric, -- percent_complete + numeric, -- estimated_hours_work + numeric, -- estimated_hours_work_min + numeric, -- estimated_hours_work_max + numeric, -- actual_hours_worked + integer, -- status_id + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer, -- package_id + integer -- priority +) returns integer +as ' +declare + p_task_id alias for $1; + p_project_id alias for $2; + p_title alias for $3; + p_description alias for $4; + p_mime_type alias for $5; + p_end_date alias for $6; + p_percent_complete alias for $7; + p_estimated_hours_work alias for $8; + p_estimated_hours_work_min alias for $9; + p_estimated_hours_work_max alias for $10; + p_actual_hours_worked alias for $11; + p_status_id alias for $12; + p_creation_date alias for $13; + p_creation_user alias for $14; + p_creation_ip alias for $15; + p_package_id alias for $16; + p_priority alias for $17; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + update cr_items set parent_id = p_project_id where item_id = p_task_id; + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + p_task_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, priority) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, p_actual_hours_worked, p_priority); + + update pm_tasks set status = p_status_id where task_id = p_task_id; + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; + + +-- The delete function deletes a record and all related overhead. + +select define_function_args('pm_task__delete_task_item', 'task_id'); + +create or replace function pm_task__delete_task_item (integer) +returns integer as ' +declare + p_task_id alias for $1; +begin + delete from pm_tasks_revisions + where task_revision_id in (select revision_id from pm_tasks_revisionsx where item_id = p_task_id); + + delete from pm_tasks + where task_id = p_task_id; + + raise NOTICE ''Deleting pm_task...''; + + PERFORM content_item__delete(p_task_id); + return 0; +end;' language 'plpgsql'; Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-notifications-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-notifications-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-notifications-create.sql 29 Apr 2005 17:43:36 -0000 1.1 @@ -0,0 +1,70 @@ +-- Following directions at +-- http://openacs.org/doc/openacs-HEAD/tutorial-notifications.html + +-- using pm_task_notif_type instead of lars_blogger_notif_type +-- using project-manager instead of lars-blogger + +create function inline_0() returns integer as ' +declare + impl_id integer; + v_foo integer; +begin + -- the notification type impl + impl_id := acs_sc_impl__new ( + ''NotificationType'', + ''pm_task_notif_type'', + ''project-manager'' + ); + + v_foo := acs_sc_impl_alias__new ( + ''NotificationType'', + ''pm_task_notif_type'', + ''GetURL'', + ''pm::task::get_url'', + ''TCL'' + ); + + v_foo := acs_sc_impl_alias__new ( + ''NotificationType'', + ''pm_task_notif_type'', + ''ProcessReply'', + ''pm::task::process_reply'', + ''TCL'' + ); + + PERFORM acs_sc_binding__new ( + ''NotificationType'', + ''pm_task_notif_type'' + ); + + v_foo:= notification_type__new ( + NULL, + impl_id, + ''pm_task_notif'', + ''Task Notification'', + ''Notifications of task changes'', + now(), + NULL, + NULL, + NULL + ); + + -- enable the various intervals and delivery methods + insert into notification_types_intervals + (type_id, interval_id) + select v_foo, interval_id + from notification_intervals where name in (''instant'',''hourly'',''daily''); + + insert into notification_types_del_methods + (type_id, delivery_method_id) + select v_foo, delivery_method_id + from notification_delivery_methods where short_name in (''email''); + + + return (0); +end; +' language 'plpgsql'; + + +select inline_0(); +drop function inline_0(); Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-notifications-drop.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-notifications-drop.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-notifications-drop.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,92 @@ +-- +-- Project Manager +-- +-- @author jader@bread.com +-- @author gwong@orchardlabs.com,ben@openforce.biz +-- @creation-date 2002-05-16 +-- +-- This code is newly concocted by Ben, but with significant concepts and code +-- lifted from Gilbert's UBB forums. Thanks Orchard Labs. +-- Jade in turn lifted this from gwong and ben. +-- + +create function inline_0 () +returns integer as ' +declare + row record; +begin + for row in select nt.type_id + from notification_types nt + where nt.short_name in (''pm_task_notif'') + loop + perform notification_type__delete(row.type_id); + end loop; + + return null; +end;' language 'plpgsql'; + +select inline_0(); +drop function inline_0 (); + +-- +-- Service contract drop stuff was missing - Roberto Mello +-- + +create function inline_0() returns integer as ' +declare + impl_id integer; + v_foo integer; +begin + + -- the notification type impl + impl_id := acs_sc_impl__get_id ( + ''NotificationType'', -- impl_contract_name + ''pm_task_notif_type'' -- impl_name + ); + + PERFORM acs_sc_binding__delete ( + ''NotificationType'', + ''pm_task_notif_type'' + ); + + v_foo := acs_sc_impl_alias__delete ( + ''NotificationType'', -- impl_contract_name + ''pm_task_notif_type'', -- impl_name + ''GetURL'' -- impl_operation_name + ); + + v_foo := acs_sc_impl_alias__delete ( + ''NotificationType'', -- impl_contract_name + ''pm_task_notif_type'', -- impl_name + ''ProcessReply'' -- impl_operation_name + ); + + select into v_foo type_id + from notification_types + where sc_impl_id = impl_id + and short_name = ''pm_task_notif''; + + perform notification_type__delete (v_foo); + + delete from notification_types_intervals + where type_id = v_foo + and interval_id in ( + select interval_id + from notification_intervals + where name in (''instant'',''hourly'',''daily'') + ); + + delete from notification_types_del_methods + where type_id = v_foo + and delivery_method_id in ( + select delivery_method_id + from notification_delivery_methods + where short_name in (''email'') + ); + + return (0); +end; +' language 'plpgsql'; + +select inline_0(); +drop function inline_0(); Index: openacs-4/packages/project-manager/sql/postgresql/project-manager-table-create.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/project-manager-table-create.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/project-manager-table-create.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,673 @@ +-- packages/project-manager/sql/postgresql/project-manager-table-create.sql +-- +-- @author jader@bread.com +-- @author ncarroll@ee.usyd.edu.au was involved in creating the initial CR version +-- @author everyone else involved in this thread: http://openacs.org/forums/message-view?message_id=90742 +-- @creation-date 2003-05-15 +-- + +-- PROJECTS + +create sequence pm_project_status_seq start 3; + +create table pm_project_status ( + status_id integer + constraint pm_project_status_pk + primary key, + description varchar(100), + -- closed or open + status_type char(1) default 'c' + constraint pm_projects_status_type_ck + check (status_type in ('c','o')) +); + +insert into pm_project_status (status_id, description, status_type) values +(1, 'Open', 'o'); +insert into pm_project_status (status_id, description, status_type) values +(2, 'Closed', 'c'); + + +-- project revisions, items are kept in cr_items + +create table pm_projects ( + project_id integer + constraint pm_proj_rev_fk + references cr_revisions on delete cascade + constraint pm_proj_rev_pk + primary key, + -- a user-specified project code + project_code varchar(255), + goal varchar(4000), + planned_start_date timestamptz, + planned_end_date timestamptz, + actual_start_date timestamptz, + actual_end_date timestamptz, + status_id integer + constraint pm_projects_status_id_nn + not null + constraint pm_projects_status_id_fk + references pm_project_status, + -- if ongoing_p is true, then actual_end_date must be null + ongoing_p char(1) default 'f' + constraint pm_projects_ongoing_p_ck + check (ongoing_p in ('t','f')), + estimated_finish_date timestamptz, + earliest_finish_date timestamptz, + latest_finish_date timestamptz, + -- denormalized, taken from logger + actual_hours_completed numeric, + estimated_hours_total numeric, + -- The logger package keeps its own projects table + logger_project integer + constraint pm_projects_logger_pj_nn + not null + constraint pm_projects_logger_pj_fk + references logger_projects +); + + +-- create the content type + select content_type__create_type ( + 'pm_project', -- content_type + 'content_revision', -- supertype + 'Project', -- pretty_name + 'Projects', -- pretty_plural + 'pm_projects', -- table_name + 'project_id', -- id_column + 'pm_project__name' -- name_method + ); + + +-- other fields are added in too. See the -custom script. + + +-- ROLES + +create sequence pm_role_seq start 4; + +create table pm_roles ( + role_id integer + constraint pm_role_id_pk + primary key, + one_line varchar(100) + constraint pm_role_one_line_uq + unique, + description varchar(2000), + sort_order integer, + is_observer_p char(1) default 'f' + constraint pm_role_is_observer_ck + check (is_observer_p in ('t','f')), + is_lead_p char(1) default 'f' + constraint pm_role_is_lead_ck + check (is_lead_p in ('t','f')) +); + + +comment on table pm_roles is ' + Roles represent the way in which a party participates in a project + or task. For example, they could be a manager, or client, or + participant.. The sort order determines what order it is displayed + in. The is_observer_p specifies whether they are directly + responsible for the task, or are just observers on it. +'; + +insert into pm_roles (role_id, one_line, description, sort_order, is_lead_p) values ('1','Lead','Team members who are responsible for the completion of the project','10','t'); +insert into pm_roles (role_id, one_line, description, sort_order) values ('2','Player','A person on the team responsible for completion of the project','20'); +insert into pm_roles (role_id, one_line, description, sort_order, is_observer_p) values ('3','Watcher','A person interested in developments, possibly helping out on it.','30','t'); + + +create table pm_default_roles ( + role_id integer + constraint pm_default_role_fk + references pm_roles + on delete cascade, + party_id integer + constraint pm_default_role_party_fk + references parties(party_id) + on delete cascade, + constraint pm_default_roles_uq + unique (role_id, party_id) +); + +comment on table pm_default_roles is ' + Specifies what role a person is a part of by default +'; + +-- PROJECT ASSIGNMENT + +create table pm_project_assignment ( + project_id integer + constraint pm_proj_role_map_project_fk + references cr_items + on delete cascade, + role_id integer + constraint pm_project_role_map_role_fk + references pm_roles, + party_id integer + constraint pm_project_role_map_user_id_fk + references parties(party_id) + on delete cascade, + constraint pm_project_assignment_uq + unique (project_id, role_id, party_id) +); + + +comment on table pm_project_assignment is ' + Maps who is a part of what project, and in what capacity +'; + + +-- PROCESSES + +create sequence pm_process_seq; + +create table pm_process ( + process_id integer + constraint pm_process_id_pk + primary key, + one_line varchar(200) + constraint pm_process_one_line_nn + not null, + description varchar(1000), + party_id integer + constraint pm_process_party_fk + references parties + constraint pm_process_party_nn + not null, + creation_date timestamptz, + deleted_p char(1) default 'f' + constraint pm_process_deleted_p_ck + check (deleted_p in ('t','f')) +); + +comment on table pm_process is ' + Processes are a set of templates for tasks, so that people can + create sets of tasks quickly. Their structure needs to match that of + tasks. The process holds the meta information, and is also an identifier + that is used by the user to select which process they''d like to copy or + use +'; + +create or replace view +pm_process_active as + SELECT * FROM pm_process where deleted_p = 'f'; + +-- each time a process is used, it creates an instance of that process +-- we use this to allow a user to see overviews of process status, etc.. + +create sequence pm_process_instance_seq start 1; + +create table pm_process_instance ( + instance_id integer + constraint pm_process_instance_id_pk + primary key, + name varchar(200), + process_id integer + constraint pm_process_instance_process_fk + references pm_process on delete cascade, + project_item_id integer + constraint pm_process_project_fk + references cr_items +); + + +create sequence pm_process_task_seq; + +create table pm_process_task ( + process_task_id integer + constraint pm_process_task_id_pk + primary key, + process_id integer + constraint pm_process_process_id_fk + references + pm_process + constraint pm_process_process_id_nn + not null, + one_line varchar(200) + constraint pm_process_task_one_line_nn + not null, + description varchar(4000), + mime_type varchar(200) + constraint pm_process_task_mime_type_fk + references cr_mime_types(mime_type) + on update no action on delete no action + default 'text/plain', + -- dates are optional, because it may be computed in reference + -- to all other items, or simply not have a deadline + -- percent complete is always 0 + estimated_hours_work numeric, + -- PERT charts require minimum and maximum estimates + -- these are optionally used + estimated_hours_work_min numeric, + estimated_hours_work_max numeric, + ordering integer +); + +comment on table pm_process_task is ' + A template for the tasks that will be created by the process +'; + +-- DEPENDENCIES + +-- dependency types +-- such as: +-- cannot start until Task X finishes +-- cannot start until Task X begins +-- cannot finish until Task X finishes +-- cannot finish until Task X begins + +create table pm_task_dependency_types ( + short_name varchar(100) + constraint pm_task_const_sn_pk + primary key, + description varchar(1000) +); + +insert into pm_task_dependency_types (short_name, description) values ('start_before_start','Starts before this starts'); +insert into pm_task_dependency_types (short_name, description) values ('start_before_finish','Starts before this finishes'); +insert into pm_task_dependency_types (short_name, description) values ('finish_before_start','Finishes before this starts'); +insert into pm_task_dependency_types (short_name, description) values ('finish_before_finish','Finishes before this finishes'); + +create sequence pm_process_task_dependency_seq; + +create table pm_process_task_dependency ( + dependency_id integer + constraint pm_proc_task_dependcy_pk + primary key, + process_task_id integer + constraint pm_proc_task_proc_task_fk + references pm_process_task + on delete cascade, + parent_task_id integer + constraint pm_proc_task_parent_id_fk + references pm_process_task + on delete cascade, + dependency_type varchar + constraint pm_process_task_dep_type + references pm_task_dependency_types, + constraint pm_proc_task_depend_uq + unique (process_task_id, parent_task_id) +); + +comment on table pm_process_task_dependency is ' + Keeps track of dependencies. Used to create the dependencies in the + new tasks. +'; + +create table pm_process_task_assignment ( + process_task_id integer + constraint pm_proc_task_assign_task_fk + references pm_process_task(process_task_id) + on delete cascade, + role_id integer + constraint pm_task_assignment_role_fk + references pm_roles, + party_id integer + constraint pm_task_assignment_party_fk + references parties(party_id) + on delete cascade, + constraint pm_proc_task_assgn_uq + unique (process_task_id, role_id, party_id) +); + + +comment on table pm_process_task_assignment is ' + Maps who is assigned to process tasks. These will be the default people + assigned to the new tasks +'; + + + +-- TASKS + +-- we create two tables to store task information +-- the information that we keep revisions on is in the +-- pm_task_revisions table, the rest is in pm_task + +create sequence pm_task_status_seq start 3; + +create table pm_task_status ( + status_id integer + constraint pm_task_status_pk + primary key, + description varchar(100), + -- closed or open + status_type char(1) default 'c' + constraint pm_task_status_type_ck + check (status_type in ('c','o')) +); + +insert into pm_task_status (status_id, description, status_type) values +(1, 'Open', 'o'); +insert into pm_task_status (status_id, description, status_type) values +(2, 'Closed', 'c'); + + +create sequence pm_tasks_number_seq; + +create table pm_tasks ( + task_id integer + constraint pm_tasks_task_id_fk + references cr_items + on delete cascade + constraint pm_task_task_id_pk + primary key, + task_number integer, + status integer + constraint pm_tasks_task_status_fk + references pm_task_status, + deleted_p char(1) default 'f' + constraint pm_tasks_deleted_p_ck + check (deleted_p in ('t','f')), + process_instance integer + constraint pm_tasks_process_instance_fk + references + pm_process_instance +); + +CREATE OR REPLACE view +pm_tasks_active as + SELECT task_id, task_number, status, process_instance FROM pm_tasks where deleted_p = 'f'; + + +create table pm_tasks_revisions ( + task_revision_id integer + constraint pm_task_revs_id_fk + references cr_revisions + on delete cascade + constraint pm_task_revs_id_pk + primary key, + -- dates are optional, because it may be computed in reference + -- to all other items, or simply not have a deadline + end_date timestamptz, + -- keep track of completion status + percent_complete numeric + constraint pm_task_per_complete_gt_ck + check(percent_complete >= 0) + constraint pm_task_per_complete_lt_ck + check(percent_complete <= 100), + estimated_hours_work numeric, + -- PERT charts require minimum and maximum estimates + -- these are optionally used + estimated_hours_work_min numeric, + estimated_hours_work_max numeric, + -- this should be computed by checking with logger? The actual + -- data should be in logger, logged by who did it, when etc.. + -- or we can create a separate table to keep track of task hours + -- and make sure its data model is similar to logger? + actual_hours_worked numeric, + -- network diagram stuff, computed + earliest_start timestamptz, + earliest_finish timestamptz, + latest_start timestamptz, + latest_finish timestamptz, + -- How important is this task + priority integer default 0 +); + +-- create the content type +select content_type__create_type ( + 'pm_task', -- content_type + 'content_revision', -- supertype + 'Task', -- pretty_name + 'Tasks', -- pretty_plural + 'pm_tasks_revisions', -- table_name (should this be pm_task?) + 'task_revision_id', -- id_column + 'pm_task__name' -- name_method +); + +-- add in attributes + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'end_date', -- attribute_name + 'date', -- datatype + 'End date', -- pretty_name + 'End dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'percent_complete', -- attribute_name + 'number', -- datatype + 'Percent complete', -- pretty_name + 'Percents complete', -- pretty_plural + null, -- sort_order + null, -- default value + 'numeric' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'estimated_hours_work', -- attribute_name + 'number', -- datatype + 'Estimated hours work', -- pretty_name + 'Estimated hours work', -- pretty_plural + null, -- sort_order + null, -- default value + 'numeric' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'estimated_hours_work_min', -- attribute_name + 'number', -- datatype + 'Estimated minimum hours', -- pretty_name + 'Estimated minimum hours', -- pretty_plural + null, -- sort_order + null, -- default value + 'numeric' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'estimated_hours_work_max', -- attribute_name + 'number', -- datatype + 'Estimated maximum hours', -- pretty_name + 'Estimated maximum hours', -- pretty_plural + null, -- sort_order + null, -- default value + 'numeric' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'actual_hours_worked', -- attribute_name + 'number', -- datatype + 'Actual hours worked', -- pretty_name + 'Actual hours worked', -- pretty_plural + null, -- sort_order + null, -- default value + 'numeric' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'earliest_start', -- attribute_name + 'date', -- datatype + 'Earliest start date', -- pretty_name + 'Earliest start dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'earliest_finish', -- attribute_name + 'date', -- datatype + 'Earliest finish date', -- pretty_name + 'Earliest finish dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'latest_start', -- attribute_name + 'date', -- datatype + 'Latest start date', -- pretty_name + 'Latest start dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec +); + +select content_type__create_attribute ( + 'pm_task', -- content_type + 'latest_finish', -- attribute_name + 'date', -- datatype + 'Latest finish date', -- pretty_name + 'Latest finish dates', -- pretty_plural + null, -- sort_order + null, -- default value + 'timestamptz' -- column_spec +); + + + +create table pm_task_logger_proj_map ( + task_item_id integer + constraint pm_task_log_proj_map_t_nn + not null + constraint pm_task_log_proj_map_t_fk + references pm_tasks + on delete cascade, + logger_entry integer + constraint pm_task_log_proj_map_l_nn + not null + constraint pm_task_log_proj_map_l_fk + references logger_entries + on delete cascade, + constraint pm_task_logger_proj_map_uq + unique (task_item_id, logger_entry) +); + + + + +create sequence pm_task_dependency_seq; + +create table pm_task_dependency ( + dependency_id integer + constraint pm_task_const_id_pk + primary key, + task_id integer + constraint pm_task_const_task_id_nn + not null + constraint pm_task_const_task_id_fk + references pm_tasks + on delete cascade, + parent_task_id integer + constraint pm_tasks_const_parent_id_nn + not null + constraint pm_tasks_const_parent_id_fk + references pm_tasks + on delete cascade, + dependency_type varchar + constraint pm_tasks_const_type_nn + not null + constraint pm_tasks_const_type_fk + references pm_task_dependency_types, + constraint pm_task_dependency_uq + unique (task_id, parent_task_id) +); + + +-- WORKGROUPS: currently not used + +create sequence pm_workgroup_seq; + +create table pm_workgroup ( + workgroup_id integer + constraint pm_workgroup_id_pk + primary key, + one_line varchar(100) + constraint pm_workgroup_one_line_uq + unique, + description varchar(2000), + sort_order integer +); + +create table pm_workgroup_parties ( + workgroup_id integer + constraint pm_workgroup_parties_wg_id_fk + references pm_workgroup(workgroup_id) + on delete cascade, + party_id integer + constraint pm_workgroup_party_fk + references parties(party_id) + on delete cascade, + role_id integer + constraint pm_workgroup_role_id + references pm_roles, + constraint pm_workgroup_parties_uq + unique (workgroup_id, party_id, role_id) +); + + +-- TASK ASSIGNMENTS + +create table pm_task_assignment ( + task_id integer + constraint pm_task_assignment_task_fk + references pm_tasks(task_id) + on delete cascade, + role_id integer + constraint pm_task_assignment_role_fk + references pm_roles, + party_id integer + constraint pm_task_assignment_party_fk + references parties(party_id) + on delete cascade, + constraint pm_task_assignment_uq + unique (task_id, role_id, party_id) +); + + +comment on table pm_task_assignment is ' + Maps who is a part of what task, and in what capacity +'; + +-- TASK CROSS REFERENCES + +create table pm_task_xref ( + task_id_1 integer + constraint pm_task_xref_task1_nn + not null + constraint pm_task_xref_task1_fk + references pm_tasks(task_id) + on delete cascade, + task_id_2 integer + constraint pm_task_xref_task2_nn + not null + constraint pm_task_xref_task2_fk + references pm_tasks(task_id) + on delete cascade, + constraint pm_task_xref_lt check (task_id_1 < task_id_2) +); + +comment on table pm_task_xref is ' + Maps related tasks. +'; + + +create table pm_users_viewed ( + viewing_user integer constraint + pm_users_viewed_viewing_user_fk + references parties, + viewed_user integer constraint + pm_users_viewed_viewed_user_fk + references parties +); + +comment on table pm_users_viewed is ' + Used to keep track of what users to see on the task calendar and other + views. +'; + +\i project-manager-custom-create.sql Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.02-1.03.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.02-1.03.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.02-1.03.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,87 @@ +-- +-- Upgrade script for project-manager 1.03 +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-05-14 +-- @cvs-id $Id: upgrade-1.02-1.03.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +-- the only change in this function is to change the project when +-- editing tasks. Previously, it would always leave the task in the +-- same project. + +create or replace function pm_task__new_task_revision ( + integer, -- task_id (the item_id) + integer, -- project_id + varchar, -- title + varchar, -- description + varchar, -- mime_type + timestamptz, -- end_date + numeric, -- percent_complete + numeric, -- estimated_hours_work + numeric, -- estimated_hours_work_min + numeric, -- estimated_hours_work_max + numeric, -- actual_hours_worked + integer, -- status_id + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) returns integer +as ' +declare + p_task_id alias for $1; + p_project_id alias for $2; + p_title alias for $3; + p_description alias for $4; + p_mime_type alias for $5; + p_end_date alias for $6; + p_percent_complete alias for $7; + p_estimated_hours_work alias for $8; + p_estimated_hours_work_min alias for $9; + p_estimated_hours_work_max alias for $10; + p_actual_hours_worked alias for $11; + p_status_id alias for $12; + p_creation_date alias for $13; + p_creation_user alias for $14; + p_creation_ip alias for $15; + p_package_id alias for $16; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + update cr_items set parent_id = p_project_id where item_id = p_task_id; + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + p_task_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, p_actual_hours_worked); + + update pm_tasks set status = p_status_id where task_id = p_task_id; + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.03-1.04b1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.03-1.04b1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.03-1.04b1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,70 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-05-19 +-- @arch-tag: 551cfc66-62c5-4f75-a321-e879d75b44b1 +-- @cvs-id $Id: upgrade-1.03-1.04b1.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +-- fixes name function + +create or replace function pm_project__name (integer) +returns varchar as ' +declare + p_pm_project_id alias for $1; + v_pm_project_name pm_projectsx.name%TYPE; +begin + select name || ''_'' || p_pm_project_id into v_pm_project_name + from pm_projectsx + where item_id = p_pm_project_id; + return v_pm_project_name; +end; +' language 'plpgsql'; + + +-- untested fix for bug #1796 + +create or replace function pm_project__new_root_folder (integer) +returns integer as ' +declare + p_package_id alias for $1; + + v_folder_id cr_folders.folder_id%TYPE; + v_folder_name cr_items.name%TYPE; +begin + + -- raise notice ''in new root folder''; + + -- Set the folder name + v_folder_name := pm_project__new_unique_name (p_package_id); + + v_folder_id := content_folder__new ( + v_folder_name, -- name + ''Projects'', -- label + ''Project Repository'', -- description + p_package_id -- parent_id + ); + + -- Register the standard content types + PERFORM content_folder__register_content_type ( + v_folder_id, -- folder_id + ''pm_project'', -- content_type + ''f'' -- include_subtypes + ); + + -- there is no facility in the API for adding in the package_id, + -- so we have to do it ourselves + + update cr_folders + set package_id = p_package_id + where folder_id = v_folder_id; + + -- TODO: Handle Permissions here for this folder. + + return v_folder_id; +end;' language 'plpgsql'; + +-- upgrade script to fix bug #1796 + +update cr_items set parent_id = (select package_id from cr_folders where folder_id = item_id and label = 'Projects') where item_id = (select folder_id from cr_folders where label = 'Projects' and description = 'Project Repository'); Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.04b1-1.05.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.04b1-1.05.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.04b1-1.05.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,53 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-06-02 +-- @arch-tag: 91272478-d825-42e8-b628-534886dffd84 +-- @cvs-id $Id: upgrade-1.04b1-1.05.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +create or replace function pm_project__new_root_folder (integer) +returns integer as ' +declare + p_package_id alias for $1; + + v_folder_id cr_folders.folder_id%TYPE; + v_folder_name cr_items.name%TYPE; +begin + + -- raise notice ''in new root folder''; + + -- Set the folder name + v_folder_name := pm_project__new_unique_name (p_package_id); + + v_folder_id := content_folder__new ( + v_folder_name, -- name + ''Projects'', -- label + ''Project Repository'', -- description + null, -- parent_id + p_package_id, -- context_id + null, -- folder_id + null, -- creation_date + null, -- creation_user + null -- creation_ip + ); + + -- Register the standard content types + PERFORM content_folder__register_content_type ( + v_folder_id, -- folder_id + ''pm_project'', -- content_type + ''f'' -- include_subtypes + ); + + -- there is no facility in the API for adding in the package_id, + -- so we have to do it ourselves + + update cr_folders + set package_id = p_package_id + where folder_id = v_folder_id; + + -- TODO: Handle Permissions here for this folder. + + return v_folder_id; +end;' language 'plpgsql'; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.08b1-1.09b1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.08b1-1.09b1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-1.08b1-1.09b1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,10 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-06-24 +-- @arch-tag: dac85e4c-c80a-4e17-b3ce-6ce34d9510c8 +-- @cvs-id $Id: upgrade-1.08b1-1.09b1.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +alter table pm_process_task add column ordering integer; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.12-2.13b1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.12-2.13b1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.12-2.13b1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,16 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-07-16 +-- @arch-tag: aa453882-e63e-4582-a1d4-097df7792d23 +-- @cvs-id $Id: upgrade-2.12-2.13b1.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +alter table pm_tasks add column deleted_p char(1); + +alter table pm_tasks alter column deleted_p set default 'f'; +update pm_tasks set deleted_p = 'f'; + +alter table pm_tasks add constraint pm_tasks_deleted_p_ck + check (deleted_p in ('t','f')); Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.13b1-2.13b2.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.13b1-2.13b2.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.13b1-2.13b2.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,12 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-07-16 +-- @arch-tag: 99b969e0-4944-4656-b5f9-61df7e10344c +-- @cvs-id $Id: upgrade-2.13b1-2.13b2.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +CREATE OR REPLACE view +pm_tasks_active as + SELECT task_id, task_number, status FROM pm_tasks where deleted_p = 'f'; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.15b4-2.16b1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.15b4-2.16b1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.15b4-2.16b1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,22 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-09-13 +-- @arch-tag: 858b0c43-d09d-4caa-ad37-09be9b5cbf4d +-- @cvs-id $Id: upgrade-2.15b4-2.16b1.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +create table pm_users_viewed ( + viewing_user integer constraint + pm_users_viewed_viewing_user_fk + references parties, + viewed_user integer constraint + pm_users_viewed_viewed_user_fk + references parties +); + +comment on table pm_users_viewed is ' + Used to keep track of what users to see on the task calendar and other + views. +'; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.20b3-2.21b1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.20b3-2.21b1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.20b3-2.21b1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,16 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-10-08 +-- @arch-tag: fe217011-50b1-4ee9-a686-21dd51cc2384 +-- @cvs-id $Id: upgrade-2.20b3-2.21b1.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +alter table pm_roles add column is_lead_p char(1) + constraint pm_role_is_lead_ck + check (is_lead_p in ('t','f')); + +alter table pm_roles alter column is_lead_p set default 'f'; + +update pm_roles set is_lead_p = 't' where one_line = 'Lead'; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.21b1-2.50b1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.21b1-2.50b1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.21b1-2.50b1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,165 @@ +-- +-- +-- +-- @author Jade Rubick (jader@bread.com) +-- @creation-date 2004-10-11 +-- @arch-tag: b03e1fb8-aee1-4429-b6fd-e3e754a5f30a +-- @cvs-id $Id: upgrade-2.21b1-2.50b1.sql,v 1.1 2005/04/29 17:43:37 timoh Exp $ +-- + +-- each time a process is used, it creates an instance of that process +-- we use this to allow a user to see overviews of process status, etc.. + +create sequence pm_process_instance_seq start 1; + +create table pm_process_instance ( + instance_id integer + constraint pm_process_instance_id_pk + primary key, + name varchar(200), + process_id integer + constraint pm_process_instance_process_fk + references pm_process on delete cascade, + project_item_id integer + constraint pm_process_project_fk + references cr_items +); + +alter table pm_tasks add column + process_instance integer + constraint pm_tasks_process_instance_fk + references pm_process_instance; + +drop view pm_tasks_active; + +CREATE view + pm_tasks_active as + SELECT task_id, task_number, status, process_instance FROM pm_tasks where deleted_p = 'f'; + + +select define_function_args('pm_task__new_task_item', 'project_id, title, description, html_p, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, status_id, process_instance_id, creation_date, creation_user, creation_ip, package_id'); + +create or replace function pm_task__new_task_item ( + integer, -- project_id + varchar, -- title + varchar, -- description + varchar, -- html_p + timestamptz, -- end_date + numeric, -- percent_complete + numeric, -- estimated_hours_work + numeric, -- estimated_hours_work_min + numeric, -- estimated_hours_work_max, + integer, -- status_id + integer, -- process_instance_id + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer -- package_id +) returns integer +as ' +declare + p_project_id alias for $1; + p_title alias for $2; + p_description alias for $3; + p_mime_type alias for $4; + p_end_date alias for $5; + p_percent_complete alias for $6; + p_estimated_hours_work alias for $7; + p_estimated_hours_work_min alias for $8; + p_estimated_hours_work_max alias for $9; + p_status_id alias for $10; + p_process_instance_id alias for $11; + p_creation_date alias for $12; + p_creation_user alias for $13; + p_creation_ip alias for $14; + p_package_id alias for $15; + + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_task_number integer; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + + -- create the task_number + + v_item_id := content_item__new ( + v_id::varchar, -- name + p_project_id, -- parent_id + v_id, -- item_id + null, -- locale + now(), -- creation_date + p_creation_user, -- creation_user + p_package_id, -- context_id + p_creation_ip, -- creation_ip + ''content_item'', -- item_subtype + ''pm_task'', -- content_type + p_title, -- title + p_description, -- description + p_mime_type, -- mime_type + null, -- nls_language + null -- data + ); + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + v_item_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks ( + task_id, task_number, status, process_instance) + values ( + v_item_id, v_task_number, p_status_id, p_process_instance_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, ''0''); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; + + +alter table pm_process_task add column + mime_type varchar(200) + constraint pm_process_task_mime_type_fk + references cr_mime_types(mime_type) + on update no action on delete no action; + +alter table pm_process_task alter column mime_type set default 'text/plain'; + +update pm_process_task set mime_type = 'text/plain'; + +alter table pm_process add column + deleted_p char(1); + +alter table pm_process alter column deleted_p set default 'f'; + +update pm_process set deleted_p = 'f'; + +alter table pm_process add constraint pm_process_deleted_p_ck + check (deleted_p in ('t','f')); + + +create or replace view +pm_process_active as + SELECT * FROM pm_process where deleted_p = 'f'; Index: openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.60b1-2.61d1.sql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.60b1-2.61d1.sql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/sql/postgresql/upgrade/upgrade-2.60b1-2.61d1.sql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,194 @@ +alter table pm_tasks_revisions add column priority integer; +alter table pm_tasks_revisions alter column priority set default 0; +update pm_tasks_revisions set priority = 0; + +select define_function_args('pm_task__new_task_item', 'project_id, title, description, html_p, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, status_id, process_instance_id, creation_date, creation_user, creation_ip, package_id, priority'); + +create or replace function pm_task__new_task_item ( + integer, -- project_id + varchar, -- title + varchar, -- description + varchar, -- html_p + timestamptz, -- end_date + numeric, -- percent_complete + numeric, -- estimated_hours_work + numeric, -- estimated_hours_work_min + numeric, -- estimated_hours_work_max, + integer, -- status_id + integer, -- process_instance_id + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer, -- package_id + integer -- priority +) returns integer +as ' +declare + p_project_id alias for $1; + p_title alias for $2; + p_description alias for $3; + p_mime_type alias for $4; + p_end_date alias for $5; + p_percent_complete alias for $6; + p_estimated_hours_work alias for $7; + p_estimated_hours_work_min alias for $8; + p_estimated_hours_work_max alias for $9; + p_status_id alias for $10; + p_process_instance_id alias for $11; + p_creation_date alias for $12; + p_creation_user alias for $13; + p_creation_ip alias for $14; + p_package_id alias for $15; + p_priority alias for $16; + + v_item_id cr_items.item_id%TYPE; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; + v_task_number integer; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + + -- create the task_number + + v_item_id := content_item__new ( + v_id::varchar, -- name + p_project_id, -- parent_id + v_id, -- item_id + null, -- locale + now(), -- creation_date + p_creation_user, -- creation_user + p_package_id, -- context_id + p_creation_ip, -- creation_ip + ''content_item'', -- item_subtype + ''pm_task'', -- content_type + p_title, -- title + p_description, -- description + p_mime_type, -- mime_type + null, -- nls_language + null -- data + ); + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + v_item_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks ( + task_id, task_number, status, process_instance) + values ( + v_item_id, v_task_number, p_status_id, p_process_instance_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, priority) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, ''0'', p_priority); + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; + +drop view pm_tasks_revisionsx; + +create or replace view pm_tasks_revisionsx as + SELECT acs_objects.object_id, acs_objects.object_type, acs_objects.context_id, acs_objects.security_inherit_p, acs_objects.creation_user, acs_objects.creation_date, acs_objects.creation_ip, acs_objects.last_modified, acs_objects.modifying_user, acs_objects.modifying_ip, acs_objects.tree_sortkey, acs_objects.max_child_sortkey, cr.revision_id, cr.title, cr.item_id, cr.description, cr.publish_date, cr.mime_type, cr.nls_language, i.name, i.parent_id, pm_tasks_revisions.task_revision_id, pm_tasks_revisions.end_date, pm_tasks_revisions.percent_complete, pm_tasks_revisions.estimated_hours_work, pm_tasks_revisions.estimated_hours_work_min, pm_tasks_revisions.estimated_hours_work_max, pm_tasks_revisions.actual_hours_worked, pm_tasks_revisions.earliest_start, pm_tasks_revisions.earliest_finish, pm_tasks_revisions.latest_start, pm_tasks_revisions.latest_finish, pm_tasks_revisions.priority + FROM acs_objects, cr_revisions cr, cr_items i, cr_text, pm_tasks_revisions + WHERE acs_objects.object_id = cr.revision_id AND cr.item_id = i.item_id AND acs_objects.object_id = pm_tasks_revisions.task_revision_id; + + +select define_function_args('pm_task__new_task_revision', 'task_id, project_id, title, description, mime_type, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, creation_date, creation_user, creation_ip, package_id, priority'); + +create or replace function pm_task__new_task_revision ( + integer, -- task_id (the item_id) + integer, -- project_id + varchar, -- title + varchar, -- description + varchar, -- mime_type + timestamptz, -- end_date + numeric, -- percent_complete + numeric, -- estimated_hours_work + numeric, -- estimated_hours_work_min + numeric, -- estimated_hours_work_max + numeric, -- actual_hours_worked + integer, -- status_id + timestamptz, -- creation_date + integer, -- creation_user + varchar, -- creation_ip + integer, -- package_id + integer -- priority +) returns integer +as ' +declare + p_task_id alias for $1; + p_project_id alias for $2; + p_title alias for $3; + p_description alias for $4; + p_mime_type alias for $5; + p_end_date alias for $6; + p_percent_complete alias for $7; + p_estimated_hours_work alias for $8; + p_estimated_hours_work_min alias for $9; + p_estimated_hours_work_max alias for $10; + p_actual_hours_worked alias for $11; + p_status_id alias for $12; + p_creation_date alias for $13; + p_creation_user alias for $14; + p_creation_ip alias for $15; + p_package_id alias for $16; + p_priority alias for $17; + v_revision_id cr_revisions.revision_id%TYPE; + v_id cr_items.item_id%TYPE; +begin + select acs_object_id_seq.nextval into v_id from dual; + + -- We want to put the task under the project item + update cr_items set parent_id = p_project_id where item_id = p_task_id; + + v_revision_id := content_revision__new ( + p_title, -- title + p_description, -- description + now(), -- publish_date + p_mime_type, -- mime_type + NULL, -- nls_language + NULL, -- data + p_task_id, -- item_id + NULL, -- revision_id + now(), -- creation_date + p_creation_user, -- creation_user + p_creation_ip -- creation_ip + ); + + PERFORM content_item__set_live_revision (v_revision_id); + + insert into pm_tasks_revisions ( + task_revision_id, end_date, percent_complete, estimated_hours_work, estimated_hours_work_min, estimated_hours_work_max, actual_hours_worked, priority) + values ( + v_revision_id, p_end_date, p_percent_complete, p_estimated_hours_work, p_estimated_hours_work_min, p_estimated_hours_work_max, p_actual_hours_worked, p_priority); + + update pm_tasks set status = p_status_id where task_id = p_task_id; + + PERFORM acs_permission__grant_permission( + v_revision_id, + p_creation_user, + ''admin'' + ); + + return v_revision_id; +end;' language 'plpgsql'; Index: openacs-4/packages/project-manager/tcl/calendar-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/calendar-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/calendar-procs-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,70 @@ + + + + + + + + + oracle8.0 + + + + SELECT ts.task_id, + ts.task_id as item_id, + ts.task_number, + t.task_revision_id, + t.title, + t.parent_id as project_item_id, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(sysdate,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'J') as latest_finish_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name || ' (' || + substr(r.one_line,1,1) || ')' as full_name, + p.person_id, + s.status_type as status, + r.is_lead_p, + projectr.title as project_name + FROM pm_tasks_active ts, + pm_task_status s, + cr_items i, + pm_tasks_revisionsx t, + pm_roles r, + persons p, + pm_task_assignment ta, + cr_items projecti, + cr_revisions projectr + WHERE ta.role_id = r.role_id (+) and + t.item_id = ta.task_id (+) and + ta.party_id = p.person_id (+) and + ta.role_id = r.role_id and + ts.status = s.status_id and + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + t.latest_start >= :first_of_month_date and + t.latest_start <= :last_of_month_date and + t.parent_id = projecti.item_id and + projecti.live_revision = projectr.revision_id + $hide_closed_clause + $selected_users_clause + ORDER BY + t.latest_start, ts.task_id, r.role_id, p.first_names, p.last_name + + + + + Index: openacs-4/packages/project-manager/tcl/calendar-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/calendar-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/calendar-procs-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,72 @@ + + + + + + + + + postgresql7.3 + + + + SELECT + ts.task_id, + ts.task_id as item_id, + ts.task_number, + t.task_revision_id, + t.title, + t.parent_id as project_item_id, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(current_timestamp,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'J') as latest_finish_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name || ' (' || + substring(r.one_line from 1 for 1) || ')' as full_name, + p.person_id, + s.status_type as status, + r.is_lead_p, + projectr.title as project_name + FROM + pm_tasks_active ts, + pm_task_status s, + cr_items i, + pm_tasks_revisionsx t + LEFT JOIN pm_task_assignment ta + ON t.item_id = ta.task_id + LEFT JOIN persons p + ON ta.party_id = p.person_id + LEFT JOIN pm_roles r + ON ta.role_id = r.role_id, + cr_items projecti, + cr_revisions projectr + WHERE + ts.status = s.status_id and + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + t.latest_start >= :first_of_month_date and + t.latest_start <= :last_of_month_date and + t.parent_id = projecti.item_id and + projecti.live_revision = projectr.revision_id + $hide_closed_clause + $selected_users_clause + ORDER BY + t.latest_start, ts.task_id, r.role_id, p.first_names, p.last_name + + + + + Index: openacs-4/packages/project-manager/tcl/calendar-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/calendar-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/calendar-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,164 @@ +# + +ad_library { + + Procs to integrate calendar with project-manager + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-08-04 + @arch-tag: cb98fba5-fba0-449f-9c14-ad9a41bbbd61 + @cvs-id $Id: calendar-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + + + +namespace eval pm::calendar { + + ad_proc -public users_to_view { + } { + Returns a list of user_ids for users to view + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-13 + + @return + + @error + } { + set user_id [ad_conn user_id] + + set user_list [db_list get_users { + SELECT + viewed_user + FROM + pm_users_viewed + WHERE + viewing_user = :user_id + }] + + if {[empty_string_p $user_list]} { + return $user_id + } else { + return $user_list + } + } + + + ad_proc -public one_month_display { + {-user_id:required} + {-date ""} + {-hide_closed_p "t"} + } { + Creates a month widget for tasks + } { + set day_template "\$day_number" + set prev_nav_template "<" + set next_nav_template ">" + + if {[empty_string_p $date]} { + set date [dt_systime] + } + + set date_list [dt_ansi_to_list $date] + set month [lindex $date_list 1] + set year [lindex $date_list 0] + + set first_of_month_date "$year-$month-01" + set last_of_month_date "$year-$month-[dt_num_days_in_month $year $month]" + + set items [ns_set create] + + # do not show closed items if the user requests not to + if {[string is true $hide_closed_p]} { + set hide_closed_clause " and s.status_type = 'o' " + } else { + set hide_closed_clause "" + } + + set selected_users [pm::calendar::users_to_view] + set selected_users_clause " and ts.task_id in (select task_id from pm_task_assignment where party_id in ([join $selected_users ", "]))" + + set last_task_id "" + set last_latest_start_j "" + set assignee_list [list] + + db_foreach select_monthly_tasks {} { + + # highlight what you're assigned to. + if {[string equal $person_id $user_id]} { + set font_begin "" + set font_end "" + } else { + set font_begin "" + set font_end "" + } + + if { \ + ![empty_string_p $is_lead_p] && \ + [string is true $is_lead_p]} { + + set font_begin "$font_begin" + set font_end "$font_end" + } + + # if this is another row of the same item, just add the name. + if {[string equal $last_task_id $task_id]} { + append day_details "
  • , ${font_begin}${full_name}${font_end}
  • " + } else { + + # this is the beginning of an item. + + # save the last item for output + if {![empty_string_p $last_task_id]} { + ns_set put $items $last_latest_start_j "${day_details}

    " + } + + # set up the next item for output + + if {[string equal $status "c"]} { + set detail_begin "" + set detail_end "" + } else { + set detail_begin "" + set detail_end "" + } + + # begin setting up this calendar item + set day_details "

    ${detail_begin}$task_id
    $title${detail_end}

    $project_name
    " + + # only add to the list if we want to see closed tasks + append day_details "

    " + } + + + # Display stuff + set day_number_template "$day_template" + + return [dt_widget_month -calendar_details $items -date $date \ + -master_bgcolor black \ + -header_bgcolor lavender \ + -header_text_color black \ + -header_text_size "+1" \ + -day_header_bgcolor lavender \ + -day_bgcolor white \ + -today_bgcolor #FFF8DC \ + -empty_bgcolor lightgrey \ + -day_text_color black \ + -prev_next_links_in_title 1 \ + -prev_month_template $prev_nav_template \ + -next_month_template $next_nav_template \ + -day_number_template $day_number_template] + } + + +} Index: openacs-4/packages/project-manager/tcl/install-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/install-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/install-procs-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,26 @@ + + + + postgresql7.1 + + + + select pm_project.get_root_folder(:package_id,'t') from dual + + + + + + + select pm_project.get_root_folder(:package_id,'f') from dual + + + + + + exec content_item.del(:folder_id) + + + + + Index: openacs-4/packages/project-manager/tcl/install-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/install-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/install-procs-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,34 @@ + + + + postgresql7.1 + + + + + + select pm_project__get_root_folder(:package_id,'t'); + + + + + + + + + select pm_project__get_root_folder(:package_id,'f'); + + + + + + + + + select content_item__delete(:folder_id); + + + + + + Index: openacs-4/packages/project-manager/tcl/install-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/install-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/install-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,38 @@ +ad_library { + + Project manager install library + + Procedures that deal with installing, instantiating, mounting. + + @creation-date 2003-01-31 + @author Jade Rubick + @copied-from Lars Pind + @cvs-id $Id: install-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + + +namespace eval pm::install {} + + +ad_proc -private pm::install::package_instantiate { + {-package_id:required} +} { + Package instantiation callback proc. +} { + # Create the project repository + + # db_exec_plsql create_project { } +} + +ad_proc -private pm::install::package_uninstantiate { + {-package_id:required} +} { + Package un-instantiation callback proc +} { + # Delete the project repository + + # ns_log Debug "pm::install::package_uninstantiate getting folder_id for package_id: $package_id" + # set folder_id [db_exec_plsql get_folder_id { }] + # ns_log Debug "pm::install::package_uninstantiate delete folder_id: $folder_id" + # db_exec_plsql delete_root_folder { } +} Index: openacs-4/packages/project-manager/tcl/notification-init.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/notification-init.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/notification-init.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,14 @@ +# + +ad_library { + + Init file to schedul registered procedures for notifications + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + @arch-tag: e72c34cc-2ed9-42c5-8423-d9b349f0e6c4 + @cvs-id $Id: notification-init.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + +# set up daily emailings +pm::task::email_status_init Index: openacs-4/packages/project-manager/tcl/process-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/process-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/process-procs-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,207 @@ + + + + + + + + + + + postgresql + 7.3 + + + + + UPDATE + pm_process + SET + deleted_p = 't' + WHERE + process_id = :process_id + + + + + + + + SELECT + t.process_task_id as process_tid, + t.one_line, + t.description, + t.mime_type as description_mime_type, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + d.dependency_id, + d.parent_task_id as process_parent_task + FROM + pm_process_task t + LEFT JOIN + pm_process_task_dependency d + ON t.process_task_id = d.process_task_id + WHERE + t.process_id = :process_id + $process_task_where_clause + ORDER BY + t.ordering, + t.process_task_id + + + + + + SELECT + process_id, + one_line as process_name + FROM + pm_process_active + ORDER BY + one_line + + + + + + SELECT + party_id, + role_id + FROM + pm_process_task_assignment + WHERE + process_task_id = :process_task_id + + + + + + INSERT INTO + pm_process_instance + (instance_id, process_id, project_item_id, name) + VALUES + (:instance_id, :process_id, :project_item_id, :name) + + + + + + SELECT + i.instance_id, + i.name + FROM + pm_process_instance i + WHERE + i.instance_id in + (SELECT + process_instance + FROM + pm_tasks t, + cr_items it + WHERE + t.task_id = it.item_id and + it.parent_id = :project_item_id) + ORDER BY + i.name, + i.instance_id + + + + + + SELECT + p.email as from_address, + p2.first_names || ' ' || p2.last_name as mod_username + FROM + parties p, + persons p2 + WHERE + p.party_id = :user_id and + p.party_id = p2.person_id + + + + + + SELECT + project.title as project_name + FROM + cr_revisions project + WHERE + revision_id = (select live_revision from cr_items where item_id + = :project_item_id) + + + + + + SELECT + i.item_id as task_item_id, + t.title as subject, + to_char(current_timestamp,'J') as today_j, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'YYYY-MM-DD') as latest_finish, + status_type + FROM + pm_tasks_revisionsx t, + cr_items i, + pm_tasks_active a, + pm_task_status s + WHERE + t.revision_id = i.live_revision and + t.item_id = i.item_id and + t.item_id = a.task_id and + a.status = s.status_id and + a.process_instance = :process_instance_id + ORDER BY + t.latest_finish, + t.title + + + + + + SELECT + p.email as to_address, + r.one_line as role, + case when r.is_lead_p is null then 'f' else r.is_lead_p end as is_lead_p, + p2.first_names || ' ' || p2.last_name as user_name, + a.task_id as my_task_id + FROM + pm_task_assignment a, + parties p, + pm_roles r, + persons p2 + WHERE + a.task_id in ([join $task_list ", "]) and + a.party_id = p.party_id and + a.role_id = r.role_id and + p.party_id = p2.person_id + + + + + + SELECT + pi.name || ' (' || pi.instance_id || ')' as process_name + FROM + pm_process_instance pi + WHERE + pi.instance_id = :process_instance_id + + + + + + SELECT + one_line + FROM + pm_process + WHERE + process_id = :process_id + + + + Index: openacs-4/packages/project-manager/tcl/process-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/process-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/process-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,609 @@ +# + +ad_library { + + Procs for processes. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-24 + @arch-tag: 29bef794-0109-464c-a5f9-99981628e379 + @cvs-id $Id: process-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + +namespace eval pm::process {} + +ad_proc -public pm::process::delete { + {-process_id:required} +} { + Deletes a process and all process tasks + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-25 + + @param process_id + + @return + + @error +} { + + db_dml delete_process { } + +} + + +ad_proc -public pm::process::remove_assignees { + {-process_task_id:required} +} { + Removes all assignees from a process task. If process_task_id + is a list, then removes from all of those task_ids + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-24 + + @param process_task_id + + @return + + @error +} { + + if {[llength $process_task_id] > 1} { + db_dml delete_assignments " + DELETE FROM + pm_process_task_assignment + WHERE + process_task_id in ([join $process_task_id ", "]) + " + } else { + db_dml delete_assignments { + DELETE FROM + pm_process_task_assignment + WHERE + process_task_id = :process_task_id + } + } + + return +} + + +ad_proc -public pm::process::assign { + {-process_task_id:required} + {-party_id:required} + {-role_id:required} +} { + Assigns party_id to process_task_id under the role_id role + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-24 + + @param process_task_id + + @param party_id + + @param role_id + + @return + + @error +} { + + db_dml add_assignment { + INSERT INTO + pm_process_task_assignment + (process_task_id, + role_id, + party_id) + VALUES + (:process_task_id, + :role_id, + :party_id) + } + + return +} + + +ad_proc -public pm::process::remove_dependency { + {-process_task_id:required} +} { + Removes all dependencies from a given task. If process_task_id + is a list of tasks, then deletes all dependencies from all the tasks. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-24 + + @param process_task_id + + @return + + @error +} { + + if {[llength $process_task_id] > 1} { + db_dml delete_dependency " + DELETE FROM pm_process_task_dependency + WHERE process_task_id in ([join $process_task_id ", "]) + " + } else { + db_dml delete_dependency { + DELETE FROM pm_process_task_dependency + WHERE process_task_id = :process_task_id + } + } + + return +} + + +ad_proc -public pm::process::add_dependency { + {-process_task_id:required} + {-parent_task_id:required} + {-dependency_type_id:required} +} { + Adds a dependency on parent_task_id for process_task_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-24 + + @param process_task_id + + @param parent_task_id + + @param dependency_type_id + + @return + + @error +} { + set dependency_id [db_nextval pm_task_dependency_seq] + + db_dml add_dependency { + INSERT INTO pm_process_task_dependency + (dependency_id, process_task_id, parent_task_id, dependency_type) + VALUES + (:dependency_id, :process_task_id, :parent_task_id, :dependency_type_id) + } + + return +} + + +ad_proc -public pm::process::get { + {-process_id:required} + {-process_task_id ""} + {-one_line_array:required} + {-description_array:required} + {-description_mime_type_array:required} + {-estimated_hours_work_array:required} + {-estimated_hours_work_min_array:required} + {-estimated_hours_work_max_array:required} + {-dependency_array:required} + {-tasks_list:required} +} { + Sets a bunch of information in a set of arrays on all + process tasks for a given process + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-23 + + @param process_id + + @param one_line_array + + @param description_array + + @param estimated_hours_work_array + + @param estimated_hours_work_min_array + + @param estimated_hours_work_max_array + + @param dependency_array + + @param tasks_list + + @return + + @error +} { + + # set variables in calling environment, using names passed in + upvar 1 $one_line_array one_line_arr + upvar 1 $description_array description_arr + upvar 1 $description_mime_type_array description_mime_type_arr + upvar 1 $estimated_hours_work_array estimated_hours_work_arr + upvar 1 $estimated_hours_work_min_array estimated_hours_work_min_arr + upvar 1 $estimated_hours_work_max_array estimated_hours_work_max_arr + upvar 1 $dependency_array dependency_arr + upvar 1 $tasks_list process_tasks_l + + if {[exists_and_not_null process_task_id]} { + set process_task_where_clause " and t.process_task_id in ([join $process_task_id ", "])" + } else { + set process_task_where_clause "" + } + + db_foreach get_process_tasks { } { + set one_line_arr($process_tid) $one_line + set description_arr($process_tid) $description + set description_mime_type_arr($process_tid) $description_mime_type + set estimated_hours_work_arr($process_tid) $estimated_hours_work + set estimated_hours_work_min_arr($process_tid) $estimated_hours_work_min + set estimated_hours_work_max_arr($process_tid) $estimated_hours_work_max + set dependency_arr($process_tid) $process_parent_task + + # make sure that we don't have empty values for estimated + # hours work + if {[empty_string_p $estimated_hours_work_arr($process_tid)]} { + set estimated_hours_work_arr($process_tid) 0 + } + if {[empty_string_p $estimated_hours_work_min_arr($process_tid)]} { + set estimated_hours_work_min_arr($process_tid) 0 + } + if {[empty_string_p $estimated_hours_work_max_arr($process_tid)]} { + set estimated_hours_work_max_arr($process_tid) 0 + } + + + lappend process_tasks_l $process_tid + } + +} + + +ad_proc -public pm::process::select_html { +} { + Returns the option part of the + HTML for a select list of process options + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-14 + + @return + + @error +} { + + set html "" + + db_foreach get_processes get_processes { + append html "\n" + } + + return $html +} + + +ad_proc -public pm::process::task_assignee_role_list { + {-process_task_id:required} +} { + Returns a list of lists, with all assignees to a particular + process task. {{party_id role_id} {party_id role_id}} + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @param process_task_id + + @return + + @error +} { + + return [db_list_of_lists get_assignees_roles { }] + +} + + +ad_proc -public pm::process::instantiate { + {-process_id:required} + {-project_item_id:required} + {-name:required} +} { + Returns a unique process instance id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @return + + @error +} { + + set instance_id [db_nextval pm_process_instance_seq] + + db_dml add_instance { } + + return $instance_id +} + + +ad_proc -public pm::process::instances { + {-project_item_id:required} +} { + Returns a list of lists of form + {{process_instance_id process_instance_name} { } ...} + + of processes in use by tasks in a particular project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @param project_item_id + + @return + + @error +} { + + return [db_list_of_lists get_process_instance { }] + +} + + +ad_proc -public pm::process::instance_options { + {-project_item_id:required} + {-process_instance_id ""} +} { + Returns the options portion of HTML for process instances + associated with tasks in a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @param project_item_id + + @return + + @error +} { + + set instances [pm::process::instances -project_item_id $project_item_id] + + set html "" + + foreach inst $instances { + set instance_id [lindex $inst 0] + set name [lindex $inst 1] + + if {[string equal $instance_id $process_instance_id]} { + set sel "selected=\"selected\"" + } else { + set sel "" + } + + append html "" + } + + return $html +} + + +ad_proc -public pm::process::url { + {-process_instance_id:required} + {-project_item_id:required} + {-fully_qualified_p "t"} +} { + Returns the URL for a process instance + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @param process_instance_id + + @return + + @error +} { + + return [pm::util::url -fully_qualified_p $fully_qualified_p][export_vars -base one {project_item_id {instance_id $process_instance_id}}] + +} + + +ad_proc -public pm::process::email_alert { + {-process_instance_id:required} + {-project_item_id:required} + {-new_p "t"} +} { + Sends out an email notification when a process is instantiated. + Gives the status of all tasks created. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-05 + + @param process_instance_id + + @return + + @error +} { + + set task_term \ + [parameter::get -parameter "Taskname" -default "Task"] + set task_term_lower \ + [parameter::get -parameter "taskname" -default "task"] + set use_uncertain_completion_times_p \ + [parameter::get -parameter "UseUncertainCompletionTimesP" -default "0"] + + set user_id [ad_conn user_id] + + db_1row get_from_address_and_more { } + db_1row get_project_info { } + + set process_name [pm::process::name \ + -process_instance_id $process_instance_id] + + set project_url [pm::project::url -project_item_id $project_item_id] + set process_url [pm::process::url \ + -process_instance_id $process_instance_id \ + -project_item_id $project_item_id] + + if {[string is true $new_p]} { + set subject_out "New: $process_name" + set intro_text "$mod_username assigned you to a process." + } else { + set subject_out "Status update: $process_name" + set notif_name [person::name -person_id $user_id] + set intro_text "$notif_name sent this process status update." + } + + + set task_info [db_list_of_lists get_task_info { }] + + set task_list [list] + foreach ti $task_info { + lappend task_list [lindex $ti 0] + } + + set assignees [db_list_of_lists get_assignees { }] + + # make a list of those who are assigned in some capacity + set to_addresses [list] + + foreach ass $assignees { + set to_address [lindex $ass 0] + + if {[lsearch $to_addresses $to_address] < 0} { + lappend to_addresses $to_address + } + } + + # make the notification for each assignee + foreach to_address $to_addresses { + + set notification_text "${intro_text} +

    Process overview

    + + + + + + + + + +
    Project:$project_name (\#$project_item_id)
    Overview of process:$process_name
    + +

    $task_term and current status

    + + + + + " + + foreach ti $task_info { + set task_item_id [lindex $ti 0] + set subject [lindex $ti 1] + set today_j [lindex $ti 2] + set earliest_start_j [lindex $ti 3] + set latest_start_j [lindex $ti 4] + set latest_finish [lindex $ti 5] + set status_type [lindex $ti 6] + + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + + set pretty_latest_finish [lc_time_fmt $latest_finish "%x"] + + set lead_html "" + + # we highlight rows when the user is assigned to this task + set assignee_involved_p f + + foreach ass $assignees { + set to_addr [lindex $ass 0] + set role [lindex $ass 1] + set is_lead_p [lindex $ass 2] + set user_name [lindex $ass 3] + set my_task_id [lindex $ass 4] + + # ignore anything that isn't for this task + if {[string equal $my_task_id $task_item_id]} { + + if {[string is true $is_lead_p]} { + append lead_html "$user_name
    " + } + + if {[string equal $to_addr $to_address]} { + set assignee_involved_p t + } + } + } + + if {[string equal $status_type "c"]} { + append notification_text "" + } elseif {[string is true $assignee_involved_p]} { + append notification_text "" + } else { + append notification_text "" + } + + append notification_text " + + + + +" + } + + # build table of current status + append notification_text "
    $task_term nameSlack timeLeadLatest finish
    $subject$slack_time$lead_html$pretty_latest_finish

    If the row is in red, you are involved in this task. If it is in grey, then it has already been completed.

    " + + pm::util::email \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject_out \ + -body $notification_text \ + -mime_type "text/html" + } + +} + + +ad_proc -public pm::process::name { + {-process_instance_id:required} +} { + Returns the name when given a process_instance_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-20 + + @param process_instance_id + + @return + + @error +} { + + db_1row get_name { } + + return $process_name +} + + +ad_proc -public pm::process::process_name { + {-process_id:required} +} { + Returns the name when given a process_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-20 + + @param process_id + + @return + + @error +} { + + db_1row get_name { } + + return $one_line +} + + Index: openacs-4/packages/project-manager/tcl/project-manager-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/project-manager-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/project-manager-procs-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,44 @@ + + + + + + + + + + + oracle + 8.0 + + + + + SELECT t.name as cat_name, + t.category_id as cat_id, + tm.tree_id, + tt.name as tree_name + FROM category_tree_map tm, + categories c, + category_translations t, + category_tree_translations tt + WHERE c.tree_id = tm.tree_id and + c.category_id = t.category_id and + tm.object_id = :package_id and + tm.tree_id = tt.tree_id and + c.deprecated_p = 'f' + ORDER BY tt.name, + t.name + + + + + + SELECT package_id + FROM cr_folders + WHERE description = 'Project Repository' + + + + + Index: openacs-4/packages/project-manager/tcl/project-manager-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/project-manager-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/project-manager-procs-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,57 @@ + + + + + + + + + + + postgresql + 7.3 + + + + + SELECT + t.name as cat_name, + t.category_id as cat_id, + tm.tree_id, + tt.name as tree_name + FROM + category_tree_map tm, + categories c, + category_translations t, + category_tree_translations tt + WHERE + c.tree_id = tm.tree_id and + c.category_id = t.category_id and + tm.object_id = :package_id and + tm.tree_id = tt.tree_id and + c.deprecated_p = 'f' + ORDER BY + tt.name, + t.name + + + + + + SELECT DISTINCT + p.first_names || ' ' || p.last_name as name, + p.person_id + FROM + persons p, + acs_rels r, + membership_rels mr + WHERE + r.object_id_one = :user_group_id and + mr.rel_id = r.rel_id and + p.person_id = r.object_id_two and + member_state = 'approved' + ORDER BY name + + + + Index: openacs-4/packages/project-manager/tcl/project-manager-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/project-manager-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/project-manager-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,755 @@ +ad_library { + + Project Manager Projects Library + + Utility procedures for project manager + + @creation-date 2003-08-25 + @author Jade Rubick + @cvs-id $Id: project-manager-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + +} + +namespace eval pm::util {} + + +ad_proc -public pm::util::hours_day { +} { + Returns the number of hours in the workday + + @author (jader-ibr@bread.com) + @creation-date 2004-11-24 + + @return + + @error +} { + return [util_memoize [list pm::util::hours_day_not_cached]] +} + + +ad_proc -public pm::util::hours_day_not_cached { +} { + Returns the number of hours in the workday + + @author (jader-ibr@bread.com) + @creation-date 2004-11-24 + + @return + + @error +} { + return 8 +} + + +ad_proc -public pm::util::days_work { + {-hours_work:required} + {-pretty_p "f"} +} { + Returns the number of days work + + @author (jader-ibr@bread.com) + @creation-date 2004-11-24 + + @param hours_work + + @return + + @error +} { + set hours_day [pm::util::hours_day] + + if {![string equal $hours_day 0]} { + set number [expr double($hours_work) / $hours_day] + } + + set return_val [pm::util::trim_number -number $number] + + if {[string is true $pretty_p]} { + if {$return_val < 1} { + return "less than 1" + } + } + + return $return_val +} + + +ad_proc -public pm::util::trim_number { + {-number:required} + {-precision "4"} +} { + Trims zeros off the end of a number + + @author (jader-ibr@bread.com) + @creation-date 2004-11-24 + + @param precision + + @return + + @error +} { + set return_val [format "%0.${precision}f" $number] + set return_val [string trimright $return_val 0] + set return_val [string trimright $return_val .] + + return $return_val +} + + + +ad_proc -public pm::util::datenvl { + -value + -value_if_null + -value_if_not_null +} { + Extended nvl, for dates only +} { + if {[string equal $value "{} {} {} {} {} {}"] \ + || [empty_string_p $value]} { + return $value_if_null + } else { + return $value_if_not_null + } +} + + +ad_proc -public pm::util::reformat_date { + the_date +} { + the end date comes in this format 2004 05 17 + we need to get it in the {2004} {05} {17} {} {} {} format + + @author Jade Rubick (jader@bread.com) + + @creation-date 2004-09-23 + + + @param the_date + + + @return + + @error +} { + + regexp {(.*) (.*) (.*)} $the_date match year month day + if {[exists_and_not_null year]} { + set return_val "$year $month $day {} {} {}" + } else { + set return_val "{} {} {} {} {} {}" + } + + return $return_val +} + + +ad_proc -public pm::util::string_truncate_and_pad { + -length + {-ellipsis "..."} + -string +} { + Truncates a string to a given length, or pads it to match a given length + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + + @param length + + @param ellipsis + + @param string + + @return + + @error +} { + + set new_string [string_truncate -len $length -ellipsis $ellipsis -- $string] + set new_string_length [string length $new_string] + + if {$new_string_length < $length} { + set new_string "$new_string[string repeat " " [expr $length - $new_string_length]]" + } + + return $new_string +} + + +ad_proc -private pm::util::word_diff { + {-old:required} + {-new:required} + {-split_by {}} + {-filter_proc {ad_quotehtml}} + {-start_old {}} + {-end_old {}} + {-start_new {}} + {-end_new {}} +} { + This procedure has been BACKPORTED from OpenACS HEAD. That means + you should not use it in your own applications. If you do, you'll + need to update your application once OpenACS 5.2 is available, and + create a dependency on OpenACS 5.2 in your .info file. + + Does a word (or character) diff on two lines of text and indicates text + that has been deleted/changed or added by enclosing it in + start/end_old/new. + + @param old The original text. + @param new The modified text. + + @param split_by If split_by is a space, the diff will be made + on a word-by-word basis. If it is the empty string, it will be made on + a char-by-char basis. + + @param filter_proc A filter to run the old/new text through before + doing the diff and inserting the HTML fragments below. Keep in mind + that if the input text is HTML, and the start_old, etc... fragments are + inserted at arbitrary locations depending on where the diffs are, you + might end up with invalid HTML unless the original HTML is quoted. + + @param start_old HTML fragment to place before text that has been removed. + @param end_old HTML fragment to place after text that has been removed. + @param start_new HTML fragment to place before new text. + @param end_new HTML fragment to place after new text. + + @see ad_quotehtml + @author Gabriel Burca +} { + + if {$filter_proc != ""} { + set old [$filter_proc $old] + set new [$filter_proc $new] + } + + set old_f [ns_tmpnam] + set new_f [ns_tmpnam] + set old_fd [open $old_f "w"] + set new_fd [open $new_f "w"] + puts $old_fd [join [split $old $split_by] "\n"] + puts $new_fd [join [split $new $split_by] "\n"] + close $old_fd + close $new_fd + + # Diff output is 1 based, our lists are 0 based, so insert a dummy + # element to start the list with. + set old_w [linsert [split $old $split_by] 0 {}] + set sv 1 + +# For debugging purposes: +# set diff_pipe [open "| diff -f $old_f $new_f" "r"] +# while {![eof $diff_pipe]} { +# append res "[gets $diff_pipe]
    " +# } + + set diff_pipe [open "| diff -f $old_f $new_f" "r"] + while {![eof $diff_pipe]} { + gets $diff_pipe diff + if {[regexp {^d(\d+)(\s+(\d+))?$} $diff full m1 m2]} { + if {$m2 != ""} {set d_end $m2} else {set d_end $m1} + for {set i $sv} {$i < $m1} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + for {set i $m1} {$i <= $d_end} {incr i} { + append res "${split_by}${start_old}[lindex $old_w $i]${end_old}" + } + set sv [expr $d_end + 1] + } elseif {[regexp {^c(\d+)(\s+(\d+))?$} $diff full m1 m2]} { + if {$m2 != ""} {set d_end $m2} else {set d_end $m1} + for {set i $sv} {$i < $m1} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + for {set i $m1} {$i <= $d_end} {incr i} { + append res "${split_by}${start_old}[lindex $old_w $i]${end_old}" + } + while {![eof $diff_pipe]} { + gets $diff_pipe diff + if {$diff == "."} { + break + } else { + append res "${split_by}${start_new}${diff}${end_new}" + } + } + set sv [expr $d_end + 1] + } elseif {[regexp {^a(\d+)$} $diff full m1]} { + set d_end $m1 + for {set i $sv} {$i < $m1} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + while {![eof $diff_pipe]} { + gets $diff_pipe diff + if {$diff == "."} { + break + } else { + append res "${split_by}${start_new}${diff}${end_new}" + } + } + set sv [expr $d_end + 1] + } + } + + for {set i $sv} {$i < [llength $old_w]} {incr i} { + append res "${split_by}[lindex $old_w $i]" + } + + file delete -- $old_f $new_f + + return $res +} + + +ad_proc -public pm::util::logger_url {} { + Returns the URL for the primary logger URL + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-24 + + @return + + @error +} { + set return_val [parameter::get -parameter "LoggerPrimaryURL" -default ""] + + if {[empty_string_p $return_val]} { + ns_log Error "Project-manager: need to set up LoggerPrimaryURL in parameters" + util_user_message -message "Administrator needs to set up logger integration" + } + + return $return_val +} + + +ad_proc -public pm::util::general_comment_add { + {-object_id:required} + {-title:required} + {-comment ""} + {-mime_type:required} + {-user_id ""} + {-peeraddr ""} + {-type "task"} + {-send_email_p "f"} +} { + Adds a general comment to a task or project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-10 + + @param object_id The item_id for the task or project + + @param title The title for the comment + + @param comment The body of the comment + + @param mime_type The mime_type for the comment + + @param user_id Optional, the user_id making the comment. If left + empty, set to the ad_conn user_id + + @param peeraddr The IP address of the user making the comment. + If empty, set to the ad_conn peeraddr + + @param type Either task or project. + + @param send_email_p Whether or not to send out an email + notification t or f + + @return the comment_id of the new comment + + @error -1 if there is an error +} { + if {[empty_string_p $user_id]} { + set user_id [ad_conn user_id] + } + + if {[empty_string_p $peeraddr]} { + set peeraddr [ad_conn peeraddr] + } + + if {![string equal $type task] && ![string equal $type project]} { + return -1 + } + + # insert the comment into the database + set is_live [ad_parameter AutoApproveCommentsP {general-comments} {t}] + + set comment_id [db_nextval acs_object_id_seq] + + db_transaction { + db_exec_plsql insert_comment { + select acs_message__new ( + :comment_id, -- 1 p_message_id + NULL, -- 2 p_reply_to + current_timestamp, -- 3 p_sent_date + NULL, -- 4 p_sender + NULL, -- 5 p_rfc822_id + :title, -- 6 p_title + NULL, -- 7 p_description + :mime_type, -- 8 p_mime_type + NULL, -- 9 p_text + NULL, -- empty_blob() -- 10 p_data + 0, -- 11 p_parent_id + :object_id, -- 12 p_context_id + :user_id, -- 13 p_creation_user + :peeraddr, -- 14 p_creation_ip + 'acs_message', -- 15 p_object_type + :is_live -- 16 p_is_live + ) + } + + db_dml add_entry { + insert into general_comments + (comment_id, + object_id, + category) + values + (:comment_id, + :object_id, + null) + } + + db_1row get_revision { + select content_item__get_latest_revision(:comment_id) as revision_id + } + + db_dml set_content { + update cr_revisions + set content = :comment + where revision_id = :revision_id + } + + if {![empty_string_p $user_id]} { + permission::grant \ + -object_id $comment_id \ + -party_id $user_id \ + -privilege "read" + + permission::grant \ + -object_id $comment_id \ + -party_id $user_id \ + -privilege "write" + } + + } + + # now send out email + + if {[string equal $send_email_p t]} { + + # task + + if {[string equal $type task]} { + + set assignees [pm::task::assignee_email_list -task_item_id $object_id] + + if {[llength $assignees] > 0} { + + set to_address $assignees + + set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] + + set task_url [pm::task::get_url $object_id] + + set subject "Task comment: $title" + + # convert to HTML + set richtext_list [list $comment $mime_type] + set comment_html [template::util::richtext::get_property html_value $richtext_list] + + set content "$title

    $comment_html" + + pm::util::email \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $content \ + -mime_type "text/html" + } + + } + + # project + + if {[string equal $type project]} { + + set assignees [pm::project::assignee_email_list -project_item_id $object_id] + + if {[llength $assignees] > 0} { + + set to_address $assignees + + set from_address [db_string get_from_email "select email from parties where party_id = :user_id" -default "nobody@nowhere.com"] + + set project_url [pm::project::url \ + -project_item_id $object_id] + + set subject "Project comment: $title" + + # convert to HTML + set richtext_list [list $comment $mime_type] + set comment_html [template::util::richtext::get_property html_value $richtext_list] + + set content "$title

    $comment_html" + + + pm::util::email \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject \ + -body $content \ + -mime_type "text/html" + } + + + } + } + + + return $comment_id +} + + +ad_proc -public pm::util::email { + {-to_addr:required} + {-from_addr:required} + {-subject:required} + {-body ""} + {-mime_type "text/plain"} +} { + Wrapper to send out email, also converts body to text/plain format + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-10 + + @param to_addr list of email addresses to send to + + @param from_addr + + @param subject + + @param body + + @param mime_type + + @return + + @error +} { + + # HTML portions of this copied from notification::email::send + + if {[string equal $mime_type "text/plain"]} { + set body_text $body + set body_html [ad_html_text_convert -from $mime_type -to "text/html" -- $body] + } elseif {[string equal $mime_type "text/html"]} { + set body_text [ad_html_text_convert -from $mime_type -to "text/plain" -- $body] + set body_html $body + + } else { + set body_text [ad_html_text_convert -from $mime_type -to "text/plain" -- $body] + set body_html [ad_html_text_convert -from $mime_type -to "text/html" -- $body] + + } + + # Use this to build up extra mail headers + set extra_headers [ns_set new] + + # This should disable most auto-replies + ns_set put $extra_headers Precedence list + + set message_data [build_mime_message $body_text $body_html] + ns_set put $extra_headers MIME-Version [ns_set get $message_data MIME-Version] + ns_set put $extra_headers Content-ID [ns_set get $message_data Content-ID] + ns_set put $extra_headers Content-Type [ns_set get $message_data Content-Type] + set content [ns_set get $message_data body] + + foreach to $to_addr { + + acs_mail_lite::send \ + -to_addr "$to" \ + -from_addr "$from_addr" \ + -subject "$subject" \ + -body $content \ + -extraheaders $extra_headers + } +} + + +ad_proc -public pm::util::category_selects { + {-export_vars ""} + {-category_id ""} + {-package_id ""} +} { + Returns an HTML fragment of forms, one for each + category tree, suitable for use on a page. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param export_vars Variables already exported with export_vars -form + + @param category_id If set, the currently selected category + + @return + + @error +} { + if {[empty_string_p $package_id]} { + set package_id [ad_conn package_id] + } + + # caches results for 2.5 minutes. + return [util_memoize [list pm::util::category_selects_not_cached -export_vars $export_vars -category_id $category_id -package_id $package_id] 300] +} + + + +ad_proc -private pm::util::category_selects_not_cached { + {-export_vars ""} + {-category_id ""} + -package_id:required +} { + Returns an HTML fragment of category choices, suitable + for use on a page. This proc + is used so that pm::util::category_selects can cache + the categories + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param export_vars Variables already exported with export_vars -form + + @param category_id If set, the currently selected category + + @return + + @error +} { + # Categories are arranged into category trees. + # Set up an array for each tree. The array contains the category for each tree + + set category_select "" + set number_of_categories 0 + set last_tree "" + set category_select "" + + db_foreach get_categories { } { + + if {![string equal $tree_name $last_tree] } { + append category_select "" + } + + if {[string equal $cat_id $category_id]} { + set select "selected" + } else { + set select "" + } + + append category_select "" + + set last_tree $tree_name + incr number_of_categories + } + + if {$number_of_categories < 1} { + return "" + } + + set return_val "

    $export_vars
    " + + return $return_val +} + + +ad_proc -public pm::util::package_id { +} { + Returns the package ID for the project manager. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-16 + + @return + + @error +} { + return [db_string get_package_id { + SELECT + package_id + FROM + cr_folders + WHERE + description = 'Project Repository' + LIMIT 1 + }] +} + + +ad_proc -public pm::util::url { + {-fully_qualified_p "t"} +} { + Returns the URL of where the project manager is located, + fully qualified + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-16 + + @return + + @error +} { + set package_id [pm::util::package_id] + + if {[string is true $fully_qualified_p]} { + set return_val [ad_url] + } else { + set return_val "" + } + append return_val [site_node::get_url_from_object_id -object_id $package_id] + + return $return_val +} + + +ad_proc -public pm::util::subsite_assignees_list_of_lists { +} { + Returns a list of lists of possible assignees + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-13 + + @return + + @error +} { + set subsite_id [ad_conn subsite_id] + return [util_memoize [list pm::util::subsite_assignees_list_of_lists_not_cached -subsite_id $subsite_id] 6000] +} + + +ad_proc -public pm::util::subsite_assignees_list_of_lists_not_cached { + {-subsite_id ""} +} { + Returns a list of lists of possible assignees + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-13 + + @return + + @error +} { + + if [empty_string_p $subsite_id] { + set subsite_id [ad_conn subsite_id] + } + + set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + + set assignees [db_list_of_lists get_assignees { }] + + return $assignees +} Index: openacs-4/packages/project-manager/tcl/project-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/project-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/project-procs-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,187 @@ + + + + oracle8.0 + + + + SELECT live_revision + FROM cr_items + WHERE item_id = :project_item_id + + + + + + SELECT i.item_id + FROM cr_items i, + cr_revisions r + WHERE i.item_id = r.item_id and + r.revision_id = :project_id + + + + + + select status_id + from pm_project_status + where status_type = 'o' and + rownum = 1 + + + + + + select status_id + from pm_project_status + where status_type = 'c' and + rownum = 1 + + + + + + begin + :1 := pm_project.new_project_item ( + p_project_name => :project_name, + p_project_code => :project_code, + p_parent_id => :parent_id, + p_goal => :goal, + p_description => :description, + p_mime_type => :mime_type, + p_planned_start_date => to_date(:planned_start_date,'YYYY MM DD HH24 MI SS'), + p_planned_end_date => to_date(:planned_end_date,'YYYY MM DD HH24 MI SS'), + p_actual_start_date => null, + p_actual_end_date => null, + p_logger_project => :logger_project, + p_ongoing_p => :ongoing_p, + p_status_id => :status_id, + p_customer_id => :organization_id, + p_creation_user => :creation_user, + p_creation_ip => :creation_ip, + p_package_id => :package_id + ); + end; + + + + + + SELECT i.item_id, + i.content_type + FROM cr_items i, + pm_tasks_active t + WHERE i.item_id = t.task_id and + i.parent_id = :project_item_id + + + + + + select sum(t.actual_hours_worked) as actual_hours_completed, + sum(t.estimated_hours_work) as estimated_hours_total, + to_char(current_timestamp,'J') as today_j + from pm_tasks_revisionsx t, + cr_items i, + pm_tasks_active a + where i.item_id = a.task_id and + t.item_id in ([join $task_list ", "]) and + i.live_revision = t.revision_id + + + + + + SELECT case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as worked, + t.estimated_hours_work as to_work, + t.item_id as my_iid, + to_char(end_date,'J') as task_deadline_j, + to_char(earliest_start,'J') as old_earliest_start_j, + to_char(earliest_finish,'J') as old_earliest_finish_j, + to_char(latest_start,'J') as old_latest_start_j, + to_char(latest_finish,'J') as old_latest_finish_j, + t.percent_complete as my_percent_complete, + s.status_type + from pm_tasks_revisionsx t, + cr_items i, + pm_tasks_active ti, + pm_task_status s + where t.item_id in ([join $task_list ", "]) and + i.live_revision = t.revision_id and + i.item_id = ti.task_id and + ti.status = s.status_id + + + + + + SELECT d.dependency_id, + d.task_id as task_item_id, + d.parent_task_id, + d.dependency_type + FROM pm_task_dependency d + WHERE d.task_id in ([join $task_list ", "]) + + + + + + SELECT to_char(planned_start_date,'J') as start_date_j, + to_char(planned_end_date,'J') as end_date_j, + ongoing_p + FROM pm_projects + WHERE project_id = (select live_revision from cr_items where item_id = :project_item_id) + + + + + + UPDATE pm_projects + SET actual_hours_completed = :actual_hours_completed, + estimated_hours_total = :estimated_hours_total, + earliest_finish_date = :max_earliest_finish, + latest_finish_date = :min_latest_start + WHERE project_id = (select live_revision from cr_items where item_id = :project_item_id) + + + + + + select parent_id + from cr_items + where item_id = :my_item_id + + + + + + select pm_project.get_root_folder (:package_id, 'f') from dual + + + + + + UPDATE pm_tasks_revisions + SET earliest_start = :es, + earliest_finish = :ef, + latest_start = :ls, + latest_finish = :lf + WHERE task_revision_id = (select live_revision from cr_items where item_id = :task_item) + + + + + + SELECT + party_id + FROM + pm_project_assignment + WHERE + project_id = :project_item_id and + party_id = :party_id + LIMIT 1 + + + + Index: openacs-4/packages/project-manager/tcl/project-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/project-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/project-procs-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,248 @@ + + + + postgresql7.3 + + + + SELECT + live_revision + FROM + cr_items + WHERE + item_id = :project_item_id + + + + + + SELECT + i.item_id + FROM + cr_items i, + cr_revisions r + WHERE + i.item_id = r.item_id and + r.revision_id = :project_id + + + + + + select status_id + from pm_project_status + where status_type = 'o' + limit 1 + + + + + + select status_id + from pm_project_status + where status_type = 'c' + limit 1 + + + + + + INSERT INTO + pm_task_logger_proj_map + (task_item_id, + logger_entry) + VALUES + (:task_item_id, + :entry_id) + + + + + + select pm_project__new_project_item ( + :project_name, + :project_code, + :parent_id, + :goal, + :description, + :mime_type, + to_timestamp(:planned_start_date,'YYYY MM DD HH24 MI SS'), + to_timestamp(:planned_end_date,'YYYY MM DD HH24 MI SS'), + null, + null, + :logger_project, + :ongoing_p, + :status_id, + :organization_id, + current_timestamp, + :creation_user, + :creation_ip, + :package_id + ); + + + + + + SELECT + i.item_id, + i.content_type + FROM + cr_items i, + pm_tasks_active t + WHERE + i.item_id = t.task_id and + i.parent_id = :project_item_id + + + + + + select + sum(t.actual_hours_worked) as actual_hours_completed, + sum(t.estimated_hours_work) as estimated_hours_total, + to_char(current_timestamp,'J') as today_j + from + pm_tasks_revisionsx t, + cr_items i, + pm_tasks_active a + where + i.item_id = a.task_id and + t.item_id in ([join $task_list ", "]) and + i.live_revision = t.revision_id + + + + + + SELECT + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as worked, + t.estimated_hours_work as to_work, + t.item_id as my_iid, + to_char(end_date,'J') as task_deadline_j, + to_char(earliest_start,'J') as old_earliest_start_j, + to_char(earliest_finish,'J') as old_earliest_finish_j, + to_char(latest_start,'J') as old_latest_start_j, + to_char(latest_finish,'J') as old_latest_finish_j, + t.percent_complete as my_percent_complete, + s.status_type + from + pm_tasks_revisionsx t, + cr_items i, + pm_tasks_active ti, + pm_task_status s + where + t.item_id in ([join $task_list ", "]) and + i.live_revision = t.revision_id and + i.item_id = ti.task_id and + ti.status = s.status_id + + + + + + select + d.dependency_id, + d.task_id as task_item_id, + d.parent_task_id, + d.dependency_type + from + pm_task_dependency d + where + d.task_id in ([join $task_list ", "]) + + + + + + select + to_char(planned_start_date,'J') as start_date_j, + to_char(planned_end_date,'J') as end_date_j, + ongoing_p + from + pm_projects + where + project_id = (select live_revision from cr_items where item_id = :project_item_id) + + + + + + update + pm_projects + set + actual_hours_completed = :actual_hours_completed, + estimated_hours_total = :estimated_hours_total, + earliest_finish_date = :max_earliest_finish, + latest_finish_date = :min_latest_start + where + project_id = (select live_revision from cr_items where item_id = :project_item_id) + + + + + + select + parent_id + from + cr_items + where + item_id = :my_item_id + + + + + + select pm_project__get_root_folder (:package_id, 'f') + + + + + + update + pm_tasks_revisions + set + earliest_start = :es, + earliest_finish = :ef, + latest_start = :ls, + latest_finish = :lf + where + task_revision_id = (select live_revision from cr_items where item_id = :task_item) + + + + + + SELECT + case when o.name is null then p.title else p.title || ' (' || o.name || ')' end, + p.item_id + FROM pm_projectsx p + LEFT JOIN + organizations o + ON p.customer_id = o.organization_id, + cr_items i, + pm_project_status s + WHERE + p.project_id = i.live_revision and + s.status_id = p.status_id and + s.status_type = 'o' + ORDER BY + lower(p.title), lower(o.name) + + + + + + SELECT + party_id + FROM + pm_project_assignment + WHERE + project_id = :project_item_id and + party_id = :party_id + LIMIT 1 + + + + Index: openacs-4/packages/project-manager/tcl/project-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/project-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/project-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,2081 @@ +ad_library { + + Project Manager Projects Library + + Procedures that deal with projects + + @creation-date 2003-08-25 + @author Jade Rubick + @cvs-id $Id: project-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + +} + +namespace eval pm::project {} + + +ad_proc -public pm::project::get_project_id { + -project_item_id:required +} { + Returns the live project_id when give the project_item_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-19 + + @param project_item_id The item_id for the project + + @return project_id + + @error +} { + set return_val [db_string get_project_id { }] + + return $return_val +} + + + +ad_proc -public pm::project::get_project_item_id { + -project_id:required +} { + Returns the item_id for a project when given the project_id + (a revision id) + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-19 + + @param project_id + + @return project_item_id + + @error +} { + set return_val [db_string get_project_item { }] + + return $return_val +} + + + +ad_proc -public pm::project::default_status_open {} { + Returns the default status value for open projects +} { + set return_val [db_string get_default_status_open { }] + + return $return_val +} + + + +ad_proc -public pm::project::default_status_closed {} { + Returns the default status value for closed projects +} { + set return_val [db_string get_default_status_closed { }] + + return $return_val +} + + + +ad_proc -private pm::project::log_hours { + {-entry_id ""} + -logger_project_id:required + -variable_id:required + -value:required + {-timestamp_ansi ""} + {-description ""} + {-task_item_id ""} + {-project_item_id ""} + {-update_status_p "t"} + {-party_id ""} +} { + Adds a logger entry to a project. If task_item_id is passed + in, also links it up with that task, and updates the task + hours. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-05 + + @see logger::entry::new + @see pm::project::compute_status + + @param entry_id If passed in, determines the entry_id for the + newly logged entry + + @param logger_project_id + + @param variable_id + + @param value + + @param timestamp_ansi Timestamp in ANSI format YYYY-MM-DD + + @param description + + @param task_item_id + + @param project_item_id If the task_item_id is passed in, the + project_item_id needs to be passed in as well + + @param update_status_p If t, then updates the database for the + task and project so that the denormalized values are updated. + This can be set to f when editing a task, because these things + are done later anyway. + + @param party_id If set, the party that creates the new logger + entry. If not set, defaults to ad_conn user_id + + @return 0 if there no task it is logged against, otherwise returns + the total number of hours logged to that task + + @error returns -1 if there is an error in pm::task::update_hours + If a task_id is passed in, essentially passes along any errors + from pm::task::update_hours +} { + set returnval 0 + + # get a new entry_id if it's not passed in (like it would be from + # a page that was using ad_form) + if {[empty_string_p $entry_id]} { + set entry_id [db_nextval acs_object_id_seq] + } + + if {[exists_and_not_null party_id]} { + set creation_user $party_id + } else { + set creation_user [ad_conn user_id] + } + + if {[empty_string_p $timestamp_ansi]} { + set timestamp_ansi [clock format [clock seconds] -format "%Y-%m-%d"] + } + + # add in the new entry + logger::entry::new -entry_id $entry_id \ + -project_id $logger_project_id \ + -variable_id $variable_id \ + -value $value \ + -time_stamp $timestamp_ansi \ + -description $description \ + -party_id $creation_user + + # if we have a pm_task_id, then we need to note that this + # entry is logged to a particular task. + if {[exists_and_not_null task_item_id]} { + db_dml add_task_logger_map { } + + set returnval [pm::task::update_hours \ + -task_item_id $task_item_id \ + -update_tasks_p $update_status_p] + + if {[string is true $update_status_p]} { + pm::project::compute_status $project_item_id + } + } + + return $returnval +} + + + +ad_proc -public pm::project::new { + -project_name:required + {-project_code ""} + {-parent_id ""} + {-goal ""} + {-description ""} + {-mime_type "text/plain"} + {-planned_start_date ""} + {-planned_end_date ""} + {-actual_start_date ""} + {-actual_end_date ""} + {-ongoing_p "f"} + -status_id:required + -organization_id:required + {-creation_date ""} + -creation_user:required + -creation_ip:required + -package_id:required +} { + Creates a new project + + @author Jade Rubick (jader@bread.com) + + @param project_name + + @error +} { + + # if the project is ongoing, there is no end date + # we set it to null to signify that. Technically, this + # is bad data model design -- we should just get rid of + # ongoing_p + if {[string equal $ongoing_p t]} { + set actual_end_date "" + set planned_end_date "" + } + + # create a logger project + set logger_project [logger::project::new \ + -name $project_name \ + -project_lead $creation_user \ + ] + + # we want the logger project to show up in logger! + set logger_URLs [parameter::get -parameter "LoggerURLsToKeepUpToDate" -default ""] + foreach url $logger_URLs { + # get the package_id + set node_id [site_node::get_node_id -url $url] + array set node [site_node::get -node_id $node_id] + set this_package_id $node(package_id) + + logger::package::map_project \ + -project_id $logger_project \ + -package_id $this_package_id + } + + # create a project manager project (associating the logger project + # with the logger project) + set project_revision [db_exec_plsql new_project_item { *SQL }] + + set project_item_id [pm::project::get_project_item_id \ + -project_id $project_revision] + + set project_role [pm::role::default] + + pm::project::assign \ + -project_item_id $project_item_id \ + -role_id $project_role \ + -party_id $creation_user \ + -send_email_p "f" + + return $project_revision +} + + +ad_proc -public pm::project::delete { + -project_item_id:required +} { + Stub for project deletion + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-03 + + @param project_item_id + + @return + + @error +} { + + # should we delete the logger project as well? + +} + + +ad_proc -public pm::project::edit { + -project_item_id:required + -project_name:required + {-project_code ""} + {-parent_id ""} + {-goal ""} + {-description ""} + {-planned_start_date ""} + {-planned_end_date ""} + {-actual_start_date ""} + {-actual_end_date ""} + -logger_project:required + {-ongoing_p "f"} + -status_id:required + -organization_id:required + {-creation_date ""} + -creation_user:required + -creation_ip:required + -package_id:required +} { + Stub for project edit + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-03 + + @param project_item_id + + @param project_name + + @return + + @error +} { + + # if we edit the name of the project, we need to edit the logger + # project name too. + + set logger_project [pm::project::get_logger_project \ + -project_item_id $project_item_id] + + set active_p [pm::status::open_p -task_status_id $status_id] + set customer_name [organizations::name -organization_id "$organization_id"] + + if {![empty_string_p $customer_name]} { + append customer_name " - " + } + + logger::project::edit \ + -project_id $logger_project \ + -name "$customer_name$project_name" \ + -description "$description" \ + -project_lead $creation_user \ + -active_p $active_p + + set returnval [db_exec_plsql update_project " + select pm_project__new_project_revision ( + :project_item_id, + :project_name, + :project_code, + :parent_id, + :goal, + :description, + to_timestamp(:planned_start_date,'YYYY MM DD HH24 MI SS'), + to_timestamp(:planned_end_date,'YYYY MM DD HH24 MI SS'), + null, + null, + :logger_project, + :ongoing_p, + :status_id, + :organization_id, + now(), + :creation_user, + :creation_ip, + :package_id + ); + "] + + return $returnval +} + + +ad_proc -public pm::project::get { + -project_item_id:required + -array:required +} { + Stub for get function + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-03 + + @param project_item_id + + @param array + + @return values for this project identified by project_item_id, in + an array named array + + @error +} { + +} + + + +ad_proc -private pm::project::latest_start { + {-end_date_j:required} + {-hours_to_complete:required} + {-hours_day:required} +} { + Returns the latest_start date. This is equal to the + latest finish date minus the amount of time it will + take to accomplish the job. Also takes into + account weekdays. +

    + Someday, it should disregard holidays! + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-20 + + @param end_date_j + + @param hours_to_complete Estimated number of hours it will take + to complete this task + + @param hours_day Number of hours in a day + + @return the latest start date, as a Julian number + + @error +} { + + + set t_end_date $end_date_j + set t_today $t_end_date + + while {![is_workday_p $t_today]} { + set t_today [expr $t_today - 1] + } + set t_total_hours $hours_to_complete + + while {$t_total_hours > $hours_day} { + + set t_today [expr $t_today - 1] + + # if it is a holiday, don't subtract from total time + + if {[is_workday_p $t_today]} { + set t_total_hours [expr $t_total_hours - $hours_day] + } + + } + + return $t_today + +} + + +ad_proc -private pm::project::earliest_finish { + earliest_start_j + hours_to_complete + hours_day +} { + + # set earliest_finish($task_item) [expr $earliest_start($task_item) + [expr $activity_time($task_item) / double($hours_day)]] + + # we now set the earliest finish. This is equal to the + # earliest start plus the amount of time it will + # take to accomplish the job. We need to disregard holidays! + + set t_start_date $earliest_start_j + set t_today $t_start_date + + while {![is_workday_p $t_today]} { + set t_today [expr $t_today + 1] + } + set t_total_hours $hours_to_complete + + while {$t_total_hours > $hours_day} { + + set t_today [expr $t_today + 1] + + # if it is a holiday, don't subtract from total time + + if {[is_workday_p $t_today]} { + set t_total_hours [expr $t_total_hours - $hours_day] + } + + } + + return $t_today + +} + + +ad_proc -private pm::project::my_earliest_start { + earliest_start_j + hours_to_complete + hours_day +} { + Computing the earliest start requires getting a max of all the possible + candidates. This returns the value for one candidate +} { + # set my_earliest_start [expr [expr $activity_time($dependent_item) / double($hours_day)] + $earliest_start($dependent_item)] + + set t_start_date $earliest_start_j + set t_today $t_start_date + + while {![is_workday_p $t_today]} { + set t_today [expr $t_today + 1] + } + + set t_total_hours $hours_to_complete + + while {$t_total_hours > $hours_day} { + + set t_today [expr $t_today + 1] + + # if it is a holiday, don't subtract from total time + + if {[is_workday_p $t_today]} { + set t_total_hours [expr $t_total_hours - $hours_day] + } + + } + + return $t_today + +} + + +ad_proc -private pm::project::my_latest_finish { + latest_start_j + hours_to_complete + hours_day +} { + Computing the latest +} { + # set temp [expr $min_latest_start + [expr $activity_time($task_item) / double($hours_day)]] + + if {[empty_string_p $latest_start_j]} { + return "" + } + + set t_start_date $latest_start_j + set t_today $t_start_date + + while {![is_workday_p $t_today]} { + set t_today [expr $t_today + 1] + } + + set t_total_hours $hours_to_complete + + while {$t_total_hours > $hours_day} { + + set t_today [expr $t_today + 1] + + # if it is a holiday, don't subtract from total time + + if {[is_workday_p $t_today]} { + set t_total_hours [expr $t_total_hours - $hours_day] + } + + } + + return $t_today + +} + + +ad_proc -private pm::project::julian_to_day_of_week { + julian_date +} { + Computes the day of the week. 0=Sunday + Initially, I used Tcl's clock command, but it doesn't accept dates + larger than 2038, so I had to do this myself. +} { + set date [dt_julian_to_ansi $julian_date] + regexp {([0-9]*)-([0-9]*)-([0-9]*)} $date match year month day + regexp {0(.)} $month match month extra + regexp {0(.)} $day match day extra + set alpha [expr [expr 14 - $month] / 12] + set y [expr $year - $alpha] + set m [expr $month + [expr 12 * $alpha] - 2] + set day_of_week_pre_mod [expr $day + $y + [expr $y / 4] - [expr $y / 100] + [expr $y / 400] + [expr 31 * $m / 12]] + set day_of_week [expr $day_of_week_pre_mod % 7] + return $day_of_week +} + + + +ad_proc -private pm::project::is_workday_p { + date_j +} { + + Figures out whether or not a given date is a workday or not. + Assumes Saturday and Sunday are not workdays + +} { + + # need to add in a table of holidays + + set day_of_week [julian_to_day_of_week $date_j] + + if {[string equal $day_of_week 6] || [string equal $day_of_week 0]} { + return 0 + } else { + return 1 + } +} + + + +ad_proc -public pm::project::compute_status {project_item_id} { + + Looks at tasks and subprojects, and computes the current status of a project. +

    + + These are the items we'd like to compute + +

    +    PROJECTS:
    +    estimated_completion_date       timestamptz,
    +    earliest_completion_date        timestamptz,
    +    latest_completion_date          timestamptz,
    +    actual_hours_completed          numeric,
    +    estimated_hours_total           numeric
    +    TASKS:
    +    earliest start(i)  = max(activity_time(i-1) + earliest_start(i-1))
    +    earliest_finish(i) = earliest_start(i) + activity_time(i)
    +    latest_start(i)    = min(latest_start(i+1) - activity_time(i)
    +    latest_finish(i)   = latest_start(i) + activity_time(i)
    +    
    + + (i-1 means an item that this task depends on) + +

    + + These algorithms are explained at: + http://mscmga.ms.ic.ac.uk/jeb/or/netaon.html

    + + Tasks in ongoing projects are given null completion dates, + unless they already have deadlines. + +

    + + The statistics are computed based on: +

    + + Project statistics are based on that project + subproject statistics +

    + + That means if a project has a subproject, then the tasks for + both of those projects are put together in one list, and computed + together. + +

    + + So for a project with no subprojects, the values are computed + for the tasks in that project + +

    + For a project with subprojects, the statistics are based on the + tasks of both of those projects. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-19 + + @param project_item_id The item_id for the project + + @return a list of task_item_ids of all tasks under a project, plus all subproject tasks. This is done so that the function can be recursive + + @error No error codes + +} { + + # Before hacking on this, you might want to look at: + # http://www.joelonsoftware.com/articles/fog0000000069.html + + # the first thing that should be done on this code is that it + # should be broken out to a number of utility procs. + + set debug 0 + + # TODO: + # + # ------------------------------------------------------------------------- + # to improve this in the future, be more intelligent about what is updated. + # i.e., this procedure updates everything, which is necessary sometimes, + # but not if you only edit one task. + # + # I added in an optimization to only save when something has + # changed -- JR + # ------------------------------------------------------------------------- + # Add in resource limits. (it's not realistic that 300 tasks can be done in + # one day) + # ------------------------------------------------------------------------- + # Use dependency types -- currently they're all treated like finish_to_start + # ------------------------------------------------------------------------- + + + # note if you want to understand the algorithms in this function, you + # should look at: + # http://mscmga.ms.ic.ac.uk/jeb/or/netaon.html + + if {[string is true $debug]} { + ns_log Notice "-----------------------------------------" + } + + # -------------------------------------------------------------------- + # for now, hardcode in a day is 8 hours. Later, we want to set this by + # person. + # -------------------------------------------------------------------- + set hours_day [pm::util::hours_day] + + + # ------------------------- + # get subprojects and tasks + # ------------------------- + set task_list [list] + set task_list_project [list] + + foreach sub_item [db_list_of_lists select_project_children { }] { + set my_id [lindex $sub_item 0] + set my_type [lindex $sub_item 1] + + if {[string equal $my_type "pm_project"]} { + + # --------------------------------------------- + # gets all tasks that are a part of subprojects + # --------------------------------------------- + set project_return [pm::project::compute_status $my_id] + set task_list_project [concat $task_list_project $project_return] + + } elseif {[string equal $my_type "pm_task"]} { + lappend task_list $my_id + } + } + + set task_list [concat $task_list $task_list_project] + + if {[string is true $debug]} { + ns_log Notice "Tasks in this project (task_list): $task_list" + } + + # ------------------------- + # no tasks for this project + # ------------------------- + if {[llength $task_list] == 0} { + return [list] + } + + # -------------------------------------------------------------- + # we now have list of tasks that includes all subprojects' tasks + # -------------------------------------------------------------- + + # returns actual_hours_completed, estimated_hours_total, and + # today_j (julian date for today) + db_1row tasks_group_query { } + + if {[string is true $debug]} { + ns_log notice "Today's date (julian format): $today_j" + } + + # -------------------------------------------------------------- + # Set up activity_time for all tasks + # Also set up deadlines for tasks that have hard-coded deadlines + # -------------------------------------------------------------- + + if {[string is true $debug]} { + ns_log notice "Going through tasks and saving their values" + } + + db_foreach tasks_query { } { + + # We now save information about all the tasks, so that we can + # save on database hits later. Specifically, what we'll do is + # we won't need to save changes if the earliest_start, + # earliest finish, latest_start and latest_finish all haven't + # changed at all. We also save whether the task is open (o) or + # closed(c). + + set old_ES_j($my_iid) $old_earliest_start_j + set old_EF_j($my_iid) $old_earliest_finish_j + set old_LS_j($my_iid) $old_latest_start_j + set old_LF_j($my_iid) $old_latest_finish_j + set task_percent_complete($my_iid) $my_percent_complete + + set activity_time($my_iid) [expr [expr $to_work * [expr 100 - $my_percent_complete] / 100]] + + if {[exists_and_not_null task_deadline_j]} { + + if {[string is true $debug]} { + ns_log notice "$my_iid has a deadline (julian: $task_deadline_j)" + } + + set latest_finish($my_iid) $task_deadline_j + + set latest_start($my_iid) [pm::project::latest_start \ + -end_date_j $task_deadline_j \ + -hours_to_complete $activity_time($my_iid) \ + -hours_day $hours_day] + + } + } + + # -------------------------------------------------------------------- + # We need to keep track of all the dependencies so we can meaningfully + # compute deadlines, earliest start times, etc.. + # -------------------------------------------------------------------- + + db_foreach dependency_query { } { + + # task_item_id depends on parent_task_id + lappend depends($task_item_id) $parent_task_id + + # parent_task_id is dependent on task_item_id + lappend dependent($parent_task_id) $task_item_id + + set dependency_types($task_item_id-$parent_task_id) $dependency_type + + if {[string is true $debug]} { + ns_log Notice "dependency (id: $dependency_id) task: $task_item_id parent: $parent_task_id type: $dependency_type" + } + } + + + # -------------------------------------------------------------- + # need to get some info on this project, so that we can base the + # task information off of them + # -------------------------------------------------------------- + + # gives up end_date_j, start_date_j, and ongoing_p + # if ongoing_p is t, then end_date_j should be null + db_1row project_info { } + + if {[string is true $ongoing_p] && ![empty_string_p $end_date_j]} { + ns_log Error "Project cannot be ongoing and have a non-null end-date. Setting end date to blank" + set end_date_j "" + } + + + # -------------------------------------------------------------- + # task_list contains all the tasks + # a subset of those do not depend on any other tasks + # -------------------------------------------------------------- + + # ---------------------------------------------------------------------- + # we want to go through and fill in all the values for earliest start. + # the brain-dead, brute force way of doing this, would be go through the + # task_list length(task_list) times, and each time, compute the values + # for each item that depends on one of those tasks. This is extremely + # inefficient. + # ---------------------------------------------------------------------- + # Instead, we create two lists, one is of tasks we just added + # earliest_start values for, the next is a new list of ones we're going to + # add earliest_start values for. We call these lists + # present_tasks and future_tasks + # ---------------------------------------------------------------------- + + set present_tasks [list] + set future_tasks [list] + + # ----------------------------------------------------- + # make a list of tasks that don't depend on other tasks + # ----------------------------------------------------- + # while we're at it, save earliest_start and earliest_finish + # info for these items + # ----------------------------------------------------- + + foreach task_item $task_list { + + if {![info exists depends($task_item)]} { + + set earliest_start($task_item) $start_date_j + set earliest_finish($task_item) [earliest_finish $earliest_start($task_item) $activity_time($task_item) $hours_day] + + lappend present_tasks $task_item + + if {[string is true $debug]} { + ns_log Notice "preliminary earliest_start($task_item): $earliest_start($task_item)" + } + } + } + + # ------------------------------- + # stop if we have no dependencies + # ------------------------------- + if {[llength $present_tasks] == 0} { + + if {[string is true $debug]} { + ns_log Notice "No tasks with dependencies" + } + + return [list] + } + + if {[string is true $debug]} { + ns_log Notice "present_tasks: $present_tasks" + } + + # ------------------------------------------------------ + # figure out the earliest start and finish times + # ------------------------------------------------------ + + while {[llength $present_tasks] > 0} { + + set future_tasks [list] + + foreach task_item $present_tasks { + + if {[string is true $debug]} { + ns_log Notice "-this task_item: $task_item" + } + + # ----------------------------------------------------- + # some tasks may already have earliest_start filled in + # the first run of tasks, for example, had their values + # filled in earlier + # ----------------------------------------------------- + + if {![exists_and_not_null earliest_start($task_item)]} { + + if {[string is true $debug]} { + ns_log Notice " !info exists for $task_item" + } + + # --------------------------------------------- + # set the earliest_start for this task = + # max(activity_time(i-1) + earliest_start(i-1)) + # + # (i-1 means an item that this task depends on) + # --------------------------------------------- + + set max_earliest_start 0 + + # testing if this fixes the bug + if {![exists_and_not_null depends($task_item)]} { + set depends($task_item) [list] + } + + foreach dependent_item $depends($task_item) { + + set my_earliest_start [my_earliest_start $earliest_start($dependent_item) $activity_time($dependent_item) $hours_day] + + if {$my_earliest_start > $max_earliest_start} { + set max_earliest_start $my_earliest_start + } + } + + set earliest_start($task_item) $max_earliest_start + + set earliest_finish($task_item) [earliest_finish $max_earliest_start $activity_time($task_item) $hours_day] + + if {[string is true $debug]} { + ns_log Notice \ + " earliest_start ($task_item): $earliest_start($task_item)" + ns_log Notice \ + " earliest_finish($task_item): $earliest_finish($task_item)" + } + + } + + # ------------------------------- + # add to list of tasks to process + # ------------------------------- + + if {[info exists dependent($task_item)]} { + set future_tasks [concat $future_tasks $dependent($task_item)] + } + } + + if {[string is true $debug]} { + ns_log Notice "future tasks: $future_tasks" + } + + set present_tasks $future_tasks + } + + # ---------------------------------------------- + # set up earliest date project will be completed + # ---------------------------------------------- + + set max_earliest_finish $today_j + + foreach task_item $task_list { + + if {[string is true $debug] && [exists_and_not_null earliest_finish($task_item)]} { + ns_log Notice "* EF: ($task_item): $earliest_finish($task_item)" + } + + if {[exists_and_not_null earliest_finish($task_item)] && $max_earliest_finish < $earliest_finish($task_item)} { + set max_earliest_finish $earliest_finish($task_item) + } + + } + + + # ----------------------------------------------------------------- + # Now compute latest_start and latest_finish dates. + # Note the latest_finish dates may be set to an arbitrary deadline. + # Also note that it is possible for a project to be ongoing. + # In that case, the latest_start and latest_finish dates should + # be set to null, unless there is a hard deadline (end_date). + # ----------------------------------------------------------------- + # If these represent the dependency hierarchy: + # 2155 + # / | \ + # 2161 2173 2179 + # | | + # 2167 2195 + # ---------------------------------------------------------------------- + # we want to go through and fill in all the values for latest start + # and latest_finish. + # the brain-dead, brute force way of doing this, would be go through the + # task_list length(task_list) times, and each time, compute the values + # for each item that depends on one of those tasks. This is extremely + # inefficient. + # ---------------------------------------------------------------------- + # Instead, we create two lists, one is of tasks we just added + # latest_finish values for, the next is a new list of ones we're going to + # add latest_finish values for. We call these lists + # present_tasks and future_tasks + # ---------------------------------------------------------------------- + # Here's a description of the algorithm. + # 1. The algorithm starts with those tasks that don't have other + # tasks depending on them. + # + # So in the example above, we'll start with + # present_tasks: 2167 2173 2195 + # future tasks: + # + # 2. While we make the present_tasks list, we store latest_start + # and latest_finish information for each of those tasks. If the + # project is ongoing, then we also keep track of tasks that have + # no latest_start or latest_finish. We keep this in the + # ongoing_task(task_id) array. If is exists, then we know that + # that task is an ongoing task, so no deadline will exist for it. + # + # 3. Stop if we don't have any dependencies + # + # 4. Then we get into a loop. + # While there are present_tasks: + # Create the future_tasks list + # For each present task: + # If the task has a dependent task: + # Go through these dependent tasks: + # If the dependent task is ongoing don't defer + # If the dependent task doesn't have LS set, + # then defer, and add to future_tasks list + # Otherwise set the LS value for that task + # If there are no deferals, get the minimum LS of + # dependents, set LF + # Add the dependent tasks to the future_tasks + # Set present_tasks equal to future_tasks, clear future_tasks + + # ---------------------------------------------------------------------- + # The biggest problem with this algorithm is that you can have items at + # two different levels in the hierarchy. + # + # if you trace through this algorithm, you'll see that we'll get to 2155 + # before 2161's values have been set, which can cause an error. The + # solution we arrive at is to defer to the future_tasks list any item + # that causes an error. That should work. + + set present_tasks [list] + set future_tasks [list] + + # ----------------------------------------------------- + # make a list of tasks that don't have tasks depend on them + # ----------------------------------------------------- + # while we're at it, save latest_start and latest_finish + # info for these items + # ----------------------------------------------------- + + if {[string is true $debug]} { + ns_log Notice "Starting foreach task-item $task_list" + } + + foreach task_item $task_list { + + if {![info exists dependent($task_item)]} { + + if {[string is true $debug]} { + ns_log Notice " !info exists dependent($task_item)" + } + + # we check this because some tasks already have + # hard deadlines set. + if {[info exists latest_finish($task_item)]} { + + # if the project needs to be completed before the + # actual hard deadline, then the project deadline + # has precedence. However, sometimes the project is + # ongoing, so we have to make sure that there actually + # is an end_date_j + + # commented out: we need to trust the user. If they + # set the deadline outside the project deadline, + # that's their business + + #if {![empty_string_p $end_date_j]} { + # if {$end_date_j < $latest_finish($task_item)} { + # set latest_finish($task_item) $end_date_j + # } + #} + + # we also set the latest_start date + + if {[string is false [exists_and_not_null activity_time($task_item)]]} { + set activity_time($task_item) 0 + ns_log Notice "setting activity_time($task_item) 0" + } + + set late_start_temp \ + [latest_start \ + -end_date_j $latest_finish($task_item) \ + -hours_to_complete $activity_time($task_item) \ + -hours_day $hours_day] + + if {$late_start_temp < $latest_start($task_item)} { + set latest_start($task_item) $late_start_temp + } + + } else { + + # this section is for items that have no solid + # deadline, but also have no items dependent on them + + # we either set the latest start and finish of the item or + # we specify that the task is an ongoing task + if {[empty_string_p $end_date_j]} { + set ongoing_task($task_item) true + + if {[string is true $debug]} { + ns_log Notice "NSDBAHNITD: end_date_j was empty ti:$task_item" + } + } else { + set latest_finish($task_item) $end_date_j + + if {[string is false [exists_and_not_null activity_time($task_item)]]} { + set activity_time($task_item) 0 + ns_log Notice "setting activity_time($task_item) 0 (location 2)" + } + + set latest_start($task_item) \ + [latest_start \ + -end_date_j $latest_finish($task_item) \ + -hours_to_complete $activity_time($task_item) \ + -hours_day $hours_day] + + } + } + lappend present_tasks $task_item + + if {[string is true $debug] && [exists_and_not_null latest_start($task_item)]} { + ns_log Notice "preliminary latest_start($task_item): $latest_start($task_item)" + } + + if {[string is true $debug] && [exists_and_not_null latest_finish($task_item)]} { + ns_log Notice "preliminary latest_finish($task_item): $latest_finish($task_item)" + } + + + + } else { + if {[string is true $debug]} { + ns_log Notice " info exists dependent($task_item)" + } + } + } + + + # ------------------------------- + # stop if we have no dependencies + # ------------------------------- + if {[llength $present_tasks] == 0} { + if {[string is true $debug]} { + ns_log Notice "No tasks with dependencies" + } + return [list] + } + + if {[string is true $debug]} { + ns_log Notice "LATEST present_tasks: $present_tasks" + } + + # ------------------------------------------------------ + # figure out the latest start and finish times + # ------------------------------------------------------ + + while {[llength $present_tasks] > 0} { + + set future_tasks [list] + + foreach task_item $present_tasks { + + if {[string is true $debug]} { + ns_log Notice "this task_item: $task_item" + } + + # ----------------------------------------------------- + # some tasks may already have latest_start filled in. + # the first run of tasks, for example, had their values + # filled in earlier + # ----------------------------------------------------- + + if {[info exists dependent($task_item)]} { + + if {[string is true $debug]} { + ns_log Notice " info exists for dependent($task_item)" + } + + # --------------------------------------------- + # set the latest_start for this task = + # min(latest_start(i+1) - activity_time(i)) + # + # (i+1 means an item that depends on this task) + # (i means this task) + # --------------------------------------------- + + # we set this to the end date, and then move it forward + # as we find dependent items that have earlier + # latest_start dates. The problem is that the + # end_date_j is empty when there is no deadline. + # So we need to remember that min_latest_start can + # be an empty value + + set min_latest_start $end_date_j + + if {[string is true $debug]} { + ns_log Notice " min_latest_start: $end_date_j" + } + + foreach dependent_item $dependent($task_item) { + + if {[string is true $debug]} { + ns_log Notice " dependent_item: $dependent_item" + } + + if {[exists_and_not_null ongoing_task($dependent_item)]} { + set defer_p f + set my_latest_start "" + + if {[string is true $debug]} { + ns_log Notice " ongoing_task, no defer" + } + + } elseif {![exists_and_not_null latest_start($dependent_item)]} { + # we defer the task if the dependent item has no + # latest_start date set + + if {[info exists defer_count($task_item)]} { + incr defer_count($task_item) + } else { + set defer_count($task_item) 1 + } + + # we use a magic number here. + # basically, we don't want to defer the + # item forever. Ideally, this should + # be cleaned up better. Defering is necessary + # given this algorithm, but there are + # times when you don't want to defer. + # This is hackish, and I'm embarrased, but on + # a deadline. :( + if {$defer_count($task_item) > 5} { + set defer_p f + + if {[string is true $debug]} { + ns_log Notice " no defer because defer count exceeded" + } + } else { + lappend future_tasks $task_item + + if {[string is true $debug]} { + ns_log Notice " defer" + } + + set defer_p t + } + + + + } else { + + # the dependent item has a deadline + + if {[string is false [exists_and_not_null activity_time($task_item)]]} { + set activity_time($task_item) 0 + ns_log Notice "setting activity_time($task_item) 0 (location 3)" + } + + set my_latest_start \ + [latest_start \ + -end_date_j $latest_start($dependent_item) \ + -hours_to_complete $activity_time($task_item) \ + -hours_day $hours_day] + + if {[string is true $debug]} { + ns_log Notice " my_latest_start: $my_latest_start" + } + + # we also only want to move forward the latest_start + # date if the dependent item is not already completed! + + if {$task_percent_complete($dependent_item) < 100} { + if {[exists_and_not_null min_latest_start]} { + if {$my_latest_start < $min_latest_start} { + set min_latest_start $my_latest_start + } + } else { + set min_latest_start $my_latest_start + } + } + + set defer_p f + } + + } + + if {[string equal $defer_p f]} { + + # we check that latest_start doesn't already exist + # which it might for hard-deadlines + + # we have to be fairly careful here. We want to + # set the latest_start date to the minimum + # latest_start, but only when min_latest_start + # actually has a value + + if {[exists_and_not_null latest_start($task_item)]} { + + if {[exists_and_not_null min_latest_start]} { + + if {$min_latest_start < $latest_start($task_item)} { + set latest_start($task_item) $min_latest_start + } + + } else { + + if {[string is true $debug]} { + ns_log notice " setting latest start date (ignoring min_latest_start" + } + + if {[string is false [exists_and_not_null activity_time($task_item)]]} { + set activity_time($task_item) 0 + ns_log Notice "setting activity_time($task_item) 0 (location 4)" + } + + + set latest_start($task_item) \ + [latest_start \ + -end_date_j $latest_finish($task_item) \ + -hours_to_complete $activity_time($task_item) \ + -hours_day $hours_day] + + } + } else { + + # so this task has no hard deadline. + # We now set the value to the minimum of the + # dependent tasks. Note that if the dependent + # tasks all have no hard deadlines, and the + # project is ongoing, then the value will be + # set to "" + + set latest_start($task_item) $min_latest_start + } + + if {[string is true $debug]} { + ns_log Notice " min_latest_start: $min_latest_start" + } + + # we now set the latest finish. Ongoing tasks set + # the latest finish to empty (sometimes) + if {[empty_string_p $latest_start($task_item)]} { + set temp_lf "" + } else { + set temp_lf [my_latest_finish $min_latest_start $activity_time($task_item) $hours_day] + } + + # if there is already a hard deadline for this + # task, then we check whether temp_lf is earlier, + # and set it to temp_lf if so + + if {[string is true $debug]} { + ns_log Notice " temp_lf: $temp_lf" + } + + if {[empty_string_p $temp_lf]} { + + # if the task is ongoing, we clear the + # latest_finish. Otherwise, we leave the + # latest_finish as it is. + + if {[exists_and_not_null ongoing_task($task_item)] && [string is true $ongoing_task($task_item)]} { + set latest_finish($task_item) "" + } + + } else { + if {[exists_and_not_null latest_finish($task_item)]} { + if {$temp_lf < $latest_finish($task_item)} { + set latest_finish($task_item) $temp_lf + } + } else { + set latest_finish($task_item) $temp_lf + } + } + + if {[string is true $debug]} { + if {[exists_and_not_null latest_start($task_item)]} { + ns_log Notice \ + " latest_start ($task_item): $latest_start($task_item)" + } + if {[exists_and_not_null latest_finish($task_item)]} { + ns_log Notice \ + " latest_finish($task_item): $latest_finish($task_item)" + } + } + + } else { + if {[string is true $debug]} { + ns_log Notice "Deferring $task_item" + } + } + } + + # ------------------------------- + # add to list of tasks to process + # ------------------------------- + + if {[info exists depends($task_item)]} { + set future_tasks [concat $future_tasks $depends($task_item)] + } + } + + if {[string is true $debug]} { + ns_log Notice "future tasks: $future_tasks" + } + + set present_tasks $future_tasks + } + + # ---------------------------------------------- + # set up latest start date for project + # ---------------------------------------------- + + if {[empty_string_p $end_date_j]} { + set min_latest_start "" + set max_earliest_finish "" + } else { + set min_latest_start $end_date_j + + foreach task_item $task_list { + + if {[string is true $debug]} { + ns_log Notice "* LS ($task_item): $latest_start($task_item)" + } + + if {[exists_and_not_null earliest_finish($task_item)] && $min_latest_start > $latest_start($task_item)} { + set max_earliest_finish $earliest_finish($task_item) + } + } + + set max_earliest_finish "J[expr floor([set max_earliest_finish])]" + set min_latest_start "J[expr floor([set min_latest_start])]" + } + + + # estimated_finish_date + # latest_finish + + db_dml update_project { } + + # now we go through and save all the values for the tasks! + # this is very inefficient and stupid + + foreach task_item $task_list { + + if {[exists_and_not_null earliest_start($task_item)]} { + set es "J[expr ceil( [set earliest_start($task_item)])]" + } else { + set es "" + } + + if {[exists_and_not_null earliest_finish($task_item)]} { + set ef "J[expr ceil( [set earliest_finish($task_item)])]" + } else { + set ef "" + } + + if {[exists_and_not_null latest_start($task_item)]} { + set ls "J[expr floor([set latest_start($task_item)])]" + } else { + set ls "" + } + + if {[exists_and_not_null latest_finish($task_item)]} { + set lf "J[expr floor($latest_finish($task_item))]" + } else { + set lf "" + } + + # Only update the task if something has actually + # changed. Hopefully this should help speed things up. + + if { \ + [string equal $es $old_ES_j($task_item)] && \ + [string equal $ef $old_EF_j($task_item)] && \ + [string equal $ls $old_LS_j($task_item)] && \ + [string equal $lf $old_LF_j($task_item)]} { + # do nothing + } else { + db_dml update_task { } + } + + + } + + + if {[string is true $debug]} { + ns_log Notice "*******************" + } + + return $task_list + +} + + + + +ad_proc -public pm::project::compute_parent_status {project_item_id} { + + When a project is updated, or a task updated within a project, we need to + update all the projects higher in the hierarchy. + + This may need to be fixed to add back in subproject support. +} { + set package_id [pm::util::package_id] + + # ns_log Notice "computing parents for $project_item_id and package_id: $package_id" + + + set my_item_id $project_item_id + set parent_id [db_string get_parent_id {}] + set last_item_id $my_item_id + + # trace up the hierarchy until we get one below the root + + set root_folder [db_exec_plsql get_root_folder { }] + + while {$parent_id != $root_folder && $parent_id != "-1"} { + set parent_id [db_string get_parent_id {} -default "-1"] + set last_item_id $my_item_id + set my_item_id $parent_id + } + + # ns_log Notice "root: $root_folder , last_item_id $last_item_id" + + set return_code [pm::project::compute_status $last_item_id] + + return $return_code +} + + + +ad_proc -public pm::project::get_logger_project { + -project_item_id:required +} { + Returns logger's project ID when given project manager's project ID + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-04 + + @param project_item_id + + @return logger's project_id + + @error returns no_project if no such project_item_id exists +} { + return [db_string get_logger_project " + SELECT + logger_project + FROM + pm_projects + WHERE + project_id = + (select live_revision from cr_items where item_id = :project_item_id) + " -default "no_project"] +} + + +ad_proc -public pm::project::get_project { + -logger_project:required +} { + Returns the project_item_id when given the logger project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-28 + + @param logger_project + + @return project_item_id + + @error +} { + return [db_string get_logger_project " + SELECT + i.item_id + FROM + pm_projectsx p, cr_items i + WHERE + i.live_revision = p.revision_id and logger_project = :logger_project + " -default "no_project"] + +} + + +ad_proc -public pm::project::get_list_of_open { +} { + Returns a list of lists, of all open project ids and their names. + + We should util_memoize this. It will dramatically improve the + speed of the task edits. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-13 + + @return list of lists, with project id and name + + @error +} { + + set return_val [db_list_of_lists get_vals { }] + + return $return_val +} + + +ad_proc -public pm::project::select_list_of_open { + {-selected ""} +} { + Returns a select list of all open project ids and their names + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-13 + + @return html for select list of open projects + + @error +} { + # is the selected project closed? + set open_p [pm::project::open_p -project_item_id $selected] + + if {[string is false $open_p]} { + set name [pm::project::name -project_item_id $selected] + set html "" + } else { + set html "" + } + + set list_of_lists [pm::project::get_list_of_open] + + foreach lol $list_of_lists { + set name [lindex $lol 0] + set id [lindex $lol 1] + + if {[string equal $id $selected]} { + set sel "selected=\"selected\"" + } else { + set sel "" + } + + append html "\n" + } + + return $html +} + + +ad_proc -public pm::project::close { + {-project_item_id:required} +} { + Closes a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-07-02 + + @param project_item_id + + @return + + @error +} { + + set closed_id [pm::status::default_closed] + + db_dml update_status { + UPDATE + pm_projects + SET + status_id = :closed_id + WHERE + project_id in (select live_revision from cr_items where item_id = :project_item_id) + } + +} + + +ad_proc -public pm::project::open_p { + {-project_item_id:required} +} { + Returns true if the project is open + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-03 + + @param project_item_id + + @return 1 if open, 0 if closed + + @error +} { + set return_val [db_string get_open_or_closed { + SELECT + case when status_type = 'c' then 0 else 1 end + FROM + pm_projectsx p, + cr_items i, + pm_project_status s + WHERE + i.item_id = p.item_id and + i.live_revision = p.revision_id and + p.status_id = s.status_id and + p.item_id = :project_item_id + } -default "0"] + + return $return_val +} + + +ad_proc -public pm::project::assign { + {-project_item_id:required} + {-role_id:required} + {-party_id:required} + {-send_email_p "t"} +} { + Assigns a user to a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param project_item_id + + @param role_id + + @param party_id + + @return + + @error +} { + + db_dml insert_assignment { + insert into pm_project_assignment + (project_id, role_id, party_id) + VALUES + (:project_item_id, :role_id, :party_id) + } + + # Flush the cache that remembers which roles to offer the current user in the 'assign role to myself' listbox + util_memoize_flush [list pm::role::project_select_list_filter_not_cached -project_item_id $project_item_id -party_id $party_id] + + if {[string is true $send_email_p]} { + + set project_name [pm::project::name \ + -project_item_id $project_item_id] + + set project_url [pm::project::url \ + -project_item_id $project_item_id] + + set to_addr [cc_email_from_party $party_id] + set from_addr [cc_email_from_party [ad_conn user_id]] + set role [pm::role::name -role_id $role_id] + + set subject "Assigned to project: $project_name" + + set content "
    You have been assigned to a project: $project_name (as $role)
    " + + + pm::util::email \ + -to_addr $to_addr \ + -from_addr $from_addr \ + -subject $subject \ + -body $content \ + -mime_type "text/html" + } + + return +} + + +ad_proc -public pm::project::unassign { + {-project_item_id:required} + {-party_id:required} +} { + Removes a user from a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param project_item_id + + @param party_id + + @return + + @error +} { + + db_dml remove_assignment { + DELETE FROM + pm_project_assignment + WHERE + project_id = :project_item_id and + party_id = :party_id + } + + # Flush the cache that remembers which roles to offer the current user in the 'assign role to myself' listbox + if {[ad_conn user_id == $party_id]} { + util_memoize_flush [list pm::role::project_select_list_filter_not_cached -project_item_id $project_item_id -party_id $party_id] + } + + return +} + + +ad_proc -public pm::project::assign_remove_everyone { + {-project_item_id:required} +} { + Removes all users from a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param project_item_id + + @return party_ids of all users removed from the project + + @error +} { + + set current_assignees [db_list get_assignees { + SELECT + party_id + FROM + pm_project_assignment + WHERE + project_id = :project_item_id + }] + + db_dml remove_assignment { + DELETE FROM + pm_project_assignment + WHERE + project_id = :project_item_id + } + + # Flush the cache that remembers which roles to offer the current user in the 'assign role to myself' listbox + util_memoize_flush [list pm::role::project_select_list_filter_not_cached -project_item_id $project_item_id -party_id [ad_conn user_id]] + return $current_assignees +} + + +ad_proc -public pm::project::assignee_filter_select { + {-status_id:required} +} { + Returns a list of lists, people who are assigned to projects with a + status of status_id. Used in the list-builder filters for + the projects list page. Cached 5 minutes. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param status_id + + @return + + @error +} { + return [util_memoize [list pm::project::assignee_filter_select_helper -status_id $status_id] 600] +} + + +ad_proc -private pm::project::assignee_filter_select_helper { + {-status_id:required} +} { + Returns a list of lists, people who are assigned projects with a + status of status_id. Used in the list-builder filters for + the projects list page. Cached 5 minutes. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param status_id + + @return + + @error +} { + return [db_list_of_lists get_people { +SELECT + distinct(first_names || ' ' || last_name) as fullname, + u.person_id + FROM + persons u, + pm_project_assignment a, + pm_projects p, + cr_items i + WHERE + u.person_id = a.party_id and + i.item_id = a.project_id and + p.status_id = :status_id and + i.live_revision = p.project_id + ORDER BY + fullname + }] +} + + +ad_proc -public pm::project::assignee_email_list { + -project_item_id:required +} { + Returns a list of assignee email addresses + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-30 + + @param project_item_id + + @return + + @error +} { + + return [db_list get_addresses { + SELECT + p.email + FROM + parties p, + pm_project_assignment a + WHERE + a.project_id = :project_item_id and + a.party_id = p.party_id + }] + +} + + +ad_proc -public pm::project::assigned_p { + -project_item_id:required + -party_id:required +} { + Returns 1 if user has been assigned to a project + + @author Richard Hamilton (ricky.hamilton@btopenworld.com) + @creation-date 2004-12-17 + + @param project_item_id + + @param party_id + + @return + + @error +} { + + return [db_0or1row assigned_p { + SELECT + party_id + FROM + pm_project_assignment + WHERE + project_id = :project_item_id and + party_id = :party_id + LIMIT 1 + }] + +} + + +ad_proc -public pm::project::name { + -project_item_id:required +} { + Returns the name for a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-07-01 + + @param project_item_id + + @return + + @error +} { + return [db_string get_name { + SELECT + title + FROM + cr_revisions p, + cr_items i + WHERE + i.live_revision = p.revision_id + and i.item_id = :project_item_id + } -default ""] +} + + +ad_proc -public pm::project::url { + -project_item_id:required +} { + Returns the URL for a project, when given the project_item_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-07-01 + + @param project_item_id + + @return + + @error +} { + + return "[ad_url][ad_conn package_url]one?project_item_id=$project_item_id" + +} + + +ad_proc -public pm::project::one_default_orderby { + {-set ""} +} { + Returns the default order by (set by ad_set_client_property) + + @author (jader@bread.com) + @creation-date 2004-11-04 + + @param if set is set, then set the default_orderby + + @return + + @error +} { + if {[empty_string_p $set]} { + + set default_orderby "latest_start,asc" + + set return_val [ad_get_client_property \ + -default $default_orderby \ + -- \ + project-manager \ + project-one-orderby] + + return $return_val + + } else { + + ad_set_client_property -- project-manager project-one-orderby $set + return $set + + } +} + + +ad_proc -public pm::project::index_default_orderby { + {-set ""} +} { + Returns the default order by (set by ad_set_client_property) + + @author (jader@bread.com) + @creation-date 2004-11-04 + + @param if set is set, then set the default_orderby + + @return + + @error +} { + if {[empty_string_p $set]} { + + set default_orderby "project_name,asc" + + set return_val [ad_get_client_property \ + -default $default_orderby \ + -- \ + project-manager \ + project-index-orderby] + + return $return_val + + } else { + + ad_set_client_property -- project-manager project-index-orderby $set + return $set + + } +} + Index: openacs-4/packages/project-manager/tcl/role-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/role-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/role-procs-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,23 @@ + + + + oracle8.0 + + + + SELECT role_id + FROM pm_roles + WHERE rownum = 1 + + + + + + + SELECT one_line || ' (' || substr(one_line,1,1) || ')' as one_line, + role_id + FROM pm_roles + ORDER BY role_id + + + Index: openacs-4/packages/project-manager/tcl/role-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/role-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/role-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,310 @@ +# + +ad_library { + + Procs for roles + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-05 + @arch-tag: 226cb104-9e32-4de3-9f93-ab96e239ca93 + @cvs-id $Id: role-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + + +namespace eval pm::role {} + +ad_proc -public pm::role::default { +} { + Gets the default role. This is pretty much random, but the first + role selected + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-05 + + @return role_id + + @error -1 if there is an error. +} { + set returnval [db_string get_default "select role_id from pm_roles limit 1" -default "-1"] + return $returnval +} + + +ad_proc -public pm::role::select_list_filter {} { + Returns a select list. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + return [util_memoize [list pm::role::select_list_filter_not_cached] 300] +} + + +ad_proc -private pm::role::select_list_filter_not_cached {} { + Returns a select list. Used so pm::role::select_list can be cached. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + return [db_list_of_lists get_roles " + SELECT + one_line || ' (' || substring(one_line from 1 for 1) || ')' as one_line, + role_id + FROM + pm_roles + ORDER BY + role_id"] +} + + +ad_proc -public pm::role::select_list { + {-select_name:required} +} { + Returns a select list, suitable for use in an HTML form. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + set select_list "" + + return $select_list +} + + +ad_proc -public pm::role::project_select_list_filter { + -project_item_id:required + -party_id:required +} { + Returns a select list. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param project_item_id + + @param party_id + + @return + + @error +} { + return [util_memoize [list pm::role::project_select_list_filter_not_cached -project_item_id $project_item_id -party_id $party_id] 300] +} + + +ad_proc -private pm::role::project_select_list_filter_not_cached { + -project_item_id:required + -party_id:required +} { + Returns a select list. Used so pm::role::project_select_list can be cached. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param project_item_id + + @param party_id + + @return + + @error +} { + return [db_list_of_lists get_roles " + SELECT + one_line || ' (' || substring(one_line from 1 for 1) || ')' as one_line, + role_id + FROM + pm_roles as r + WHERE NOT EXISTS + (SELECT 1 + FROM + pm_project_assignment as pa + WHERE + r.role_id = pa.role_id and + pa.project_id = :project_item_id and + pa.party_id = :party_id) + ORDER BY + role_id"] +} + + +ad_proc -public pm::role::project_select_list { + {-select_name:required} + {-project_item_id:required} + {-party_id:required} +} { + Returns a select list, suitable for use in an HTML form. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + set select_list "" + + return $select_list +} + + +ad_proc -public pm::role::task_select_list_filter { + -task_item_id:required + -party_id:required +} { + Returns a select list. + + @author Richard Hamilton (ricky.hamilton@btopenworld.com) + @creation-date 2004-12-18 + + @param task_item_id + + @param party_id + + @return + + @error +} { + return [util_memoize [list pm::role::task_select_list_filter_not_cached -task_item_id $task_item_id -party_id $party_id] 300] +} + + +ad_proc -private pm::role::task_select_list_filter_not_cached { + -task_item_id:required + -party_id:required +} { + Returns a select list. Used so pm::role::task_select_list can be cached. + + @author Richard Hamilton (ricky.hamilton@btopenworld.com) + @creation-date 2004-12-18 + + @param task_item_id + + @param party_id + + @return + + @error +} { + return [db_list_of_lists get_roles " + SELECT + one_line || ' (' || substring(one_line from 1 for 1) || ')' as one_line, + role_id + FROM + pm_roles as r + WHERE NOT EXISTS + (SELECT 1 + FROM + pm_task_assignment as ta + WHERE + r.role_id = ta.role_id and + ta.task_id = :task_item_id and + ta.party_id = :party_id) + ORDER BY + role_id"] +} + + +ad_proc -public pm::role::task_select_list { + {-select_name:required} + {-task_item_id:required} + {-party_id:required} +} { + Returns a select list, suitable for use in an HTML form. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + set select_list "" + + return $select_list +} + + +ad_proc -public pm::role::name { + -role_id:required +} { + Returns the one_line for the role from the role_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-08 + + @param role_id + + @return one_line + + @error +} { + return [util_memoize [list pm::role::name_not_cached -role_id $role_id]] +} + + +ad_proc -public pm::role::name_not_cached { + -role_id:required +} { + Returns the one_line for the role from the role_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-08 + + @param role_id + + @return one_line + + @error +} { + return [db_string get_one_line { + SELECT + one_line + FROM + pm_roles + WHERE + role_id = :role_id + } -default "error"] +} Index: openacs-4/packages/project-manager/tcl/status-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/status-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/status-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,124 @@ +# + +ad_library { + + Procs for project manager status codes and so on. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-21 + @arch-tag: 23a501b5-de19-4d4a-ad9f-57dfa5c8bbd3 + @cvs-id $Id: status-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + +namespace eval pm::status {} + +ad_proc -public pm::status::open_p { + -task_status_id:required +} { + Returns t if the task status code is open, f otherwise + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-21 + + @param task_status_id + + @return + + @error +} { + + set return_val [db_string get_open_p { + SELECT + case when status_type = 'c' then 'f' else 't' end + FROM + pm_task_status + WHERE + status_id = :task_status_id + }] + + return $return_val +} + + +ad_proc -public pm::status::default_closed { } { + Returns a default project_status id that is closed + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-07-02 + + @param task_status_id + + @return + + @error +} { + + set return_val [db_string get_closed_status { + SELECT + status_id + FROM + pm_project_status + WHERE + status_type = 'c' + LIMIT 1 + }] + + return $return_val +} + + +ad_proc -public pm::status::default_open { } { + Returns a default project_status id that is open + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-17 + + @param status_id + + @return + + @error +} { + + set return_val [db_string get_open_status { + SELECT + status_id + FROM + pm_project_status + WHERE + status_type = 'o' + LIMIT 1 + }] + + return $return_val +} + + +ad_proc -public pm::status::project_status_select { +} { + Returns a list of project status codes, suitable for list-builder filters + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + return [util_memoize [list pm::status::project_status_select_helper] 300] +} + + +ad_proc -private pm::status::project_status_select_helper { +} { + Returns a list of project status codes, suitable for list-builder filters + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @return + + @error +} { + return [db_list_of_lists get_status "select description, status_id from pm_project_status order by status_type desc, description"] +} Index: openacs-4/packages/project-manager/tcl/task-procs-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/task-procs-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/task-procs-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,126 @@ + + + + oracle8.0 + + + + SELECT i.item_id + FROM cr_items i, + cr_revisions r + WHERE i.item_id = r.item_id and + r.revision_id = :task_id + + + + + + SELECT live_revision + FROM cr_items i + WHERE i.item_id = :task_item_id + + + + + + select status + from pm_tasks + where task_id = :task_item_id + + + + + + SELECT case when status_type = 'c' + then 0 + else 1 end as open_p + FROM pm_tasks t, + pm_task_status s + WHERE task_id = :task_item_id and + t.status = s.status_id + + + + + + select status_id + from pm_task_status + where status_type = 'o' and + rownum = 1 + + + + + + select status_id + from pm_task_status + where status_type = 'c' and + rownum = 1 + + + + + + SELECT r.item_id, + r.title as task_title + FROM pm_tasks_revisionsx r, + cr_items i, + pm_tasks t, + pm_task_status s + WHERE r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id and + t.status = s.status_id and + s.status_type = 'o' + $union_clause + ORDER BY task_title + + + + + + begin + :1 := pm_task.new_task_revision ( + p_task_id => :task_item_id, + p_project_id => :project_item_id, + p_title => :title, + p_description => :description, + p_mime_type => :mime_type, + p_end_date => [pm::util::datenvl -value $end_date -value_if_null "null" -value_if_not_null "to_timestamp('$end_date','YYYY MM DD HH24 MI SS')"], + p_percent_complete => :percent_complete, + p_estimated_hours_work => :estimated_hours_work, + p_estimated_hours_work_min => :estimated_hours_work_min, + p_estimated_hours_work_max => :estimated_hours_work_max, + p_actual_hours_worked => :actual_hours_worked, + p_status_id => :status_id, + p_creation_date => sysdate , + p_creation_user => :update_user, + p_creation_ip => :update_ip, + p_package_id => :package_id); + end; + + + + + + begin + :1 := pm_task.new_task_item ( + p_project_id => :project_id, + p_title => :title, + p_description => :description, + p_mime_type => :mime_type, + p_end_date => [pm::util::datenvl -value $end_date -value_if_null "null" -value_if_not_null "to_timestamp('$end_date','YYYY MM DD HH24 MI SS')"], + p_percent_complete => :percent_complete, + p_estimated_hours_work => :estimated_hours_work, + p_estimated_hours_work_min => :estimated_hours_work_min, + p_estimated_hours_work_max => :estimated_hours_work_max, + p_status_id => :status_id, + p_creation_date => :creation_date, + p_creation_user => :creation_user, + p_creation_ip => :creation_ip, + p_package_id => :package_id); + end; + + + + Index: openacs-4/packages/project-manager/tcl/task-procs-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/task-procs-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/task-procs-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,385 @@ + + + + postgresql7.3 + + + + SELECT + r.title + FROM + cr_items i, + cr_revisions r + WHERE + i.item_id = r.item_id and + i.item_id = :task_item_id and + i.live_revision = r.revision_id + + + + + + SELECT + i.item_id + FROM + cr_items i, + cr_revisions r + WHERE + i.item_id = r.item_id and + r.revision_id = :task_id + + + + + + SELECT + live_revision + FROM + cr_items i + WHERE + i.item_id = :task_item_id + + + + + + select status + from pm_tasks + where task_id = :task_item_id + + + + + + SELECT + case when status_type = 'c' then 0 else 1 end as open_p + FROM + pm_tasks t, + pm_task_status s + WHERE + task_id = :task_item_id and + t.status = s.status_id + + + + + + select status_id + from pm_task_status + where status_type = 'o' + limit 1 + + + + + + select status_id + from pm_task_status + where status_type = 'c' + limit 1 + + + + + + DELETE FROM + pm_task_dependency + WHERE + task_id = :task_item_id + + + + + + SELECT + task.item_id as t_item_id + FROM + cr_items task, + cr_items project + WHERE + task.parent_id = project.item_id and + project.item_id = :project_item_id + + + + + + SElECT + d.task_id as dep_task, + d.parent_task_id as dep_task_parent + FROM + pm_task_dependency d + WHERE + d.task_id in ([join $project_tasks ", "]) + + + + + + INSERT INTO + pm_task_dependency + (dependency_id, + task_id, + parent_task_id, + dependency_type) + values + (:dependency_id, + :task_item_id, + :parent_id, + 'finish_before_start') + + + + + + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks t, + pm_task_status s + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id and + t.status = s.status_id and + s.status_type = 'o' + $union_clause + ORDER BY + task_title + + + + + + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks t, + pm_task_status s + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id and + t.status = s.status_id and + s.status_type = 'o' + $union_clause + ORDER BY + task_title + + + + + + select pm_task__new_task_revision ( + :task_item_id, + :project_item_id, + :title, + :description, + :mime_type, + [pm::util::datenvl -value $end_date -value_if_null "null" -value_if_not_null ":end_date"], + :percent_complete, + :estimated_hours_work, + :estimated_hours_work_min, + :estimated_hours_work_max, + :actual_hours_worked, + :status_id, + current_timestamp, + :update_user, + :update_ip, + :package_id, + :priority) + + + + + + UPDATE + logger_entries + SET + project_id = :logger_project + WHERE + entry_id in + (select + logger_entry + from + pm_task_logger_proj_map + where + task_item_id = :task_item_id) + + + + + + select pm_task__new_task_item ( + :project_id, + :title, + :description, + :mime_type, + [pm::util::datenvl -value $end_date -value_if_null "null" -value_if_not_null "to_timestamp('$end_date','YYYY MM DD HH24 MI SS')"], + :percent_complete, + :estimated_hours_work, + :estimated_hours_work_min, + :estimated_hours_work_max, + :status_id, + :process_instance_id, + coalesce (:creation_date,current_timestamp), + :creation_user, + :creation_ip, + :package_id, + :priority) + + + + + + + SELECT + p.email as from_address, + p2.first_names || ' ' || p2.last_name as mod_username + FROM + parties p, + persons p2 + WHERE + p.party_id = :user_id and + p.party_id = p2.person_id + + + + + + SELECT + t.title as subject, + t.description, + t.mime_type as description_mime_type, + to_char(t.earliest_start,'MM-DD-YYYY') as earliest_start, + to_char(t.earliest_finish,'MM-DD-YYYY') as earliest_finish, + to_char(t.latest_start,'MM-DD-YYYY') as latest_start, + to_char(t.latest_finish,'MM-DD-YYYY') as latest_finish, + t.estimated_hours_work as work, + t.estimated_hours_work_min as work_min, + t.estimated_hours_work_max as work_max, + t.percent_complete, + p.title as project_name, + t.parent_id as project_item_id, + a.process_instance + FROM + pm_tasks_revisionsx t, + pm_tasks_active a, + cr_items i, + cr_items project, + pm_projectsx p + WHERE + t.item_id = :task_item_id and + t.item_id = a.task_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id and + t.parent_id = project.item_id and + project.item_id = p.item_id and + project.live_revision = p.revision_id + + + + + + SELECT + p.email as to_address, + r.one_line as role, + r.is_lead_p + FROM + pm_task_assignment a, + parties p, + pm_roles r + WHERE + task_id = :task_item_id and + a.party_id = p.party_id and + a.role_id = r.role_id + + + + + + + SELECT + t.title as one_line, + t.description, + t.mime_type as description_mime_type, + t.estimated_hours_work as estimated_hours_work, + t.estimated_hours_work_min as estimated_hours_work_min, + t.estimated_hours_work_max as estimated_hours_work_max, + t.percent_complete, + to_char(t.end_date, 'DD') as end_date_day, + to_char(t.end_date, 'MM') as end_date_month, + to_char(t.end_date, 'YYYY') as end_date_year, + d.parent_task_id, + i.item_id as tid, + t.parent_id as project, + t.priority + FROM + pm_tasks_revisionsx t, + cr_items i + LEFT JOIN + pm_task_dependency d + ON i.item_id = d.task_id + WHERE + t.revision_id = i.live_revision and + t.item_id = i.item_id + $task_where_clause + + + + + + + SELECT + party_id, + role_id + FROM + pm_task_assignment + WHERE + task_id = :task_item_id + + + + + + + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :task_item_id + + + + + + UPDATE + pm_tasks + SET + status = :status_code + WHERE + task_id = :task_item_id + + + + + + SELECT + p.first_names || ' ' || p.last_name + FROM + pm_task_assignment a, + persons p + WHERE + task_id = :task_item_id and + a.party_id = p.person_id + + + + Index: openacs-4/packages/project-manager/tcl/task-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/task-procs.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/task-procs.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,2647 @@ +ad_library { + + Project Manager Projects Library + + Procedures that deal with tasks + + @creation-date 2003-12-18 + @author Jade Rubick + @cvs-id $Id: task-procs.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + +} + +namespace eval pm::task {} + + +ad_proc -public pm::task::name { + {-task_item_id:required} +} { + Returns the name of the task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-25 + + @param task_item_id + + @return + + @error -1 +} { + return [db_string get_name { } -default "-1"] +} + + +ad_proc -public pm::task::options_list { + {-edit_p "f"} + -project_item_id + {-task_item_id ""} + {-dependency_task_ids ""} + {-number "0"} + {-current_number "0"} +} { + Returns a list of lists suitable for use in a select list for + ad_form. Contains a list of possible tasks that this task can + depend upon, or selected. These tasks are limited to just the + one project. + +

    + + There is one special case that we handle: if you are creating new + tasks (not editing), you can have them depend on each other. + So if you create two tasks at the same time, you may want task + 2 to depend on task 1. Instead of a task_item_id, we then + specify a value of this form: + +

    + numX +
    + + where X represents the number of the new task, ranging from 1 + to n. + +

    + + To be more efficient when creating multiple tasks at the same + time, we should cache the database calls. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-13 + + @param edit_p Is this for a task being edited? Or a new task? + + @param project_item_id The project we're finding tasks from + + @param task_item_id The task ID. This is used because we do not + want a task to depend on itself, so it is excluded from the list. + + @param dependency_task_ids For edited tasks, the current task_ids + that it depends on. Used because sometimes it can be closed, and + it wouldn't otherwise appear on the list. This is a list. + + @param number When the list is returned, it includes entries for + number new tasks, in the numX format described in these docs. + + @param current_number The current number. Used for new tasks. It + prevents allowing dependencies on the task being created. + + @return + + @error +} { + + # get tasks this task can depend on + + if {[exists_and_not_null dependency_task_ids]} { + + set union_clause " + UNION + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks_active t + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id + and t.task_id in ([join $dependency_task_ids ","])" + } else { + set union_clause "" + } + + set keys [list] + + db_foreach get_dependency_tasks { } { + set options($task_title) $item_id + lappend keys $task_title + } + + set keys [lsort $keys] + + + set dependency_options_full "{\"--None--\" \"\"} " + + if {[string is true $edit_p]} { + # Do nothing + } else { + + # now set up dependency options + + for {set j 1} {$j <= $number} {incr j} { + if {![string equal $current_number $j]} { + append dependency_options_full "{\"New Task \#$j\" \"num$j\"} " + } + } + } + + # for editing tasks, we skip ourselves (because depending on + # ourselves just sometimes isn't an option) + + if {[string is true $edit_p]} { + foreach key $keys { + + # make sure we're not dependent on ourselves + + if {![string equal $task_item_id $options($key)]} { + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an error. + append dependency_options_full "{{$key} $options($key)} " + } + } + } else { + foreach key $keys { + + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an error. + append dependency_options_full "{{$key} $options($key)} " + } + } + + + return $dependency_options_full +} + + +ad_proc -public pm::task::options_list_html { + {-edit_p "f"} + -project_item_id + {-task_item_id ""} + {-dependency_task_id ""} + {-dependency_task_ids ""} + {-number "0"} + {-depends_on_new ""} + {-current_number "0"} +} { + Returns a list of options suiteable for HTML. + Contains a list of possible tasks that this task can + depend upon, or selected. These tasks are limited to just the + one project. + +

    + + There is one special case that we handle: if you are creating new + tasks (not editing), you can have them depend on each other. + So if you create two tasks at the same time, you may want task + 2 to depend on task 1. Instead of a task_item_id, we then + specify a value of this form: + +

    + numX +
    + + where X represents the number of the new task, ranging from 1 + to n. + +

    + + To be more efficient when creating multiple tasks at the same + time, we should cache the database calls. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-13 + + @param edit_p Is this for a task being edited? Or a new task? + + @param project_item_id The project we're finding tasks from + + @param task_item_id The task ID. This is used because we do not + want a task to depend on itself, so it is excluded from the list. + + @param dependency_task_ids For edited tasks, the current task_ids + that it depends on. Used because sometimes it can be closed, and + it wouldn't otherwise appear on the list. This is a list. + + @param dependency_task_id For edited tasks, the current task that + it depends on, used for setting the default option in HTML. + + @param number When the list is returned, it includes entries for + number new tasks, in the numX format described in these docs. + + @param depends_on_new When you're using a process, you want the + dependency to be on other new tasks. The format for this should + be num1 num2, etc.. So we make the default if this parameter is set. + + @param current_number The current number. Used for new tasks. It + prevents allowing dependencies on the task being created. + + @return + + @error +} { + + # get tasks this task can depend on + + if {[exists_and_not_null dependency_task_ids]} { + + set union_clause " + UNION + SELECT + r.item_id, + r.title as task_title + FROM + pm_tasks_revisionsx r, + cr_items i, + pm_tasks_active t + WHERE + r.parent_id = :project_item_id and + r.revision_id = i.live_revision and + i.item_id = t.task_id + and t.task_id in ([join $dependency_task_ids ","])" + } else { + set union_clause "" + } + + set keys [list] + + db_foreach get_dependency_tasks { } { + set options($task_title) $item_id + lappend keys $task_title + } + + set keys [lsort $keys] + + # --------------------------------------------------------------- + # Start setting up the output. + # These are for new tasks, the already created tasks are added to + # the list later. + # --------------------------------------------------------------- + + set dependency_options_full " " + + if {[string is false $edit_p]} { + + # now set up dependency options + + for {set j 1} {$j <= $number} {incr j} { + + if {[string equal $depends_on_new $j]} { + set selected "selected=\"selected\" " + } else { + set selected "" + } + + if {![string equal $current_number $j]} { + append dependency_options_full " " + } + } + } + + # ------------------------------------------------- + # Now add the tasks that are already in the project + # ------------------------------------------------- + + + if {[string is true $edit_p]} { + foreach key $keys { + + # for editing tasks, we skip ourselves (because depending on + # ourselves just sometimes isn't an option) + if {![string equal $task_item_id $options($key)]} { + + if {[string equal $options($key) $dependency_task_id]} { + set selected "selected=\"selected\" " + } else { + set selected "" + } + + # check for case when there is a quote in the name of + # a task. We have to filter this out, or we get an + # error. -- not sure what this comment is for -- JR + + + append dependency_options_full " " + } + } + } else { + + foreach key $keys { + + # check for case when there is a quote in the name of a + # task. We have to filter this out, or we get an error. -- + # not sure what this comment is for -- JR + + append dependency_options_full " " + } + } + + + return $dependency_options_full +} + + +ad_proc -public pm::task::dependency_delete_all { + -task_item_id:required + +} { + Deletes all the dependencies of a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-23 + + @param task_item_id The task we wish to remove the dependencies from. + + @return + + @error +} { + db_dml delete_deps { } + + return 1 +} + + +ad_proc -public pm::task::dependency_add { + -task_item_id:required + -parent_id:required + -dependency_type:required + -project_item_id:required +} { + + Adds a dependency to a task, checking for loops in the process + +

    + + We make the assumption that the following is true: + +

      +
    • no loop is created if you depend on a task already present
    • +
    • therefore, if you add a task without creating a loop in the + newly created tasks, you are safe.
    • +
    + + We check that the new items don't depend on each other by + following them if they loop more than the number of tasks in the + project, then we have a loop + +

    + The way we check for a loop is to follow the dependencies + until we get to a task that has already been created. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-23 + + @param task_item_id The task that is trying to create a + dependency. Of course this means that the task has already been + created. + + @param parent_id The task that we would like to create a + dependency on. (item_id for task, of course) + + @param dependency_type Type of dependency, from pm_dependency_types + + @param project_item_id The project's item_id. All dependencies are + created within this project + + @return + + @error +} { + + set project_tasks [db_list get_tasks { }] + + # we do not allow tasks to depend on items outside of their + # project. So if it's not in the list of tasks for that project, + # we reject it + + if {[lsearch $project_tasks $parent_id] < 0} { + set loop_limit 0 + set valid_p FALSE + } else { + set loop_limit [llength $project_tasks] + } + + if {$loop_limit > 0} { + + set dep_list [list] + db_foreach get_dependencies { } { + lappend dep_list d-$dep_task-$dep_task_parent + } + + # are there any loops? + lappend dep_list d-$task_item_id-$parent_id + + foreach ti $project_tasks { + set task_state($ti) 0 + } + nsv_array set task_node_status [array get task_state] + + + set valid_p [pm::task::verify_no_loops \ + -current_task $task_item_id \ + -dependency_list $dep_list] + + } + + if {[string is true $valid_p]} { + # after it passes + set dependency_id [db_nextval pm_task_dependency_seq] + + db_dml insert_dep { } + + } else { + ns_log Notice "Task dependency for $task_item_id on $parent_id was not added due to looping or being outside of the current project" + } + +} + + +ad_proc -private pm::task::verify_no_loops { + {-current_task:required} + {-dependency_list:required} +} { + Based on the dag_dfs algorithm at http://wiki.tcl.tk/3716 + +

    + + Determines if adding in the additional dependency would create + an cyclical graph or not + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-25 + + @param project_task_list + + @param current_task + + @param dependency_list a list of dependencies, each of the form + d-n1-n2 where n1 is the child and n2 is the parent. The initial + call to this function should include the proposed addition in + this list. + + @return TRUE if no loops, FALSE if the proposed additon would add loops + + @error +} { + + set return_val "" + + array set task_state [nsv_array get task_node_status] + + set task_state($current_task) 1 + + nsv_array set task_node_status [array get task_state] + + foreach arc $dependency_list { + regexp {d-(.*)-(.*)} $arc match child parent + + # only walk to dependencies from the current task + if {[string equal $child $current_task]} { + + set tNode $parent + + array set task_state [nsv_array get task_node_status] + + # this should only happen if dependencies span projects + # they shouldn't, but I check anyway. + if {![info exists task_state($tNode)]} { + set used 0 + } else { + set used $task_state($tNode) + } + + if {[string equal $used 1]} { + return FALSE + } + + set return_val [pm::task::verify_no_loops \ + -current_task $parent \ + -dependency_list $dependency_list + ] + + if {[string equal $return_val FALSE]} { + return FALSE + } + } + + } + + array set task_state [nsv_array get task_node_status] + + set task_state($current_task) 2 + + nsv_array set task_node_status [array get task_state] + + return TRUE +} + + + +ad_proc -public pm::task::get_item_id { + -task_id:required +} { + Returns the task_item_id (item_id) when given the task_id (revision_id) + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-19 + + @param task_id The revision item + + @return task_item_id + + @error Returns -1 if there is no such task +} { + set return_val [db_string get_item_id { } -default "-1"] + + return $return_val +} + + + +ad_proc -public pm::task::get_revision_id { + -task_item_id:required +} { + Returns task_id (revision_id) when given the task_item_id (item_id) + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-19 + + @param task_item_id The revision item + + @return task_item_id + + @error If there is no such task item, then returns -1 +} { + set return_val [db_string get_revision_id { } -default "-1"] + + return $return_val +} + + + +ad_proc -public pm::task::current_status { + -task_item_id:required +} { + Returns the current status value for open tasks +} { + set return_val [db_string get_current_status { }] + + return $return_val +} + + +ad_proc -public pm::task::open_p { + -task_item_id:required +} { + Returns 1 if the task is open, 0 otherwise +} { + set return_val [db_string open_p { }] + + return $return_val +} + + +ad_proc -public pm::task::default_status_open {} { + Returns the default status value for open tasks +} { + set return_val [db_string get_default_status_open { }] + + return $return_val +} + + +ad_proc -public pm::task::default_status_closed {} { + Returns the default status value for closed tasks +} { + set return_val [db_string get_default_status_closed { }] + + return $return_val +} + + + +ad_proc -public pm::task::edit { + -task_item_id:required + -project_item_id:required + -title:required + -description:required + {-mime_type "text/plain"} + {-comment ""} + {-comment_type "text/plain"} + -end_date:required + -percent_complete:required + -estimated_hours_work:required + -estimated_hours_work_min:required + -estimated_hours_work_max:required + -update_user:required + -update_ip:required + -package_id:required + {-priority "0"} +} { + + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-23 + + @param task_item_id + + @param project_item_id + + @param title + + @param description + + @param comment The comment to send out by email if the task + is closed. Otherwise, it is NOT sent out. + + @param mime_type + + @param end_date + + @param percent_complete + + @param estimated_hours_work + + @param estimated_hours_work_min + + @param estimated_hours_work_max + + @param update_user The user updating the task + + @param update_ip The IP address of the request + + @param package_id + + @return new revision_id for the task + + @error +} { + # simple sanity check for min and max estimated hours + if {$estimated_hours_work_min > $estimated_hours_work_max} { + set temp $estimated_hours_work_max + set estimated_hours_work_max $estimated_hours_work_min + set estimated_hours_work_min $temp + } + + if {$percent_complete >= 100} { + + set status_id [pm::task::default_status_closed] + + } elseif {$percent_complete < 100} { + + set status_id [pm::task::default_status_open] + } + + set actual_hours_worked [pm::task::update_hours \ + -task_item_id $task_item_id] + + set return_val [db_exec_plsql new_task_revision { *SQL }] + + # we have to update all logged hours to make sure the hours are + # set to the correct project whenever the project is changed. + + set logger_project [pm::project::get_logger_project -project_item_id $project_item_id] + + db_dml update_logger_entries { } + + return $return_val +} + + + +ad_proc -public pm::task::new { + -project_id:required + {-title "Subject missing"} + {-description ""} + {-mime_type "text/plain"} + {-end_date ""} + {-percent_complete "0"} + {-estimated_hours_work "0"} + {-estimated_hours_work_min "0"} + {-estimated_hours_work_max "0"} + {-creation_date ""} + {-status_id ""} + {-process_instance_id ""} + -creation_user:required + -creation_ip:required + -package_id:required + {-priority "0"} +} { + Creates a new task. + + @param process_instance_id If a process was used to create the + task, then it is linked in to that process instance, so we can + things like display only tasks that are a part of a process. + + @author Jade Rubick (jader@bread.com) + @creation-date who knows? + + @return new task_item_id + + @error + +} { + if {![exists_and_not_null status_id]} { + set status_id [pm::task::default_status_open] + } + + if {$estimated_hours_work_min > $estimated_hours_work_max} { + set temp $estimated_hours_work_max + set estimated_hours_work_max $estimated_hours_work_min + set estimated_hours_work_min $temp + } + + set task_revision [db_exec_plsql new_task_item { *SQL }] + set task_item_id [pm::task::get_item_id \ + -task_id $task_revision] + + if {$percent_complete >= 100} { + pm::task::close -task_item_id $task_item_id + } + + return $task_item_id +} + + + +ad_proc -public pm::task::delete { + -task_item_id:required +} { + Marks a task deleted + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-10 + + @param task_item_id + + @return 1, no matter once + + @error No error thrown if there is no such task. +} { + db_dml mark_delete "update pm_tasks set deleted_p = 't' where task_id = :task_item_id" + + pm::project::compute_status [pm::task::project_item_id -task_item_id $task_item_id] + + return 1 +} + + +ad_proc -public pm::task::project_item_id { + -task_item_id:required +} { + Returns the project item id for a given task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-07-16 + + @param task_item_id + + @return -1 if there is an error. + + @error +} { + return [db_string get_project_id "select parent_id from cr_items where item_id = :task_item_id" -default -1] +} + + + +ad_proc -public pm::task::get_url { + object_id +} { + set url [pm::util::url] + + set package_url "${url}task-one?task_id=$object_id" + + return $package_url + +} + + + +ad_proc -public pm::task::process_reply { + reply_id +} { + # return successful_p = "f" + return "f" +} + + + +ad_proc -public pm::task::slack_time { + -earliest_start_j:required + -today_j:required + -latest_start_j:required +} { + Return the amount of slack time + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-02-20 + + @param earliest_start_j Earliest start date, Julian + + @param today_j today's date, in Julian + + @param latest_start_j Latest start date, in Julian + + @return Slack days + + @error +} { + if { \ + [exists_and_not_null earliest_start_j] && \ + [exists_and_not_null latest_start_j]} { + + if {$earliest_start_j < $today_j} { + set slack_time "[expr $latest_start_j - $today_j] days" + } else { + set slack_time "[expr $latest_start_j - $earliest_start_j] days" + } + + } else { + set slack_time "n/a" + } + +} + + + +ad_proc -private pm::task::update_hours { + {-task_item_id ""} + {-task_revision_id ""} + {-update_tasks_p "t"} +} { + The pm_tasks_revisions table contains a denormalized cache of the + total number of hours logged to it. Updates the cache from the + hours logged in logger and the pm_task_logger_proj_map table + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-04 + + @param task_item_id + + @param task_revision_id + + @param update_tasks_p If t, updates the current pm_tasks_revision + table in the database. + + @return total logged hours + + @error if neither task_item_id or task_revision_id is defined, + returns -1 +} { + if { \ + ![info exists task_item_id] && \ + ![info exists task_revision_id]} { + + ns_log Error "Illegal parameters in pm::task::update_hours" + return -1 + } + + if { \ + [exists_and_not_null task_item_id] && \ + ![exists_and_not_null task_revision_id]} { + + set task_revision_id [pm::task::get_revision_id \ + -task_item_id $task_item_id] + } + + if { \ + ![exists_and_not_null task_item_id] && \ + [exists_and_not_null task_revision_id]} { + + set task_item_id [pm::task::get_item_id \ + -task_id $task_revision_id] + } + + + set total_logged_hours [db_string total_hours " + select sum(le.value) from logger_entries le where entry_id in (select logger_entry from pm_task_logger_proj_map where task_item_id = :task_item_id) and le.variable_id = '[logger::variable::get_default_variable_id]' + " -default "0"] + + if {[string is true $update_tasks_p]} { + + db_dml update_current_task { + UPDATE + pm_tasks_revisions + SET + actual_hours_worked = :total_logged_hours + WHERE + task_revision_id = :task_revision_id + } + } + + return $total_logged_hours + +} + + +ad_proc -public pm::task::link { + -task_item_id_1:required + -task_item_id_2:required +} { + Links two tasks together + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-10 + + @param task_item_id_1 + + @param task_item_id_2 + + @return + + @error +} { + + if {[string equal $task_item_id_1 $task_item_id_2]} { + # do nothing + ns_log Notice "Project-manager: Cannot link a task to itself!" + } elseif {$task_item_id_1 < $task_item_id_2} { + db_dml link_tasks " + INSERT INTO + pm_task_xref + (task_id_1, task_id_2) + VALUES + (:task_item_id_1, :task_item_id_2)" + } else { + db_dml link_tasks " + INSERT INTO + pm_task_xref + (task_id_1, task_id_2) + VALUES + (:task_item_id_2, :task_item_id_1)" + } + +} + + +ad_proc -public pm::task::assign_remove_everyone { + -task_item_id:required +} { + Removes all assignments for a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-09 + + @param task_item_id + + @return + + @error +} { + + db_dml remove_assignment { } + + # Flush the cache that remembers which roles to offer the current user in the 'assign role to myself' listbox + util_memoize_flush [list pm::role::task_select_list_filter_not_cached -task_item_id $task_item_id -party_id [ad_conn user_id]] +} + + +ad_proc -public pm::task::unassign { + -task_item_id:required + -party_id:required +} { + Removes an assignment for a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-11-18 + + @param task_item_id + + @param party_id + + @return + + @error +} { + db_dml remove_assignment { } + + # Flush the cache that remembers which roles to offer the current user in the 'assign role to myself' listbox + if {[ad_conn user_id] == $party_id} { + util_memoize_flush [list pm::role::task_select_list_filter_not_cached -task_item_id $task_item_id -party_id $party_id] + } +} + + +ad_proc -public pm::task::assign { + -task_item_id:required + -party_id:required + {-role_id ""} +} { + Assigns party_id to task_item_id + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-05 + + @param task_item_id + + @param party_id + + @param role_id the role under which the person is assigned + + @return + + @error +} { + if {![exists_and_not_null role_id]} { + set role_id [pm::role::default] + } + + db_transaction { + # make sure we avoid case when that assignment has already + # been made. + db_dml delete_assignment { + delete from + pm_task_assignment + where + task_id = :task_item_id and + party_id = :party_id + } + + db_dml add_assignment { + insert into pm_task_assignment + (task_id, + role_id, + party_id) + values + (:task_item_id, + :role_id, + :party_id) + } + } + + # Flush the cache that remembers which roles to offer the current user in the 'assign role to myself' listbox + if {[ad_conn user_id] == $party_id} { + util_memoize_flush [list pm::role::task_select_list_filter_not_cached -task_item_id $task_item_id -party_id $party_id] + } +} + + +ad_proc -public pm::task::assigned_p { + -task_item_id:required + -party_id:required +} { + Returns 1 if assigned, 0 if not + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-11-18 + + @param task_item_id + + @param party_id + + @return + + @error +} { + return [db_string assigned_p { } -default 0] +} + + +ad_proc -public pm::task::open { + {-task_item_id:required} +} { + Opens a task. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-22 + + @param task_item_id + + @return + + @error +} { + set status_code [pm::task::default_status_open] + + db_dml update_status { } +} + +ad_proc -public pm::task::close { + {-task_item_id:required} +} { + Closes a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-22 + + @param task_item_id + + @return + + @error +} { + set status_code [pm::task::default_status_closed] + + db_dml update_status { } + +} + + + +ad_proc -public pm::task::email_status {} { + + set send_email_p [parameter::get_from_package_key -package_key "project-manager" -parameter SendDailyEmail -default "0"] + + if {[string is false $send_email_p]} { + ns_log Notice "Parameter SendDailyEmail for project manager says skip email today" + return + } + + # also don't send reminders on weekends. + + set today_j [db_string get_today "select to_char(current_timestamp,'J')"] + if {![pm::project::is_workday_p $today_j]} { + return + } + + set parties [list] + + # what if the person assigned is no longer a part of the subsite? + # right now, we still email them. + + db_foreach get_all_open_tasks { + SELECT + ts.task_id, + ts.task_id as item_id, + ts.task_number, + t.task_revision_id, + t.title, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(current_timestamp,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name as full_name, + p.party_id, + (select one_line from pm_roles r where ta.role_id = r.role_id) as role + FROM + pm_tasks_active ts, + pm_tasks_revisionsx t, + pm_task_assignment ta, + acs_users_all p, + cr_items i, + pm_task_status s + WHERE + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + ts.status = s.status_id and + s.status_type = 'o' and + t.item_id = ta.task_id and + ta.party_id = p.party_id + ORDER BY + t.latest_start asc + } { + set earliest_start_pretty [lc_time_fmt $earliest_start "%x"] + set earliest_finish_pretty [lc_time_fmt $earliest_finish "%x"] + set latest_start_pretty [lc_time_fmt $latest_start "%x"] + set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] + + if {[exists_and_not_null earliest_start_j]} { + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + + } + + if {[lsearch $parties $party_id] == -1} { + lappend parties $party_id + } + + lappend task_list($party_id) $task_id + set titles_arr($task_id) $title + set ls_arr($task_id) $latest_start_pretty + set lf_arr($task_id) $latest_finish_pretty + set slack_arr($task_id) $slack_time + set roles($task_id-$party_id) $role + + # how many tasks does this person have? + if {[info exists task_count($party_id)]} { + incr task_count($party_id) + } else { + set task_count($party_id) 1 + } + } + + # transitions are < this value + set OVERDUE_THRESHOLD 0 + set PRESSING_THRESHOLD 7 + set LONGTERM_THRESHOLD 90 + + foreach party $parties { + + set subject "Daily Task status report" + set address [db_string get_email "select email from parties where party_id = :party" -default "jade-errors@bread.com"] + + set overdue [list] + set pressing [list] + set longterm [list] + + foreach task $task_list($party) { + + set url [pm::task::get_url $task] + + if {$slack_arr($task) < $OVERDUE_THRESHOLD} { + set which_pile overdue + } elseif {$slack_arr($task) < $PRESSING_THRESHOLD} { + set which_pile pressing + } elseif {$slack_arr($task) < $LONGTERM_THRESHOLD} { + set which_pile longterm + } else { + set which_pile "" + } + + if {![empty_string_p $which_pile]} { + + lappend $which_pile " +\#$task$titles_arr($task)$roles($task-$party)$ls_arr($task)$lf_arr($task)$slack_arr($task)" + + } + + } + + set overdue_title "

    Overdue Tasks

    " + + set overdue_description "consult with people affected, and let them know deadlines are affected" + + set pressing_title "

    Pressing Tasks

    " + + set pressing_description "you need to start working on these soon to avoid affecting deadlines" + + set longterm_title "

    Long Term Tasks

    " + + set longterm_description "look over these to plan ahead" + + # okay, let's now set up the email body + + set description " +

    This is a daily reminder of tasks that are assigned to you +You currently have $task_count($party) tasks assigned to you

    + +$overdue_title + +
    + +$overdue_description + + + + + + + + + + +" + + foreach overdue_item $overdue { + append description $overdue_item + } + + append description " +
    Task \#SubjectRoleLatest startLatest finishSlack
    + +$pressing_title + +
    + +$pressing_description + + + + + + + + + + +" + + foreach pressing_item $pressing { + append description $pressing_item + } + + append description " +
    Task \#SubjectRoleLatest startLatest finishSlack
    + +$longterm_title + +$longterm_description + + + + + + + + + + +" + + foreach longterm_item $longterm { + append description $longterm_item + } + + append description "
    Task \#SubjectRoleLatest startLatest finishSlack
    " + + pm::util::email \ + -to_addr $address \ + -from_addr $address \ + -subject $subject \ + -body $description \ + -mime_type "text/html" + } + + # consider also sending out emails to people who have created + # tickets that are not assigned to anyone + +} + + + +ad_proc -private pm::task::email_status_init { +} { + Schedules the daily emailings + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-14 + + @return + + @error +} { + ns_log Notice "Scheduling daily email notifications for project manager to 5:00 am" + ad_schedule_proc -thread t -debug t -schedule_proc ns_schedule_daily "5 0" pm::task::email_status +} + + + +ad_proc -public pm::task::email_alert { + -task_item_id:required + {-edit_p "t"} + {-comment ""} + {-comment_mime_type "text/plain"} + {-extra_description ""} +} { + Sends out an email notification when changes have been made to a task + +

    + + If any of the following are missing, fills in from the database: + subject, work, work_min, work_max, project_name, earliest_start, + earliest_finish, latest_start, latest_finish + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-03 + + @param task_item_id + + @param edit_p Is this an edited task, or a new one? t for edited, + f otherwise. + + @param extra_description Additional email content to send. In text format. + + @return + + @error +} { + + set task_term \ + [parameter::get -parameter "Taskname" -default "Task"] + set task_term_lower \ + [parameter::get -parameter "taskname" -default "task"] + set use_uncertain_completion_times_p \ + [parameter::get -parameter "UseUncertainCompletionTimesP" -default "0"] + + set user_id [ad_conn user_id] + + db_1row get_from_address_and_more { } + + db_1row get_task_info { } + + if {[string is true $edit_p]} { + + # ---- + # EDIT + # ---- + + set subject_out "Edited $task_term \#$task_item_id: $subject" + set intro_text "$mod_username edited this $task_term_lower" + + + } else { + + # --- + # NEW + # --- + + set subject_out "New $task_term \#$task_item_id: $subject" + set intro_text "$mod_username assigned you to a new $task_term_lower" + + } + + + if {[empty_string_p $comment]} { + set comment_text "" + } else { + set comment_text "

    Comment:

    $comment

    " + } + + set url [pm::task::get_url $task_item_id] + + set description [ad_html_text_convert -from $description_mime_type -to "text/html" -- $description] + + set extra_description [ad_html_text_convert -from "text/plain" -to "text/html" -- $extra_description] + + set description_out "$description $extra_description" + + set assignees [db_list_of_lists get_assignees { }] + + if {[exists_and_not_null $process_instance]} { + + set process_url [pm::process::url \ + -process_instance_id $process_instance \ + -project_item_id $project_item_id] + + set process_description [pm::process::name \ + -process_instance_id $process_instance] + + set process_html " +

    Process

    + + + + +
    $process_description
    +" + } else { + set process_html "" + } + + foreach ass $assignees { + + set to_address [lindex $ass 0] + set role [lindex $ass 1] + set is_lead_p [lindex $ass 2] + + set notification_text "${intro_text}${comment_text} +

    Task overview

    + + + + + + + + + + + + + +
    Subject:$subject (\#$task_item_id)
    Project:$project_name
    Your role:$role
    + +$process_html +

    Description

    + + + + +
    $description_out
    + +

    Dates:

    + + + + + + + + + +
    Latest start:$latest_start
    Latest finish$latest_finish
    " + + pm::util::email \ + -to_addr $to_address \ + -from_addr $from_address \ + -subject $subject_out \ + -body $notification_text \ + -mime_type "text/html" + } +} + + +ad_proc -public pm::task::update_percent { + -task_item_id:required + -percent_complete:required +} { + Updates the task's percent complete. Called from logger to + update the percentage complete. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-24 + + @param task_item_id + + @param percent_complete + + @return + + @error +} { + + db_dml update_percent { + UPDATE + pm_tasks_revisions + SET + percent_complete = :percent_complete + WHERE + task_revision_id = (select + live_revision + from + cr_items + where + item_id = :task_item_id) + } + + if {$percent_complete >= 100} { + + pm::task::close -task_item_id $task_item_id + + } else { + + pm::task::open -task_item_id $task_item_id + + } + +} + + +ad_proc -public pm::task::hours_remaining { + -estimated_hours_work:required + -estimated_hours_work_min:required + -estimated_hours_work_max:required + -percent_complete:required +} { + Displays the estimated hours work remaining in a consistent format + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-02 + + @param hours_work + + @param hours_work_min + + @param hours_work_max + + @param percent_complete + + @return + + @error +} { + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + + if {[string equal $percent_complete 100]} { + return 0 + } + + if {[string equal $percent_complete 0]} { + return [pm::task::estimated_hours_work \ + -estimated_hours_work $estimated_hours_work \ + -estimated_hours_work_min $estimated_hours_work_min \ + -estimated_hours_work_max $estimated_hours_work_max] + } + + if {[string is true $use_uncertain_completion_times_p]} { + + set display_value1 [expr round($estimated_hours_work_min * [expr 100 - $percent_complete] / double(100))] + set display_value2 [expr round($estimated_hours_work_max * [expr 100 - $percent_complete] / double(100))] + + if {[string equal $display_value1 $display_value2]} { + set display_value "$display_value1" + } else { + set display_value "$display_value1 - $display_value2" + } + } else { + set display_value [expr round($estimated_hours_work * [expr 100 - $percent_complete] / double(100))] + } + + return $display_value +} + + +ad_proc -public pm::task::days_remaining { + -estimated_hours_work:required + -estimated_hours_work_min:required + -estimated_hours_work_max:required + -percent_complete:required +} { + Displays the estimated days work remaining in a consistent format + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-11-24 + + @param hours_work + + @param hours_work_min + + @param hours_work_max + + @param percent_complete + + @return + + @error +} { + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + set hours_day [pm::util::hours_day] + + if {[string equal $percent_complete 100]} { + return 0 + } + + if {[string equal $percent_complete 0]} { + return [pm::task::estimated_days_work \ + -estimated_hours_work $estimated_hours_work \ + -estimated_hours_work_min $estimated_hours_work_min \ + -estimated_hours_work_max $estimated_hours_work_max] + } + + if {[string is true $use_uncertain_completion_times_p]} { + + set display_value1 [expr $estimated_hours_work_min * $hours_day * [expr 100 - $percent_complete] / double(100)] + set display_value1 [pm::util::trim_number -number $display_value1] + set display_value2 [expr $estimated_hours_work_max * $hours_day * [expr 100 - $percent_complete] / double(100)] + set display_value2 [pm::util::trim_number -number $display_value2] + # set display_value2 [expr round($estimated_hours_work_max * [expr 100 - $percent_complete] / double(100))] + + if {[string equal $display_value1 $display_value2]} { + set display_value "$display_value1" + } else { + set display_value "$display_value1 - $display_value2" + } + } else { + set display_value [expr $estimated_hours_work * [expr 100 - $percent_complete] / double(100)] + set display_value [pm::util::trim_number -number $display_value] + } + + return $display_value +} + + +ad_proc -public pm::task::estimated_hours_work { + -estimated_hours_work:required + -estimated_hours_work_min:required + -estimated_hours_work_max:required +} { + Displays the total estimated hours work in a consistent format + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-02 + + @param estimated_hours_work + + @param estimated_hours_work_min + + @param estimated_hours_work_max + + @return + + @error +} { + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + + if {[string equal $use_uncertain_completion_times_p 1]} { + if {[string equal $estimated_hours_work_min $estimated_hours_work_max]} { + set display_value "$estimated_hours_work_min" + } else { + set display_value "$estimated_hours_work_min - $estimated_hours_work_max" + } + } else { + set display_value "$estimated_hours_work" + } + + return $display_value +} + + +ad_proc -public pm::task::estimated_days_work { + -estimated_hours_work:required + -estimated_hours_work_min:required + -estimated_hours_work_max:required +} { + Displays the total estimated days work in a consistent format + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-02 + + @param estimated_hours_work + + @param estimated_hours_work_min + + @param estimated_hours_work_max + + @return + + @error +} { + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + + if {[string equal $use_uncertain_completion_times_p 1]} { + if {[string equal $estimated_hours_work_min $estimated_hours_work_max]} { + set display_value [pm::util::days_work -hours_work $estimated_hours_work_min -pretty_p t] + } else { + set v1 [pm::util::days_work -hours_work $estimated_hours_work_min -pretty_p t] + set v2 [pm::util::days_work -hours_work $estimated_hours_work_max -pretty_p t] + + if {[string equal $v1 $v2]} { + set display_value $v1 + } else { + set display_value "$v1 - $v2" + } + } + } else { + set display_value [pm::util::days_work -hours_work $estimated_hours_work -pretty_p t] + } + + return $display_value +} + + +ad_proc -public pm::task::assignee_email_list { + -task_item_id:required +} { + Returns a list of assignee email addresses + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-10 + + @param task_item_id + + @return + + @error +} { + + return [db_list get_addresses { + SELECT + p.email + FROM + parties p, + pm_task_assignment a + WHERE + a.task_id = :task_item_id and + a.party_id = p.party_id + }] + +} + + +ad_proc -public pm::task::assignee_filter_select { + {-status_id:required} +} { + Returns a list of lists, people who are assigned tasks with a + status of status_id. Used in the list-builder filters for + the tasks list page. Cached 5 minutes. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param status_id + + @return + + @error +} { + return [util_memoize [list pm::task::assignee_filter_select_helper -status_id $status_id] 1] +} + + +ad_proc -private pm::task::assignee_filter_select_helper { + {-status_id:required} +} { + Returns a list of lists, people who are assigned tasks with a + status of status_id. Used in the list-builder filters for + the tasks list page. Cached 5 minutes. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + + @param status_id + + @return + + @error +} { + return [db_list_of_lists get_people " + SELECT + distinct(first_names || ' ' || last_name) as fullname, + u.person_id + FROM + persons u, + pm_task_assignment a, + pm_tasks_active ts + WHERE + u.person_id = a.party_id and + ts.task_id = a.task_id and + ts.status = :status_id + ORDER BY + fullname"] +} + + + +ad_proc -public pm::task::assignee_html { + {-number:required} + {-process_task_id ""} + {-task_item_id ""} +} { + Assignee HTML for new tasks + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-13 + + @return + + @error +} { + + # ------------------------------ + # cache these to speed it all up + + set roles_list_of_lists [pm::role::select_list_filter] + set assignee_list_of_lists [pm::util::subsite_assignees_list_of_lists] + + + # Get assignments for when using processes + if {[exists_and_not_null process_task_id]} { + + # PROCESS + + set task_assignee_list_of_lists \ + [pm::process::task_assignee_role_list \ + -process_task_id $process_task_id] + + } elseif {[exists_and_not_null task_item_id]} { + + # EDITING + + set task_assignee_list_of_lists \ + [pm::task::assignee_role_list \ + -task_item_id $task_item_id] + + } else { + + # NEW + + set task_assignee_list_of_lists [list] + } + + # Get assignments for when editing + + + set html "" + + foreach role_list $roles_list_of_lists { + + set role_name [lindex $role_list 0] + set role [lindex $role_list 1] + + append html " + " + + } + + append html "

    $role_name

    " + + foreach assignee_list $assignee_list_of_lists { + set name [lindex $assignee_list 0] + set person_id [lindex $assignee_list 1] + + if {[lsearch $task_assignee_list_of_lists [list $person_id $role]] >= 0} { + + append html " + $name +
    " + + } else { + + append html " + $name +
    " + } + + } + + append html "

    " + + return $html +} + + +ad_proc -public pm::task::get { + {-tasks_item_id:required} + {-one_line_array:required} + {-description_array:required} + {-description_mime_type_array:required} + {-estimated_hours_work_array:required} + {-estimated_hours_work_min_array:required} + {-estimated_hours_work_max_array:required} + {-dependency_array:required} + {-percent_complete_array:required} + {-end_date_day_array:required} + {-end_date_month_array:required} + {-end_date_year_array:required} + {-project_item_id_array:required} + {-set_client_properties_p "f"} + {-priority_array:required} +} { + Stuff information about tasks into several arrays + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-14 + + @param tasks_item_id a list of tasks to retrieve and stuff in + arrays + + @param one_line_array stuff one_line info in + one_line_array(task_item_id) + + @return + + @error +} { + + # set variables in calling environment, using names passed in + upvar 1 $one_line_array one_line_arr + upvar 1 $description_array description_arr + upvar 1 $description_mime_type_array description_mime_type_arr + upvar 1 $estimated_hours_work_array estimated_hours_work_arr + upvar 1 $estimated_hours_work_min_array estimated_hours_work_min_arr + upvar 1 $estimated_hours_work_max_array estimated_hours_work_max_arr + upvar 1 $dependency_array dependency_arr + upvar 1 $percent_complete_array percent_complete_arr + upvar 1 $end_date_day_array end_date_day_arr + upvar 1 $end_date_month_array end_date_month_arr + upvar 1 $end_date_year_array end_date_year_arr + upvar 1 $project_item_id_array project_item_id_arr + upvar 1 $priority_array priority_arr + + set task_where_clause " and i.item_id in ([join $tasks_item_id ", "])" + + db_foreach get_tasks { } { + set one_line_arr($tid) $one_line + set description_arr($tid) $description + set description_mime_type_arr($tid) $description_mime_type + set estimated_hours_work_arr($tid) $estimated_hours_work + set estimated_hours_work_min_arr($tid) $estimated_hours_work_min + set estimated_hours_work_max_arr($tid) $estimated_hours_work_max + set dependency_arr($tid) $parent_task_id + set percent_complete_arr($tid) $percent_complete + set end_date_day_arr($tid) $end_date_day + set end_date_month_arr($tid) $end_date_month + set end_date_year_arr($tid) $end_date_year + set project_item_id_arr($tid) $project + set priority_arr($tid) $priority + + # make sure that we don't have empty values for estimated + # hours work + if {[empty_string_p $estimated_hours_work_arr($tid)]} { + set estimated_hours_work_arr($tid) 0 + } + if {[empty_string_p $estimated_hours_work_min_arr($tid)]} { + set estimated_hours_work_min_arr($tid) 0 + } + if {[empty_string_p $estimated_hours_work_max_arr($tid)]} { + set estimated_hours_work_max_arr($tid) 0 + } + + if {[string is true $set_client_properties_p]} { + + ad_set_client_property -persistent f -- \ + project-manager \ + old_one_line($tid) \ + $one_line + + ad_set_client_property -persistent f -- \ + project-manager \ + old_description($tid) \ + $description + + ad_set_client_property -persistent f -- \ + project-manager \ + old_description_mime_type($tid) \ + $description_mime_type + + ad_set_client_property -persistent f -- \ + project-manager \ + old_estimated_hours_work($tid) \ + $estimated_hours_work + + ad_set_client_property -persistent f -- \ + project-manager \ + old_estimated_hours_work_min($tid) \ + $estimated_hours_work_min + + ad_set_client_property -persistent f -- \ + project-manager \ + old_estimated_hours_work_max($tid) \ + $estimated_hours_work_max + + ad_set_client_property -persistent f -- \ + project-manager \ + old_dependency($tid) \ + $parent_task_id + + ad_set_client_property -persistent f -- \ + project-manager \ + old_percent_complete($tid) \ + $percent_complete + + ad_set_client_property -persistent f -- \ + project-manager \ + old_end_date_day($tid) \ + $end_date_day + + ad_set_client_property -persistent f -- \ + project-manager \ + old_end_date_month($tid) \ + $end_date_month + + ad_set_client_property -persistent f -- \ + project-manager \ + old_end_date_year($tid) \ + $end_date_year + + ad_set_client_property -persistent f -- \ + project-manager \ + old_project_item_id($tid) \ + $project + + ad_set_client_property -persistent f -- \ + project-manager \ + old_assignees($tid) \ + [pm::task::get_assignee_names \ + -task_item_id $tid] + + } + + + } + +} + + +ad_proc -public pm::task::date_html { + {-selected_month ""} + {-selected_day ""} + {-selected_year ""} + {-show_help_p "t"} + {-month_target "end_date_month"} + {-day_target "end_date_day"} + {-year_target "end_date_year"} + +} { + Returns HTML for the date widget in the task-add-edit page + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-15 + + @return + + @error +} { + for {set i 1} {$i <= 12} {incr i} { + + # numbers are in the form of 01 - 12 + if {$i < 10} { + set j "0$i" + } else { + set j $i + } + set selected_[set j] "" + } + set selected_[set selected_month] "selected=\"selected\"" + + set return_val " + + + + + + " + + if {[string is true $show_help_p]} { + append return_val " + + + + + " + } + + append return_val "
    +   + + +
    + Month + + Day + + Year +
    " + + return $return_val +} + + +ad_proc -public pm::task::get_assignee_names { + {-task_item_id:required} +} { + Returns a list of assignees to a task (first name + last name) + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-20 + + @param task_item_id + + @return + + @error +} { + + return [db_list get_assignees { }] + +} + + +ad_proc -public pm::task::assignee_role_list { + {-task_item_id:required} +} { + Returns a list of lists, with all assignees to a particular + task. {{party_id role_id} {party_id role_id}} + + Todo: dependency changes, deadline changes + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-18 + + @param task_item_id + + @return + + @error +} { + + return [db_list_of_lists get_assignees_roles { }] + +} + + +ad_proc -public pm::task::what_changed { + {-comments_array:required} + {-comments_mime_type_array:required} + {-task_item_id_array:required} + {-number:required} +} { + Compares how a task was and how it currently is, and + adds to the comments array a list of changes. Uses properties + last set in the task::get proc. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-20 + + @param comments_array + + @param comments_mime_type_array + + @param task_item_id_array an array of task_item_ids, with keys + based on number + + @param number the keys to the task_item_id array, a list of integers + + @return + + @error +} { + + # we will append the changes to these arrays and convert them to + # text/html format + upvar 1 $comments_array comments_arr + upvar 1 $comments_mime_type_array comments_mime_type_arr + upvar 1 $task_item_id_array task_item_id + + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + set use_days_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] + set hours_day [pm::util::hours_day] + + + # get the new task values + set tasks_item_id [list] + foreach num $number { + lappend tasks_item_id $task_item_id($num) + } + + pm::task::get \ + -tasks_item_id $tasks_item_id \ + -one_line_array one_line_array \ + -description_array description_array \ + -description_mime_type_array description_mime_type_array \ + -estimated_hours_work_array estimated_hours_work_array \ + -estimated_hours_work_min_array estimated_hours_work_min_array \ + -estimated_hours_work_max_array estimated_hours_work_max_array \ + -dependency_array dependency_array \ + -percent_complete_array percent_complete_array \ + -end_date_day_array end_date_day_array \ + -end_date_month_array end_date_month_array \ + -end_date_year_array end_date_year_array \ + -project_item_id_array project_item_id_array \ + -priority_array priority_array + + + foreach num $number { + + set changes [list] + + set tid $task_item_id($num) + + set old [ad_get_client_property -- project-manager old_percent_complete($tid)] + + set new $percent_complete_array($tid) + + if {![string equal $old $new]} { + + if {$new >= 100 && $old < 100} { + + lappend changes "Closing task" + + } elseif {$new < 100 && $old >= 100} { + + lappend changes "Reopening task" + + } else { + lappend changes "Percent complete changed from $old%to $new%" + } + + } + + + set old_end_date_day [ad_get_client_property -- project-manager old_end_date_day($tid)] + set old_end_date_month [ad_get_client_property -- project-manager old_end_date_month($tid)] + set old_end_date_year [ad_get_client_property -- project-manager old_end_date_year($tid)] + + # end date + if { \ + ![string equal $old_end_date_day $end_date_day_array($tid)] || \ + ![string equal $old_end_date_month $end_date_month_array($tid)] || \ + ![string equal $old_end_date_year $end_date_year_array($tid)]} { + + # internationalize the dates + set iso_date_old "$old_end_date_year-$old_end_date_month-$old_end_date_day 00:00:00" + set iso_date_new "$end_date_year_array($tid)-$end_date_month_array($tid)-$end_date_day_array($tid) 00:00:00" + + if {[string equal $iso_date_old "-- 00:00:00"]} { + set date_old "no hard deadline" + } else { + set date_old [lc_time_fmt $iso_date_old "%x"] + } + + if {[string equal $iso_date_new "-- 00:00:00"]} { + set date_new "no hard deadline" + } else { + set date_new [lc_time_fmt $iso_date_new "%x"] + } + + lappend changes "Hard deadline changed from $date_old to $date_new" + } + + set old_one_line [ad_get_client_property -- project-manager old_one_line($tid)] + + # one_line + if {![string equal $old_one_line $one_line_array($tid)]} { + lappend changes "Subject changed from $old_one_line to $one_line_array($tid)" + } + + set old_description [ad_get_client_property -- project-manager old_description($tid)] + set old_description_mime_type [ad_get_client_property -- project-manager old_description_mime_type($tid)] + + # description + if { \ + ![string equal $old_description $description_array($tid)] || \ + ![string equal $old_description_mime_type $description_mime_type_array($tid)]} { + + set richtext_list [list $old_description $old_description_mime_type] + set old_description_html [template::util::richtext::get_property html_value $richtext_list] + set richtext_list [list $description_array($tid) $description_mime_type_array($tid)] + set new_description_html [template::util::richtext::get_property html_value $richtext_list] + + lappend changes "Description changed" + } + + set old_estimated_hours_work [ad_get_client_property -- project-manager old_estimated_hours_work($tid)] + set old_estimated_hours_work_min [ad_get_client_property -- project-manager old_estimated_hours_work_min($tid)] + set old_estimated_hours_work_max [ad_get_client_property -- project-manager old_estimated_hours_work_max($tid)] + + # estimated_hours_work or days work + if {[string is true $use_days_p]} { + if {[string is true $use_uncertain_completion_times_p]} { + + set old [pm::util::days_work -hours_work $old_estimated_hours_work_min] + set new [pm::util::days_work -hours_work $estimated_hours_work_min_array($tid)] + + if {![string equal $old $new]} { + lappend changes "Work estimate (min) changed from $old to $new days" + } + + set old [pm::util::days_work -hours_work $old_estimated_hours_work_max] + set new [pm::util::days_work -hours_work $estimated_hours_work_max_array($tid)] + if {![string equal $old $new]} { + lappend changes "Work estimate (max) changed from $old to $new days" + } + + } else { + + set old [pm::util::days_work -hours_work $old_estimated_hours_work] + set new [pm::util::days_work -hours_work $estimated_hours_work_array($tid)] + + if {![string equal $old $new]} { + lappend changes "Work estimate changed from $old to $new days" + } + + } + + } else { + + # estimated_hours_work - hours + if {[string is true $use_uncertain_completion_times_p]} { + + if {![string equal $old_estimated_hours_work_min $estimated_hours_work_min_array($tid)]} { + lappend changes "Work estimate (min) changed from $old_estimated_hours_work_min to $estimated_hours_work_min_array($tid) hrs" + } + + if {![string equal $old_estimated_hours_work_max $estimated_hours_work_max_array($tid)]} { + lappend changes "Work estimate (max) changed from $old_estimated_hours_work_max to $estimated_hours_work_max_array($tid) hrs" + } + } else { + + if {![string equal $old_estimated_hours_work $estimated_hours_work_array($tid)]} { + lappend changes "Work estimate changed from $old_estimated_hours_work to $estimated_hours_work_array($tid) hrs" + } + + } + } + + set old_assignees [ad_get_client_property -- \ + project-manager \ + old_assignees($tid)] + + set new_assignees [pm::task::get_assignee_names \ + -task_item_id $task_item_id($num)] + + # check for assignees that have been added + + foreach new $new_assignees { + if { [lsearch $old_assignees $new] == -1} { + lappend changes "Added: $new" + } + } + + # check for assignees that have been removed + foreach old $old_assignees { + if { [lsearch $new_assignees $old] == -1} { + lappend changes "Removed: $old" + } + } + + set old_project_item_id [ad_get_client_property -- project-manager old_project_item_id($tid)] + + # project + + if {![string equal $old_project_item_id $project_item_id_array($tid)]} { + + set old [pm::project::name -project_item_id $old_project_item_id] + + lappend changes "Project changed from $old" + + } + + set old_dependency [ad_get_client_property -- project-manager old_dependency($tid)] + + # dependency + if {![string equal $old_dependency $dependency_array($tid)]} { + + if {[empty_string_p $old_dependency]} { + set old "Nothing" + } else { + set old [pm::task::name \ + -task_item_id $old_dependency] + } + + if {[empty_string_p $dependency_array($tid)]} { + set new "Nothing" + } else { + set new [pm::task::name \ + -task_item_id $dependency_array($tid)] + } + + lappend changes "Dependency changed from $old ($old_dependency) to $new ($dependency_array($tid))" + } + + + # convert comments to richtext + set richtext_list [list $comments_arr($num) $comments_mime_type_arr($num)] + set comment_html [template::util::richtext::get_property html_value $richtext_list] + + + # add in changes + + if {[llength $changes] > 0} { + append comment_html "
    • [join $changes "
    • "]
    " + + set comments_arr($num) $comment_html + set comments_mime_type_arr($num) "text/html" + } + + } + + +} + + +ad_proc -public pm::task::clear_client_properties { + {-task_item_id:required} +} { + Clears all the client properties for a given task_item_id + + @author (ibr@test) + @creation-date 2004-11-03 + + @param task_item_id + + @return + + @error +} { + + ad_set_client_property -persistent f -- \ + project-manager \ + old_one_line($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_description($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_description_mime_type($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_estimated_hours_work($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_estimated_hours_work_min($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_estimated_hours_work_max($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_dependency($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_percent_complete($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_end_date_day($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_end_date_month($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_end_date_year($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_project_item_id($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_assignees($task_item_id) \ + "" + + ad_set_client_property -persistent f -- \ + project-manager \ + old_assignees($task_item_id) \ + "" + +} + + +ad_proc -public pm::task::default_orderby { + {-set ""} +} { + Returns the default order by (set by ad_set_client_property) + + @author (jader@bread.com) + @creation-date 2004-11-04 + + @param if set is set, then set the default_orderby + + @return + + @error +} { + if {[empty_string_p $set]} { + + set default_orderby "latest_finish_pretty,asc" + + set return_val [ad_get_client_property \ + -default $default_orderby \ + -- \ + project-manager \ + task-index-orderby] + + return $return_val + + } else { + + ad_set_client_property -- project-manager task-index-orderby $set + return $set + + } +} + + +ad_proc -public pm::task::today_html { + {-show_help_p "f"} + {-month_target "end_date_month"} + {-day_target "end_date_day"} + {-year_target "end_date_year"} + +} { + Returns today in an html form widget + + @author (jader-ibr@bread.com) + @creation-date 2004-11-18 + + @return + + @error +} { + + set today_day [clock format [clock scan today] -format "%d"] + set today_month [clock format [clock scan today] -format "%m"] + set today_year [clock format [clock scan today] -format "%Y"] + + set return_val [pm::task::date_html \ + -selected_month $today_month \ + -selected_day $today_day \ + -selected_year $today_year \ + -show_help_p $show_help_p \ + -month_target $month_target \ + -day_target $day_target \ + -year_target $year_target] + + return $return_val +} Index: openacs-4/packages/project-manager/tcl/task-procs.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/tcl/task-procs.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/tcl/task-procs.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,42 @@ + + + + + + + + + + + + DELETE FROM + pm_task_assignment + WHERE + task_id = :task_item_id + + + + + + DELETE FROM + pm_task_assignment + WHERE + task_id = :task_item_id and + party_id = :party_id + + + + + + SELECT + party_id + FROM + pm_task_assignment + WHERE + task_id = :task_item_id and + party_id = :party_id + LIMIT 1 + + + + Index: openacs-4/packages/project-manager/www/add-edit-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit-2-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit-2-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,21 @@ + + + + + SELECT p.item_id as project_item_id, + p.title as project_name, + p.description + FROM pm_projectsx p + WHERE p.project_id = :old_project_id + + + + + + UPDATE pm_projects set + WHERE + project_id = :project_id + + + + Index: openacs-4/packages/project-manager/www/add-edit-2-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit-2-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit-2-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,25 @@ + + + + + SELECT + p.item_id as project_item_id, + p.title as project_name, + p.description + FROM + pm_projectsx p + WHERE + p.project_id = :old_project_id + + + + + + UPDATE + pm_projects set + WHERE + project_id = :project_id + + + + Index: openacs-4/packages/project-manager/www/add-edit-2.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit-2.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit-2.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,7 @@ + +@context_bar;noquote@ +@title@ + +
    + +
    Index: openacs-4/packages/project-manager/www/add-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit-2.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,106 @@ +ad_page_contract { + + Page for customized columns on projects + + This is skipped if the UseProjectCustomizationsP is set to 0, used + if it is set to 1. + + Use this page to create a second page for editing customized project + information. + + @author jader@bread.com + @creation-date 2003-12-05 + @cvs-id $Id: add-edit-2.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + +} { + project_id:integer,optional + {old_project_id ""} + {project_item_id ""} + {project_name ""} + {description ""} + +} -properties { + + context_bar:onevalue + title:onevalue + +} + + +# this is necessary for new projects +if {![exists_and_not_null old_project_id]} { + set old_project_id $project_id +} + +# --------------------------------------------------------------- # +# the unique identifier for this package +set package_id [ad_conn package_id] +set subsite_id [ad_conn subsite_id] +set user_id [auth::require_login] + +set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + +# terminology +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] +set use_goal_p [parameter::get -parameter "UseGoalP" -default "1"] +set use_project_code_p [parameter::get -parameter "UseUserProjectCodesP" -default "1"] + + +set title "Edit a $project_term_lower" +set context_bar [ad_context_bar "Edit $project_term"] + +permission::require_permission -party_id $user_id -object_id $package_id -privilege write + +# set project_item_id [db_string get_item_id { }] +set keyval 1 + +ad_form -name add_edit \ + -form { + keyval:key + + {project_id:text(hidden) + {value $project_id}} + + {project_item_id:text(hidden) + {value $project_item_id}} + + {project_name:text(inform) + {label "[set project_term] name"} + {value $project_name} + } + + {description:text(inform) + {label "Old Description"} + {value $description} + } + + } \ + -validate { + } \ + -select_query_name project_query \ + -on_submit { + + set user_id [ad_conn user_id] + set peeraddr [ad_conn peeraddr] + + } \ + -new_data { + + ad_returnredirect -message "Project changes saved" "one?[export_url_vars project_item_id]" + ad_script_abort + + } -edit_data { + + db_dml update_project { *SQL* } + + } -after_submit { + + ad_returnredirect -message "Project changes saved" "one?[export_url_vars project_item_id]" + ad_script_abort + + } Index: openacs-4/packages/project-manager/www/add-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,41 @@ + + + + + SELECT p.item_id as project_item_id, + p.parent_id, + p.project_id, + p.title as project_name, + p.project_code, + p.goal, + p.description, + p.customer_id, + p.status_id, + p.logger_project, + to_char(p.planned_start_date,'YYYY-MM-DD') as planned_start_date, + to_char(p.planned_end_date,'YYYY-MM-DD') as planned_end_date, + p.ongoing_p + FROM pm_projectsx p + WHERE p.item_id = :project_item_id and + p.project_id = :project_id + + + + + + SELECT sysdate + from dual + + + + + + SELECT description, + status_id + FROM pm_project_status + ORDER BY status_type desc, + description asc + + + + Index: openacs-4/packages/project-manager/www/add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,45 @@ + + + + + SELECT + p.item_id as project_item_id, + p.parent_id, + p.project_id, + p.title as project_name, + p.project_code, + p.goal, + p.description, + p.customer_id, + p.status_id, + p.logger_project, + to_char(p.planned_start_date,'YYYY-MM-DD') as planned_start_date, + to_char(p.planned_end_date,'YYYY-MM-DD') as planned_end_date, + p.ongoing_p + FROM + pm_projectsx p + WHERE + p.item_id = :project_item_id and + p.project_id = :project_id + + + + + + SELECT + current_timestamp + + + + + + SELECT + description, status_id + FROM + pm_project_status + ORDER BY + status_type desc, description asc + + + + Index: openacs-4/packages/project-manager/www/add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,8 @@ + + +@context_bar;noquote@ +@title@ + +
    + +
    Index: openacs-4/packages/project-manager/www/add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/add-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/add-edit.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,326 @@ +ad_page_contract { + + Simple add/edit form for projects + + @author jader@bread.com, ncarroll@ee.usyd.edu.au + @creation-date 2003-05-15 + @cvs-id $Id: add-edit.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + +} { + project_id:integer,optional + {project_revision_id ""} + {project_item_id ""} + {project_name ""} + {project_code ""} + {parent_id ""} + {goal ""} + {description ""} + {customer_id ""} + {planned_start_date ""} + {planned_end_date ""} + {deadline_scheduling ""} + {ongoing_p ""} + {status_id ""} + {logger_project ""} + +} -properties { + + context_bar:onevalue + title:onevalue + +} + +# --------------------------------------------------------------- # +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# terminology +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] +set use_goal_p [parameter::get -parameter "UseGoalP" -default "1"] +set use_project_code_p [parameter::get -parameter "UseUserProjectCodesP" -default "1"] + +set use_project_customizations_p [parameter::get -parameter "UseProjectCustomizationsP" -default "0"] + +set ongoing_by_default_p [parameter::get -parameter "OngoingByDefaultP" -default "f"] + + +if {[exists_and_not_null project_item_id] && ![exists_and_not_null project_id]} { + set project_id [pm::project::get_project_id -project_item_id $project_item_id] +} + + +if {[exists_and_not_null project_id]} { + set title "Edit a $project_term_lower" + set context_bar [ad_context_bar "Edit $project_term"] + + # permissions + permission::require_permission -party_id $user_id -object_id $package_id -privilege write + +} else { + set title "Add a $project_term_lower" + set context_bar [ad_context_bar "New $project_term"] + + # permissions + permission::require_permission -party_id $user_id -object_id $package_id -privilege create +} + + +if {[ad_form_new_p -key project_item_id]} { + set logger_project "" + set logger_values "" +} else { + + set logger_project [pm::project::get_logger_project -project_item_id $project_item_id] + set logger_values [logger::project::get_variables -project_id $logger_project] + +} + +ad_form -name add_edit \ + -form { + project_id:key + + {parent_id:text(hidden) + {value $parent_id} + } + + {project_item_id:text(hidden) + {value $project_item_id} + } + + {logger_project:text(hidden) + {value $logger_project} + } + + {project_name:text + {label "[set project_term] name"} + {value $project_name} + {html {size 50}} + } + + {description:text(textarea),optional + {label "Description"} + {value $description} + {html { rows 5 cols 40 wrap soft}}} + + {customer_id:text(select),optional + {label "Customer"} + {options {{"--- TBD ---" ""} [db_list_of_lists get_customer "select o.name, o.organization_id from organizations o order by o.name"]}} + } + + {planned_start_date:text(text) + {label "Starts"} + {html {id sel1}} + {after_html { \[y-m-d \] + }} + } + + {planned_end_date:text(text) + {label "Deadline"} + {html {id sel2}} + {after_html { \[y-m-d \] + }} + } + + + {ongoing_p:text(select) + {label "Project is ongoing?"} + {options {{"No" f} {"Yes" t}}} + {value $ongoing_p} + {help_text "If yes, then this project has no deadline"} + } + + {status_id:text(select) + {label "Status"} + {options {[db_list_of_lists get_status_codes { }]}} + } + + {variables:text(multiselect),multiple + {label "Logged variables"} + {options {[logger::ui::variable_options_all]}} + {values {$logger_values}} + {html {size 6}} + } + + } + +if {[exists_and_not_null project_id]} { + if {![empty_string_p [category_tree::get_mapped_trees $package_id]]} { + ad_form -extend -name add_edit -form { + {category_ids:integer(category),multiple {label "Categories"} + {html {size 7}} {value {$project_item_id $package_id}} + } + } + } +} else { + if {![empty_string_p [category_tree::get_mapped_trees $package_id]]} { + ad_form -extend -name add_edit -form { + {category_ids:integer(category),multiple,optional {label "Categories"} + {html {size 7}} {value {}} + } + } + } +} + +if {$use_goal_p} { + ad_form -extend -name add_edit \ + -form { + {goal:text(textarea),optional + {label "[set project_term] goal"} + {value $goal} + {html { rows 5 cols 40 wrap soft}}} + } +} + + +if {$use_project_code_p} { + ad_form -extend -name add_edit \ + -form { + {project_code:text,optional + {label "[set project_term] code"} + {value $project_code} + } + } +} + + + + +ad_form -extend -name add_edit \ + -select_query_name project_query \ + -on_submit { + + set user_id [ad_conn user_id] + set peeraddr [ad_conn peeraddr] + + } \ + -new_request { + + if {[string equal $ongoing_by_default_p t]} { + set ongoing_p t + } + + set planned_end_date [util::date acquire clock [clock scan $planned_end_date]] + set planned_end_date "[lindex $planned_end_date 0]-[lindex $planned_end_date 1]-[lindex $planned_end_date 2]" + set planned_start_date [util::date acquire clock [clock scan $planned_start_date]] + set planned_start_date "[lindex $planned_start_date 0]-[lindex $planned_start_date 1]-[lindex $planned_start_date 2]" + + + + + } \ + -new_data { + + set project_id [pm::project::new \ + -project_name $project_name \ + -project_code $project_code \ + -parent_id $parent_id \ + -goal $goal \ + -description $description \ + -planned_start_date $planned_start_date \ + -planned_end_date $planned_end_date \ + -actual_start_date "" \ + -actual_end_date "" \ + -ongoing_p $ongoing_p \ + -status_id $status_id \ + -organization_id $customer_id \ + -creation_date "" \ + -creation_user $user_id \ + -creation_ip $peeraddr \ + -package_id $package_id + ] + + set project_item_id [pm::project::get_project_item_id -project_id $project_id] + set logger_project [pm::project::get_logger_project -project_item_id $project_item_id] + + if {[exists_and_not_null category_ids]} { + category::map_object -remove_old -object_id $project_item_id $category_ids + } + + if {[exists_and_not_null variables]} { + foreach var $variables { + logger::project::map_variable \ + -project_id $logger_project \ + -variable_id $var + } + } else { + # add in the default variable + logger::project::map_variable \ + -project_id $logger_project \ + -variable_id [logger::variable::get_default_variable_id] + } + + if {$use_project_customizations_p} { + # warn of current bug so users can work around it + ad_returnredirect -message "You must submit changes on this page or you will lose any data on this page" "add-edit-2?[export_url_vars project_item_id project_id]" + ad_script_abort + } else { + ad_returnredirect -message "Project: '$project_name' added" "one?[export_url_vars project_item_id project_id]" + ad_script_abort + } + + } -edit_data { + + # we need to pass the old_project_id to add-edit-2.tcl because + # the new revision will not have any of the custom values in + # it until it is edited. So we need to pull in these values + set old_project_id $project_id + + set project_id [pm::project::edit \ + -project_item_id $project_item_id \ + -project_name $project_name \ + -project_code $project_code \ + -parent_id $parent_id \ + -goal $goal \ + -description $description \ + -planned_start_date $planned_start_date \ + -planned_end_date $planned_end_date \ + -actual_start_date "" \ + -actual_end_date "" \ + -logger_project $logger_project \ + -ongoing_p $ongoing_p \ + -status_id $status_id \ + -organization_id $customer_id \ + -creation_user $user_id \ + -creation_ip $peeraddr \ + -package_id $package_id] + + set project_item_id [pm::project::get_project_item_id \ + -project_id $project_id] + + set logger_project [pm::project::get_logger_project -project_item_id $project_item_id] + + + if {[exists_and_not_null variables]} { + + logger::project::remap_variables -project_id $logger_project -new_variable_list $variables + + } else { + logger::project::remap_variables -project_id $logger_project -new_variable_list [logger::variable::get_default_variable_id] + } + + if {[exists_and_not_null category_ids]} { + category::map_object -remove_old -object_id $project_item_id $category_ids + } + } -after_submit { + + if {$use_project_customizations_p} { + # warn of current bug so users can work around it + ad_returnredirect -message "You must submit changes on this page or you will lose any data on this page" "add-edit-2?[export_url_vars project_id old_project_id]" + # to add back in subproject support, should use + # compute_parent_status + pm::project::compute_status $project_item_id + ad_script_abort + } else { + ad_returnredirect -message "Changes to project saved" "one?[export_url_vars project_id]" + # to add back in subproject support, should use + # compute_parent_status + pm::project::compute_status $project_item_id + ad_script_abort + } +} + Index: openacs-4/packages/project-manager/www/bulk-close.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/bulk-close.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/bulk-close.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,39 @@ +# + +ad_page_contract { + + Closes several projects at once. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-07-02 + @arch-tag: ca6395ca-df76-467c-8b46-65f4370d3248 + @cvs-id $Id: bulk-close.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + project_item_id:integer,multiple + {return_url "index?assignee_id=[ad_conn user_id]"} +} -properties { +} -validate { +} -errors { +} + + +permission::require_permission \ + -privilege write \ + -object_id [ad_conn package_id] \ + +set number 0 + +foreach project $project_item_id { + pm::project::close \ + -project_item_id $project + + incr number +} + +if {$number > 1} { + set project_projects projects +} else { + set project_projects project +} + +ad_returnredirect -message "$number $project_projects closed" $return_url Index: openacs-4/packages/project-manager/www/calendar-users-update.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/calendar-users-update.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/calendar-users-update.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,42 @@ +# + +ad_page_contract { + + Updates the users the user will see on the calendar + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-09-13 + @arch-tag: 43aadba9-fd89-414a-a6c7-3b25ac2a4779 + @cvs-id $Id: calendar-users-update.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + {party_id:integer,multiple ""} +} -properties { +} -validate { +} -errors { +} + +set user_id [auth::require_login] + +if {[empty_string_p $party_id]} { + set party_id [list $user_id] +} + +db_transaction { + db_dml delete_old_user_list { + DELETE FROM + pm_users_viewed + WHERE + viewing_user = :user_id + } + + foreach party $party_id { + db_dml add_user_to_view { + INSERT INTO + pm_users_viewed + (viewing_user, viewed_user) values + (:user_id, :party) + } + } +} + +ad_returnredirect -message "Updated who you will see on the task calendar" task-calendar Index: openacs-4/packages/project-manager/www/index-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/Attic/index-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/index-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,69 @@ + + + oracle8.0 + + + + SELECT + p.item_id as project_item_id, + p.project_id, + p.parent_id as folder_id, + p.object_type as content_type, + p.title as project_name, + p.project_code, + to_char(p.planned_start_date, 'MM/DD/YY') as planned_start_date, + to_char(p.planned_end_date, 'MM/DD/YY') as planned_end_date, + p.ongoing_p, + c.category_id, + c.category_name, + p.earliest_finish_date - sysdate as days_to_earliest_finish, + p.latest_finish_date - sysdate as days_to_latest_finish, + p.actual_hours_completed, + p.estimated_hours_total, + to_char(p.estimated_finish_date, 'MM/DD/YY') as estimated_finish_date, + to_char(p.earliest_finish_date, 'MM/DD/YY') as earliest_finish_date, + to_char(p.latest_finish_date, 'MM/DD/YY') as latest_finish_date, + case when o.name is null then '--no customer--' else o.name + end as customer_name, + o.organization_id as customer_id + FROM pm_projectsx p + LEFT JOIN pm_project_assignment pa + ON p.item_id = pa.project_id + LEFT JOIN organizations o ON p.customer_id = + o.organization_id + LEFT JOIN ( + select + om.category_id, + om.object_id, + t.name as category_name + from + category_object_map om, + category_translations t, + categories ctg + where + om.category_id = t.category_id and + ctg.category_id = t.category_id and + ctg.deprecated_p = 'f') + c ON p.item_id = c.object_id, + cr_items i, + cr_folders f, + pm_project_status s + WHERE + p.project_id = i.live_revision and + s.status_id = p.status_id + and i.parent_id = f.folder_id + and f.package_id = :package_id + [template::list::filter_where_clauses -and -name projects] + [template::list::orderby_clause -orderby -name projects] + + + + + + select pm_project.get_root_folder (:package_id, 'f') + from dual + + + + + Index: openacs-4/packages/project-manager/www/index-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/Attic/index-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/index-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,61 @@ + + + postgresql7.3 + + + + SELECT + p.item_id as project_item_id, + p.project_id, + p.parent_id as folder_id, + p.object_type as content_type, + p.title as project_name, + p.project_code, + to_char(p.planned_start_date, 'MM/DD/YY') as planned_start_date, + to_char(p.planned_end_date, 'MM/DD/YY') as planned_end_date, + p.ongoing_p, + c.category_id, + c.category_name, + p.earliest_finish_date - current_date as days_to_earliest_finish, + p.latest_finish_date - current_date as days_to_latest_finish, + p.actual_hours_completed, + p.estimated_hours_total, + to_char(p.estimated_finish_date, 'MM/DD/YY') as estimated_finish_date, + to_char(p.earliest_finish_date, 'MM/DD/YY') as earliest_finish_date, + to_char(p.latest_finish_date, 'MM/DD/YY') as latest_finish_date, + case when o.name is null then '--no customer--' else o.name + end as customer_name, + o.organization_id as customer_id + FROM pm_projectsx p + LEFT JOIN pm_project_assignment pa + ON p.item_id = pa.project_id + LEFT JOIN organizations o ON p.customer_id = + o.organization_id + LEFT JOIN ( + select + om.category_id, + om.object_id, + t.name as category_name + from + category_object_map om, + category_translations t, + categories ctg + where + om.category_id = t.category_id and + ctg.category_id = t.category_id and + ctg.deprecated_p = 'f') + c ON p.item_id = c.object_id, + cr_items i, + cr_folders f, + pm_project_status s + WHERE + p.project_id = i.live_revision and + s.status_id = p.status_id + and i.parent_id = f.folder_id + and f.package_id = :package_id + [template::list::filter_where_clauses -and -name projects] + [template::list::orderby_clause -orderby -name projects] + + + + Index: openacs-4/packages/project-manager/www/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/index.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/index.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,38 @@ + + + + + @project_term@s + @context;noquote@ + + + + + + + + + + + +
    + +
    + Search:
    + + @hidden_vars;noquote@ + +
    + + @category_select;noquote@ + + + +
    + + + +
    + + + Index: openacs-4/packages/project-manager/www/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/index.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/index.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,264 @@ +ad_page_contract { + + Main view page for projects. + + @author jader@bread.com + @author ncarroll@ee.usyd.edu.au (on first version that used CR) + @creation-date 2003-05-15 + @cvs-id $Id: index.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return projects Multirow data set of projects. + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) + +} { + orderby_project:optional + {status_id:integer,optional} + {searchterm ""} + category_id:multiple,optional + {format "normal"} + {assignee_id:integer,optional} +} -properties { + + context:onevalue + projects:multirow + write_p:onevalue + create_p:onevalue + admin_p:onevalue + task_term:onevalue + task_term_lower:onevalue + project_term:onevalue + project_term_lower:onevalue +} + +# --------------------------------------------------------------- # + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +set exporting_vars { status_id category_id assignee_id orderby_project format } +set hidden_vars [export_vars -form $exporting_vars] + + +# set up context bar +set context [list] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# root CR folder +set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + +# Projects, using list-builder --------------------------------- + +# set default values +if {![exists_and_not_null status_id]} { + set status_id [pm::project::default_status_open] +} + + +# We want to set up a filter for each category tree. + +set export_vars [export_vars -form {status_id orderby}] + +if {[exists_and_not_null category_id]} { + set temp_category_id $category_id +} else { + set temp_category_id "" +} + +set category_select [pm::util::category_selects \ + -export_vars $export_vars \ + -category_id $temp_category_id \ + -package_id $package_id \ + ] + +set assignees_filter [pm::project::assignee_filter_select -status_id $status_id] + +if {![empty_string_p $searchterm]} { + + if {[regexp {([0-9]+)} $searchterm match query_digits]} { + set search_term_where " (upper(p.title) like upper('%$searchterm%') + or p.item_id = :query_digits) " + } else { + set search_term_where " upper(p.title) like upper('%$searchterm%')" + } +} else { + set search_term_where "" +} + + +set default_orderby [pm::project::index_default_orderby] + +if {[exists_and_not_null orderby_project]} { + pm::project::index_default_orderby \ + -set $orderby_project +} + +# Get url of the organizations package if it has been mounted for the links on the index page. +set organizations_url [util_memoize [list site_node::get_package_url -package_key organizations]] +if {[empty_string_p $organizations_url]} { + set organization_column "@projects.customer_name@" +} else { + set organization_column "@projects.customer_name@" +} + + +template::list::create \ + -name projects \ + -multirow projects \ + -selected_format $format \ + -key project_item_id \ + -elements { + project_name { + label "Project name" + link_url_col item_url + link_html { title "View this project version" } + } + customer_name { + label "Customer" + display_template " +$organization_column@projects.customer_name@ +" + } + earliest_finish_date { + label "Earliest finish" + display_template "@projects.earliest_finish_date@@projects.earliest_finish_date@" + } + latest_finish_date { + label "Latest Finish" + display_template "@projects.latest_finish_date@@projects.latest_finish_date@" + } + actual_hours_completed { + label "Hours completed" + display_template "@projects.actual_hours_completed@/@projects.estimated_hours_total@" + } + category_id { + display_template "" + } + } \ + -actions [list "Add project" "add-edit" "Add project" "Customers" "[site_node::get_package_url -package_key organizations]" "View customers"] \ + -bulk_actions [list "Close" "bulk-close" "Close project"] \ + -sub_class { + narrow + } \ + -filters { + searchterm { + label "Search" + where_clause {$search_term_where} + } + status_id { + label "Status" + values {[pm::status::project_status_select]} + where_clause {s.status_id = :status_id} + } + assignee_id { + label "Assignee" + values {$assignees_filter} + where_clause {pa.party_id = :assignee_id} + } + category_id { + label Categories + where_clause {c.category_id = [join [value_if_exists category_id] ","]} + } + } \ + -orderby { + default_value $default_orderby + project_name { + label "Project name" + orderby_desc "upper(p.title) desc" + orderby_asc "upper(p.title) asc" + default_direction asc + } + customer_name { + label "Customer Name" + orderby_desc "upper(o.name) desc, earliest_finish_date desc" + orderby_asc "upper(o.name) asc, earliest_finish_date asc" + default_direction asc + } + category_id { + label "Categories" + orderby_desc "c.category_name desc" + orderby_asc "c.category_name asc" + default_direction asc + } + earliest_finish_date { + label "Earliest finish" + orderby_desc "p.earliest_finish_date desc" + orderby_asc "p.earliest_finish_date asc" + default_direction asc + } + latest_finish_date { + label "Latest finish" + orderby_desc "p.latest_finish_date desc" + orderby_asc "p.latest_finish_date asc" + default_direction asc + } + actual_hours_completed { + label "Hours completed" + orderby_desc "p.actual_hours_completed desc" + orderby_asc "p.actual_hours_completed asc" + default_direction asc + } + } \ + -formats { + normal { + label "Table" + layout table + row { + project_name {} + customer_name {} + category_id {} + earliest_finish_date {} + latest_finish_date {} + actual_hours_completed {} + } + } + csv { + label "CSV" + output csv + page_size 0 + row { + project_name {} + customer_name {} + category_id {} + earliest_finish_date {} + latest_finish_date {} + actual_hours_completed {} + } + } + } \ + -orderby_name orderby_project \ + -html { + width 100% + } + +# Note: On oracle it you get "ORA-03113: end-of-file on communication channel" +# please drop the index cat_object_map_i. Unique indexes are not allowed in organization index tables + +db_multirow -extend { item_url } projects project_folders { +} { + set item_url [export_vars -base "one" {project_item_id}] +} + + + +list::write_output -name projects + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/log-bulk.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/log-bulk.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/log-bulk.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,6 @@ + + @title@ + @context@ + +This page will eventually allow you to log hours against multiple +tasks at once. Index: openacs-4/packages/project-manager/www/log-bulk.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/log-bulk.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/log-bulk.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,31 @@ +# + +ad_page_contract { + + Logs hours against multiple tasks at once. + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-13 + @arch-tag: 4d3fcd3a-71d0-4ca5-9213-51e4c4ec4620 + @cvs-id $Id: log-bulk.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @param item_id A multiple containing the task item_ids +} { + task_item_id:multiple + {return_url ""} +} -properties { +} -validate { +} -errors { +} + +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +set title "Log time for multiple tasks" + +if {[exists_and_not_null return_url]} { + set context [list [list $return_url Tasks] "Log time"] +} else { + set context [list "Log time"] +} + Index: openacs-4/packages/project-manager/www/log.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/log.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/log.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,11 @@ + +@title;noquote@ +@context;noquote@ + + +The administrator needs to set up integration with logger. + +

    + +After they have done this, you can go back to the previous page, + refresh it, and then add and edit logged hours. Index: openacs-4/packages/project-manager/www/log.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/log.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/log.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,11 @@ +ad_page_contract { + Stub that tells people to set up logger/project-manager integration + + @author Jade Rubick (jader@bread.com) stolen from Peter + @creation-date 2003-04-16 + @cvs-id $Id: log.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} + + +set title "Set up logger integration" +set context [list] Index: openacs-4/packages/project-manager/www/log.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/log.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/log.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,5 @@ + + + + + Index: openacs-4/packages/project-manager/www/one-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/one-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/one-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,135 @@ + + + + + + SELECT p.item_id, + p.project_id, + p.title as project_name, + p.project_code, + p.goal, + p.description, + p.mime_type, + to_char(p.planned_start_date,'YYYY-MM-DD HH24:MI') as planned_start_date, + to_char(p.planned_end_date,'YYYY-MM-DD HH24:MI') as planned_end_date, + p.logger_project, + p.ongoing_p, + i.live_revision, + to_char(p.estimated_finish_date,'YYYY-MM-DD HH24:MI') as estimated_finish_date, + to_char(p.earliest_finish_date,'YYYY-MM-DD HH24:MI') as earliest_finish_date, + to_char(p.latest_finish_date,'YYYY-MM-DD HH24:MI') as latest_finish_date, + p.actual_hours_completed, + p.estimated_hours_total, + p.parent_id + FROM pm_projectsx p, cr_items i + WHERE p.item_id = :project_item_id and + p.project_id = :project_id and + p.item_id = i.item_id + + + + + + SELECT t.item_id as task_id, + t.title, + to_char(t.end_date,'YYYY-MM-DD HH24:MI') as end_date, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + t.earliest_start - sysdate as days_to_earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + t.earliest_finish - sysdate as days_to_earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + t.latest_start - sysdate as days_to_latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(sysdate,'J') as today_j, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.latest_finish - sysdate as days_to_latest_finish, + u.first_names, + u.last_name, + t.percent_complete, + d.parent_task_id, + d.dependency_type, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.actual_hours_worked, + s.status_type, + s.description as status_description + FROM (SELECT * + FROM pm_tasks_revisionsx tk, + pm_task_assignment asg + WHERE tk.item_id = asg.task_id (+) + ) t , + persons u, + cr_items i, + pm_tasks_active ti, + pm_task_status s , + pm_task_dependency d + WHERE i.item_id = d.task_id (+) and + t.party_id = u.person_id (+) and + t.parent_id = :project_item_id and + t.revision_id = i.live_revision and + t.item_id = ti.task_id and + ti.status = s.status_id + [template::list::orderby_clause -name tasks -orderby] + + + + + + begin + :1 := pm_project.get_root_folder (:package_id, 'f'); + end; + + + + + + SELECT p.item_id, + p.project_id, + p.parent_id as folder_id, + p.object_type as content_type, + p.title as project_name, + p.project_code, + to_char(p.planned_start_date, 'Mon DD') as planned_start_date, + to_char(p.planned_end_date, 'Mon DD') as planned_end_date, + p.ongoing_p, + p.actual_hours_completed, + p.estimated_hours_total + FROM pm_projectsx p, + cr_items i + WHERE p.project_id = i.live_revision and + p.parent_id = :project_item_id + ORDER BY p.title + + + + + + SELECT a.project_id, + r.one_line as role_name, + p.first_names || ' ' || p.last_name as user_name + FROM pm_project_assignment a, + pm_roles r, + persons p + WHERE a.role_id = r.role_id and + a.party_id = p.person_id and + project_id = :project_item_id + ORDER BY r.role_id, + p.first_names, + p.last_name + + + + + + SELECT p.customer_id, + c.name as customer_name + FROM pm_projectsx p , + organizations c + WHERE p.customer_id = c.organization_id (+) and + p.project_id = :original_project_id + + + + Index: openacs-4/packages/project-manager/www/one-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/one-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/one-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,176 @@ + + + + + + SELECT + p.item_id, + p.project_id, + p.title as project_name, + p.project_code, + p.goal, + p.description, + p.mime_type, + to_char(p.planned_start_date,'YYYY-MM-DD HH24:MI') as planned_start_date, + to_char(p.planned_end_date,'YYYY-MM-DD HH24:MI') as planned_end_date, + p.logger_project, + p.ongoing_p, + i.live_revision, + to_char(p.estimated_finish_date,'YYYY-MM-DD HH24:MI') as estimated_finish_date, + to_char(p.earliest_finish_date,'YYYY-MM-DD HH24:MI') as earliest_finish_date, + to_char(p.latest_finish_date,'YYYY-MM-DD HH24:MI') as latest_finish_date, + p.actual_hours_completed, + p.estimated_hours_total, + p.parent_id, + s.status_type + FROM + pm_projectsx p, + cr_items i, + pm_project_status s + WHERE + p.item_id = :project_item_id and + p.project_id = :project_id and + p.item_id = i.item_id and + p.status_id = s.status_id + + + + + + SELECT + t.item_id as task_item_id, + t.parent_id as project_item_id, + t.title, + to_char(t.end_date,'YYYY-MM-DD HH24:MI') as end_date, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + t.earliest_start - current_date as days_to_earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + t.earliest_finish - current_date as days_to_earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + t.latest_start - current_date as days_to_latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(current_date,'J') as today_j, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.latest_finish - current_date as days_to_latest_finish, + u.person_id, + u.first_names, + u.last_name, + t.percent_complete, + d.parent_task_id, + d.dependency_type, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.actual_hours_worked, + s.status_type, + s.description as status_description, + r.is_lead_p, + t.priority + FROM + (select tr.item_id, + ta.party_id, + ta.role_id, + tr.title, + tr.end_date, + tr.earliest_start, + tr.earliest_finish, + tr.latest_start, + tr.latest_finish, + tr.percent_complete, + tr.estimated_hours_work, + tr.estimated_hours_work_min, + tr.estimated_hours_work_max, + tr.actual_hours_worked, + tr.parent_id, + tr.revision_id, + tr.priority + from pm_tasks_revisionsx tr + LEFT JOIN + pm_task_assignment ta ON tr.item_id = ta.task_id) t + LEFT JOIN + persons u + ON + t.party_id = u.person_id + LEFT JOIN + pm_roles r + ON t.role_id = r.role_id, + cr_items i + LEFT JOIN + pm_task_dependency d + ON + i.item_id = d.task_id, + pm_tasks_active ti, + pm_task_status s + WHERE + t.parent_id = :project_item_id and + t.revision_id = i.live_revision and + t.item_id = ti.task_id and + ti.status = s.status_id + $done_clause + [template::list::filter_where_clauses -and -name tasks] + [template::list::orderby_clause -name tasks -orderby] + + + + + + select pm_project__get_root_folder (:package_id, 'f') + + + + + + SELECT + p.item_id, + p.project_id, + p.parent_id as folder_id, + p.object_type as content_type, + p.title as project_name, + p.project_code, + to_char(p.planned_start_date, 'Mon DD') as planned_start_date, + to_char(p.planned_end_date, 'Mon DD') as planned_end_date, + p.ongoing_p, + p.actual_hours_completed, + p.estimated_hours_total + FROM pm_projectsx p, cr_items i + WHERE p.project_id = i.live_revision and + p.parent_id = :project_item_id + ORDER BY p.title + + + + + + SELECT + a.project_id, + r.one_line as role_name, + p.first_names || ' ' || p.last_name as user_name, + r.is_lead_p + FROM + pm_project_assignment a, + pm_roles r, + persons p + WHERE + a.role_id = r.role_id and + a.party_id = p.person_id and + project_id = :project_item_id + ORDER BY + r.role_id, p.first_names, p.last_name + + + + + + SELECT + p.customer_id, + c.name as customer_name + FROM + pm_projectsx p + LEFT JOIN organizations c ON p.customer_id = c.organization_id + WHERE + p.project_id = :original_project_id + + + + Index: openacs-4/packages/project-manager/www/one.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/one.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/one.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,416 @@ + + + + @my_title;noquote@ -- Closed + + + @my_title;noquote@ + + @context;noquote@ + + +

    (not current, select live version from the task change page)

    + + + + + + + +
    + + + + + + + + + + + + + + +
    + + + + + + + + Edit + + +   @project_term@ + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Name:@project.project_name@
    Code:@project.project_code@
    Goal:@project.goal@
    Description:@project.description;noquote@
    +
     
    + +

    + + + + + + + + + + + +
    + + Dates + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Start@project.planned_start_date@
    Earliest finish@project.earliest_finish_date@Ongoing
    Latest finish@project.latest_finish_date@Ongoing
    Task hours completed@project.actual_hours_completed@ of @project.estimated_hours_total@
    +
    +
    + +

    + + + + + + + + + + + + + + + +
    + + Assignees + +
    + +  
    + +  
    + +

    + + +

    + + + + + + + + + + + +
    + + Project information + +
    + + + + + +
    Customer@custom.customer_name@
    +
     
    + + +

    + + + + + + + + + + + + +
    + + Categories + +
    + + + +
    + +
      + + +
    • @categories:item@ + + +
    + +
    +
     
    + +

    + + + + + + + + + + + + +
    + + Subprojects + +
    Add subproject + + + +
    + +

    + + + + + + + + + + + + + +
    + + Comments + +
    + @comments;noquote@ +
      +
    • @comments_link;noquote@ +
    +
     
    + +

    + + + + + + + + + + + + +
    + + Actions + +
    + +  
    + +

    + + + TASKS + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + @task_term@ + +
    @instance_html;noquote@ 
    + +  
    + + +  
    + +

    + + + + + + + + + + + + + + + + + +
    + + Logger + +
    +
    + @variable_widget;noquote@ + @variable_exports;noquote@ + @day_widget;noquote@ + +
    +
     
    + +  
    +

    Index: openacs-4/packages/project-manager/www/one.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/one.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/one.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,508 @@ +ad_page_contract { + Main view page for one project. Also shows logged time, and allows a + user to log time + + @author jader@bread.com, ncarroll@ee.usyd.edu.au + @creation-date 2003-05-15 + @cvs-id $Id: one.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @return context Context bar. + @return versions a multirow holding versions of the project + @return live_revision the project_id of the live_revision + + @param project_name + @param project_code + @param project_folder_id + @param goal + @param description + @param planned_start_date + @param planned_end_date + @param ongoing_p + @param use_goal_p Specifies whether or not to include the goal field 1 = yes + @param use_project_code_p Specifies whether or not to show the user-specified project code 1 = yes + @param use_uncertain_completion_times_p Specifies whether or not to use PERT style uncertainty times 1 = yes + @param logger_days The number of days back to view logged entries + @param instance_id The process instance ID to show for tasks +} { + + project_item_id:integer,optional + project_id:integer,optional + {orderby_subproject ""} + {orderby_tasks ""} + {logger_variable_id:integer ""} + {logger_days:integer "30"} + {instance_id:integer ""} + +} -properties { + categories:onelist + my_title:onevalue + context:onevalue + project:multirow + people:multirow + tasks:multirow + people:multirow + write_p:onevalue + create_p:onevalue + custom:multirow + parent_task_id:onevalue + task_type:onevalue + project_id:onevalue + use_goal_p:onevalue + use_project_code_p:onevalue + use_uncertain_completion_times_P:onevalue + use_project_customizations_p:onevalue + task_term:onevalue + then_ansi:onevalue + edit_url:onevalue + comments:onevalue + comments_link:onevalue +} -validate { + project_exists { + if {![exists_and_not_null project_item_id] && \ + ![exists_and_not_null project_id]} { + + ad_complain "No project passed in" + + } + } + project_item_id_exists { + if {![exists_and_not_null project_item_id] && [exists_and_not_null project_id]} { + set project_item_id [pm::project::get_project_item_id \ + -project_id $project_id] + } + } + project_id_exists { + if {![exists_and_not_null project_id] && [exists_and_not_null project_item_id]} { + set project_id [pm::project::get_project_id \ + -project_item_id $project_item_id] + } + } + logger_days_positive { + if {$logger_days < 1} { + set logger_days 1 + } + } +} + +set original_project_id $project_id + +# for edits of tasks. We want to come back to here. +set return_url [ad_return_url -qualified] + +# --------------------------------------------------------------- # + +# the unique identifier for this package +set package_id [ad_conn package_id] +set package_url [ad_conn package_url] +set user_id [auth::require_login] + + +# terminology and other parameters +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set use_goal_p [parameter::get -parameter "UseGoalP" -default "1"] +set hide_done_tasks_p [parameter::get -parameter "HideDoneTaskP" -default "1"] +set use_project_code_p [parameter::get -parameter "UseUserProjectCodesP" -default "1"] +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] +set use_project_customizations_p [parameter::get -parameter "UseProjectCustomizationsP" -default "0"] +set use_subprojects_p [parameter::get -parameter "UseSubprojectsP" -default "0"] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] + + +set process_instance_options [pm::process::instance_options \ + -project_item_id $project_item_id \ + -process_instance_id $instance_id] + + +set process_reminder_url [export_vars -base process-reminder {instance_id project_item_id return_url}] + +if {[empty_string_p $process_instance_options]} { + set instance_html "" +} else { + + set instance_html " +
    + [export_vars -form -entire_form -exclude {instance_id}] + + +
    " +} + +# we do this so that the list builder templates don't add a where +# clause when instance_id is set. +if {[empty_string_p $instance_id]} { + unset instance_id +} + +# categories + +set categories [list] +set cat_list [category::get_mapped_categories $project_item_id] +foreach cat $cat_list { + lappend categories [category::get_name $cat] +} + +db_1row project_query { } -column_array project + +set richtext_list [list $project(description) $project(mime_type)] + +set project(description) [template::util::richtext::get_property html_value $richtext_list] + +set project_root [db_exec_plsql get_root_folder { }] + +set project(planned_start_date) [lc_time_fmt $project(planned_start_date) "%x"] +set project(planned_end_date) [lc_time_fmt $project(planned_end_date) "%x"] +set project(estimated_finish_date) [lc_time_fmt $project(estimated_finish_date) "%x"] +set project(earliest_finish_date) [lc_time_fmt $project(earliest_finish_date) "%x"] +set project(latest_finish_date) [lc_time_fmt $project(latest_finish_date) "%x"] + +# ---------------- +# general comments +# ---------------- +set comments [general_comments_get_comments -print_content_p 1 -print_attachments_p 1 $project_item_id "[ad_conn url]?project_item_id=$project_item_id"] + +set comments_link "Add comment" + + +# we can also get the link to the logger instance. +set logger_url [pm::util::logger_url] +set logger_project_url "$logger_url?project_id=$project(logger_project)" + +if {![exists_and_not_null logger_variable_id]} { + set logger_variable_id [logger::project::get_primary_variable \ + -project_id $project(logger_project)] +} + +set variable_widget [logger::ui::variable_select_widget \ + -project_id $project(logger_project) \ + -current_variable_id $logger_variable_id \ + -select_name logger_variable_id] + +set variable_exports [export_vars -form -entire_form -exclude {logger_variable_id logger_days }] + +set log_url "${logger_url}log?project_id=$project(logger_project)&pm_project_id=$project_item_id&return_url=$return_url&variable_id=$logger_variable_id" + +# There is no point showing an empty listbox, which happens if the user assigns all roles to himself. Doing it this way avoids another trip to the database. +set select_list_html [pm::role::project_select_list -select_name "role_id" -project_item_id $project_item_id -party_id $user_id] +if {[string compare $select_list_html ""]} { + set assignee_add_self_widget "Add myself as
    [export_vars -form {project_item_id user_id return_url}]$select_list_html
    " + set roles_listbox_p 1 +} else { + set roles_listbox_p 0 +} + +# Only need a 'remove myself' link if you are already assigned +set assigned_p [pm::project::assigned_p -project_item_id $project_item_id -party_id $user_id] +if {$assigned_p} { + set assignee_remove_self_url [export_vars -base project-assign-remove {project_item_id user_id return_url}] +} + +set assignee_edit_url [export_vars -base project-assign-edit {project_item_id return_url}] + +set today_ansi [clock format [clock scan today] -format "%Y-%m-%d"] +set then_ansi [clock format [clock scan "-$logger_days days"] -format "%Y-%m-%d"] + + +set day_widget "Last Days" + + +set my_title "$project_term \#$project_item_id: $project(project_name)" + + +set edit_url "[ad_conn package_url]add-edit?[export_url_vars project_item_id]" + +# set up context bar, needs parent_id +if {[string equal $project(parent_id) $project_root]} { + set context [list "$project(project_name)"] +} else { + set context [list [list "one?project_item_id=$project(parent_id)" "Parent"] "$project(project_name)"] +} + +set processes_html [pm::process::select_html] + +# Tasks, using list-builder --------------------------------- + +# Hide finished tasks. This should be added as a filter, but I did not have time to look it up in the howto. + +if {$hide_done_tasks_p} { + set done_clause "and t.percent_complete < 100" +} else { + set done_clause "" +} + +set process_link "process-use?project_item_id=$project_item_id" + +set default_orderby [pm::project::one_default_orderby] + +if {[exists_and_not_null orderby_tasks]} { + pm::project::one_default_orderby \ + -set $orderby_tasks +} + + +template::list::create \ + -name tasks \ + -multirow tasks \ + -key task_item_id \ + -html {width 100%} \ + -elements { + task_item_id { + label "ID" + } + status_type { + label "Done" + display_template { + + } + } + title { + label "Subject" + display_template "@tasks.title@@tasks.title@" + } + parent_task_id { + label "Dep" + display_template { + @tasks.parent_task_id@ + } + } + priority { + label "Priority" + display_template { + @tasks.priority@ + } + } + slack_time { + label "Slack" + display_template " + + + @tasks.slack_time@ + + " + } + earliest_start { + label "Earliest Start" + display_template "@tasks.earliest_start_pretty@@tasks.earliest_start_pretty@" + } + earliest_finish { + label "Earliest Finish" + display_template "@tasks.earliest_finish_pretty@@tasks.earliest_finish_pretty@" + } + latest_start { + label "Latest Start" + display_template "@tasks.latest_start_pretty@@tasks.latest_start_pretty@" + } + latest_finish { + label "Latest Finish" + display_template "@tasks.latest_finish_pretty@@tasks.latest_finish_pretty@" + } + last_name { + label "Who" + display_template { + + + + + + @tasks.first_names@ @tasks.last_name@ + + + + +
    +
    + } + + } + } \ + -bulk_actions { + "Edit" "task-add-edit" "Edit tasks" + } \ + -bulk_action_export_vars { + project_item_id + {return_url} + } \ + -sub_class { + narrow + } \ + -filters { + project_item_id { + hide_p 1 + } + instance_id { + hide_p 1 + where_clause {ti.process_instance = :instance_id} + } + orderby_subproject { + hide_p 1 + } + orderby_people { + hide_p 1 + } + } \ + -orderby { + default_value $default_orderby + title { + orderby_asc "title asc, task_item_id asc" + orderby_desc "title desc, task_item_id desc" + default_direction asc + } + priority { + orderby_asc "priority, earliest_start, task_item_id asc, u.first_names, u.last_name" + orderby_desc "priority desc, earliest_start desc, task_item_id desc, u.first_names, u.last_name" + default_direction desc + } + earliest_start { + orderby_asc "earliest_start, task_item_id asc, u.first_names, u.last_name" + orderby_desc "earliest_start desc, task_item_id desc, u.first_names, u.last_name" + default_direction asc + } + earliest_finish { + orderby_asc "earliest_finish, task_item_id asc, u.first_names, u.last_name" + orderby_desc "earliest_finish desc, task_item_id desc, u.first_names, u.last_name" + default_direction asc + } + latest_start { + orderby_asc "latest_start, task_item_id asc, u.first_names, u.last_name" + orderby_desc "latest_start desc, task_item_id desc, u.first_names, u.last_name" + default_direction asc + } + latest_finish { + orderby_asc "latest_finish, task_item_id asc, u.first_names, u.last_name" + orderby_desc "latest_finish desc, task_item_id desc, u.first_names, u.last_name" + default_direction asc + } + } \ + -orderby_name orderby_tasks + + +db_multirow -extend { item_url earliest_start_pretty earliest_finish_pretty latest_start_pretty latest_finish_pretty slack_time my_user_id} tasks project_tasks_query { +} { + set item_url [export_vars -base "task-one" { {task_id $task_item_id}}] + + set earliest_start_pretty [lc_time_fmt $earliest_start "%x"] + set earliest_finish_pretty [lc_time_fmt $earliest_finish "%x"] + set latest_start_pretty [lc_time_fmt $latest_start "%x"] + set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] + + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + + set my_user_id $user_id +} + + +if {$use_subprojects_p} { + + # Subprojects, using list-builder --------------------------------- + + db_multirow subproject project_subproject_query { } + + template::list::create \ + -name subproject \ + -multirow subproject \ + -key item_id \ + -elements { + project_name { + label "Subject" + link_url_col item_url + link_html { title "View this subproject" } + } + actual_hours_completed { + label "Hours completed" + } + } \ + -sub_class { + narrow + } \ + -filters { + project_item_id {} + orderby_tasks {} + orderby_people {} + } \ + -orderby { + project_name {orderby project_name} + default_value project_name,desc + } \ + -orderby_name orderby_subproject \ + -html { + width 100% + } + + + + db_multirow -extend { item_url } subproject project_subproject_query { + } { + set item_url [export_vars -base "one" -override {{project_item_id $item_id}} {project_item_id}] + } +} + +# People, using list-builder --------------------------------- + +db_multirow people project_people_query { } + +template::list::create \ + -name people \ + -multirow people \ + -key item_id \ + -elements { + user_name { + label "Who" + display_template { + + @people.user_name@ + + } + } + role_name { + label "Role" + } + } \ + -sub_class { + narrow + } \ + -filters { + party_id {} + orderby_subproject {} + orderby_tasks {} + } \ + -orderby { + role_id {orderby role_id} + default_value role_id,desc + } \ + -orderby_name orderby_subproject \ + -html { + width 100% + } + + +db_multirow -extend { item_url } subproject project_people_query { +} { + +} + + + +# -------------------------CUSTOMIZATIONS-------------------------- +# If there are customizations, put them in a multirow called custom +# ----------------------------------------------------------------- + +db_1row custom_query { } -column_array custom + +set customer_link "[site_node::get_package_url -package_key organizations]one?organization_id=$custom(customer_id)" + +# end of customizations + +ad_return_template +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/process-add-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-add-edit-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-add-edit-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,47 @@ + + + + + select sysdate from dual + + + + + + insert into pm_process + (process_id, + one_line, + description, + party_id, + creation_date) + values + (:process_id, + :one_line, + :description, + :party_id, + :creation_date) + + + + + + update pm_process + set one_line = :one_line, + description = :description, + party_id = :party_id + + + + + + SELECT process_id, + one_line, + description, + party_id, + creation_date + FROM pm_process + WHERE process_id = :process_id + + + + Index: openacs-4/packages/project-manager/www/process-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-add-edit-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-add-edit-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,49 @@ + + + + + select current_timestamp from dual; + + + + + + insert into pm_process + (process_id, + one_line, + description, + party_id, + creation_date) + values + (:process_id, + :one_line, + :description, + :party_id, + :creation_date) + + + + + + update pm_process + set one_line = :one_line, + description = :description, + party_id = :party_id + + + + + + select + process_id, + one_line, + description, + party_id, + creation_date + from + pm_process + where process_id = :process_id + + + + Index: openacs-4/packages/project-manager/www/process-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-add-edit.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,7 @@ + +@context_bar;noquote@ +@title@ + +
    + +
    Index: openacs-4/packages/project-manager/www/process-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-add-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-add-edit.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,94 @@ +ad_page_contract { + + Simple add/edit form for processs + + @author jader@bread.com + @creation-date 2003-09-15 + @cvs-id $Id: process-add-edit.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + +} { + + process_id:integer,optional + {one_line ""} + {description ""} + {number_of_tasks:integer ""} + +} -properties { + + context_bar:onevalue + title:onevalue + +} + + +# --------------------------------------------------------------- # +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# terminology and parameters +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +if {[exists_and_not_null process_id]} { + set title "Edit a Process" + set context_bar [ad_context_bar "Edit Process"] + + # permissions + permission::require_permission -party_id $user_id -object_id $package_id -privilege write +} else { + set title "Add a Process" + set context_bar [ad_context_bar "New Process"] + + # permissions + permission::require_permission -party_id $user_id -object_id $package_id -privilege create +} + + +ad_form -name add_edit -form { + process_id:key + + {one_line:text + {label "Subject"} + {value $one_line} + {html {size 40}} + } + + {description:text(textarea),optional + {label "Description"} + {value $description} + {html { rows 5 cols 40 wrap soft}}} + + {number_of_tasks:text + {label "Number of new tasks"} + {value "1"} + {html {size 5}} + } + +} -select_query_name process_query -on_submit { + + set party_id [ad_conn user_id] + set creation_date [db_string get_today { }] + +} -new_data { + set process_id [db_nextval pm_process_seq] + + db_dml new_process { *SQL* } + + ad_returnredirect -message "Process added. Now add process tasks." "process-task-add-edit?[export_vars -url {{number $number_of_tasks} process_id}]" + ad_script_abort + +} -edit_data { + + db_dml edit_process { *SQL* } + +} -after_submit { + + ad_returnredirect -message "Process changes saved. Now edit process tasks" "process-task-add-edit?[export_vars -url {{number $number_of_tasks} process_id}]" + ad_script_abort +} + + Index: openacs-4/packages/project-manager/www/process-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-delete.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-delete.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,16 @@ + + @title@ + @context@ + +

    + Are you sure you want to delete this process: @one_line@ + +

    + @description@ +
    + +

    + Delete +     + Cancel, do not delete +

    Index: openacs-4/packages/project-manager/www/process-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-delete.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,41 @@ +# + +ad_page_contract { + + Delete a process + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-25 + @arch-tag: e4153029-2cda-462d-b429-8f2b24999580 + @cvs-id $Id: process-delete.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + process_id:integer + {confirm_p:boolean 0} + {return_url "processes"} +} -properties { +} -validate { +} -errors { +} + +set package_id [ad_conn package_id] + + +if {[string is false $confirm_p]} { + + db_1row get_name "select one_line, description from pm_process where process_id = :process_id" + + set title "Delete process: $one_line" + set context [list "Delete: $one_line"] + + set yes_url "process-delete?[export_vars {process_id {confirm_p 1} return_url}]" + set no_url $return_url + + return +} + + +permission::require_permission -object_id $package_id -privilege delete + +pm::process::delete -process_id $process_id + +ad_returnredirect -message "Process deleted" $return_url Index: openacs-4/packages/project-manager/www/process-dependency-add-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-dependency-add-edit-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-dependency-add-edit-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,36 @@ + + + + + SELECT t.process_task_id as task_id, + t.one_line as task_title, + t.description, + d.parent_task_id + FROM pm_process_task t , + pm_process_task_dependency d + WHERE t.process_task_id = d.process_task_id (+) and + t.process_task_id in ([join $use_dependency_list ", "]) + ORDER BY t.ordering, t.process_task_id + + + + + + SELECT short_name, + description + FROM pm_task_dependency_types + ORDER BY short_name + + + + + + SELECT process_task_id as task_id, + one_line as task_title + FROM pm_process_task + WHERE process_id = :process_id + ORDER BY ordering + + + + Index: openacs-4/packages/project-manager/www/process-dependency-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-dependency-add-edit-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-dependency-add-edit-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,45 @@ + + + + + select + t.process_task_id as task_id, + t.one_line as task_title, + t.description, + d.parent_task_id + FROM + pm_process_task t LEFT JOIN pm_process_task_dependency d ON t.process_task_id = d.process_task_id + WHERE + t.process_task_id in ([join $use_dependency_list ", "]) + ORDER BY + t.ordering, t.process_task_id + + + + + + select + short_name, + description + FROM + pm_task_dependency_types + ORDER BY + short_name + + + + + + select + process_task_id as task_id, + one_line as task_title + FROM + pm_process_task + WHERE + process_id = :process_id + ORDER BY + ordering + + + + Index: openacs-4/packages/project-manager/www/process-dependency-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-dependency-add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-dependency-add-edit.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,23 @@ + +@context_bar;noquote@ +@title@ + + +You may now add dependencies to these process +@task_term_lower@s. Dependencies describe the order in which items must +be completed. For example, "the boards must be delivered before +construction can begin". Entering dependencies is important because it +allows the system to automatically compute schedules. However, you can +skip adding dependencies. + +

    + +

    + + + + + +
    + + Index: openacs-4/packages/project-manager/www/process-dependency-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-dependency-add-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-dependency-add-edit.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,221 @@ +ad_page_contract { + + Form to add task dependencies + + @author jader@bread.com + @creation-date 2003-08-06 + @cvs-id $Id: process-dependency-add-edit.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + @return task_term_lower Terminology to use for Task + + @param dependency_id The new ID for dependencies we create + @param use_dependency The tasks for whom we want to create dependencies + +} { + + {use_dependency:array ""} + {use_dependency_list:multiple ""} + process_id:integer + dependency_id:integer,optional + process_task_id:multiple,optional + dependency_type:array,optional + dependency_task_id:array,optional + {project_item_id:integer ""} + +} -properties { + + context_bar:onevalue + title:onevalue + task_term_lower:onevalue + +} + +# --------------------------------------------------------------- # + + +# turn the use_dependency + +if {[llength [array get use_dependency]] > 0} { + foreach {index value} [array get use_dependency] { + lappend use_dependency_list $value + } +} + +# HACK because there isn't a facility for exporting multiple hidden +# form variables in ad_form + +set process_task_id_pass $process_task_id +set process_task_id_pass [string map {"-" " "} $process_task_id_pass] +set process_task_id $process_task_id_pass + +set use_dependency_list_pass $use_dependency_list +set use_dependency_list_pass [string map {"-" " "} $use_dependency_list_pass] +set use_dependency_list $use_dependency_list_pass + + +if {![exists_and_not_null use_dependency_list]} { + pm::process::remove_dependency \ + -process_task_id $process_task_id + + ad_returnredirect "process-one?[export_url_vars process_id]" + ad_script_abort +} + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions + +set title "Add $task_term_lower dependencies" +set context_bar [ad_context_bar [list "process-task-add-edit?[export_vars -url {{process_id process_task_id:multiple}}]" "Assignments"] "New $task_term dependency"] + +permission::require_permission -party_id $user_id -object_id $package_id -privilege create + +set process_task_id_pass [string map {" " "-"} $process_task_id] +set use_dependency_list_pass [string map {" " "-"} $use_dependency_list] + +ad_form -name add_edit -form { + dependency_id:key(pm_process_task_dependency_seq) + + {process_task_id:text(hidden) + {value $process_task_id_pass} + } + + {use_dependency_list:text(hidden) + {value $use_dependency_list_pass} + } + + {process_id:text(hidden) + {value $process_id} + } + + +} -export { + +} -on_submit { + + set user_id [ad_conn user_id] + set peeraddr [ad_conn peeraddr] + +} -new_data { + + # convert from our hack back to a list + set process_task_id [string map {"-" " "} $process_task_id] + + pm::process::remove_dependency \ + -process_task_id $process_task_id + + # convert from our hack back to a list + set use_dependency_list [string map {"-" " "} $use_dependency_list] + + foreach tr $use_dependency_list { + + set type_id $dependency_type($tr) + set parent_tsk_id $dependency_task_id($tr) + + set tsk_revision_id $tr + set tsk_id $tr + + pm::process::add_dependency \ + -process_task_id $tsk_id \ + -parent_task_id $parent_tsk_id \ + -dependency_type_id $type_id + } + +} -edit_data { + + set process_task_id_pass $process_task_id + set process_task_id_pass [string map {"-" " "} $process_task_id_pass] + set process_task_id $process_task_id_pass + + pm::process::remove_dependency -process_task_id $process_task_id + + foreach tr $use_dependency_list { + + set type_id $dependency_type($tr) + set parent_tsk_id $dependency_task_id($tr) + set tsk_revision_id $tr + set tsk_id [db_string get_task_id { }] + + pm::process::add_dependency \ + -process_task_id $tsk_id \ + -parent_task_id $parent_tsk_id \ + -dependency_type_id $type_id + } + +} -after_submit { + + ad_returnredirect -message "Process task dependencies saved" [export_vars -base process-one -url {process_id}] + ad_script_abort +} + +# get dependency types + +#set options [list] +#db_foreach get_dependency_types { } -column_array dependencies { +# lappend options "{\"$dependencies(description)\" $dependencies(short_name)}" +#} + +# set up list of tasks that this task can be depend on + +set dependency_keys [list] + +db_foreach get_dependency_tasks { } -column_array dependency_tasks { + + set dependency_options($dependency_tasks(task_title)) $dependency_tasks(task_id) + + lappend dependency_keys $dependency_tasks(task_title) +} + + + +# get the information on tasks from their task_id numbers + +db_foreach dependency_query { } -column_array tasks { + + # set up the tasks that can be viewed. Takes out the current task + set dependency_options_full [list] + foreach key $dependency_keys { + if {![string equal $key $tasks(task_title)]} { + lappend dependency_options_full [list $key $dependency_options($key)] + } + } + + append add_edit_definition " + {task_id.$tasks(task_id):text(hidden) + {value {$tasks(task_id)}} + } + + {task_title.$tasks(task_id):text(hidden) + {section {$tasks(task_title)}} + {label \"Subject\"} + {value {$tasks(task_title)}} + } + + {description.$tasks(task_id):text(inform) + {label \"Description\"} + {value {$tasks(description)}} + } + + {dependency_type.$tasks(task_id):text(hidden) + {value {finish_before_start}} + } + + {dependency_task_id.$tasks(task_id):text(select) + {label \"Dependency\"} + {options {$dependency_options_full}} + {value {$tasks(parent_task_id)}} + {help_text {$task_term the dependency is based on}} + } + " +} + + +ad_form -extend -name add_edit -form $add_edit_definition Index: openacs-4/packages/project-manager/www/process-instance-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instance-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instance-edit-2.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,30 @@ +# + +ad_page_contract { + + Processes the process instance changes + + @author (jader-ibr@bread.com) + @creation-date 2004-11-05 + @arch-tag: 6d8d980e-c28f-4333-874b-4e71c3803ffd + @cvs-id $Id: process-instance-edit-2.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + instance_id:integer,notnull + my_name:notnull + process_id:integer,notnull +} -properties { +} -validate { +} -errors { +} + +set user_id [auth::require_login] +set package_id [ad_conn package_id] + +permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege write + +db_dml change_process_instance { } + +ad_returnredirect -message "Saved change of process instance name" process-instances?process_id=$process_id Index: openacs-4/packages/project-manager/www/process-instance-edit-2.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instance-edit-2.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instance-edit-2.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,21 @@ + + + + + + + + + + + + UPDATE + pm_process_instance + SET + name = :my_name + WHERE + instance_id = :instance_id + + + + Index: openacs-4/packages/project-manager/www/process-instance-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instance-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instance-edit.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,11 @@ + + @title@ + @context@ + + +
    + + + + +
    Index: openacs-4/packages/project-manager/www/process-instance-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instance-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instance-edit.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,23 @@ +# + +ad_page_contract { + + Allows a user to edit a process instance name + + @author (jader-ibr@bread.com) + @creation-date 2004-11-05 + @arch-tag: c792123e-8a76-4b61-829f-932f176be045 + @cvs-id $Id: process-instance-edit.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + instance_id:integer,notnull +} -properties { +} -validate { +} -errors { +} + +db_1row get_instance { } + +set title "Edit process instance" +set context [list [list "Processes" processes ] [list "Process instances" "process-instances?process_id=$process_id"] $title] + + Index: openacs-4/packages/project-manager/www/process-instance-edit.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instance-edit.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instance-edit.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,22 @@ + + + + + + + + + + + + SELECT + i.name, + i.process_id + FROM + pm_process_instance i + WHERE + i.instance_id = :instance_id + + + + Index: openacs-4/packages/project-manager/www/process-instances.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instances.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instances.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,6 @@ + + @title@ + @header_stuff@ + @context@ + + Index: openacs-4/packages/project-manager/www/process-instances.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instances.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instances.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,73 @@ +# + +ad_page_contract { + + Lists all the process instances of a given process_id + + @author (ibr@test) + @creation-date 2004-11-05 + @arch-tag: 57bfd18d-a3e5-4047-8185-06707c42f058 + @cvs-id $Id: process-instances.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + process_id:integer,notnull +} -properties { +} -validate { +} -errors { +} + + +# set up context bar +set title "Process Instances" +set context [list [list "Processes" processes] $title] +set header_stuff "" + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +# Processes, using list-builder --------------------------------- + +template::list::create \ + -name instances \ + -multirow instances \ + -key instance_id \ + -elements { + edit { + display_template { + + Edit + + } + } + instance_id { + label "ID" + } + name { + label "Name" + } + project_item_id { + label "Project" + display_template { + @instances.project_name@ + } + } + active_tasks { + label "Active tasks" + } + } \ + -main_class { + narrow + } \ + -html { + width 100% + } + + +db_multirow -extend { delete_url creation_date } instances instances_query { +} { + set delete_url [export_vars -base "process-delete" {process_id}] +} + Index: openacs-4/packages/project-manager/www/process-instances.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-instances.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-instances.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,38 @@ + + + + + + + + + + + + SELECT + i.name, + i.instance_id, + i.project_item_id, + projectr.title as project_name, + (select count(*) + from + pm_tasks_active t, + pm_task_status s + where + t.status = s.status_id and + s.status_type = 'o' and + t.process_instance = i.instance_id) as active_tasks + FROM + pm_process_instance i, + cr_items projecti, + cr_revisions projectr + WHERE + i.process_id = :process_id and + i.project_item_id = projecti.item_id and + projecti.live_revision = projectr.revision_id + ORDER BY + i.instance_id desc + + + + Index: openacs-4/packages/project-manager/www/process-one-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-one-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-one-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,22 @@ + + + + + + SELECT t.process_task_id, + t.one_line, + t.description, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + d.dependency_type, + t.ordering + FROM pm_process_task t , + pm_process_task_dependency d + WHERE t.process_task_id = d.process_task_id (+) and + t.process_id = :process_id + [template::list::orderby_clause -orderby -name tasks] + + + + Index: openacs-4/packages/project-manager/www/process-one-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-one-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-one-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,40 @@ + + + + + + SELECT + t.process_task_id, + t.one_line, + t.description, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + d.dependency_type, + t.ordering, + p.first_names, + p.last_name, + p.person_id + FROM + pm_process_task t + LEFT JOIN + pm_process_task_assignment a + ON + t.process_task_id = a.process_task_id + LEFT JOIN + pm_roles r + ON r.role_id = a.role_id + LEFT JOIN + persons p + ON p.person_id = a.party_id + LEFT JOIN + pm_process_task_dependency d + ON t.process_task_id = d.process_task_id + WHERE + t.process_id = :process_id and + (r.is_lead_p = 't' or r.is_lead_p is null) + [template::list::orderby_clause -orderby -name tasks] + + + + Index: openacs-4/packages/project-manager/www/process-one.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-one.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-one.adp 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,25 @@ + + + + +One process +@context_bar;noquote@ + +Process tasks: + +
      +
    • Use all tasks in this process: @use_link;noquote@

      +

    • +
      + Add + + + new task(s) to this process + +
      +
    • +
    + + + + Index: openacs-4/packages/project-manager/www/process-one.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-one.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-one.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,121 @@ +ad_page_contract { + Main view page for one process + + @author jader@bread.com + @creation-date 2003-09-25 + @cvs-id $Id: process-one.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ + + @param process_id The process we're looking at. + + @return process_id the id for the process + @return context_bar Context bar. + @return use_link the link to use this process + +} { + + process_id:integer,notnull + orderby:optional + {project_item_id ""} + +} -properties { + process_id:onevalue + context_bar:onevalue + use_link:onevalue +} -validate { +} -errors { + process_id:notnull {You must specify a process to use. Please back up and select a process} +} + +# --------------------------------------------------------------- + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] + +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + +# set up context bar, needs parent_id + +set context_bar [ad_context_bar [list "processes?process_id=$process_id" "Processes"] "One"] + +set use_link "" + + +set elements \ + [list \ + one_line { + label "Subject" + display_template {@tasks.one_line@ + + + + + + + + + + + + + } + } \ + description { + label "Description" + } \ + person_id { + label "Lead" + display_template { + + @tasks.first_names@ @tasks.last_name@
    +
    + } + }] + + +# Process tasks, using list-builder --------------------------------- + +template::list::create \ + -name tasks \ + -multirow tasks \ + -key process_task_id \ + -elements $elements \ + -orderby { + default_value ordering,asc + ordering { + label "Order" + orderby_asc "t.ordering, t.process_task_id, p.first_names, p.last_name" + orderby_desc "t.ordering desc, t.process_task_id desc, p.first_names, p.last_name" + default_direction asc + } + } \ + -bulk_actions { + "Use" "task-select-project" "Use process" + "Edit" "process-task-add-edit" "Edit tasks" + "Delete" "process-task-delete" "Delete tasks" + } \ + -bulk_action_export_vars { + process_id + project_item_id + } \ + -sub_class { + narrow + } \ + -filters { + process_id {} + } \ + -html { + width 100% + } + + +db_multirow -extend { item_url } tasks task_query { +} { +} + Index: openacs-4/packages/project-manager/www/process-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,17 @@ + + +postgresql7.3 + + + + SELECT p.process_id, + p.one_line, + p.description, + p.party_id, + to_char(p.creation_date,'YYYY-MM-DD') as creation_date_ansi + FROM pm_process p + ORDER BY p.one_line + + + + Index: openacs-4/packages/project-manager/www/process-reminder.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-reminder.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-reminder.tcl 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,25 @@ +# + +ad_page_contract { + + Sends out a process status update + + @author (jader-ibr@bread.com) + @creation-date 2004-11-18 + @arch-tag: 1a2152ed-1746-4d03-b191-b00c3fb32731 + @cvs-id $Id: process-reminder.tcl,v 1.1 2005/04/29 17:43:37 timoh Exp $ +} { + instance_id:integer,notnull + project_item_id:integer,notnull + return_url:notnull +} -properties { +} -validate { +} -errors { +} + +pm::process::email_alert \ + -process_instance_id $instance_id \ + -project_item_id $project_item_id \ + -new_p f + +ad_returnredirect -message "Status update sent" $return_url Index: openacs-4/packages/project-manager/www/process-task-add-edit-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit-2-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit-2-oracle.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,47 @@ + + + + + INSERT into pm_process_task + (process_task_id, + process_id, + one_line, + description, + estimated_hours_work, + estimated_hours_work_min, + estimated_hours_work_max, + ordering) + values + (:task_id, + :process_id, + :one_line, + :desc, + :work, + :work_min, + :work_max, + :order) + + + + + + UPDATE pm_process_task + SET one_line = :one_line, + description = :desc, + estimated_hours_work = :work, + estimated_hours_work_min = :work_min, + estimated_hours_work_max = :work_max, + ordering = :order + WHERE process_task_id = :task_id + + + + + + SELECT count(*) + FROM pm_process_task + WHERE process_task_id in ([join $process_task_id ","]) + + + + Index: openacs-4/packages/project-manager/www/process-task-add-edit-2-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit-2-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit-2-postgresql.xql 29 Apr 2005 17:43:37 -0000 1.1 @@ -0,0 +1,48 @@ + + + + + insert into + pm_process_task + (process_task_id, + process_id, + one_line, + description, + estimated_hours_work, + estimated_hours_work_min, + estimated_hours_work_max, + ordering) + values + (:task_id, + :process_id, + :one_line, + :desc, + :work, + :work_min, + :work_max, + :order) + + + + + + update pm_process_task set + one_line = :one_line, + description = :desc, + estimated_hours_work = :work, + estimated_hours_work_min = :work_min, + estimated_hours_work_max = :work_max, + ordering = :order + where + process_task_id = :task_id + + + + + + select count(*) from pm_process_task where + process_task_id in ([join $process_task_id ","]) + + + + Index: openacs-4/packages/project-manager/www/process-task-add-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit-2.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,233 @@ +ad_page_contract { + + Add/edit form for process tasks, page 2 + + @author jader@bread.com + @creation-date 2003-09-29 + @cvs-id $Id: process-task-add-edit-2.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @param process_id The process that we're adding or editing items for. + @param task_title The titles of the tasks + @param estimated_hours_work Estimated hours worked + @param estimated_hours_work Estimated hours worked (min) + @param estimated_hours_work Estimated hours worked (max) + @param process_task_id the ID for each process + @param use_dependency this task will depend on others + +} { + + process_id:integer,notnull + {task_title:array ""} + {description:array ""} + {estimated_hours_work:array ""} + {estimated_hours_work_min:array ""} + {estimated_hours_work_max:array ""} + {estimated_days_work:array ""} + {estimated_days_work_min:array ""} + {estimated_days_work_max:array ""} + {ordering:array ""} + {assignee:multiple ""} + process_task_id:integer,multiple + {use_dependency:array ""} + +} -validate { + process_id_missing { + if {![exists_and_not_null process_id]} { + ad_complain + } + } + task_title_too_long { + foreach {index tt} [array get task_title] { + if {[string length $tt] > 198} { + ad_complain + } + } + } + description_too_long { + foreach {index d} [array get description] { + if {[string length $d] > 3998} { + ad_complain + } + } + } + description_empty { + foreach {index d} [array get description] { + if {[empty_string_p $d]} { + ad_complain + } + } + } + bad_estimated_hours_work_range { + foreach {index wr} [array get estimated_hours_work] { + if {$wr > 500 || $wr < 0} { + ad_complain + } + } + } + process_task_id_missing { + foreach ptid $process_task_id { + if {![exists_and_not_null ptid]} { + ad_complain + } + } + } +} -errors { + process_id_missing {I don't know which process these tasks are for!} + task_title_too_long {A task subject is too long. It must be 198 characters or less} + description_too_long {A description subject is too long. It must be 3998 characters or less} + description_empty {The description may not be empty} + bad_estimated_hours_work_range {The estimated hours must be between 0 and 499 hours} + process_task_id_missing {I don't know which process task is being added or edited!} +} + + +set user_id [auth::require_login] +set package_id [ad_conn package_id] + +permission::require_permission -party_id $user_id -object_id $package_id -privilege create + +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + +set use_days_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] +set hours_day [pm::util::hours_day] + +# ------------------------------------------------------------ +# we need to determine if these tasks are new or being edited. +# we know this by checking if the numbers exist. +# we assume that if any of them exist, that we're editing. +# ------------------------------------------------------------ + +set edit_p [db_string editing_process_tasks_p { } -default "0"] + + +if {[string is false $edit_p]} { + + # ----------------------------- + # if we're adding process tasks + # ----------------------------- + + set index 0 + set array_index 0 + + foreach ptid $process_task_id { + + set array_index [expr $index +1] + + # set up the values + set task_id [lindex $process_task_id $index] + + set one_line $task_title($array_index) + set desc $description($array_index) + set order $ordering($array_index) + + if {[string is true $use_days_p]} { + if {[string is true $use_uncertain_completion_times_p]} { + set work_min [expr $estimated_days_work_min($array_index) * $hours_day] + set work_max [expr $estimated_days_work_max($array_index) * $hours_day] + set work [expr .5 * [expr $work_max - $work_min] + $work_min] + } else { + set work [expr $estimated_hours_work($array_index) * $hours_day] + set work_min $work + set work_max $work + } + } else { + if {[string is true $use_uncertain_completion_times_p]} { + set work_min $estimated_hours_work_min($array_index) + set work_max $estimated_hours_work_max($array_index) + set work [expr .5 * [expr $work_max - $work_min] + $work_min] + } else { + set work $estimated_hours_work($array_index) + set work_min $work + set work_max $work + } + } + + db_dml new_task { *SQL* } + incr index + } +} else { + + # ----------------------------- + # if we're editing process tasks + # ----------------------------- + + # ----------------------------- + # if we're adding process tasks + # ----------------------------- + + set index 0 + set array_index 0 + + foreach ptid $process_task_id { + + set array_index [expr $index +1] + + # set up the values + set task_id [lindex $process_task_id $index] + + set one_line $task_title($array_index) + set desc $description($array_index) + set order $ordering($array_index) + + if {[string is true $use_days_p]} { + if {[string is true $use_uncertain_completion_times_p]} { + set work_min [expr $estimated_days_work_min($array_index) * $hours_day] + set work_max [expr $estimated_days_work_max($array_index) * $hours_day] + set work [expr .5 * [expr $work_max - $work_min] + $work_min] + } else { + set work [expr $estimated_hours_work($array_index) * $hours_day] + set work_min $work + set work_max $work + } + } else { + if {[string is true $use_uncertain_completion_times_p]} { + set work_min $estimated_hours_work_min($array_index) + set work_max $estimated_hours_work_max($array_index) + set work [expr .5 * [expr $work_max - $work_min] + $work_min] + } else { + set work $estimated_hours_work($array_index) + set work_min $work + set work_max $work + } + } + + db_dml edit_task { *SQL* } + incr index + } +} + + +# remove assignments +foreach ptid $process_task_id { + + pm::process::remove_assignees \ + -process_task_id $process_task_id + +} + +foreach ass $assignee { + + regexp {(.*)-(.*)-(.*)} $ass match process_task party_id role_id + + pm::process::assign \ + -process_task_id $process_task \ + -party_id $party_id \ + -role_id $role_id + +} + +if {[llength $process_task_id] > 1} { + set task_tasks tasks +} else { + set task_tasks task +} + +if {[llength [array get use_dependency]] > 0} { + set dep_msg "Now set up dependencies" +} else { + set dep_msg "" +} + +ad_returnredirect -message "Process $task_tasks saved. $dep_msg" "process-dependency-add-edit?[export_vars -url {process_task_id:multiple process_id use_dependency:array}]" + +ad_script_abort Index: openacs-4/packages/project-manager/www/process-task-add-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,24 @@ + + + + + + SELECT t.process_task_id as pti, + t.one_line, + t.description, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + d.dependency_type, + t.ordering + FROM pm_process_task t , + pm_process_task_dependency d + WHERE t.process_task_id = d.process_task_id (+) and + t.process_task_id in ([join $process_task_id ", "]) + ORDER BY t.ordering, + t.process_task_id + + + + + Index: openacs-4/packages/project-manager/www/process-task-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,28 @@ + + + + + + SELECT + t.process_task_id as pti, + t.one_line, + t.description, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + d.dependency_type, + t.ordering + FROM + pm_process_task t + LEFT JOIN + pm_process_task_dependency d + ON t.process_task_id = d.process_task_id + WHERE + t.process_task_id in ([join $process_task_id ", "]) + ORDER BY + t.ordering, t.process_task_id + + + + + Index: openacs-4/packages/project-manager/www/process-task-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,103 @@ + + @context_bar;noquote@ + @title@ + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     @num.rownum@  Subject:*

    + + Description:
    +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Work required:*
    Min: days
    Max: days
    days
    Min: hrs
    Max: hrs
    hrs
    + +

    + + + depends on another @task_term_lower@ + +

    + + Order + + +
    + + +

    @num.assignee_html;noquote@
    +
    Index: openacs-4/packages/project-manager/www/process-task-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-add-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-add-edit.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,205 @@ +ad_page_contract { + + Add/edit form for process tasks + + @author jader@bread.com + @creation-date 2003-09-25 + @cvs-id $Id: process-task-add-edit.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + @return process_id The process we're adding/editing tasks for + + @return num used as a multirow datasource to iterate over the form elements + + @param process_id The process that we're adding or editing items for. + @param number The number of Tasks to create + + @param process_task_id If we are editing tasks, this will be the value we receive +} { + + process_id:integer,notnull + {number:integer "1"} + {process_task_id:integer,multiple ""} + +} -properties { + + context_bar:onevalue + onevalue:multirow + title:onevalue + process_id:onevalue + num:multirow + use_uncertain_completion_times_p:onevalue + +} -validate { + number_is_in_range -requires {number:integer} { + # todo: make 100 a parameter + if {$number < 1 || $number > 100} { + ad_complain + } + } +} -errors { + number_is_in_range {Number must be between 1 and 100} +} + +# --------------------------------------------------------------- # + +# -------------------------- +# terminology and parameters +# -------------------------- + +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] +set use_day_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] + +set DEFAULT_ORDERING_GAP 5 + +# -------------------------------------- +# the unique identifier for this package +# -------------------------------------- + +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# ------------------------------------------------------------ +# if process_task_id is set, then we are editing process tasks +# ------------------------------------------------------------ + +if {[exists_and_not_null process_task_id]} { + + set edit_p 1 + set title "Edit a process $task_term_lower" + set context_bar [ad_context_bar [list "process-one?process_id=$process_id" "Process"] "Edit tasks"] + permission::require_permission -party_id $user_id -object_id $package_id -privilege write + + set process_tasks [list] + set i 1 + + db_foreach get_process_tasks { } { + set process_task_v($i) $pti + set one_line_v($i) $one_line + set description_v($i) $description + set estimated_hours_work_v($i) $estimated_hours_work + set estimated_hours_work_min_v($i) $estimated_hours_work_min + set estimated_hours_work_max_v($i) $estimated_hours_work_max + set ordering_v($i) $ordering + + set estimated_days_work_v($i) [pm::util::days_work \ + -hours_work $estimated_hours_work] + set estimated_days_work_min_v($i) [pm::util::days_work \ + -hours_work $estimated_hours_work_min] + set estimated_days_work_max_v($i) [pm::util::days_work \ + -hours_work $estimated_hours_work_max] + + if {[empty_string_p $ordering_v($i)]} { + set ordering_v($i) [expr $i * $DEFAULT_ORDERING_GAP] + } + + if {[exists_and_not_null dependency_type]} { + set checked_v($i) "checked" + } else { + set checked_v($i) "" + } + + lappend process_tasks $pti + incr i + } + set number [llength $process_tasks] +} else { + + set edit_p 0 + set title "Add a process $task_term_lower" + set context_bar [ad_context_bar [list "process-one?process_id=$process_id" "Process"] "Add tasks"] + permission::require_permission -party_id $user_id -object_id $package_id -privilege create + + for {set i 1} {$i <= $number} {incr i} { + set process_task_v($i) "" + set one_line_v($i) "" + set description_v($i) "" + set estimated_hours_work_v($i) "" + set estimated_hours_work_min_v($i) "" + set estimated_hours_work_max_v($i) "" + set estimated_days_work_v($i) "" + set estimated_days_work_min_v($i) "" + set estimated_days_work_max_v($i) "" + set ordering_v($i) [expr $i * $DEFAULT_ORDERING_GAP] + set checked_v($i) "" + } +} + + +# set up assignees and roles + +set roles_list_of_lists [pm::role::select_list_filter] + +set assignee_list_of_lists [pm::util::subsite_assignees_list_of_lists] + + +template::multirow create num process_task_id one_line description work work_min work_max work_days work_days_min work_days_max ordering checked assignee_html + +for {set i 1} {$i <= $number} {incr i} { + + if {[string is false $edit_p]} { + set process_task_id_tmp [db_nextval pm_process_task_seq] + } else { + set process_task_id_tmp [lindex $process_task_id [expr $i-1]] + + # remember all the assignees for this task + db_foreach assignee_query { + SELECT + a.party_id, + a.role_id + FROM + pm_process_task_assignment a + WHERE + a.process_task_id = :process_task_id_tmp + ORDER BY + a.role_id + } { + set assigned($process_task_id_tmp-$party_id-$role_id) 1 + } + + } + + # we set up the assignments by using this convention: + # {process_task_id}-{party_id}-{role_id} + + set html "" + + foreach role_list $roles_list_of_lists { + + set role_name [lindex $role_list 0] + set role [lindex $role_list 1] + + append html " + " + + } + + append html "

    Assignee: $role_name

    " + + foreach assignee_list $assignee_list_of_lists { + set name [lindex $assignee_list 0] + set person_id [lindex $assignee_list 1] + + if {[exists_and_not_null assigned($process_task_id_tmp-$person_id-$role)]} { + set checked "checked" + } else { + set checked "" + } + + append html " + $name +
    + " + + } + + append html "

    " + + template::multirow append num $process_task_id_tmp $one_line_v($i) $description_v($i) $estimated_hours_work_v($i) $estimated_hours_work_min_v($i) $estimated_hours_work_max_v($i) $estimated_days_work_v($i) $estimated_days_work_min_v($i) $estimated_days_work_max_v($i) $ordering_v($i) $checked_v($i) $html + +} + + Index: openacs-4/packages/project-manager/www/process-task-assign-add-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-assign-add-edit-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-assign-add-edit-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,75 @@ + + + + + SELECT one_line, + description, + process_task_id + FROM pm_process_task + WHERE process_task_id in ([join $process_task_id ","]) + ORDER BY process_task_id + + + + + + SELECT p.first_names || ' ' || p.last_name as who, + p.person_id + FROM persons p, + acs_rels r, + membership_rels mr + WHERE r.object_id_one = :user_group_id and + mr.rel_id = r.rel_id and + p.person_id = r.object_id_two and + member_state = 'approved' + ORDER BY p.first_names, + p.last_name + + + + + + SELECT one_line, + role_id + FROM pm_roles + ORDER BY sort_order + + + + + + DELETE from pm_process_task_assignment + WHERE process_task_id in ([join $process_task_id ","]) + + + + + + INSERT into pm_process_task_assignment + (process_task_id, + role_id, + party_id) + VALUES + (:t_id, + :r_id, + :p_id) + + + + + + SELECT party_id + FROM pm_process_task_assignment + WHERE process_task_id = :tiid + + + + + + SELECT role_id + FROM pm_process_task_assignment a + WHERE process_task_id = :tiid + + + + Index: openacs-4/packages/project-manager/www/process-task-assign-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-assign-add-edit-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-assign-add-edit-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,91 @@ + + + + + select + one_line, + description, + process_task_id + FROM + pm_process_task + WHERE + process_task_id in ([join $process_task_id ","]) + ORDER BY + process_task_id + + + + + + select + p.first_names || ' ' || p.last_name as who, + p.person_id + FROM + persons p, + acs_rels r, + membership_rels mr + WHERE + r.object_id_one = :user_group_id and + mr.rel_id = r.rel_id and + p.person_id = r.object_id_two and + member_state = 'approved' + ORDER BY + p.first_names, p.last_name + + + + + + select + one_line, + role_id + FROM + pm_roles + ORDER BY + sort_order + + + + + + delete from pm_process_task_assignment + where process_task_id in ([join $process_task_id ","]) + + + + + + insert into pm_process_task_assignment + (process_task_id, + role_id, + party_id) + values + (:t_id, + :r_id, + :p_id) + + + + + + select + party_id + FROM + pm_process_task_assignment + WHERE + process_task_id = :tiid + + + + + + select + role_id + FROM + pm_process_task_assignment a + WHERE + process_task_id = :tiid + + + + Index: openacs-4/packages/project-manager/www/process-task-assign-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-assign-add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-assign-add-edit.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,52 @@ + + @context_bar;noquote@ + @title@ + + +
    + + + + + + + + + + + + + + +
    @tasks.one_line@
    + + + + + Error + + + + + + + +
    +
    +
    + +
    + +

    + + + + + +

    + + Index: openacs-4/packages/project-manager/www/process-task-assign-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-assign-add-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-assign-add-edit.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,335 @@ +ad_page_contract { + + Form to add in assignments to process tasks + + @author jader@bread.com + @creation-date 2003-09-25 + @cvs-id $Id: process-task-assign-add-edit.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + @return process_id The process we're adding/editing tasks for + + @return num used as a multirow datasource to iterate over the form elements + + @param process_id The process that we're adding or editing items for. + @param process_task_id The tasks we're creating and adding assignments for + @param use_dependency A list of tasks that will need dependencies. Needs to be passed to the depedency page. +} { + + my_key:integer,optional + process_id:integer,notnull + process_task_id:notnull,multiple + {use_dependency:multiple ""} + role_id:array,optional + party_id:array,optional + +} -properties { + + context_bar:onevalue + title:onevalue + process_id:onevalue + tasks:multirow + num:multirow + task_term_lower:onevalue + +} -validate { +} -errors { +} + +# --------------------------------------------------------------- # + + +# hack to get around lack of multiple hidden support with ad_form + +set process_task_id_pass $process_task_id +set process_task_id_pass [string map {"-" " "} $process_task_id_pass] +set process_task_id $process_task_id_pass + +set use_dependency_pass $use_dependency +set use_dependency_pass [string map {"-" " "} $use_dependency_pass] +set use_dependency $use_dependency_pass + + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] + + +# the unique identifier for this package +set package_id [ad_conn package_id] +set subsite_id [ad_conn subsite_id] +set user_id [ad_maybe_redirect_for_registration] + +set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + + +# permissions and more + +set title "Add a process $task_term_lower (assignment)" +set context_bar [ad_context_bar [list "processes?process_id=$process_id" "Processes"] "Add assignment"] +permission::require_permission -party_id $user_id -object_id $package_id -privilege create + + +set user_id [ad_conn user_id] +set peeraddr [ad_conn peeraddr] + +db_multirow tasks get_tasks { + set description [ad_text_to_html -- $description] +} + + + +# create a multirow we can use to iterate +template::multirow create num number + +# currently hardcoded the number of assignments + +for {set i 0} {$i <= 5} {incr i} { + template::multirow append num $i +} + + + +set users_lofl "{{--Select Person--} {}} " +append users_lofl [db_list_of_lists get_users { }] + + +set roles_lofl "{{--Select Role--} {}} " +append roles_lofl [db_list_of_lists get_roles { }] + + +set process_task_id_pass $process_task_id +set process_task_id_pass [string map {" " "-"} $process_task_id] + +set use_dependency_pass $use_dependency +set use_dependency_pass [string map {" " "-"} $use_dependency] + + +ad_form -name add_edit -form { + + my_key:key(acs_object_id_seq) + + {process_id:text(hidden) + {value $process_id}} + + {process_task_id:text(hidden) + {value $process_task_id_pass}} + + {use_dependency:text(hidden) + {value $use_dependency_pass}} + + +} -on_submit { + + set user_id [ad_conn user_id] + set peeraddr [ad_conn peeraddr] + +} -new_data { + + #role_id + #party_id + + if {[info exists role_id]} { + + set searchToken [array startsearch role_id] + + while {[array anymore role_id $searchToken]} { + + set keyname [array nextelement role_id $searchToken] + set keyvalu $role_id($keyname) + + # keyname looks like 2308.1 - 2308.10 + # first element is task_id, second is 1-10 + # if keyvalu is not empty, then we pay attention to it. + + if {[exists_and_not_null keyvalu]} { + + regexp {(.*)\.(.*)} $keyname match task_id_val num_value + + set assignment_role($task_id_val,$num_value) $keyvalu + + } + } + + } + + set party_list [list] + + if {[info exists party_id]} { + + set searchToken [array startsearch party_id] + + while {[array anymore party_id $searchToken]} { + + set keyname [array nextelement party_id $searchToken] + set keyvalu $party_id($keyname) + + # keyname looks like 2308.1 - 2308.10 + # first element is task_id, second is 1-10 + # if keyvalu is not empty, then we pay attention to it. + + if {[exists_and_not_null keyvalu]} { + + regexp {(.*)\.(.*)} $keyname match task_id_val num_value + + set assignment_party($task_id_val,$num_value) $keyvalu + + lappend party_list "$task_id_val,$num_value" + + } + } + + } + + set process_task_id_pass $process_task_id + set process_task_id_pass [string map {"-" " "} $process_task_id_pass] + set process_task_id $process_task_id_pass + + db_dml delete_assignments { } + + foreach pl $party_list { + + regexp {(.*),(.*)} $pl match task_id_v num_value + + set t_id $task_id_v + set r_id $assignment_role($pl) + set p_id $assignment_party($pl) + + db_dml add_assignment { } + + } + +} -edit_data { + + # do something + #role_id + #party_id + + if {[info exists role_id]} { + + set searchToken [array startsearch role_id] + + while {[array anymore role_id $searchToken]} { + + set keyname [array nextelement role_id $searchToken] + set keyvalu $role_id($keyname) + + # keyname looks like 2308.1 - 2308.10 + # first element is task_id, second is 1-10 + # if keyvalu is not empty, then we pay attention to it. + + if {[exists_and_not_null keyvalu]} { + + regexp {(.*)\.(.*)} $keyname match task_id_val num_value + + set assignment_role($task_id_val,$num_value) $keyvalu + + } + } + + } + + set party_list [list] + + if {[info exists party_id]} { + + set searchToken [array startsearch party_id] + + while {[array anymore party_id $searchToken]} { + + set keyname [array nextelement party_id $searchToken] + set keyvalu $party_id($keyname) + + # keyname looks like 2308.1 - 2308.10 + # first element is task_id, second is 1-10 + # if keyvalu is not empty, then we pay attention to it. + + if {[exists_and_not_null keyvalu]} { + + regexp {(.*)\.(.*)} $keyname match task_id_val num_value + + set assignment_party($task_id_val,$num_value) $keyvalu + + lappend party_list "$task_id_val,$num_value" + + } + } + + } + + set process_task_id_pass $process_task_id + set process_task_id_pass [string map {"-" " "} $process_task_id_pass] + set process_task_id $process_task_id_pass + + db_dml delete_assignments { } + + foreach pl $party_list { + + regexp {(.*),(.*)} $pl match task_id_v num_value + + set t_id $task_id_v + set r_id $assignment_role($pl) + set p_id $assignment_party($pl) + + db_dml add_assignment { } + + } + +} -after_submit { + + # for some reason this hack is necessary here + + set process_task_id_pass $process_task_id + set process_task_id_pass [string map {"-" " "} $process_task_id_pass] + set process_task_id $process_task_id_pass + + + #set task_revisions $revision_has_dependencies + + ad_returnredirect "process-dependency-add-edit?[export_vars -url {process_task_id:multiple process_id use_dependency:multiple}]" + ad_script_abort +} + + +# we create a terrible monster array + +foreach tiid $process_task_id { + + set roles_values [db_list_of_lists get_current_roles { }] + set users_values [db_list_of_lists get_current_users { }] + + set users_length [string length $users_values] + set roles_length [string length $roles_values] + + for {set i 0} {$i <= 10} {incr i} { + + if {$i < $users_length && $i < $roles_length} { + set uv [lindex $users_values $i] + set rv [lindex $roles_values $i] + } else { + set uv "" + set rv "" + } + + ad_form -extend -name add_edit -form \ + [list \ + [list \ + party_id.$tiid.$i:text(select) \ + {label "Assignments \#$i $tiid"} \ + {options {[set users_lofl]}} \ + {values $uv} \ + ] \ + [list \ + role_id.$tiid.$i:text(select) \ + {label "Role \#$i $tiid"} \ + {options {[set roles_lofl]}} \ + {values $rv} \ + ] \ + ] + + } +} + + Index: openacs-4/packages/project-manager/www/process-task-delete-2-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-delete-2-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-delete-2-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,12 @@ + + + + + + DELETE FROM pm_process_task + WHERE process_task_id in ([join $process_task_id ", "]) + + + + + Index: openacs-4/packages/project-manager/www/process-task-delete-2-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-delete-2-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-delete-2-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,14 @@ + + + + + + DELETE FROM + pm_process_task + WHERE + process_task_id in ([join $process_task_id ", "]) + + + + + Index: openacs-4/packages/project-manager/www/process-task-delete-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-delete-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-delete-2.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,24 @@ +ad_page_contract { + + Delete of process tasks + + @author jader@bread.com + @creation-date 2003-10-08 + @cvs-id $Id: process-task-delete-2.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + +} { + process_id:integer + process_task_id:multiple,verify +} + +# --------------------------------------------------------------- # +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege write + +db_dml delete_process_tasks { } + +ad_returnredirect -message "Process task deleted" "process-one?[export_vars -url {process_id}]" Index: openacs-4/packages/project-manager/www/process-task-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-delete.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-delete.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,17 @@ + +@context_bar;noquote@ +@title@ + + +
    + +
    + +Are you sure you'd like to delete these @task_term_lower@s? + + +@hidden_vars;noquote@ + +
    + +
    Index: openacs-4/packages/project-manager/www/process-task-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-task-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-task-delete.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,41 @@ +ad_page_contract { + + Confirm delete of process tasks + + @author jader@bread.com + @creation-date 2003-10-08 + @cvs-id $Id: process-task-delete.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return task_term_lower What to call tasks + @return context_bar Context bar. + @return title Page title. + +} { + + process_id:integer,optional + process_task_id:integer,multiple,notnull + +} -properties { + + hidden_vars:onevalue + task_term_lower:onevalue + context_bar:onevalue + title:onevalue + +} + +# --------------------------------------------------------------- # +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# terminology +set task_term_lower [parameter::get -parameter "taskname" -default "task"] + +set title "Delete process $task_term_lower" +set context_bar [ad_context_bar "Delete process $task_term_lower"] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege write + +set hidden_vars [export_vars -form {process_task_id:multiple,sign process_id}] Index: openacs-4/packages/project-manager/www/process-use-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-use-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-use-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,13 @@ + + + + + + SELECT process_id, + one_line + FROM pm_process + ORDER BY one_line + + + + Index: openacs-4/packages/project-manager/www/process-use-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-use-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-use-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,14 @@ + + + + + + SELECT + process_id, + one_line + FROM pm_process + ORDER BY one_line + + + + Index: openacs-4/packages/project-manager/www/process-use.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-use.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-use.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,8 @@ + +@title@ +@context_bar;noquote@ + +@form_definition_beg;noquote@ + @select_widget;noquote@ + +@form_definition_end;noquote@ Index: openacs-4/packages/project-manager/www/process-use.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/process-use.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/process-use.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,64 @@ +ad_page_contract { + + Page to get the process if one is missing for task creation + + @author jader@bread.com + @creation-date 2003-10-08 + @cvs-id $Id: process-use.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + @return projects A multirow containing the list of projects + + @param process_id The process we're using to create this task +} { + + project_item_id:integer,notnull + +} -properties { + + context_bar:onevalue + title:onevalue + select_widget:onevalue + select_widget_name:onevalue + form_definition_beg:onevalue + form_definition_end:onevalue + +} -validate { +} -errors { +} + +# --------------------------------------------------------------- # + +set user_id [auth::require_login] +set package_id [ad_conn package_id] + +# terminology +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + + +set title "Use a process" +set context_bar [ad_context_bar [list "processes" "Processes"] "Use"] + + +# need to change this to show all the projects you're on by +# default, and then give you the option of selecting all projects +# as an option. + +set select_widget_name process_id +set select_widget "" + +set form_definition_beg "
    " + +append form_definition_beg [export_vars -form {project_item_id}] +set form_definition_end "
    " + Index: openacs-4/packages/project-manager/www/processes-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/processes-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/processes-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,17 @@ + + +oracle8.0 + + + + SELECT p.process_id, + p.one_line, + p.description, + p.party_id, + to_char(p.creation_date,'YYYY-MM-DD') as creation_date_ansi + FROM pm_process p + ORDER BY p.one_line + + + + Index: openacs-4/packages/project-manager/www/processes-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/processes-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/processes-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,22 @@ + + +postgresql7.3 + + + + SELECT + p.process_id, + p.one_line, + p.description, + p.party_id, + to_char(p.creation_date,'YYYY-MM-DD') as creation_date_ansi, + (select count(*) from pm_process_instance i where i.process_id = + p.process_id) as instances + FROM + pm_process_active p + ORDER BY + p.one_line + + + + Index: openacs-4/packages/project-manager/www/processes.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/processes.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/processes.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,10 @@ + + + + +Processes +@context_bar@ + + + + Index: openacs-4/packages/project-manager/www/processes.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/processes.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/processes.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,113 @@ +ad_page_contract { + + Main view page for projects. + + @author jader@bread.com, ncarroll@ee.usyd.edu.au + @creation-date 2003-05-15 + @cvs-id $Id: processes.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return projects Multirow data set of projects. + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) + +} -properties { + + context:onevalue + processes:multirow + write_p:onevalue + create_p:onevalue + admin_p:onevalue + task_term:onevalue + task_term_lower:onevalue + project_term:onevalue + project_term_lower:onevalue +} + +# --------------------------------------------------------------- # + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +# set up context bar +set context_bar [list "Processes"] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# root CR folder +# set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + +# Processes, using list-builder --------------------------------- + +template::list::create \ + -name processes \ + -multirow processes \ + -key item_id \ + -elements { + one_line { + label "Subject" + display_template { + @processes.one_line@ + } + } + description { + label "Description" + } + instances { + label "Times used" + display_template { + @processes.instances@ + } + } + creation_date { + label "Created" + } + delete { + link_url_col delete_url + display_template { + + } + } + } \ + -main_class { + narrow + } \ + -actions { + "Add process" "process-add-edit" "Add a process" + } \ + -filters { + orderby_process {} + } \ + -orderby { + one_line {orderby one_line} + default_value one_line,desc + } \ + -orderby_name orderby_project \ + -html { + width 100% + } + + +db_multirow -extend { delete_url creation_date } processes process_query { +} { + set delete_url [export_vars -base "process-delete" {process_id}] + set creation_date [lc_time_fmt $creation_date_ansi "%x"] +} + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/project-assign-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-assign-add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-assign-add.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,42 @@ +# + +ad_page_contract { + + Adds assignees to a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + @arch-tag: f52518ee-57d2-474b-a627-9050654c2f3f + @cvs-id $Id: project-assign-add.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + project_item_id:notnull + user_id:notnull,multiple + role_id:notnull,multiple + return_url:notnull +} -properties { +} -validate { +} -errors { +} + +set index 0 + +foreach user $user_id { + + set role [lindex $role_id $index] + + pm::project::assign \ + -project_item_id $project_item_id \ + -role_id $role_id \ + -party_id $user + + + incr index +} + +if {[llength $user_id] > 1} { + set assign "Assignments" +} else { + set assign "Assignment" +} + +ad_returnredirect -message "$assign saved" $return_url Index: openacs-4/packages/project-manager/www/project-assign-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-assign-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-assign-edit-2.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,44 @@ +# + +ad_page_contract { + + Processes the form for assignments and removals + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + @arch-tag: acef7904-fdc0-4fd7-9346-b6a1e011f604 + @cvs-id $Id: project-assign-edit-2.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + project_item_id:integer,notnull + return_url:notnull + assignee:multiple +} -properties { +} -validate { +} -errors { +} + +set user_id [auth::require_login] + +# remove assignments +set current_assignees [pm::project::assign_remove_everyone \ + -project_item_id $project_item_id] + +foreach ass $assignee { + + regexp {(.*)-(.*)} $ass match party_id role_id + + if {[lsearch $current_assignees $party_id] > -1} { + set send_email_p f + } else { + set send_email_p t + } + + pm::project::assign \ + -project_item_id $project_item_id \ + -party_id $party_id \ + -role_id $role_id \ + -send_email_p $send_email_p + +} + +ad_returnredirect -message "Assignments saved" $return_url Index: openacs-4/packages/project-manager/www/project-assign-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-assign-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-assign-edit.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,7 @@ + + @title@ + @context@ + + + +@html;noquote@ Index: openacs-4/packages/project-manager/www/project-assign-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-assign-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-assign-edit.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,112 @@ +# + +ad_page_contract { + + Allows the user to edit the assignees for a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + @arch-tag: e7f97c50-b2de-4483-b0a6-daadd802965b + @cvs-id $Id: project-assign-edit.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + project_item_id:integer,notnull + return_url:notnull +} -properties { +} -validate { +} -errors { +} + +# The unique identifier for this package. +set package_id [ad_conn package_id] + +# The id of the person logged in and browsing this page +set user_id [auth::require_login] + +set subsite_id [ad_conn subsite_id] + +set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + + +set project_name [pm::project::name -project_item_id $project_item_id] + +set title "Edit project assignees" +set context [list [list "one?project_item_id=$project_item_id" "$project_name"] "Edit assignees"] + +set project_task_assignee_url [export_vars -base project-assign-task-assignees {project_item_id return_url}] + +set roles_list_of_lists [pm::role::select_list_filter] + +db_foreach assignee_query { + SELECT + a.party_id, + r.role_id + FROM + pm_project_assignment a, + pm_roles r, + persons p + WHERE + a.role_id = r.role_id and + a.party_id = p.person_id and + a.project_id = :project_item_id + ORDER BY + r.role_id, + p.first_names, + p.last_name + +} { + set assigned($party_id-$role_id) 1 +} + +set assignee_list_of_lists [db_list_of_lists get_assignees { + select distinct + p.first_names || ' ' || p.last_name as name, + p.person_id + FROM + persons p, + acs_rels r, + membership_rels mr + WHERE + r.object_id_one = :user_group_id and + mr.rel_id = r.rel_id and + p.person_id = r.object_id_two and + member_state = 'approved' + ORDER BY name +}] + + +set html "
    " + +foreach role_list $roles_list_of_lists { + + set role_name [lindex $role_list 0] + set role [lindex $role_list 1] + + append html " + " + +} + +set export_vars [export_vars -form {project_item_id return_url}] + +append html "

    Assignee: $role_name

    " + + foreach assignee_list $assignee_list_of_lists { + set name [lindex $assignee_list 0] + set person_id [lindex $assignee_list 1] + + if {[exists_and_not_null assigned($person_id-$role)]} { + set checked "checked" + } else { + set checked "" + } + + append html " + $name +
    + " + + } + + append html "

    $export_vars
    " Index: openacs-4/packages/project-manager/www/project-assign-remove.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-assign-remove.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-assign-remove.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,34 @@ +# + +ad_page_contract { + + Remove a project assignment for a list of assignees + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-11 + @arch-tag: 479be68c-3849-4017-b950-ff6029839362 + @cvs-id $Id: project-assign-remove.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + project_item_id:notnull + user_id:notnull,multiple + return_url:notnull +} -properties { +} -validate { +} -errors { +} + + +foreach user $user_id { + + pm::project::unassign \ + -project_item_id $project_item_id \ + -party_id $user +} + +if {[llength $user_id] > 1} { + set assign "Assignments" +} else { + set assign "Assignment" +} + +ad_returnredirect -message "$assign removed" $return_url Index: openacs-4/packages/project-manager/www/project-assign-task-assignees.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-assign-task-assignees.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-assign-task-assignees.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,78 @@ +# + +ad_page_contract { + + Assigns people to a project based on the assignments for tasks in + the project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-28 + @arch-tag: 0ef1b86a-6653-4734-81b9-280c6f71f408 + @cvs-id $Id: project-assign-task-assignees.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + project_item_id:integer,notnull + return_url +} -properties { +} -validate { +} -errors { +} + +# remove all assignments + +set current_assignees [pm::project::assign_remove_everyone \ + -project_item_id $project_item_id] + +# get all task assignments for this project + +set assignments_lol [db_list_of_lists get_people { + SELECT + a.party_id, + a.role_id + FROM + pm_task_assignment a, + cr_items i + WHERE + i.parent_id = :project_item_id and + i.item_id = a.task_id +}] + +set parties [list] + +foreach pair $assignments_lol { + + foreach {party role} $pair { + + # set the lowest role someone is assigned as + if {[string is false [info exists lowest_role($party)]]} { + set lowest_role($party) $role + } + + if {$lowest_role($party) < $role} { + set lowest_role($party) $role + } + + # make a list of parties assigned + if {[lsearch $parties $party] < 0} { + lappend parties $party + } + } +} + +# make project assignments + +foreach party $parties { + + if {[lsearch $current_assignees $party] > -1} { + set send_email_p f + } else { + set send_email_p t + } + + pm::project::assign \ + -project_item_id $project_item_id \ + -role_id $lowest_role($party) \ + -party_id $party \ + -send_email_p $send_email_p +} + +ad_returnredirect -message "Saved project assignments based on task assignments" [export_vars -base project-assign-edit {project_item_id return_url}] Index: openacs-4/packages/project-manager/www/project-revisions-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-revisions-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-revisions-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,41 @@ + + + + + + + + + + + oracle + 8.0 + + + + + SELECT p.item_id, + p.project_id, + p.title as project_name, + p.project_code, + p.goal, + p.description, + p.mime_type, + to_char(p.planned_start_date,'Mon DD') as planned_start_date, + to_char(p.planned_end_date,'Mon DD') as planned_end_date, + p.ongoing_p, + i.live_revision, + to_char(p.estimated_finish_date,'Mon DD') as estimated_finish_date, + to_char(p.earliest_finish_date,'Mon DD') as earliest_finish_date, + to_char(p.latest_finish_date,'Mon DD') as latest_finish_date, + p.estimated_hours_total + FROM pm_projectsx p, + cr_items i + WHERE p.item_id = :project_item_id and + p.item_id = i.item_id + ORDER BY p.project_id asc + + + + + Index: openacs-4/packages/project-manager/www/project-revisions-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-revisions-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-revisions-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,44 @@ + + + + + + + + + + + postgresql + 7.3 + + + + + SELECT + p.item_id, + p.project_id, + p.title as project_name, + p.project_code, + p.goal, + p.description, + p.mime_type, + to_char(p.planned_start_date,'Mon DD') as planned_start_date, + to_char(p.planned_end_date,'Mon DD') as planned_end_date, + p.ongoing_p, + i.live_revision, + to_char(p.estimated_finish_date,'Mon DD') as estimated_finish_date, + to_char(p.earliest_finish_date,'Mon DD') as earliest_finish_date, + to_char(p.latest_finish_date,'Mon DD') as latest_finish_date, + p.estimated_hours_total + FROM + pm_projectsx p, cr_items i + WHERE + p.item_id = :project_item_id and + p.item_id = i.item_id + ORDER BY + p.project_id asc + + + + + Index: openacs-4/packages/project-manager/www/project-revisions.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-revisions.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-revisions.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,7 @@ + + @title@ + @context@ + + + + Index: openacs-4/packages/project-manager/www/project-revisions.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/project-revisions.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/project-revisions.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,97 @@ +# + +ad_page_contract { + + Shows all the revisions of a project + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-30 + @arch-tag: 339a6143-11a3-4f1b-902d-a3cd71f7d531 + @cvs-id $Id: project-revisions.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + +} { + project_item_id:integer +} -properties { + revisions:multirow +} -validate { +} -errors { +} + + +set title "Project Changes" + +set context [list "one?project_item_id=$project_item_id Project" "View Revisions"] + + +# Project Revisions, using list-builder --------------------------------- + +template::list::create \ + -name revisions \ + -multirow revisions \ + -key project_id \ + -elements { + project_id { + label "Subject" + display_col project_name + link_url_col item_url + link_html { title "View this revision" } + display_template {@revisions.project_name@@revisions.project_name@} + } + description { + label "Description" + display_template { + @revisions.description_rich;noquote@ + } + } + planned_end_date { + label "Deadline" + } + } \ + -sub_class { + narrow + } + + +set descriptions [list] + +db_multirow -extend { item_url description_rich old_revision_id } revisions project_revisions_query { +} { + set item_url [export_vars -base "one" -override {{project_item_id $item_id}} { project_id }] + + set richtext_list [list $description $mime_type] + + set description_rich [template::util::richtext::get_property html_value $richtext_list] + + set descriptions_length [llength $descriptions] + + # if there isn't any previous items, then we don't have to do a + # word diff. All the content is new. + if {$descriptions_length < 1} { + set description_rich $description_rich + lappend descriptions "$description_rich" + + } else { + + set old_description [lindex $descriptions [expr [llength $descriptions] - 1]] + set old_description [ad_html_to_text $old_description] + lappend descriptions "$description_rich" + + set description_rich [pm::util::word_diff \ + -split_by " " \ + -old "$old_description" \ + -start_old "" \ + -end_old "" \ + -start_new "" \ + -end_new "" \ + -new "[ad_html_to_text $description_rich]" \ + -filter_proc ""] + + # set description_rich [ad_html_to_text $description_rich] + set description_rich [ad_text_to_html -no_quote -includes_html -- $description_rich] + + } + +} + + + Index: openacs-4/packages/project-manager/www/style.css =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/style.css,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/style.css 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,104 @@ +td.highlighted { + background-color:#ddddff; +} + +td.highlight { + background-color:#ffffdd; + border-bottom: 1px dotted #A0BDEB; +} + +td.subheader { + background-color:#ffffdd; + border-top: 1px dotted #e6e6fa; + border-bottom: 1px dotted #e6e6fa; + border-left: 1px solid #e6e6fa; +} + +td.list-bg { + border-left: 1px solid #e6e6fa; +} + +td.list-bottom-bg { + border-bottom: 1px solid #e6e6fa; + border-left: 1px solid #e6e6fa; +} + +td.list-right-bg { + border-bottom: 1px solid #e6e6fa; + border-right: 1px solid #e6e6fa; +} + +th.project { + background-color:#9999cc; +} + +td.project-filter-pane { + background-color: #bbbbee; + vertical-align: top; +} + +.shaded { + background-color: #dddddd; +} + +.selected { + background-color: #eeccdd; +} + +th { + font-size: 9pt; + text-align: left; + background-color:dfdfff; +} + + +/* From logger */ + +table.logger_navbar { + background-color: #41329c; + clear: both; +} +a.logger_navbar { + color: white; + text-decoration: none; +} +a.logger_navbar:visited { + color: white; +} +a.logger_navbar:hover { + color: white; + text-decoration: underline; +} +td.logger_navbar { + font-family: tahoma,verdana,arial,helvetica; + font-size: 70%; + font-weight: bold; + color: #ccccff; + text-decoration: none; +} + +td.fill-list-right { + border-bottom: 3px solid #A0BDEB; + border-right: 1px solid #A0BDEB; + background-color: #eaf2ff; +} + +td.fill-list-right2 { + border-right: 1px solid #A0BDEB; + background-color: #eaf2ff; +} + +td.fill-list-bottom { + border-bottom: 3px solid #A0BDEB; + border-left: 1px solid #A0BDEB; + background-color: #eaf2ff; +} + +td.fill-list-middle { + border-left: 1px solid #A0BDEB; + background-color: #eaf2ff; +} + +td.fill-list-bg { + background-color: #eaf2ff; +} Index: openacs-4/packages/project-manager/www/task-add-edit-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-add-edit-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-add-edit-2.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,388 @@ +# + +ad_page_contract { + + Processes the add or edit + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-13 + @arch-tag: 8de16306-6d59-419a-a0ef-dae06dc5e69e + @cvs-id $Id: task-add-edit-2.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + {project_item_id:array ""} + {process_id:integer ""} + {process_name ""} + {task_item_id:array ""} + {number:integer,multiple ""} + {comments:html,array ""} + {comments_mime_type:array ""} + {task_title:array ""} + {description:html,array ""} + {description_mime_type:array ""} + {estimated_hours_work:array ""} + {estimated_hours_work_min:array ""} + {estimated_hours_work_max:array ""} + {estimated_days_work:array ""} + {estimated_days_work_min:array ""} + {estimated_days_work_max:array ""} + {process_task_id:integer,multiple ""} + {percent_complete:array ""} + {dependency:array ""} + {assignee:multiple ""} + {use_dependency:array ""} + {edit_p "f"} + {using_process_p "f"} + {end_date_month:multiple ""} + {end_date_day:multiple ""} + {end_date_year:multiple ""} + return_url:optional + {send_email_p "t"} + {hours:array ""} + {log_month:multiple ""} + {log_day:multiple ""} + {log_year:multiple ""} + {log_date:multiple ""} + {log:array ""} + {logger_variable:array ""} + {date:multiple ""} + {priority:array ""} +} -properties { +} -validate { +} -errors { +} + +# --------------------------------------------------------------- +# Set up +# --------------------------------------------------------------- +set user_id [auth::require_login] +set package_id [ad_conn package_id] +set peeraddr [ad_conn peeraddr] + +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + +set hours_day [pm::util::hours_day] +set use_days_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] + +foreach i $number { + + set date_$i [split [lindex $date [expr $i-1]] "-"] + set end_date_${i}(day) [lindex [set date_$i] 2] + set end_date_${i}(month) [lindex [set date_$i] 1] + set end_date_${i}(year) [lindex [set date_$i] 0] + set end_date_${i}(format) "" + + ad_page_contract_filter_proc_date end_date_$i end_date_$i + + + set log_date_$i [split [lindex $log_date [expr $i-1]] "-"] + + set log_date_${i}_day [lindex [set log_date_$i] 2] + set log_date_${i}_month [lindex [set log_date_$i] 1] + set log_date_${i}_year [lindex [set log_date_$i] 0] + set log_date_${i}_format "" + + + ad_page_contract_filter_proc_date log_date_$i log_date_$i + + if {[string is true $use_days_p]} { + + # set the hours work + if {[string is true $use_uncertain_completion_times_p]} { + + set estimated_hours_work_min($i) \ + [expr $estimated_days_work_min($i) * $hours_day] + set estimated_hours_work_max($i) \ + [expr $estimated_days_work_max($i) * $hours_day] + + } else { + + set estimated_hours_work($i) \ + [expr $estimated_days_work($i) * $hours_day] + + } + } +} + + + +if {[string is true $edit_p]} { + + # ------- + # EDITING + # ------- + + permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege write + + # ----------------------------------------------------- + # find out information about the task before we edit it + # ----------------------------------------------------- + + set tasks_item_id [list] + foreach num $number { + lappend tasks_item_id $task_item_id($num) + } + + foreach task $tasks_item_id { + pm::task::clear_client_properties \ + -task_item_id $task + } + + pm::task::get \ + -tasks_item_id $tasks_item_id \ + -one_line_array old_one_line \ + -description_array old_description \ + -description_mime_type_array old_description_mime_type \ + -estimated_hours_work_array old_estimated_hours_work \ + -estimated_hours_work_min_array old_estimated_hours_work_min \ + -estimated_hours_work_max_array old_estimated_hours_work_max \ + -dependency_array old_dependency \ + -percent_complete_array old_percent_complete \ + -end_date_day_array old_end_date_day \ + -end_date_month_array old_end_date_month \ + -end_date_year_array old_end_date_year \ + -project_item_id_array old_project_item_id \ + -priority_array old_priority \ + -set_client_properties_p t + foreach num $number { + + # -------------------------- + # figure out estimated hours + # -------------------------- + + if {[string is true $use_uncertain_completion_times_p]} { + set estimated_hours_work($num) \ + [expr .5 * \ + ($estimated_hours_work_max($num) - \ + $estimated_hours_work_min($num)) + \ + $estimated_hours_work_min($num)] + } else { + set estimated_hours_work_min($num) $estimated_hours_work($num) + set estimated_hours_work_max($num) $estimated_hours_work($num) + } + + # ------------------------------------- + # Log hours and other variables to task + # ------------------------------------- + + set logger_project [pm::project::get_logger_project \ + -project_item_id $project_item_id($num)] + + + if {[exists_and_not_null hours($num)]} { + + pm::project::log_hours \ + -logger_project_id $logger_project \ + -variable_id $logger_variable($num) \ + -value $hours($num) \ + -description $log($num) \ + -task_item_id $task_item_id($num) \ + -project_item_id $project_item_id($num) \ + -update_status_p f \ + -party_id $user_id \ + -timestamp_ansi [set log_date_${num}] + } + + # --------- + # edit task + # --------- + + + set dead_line "[set end_date_${num}(year)]-[set end_date_${num}(month)]-[set end_date_${num}(day)]" + set task_revision \ + [pm::task::edit \ + -task_item_id $task_item_id($num) \ + -project_item_id $project_item_id($num) \ + -title $task_title($num) \ + -description $description($num) \ + -mime_type $description_mime_type($num) \ + -end_date [set end_date_${num}(date)] \ + -percent_complete $percent_complete($num) \ + -estimated_hours_work $estimated_hours_work($num) \ + -estimated_hours_work_min $estimated_hours_work_min($num) \ + -estimated_hours_work_max $estimated_hours_work_max($num) \ + -update_user $user_id \ + -update_ip $peeraddr \ + -package_id $package_id \ + -priority $priority($num) + ] + + # -------------------------- + # remove all old assignments + # -------------------------- + pm::task::assign_remove_everyone \ + -task_item_id $task_item_id($num) + + # ----------------------- + # remove all dependencies + # ----------------------- + pm::task::dependency_delete_all \ + -task_item_id $task_item_id($num) + + } + + # ----------------------- + # add back in assignments + # ----------------------- + + foreach ass $assignee { + regexp {(\d+)-(\d+)-(\d+)} $ass match num person role + + set task $task_item_id($num) + + pm::task::assign \ + -task_item_id $task \ + -party_id $person \ + -role_id $role + } + + # ----------------------- + # add in the dependencies + # ----------------------- + foreach num $number { + if {[exists_and_not_null dependency($num)]} { + pm::task::dependency_add \ + -task_item_id $task_item_id($num) \ + -parent_id $dependency($num) \ + -dependency_type finish_before_start \ + -project_item_id $project_item_id($num) + } + } + +} else { + + # ----------------------------------- + # USING PROCESS OR CREATING NEW TASKS + # ----------------------------------- + + permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege create + + if {[string is true $using_process_p]} { + + set process_instance_id [pm::process::instantiate \ + -process_id $process_id \ + -project_item_id $project_item_id([lindex $number 0]) \ + -name $process_name] + } else { + set process_instance_id "" + } + + foreach num $number { + + # -------------------------- + # figure out estimated hours + # -------------------------- + + if {[string is true $use_uncertain_completion_times_p]} { + set estimated_hours_work($num) \ + [expr .5 * \ + ($estimated_hours_work_max($num) - \ + $estimated_hours_work_min($num)) + \ + $estimated_hours_work_min($num)] + } else { + set estimated_hours_work_min($num) $estimated_hours_work($num) + set estimated_hours_work_max($num) $estimated_hours_work($num) + } + + # ----------- + # create task + # ----------- + + set task_item \ + [pm::task::new \ + -project_id $project_item_id($num) \ + -title $task_title($num) \ + -description $description($num) \ + -mime_type $description_mime_type($num) \ + -end_date [set end_date_${num}(date)]\ + -percent_complete $percent_complete($num) \ + -estimated_hours_work $estimated_hours_work($num) \ + -estimated_hours_work_min $estimated_hours_work_min($num) \ + -estimated_hours_work_max $estimated_hours_work_max($num) \ + -process_instance_id $process_instance_id \ + -creation_user $user_id \ + -creation_ip $peeraddr \ + -package_id $package_id \ + -priority $priority($num) + ] + + set task_item_id($num) $task_item + } + + # ---------------- + # add in assignees + # ---------------- + + foreach ass $assignee { + regexp {(\d+)-(\d+)-(\d+)} $ass match num person role + + set task $task_item_id($num) + + pm::task::assign \ + -task_item_id $task \ + -party_id $person \ + -role_id $role + } + + # ------------------- + # add in dependencies + # ------------------- + foreach num $number { + + # if there is a numXX as the dependency, then we are relying + # on new tasks that had not been created yet. So we match them + # up with the new tasks we've just created. + if {[regexp {num(.*)} $dependency($num) match parent]} { + set dependency($num) $task_item_id($parent) + } + + if {[exists_and_not_null dependency($num)]} { + + pm::task::dependency_add \ + -task_item_id $task_item_id($num) \ + -parent_id $dependency($num) \ + -dependency_type finish_before_start \ + -project_item_id $project_item_id($num) + } + } + +} + +# -------------------------------------------------------------------- +# Internet Explorer sucks. It really really does. Due to length limits +# on URLs for IE, we have to pass these variables through +# ad_set_client_property. +# -------------------------------------------------------------------- + +foreach num $number { + ad_set_client_property -persistent f -- \ + project-manager \ + project_item_id($num) \ + $project_item_id($num) + + ad_set_client_property -persistent f -- \ + project-manager \ + task_item_id($num) \ + $task_item_id($num) + +} + +# We're done! + +ad_returnredirect \ + [export_vars -base task-add-edit-3 \ + { \ + number:multiple \ + using_process_p \ + process_instance_id \ + edit_p \ + comments:array \ + comments_mime_type:array \ + send_email_p \ + return_url}] + Index: openacs-4/packages/project-manager/www/task-add-edit-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-add-edit-3.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-add-edit-3.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,155 @@ +# + +ad_page_contract { + + Send email and update project status + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-14 + @arch-tag: f6cf8b76-a1e0-42a0-9489-000cad7ad7b5 + @cvs-id $Id: task-add-edit-3.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + number:multiple + {return_url ""} + {edit_p "f"} + {using_process_p "f"} + {process_instance_id:integer ""} + {comments:html,array ""} + {comments_mime_type:array ""} + {send_email_p "t"} +} -properties { +} -validate { +} -errors { +} + +# -------------------------------------------------------------------- +# Internet Explorer sucks. It really really does. Due to length limits +# on URLs for IE, we have to pass these variables through +# ad_set_client_property. +# -------------------------------------------------------------------- + +foreach num $number { + set project_item_id($num) [ad_get_client_property -- \ + project-manager \ + project_item_id($num)] + + set task_item_id($num) [ad_get_client_property -- \ + project-manager \ + task_item_id($num)] + +} + + +# --------------------------------------------- +# set up the return_url if it's not already set +# --------------------------------------------- + +if {[empty_string_p $return_url]} { + set return_url [export_vars -base one \ + {{project_item_id "$project_item_id([lindex $number 0])"}} ] +} + + +# --------------------------------------------------------------- +# Set up +# --------------------------------------------------------------- +set user_id [auth::require_login] +set package_id [ad_conn package_id] +set peeraddr [ad_conn peeraddr] + +if {[string is true $edit_p]} { + permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege write +} else { + permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege create +} + +if {[string is true $using_process_p]} { + + set return_url "$return_url&[export_vars -url {{instance_id $process_instance_id}}]" + +} + +ad_progress_bar_begin -title "Updating status..." -message_1 "Please wait..." -message_2 "Will continue automatically" + +# compute the status for all projects + +# BUG: currently, if you have a task in a project, and you change the +# project to another project, it won't update the old project. It should + +set computed_projects [list] + +foreach num $number { + + if {[lsearch $computed_projects $project_item_id($num)] < 0} { + + pm::project::compute_status $project_item_id($num) + lappend computed_projects $project_item_id($num) + } +} + +util_user_message -message "Saved tasks. You may need to refresh the screen to see the changes." + +ad_progress_bar_end -url $return_url + + +# send out email alerts + +if {[string is true $using_process_p]} { + + if {[string is true $send_email_p]} { + pm::process::email_alert \ + -process_instance_id $process_instance_id \ + -project_item_id $project_item_id(1) + } + +} elseif {[string is true $edit_p]} { + + # append to comments what has changed in each task + pm::task::what_changed \ + -task_item_id_array task_item_id \ + -number $number \ + -comments_array comments \ + -comments_mime_type_array comments_mime_type + + foreach num $number { + + if {[exists_and_not_null comments($num)]} { + # add comment to task + pm::util::general_comment_add \ + -object_id $task_item_id($num) \ + -title [pm::task::name -task_item_id $task_item_id($num)] \ + -comment $comments($num) \ + -mime_type $comments_mime_type($num) \ + -user_id $user_id \ + -peeraddr $peeraddr \ + -type "task" \ + -send_email_p f + + if {[string is true $send_email_p]} { + # send email notification + pm::task::email_alert \ + -task_item_id $task_item_id($num) \ + -edit_p $edit_p \ + -comment $comments($num) \ + -comment_mime_type $comments_mime_type($num) + } + } + } +} else { + + foreach num $number { + + if {[string is true $send_email_p]} { + pm::task::email_alert \ + -task_item_id $task_item_id($num) \ + -edit_p $edit_p + } + } + +} Index: openacs-4/packages/project-manager/www/task-add-edit-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-add-edit-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-add-edit-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,79 @@ + + + + + SELECT t.process_task_id as process_tid, + t.one_line, + t.description, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + d.dependency_id, + d.parent_task_id as process_parent_task + FROM pm_process_task t , + pm_process_task_dependency d + WHERE t.process_task_id = d.process_task_id (+) and + t.process_id = :process_id + ORDER BY t.ordering, + t.process_task_id + + + + + + select sysdate from dual + + + + + + SELECT t.parent_id as my_project_item_id, + t.task_revision_id, + t.title as my_task_title, + t.description as my_description, + t.mime_type as my_mime_type, + to_char(t.end_date,'YYYY MM DD') as my_end_date, + t.percent_complete as my_percent_complete, + t.estimated_hours_work as my_estimated_work, + t.estimated_hours_work_min as my_estimated_work_min, + t.estimated_hours_work_max as my_estimated_work_max, + t.actual_hours_worked as my_actual_hours_worked, + d.parent_task_id as my_dependency + FROM pm_tasks_revisionsx t, + cr_items i , + pm_task_dependency d + WHERE i.item_id = d.task_id (+) and + t.item_id in ([join $task_id ","]) and + t.revision_id = i.live_revision + ORDER BY t.item_id + + + + + + SELECT p.project_id + FROM pm_projectsx p, + cr_items i + WHERE p.item_id = :project_item_id and + p.revision_id = i.live_revision + + + + + + SELECT short_name, + description + FROM pm_task_dependency_types + ORDER BY short_name + + + + + + SELECT item_id + FROM pm_tasks_revisionsx + WHERE revision_id = :this_revision_id + + + + Index: openacs-4/packages/project-manager/www/task-add-edit-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-add-edit-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-add-edit-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,71 @@ + + + + + select + current_timestamp + + + + + + select + t.parent_id as my_project_item_id, + t.task_revision_id, + t.title as my_task_title, + t.description as my_description, + t.mime_type as my_mime_type, + to_char(t.end_date,'YYYY MM DD') as my_end_date, + t.percent_complete as my_percent_complete, + t.estimated_hours_work as my_estimated_work, + t.estimated_hours_work_min as my_estimated_work_min, + t.estimated_hours_work_max as my_estimated_work_max, + t.actual_hours_worked as my_actual_hours_worked, + d.parent_task_id as my_dependency + FROM + pm_tasks_revisionsx t, + cr_items i LEFT JOIN pm_task_dependency d ON i.item_id = d.task_id + WHERE + t.item_id in ([join $task_id ","]) and + t.revision_id = i.live_revision + ORDER BY + t.item_id + + + + + + SELECT + p.project_id + FROM + pm_projectsx p, cr_items i + WHERE + p.item_id = :project_item_id and + p.revision_id = i.live_revision + + + + + + select + short_name, + description + FROM + pm_task_dependency_types + ORDER BY + short_name + + + + + + select + item_id + FROM + pm_tasks_revisionsx + WHERE + revision_id = :this_revision_id + + + + Index: openacs-4/packages/project-manager/www/task-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-add-edit.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,319 @@ + + @title;noquote@ + @context@ + + +
    +
    + @export_vars;noquote@ + + + Send email to assignees? + + + + Process name + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + + + + @task_term_lower;noquote@  @tasks.task_item_id@ + + + @task_term_lower;noquote@  @tasks.rownum@ + + + +
    + + + Subject:*

    + + Description:
    +
    + + Format: + + + + +

    + Comment
    +
    + + Format: + + + + + + + + +

      + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Work required:*
    Min: @work_units;noquote@
    Max: @work_units;noquote@
    @work_units;noquote@
    Min: @work_units;noquote@
    Max: @work_units;noquote@
    @work_units;noquote@
    + +

    + +

    + + Deadline: @tasks.end_date_html;noquote@

    + + + +

    + + @tasks.project_html;noquote@ + +

    + + Dependency:
    + + +

    + + Priority: + +
    + + [i] + Enter a number for ordering the priority. 0 is the default + and also the lowest priority. + +

    + + + Status: + + %
    + + [i] + Enter 100% to close the @task_term_lower@, or less to open it. + +
    + + Status: + + + + + + + +

    + + +

    + Log entry: + + + + + + + + + + + + + + + + + + + +
    Quantity: + + @tasks.logger_variable_html;noquote@ +
    Date: + <%= [set today_html@tasks.task_item_id@] %> +
    Description: + +
    + +

    + [i] + You can optionally log time worked here. +

    +
    + + + +

    @tasks.assignee_html;noquote@
    + +   + +
    + +   + +
     
    +
    + + Index: openacs-4/packages/project-manager/www/task-add-edit.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-add-edit.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-add-edit.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,432 @@ +ad_page_contract { + + Add/edit form for tasks + + Needs to handle the following cases: +
      +
    • Adding a new task or tasks
    • +
    • Editing a task or tasks
    • +
    • Using a process to add new tasks
    • +
    + + @author jader@bread.com + @creation-date 2003-07-28 + @cvs-id $Id: task-add-edit.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return context Context bar + @return title Page title. + + @param task_item_id list of tasks to edit, if there are any + @project_item_id The project these tasks are assigned to. + @param process_id The id for the process used, if any + @param process_task_id The process task IDs if there is a process used. + @param return_url + @param new_tasks if we are creating new tasks, how many to create +} { + {task_item_id:integer,multiple ""} + {project_item_id:integer ""} + {process_id:integer ""} + {process_task_id:integer,multiple ""} + {return_url ""} + {new_tasks "1"} +} -properties { + +} -validate { +} -errors { +} + + +# --------------------------------------------------------------- +# Set up +# --------------------------------------------------------------- +set user_id [auth::require_login] +set package_id [ad_conn package_id] + +# use hour units or day units +set use_day_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] +set hours_day [pm::util::hours_day] + +if {[string is true $use_day_p]} { + set work_units "days" +} else { + set work_units "hrs" +} + +# --------------------------------------------------------------- +# terminology +# --------------------------------------------------------------- +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + +# ------------------------- +# Set up flags to use later +# ------------------------- + +if {[exists_and_not_null task_item_id]} { + set edit_p t +} else { + set edit_p f +} + +if {[exists_and_not_null process_id]} { + set using_process_p t +} else { + set using_process_p f +} + +# -------------------------------------------------------------------- +# if we are editing tasks, each task has its own project. We also want +# to look up all the old information to store it for later. We use +# this for comparison, to see what has changed. +# -------------------------------------------------------------------- + +if {[string is true $edit_p]} { + + # get old values + pm::task::get \ + -tasks_item_id $task_item_id \ + -one_line_array task_one_line \ + -description_array task_description \ + -description_mime_type_array task_description_mime_type \ + -estimated_hours_work_array task_estimated_hours_work \ + -estimated_hours_work_min_array task_estimated_hours_work_min \ + -estimated_hours_work_max_array task_estimated_hours_work_max \ + -dependency_array task_dependency \ + -percent_complete_array task_percent_complete \ + -end_date_day_array task_end_date_day \ + -end_date_month_array task_end_date_month \ + -end_date_year_array task_end_date_year \ + -project_item_id_array task_project_item_id \ + -priority_array task_priority + +} elseif {[empty_string_p $project_item_id]} { + + ad_return_error "Project missing" "For new tasks, a project must be passed in" + ad_script_abort +} + +# --------------------------------------------------------------- +# permissions and title setup, etc +# --------------------------------------------------------------- + +if {[string is true $edit_p]} { + + set title "Edit a $task_term_lower" + set context [list [list $return_url "Go back"] "Edit $task_term"] + + permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege write + +} else { + + set title "Add $task_term_lower" + set context [list [list "one?item_id=$project_item_id" "One $project_term"] "New $task_term"] + + permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege create + +} + +# ------------------------------------------------------------- +# Start creating the multirow we'll use to create the interface +# ------------------------------------------------------------- + +template::multirow create \ + tasks \ + task_item_id \ + process_task_id \ + one_line \ + description \ + description_mime_type \ + work_hrs \ + work_min_hrs \ + work_max_hrs \ + work_days \ + work_min_days \ + work_max_days \ + percent_complete \ + end_date_html \ + depends \ + assignee_html \ + dependency_html \ + logger_variable_html \ + project_html \ + priority + + +if {[string is true $edit_p]} { + +# set today_html [pm::task::today_html \ + \# -month_target log_month \ + \# -day_target log_day \ + \# -year_target log_year] + + + # ------- + # EDITING + # ------- + + set number 1 + set total_number [llength $task_item_id] + + + + set deps [list] + foreach task $task_item_id { + if {[lsearch $deps $task_dependency($task)] == -1 && \ + ![empty_string_p $task_dependency($task)]} { + lappend deps $task_dependency($task) + } + } + + foreach task $task_item_id { + + set this_project $task_project_item_id($task) + + set project_options [pm::project::select_list_of_open \ + -selected $this_project] + + # find out the default logger variable for this project + set logger_project [pm::project::get_logger_project \ + -project_item_id $this_project] + set logger_variable_id [logger::project::get_primary_variable \ + -project_id $logger_project] + set today_date [db_string today "select to_date(sysdate,'YYYY-MM-DD') from dual"] + set today_html$task "
    y-m-d " + + #set end_date_html [pm::task::date_html \ + \# -selected_day $task_end_date_day($task) \ + \# -selected_month $task_end_date_month($task) \ + \# -selected_year $task_end_date_year($task)] + + set end_date_html "
    y-m-d " + + set assignee_html [pm::task::assignee_html \ + -task_item_id $task \ + -number $number] + + set dependency_options_full [pm::task::options_list_html \ + -edit_p $edit_p \ + -task_item_id $task \ + -project_item_id $this_project \ + -dependency_task_id $task_dependency($task) \ + -dependency_task_ids "$deps" \ + -number $total_number \ + -current_number $number] + + set variable_widget [logger::ui::variable_select_widget \ + -project_id $logger_project \ + -current_variable_id $logger_variable_id \ + -select_name logger_variable.$number] + + set project_html "$project_term: + " + + set task_estimated_days_work($task) \ + [pm::util::days_work \ + -hours_work $task_estimated_hours_work($task)] + + set task_estimated_days_work_min($task) \ + [pm::util::days_work \ + -hours_work $task_estimated_hours_work_min($task)] + + set task_estimated_days_work_max($task) \ + [pm::util::days_work \ + -hours_work $task_estimated_hours_work_max($task)] + + + template::multirow append tasks \ + $task \ + "" \ + $task_one_line($task) \ + $task_description($task) \ + $task_description_mime_type($task) \ + $task_estimated_hours_work($task) \ + $task_estimated_hours_work_min($task) \ + $task_estimated_hours_work_max($task) \ + $task_estimated_days_work($task) \ + $task_estimated_days_work_min($task) \ + $task_estimated_days_work_max($task) \ + $task_percent_complete($task) \ + $end_date_html \ + $task_dependency($task) \ + $assignee_html \ + $dependency_options_full \ + $variable_widget \ + $project_html \ + $task_priority($task) + + incr number + } + + +} elseif {[string is true $using_process_p]} { + + # ------------- + # USING PROCESS + # ------------- + + set process_name [pm::process::process_name \ + -process_id $process_id] + + # get all the process task info + pm::process::get \ + -process_id $process_id \ + -process_task_id $process_task_id \ + -one_line_array process_one_line \ + -description_array process_description \ + -description_mime_type_array process_description_mime_type \ + -estimated_hours_work_array process_estimated_hours_work \ + -estimated_hours_work_min_array process_estimated_hours_work_min \ + -estimated_hours_work_max_array process_estimated_hours_work_max \ + -dependency_array process_dependency \ + -tasks_list process_tasks + + # we now have an array (process_dependency) that contains all the + # templates for where the dependencies should lie. However, the + # user may not have selected all the process tasks to be + # created. We also need to keep track of which new task + # corresponds with which process task, so we can make sure the + # default process + set number 1 + foreach pt $process_tasks { + set task_num($pt) $number + incr number + } + foreach pt $process_tasks { + if {[exists_and_not_null process_dependency($pt)]} { + # keep track of which task the new task should by default + # depend upon + set task_parent_num($pt) $task_num($process_dependency($pt)) + } else { + set task_parent_num($pt) "" + } + } + + set new_tasks [llength $process_tasks] + +# set end_date_html [pm::task::date_html] + + + set end_date_html "
    y-m-d " + + + set number 1 + set total_number [llength $process_tasks] + + foreach pt $process_tasks { + + set assignee_html [pm::task::assignee_html \ + -number $number \ + -process_task_id $pt] + + + set dependency_options_full [pm::task::options_list_html \ + -edit_p $edit_p \ + -project_item_id $project_item_id \ + -depends_on_new $task_parent_num($pt) \ + -number $new_tasks \ + -current_number $number] + + set project_html "" + + set process_estimated_days_work($pt) \ + [pm::util::days_work \ + -hours_work $process_estimated_hours_work($pt)] + + set process_estimated_days_work_min($pt) \ + [pm::util::days_work \ + -hours_work $process_estimated_hours_work_min($pt)] + + set process_estimated_days_work_max($pt) \ + [pm::util::days_work \ + -hours_work $process_estimated_hours_work_max($pt)] + + + # make sure deps are working. + + template::multirow append tasks \ + "" \ + $process_task_id \ + $process_one_line($pt) \ + $process_description($pt) \ + $process_description_mime_type($pt) \ + $process_estimated_hours_work($pt) \ + $process_estimated_hours_work_min($pt) \ + $process_estimated_hours_work_max($pt) \ + $process_estimated_days_work($pt) \ + $process_estimated_days_work_min($pt) \ + $process_estimated_days_work_max($pt) \ + "0" \ + $end_date_html \ + $process_dependency($pt) \ + $assignee_html \ + $dependency_options_full \ + "" \ + $project_html + + incr number + } + +} else { + + # --- + # NEW + # --- + +set today_date [db_string today "select to_date(sysdate,'YYYY-MM-DD') from dual"] + # set end_date_html [pm::task::date_html] + + for {set i 1} {$i <= $new_tasks} {incr i} { + set end_date_html "
    y-m-d " + + set assignee_html [pm::task::assignee_html \ + -number $i] + + set dependency_options_full [pm::task::options_list_html \ + -edit_p $edit_p \ + -project_item_id $project_item_id \ + -number $new_tasks \ + -current_number $i] + + set project_html "" + + # sorry this isn't internationalized. The choice is to cludge + # around dates, or to cludge around ad_forms poor support for + # multiple dates. + + template::multirow append tasks \ + "" \ + "" \ + "" \ + "" \ + "text/plain" \ + 0 \ + 0 \ + 0 \ + 0 \ + 0 \ + 0 \ + 0 \ + $end_date_html \ + "" \ + $assignee_html \ + $dependency_options_full \ + "" \ + $project_html \ + 0 + + } +} + + + +set export_vars [export_vars -form {edit_p using_process_p return_url}] Index: openacs-4/packages/project-manager/www/task-assign-add-edit.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-assign-add-edit.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-assign-add-edit.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,49 @@ + + @context@ + @title@ + + +
    + + + + + +
    + + + + + + + + + +
    @tasks.one_line@
    + + + + + + + + + + + +
    +
    +
    + + + +

    + + + + + + + + Index: openacs-4/packages/project-manager/www/task-assign-add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-assign-add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-assign-add.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,61 @@ +# + +ad_page_contract { + + Adds assignees to a task + + @author (jader-ibr@bread.com) + @creation-date 2004-11-18 + @arch-tag: b877079e-edc9-49ae-8e6b-4c8cfd6edbf0 + @cvs-id $Id: task-assign-add.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + task_item_id:notnull + user_id:notnull,multiple + role_id:notnull,multiple + return_url:notnull +} -properties { +} -validate { +} -errors { +} + +set present_user_id [ad_conn user_id] +set peeraddr [ad_conn peeraddr] + +set index 0 + +set comment "

      " + +foreach user $user_id { + + set role [lindex $role_id $index] + + pm::task::assign \ + -task_item_id $task_item_id \ + -role_id $role_id \ + -party_id $user + + append comment "
    • Added: [person::name -person_id $user]
    • " + + incr index +} + +append comment "
    " + +pm::util::general_comment_add \ + -object_id $task_item_id \ + -title [pm::task::name -task_item_id $task_item_id] \ + -comment $comment \ + -mime_type "text/html" \ + -user_id $present_user_id \ + -peeraddr $peeraddr \ + -type "task" \ + -send_email_p f + + +if {[llength $user_id] > 1} { + set assign "Assignments" +} else { + set assign "Assignment" +} + +ad_returnredirect -message "$assign saved" $return_url Index: openacs-4/packages/project-manager/www/task-assign-remove.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-assign-remove.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-assign-remove.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,65 @@ +# + +ad_page_contract { + + Removes assignment from a task + + @author (jader-ibr@bread.com) + @creation-date 2004-11-18 + @arch-tag: f70e02f1-2475-4ede-ad40-cda9567f99b1 + @cvs-id $Id: task-assign-remove.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + task_item_id:integer,notnull + user_id:notnull,multiple + return_url:notnull +} -properties { +} -validate { +} -errors { +} + +set present_user_id [ad_conn user_id] +set peeraddr [ad_conn peeraddr] + +set comment_pre "
      " +set comment_list [list] + +foreach user $user_id { + + set assigned_p [pm::task::assigned_p \ + -task_item_id $task_item_id \ + -party_id $user] + + pm::task::unassign \ + -task_item_id $task_item_id \ + -party_id $user + + if {[string is true $assigned_p]} { + lappend comment_list "
    • Removed: [person::name -person_id $user]
    • " + } +} + +append comment_post "
    " + +if {[llength $comment_list] > 0} { + + set comment "$comment_pre [join $comment_list] $comment_post" + + pm::util::general_comment_add \ + -object_id $task_item_id \ + -title [pm::task::name -task_item_id $task_item_id] \ + -comment $comment \ + -mime_type "text/html" \ + -user_id $present_user_id \ + -peeraddr $peeraddr \ + -type "task" \ + -send_email_p f +} + +if {[llength $user_id] > 1} { + set assign "Assignments" +} else { + set assign "Assignment" +} + +ad_returnredirect -message "$assign removed" $return_url + Index: openacs-4/packages/project-manager/www/task-calendar-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-calendar-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-calendar-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,12 @@ + + + oracle8.0 + + + SELECT one_line as role, + substr(one_line,1,1) as abbreviation + FROM pm_roles + + + + Index: openacs-4/packages/project-manager/www/task-calendar.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-calendar.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-calendar.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,48 @@ + + + @title@ + @context@ + @header_stuff;noquote@ + + View options + Key + +
    + + @edit_hidden_vars;noquote@ + + @calendar;noquote@ + +
    + +

    View options

    + + @hide_show_closed;noquote@ + +

    Key

    + +
    + +
    @roles.abbreviation;noquote@
    +
    @roles.role;noquote@
    +
    +
    + +

    Users to view

    + +
    + + + + + @users.name@
    +
    + + + @users.name@
    +
    + +
    + + +
    Index: openacs-4/packages/project-manager/www/task-calendar.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-calendar.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-calendar.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,130 @@ +# /packages/room-reservation/www/room-reservations.tcl + +ad_page_contract { + + Shows tasks on the calendar + + @author Jade Rubick (jader@bread.com) + @author Deds Castillo (deds@infiniteinfo.com) + @creation-date 2002-08-28 + @cvs-id $Id: task-calendar.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + +} { + {view "month"} + {date ""} + {julian_date ""} + {hide_closed_p "t"} +} -properties { + title:onevalue + context:onevalue + roles:multirow +} + +set user_id [auth::require_login] + +set date [calendar::adjust_date -date $date -julian_date $julian_date] + +set title "Task calendar" +set context [list $title] +set header_stuff " +" + +set return_url [ad_return_url] + +set edit_hidden_vars [export_vars -form {return_url}] + +set calendar [pm::calendar::one_month_display \ + -user_id $user_id \ + -date $date \ + -hide_closed_p $hide_closed_p \ + ] + + +if {[string is true $hide_closed_p]} { + set hide_show_closed "Show closed" + set here [export_vars -base task-calendar {{hide_closed_p f} view date julian_date}] +} else { + set hide_show_closed "Hide closed" + set here [export_vars -base task-calendar {{hide_closed_p t} view date julian_date}] +} + +# --------------------------------------------- +# make a key of list of roles and abbreviations +# --------------------------------------------- + +db_multirow roles roles_and_abbrevs { + SELECT + one_line as role, + substring(one_line from 1 for 1) as abbreviation + FROM + pm_roles +} + + +# ------------------------------------- +# make a list of users in this subsite. +# ------------------------------------- + +set users_to_view [pm::calendar::users_to_view] + +set subsite_id [ad_conn subsite_id] + +set user_group_id [application_group::group_id_from_package_id \ + -package_id $subsite_id] + + +db_multirow -extend {checked_p} users users_list { + select + p.first_names || ' ' || p.last_name as name, + p.person_id as party_id + FROM + persons p, + acs_rels r, + membership_rels mr + WHERE + r.object_id_one = :user_group_id and + mr.rel_id = r.rel_id and + p.person_id = r.object_id_two and + member_state = 'approved' + ORDER BY + p.first_names, p.last_name +} { + if {[lsearch $users_to_view $party_id] == -1} { + set checked_p f + } else { + set checked_p t + } +} Index: openacs-4/packages/project-manager/www/task-delete-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-delete-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-delete-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,31 @@ + + +oracle8.0 + + + + SELECT t.item_id, + t.title as task_title, + t.description, + t.mime_type, + to_char(current_timestamp,'Mon DD ''YY') as current_time, + to_char(t.earliest_start,'Mon DD ''YY') as earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'Mon DD ''YY') as earliest_finish, + to_char(t.latest_start,'Mon DD ''YY') as latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'Mon DD ''YY') as latest_finish, + to_char(current_date,'J') as today_j, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.percent_complete, + i.live_revision + FROM pm_tasks_revisionsx t, cr_items i + WHERE t.item_id = :task_item_id and + t.item_id = i.item_id and + i.live_revision = t.revision_id + + + + Index: openacs-4/packages/project-manager/www/task-delete-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-delete-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-delete-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,34 @@ + + +postgresql7.2 + + + + SELECT + t.item_id, + t.title as task_title, + t.description, + t.mime_type, + to_char(current_timestamp,'Mon DD ''YY') as current_time, + to_char(t.earliest_start,'Mon DD ''YY') as earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'Mon DD ''YY') as earliest_finish, + to_char(t.latest_start,'Mon DD ''YY') as latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'Mon DD ''YY') as latest_finish, + to_char(current_date,'J') as today_j, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.percent_complete, + i.live_revision + FROM + pm_tasks_revisionsx t, cr_items i + WHERE + t.item_id = :task_item_id and + t.item_id = i.item_id and + i.live_revision = t.revision_id + + + + Index: openacs-4/packages/project-manager/www/task-delete.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-delete.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-delete.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,5 @@ + + @title@ + @context@ + + Index: openacs-4/packages/project-manager/www/task-delete.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-delete.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-delete.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,87 @@ +# + +ad_page_contract { + + Deletes a task + + @author Chris Davis (mcd@daviesinc.com) + @author Jade Rubick (jader@bread.com) + @creation-date 2004-03-31 + @arch-tag: af0efc2f-cf78-4f80-a484-1f52f3db6a48 + @cvs-id $Id: task-delete.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + task_item_id:integer +} -properties { +} -validate { +} -errors { +} + +set package_id [ad_conn package_id] + +permission::require_permission -privilege "delete" -object_id $package_id + +set title "Delete task" +set context [list "Delete task"] + + +set action [template::form get_action delete_task] + +if {[string equal $action delete]} { + + pm::task::delete -task_item_id $task_item_id + ad_returnredirect -message "Task $task_item_id Deleted" "tasks" + ad_script_abort + +} else { + + set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + + if {[string is true $use_uncertain_completion_times_p]} { + set hours_work { + {estimated_hours_work_min:text + {label "Estimated Hours (Min)"} + } + {estimated_hours_work_max:text + {label "Estimated Hours (Max)"} + } + } + } else { + set hours_work { + {estimated_hours_work:text + {label "Estimated Hours"} + } + } + } + + + set form " + task_item_id:key + {task_title:text + {label \"Title\"} + } + {description:richtext + {label \"Description\"} + } + $hours_work + {percent_complete:text + {label \"Percent Complete\"} + } + " + + ad_form -name delete_task \ + -edit_request { + + db_1row task_query { } + + set description [list $description $mime_type] + + } \ + -mode display \ + -has_submit 1 \ + -has_edit 1 \ + -actions {{"Delete this task?" delete} {"Cancel" cancel}} \ + -cancel_url "task-one?task_id=$task_item_id" \ + -form $form + +} + Index: openacs-4/packages/project-manager/www/task-link.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-link.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-link.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,32 @@ +# + +ad_page_contract { + + Links two tasks together + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-10-14 + @arch-tag: 126cf2fd-ffcd-4396-961d-648dc8849fc4 + @cvs-id $Id: task-link.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ +} { + to_task:integer,notnull + from_task:integer,notnull + {return_url "task-one?task_id=$from_task"} +} -properties { +} -validate { +} -errors { +} + +set user_id [auth::require_login] +set package_id [ad_conn package_id] + +permission::require_permission \ + -party_id $user_id \ + -object_id $package_id \ + -privilege write + +pm::task::link \ + -task_item_id_1 $from_task \ + -task_item_id_2 $to_task + +ad_returnredirect -message "Tasks linked" $return_url Index: openacs-4/packages/project-manager/www/task-one-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-one-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-one-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,136 @@ + + + oracle8.0 + + + SELECT t.item_id, + t.parent_id as project_item_id, + t.title as task_title, + t.revision_id, + t.description, + t.mime_type, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + to_char(t.end_date,'YYYY-MM-DD HH24:MI') as end_date, + to_char(current_date,'J') as today_j, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.percent_complete, + i.live_revision, + p.first_names || ' ' || p.last_name as creation_user, + proj_rev.title as project_name + FROM pm_tasks_revisionsx t, + cr_items i, + persons p, + cr_items proj, + cr_revisions proj_rev + WHERE t.item_id = :task_id and + t.revision_id = :task_revision_id and + t.item_id = i.item_id and + t.creation_user = p.person_id and + t.parent_id = proj.item_id and + proj.live_revision = proj_rev.revision_id + + + + + + SELECT + t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type + FROM + pm_tasks_revisionsx t, cr_items i, pm_task_dependency d + WHERE + d.task_id = :task_id and + d.parent_task_id = t.item_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency -orderby] + + + + + + SELECT t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type, + d.task_id as d_task_id + FROM pm_tasks_revisionsx t, + cr_items i, + pm_task_dependency d + WHERE d.task_id = t.item_id and + d.parent_task_id = :task_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency2 -orderby] + + + + + + select r.one_line, + u.first_names || ' ' || u.last_name as user_info, + r.role_id + from pm_task_assignment a, + persons u, + pm_roles r + where a.task_id = :task_id and + u.person_id = a.party_id and + a.role_id = r.role_id + [template::list::orderby_clause -name people -orderby] + + + + + + SELECT x.task_id_1 as x_task_id, + r.title, + to_char(r.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + r.earliest_start - current_date as days_to_earliest_start, + to_char(r.earliest_start,'J') as earliest_start_j, + to_char(r.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + r.earliest_finish - current_date as days_to_earliest_finish, + to_char(r.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + r.latest_start - current_date as days_to_latest_start, + to_char(r.latest_start,'J') as latest_start_j, + to_char(current_date,'J') as today_j, + to_char(r.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + r.latest_finish - current_date as days_to_latest_finish + FROM pm_task_xref x, pm_tasks_revisionsx r, cr_items i + WHERE x.task_id_2 = :task_id and + x.task_id_1 = r.item_id and + r.revision_id = i.live_revision + UNION + SELECT x2.task_id_2 as x_task_id, + r2.title, + to_char(r2.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + r2.earliest_start - current_date as days_to_earliest_start, + to_char(r2.earliest_start,'J') as earliest_start_j, + to_char(r2.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + r2.earliest_finish - current_date as days_to_earliest_finish, + to_char(r2.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + r2.latest_start - current_date as days_to_latest_start, + to_char(r2.latest_start,'J') as latest_start_j, + to_char(current_date,'J') as today_j, + to_char(r2.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + r2.latest_finish - current_date as days_to_latest_finish + FROM pm_task_xref x2, pm_tasks_revisionsx r2, cr_items i2 + WHERE x2.task_id_1 = :task_id and + x2.task_id_2 = r2.item_id and + i2.live_revision = r2.revision_id + + + + Index: openacs-4/packages/project-manager/www/task-one-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-one-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-one-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,155 @@ + + + + + + SELECT + t.item_id, + t.parent_id as project_item_id, + t.title as task_title, + t.revision_id, + t.description, + t.mime_type, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + to_char(t.end_date,'YYYY-MM-DD HH24:MI') as end_date, + to_char(current_date,'J') as today_j, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.percent_complete, + t.priority, + i.live_revision, + p.first_names || ' ' || p.last_name as creation_user, + proj_rev.title as project_name, + a.process_instance + FROM + pm_tasks_revisionsx t, + cr_items i, + persons p, + cr_items proj, + cr_revisions proj_rev, + pm_tasks_active a + WHERE + t.item_id = :task_id and + t.revision_id = :task_revision_id and + t.item_id = i.item_id and + t.creation_user = p.person_id and + t.parent_id = proj.item_id and + proj.live_revision = proj_rev.revision_id and + t.item_id = a.task_id + + + + + + SELECT + t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type + FROM + pm_tasks_revisionsx t, cr_items i, pm_task_dependency d + WHERE + d.task_id = :task_id and + d.parent_task_id = t.item_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency -orderby] + + + + + + SELECT + t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type, + d.task_id as d_task_id + FROM + pm_tasks_revisionsx t, cr_items i, pm_task_dependency d + WHERE + d.task_id = t.item_id and + d.parent_task_id = :task_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency2 -orderby] + + + + + + select + r.one_line, + u.first_names || ' ' || u.last_name as user_info, + r.role_id, + r.is_observer_p, + r.is_lead_p + from + pm_task_assignment a, + persons u, + pm_roles r + where + a.task_id = :task_id and + u.person_id = a.party_id and + a.role_id = r.role_id + [template::list::orderby_clause -name people -orderby] + + + + + + SELECT + x.task_id_1 as x_task_id, + r.title, + to_char(r.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + r.earliest_start - current_date as days_to_earliest_start, + to_char(r.earliest_start,'J') as earliest_start_j, + to_char(r.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + r.earliest_finish - current_date as days_to_earliest_finish, + to_char(r.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + r.latest_start - current_date as days_to_latest_start, + to_char(r.latest_start,'J') as latest_start_j, + to_char(current_date,'J') as today_j, + to_char(r.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + r.latest_finish - current_date as days_to_latest_finish + FROM + pm_task_xref x, pm_tasks_revisionsx r, cr_items i + WHERE + x.task_id_2 = :task_id and + x.task_id_1 = r.item_id and + r.revision_id = i.live_revision + UNION + SELECT + x2.task_id_2 as x_task_id, + r2.title, + to_char(r2.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + r2.earliest_start - current_date as days_to_earliest_start, + to_char(r2.earliest_start,'J') as earliest_start_j, + to_char(r2.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + r2.earliest_finish - current_date as days_to_earliest_finish, + to_char(r2.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + r2.latest_start - current_date as days_to_latest_start, + to_char(r2.latest_start,'J') as latest_start_j, + to_char(current_date,'J') as today_j, + to_char(r2.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + r2.latest_finish - current_date as days_to_latest_finish + FROM + pm_task_xref x2, pm_tasks_revisionsx r2, cr_items i2 + WHERE + x2.task_id_1 = :task_id and + x2.task_id_2 = r2.item_id and + i2.live_revision = r2.revision_id + + + + Index: openacs-4/packages/project-manager/www/task-one.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-one.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-one.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,363 @@ + + + @task_term@ #@task_id@: + @task_info.task_title;noquote@ @closed_message@ + @context;noquote@ + + +

    (not current, select live version from the task change page)

    +
    + + + + + + + + +
    + + + + + + + + + + + + +
    + + Process status + +
    @process_html;noquote@
    +

    + + + + + + + + + + + + + + + + + +
    + + + + + + + + + Edit + + + Print + + + + + + + + @task_term@ #@task_id@: @task_info.task_title@ + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Description
    @task_info.description;noquote@
    -- @task_info.creation_user@
    Comments +
    @comments;noquote@ +

    + @comments_link;noquote@ +

    Actions
    + +
    +
     
    + +

    + + + + @notification_chunk;noquote@ + + + +

    +   + + + + + + + + + + + + +
    + + Dates + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Earliest start@task_info.earliest_start@ 
    Earliest finish@task_info.earliest_finish@
    Latest start@task_info.latest_start@
    Latest finish@task_info.latest_finish@
    Deadline@task_info.end_date@
    +
     
    +

    + + + + + + + + + + + + + + + +
    + + Assignees + +
    + +  
    + +  
    + +

    + + + + + + + + + + + + + + + + + + + + + + + + +
    + + Logger + +
    + Priority: @task_info.priority@
    + + Days remaining: @task_info.days_remaining@
    +
    + + Hours remaining: @task_info.hours_remaining@
    +
    + + Slack: n/a + + + Slack: @task_info.slack_time@
    +
    + + Slack: @task_info.slack_time@
    +
    + + Complete: @task_info.percent_complete@% +
     
    +
    + @variable_widget;noquote@ + @variable_exports;noquote@ + @day_widget;noquote@ + +
    +
     
    + +  
    + +

    + + + + + + + + + + + +
    + + @task_term@s this depends on. + +
    + +  
    + +

    + + + + + + + + + + + +
    + + @task_term@s depending on this @task_term@ + +
    + +  
    + +

    + + + + + + + + + + + + + + + +
    + + Related @task_term@s + +
    + +  
    +
    + Link task: + + + +
     
    + +

    + + + Index: openacs-4/packages/project-manager/www/task-one.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-one.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-one.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,467 @@ +ad_page_contract { + Main view page for one task. + + @author jader@bread.com + @creation-date 2003-07-28 + @cvs-id $Id: task-one.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return task_term Term to use for Task + @return task_term_lower Term to use for task + @return assignee_term Term to use for assignee + @return watcher_term Term to use for watcher + @return dependency multirow that stores dependency information + @return dependency2 multirow that stores dependency information for tasks that have dependencies on this particular task + + @param task_id item_id for the task + @param project_item_id the item_id for the project. Used for navigational links + @param project_id the revision_id for the project. Used for navigational links + @param context_bar value for context bar creation + @param orderby_dependency specifies how the dependencies will be sorted + @param orderby_dependency2 specifies how the dependencies will be sorted (for tasks that have dependencies on this task) + @param logger_days The number of days back to view logged entries +} { + task_id:integer,optional + task_revision_id:integer,optional + orderby_dependency:optional + orderby_dependency2:optional + orderby_people:optional + {logger_variable_id:integer ""} + {logger_days:integer "180"} +} -properties { + closed_message:onevalue + notification_chunk:onevalue + task_info:onerow + project_item_id:onevalue + project_id:onevalue + context:onevalue + write_p:onevalue + create_p:onevalue + dependency:multirow + dependency2:multirow + people:multirow + task_term:onevalue + task_term_lower:onevalue + assignee_term:onevalue + watcher_term:onevalue + comments:onevalue + comments_link:onevalue + print_link:onevalue + use_uncertain_completion_times_p:onevalue +} -validate { + task_id_exists { + if {![info exists task_id]} { + set task_id [pm::task::get_item_id \ + -task_id $task_revision_id] + if {[string equal $task_id -1]} { + ad_complain + } + } + } + revision_id_exists { + if {![info exists task_revision_id]} { + set task_revision_id [pm::task::get_revision_id \ + -task_item_id $task_id] + if {[string equal $task_revision_id -1]} { + ad_complain + } + } + } + logger_days_positive { + if {$logger_days < 1} { + set logger_days 1 + } + } +} -errors { + task_id_exists {That task does not exist} + revision_id_exists {That task does not exist} +} + + +# --------------------------------------------------------------- # + +# terminology and other parameters +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set assignee_term [parameter::get -parameter "AssigneeName" -default "Assignee"] +set watcher_term [parameter::get -parameter "WatcherName" -default "Watcher"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set use_uncertain_completion_times_p [parameter::get -parameter "UseUncertainCompletionTimesP" -default "1"] + +set use_days_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] +set urgency_threshold 8 +# the unique identifier for this package +set package_id [ad_conn package_id] +set package_url [ad_conn package_url] +set user_id [auth::require_login] + + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] + + + +# Task info ---------------------------------------------------------- + +db_1row task_query { } -column_array task_info + +# format the hours remaining section + +set task_info(hours_remaining) \ + [pm::task::hours_remaining \ + -estimated_hours_work $task_info(estimated_hours_work) \ + -estimated_hours_work_min $task_info(estimated_hours_work_min) \ + -estimated_hours_work_max $task_info(estimated_hours_work_max) \ + -percent_complete $task_info(percent_complete)] + +set task_info(days_remaining) \ + [pm::task::days_remaining \ + -estimated_hours_work $task_info(estimated_hours_work) \ + -estimated_hours_work_min $task_info(estimated_hours_work_min) \ + -estimated_hours_work_max $task_info(estimated_hours_work_max) \ + -percent_complete $task_info(percent_complete)] + +# format the dates according to the local settings +set task_info(earliest_start) [lc_time_fmt $task_info(earliest_start) "%x"] +set task_info(earliest_finish) [lc_time_fmt $task_info(earliest_finish) "%x"] +set task_info(latest_start) [lc_time_fmt $task_info(latest_start) "%x"] +set task_info(latest_finish) [lc_time_fmt $task_info(latest_finish) "%x"] +set task_info(end_date) [lc_time_fmt $task_info(end_date) "%x"] + +# we do this for the hours include portion +set project_item_id $task_info(project_item_id) + +set context [list [list "one?project_item_id=$task_info(project_item_id)" "$task_info(project_name)"] "$task_info(task_title)"] + + +set richtext_list [list $task_info(description) $task_info(mime_type)] + +set task_info(description) [template::util::richtext::get_property html_value $richtext_list] + +if {[exists_and_not_null task_info(earliest_start_j)]} { + set task_info(slack_time) [pm::task::slack_time \ + -earliest_start_j $task_info(earliest_start_j) \ + -today_j $task_info(today_j) \ + -latest_start_j $task_info(latest_start_j)] +} + +if {$task_info(percent_complete) >= 100} { + set closed_message "-- Closed" +} else { + set closed_message "" +} + + +# if part of a process, offer link to process +if {![empty_string_p $task_info(process_instance)]} { + set process_url [pm::process::url \ + -process_instance_id $task_info(process_instance) \ + -project_item_id $task_info(project_item_id) \ + -fully_qualified_p "f"] + set process_name [pm::process::name \ + -process_instance_id $task_info(process_instance)] + set process_html "$process_name" +} else { + set process_html "" +} + +# set link to comments + +set comments [general_comments_get_comments -print_content_p 1 -print_attachments_p 1 $task_id "[pm::task::get_url $task_id]"] + +set comments_link "Add comment" + +set print_link "task-print?&task_id=$task_id&project_item_id=$task_info(project_item_id)" + + +# how to get back here +set return_url [ad_return_url] + +set task_edit_url [export_vars -base task-add-edit {{task_item_id $task_id} return_url project_item_id}] + +set logger_project [pm::project::get_logger_project \ + -project_item_id $task_info(project_item_id)] + +set logger_url [pm::util::logger_url] + +if {[empty_string_p $logger_variable_id]} { + set logger_variable_id [logger::project::get_primary_variable \ + -project_id $logger_project] +} + +set log_url [export_vars -base "${logger_url}log" {{return_url $return_url} {project_id $logger_project} {pm_project_id $task_info(project_item_id)} {pm_task_id $task_id}}] + +set assignee_add_self_widget "Add myself as [export_vars -form {{task_item_id $task_id} user_id return_url}][pm::role::task_select_list -select_name "role_id" -task_item_id $task_id -party_id $user_id]" + +# Only need a 'remove myself' link if you are already assigned +set assigned_p [pm::task::assigned_p -task_item_id $task_id -party_id $user_id] +if {$assigned_p} { + set assignee_remove_self_url [export_vars -base task-assign-remove {{task_item_id $task_id} user_id return_url}] +} + + + +set nextyear_ansi [clock format [clock scan "+ 365 day"] -format "%Y-%m-%d"] +set then_ansi [clock format [clock scan "-$logger_days days"] -format "%Y-%m-%d"] + +set day_widget "Last Days" + +set variable_widget [logger::ui::variable_select_widget \ + -project_id $logger_project \ + -current_variable_id $logger_variable_id \ + -select_name logger_variable_id] + +set variable_exports [export_vars -form -entire_form -exclude {logger_variable_id logger_days }] + + +# ------------------ +# Notifications info +# ------------------ +set notification_chunk [notification::display::request_widget \ + -type pm_task_notif \ + -object_id $task_id \ + -pretty_name "$task_info(task_title)" \ + -url "[ad_conn url]?[ad_conn query]" \ + ] + + +# Dependency info ------------------------------------------------ + +template::list::create \ + -name dependency \ + -multirow dependency \ + -key d_task_id \ + -elements { + dependency_type { + label "Type" + display_template { + + + + + + + + + + + + + } + } + d_task_id { + label "Task" + display_col task_title + link_url_col item_url + link_html { title "View this task" } + } + percent_complete { + label "Status" + display_template "@dependency.percent_complete@\%" + } + end_date { + label "Deadline" + } + } \ + -orderby { + percent_complete {orderby percent_complete} + end_date {orderby end_date} + } \ + -orderby_name orderby_dependency \ + -sub_class { + narrow + } \ + -filters { + task_revision_id {} + orderby_dependency2 {} + } \ + -html { + width 100% + } + +db_multirow -extend { item_url } dependency dependency_query { +} { + set item_url [export_vars -base "task-one" -override {{task_id $parent_task_id}} { task_id $d_task_id }] +} + +# Dependency info (dependency other task have on this task) ------ + +template::list::create \ + -name dependency2 \ + -multirow dependency2 \ + -key d_task_id \ + -elements { + dependency_type { + label "Type" + display_template { + + + + + + + + + + + + + } + } + d_task_id { + label "Task" + display_col task_title + link_url_eval {task-one?task_id=$d_task_id} + link_html { title "View this task" } + } + percent_complete { + label "Status" + display_template "@dependency2.percent_complete@\%" + } + end_date { + label "Deadline" + } + } \ + -orderby { + percent_complete {orderby percent_complete} + end_date {orderby end_date} + } \ + -orderby_name orderby_dependency2 \ + -sub_class { + narrow + } \ + -filters { + task_revision_id {} + orderby_dependency {} + } \ + -html { + width 100% + } + + +db_multirow -extend { item_url } dependency2 dependency2_query { +} { + +} + +# People, using list-builder --------------------------------- + +template::list::create \ + -name people \ + -multirow people \ + -key item_id \ + -elements { + first_names { + label { + Who + } + display_template { + @people.user_info@ + } + } + role_id { + label "Role" + display_template "@people.one_line@" + } + } \ + -sub_class { + narrow + } \ + -filters { + party_id {} + task_id {} + orderby_subproject {} + orderby_versions {} + orderby_tasks {} + } \ + -orderby { + default_value role_id,desc + first_names { + orderby_asc "first_names asc, last_name asc" + orderby_desc "first_names desc, last_name desc" + default_direction asc + } + role_id { + orderby_asc "role_id asc, user_info asc" + orderby_desc "role_id desc, user_info asc" + default_direction asc + } + default_value role_id,asc + } \ + -orderby_name orderby_people \ + -html { + width 100% + } + +db_multirow people task_people_query { } + +# Xrefs ------------------------------------------------ + +template::list::create \ + -name xrefs \ + -multirow xrefs \ + -key x_task_id \ + -elements { + x_task_id { + label "ID" + } + title { + label "Task" + link_url_col item_url + link_html { title "View this task" } + } + slack_time { + label "Slack" + } + earliest_start_pretty { + label "ES" + } + earliest_finish_pretty { + label "EF" + } + latest_start_pretty { + label "LS" + } + latest_finish_pretty { + label "LF" + display_template { + @xrefs.latest_finish_pretty@ + } + } + } \ + -sub_class { + narrow + } \ + -filters { + task_revision_id {} + orderby_revision {} + orderby_dependency {} + orderby_dependency2 {} + } \ + -html { + width 100% + } + +db_multirow -extend { item_url earliest_start_pretty earliest_finish_pretty latest_start_pretty latest_finish_pretty slack_time } xrefs xrefs_query { +} { + set item_url [export_vars -base "task-one" -override {{task_id $x_task_id}}] + + set earliest_start_pretty [lc_time_fmt $earliest_start "%x"] + set earliest_finish_pretty [lc_time_fmt $earliest_finish "%x"] + set latest_start_pretty [lc_time_fmt $latest_start "%x"] + set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] + + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + +} + + +ad_return_template + +# ------------------------- END OF FILE ------------------------- # + Index: openacs-4/packages/project-manager/www/task-print-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-print-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-print-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,100 @@ + + + + + + SELECT t.revision_id as task_revision_id + FROM pm_tasks_revisionsx t, cr_items i + WHERE t.item_id = :task_id and + i.live_revision = t.revision_id + + + + + + SELECT t.parent_id as project_item_id + FROM pm_tasks_revisionsx t, cr_items i + WHERE i.item_id = t.item_id and + t.revision_id = :task_revision_id + + + + + + SELECT t.item_id, + t.title as task_title, + t.description, + t.mime_type, + to_char(current_timestamp,'Mon DD ''YY') as current_time, + to_char(t.earliest_start,'Mon DD ''YY') as earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'Mon DD ''YY') as earliest_finish, + to_char(t.latest_start,'Mon DD ''YY') as latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'Mon DD ''YY') as latest_finish, + to_char(current_date,'J') as today_j, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.percent_complete, + i.live_revision + FROM pm_tasks_revisionsx t, cr_items i + WHERE t.item_id = :task_id and + t.revision_id = :task_revision_id and + t.item_id = i.item_id + + + + + + + SELECT t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type + FROM pm_tasks_revisionsx t, + cr_items i, + pm_task_dependency d + WHERE d.task_id = :task_id and + d.parent_task_id = t.item_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency -orderby] + + + + + + SELECT t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type, + d.task_id + FROM pm_tasks_revisionsx t, cr_items i, pm_task_dependency d + WHERE d.task_id = t.item_id and + d.parent_task_id = :task_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency2 -orderby] + + + + + + SELECT r.one_line, + u.first_names || ' ' || u.last_name as user_info, + r.role_id + FROM pm_task_assignment a, + cc_users u, + pm_roles r + WHERE a.task_id = :task_id and + u.party_id = a.party_id and + a.role_id = r.role_id + + + + Index: openacs-4/packages/project-manager/www/task-print-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-print-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-print-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,116 @@ + + + + + + SELECT + t.revision_id as task_revision_id + FROM + pm_tasks_revisionsx t, cr_items i + WHERE + t.item_id = :task_id and + i.live_revision = t.revision_id + + + + + + SELECT + t.parent_id as project_item_id + FROM + pm_tasks_revisionsx t, cr_items i + WHERE + i.item_id = t.item_id and + t.revision_id = :task_revision_id + + + + + + SELECT + t.item_id, + t.title as task_title, + t.description, + t.mime_type, + to_char(current_timestamp,'Mon DD ''YY') as current_time, + to_char(t.earliest_start,'Mon DD ''YY') as earliest_start, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(t.earliest_finish,'Mon DD ''YY') as earliest_finish, + to_char(t.latest_start,'Mon DD ''YY') as latest_start, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_finish,'Mon DD ''YY') as latest_finish, + to_char(current_date,'J') as today_j, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.percent_complete, + i.live_revision + FROM + pm_tasks_revisionsx t, cr_items i + WHERE + t.item_id = :task_id and + t.revision_id = :task_revision_id and + t.item_id = i.item_id + + + + + + + SELECT + t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type + FROM + pm_tasks_revisionsx t, cr_items i, pm_task_dependency d + WHERE + d.task_id = :task_id and + d.parent_task_id = t.item_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency -orderby] + + + + + + SELECT + t.title as task_title, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + i.live_revision, + d.parent_task_id, + d.dependency_type, + d.task_id + FROM + pm_tasks_revisionsx t, cr_items i, pm_task_dependency d + WHERE + d.task_id = t.item_id and + d.parent_task_id = :task_id and + t.revision_id = i.live_revision and + t.item_id = i.item_id + [template::list::orderby_clause -name dependency2 -orderby] + + + + + + select + r.one_line, + u.first_names || ' ' || u.last_name as user_info, + r.role_id + from + pm_task_assignment a, + cc_users u, + pm_roles r + where + a.task_id = :task_id and + u.party_id = a.party_id and + a.role_id = r.role_id + + + + Index: openacs-4/packages/project-manager/www/task-print.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-print.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-print.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,129 @@ + + +@task_term@ #@task_id@: @task_info.task_title@ + + + + + + + + + +
    + + + + + + + +
    @task_term@ #@task_id@: @task_info.task_title@
    + + + + + + + + + + + + +
    Description
    @task_info.description;noquote@ +
    + +

    Comments

    @comments;noquote@ +
    + +

    @show_comment_link;noquote@ + +

    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Assignees
    Work
    @task_info.percent_complete@% complete
    @task_info.estimated_hours_work_min@ - @task_info.estimated_hours_work_max@ hrs estimated
    Slack time: @task_info.slack_time@
    Dates
    + + + + + + + + + + + + + + + + + + + + + +
    Now +@task_info.current_time@
    Earliest start +@task_info.earliest_start@
    Earliest finish +@task_info.earliest_finish@
    Latest start +@task_info.latest_start@
    Latest finish +@task_info.latest_start@
    + +
    @task_term@(s) this depends on.
    +
    @task_term@(s) depending on this @task_term@
    + +
    + +
    + + + + Index: openacs-4/packages/project-manager/www/task-print.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-print.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-print.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,275 @@ +ad_page_contract { + Main view page for one task. + + @author jader@bread.com + @creation-date 2003-07-28 + @cvs-id $Id: task-print.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return task_term Term to use for Task + @return task_term_lower Term to use for task + @return assignee_term Term to use for assignee + @return watcher_term Term to use for watcher + @return dependency multirow that stores dependency information + @return dependency2 multirow that stores dependency information for tasks that have dependencies on this particular task + + @param task_id item_id for the task + @param project_item_id the item_id for the project. Used for navigational links + @param project_id the revision_id for the project. Used for navigational links + @param context_bar value for context bar creation + @param orderby_revisions specifies how the revisions table will be sorted + @param orderby_dependency specifies how the dependencies will be sorted + @param orderby_dependency2 specifies how the dependencies will be sorted (for tasks that have dependencies on this task) +} { + task_id:integer,optional + task_revision_id:integer,optional + orderby_revisions:optional + orderby_dependency:optional + orderby_dependency2:optional + {show_comment_p "f"} + +} -properties { + task_info:onerow + project_item_id:onevalue + project_id:onevalue + context_bar:onevalue + write_p:onevalue + create_p:onevalue + revisions:multirow + dependency:multirow + dependency2:multirow + people:multirow + task_term:onevalue + task_term_lower:onevalue + assignee_term:onevalue + watcher_term:onevalue + comments:onevalue + comments_link:onevalue +} -validate { + task_id_exists { + if {![info exists task_id]} { + set task_id [db_string get_task_id { }] + } + } + revision_id_exists { + if {![info exists task_revision_id]} { + set task_revision_id [db_string get_revision_id { }] + } + } +} + + +# --------------------------------------------------------------- # + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set assignee_term [parameter::get -parameter "AssigneeName" -default "Assignee"] +set watcher_term [parameter::get -parameter "WatcherName" -default "Watcher"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] + +db_1row get_project_ids { } + +set context_bar [ad_context_bar "one?project_item_id=$project_item_id $project_term" "View"] + + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +set comments [general_comments_get_comments -print_content_p 1 -print_attachments_p 1 $task_id "[ad_conn url]?task_id=$task_id"] + +set comments_link [general_comments_create_link -object_name pm_task -link_text "Add a comment" -context_id $package_id $task_id "[ad_conn url]?task_id=$task_id"] + +set show_comment_link "show comments" + + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] + +# Task info ---------------------------------------------------------- + +db_1row task_query { } -column_array task_info + +set richtext_list [list $task_info(description) $task_info(mime_type)] + +set task_info(description) [template::util::richtext::get_property html_value $richtext_list] + +set task_info(slack_time) [pm::task::slack_time \ + -earliest_start_j $task_info(earliest_start_j) \ + -today_j $task_info(today_j) \ + -latest_start_j $task_info(latest_start_j)] + +# Dependency info ------------------------------------------------ + +template::list::create \ + -name dependency \ + -multirow dependency \ + -key task_id \ + -elements { + dependency_type { + label "Type" + display_template { + + + + + + + + + + + + + } + } + task_id { + label "Task" + display_col task_title + link_url_col item_url + link_html { title "View this task" } + } + percent_complete { + label "Status" + display_template "@dependency.percent_complete@\%" + } + end_date { + label "Deadline" + } + } \ + -orderby { + percent_complete {orderby percent_complete} + end_date {orderby end_date} + } \ + -orderby_name orderby_dependency \ + -sub_class { + narrow + } \ + -filters { + task_revision_id {} + orderby_revisions {} + orderby_dependency2 {} + } \ + -html { + width 100% + } + +db_multirow -extend { item_url } dependency dependency_query { +} { + set item_url [export_vars -base "task-one" -override {{task_id $parent_task_id}} { task_id }] +} + +# Dependency info (dependency other task have on this task) ------ + +template::list::create \ + -name dependency2 \ + -multirow dependency2 \ + -key task_id \ + -elements { + dependency_type { + label "Type" + display_template { + + + + + + + + + + + + + } + } + task_id { + label "Task" + display_col task_title + link_url_eval {task-one?task_id=$task_id} + link_html { title "View this task" } + } + percent_complete { + label "Status" + display_template "@dependency2.percent_complete@\%" + } + end_date { + label "Deadline" + } + } \ + -orderby { + percent_complete {orderby percent_complete} + end_date {orderby end_date} + } \ + -orderby_name orderby_dependency2 \ + -sub_class { + narrow + } \ + -filters { + task_revision_id {} + orderby_revisions {} + orderby_dependency {} + } \ + -html { + width 100% + } + + +db_multirow -extend { item_url } dependency2 dependency2_query { +} { + +} + +# People, using list-builder --------------------------------- + +db_multirow people task_people_query { } + +template::list::create \ + -name people \ + -multirow people \ + -key last_name \ + -elements { + first_names { + label {Who} + display_template { + @people.user_info@ + } + } + role_id { + label "Role" + display_template "@people.one_line@" + } + } \ + -sub_class { + narrow + } \ + -filters { + party_id {} + task_id {} + orderby_subproject {} + orderby_versions {} + orderby_tasks {} + } \ + -orderby { + role_id {orderby role_id} + default_value role_id,desc + } \ + -orderby_name orderby_people \ + -html { + } + + + +db_multirow -extend { item_url } subproject task_people_query { +} { + +} + + + +ad_return_template + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/task-revisions-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-revisions-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-revisions-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,37 @@ + + + + + + + + + + + oracle + 8.0 + + + + + SELECT t.item_id, + t.revision_id, + i.live_revision, + t.title as task_title, + t.description || ' -- ' || p.first_names || ' ' || p.last_name as description, + t.mime_type, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.actual_hours_worked + FROM pm_tasks_revisionsx t, cr_items i, persons p + WHERE t.item_id = :task_id and + t.item_id = i.item_id and + t.creation_user = p.person_id + ORDER BY t.revision_id asc + + + + + Index: openacs-4/packages/project-manager/www/task-revisions-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-revisions-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-revisions-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,42 @@ + + + + + + + + + + + postgresql + 7.3 + + + + + SELECT + t.item_id, + t.revision_id, + i.live_revision, + t.title as task_title, + t.description || ' -- ' || p.first_names || ' ' || p.last_name + as description, + t.mime_type, + to_char(t.end_date,'MM/DD/YYYY') as end_date, + t.percent_complete, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + t.actual_hours_worked + FROM + pm_tasks_revisionsx t, cr_items i, persons p + WHERE + t.item_id = :task_id and + t.item_id = i.item_id and + t.creation_user = p.person_id + ORDER BY + t.revision_id asc + + + + + Index: openacs-4/packages/project-manager/www/task-revisions.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-revisions.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-revisions.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,7 @@ + + @title@ + @context@ + + + + Index: openacs-4/packages/project-manager/www/task-revisions.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-revisions.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-revisions.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,113 @@ +# + +ad_page_contract { + + Shows all the revisions of a task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-04-30 + @arch-tag: 339a6143-11a3-4f1b-902d-a3cd71f7d531 + @cvs-id $Id: task-revisions.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @param orderby_revisions specifies how the revisions table will be sorted + +} { + task_id:integer + orderby_revisions:optional +} -properties { + revisions:multirow +} -validate { +} -errors { +} + + +set task_term [parameter::get -parameter "TaskName" -default "Task Revisions"] + +set title "$task_term Changes" + +set context [list "task-one?task_id=$task_id $task_term" "View"] + + +# Task Revisions, using list-builder --------------------------------- + +template::list::create \ + -name revisions \ + -multirow revisions \ + -key revision_id \ + -elements { + revision_id { + label "Subject" + display_col task_title + link_url_col item_url + link_html { title "View this revision" } + display_template {@revisions.task_title@@revisions.task_title@} + } + description { + label "Description" + display_template { + @revisions.description_rich;noquote@ + } + } + percent_complete { + label "Status" + display_template "@revisions.percent_complete@\%" + } + actual_hours_worked { + label "Hour to date" + display_template "@revisions.actual_hours_worked@ hrs" + } + estimated_hours_work_min { + label "Work estimate" + display_template "@revisions.estimated_hours_work_min@ - @revisions.estimated_hours_work_max@ hrs" + } + end_date { + label "Deadline" + } + } \ + -sub_class { + narrow + } + +set descriptions [list] + +db_multirow -extend { item_url description_rich old_revision_id } revisions task_revisions_query { +} { + set item_url [export_vars -base "task-one" -override {{task_revision_id $revision_id}} -exclude {revision_id} { revision_id task_id}] + + set richtext_list [list $description $mime_type] + + set description_rich [template::util::richtext::get_property html_value $richtext_list] + + set descriptions_length [llength $descriptions] + + # if there isn't any previous items, then we don't have to do a + # word diff. All the content is new. + if {$descriptions_length < 1} { + set description_rich $description_rich + lappend descriptions "$description_rich" + + } else { + + set old_description [lindex $descriptions [expr [llength $descriptions] - 1]] + set old_description [ad_html_to_text $old_description] + lappend descriptions "$description_rich" + + set description_rich [pm::util::word_diff \ + -split_by " " \ + -old "$old_description" \ + -start_old "" \ + -end_old "" \ + -start_new "" \ + -end_new "" \ + -new "[ad_html_to_text $description_rich]" \ + -filter_proc ""] + + # set description_rich [ad_html_to_text $description_rich] + set description_rich [ad_text_to_html -no_quote -includes_html -- $description_rich] + + } + +} + + + Index: openacs-4/packages/project-manager/www/task-select-project-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-select-project-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-select-project-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,30 @@ + + + + + + SELECT p.item_id as project_item_id, + p.title as project_name, + p.description as description, + p.mime_type, + o.organization_id as customer_id, + o.name as customer_name + FROM pm_projectsx p LEFT JOIN organizations o on p.customer_id = o.organization_id, + cr_items i, + pm_project_status s + WHERE p.project_id = i.live_revision and + p.parent_id = :root_folder and + p.status_id = s.status_id + [template::list::filter_where_clauses -and -name projects] + [template::list::orderby_clause -orderby -name projects] + + + + + + SELECT pm_project.get_root_folder (:package_id, 'f') + FROM dual + + + + Index: openacs-4/packages/project-manager/www/task-select-project-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-select-project-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-select-project-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,29 @@ + + + + + + SELECT + p.item_id as project_item_id, + p.title as project_name, + p.description as description, + p.mime_type, + o.organization_id as customer_id, + o.name as customer_name + FROM + pm_projectsx p + LEFT JOIN + organizations o + ON + p.customer_id = o.organization_id, + cr_items i, + pm_project_status s + WHERE p.project_id = i.live_revision and + p.parent_id = :root_folder and + p.status_id = s.status_id + [template::list::filter_where_clauses -and -name projects] + [template::list::orderby_clause -orderby -name projects] + + + + Index: openacs-4/packages/project-manager/www/task-select-project.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-select-project.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-select-project.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,29 @@ + +@context@ +@title@ + + + + + + + + + + + +
    + +
    + Project Search:
    + + @hidden_vars;noquote@ +
    + + + +
    + + + +
    Index: openacs-4/packages/project-manager/www/task-select-project.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/task-select-project.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/task-select-project.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,156 @@ +ad_page_contract { + + Page to get the project if one is missing for task creation + + @author jader@bread.com + @creation-date 2003-10-06 + @cvs-id $Id: task-select-project.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return context_bar Context bar. + @return title Page title. + @return projects A multirow containing the list of projects + + @param process_id The process we're using to create this task +} { + + {process_id:integer ""} + {process_task_id:integer,multiple ""} + {project_item_id ""} + {return_url ""} + {status_type "o"} + {searchterm ""} + {orderby ""} + +} -properties { + + context_bar:onevalue + title:onevalue + choices:onevalue + searchterm_copy:onevalue + +} -validate { +} -errors { +} + +# --------------------------------------------------------------- # + +set user_id [auth::require_login] +set package_id [ad_conn package_id] + +permission::require_permission -object_id $package_id -privilege write + +if {[empty_string_p $searchterm]} { + unset searchterm +} + +set hidden_vars [export_vars -form {process_id return_url process_task_id:multiple}] + +if {[exists_and_not_null project_item_id]} { + ad_returnredirect [export_vars -base task-add-edit {project_item_id process_id return_url process_task_id:multiple}] +} + + +# terminology +set Project_Term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term [parameter::get -parameter "projectname" -default "project"] +set Task_Term [parameter::get -parameter "TaskName" -default "Task"] +set task_term [parameter::get -parameter "taskname" -default "task"] + +if {[empty_string_p $process_id]} { + set title "Select a $project_term to assign this $task_term to" +} else { + set title "Select a $project_term to assign this process to" +} + +if {![exists_and_not_null searchterm]} { + set searchterm_copy "" + set searchterm_where_clause "" +} else { + set searchterm_copy $searchterm + set searchterm_where_clause "upper(p.title) like upper('%$searchterm%')" +} + +if {[exists_and_not_null process_id]} { + set context [list [list "processes" "Processes"] "Use"] +} else { + set context [list [list "tasks" "Tasks"] "Select Project"] +} + +# need to change this to show all the projects you're on by +# default, and then give you the option of selecting all projects +# as an option. + +set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + +template::list::create \ + -name projects \ + -multirow projects \ + -key project_item_id \ + -elements { + customer_name { + label "Customer" + } + project_item_id { + label "Project" + link_url_col item_url + display_template "@projects.project_name@" + } + description { + label "Description" + display_template "@projects.description_html;noquote@" + } + } \ + -sub_class { + narrow + } \ + -filters { + customer_name { + label "Customer" + where_clause {p.organization_id = :customer_id} + } + + searchterm { + label "Project Search term" + where_clause $searchterm_where_clause + } + + status_type { + label "Status" + values {{"Open" o} {"Closed" c}} + where_clause { + s.status_type = :status_type + } + } + return_url { + hide_p 1 + } + } \ + -orderby { + default_value customer_name,asc + project_item_id { + label "Project" + orderby_desc "upper(p.title) desc" + orderby_asc "upper(p.title) asc" + default_direction asc + } + customer_name { + label "Customer" + orderby_desc "upper(o.name) desc, upper(p.title) desc" + orderby_asc "upper(o.name) asc, upper(p.title) asc" + default_direction asc + } + } \ + -orderby_name orderby \ + -html { + width 100% + } + + +db_multirow -extend { item_url description_html } projects select_a_project { +} { + set item_url [export_vars -base "task-add-edit" {project_item_id process_id process_task_id:multiple return_url}] + + set richtext_list [list $description $mime_type] + set description_html [template::util::richtext::get_property html_value $richtext_list] +} + Index: openacs-4/packages/project-manager/www/tasks-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/tasks-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/tasks-oracle.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,53 @@ + + +oracle8.0 + + + + SELECT ts.task_id as task_item_id, + ts.task_number, + t.task_revision_id, + t.title, + t.description, + t.parent_id as project_item_id, + proj_rev.logger_project, + proj_rev.title as project_name, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(sysdate,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name as full_name, + substr(r.one_line,1,1) as role + FROM pm_tasks_active ts, + cr_items i, + pm_tasks_revisionsx t , + pm_task_assignment ta , + persons p , + pm_roles r , + cr_items proj, + pm_projectsx proj_rev + WHERE t.item_id = ta.task_id (+) and + ta.party_id = p.person_id (+) and + ta.role_id = r.role_id (+) and + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + t.parent_id = proj.item_id and + proj.live_revision = proj_rev.revision_id + [template::list::filter_where_clauses -and -name tasks] + [template::list::orderby_clause -orderby -name tasks] + + + + Index: openacs-4/packages/project-manager/www/tasks-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/tasks-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/tasks-postgresql.xql 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,59 @@ + + +postgresql7.2 + + + + SELECT + ts.task_id as task_item_id, + ts.task_number, + t.task_revision_id, + t.title, + t.description, + t.parent_id as project_item_id, + proj_rev.logger_project, + proj_rev.title as project_name, + to_char(t.earliest_start,'J') as earliest_start_j, + to_char(current_timestamp,'J') as today_j, + to_char(t.latest_start,'J') as latest_start_j, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + t.percent_complete, + t.estimated_hours_work, + t.estimated_hours_work_min, + t.estimated_hours_work_max, + case when t.actual_hours_worked is null then 0 + else t.actual_hours_worked end as actual_hours_worked, + to_char(t.earliest_start,'YYYY-MM-DD HH24:MI') as earliest_start, + to_char(t.earliest_finish,'YYYY-MM-DD HH24:MI') as earliest_finish, + to_char(t.latest_start,'YYYY-MM-DD HH24:MI') as latest_start, + to_char(t.latest_finish,'YYYY-MM-DD HH24:MI') as latest_finish, + p.first_names || ' ' || p.last_name as full_name, + r.one_line as role + FROM + pm_tasks_active ts, + cr_items i, + pm_tasks_revisionsx t + LEFT JOIN pm_task_assignment ta + ON t.item_id = ta.task_id + LEFT JOIN persons p + ON ta.party_id = p.person_id + LEFT JOIN pm_roles r + ON ta.role_id = r.role_id, + cr_items proj, + cr_folders f, + pm_projectsx proj_rev + WHERE + ts.task_id = t.item_id and + i.item_id = t.item_id and + t.task_revision_id = i.live_revision and + t.parent_id = proj.item_id and + proj.live_revision = proj_rev.revision_id + and proj.parent_id = f.folder_id + and f.package_id = :package_id + [template::list::filter_where_clauses -and -name tasks] + [template::list::orderby_clause -orderby -name tasks] + + + + Index: openacs-4/packages/project-manager/www/tasks.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/tasks.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/tasks.adp 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,36 @@ + + + + + @task_term@s + @context@ + + + + + + + + + + + + +
    + +
    + Search:
    + + @hidden_vars;noquote@ +
    + + + +
    + + + +
    + + + Index: openacs-4/packages/project-manager/www/tasks.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/tasks.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/tasks.tcl 29 Apr 2005 17:43:38 -0000 1.1 @@ -0,0 +1,303 @@ +ad_page_contract { + + Main view page for tasks. + + @author jader@bread.com + @creation-date 2003-12-03 + @cvs-id $Id: tasks.tcl,v 1.1 2005/04/29 17:43:38 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return tasks Multirow data set of tasks + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) + + @param mine_p is used to make the default be the user, but + still allow people to view everyone. + +} { + orderby:optional + party_id:optional + {searchterm ""} + {mine_p "t"} + {status_id ""} + role_id:optional +} -properties { + task_term:onevalue + context:onevalue + tasks:multirow + hidden_vars:onevalue +} + +# if someone clicks on a party, then we want to see those tasks. +if {[exists_and_not_null party_id]} { + set mine_p "f" +} + +# --------------------------------------------------------------- # + +# terminology and parameters +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +set use_days_p [parameter::get -parameter "UseDayInsteadOfHour" -default "t"] + +set exporting_vars { status_id party_id orderby mine_p } +set hidden_vars [export_vars -form $exporting_vars] +# how to get back here +set return_url [ad_return_url -qualified] +set logger_url [pm::util::logger_url] + +# set up context bar +set context [list "Tasks"] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# if mine_p is true, show only my tasks +if {[string equal $mine_p t]} { + set party_id $user_id +} + +# status defaults to open +if {![exists_and_not_null status_id]} { + set status_id [pm::task::default_status_open] +} + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# Tasks, using list-builder --------------------------------- + +if {![empty_string_p $searchterm]} { + + # if we're searching, we disregard who we were searching for. + if {[info exists party_id]} { + unset party_id + } + set mine_p "f" + + if {[regexp {([0-9]+)} $searchterm match query_digits]} { + set search_term_where " (upper(t.title) like upper('%$searchterm%') + or t.item_id = :query_digits) " + } else { + set search_term_where " upper(t.title) like upper('%$searchterm%')" + } +} else { + set search_term_where "" +} + + +set default_orderby [pm::task::default_orderby] + +if {[exists_and_not_null orderby]} { + pm::task::default_orderby \ + -set $orderby +} + + +set elements { + task_number { + label "\#" + link_url_col item_url + link_html { title "View this project version" } + display_template {@tasks.task_item_id@} + } + title { + label "Subject" + } + slack_time { + label "Slack" + display_template "@tasks.slack_time@@tasks.slack_time@" + } + role { + label "Role" + } + latest_start_pretty { + label "Latest Start" + } + latest_finish_pretty { + label "Latest Finish" + display_template { + @tasks.latest_finish_pretty@ + } + } +} + +if {[string is true $use_days_p]} { + append elements { + days_remaining { + label "Days work" + html { + align right + } + } + } +} else { + append elements { + hours_remaining { + label "Hours remaining" + html { + align right + } + } + } +} + +append elements { + project_item_id { + label "Project" + display_col project_name + link_url_eval {[export_vars -base one {project_item_id $tasks(project_item_id)}]} + } + log_url { + label "Log" + display_template {L} + } + percent_complete { + display_template "" + } +} + +template::list::create \ + -name tasks \ + -multirow tasks \ + -key task_item_id \ + -elements $elements \ + -actions [list "Add task" [export_vars -base task-select-project {return_url}] "Add a task"] \ + -bulk_actions { + "Log hours" "log-bulk" "Log hours for several tasks" + "Edit tasks" "task-add-edit" "Edit multiple tasks" + } \ + -bulk_action_export_vars { + {return_url} + } \ + -sub_class { + narrow + } \ + -filters { + searchterm { + label "Search" + where_clause {$search_term_where} + } + role_id { + label "Roles" + values {[pm::role::select_list_filter]} + where_clause { + ta.role_id = :role_id + } + } + party_id { + label "People" + values {[pm::task::assignee_filter_select -status_id $status_id]} + where_clause { + ta.party_id = :party_id + } + } + status_id { + label "Status" + values {[db_list_of_lists get_status_values "select description, status_id from pm_task_status order by status_type desc, description"]} + where_clause {ts.status = :status_id} + } + mine_p { + label "Show others' tasks" + } + } \ + -orderby { + default_value $default_orderby + task_number { + label "Task \#" + orderby_desc "ts.task_number desc, p.first_names, p.last_name" + orderby_asc "ts.task_number asc, p.first_names, p.last_name" + default_direction asc + } + title { + label "Subject" + orderby_desc "t.title desc, ts.task_id, p.first_names, p.last_name" + orderby_asc "t.title asc, ts.task_id, p.first_names, p.last_name" + default_direction asc + } + full_name { + label "Who" + orderby_desc "p.first_names desc,p.last_name desc, ts.task_id" + orderby_asc "p.first_names, p.last_name, ts.task_id" + default_direction asc + } + description { + label "Description" + orderby_desc "t.description desc, ts.task_id, p.first_names, p.last_name" + orderby_asc "t.description, ts.task_id, p.first_names, p.last_name" + default_direction asc + } + slack_time { + label "Slack" + orderby_desc "(latest_start - earliest_start) desc, ts.task_id, p.first_names, p.last_name" + orderby_asc "(latest_start - earliest_start), ts.task_id, p.first_names, p.last_name" + default_direction asc + } + latest_start_pretty { + label "Latest start" + orderby_desc "t.latest_start desc, ts.task_id, p.first_names, p.last_name" + orderby_asc "t.latest_start, ts.task_id, p.first_names, p.last_name" + default_direction asc + } + latest_finish_pretty { + label "Latest finish" + orderby_desc "t.latest_finish desc, ts.task_id, p.first_names, p.last_name" + orderby_asc "t.latest_finish, ts.task_id, p.first_names, p.last_name" + default_direction asc + } + } \ + -orderby_name orderby \ + -html { + width 100% + } + + + + +db_multirow -extend { item_url latest_start_pretty latest_finish_pretty slack_time log_url hours_remaining days_remaining} tasks tasks { +} { + set item_url [export_vars -base "task-one" {{task_id $task_item_id}}] + + set log_url [export_vars -base "${logger_url}log" {{project_id $logger_project} {pm_task_id $task_item_id} {pm_project_id $project_item_id} {return_url $return_url}}] + + set latest_start_pretty [lc_time_fmt $latest_start "%x"] + set latest_finish_pretty [lc_time_fmt $latest_finish "%x"] + + if {[exists_and_not_null earliest_start_j]} { + set slack_time [pm::task::slack_time \ + -earliest_start_j $earliest_start_j \ + -today_j $today_j \ + -latest_start_j $latest_start_j] + } else { + set slack_time "n/a" + } + + set hours_remaining \ + [pm::task::hours_remaining \ + -estimated_hours_work $estimated_hours_work \ + -estimated_hours_work_min $estimated_hours_work_min \ + -estimated_hours_work_max $estimated_hours_work_max \ + -percent_complete $percent_complete] + + set days_remaining \ + [pm::task::days_remaining \ + -estimated_hours_work $estimated_hours_work \ + -estimated_hours_work_min $estimated_hours_work_min \ + -estimated_hours_work_max $estimated_hours_work_max \ + -percent_complete $percent_complete] + +} + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/admin/default-project-roles-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/default-project-roles-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/default-project-roles-oracle.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,20 @@ + + +oracle8.0 + + + + SELECT role_id, + party_id + FROM pm_default_roles + + + + + + select pm_project.get_root_folder (:package_id, 'f') + from dual + + + + Index: openacs-4/packages/project-manager/www/admin/default-project-roles-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/default-project-roles-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/default-project-roles-postgresql.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,15 @@ + + +postgresql7.2 + + + + SELECT + role_id, + party_id + FROM + pm_default_roles + + + + Index: openacs-4/packages/project-manager/www/admin/default-project-roles.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/default-project-roles.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/default-project-roles.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,10 @@ + + + + +@project_term@s +@context_bar;noquote@ + + + + Index: openacs-4/packages/project-manager/www/admin/default-project-roles.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/default-project-roles.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/default-project-roles.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,92 @@ +ad_page_contract { + + page to view project roles + + @author jader@bread.com + @creation-date 2003-09-10 + @cvs-id $Id: default-project-roles.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return roles Multirow data set of project roles + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) +} { + {orderby_r ""} +} -properties { + + context_bar:onevalue + projects:multirow + write_p:onevalue + create_p:onevalue + admin_p:onevalue + task_term:onevalue + task_term_lower:onevalue + project_term:onevalue + project_term_lower:onevalue +} + +# --------------------------------------------------------------- # + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +# set up context bar +set context_bar [ad_context_bar "View $project_term_lower roles"] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# root CR folder +set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + +# Project roles, using list-builder --------------------------------- + +template::list::create \ + -name roles \ + -multirow roles \ + -key role_id \ + -elements { + role_id { + label "Role ID" + link_url_col item_url + link_html { title "Edit this role" } + } + party_id { + label "Party ID" + } + } \ + -filters { + orderby_r {} + } \ + -orderby { + role_id {orderby role_id} + party_id {orderby party_id} + default_value role_id,asc + } \ + -orderby_name orderby_r \ + -html { + width 100% + } + + +db_multirow -extend { item_url } roles default_project_roles_query { +} { + set item_url [export_vars -base "default-project-role-add-edit" -override {{project_item_id}} {project_item_id}] +} + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/admin/index-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/index-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/index-oracle.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,36 @@ + + +oracle8.0 + + + + SELECT p.item_id, + p.project_id, + p.parent_id as folder_id, + p.object_type as content_type, + p.title as project_name, + p.project_code, + to_char(p.planned_start_date, 'Mon DD ''YY') as planned_start_date, + to_char(p.planned_end_date, 'Mon DD ''YY') as planned_end_date, + p.ongoing_p, + p.actual_hours_completed, + p.estimated_hours_total, + to_char(p.estimated_finish_date, 'Mon DD ''YY') as estimated_finish_date, + to_char(p.earliest_finish_date, 'Mon DD ''YY') as earliest_finish_date, + to_char(p.latest_finish_date, 'Mon DD ''YY') as latest_finish_date + FROM pm_projectsx p, + cr_items i + WHERE p.project_id = i.live_revision and + p.parent_id = :root_folder + ORDER BY p.title + + + + + + SELECT pm_project.get_root_folder (:package_id, 'f') + FROM dual + + + + Index: openacs-4/packages/project-manager/www/admin/index-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/index-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/index-postgresql.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,29 @@ + + +postgresql7.2 + + + + SELECT + p.item_id, + p.project_id, + p.parent_id as folder_id, + p.object_type as content_type, + p.title as project_name, + p.project_code, + to_char(p.planned_start_date, 'Mon DD ''YY') as planned_start_date, + to_char(p.planned_end_date, 'Mon DD ''YY') as planned_end_date, + p.ongoing_p, + p.actual_hours_completed, + p.estimated_hours_total, + to_char(p.estimated_finish_date, 'Mon DD ''YY') as estimated_finish_date, + to_char(p.earliest_finish_date, 'Mon DD ''YY') as earliest_finish_date, + to_char(p.latest_finish_date, 'Mon DD ''YY') as latest_finish_date + FROM pm_projectsx p, cr_items i + WHERE p.project_id = i.live_revision and + p.parent_id = :root_folder + ORDER BY p.title + + + + Index: openacs-4/packages/project-manager/www/admin/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/index.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/index.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,124 @@ + + + + + @title@ + @context;noquote@ + + Click on one of the following items to set it up: + +

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    SectionActionDescription
    RolesViewThe roles people can take on projects and tasks, such as + manager, sales contact, tech support person, etc.. Currently, + can only be edited directly in the database.
    Default rolesViewThe data model has a facility for default roles, although + it is not currently used at all. This shows what is in the + database for default roles. Currently unimplemented.
    WorkgroupsViewThere is a data model for workgroups, but it is not a part + of the UI. Shows what is in the database (currently, nothing!)
    Dependency typesNo UIWhen implemented, this page will allow you to view and + edit the descriptions given to various dependency types (such + as finish before start, etc..) Currently, the only dependency + used is finish before start, so it's not exposed in the UI
    Status typesNo UIValid status codes, for example, 'Open' and 'Closed'
    Project categoriesEdit categoriesProjects can be categorized according to multiple 'trees' + of categories. What this means is you can have multiple ways + of categorizing your projects. This section sets up your + categories and allows you to link them to projects. Currently, + there is a bug in the categories package that prevents the + context bar at the top of the screen from returning you to the + project-manager pages.
    Logger integrationSet upLogger is a package that lets you log time, expenses, and + other variables. Project manager requires you to + install and mount at least one instance of logger, because it + uses logger to log time and other variables against projects + and tasks. However, you can have varying levels of integration + with logger. This section sets up which logger instances you + want to be fully integrated with project-manager, so that new + project-manager projects appear in the logger instance.

    + @logger_warning;noquote@ +

    Set upYou must choose a logger instance to be the primary + logger linked in with project-manager. This is closely linked + in with project-manager, so you can view reports of a project, etc. +

    + @logger_primary_warning;noquote@ +

    SyncOnce you have chosen logger instances to be integrated + with project-manager, you may have a lot of older + project-manager projects that are not synchronized with + logger. This page lets you synchronize older project-manager + projects with logger, so that they are all linked in correctly + with that instance. This does not add in logger projects to + project-manager (although someone can certainly add that + functionality if they wish). +
    ParametersEditThe parameters allow you to do things such as set up daily + reminder emails, change what fields are shown in the project + view and edit pages, and so on. Highly recommended if you're + setting up project-manager.
    ProjectsUpdate allThis page allows you to update the deadlines of all the + projects in your installation. It will take a while.
    + Index: openacs-4/packages/project-manager/www/admin/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/index.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/index.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,78 @@ +ad_page_contract { + + Main admin view page + + @author jader@bread.com + @creation-date 2003-09-10 + @cvs-id $Id: index.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return projects Multirow data set of projects. + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) + +} -properties { + + categories_link:onevalue + context:onevalue + projects:multirow + write_p:onevalue + create_p:onevalue + admin_p:onevalue + task_term:onevalue + task_term_lower:onevalue + project_term:onevalue + project_term_lower:onevalue + logger_link:onevalue + logger_primary_link:onevalue + logger_sync_link:onevalue +} + +# --------------------------------------------------------------- # + +set logger_URLs [parameter::get -parameter "LoggerURLsToKeepUpToDate" -default ""] +set logger_primary [parameter::get -parameter "LoggerPrimaryURL" -default ""] + +# set up context bar +set context [list] +set title "Project Manager Administration" + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# set up links +set categories_link "/categories/cadmin/one-object?object_id=$package_id" +set parameters_link "/shared/parameters?package_id=$package_id&return_url=[site_node::get_package_url -package_key project-manager]admin/" +set logger_link "logger" +set logger_primary_link "logger-primary" +set logger_sync_link "logger-sync" +set update_projects_link "update-projects" + +if {[empty_string_p $logger_URLs]} { + set logger_warning "not set up" +} else { + set logger_warning "Currently integrated:

    • [join $logger_URLs "
    • "]
    " +} + +if {[empty_string_p $logger_primary]} { + set logger_primary_warning "not set up" +} else { + set logger_primary_warning "Currently selected:
    • $logger_primary
    " +} + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege admin + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# root CR folder +set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/admin/logger-primary.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/logger-primary.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/logger-primary.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,22 @@ + + @title@ + @context@ + + Logger is a package that lets you log time, expenses, and + other variables. Project manager requires you to + install and mount at least one instance of logger, because it + uses logger to log time and other variables against projects + and tasks. However, you can have varying levels of integration + with logger. This section sets up which logger instances you + want to be fully integrated with project-manager, so that new + project-manager projects appear in the logger instance. + +

    + + There is currently a bug in this page where it will not allow you to + remove values. You will have to do that through the parameters section. + +

    + + + Index: openacs-4/packages/project-manager/www/admin/logger-primary.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/logger-primary.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/logger-primary.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,67 @@ +# /project-manager/www/admin/logger-primary.tcl + +ad_page_contract { + + Sets up which instances of logger to integrate with project-manager + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-21 + @arch-tag: bac17115-5b9e-4b63-adac-8deb6fef3015 + @cvs-id $Id: logger-primary.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ +} { + +} -properties { +} -validate { +} -errors { +} + +# set up context bar and title +set context [list "Logger integration"] +set title "Administration: setting up primary logger instance" + +set package_id [ad_conn package_id] + +set possible_URLs [parameter::get -parameter "LoggerURLsToKeepUpToDate" -default ""] + +set logger_primary [parameter::get -parameter "LoggerPrimaryURL" -default ""] + +ad_form -name logger \ + -form { + acs_object_id_seq:key + } + +set logger_options [list] + +foreach url $possible_URLs { + + lappend logger_options [list $url $url] +} + +set logger_definition " + {package_url:text(select) + {label \"Primary logger instance\"} + {options {$logger_options}} + {value $logger_primary} + } +" + + +ad_form -extend -name logger \ + -form $logger_definition + + +ad_form -extend -name logger \ + -on_submit { + + parameter::set_value \ + -package_id $package_id \ + -parameter LoggerPrimaryURL \ + -value "$package_url" + + ad_returnredirect -message "Primary logger instance saved" . + + } \ + -new_data { + } \ + -edit_data { + } \ Index: openacs-4/packages/project-manager/www/admin/logger-sync.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/logger-sync.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/logger-sync.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,24 @@ + + @title@ + @context@ + + + + Done. + + + + + Are you ready to sync with these URLs? +

      + +
    • @logger_URLs:item@
    • +
      +
    + +

    + Begin synchronization (be patient, + this takes a long time, you can read the log files to see what's + happening if you like.) + + Index: openacs-4/packages/project-manager/www/admin/logger-sync.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/logger-sync.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/logger-sync.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,93 @@ +# + +ad_page_contract { + + Synchronizes the projects in logger and project-manager + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-04 + @arch-tag: fc794335-9bb0-4447-92cf-b3c1c69124bd + @cvs-id $Id: logger-sync.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ +} { + {confirmed_p "n"} +} -properties { +} -validate { +} -errors { +} + +set title "Synchronize logger projects" +set context [list $title] + +set logger_URLs [parameter::get -parameter "LoggerURLsToKeepUpToDate" -default ""] + +if {[string equal $confirmed_p n]} { + set confirm_link [export_vars -base logger-sync {{confirmed_p y}}] +} else { + + # projects + set projects_list [db_list_of_lists get_projects_not_already_linked { + SELECT + p.title as project_name, + p.description, + p.creation_user, + p.item_id as project_item_id, + p.status_id, + p.customer_id as organization_id, + p.logger_project + FROM + pm_projectsx p, + cr_items i + WHERE + i.item_id = p.item_id and + i.live_revision = p.revision_id + }] + + foreach project $projects_list { + set project_name [lindex $project 0] + set description [lindex $project 1] + set creation_user [lindex $project 2] + set project_item_id [lindex $project 3] + set status_id [lindex $project 4] + set organization_id [lindex $project 5] + set logger_project [lindex $project 6] + + set active_p [pm::status::open_p -task_status_id $status_id] + set customer_name [organizations::name -organization_id "$organization_id"] + if {![empty_string_p $customer_name]} { + append customer_name " - " + } + + logger::project::edit \ + -project_id $logger_project \ + -name "$customer_name$project_name" \ + -description "$description" \ + -project_lead $creation_user \ + -active_p $active_p + + + foreach url $logger_URLs { + # get the package_id + set node_id [site_node::get_node_id -url $url] + array set node [site_node::get -node_id $node_id] + set this_package_id $node(package_id) + + # make sure the project_id is not already mapped + + set num_exists [db_string already_exists_p "select count(*) from logger_project_pkg_map where project_id = :logger_project and package_id = :this_package_id" -default "0"] + + ns_log Notice "Logger sync: (num_exists: $num_exists) (project: $logger_project package_id: $this_package_id)" + + if {$num_exists < 1} { + ns_log Notice "Logger sync: Mapping: (project: $logger_project package_id: $this_package_id)" + logger::package::map_project \ + -project_id $logger_project \ + -package_id $this_package_id + } + } + + } + + ad_returnredirect -message "Logger projects synchronized" index +} + + Index: openacs-4/packages/project-manager/www/admin/logger.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/logger.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/logger.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,22 @@ + + @title@ + @context@ + + Logger is a package that lets you log time, expenses, and + other variables. Project manager requires you to + install and mount at least one instance of logger, because it + uses logger to log time and other variables against projects + and tasks. However, you can have varying levels of integration + with logger. This section sets up which logger instances you + want to be fully integrated with project-manager, so that new + project-manager projects appear in the logger instance. + +

    + + There is currently a bug in this page where it will not allow you to + remove values. You will have to do that through the parameters section. + +

    + + + Index: openacs-4/packages/project-manager/www/admin/logger.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/logger.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/logger.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,84 @@ +# /project-manager/www/admin/logger.tcl + +ad_page_contract { + + Sets up which instances of logger to integrate with project-manager + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-05-21 + @arch-tag: bac17115-5b9e-4b63-adac-8deb6fef3015 + @cvs-id $Id: logger.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ +} { + +} -properties { +} -validate { +} -errors { +} + +# set up context bar and title +set context [list "Logger integration"] +set title "Administration: setting up logger integration" + +set package_id [ad_conn package_id] + +set logger_URLs [parameter::get -parameter "LoggerURLsToKeepUpToDate" -default ""] + +set possible_URLs [site_node::get_children -all -package_key logger -node_id [site_node::get_node_id -url "/"]] + +ad_form -name logger \ + -form { + acs_object_id_seq:key + } + +set logger_definition "" +set index 0 +foreach url $possible_URLs { + + if {[lsearch $logger_URLs $url] >= 0} { + set value t + } else { + set value "" + } + + append logger_definition " + + {package_url_$url:text(checkbox),optional + {label \"$url\"} + {options {{\"\" \"t\"}}} + {value $value} + } + " + + incr index +} + + ad_form -extend -name logger \ + -form $logger_definition + + +ad_form -extend -name logger \ + -on_submit { + + # go through each URL, find out if it has been checked, and + # save it if so. + + set urls_list [list] + foreach url $possible_URLs { + + set this_value "[set package_url_[set url]]" + if {[string equal t $this_value]} { + lappend urls_list $url + } + } + parameter::set_value \ + -package_id $package_id \ + -parameter LoggerURLsToKeepUpToDate \ + -value "$urls_list" + + ad_returnredirect -message "List of integrated logger instances saved" . + + } \ + -new_data { + } \ + -edit_data { + } \ Index: openacs-4/packages/project-manager/www/admin/roles-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/roles-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/roles-oracle.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,23 @@ + + +oracle8.0 + + + + SELECT role_id, + one_line, + description, + is_observer_p, + sort_order + FROM pm_roles + + + + + + select pm_project.get_root_folder (:package_id, 'f') + from dual + + + + Index: openacs-4/packages/project-manager/www/admin/roles-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/roles-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/roles-postgresql.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,18 @@ + + +postgresql7.2 + + + + SELECT + role_id, + one_line, + description, + is_observer_p, + sort_order + FROM + pm_roles + + + + Index: openacs-4/packages/project-manager/www/admin/roles.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/roles.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/roles.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,10 @@ + + + + +@project_term;noquote@s +@context_bar;noquote@ + + + + Index: openacs-4/packages/project-manager/www/admin/roles.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/roles.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/roles.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,101 @@ +ad_page_contract { + + page to view roles + + @author jader@bread.com + @creation-date 2003-09-10 + @cvs-id $Id: roles.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return tasks Multirow data set of task roles + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) +} { + {orderby_r ""} +} -properties { + + context_bar:onevalue + roles:multirow + write_p:onevalue + create_p:onevalue + admin_p:onevalue + task_term:onevalue + task_term_lower:onevalue + project_term:onevalue + project_term_lower:onevalue +} + +# --------------------------------------------------------------- # + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +# set up context bar +set context_bar [ad_context_bar "View $project_term_lower roles"] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# root CR folder +set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + +# Project roles, using list-builder --------------------------------- + +template::list::create \ + -name roles \ + -multirow roles \ + -key role_id \ + -elements { + role_id { + label "Role ID" + link_url_col item_url + link_html { title "Edit this role" } + } + one_line { + label "One line description" + } + description { + label "Description" + } + is_observer_p { + label "Observer?" + } + sort_order { + label "Sort order" + } + } \ + -filters { + orderby_r {} + } \ + -orderby { + one_line {orderby one_line} + sort_order {orderby sort_order} + default_value sort_order,asc + } \ + -orderby_name orderby_r \ + -html { + width 100% + } + + +db_multirow -extend { item_url } roles roles_query { +} { + set item_url [export_vars -base "ask-role-add-edit" -override {{project_item_id}} {project_item_id}] +} + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/admin/update-projects.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/update-projects.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/update-projects.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,41 @@ +# /project-manager/www/admin/update-projects.tcl + +ad_page_contract { + page which updates the status of all projects and tasks + + @author jader@bread.com + @cvs-id $Id: update-projects.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ + @creation-date 11/24/03 +} { +} + +ns_log Debug "---------------------------------------------------" +ns_log Debug "Project manager: Updating all projects" + +# make sure user is administrator +set user_id [ad_conn user_id] + +permission::require_permission -party_id $user_id -object_id $user_id -privilege admin + +set context_id [ad_conn package_id] +set peeraddr [ad_conn peeraddr] + +ns_write "Updating projects and tasks + +Starting...

    " + + +set projects_list [db_list get_projects "select item_id from cr_items where content_type = 'pm_project'"] + +foreach project $projects_list { + pm::project::compute_status $project + ns_write ". " +} + + +ns_log Notice "done with project update page (finally!)" + + +ns_write " +back to admin page" + Index: openacs-4/packages/project-manager/www/admin/workgroups-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/workgroups-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/workgroups-oracle.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,22 @@ + + +oracle8.0 + + + + SELECT workgroup_id, + one_line, + description, + sort_order + FROM pm_workgroup + + + + + + select pm_project.get_root_folder (:package_id, 'f') + from dual + + + + Index: openacs-4/packages/project-manager/www/admin/workgroups-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/workgroups-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/workgroups-postgresql.xql 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,17 @@ + + +postgresql7.2 + + + + SELECT + workgroup_id, + one_line, + description, + sort_order + FROM + pm_workgroup + + + + Index: openacs-4/packages/project-manager/www/admin/workgroups.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/workgroups.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/workgroups.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,10 @@ + + + + +@project_term@s +@context_bar;noquote@ + + + + Index: openacs-4/packages/project-manager/www/admin/workgroups.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/admin/workgroups.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/admin/workgroups.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,98 @@ +ad_page_contract { + + page to view workgroups + + @author jader@bread.com + @creation-date 2003-09-10 + @cvs-id $Id: workgroups.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ + + @return title Page title. + @return context Context bar. + @return tasks Multirow data set of task roles + @return task_term Terminology for tasks + @return task_term_lower Terminology for tasks (lower case) + @return project_term Terminology for projects + @return project_term_lower Terminology for projects (lower case) +} { + {orderby_r ""} +} -properties { + + context_bar:onevalue + workgroup:multirow + write_p:onevalue + create_p:onevalue + admin_p:onevalue + task_term:onevalue + task_term_lower:onevalue + project_term:onevalue + project_term_lower:onevalue +} + +# --------------------------------------------------------------- # + +# terminology +set task_term [parameter::get -parameter "TaskName" -default "Task"] +set task_term_lower [parameter::get -parameter "taskname" -default "task"] +set project_term [parameter::get -parameter "ProjectName" -default "Project"] +set project_term_lower [parameter::get -parameter "projectname" -default "project"] + +# set up context bar +set context_bar [ad_context_bar "View $project_term_lower workgroups"] + +# the unique identifier for this package +set package_id [ad_conn package_id] +set user_id [auth::require_login] + +# permissions +permission::require_permission -party_id $user_id -object_id $package_id -privilege read + +set write_p [permission::permission_p -object_id $package_id -privilege write] +set create_p [permission::permission_p -object_id $package_id -privilege create] +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# root CR folder +set root_folder [db_string get_root "select pm_project__get_root_folder (:package_id, 'f')"] + +# Project workgroups, using list-builder --------------------------------- + +template::list::create \ + -name workgroup \ + -multirow workgroup \ + -key role_id \ + -elements { + workgroup_id { + label "Workgroup ID" + link_url_col item_url + link_html { title "Edit this role" } + } + one_line { + label "One line description" + } + description { + label "Description" + } + sort_order { + label "Sort order" + } + } \ + -filters { + orderby_r {} + } \ + -orderby { + one_line {orderby one_line} + sort_order {orderby sort_order} + default_value sort_order,asc + } \ + -orderby_name orderby_r \ + -html { + width 100% + } + + +db_multirow -extend { item_url } workgroup wg_query { +} { + set item_url [export_vars -base "ask-role-add-edit" -override {{project_item_id}} {project_item_id}] +} + + +# ------------------------- END OF FILE ------------------------- # Index: openacs-4/packages/project-manager/www/comments/add.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/comments/add.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/comments/add.adp 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,5 @@ + + @title@ + @context@ + + Index: openacs-4/packages/project-manager/www/comments/add.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/comments/add.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/comments/add.tcl 29 Apr 2005 17:43:39 -0000 1.1 @@ -0,0 +1,78 @@ +# /packages/project-manager/www/comments/add.tcl + +ad_page_contract { + + Adds a general comment to a project or task + + @author Jade Rubick (jader@bread.com) + @creation-date 2004-06-09 + @arch-tag: 7448d185-3d5c-43f2-853e-de7c929c4526 + @cvs-id $Id: add.tcl,v 1.1 2005/04/29 17:43:39 timoh Exp $ +} { + object_id:integer,notnull + title:notnull + return_url:notnull + {type "task"} + {description:html ""} +} -properties { +} -validate { +} -errors { +} + +set display_title "Add a comment to: $title" +set context [list "$display_title"] + + +ad_form -name comment \ + -form { + acs_object_id_seq:key + + {object_id:text(hidden) + {value $object_id} + } + + {return_url:text(hidden) + {value "$return_url"} + } + + {type:text(hidden) + {value "$type"} + } + + {title:text + {label "Title"} + {html {size 50}} + } + + {description:richtext(richtext),optional + {label "Comment"} + {html { rows 9 cols 40 wrap soft}}} + + {send_email_p:text(select),optional + {label "Send email?"} + {options {{"Yes" "t"} {"No" "f"}}} + } + + } -new_request { + + set description [template::util::richtext::create "" {}] + + } -on_submit { + + # insert the comment into the database + set description_body [template::util::richtext::get_property contents $description] + set description_format [template::util::richtext::get_property format $description] + + pm::util::general_comment_add \ + -object_id $object_id \ + -title "$title" \ + -comment "$description_body" \ + -mime_type "$description_format" \ + -send_email_p $send_email_p \ + -type $type + + # does not seem to be working for some reason + util_user_message -message "Comment: [ad_quotehtml $title] saved" + ad_returnredirect $return_url + } + Index: openacs-4/packages/project-manager/www/lib/entries-table-oracle.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/entries-table-oracle.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/entries-table-oracle.xql 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,40 @@ + + + + postgresql7.2 + + + + SELECT le.entry_id as id, + acs_permission.permission_p(le.entry_id, :current_user_id, 'delete') as delete_p, + acs_permission.permission_p(le.entry_id, :current_user_id, 'write') as edit_p, + le.time_stamp, + to_char(le.time_stamp, 'fmDyfm fmMMfm-fmDDfm-YYYY') as time_stamp_pretty, + to_char(le.time_stamp, 'IW-YYYY') as time_stamp_week, + le.value, + le.description, + task.title as project_name, + submitter.person_id as user_id, + submitter.first_names || ' ' || submitter.last_name as user_name + FROM logger_entries le , + (SELECT r.title, + m.logger_entry + FROM cr_items i, + cr_revisions r, + pm_task_logger_proj_map m + WHERE r.item_id = m.task_item_id and + i.live_revision = r.revision_id) task, + logger_projects lp, + acs_objects ao, + persons submitter + WHERE le.entry_id = task.logger_entry (+) and + le.project_id = lp.project_id and + ao.object_id = le.entry_id and + ao.creation_user = submitter.person_id + [ad_decode $where_clauses "" "" "and [join $where_clauses "\n and "]"] + ORDER BY + $order_by + + + + Index: openacs-4/packages/project-manager/www/lib/entries-table-postgresql.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/entries-table-postgresql.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/entries-table-postgresql.xql 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,46 @@ + + + + postgresql7.2 + + + + SELECT + le.entry_id as id, + acs_permission__permission_p(le.entry_id, :current_user_id, 'delete') as delete_p, + acs_permission__permission_p(le.entry_id, :current_user_id, 'write') as edit_p, + le.time_stamp, + to_char(le.time_stamp, 'fmDyfm fmMMfm-fmDDfm-YYYY') as time_stamp_pretty, + to_char(le.time_stamp, 'IW-YYYY') as time_stamp_week, + le.value, + le.description, + task.title as project_name, + submitter.person_id as user_id, + submitter.first_names || ' ' || submitter.last_name as user_name + FROM + logger_entries le + LEFT JOIN (select + r.title, + m.logger_entry + from + cr_items i, + cr_revisions r, + pm_task_logger_proj_map m + where + r.item_id = m.task_item_id and + i.live_revision = r.revision_id) task + ON le.entry_id = task.logger_entry, + logger_projects lp, + acs_objects ao, + persons submitter + WHERE + le.project_id = lp.project_id and + ao.object_id = le.entry_id and + ao.creation_user = submitter.person_id + [ad_decode $where_clauses "" "" "and [join $where_clauses "\n and "]"] + ORDER BY + $order_by + + + + Index: openacs-4/packages/project-manager/www/lib/entries-table.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/entries-table.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/entries-table.adp 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,213 @@ + + + + There are no matching log entries + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
     TaskUserDate@variable.name@Description 
    +   +
    + + + User: @entries.user_chunk;noquote@ + + + Project: @entries.project_name@ + + + Date: @entries.time_stamp_pretty@ + + + Week: @entries.time_stamp_week@ + + + Unknown group by column @group_by@ + + +
    + + Edit + + @entries.project_name@@entries.user_chunk;noquote@@entries.time_stamp_pretty@ + @entries.value@ + + @entries.description@ + + + Delete + +
      + + Subtotal + + + Subtotal Average + + + + @entries.subtotal@ + + + @entries.subaverage@ + +   
    + + Edit + + @entries.project_name@@entries.user_chunk;noquote@@entries.time_stamp_pretty@ + + @entries.value@ + + + @entries.value@ + + + @entries.description@ + + + Delete + +
    +   +
      + + Total + + + Average + + + + + @value_total@ + + + @value_total@ + + + + + @value_average@ + + + @value_average@ + + +   
    +   +
     Projection@projection_value@  
        @variable.unit@  
    +
    + + Index: openacs-4/packages/project-manager/www/lib/entries-table.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/entries-table.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/entries-table.tcl 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,133 @@ +# Displays list of log entries +# +# Expects: +# selected_project_id +# selected_variable_id +# selected_user_id +# selected_entry_id +# start_date_ansi +# end_date_ansi +# projection_value +# group_by:optional +# pm_project_id project manager project ID +# pm_task_id project manger task ID + + +if {![exists_and_not_null pm_task_id]} { + set pm_task_id "" +} + + +set current_user_id [ad_conn user_id] +set package_id [ad_conn package_id] + +set where_clauses [list] +if { [exists_and_not_null selected_project_id] } { + # Only selected project + lappend where_clauses "lp.project_id = :selected_project_id" +} else { + # All projects mapped to the package + lappend where_clauses \ + "exists (select 1 + from logger_project_pkg_map + where project_id = lp.project_id + and package_id = :package_id + )" +} + + +if { [exists_and_not_null selected_variable_id] } { + db_1row select_variable_info {} -column_array variable + + lappend where_clauses "le.variable_id = :selected_variable_id" +} + +if { [exists_and_not_null selected_user_id] } { + lappend where_clauses "submitter.user_id = :selected_user_id" +} + +if { [exists_and_not_null start_date_ansi] } { + lappend where_clauses "le.time_stamp >= to_date(:start_date_ansi,'YYYY-MM-DD')" +} + +if { [exists_and_not_null end_date_ansi] } { + lappend where_clauses "le.time_stamp <= to_date(:end_date_ansi,'YYYY-MM-DD')" +} + +# if pm_task_id is passed in, then we limit what is displayed to that +# project manager task. + +if { [exists_and_not_null pm_task_id] } { + lappend where_clauses "le.entry_id in (select logger_entry from pm_task_logger_proj_map where task_item_id = :pm_task_id)" +} + + +if { ![exists_and_not_null selected_entry_id] } { + set selected_entry_id {} +} + +set order_by "le.time_stamp desc, ao.creation_date desc" + + +# If we're grouping by, we should sort by that column first +if { [exists_and_not_null group_by] } { + switch -exact $group_by { + user_id { + set order_by "user_name asc, $order_by" + } + project_name { + set order_by "project_name asc, $order_by" + } + } +} + +set value_total 0 +set value_count 0 + +set last_group_by_value {} +set value_subcount 0 +set value_subtotal 0 + +db_multirow -extend { subtotal subaverage view_url edit_url delete_url delete_onclick user_chunk selected_p } entries select_entries {} { + set description [string_truncate -len 50 -- $description] + set project_name [string_truncate -len 20 -- $project_name] + set selected_p [string equal $id $selected_entry_id] + set action_links_list [list] + set view_url "[ad_conn package_url]log?[export_vars { { entry_id $id } { pm_project_id $pm_project_id } {pm_task_id $pm_task_id} }]" + set edit_url "[ad_conn package_url]log?[export_vars { { entry_id $id } { edit "t" } {pm_project_id $pm_project_id} {pm_task_id $pm_task_id} }]" + if { $delete_p } { + set delete_onclick "return confirm('Are you sure you want to delete log entry with $value $variable(unit) $variable(name) on $time_stamp?');" + set delete_url "[site_node::get_package_url -package_key logger]log-delete?[export_vars { { entry_id $id } {pm_task_id $pm_task_id} {return_url "[ad_return_url]"} {confirm_p 1} }]" + } else { + set delete_url "" + } + + set user_chunk [ad_present_user $user_id $user_name] + + if { [exists_and_not_null group_by] } { + # Should we reset the subtotal? + if { ![string equal $last_group_by_value [set $group_by]] } { + set value_subtotal 0 + set value_subcount 0 + } + + # Calculate new subtotal/average + set value_subtotal [expr $value_subtotal + $value] + incr value_subcount + + # and store it in the column + set subtotal $value_subtotal + set subaverage [expr round(100.0 * $value_subtotal / $value_subcount) / 100.0] + + set last_group_by_value [set $group_by] + } + + set value_total [expr $value_total + $value] + incr value_count +} + +if { $value_count > 0 } { + set value_average [expr round(100.0 * $value_total / $value_count) / 100.0] } { + set value_average "n/a" +} + Index: openacs-4/packages/project-manager/www/lib/entries-table.xql =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/entries-table.xql,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/entries-table.xql 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,15 @@ + + + + + + + select name, + unit, + type + from logger_variables + where variable_id = :selected_variable_id + + + + Index: openacs-4/packages/project-manager/www/lib/master.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/master.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/master.adp 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,28 @@ + +@title;noquote@ +@context;noquote@ +@focus;noquote@ + + @header_stuff;noquote@ + + + + + + + + + + +

    + + + +

    + + Index: openacs-4/packages/project-manager/www/lib/master.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/master.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/master.tcl 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,5 @@ +if [template::util::is_nil context] { set context {}} + +set package_url [ad_conn package_url] + +if { ![info exists header_stuff] } { set header_stuff {} } Index: openacs-4/packages/project-manager/www/lib/nav-bar.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/nav-bar.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/nav-bar.adp 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,20 @@ + + + + + +
    + + + + +
    + +  |  + + @links.name@ + + +    +
    +
    Index: openacs-4/packages/project-manager/www/lib/nav-bar.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/lib/nav-bar.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/project-manager/www/lib/nav-bar.tcl 29 Apr 2005 17:43:40 -0000 1.1 @@ -0,0 +1,75 @@ +# Set up links in the navbar that the user has access to + +set user_id [ad_conn user_id] +set package_id [ad_conn package_id] +set package_url [ad_conn package_url] +set page_url [ad_conn url] +set page_query [ad_conn query] + +if {[string is false [empty_string_p $page_query]]} { + set page_query "?$page_query" +} + +set logger_url [pm::util::logger_url] + + +set admin_p [permission::permission_p -object_id $package_id -privilege admin] + +# The links used in the navbar on format url1 label1 url2 label2 ... +set link_list {} + + +if { [ad_conn user_id] != 0} { + lappend link_list [list "${package_url}tasks"] + lappend link_list {} + lappend link_list "Tasks" + + lappend link_list [list "${package_url}task-calendar"] + lappend link_list {} + lappend link_list "Task Calendar" + + lappend link_list [list "${package_url}?assignee_id=${user_id}"] + lappend link_list {} + lappend link_list "Projects" + + lappend link_list [list "${package_url}processes"] + lappend link_list {} + lappend link_list "Processes" + + lappend link_list [list "${logger_url}?user_id=${user_id}"] + lappend link_list {} + lappend link_list "Logger" + + lappend link_list [list "${package_url}task-select-project"] + lappend link_list {} + lappend link_list "Add task" +} + +if { $admin_p } { + lappend link_list [list "${package_url}admin/"] + lappend link_list {} + lappend link_list "Admin" +} + + +# Convert the list to a multirow and add the selected_p attribute +multirow create links name url selected_p +foreach {url_list param_list label} $link_list { + set selected_p 0 + + foreach url $url_list { + + if {[string equal "$page_url$page_query" $url]} { + set selected_p 1 + } + } + + + if { ![empty_string_p $param_list] } { + append url "?[export_vars $param_list]" + } + + multirow append links $label $url $selected_p +} + +ad_return_template Index: openacs-4/packages/project-manager/www/resources/bl-ddffdd.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/bl-ddffdd.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/bl-e6e6fa.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/bl-e6e6fa.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/br-ddffdd.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/br-ddffdd.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/br-e6e6fa.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/br-e6e6fa.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/finish_before_finish.png =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/finish_before_finish.png,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/finish_before_start.png =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/finish_before_start.png,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/print-16.png =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/print-16.png,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/start_before_finish.png =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/start_before_finish.png,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/start_before_start.png =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/start_before_start.png,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tl-9999cc.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tl-9999cc.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tl-ddffdd.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tl-ddffdd.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tl-dfdfff.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tl-dfdfff.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tl-e6e6fa.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tl-e6e6fa.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tr-9999cc.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tr-9999cc.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tr-ddffdd.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tr-ddffdd.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tr-dfdfff.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tr-dfdfff.jpg,v diff -u Binary files differ Index: openacs-4/packages/project-manager/www/resources/tr-e6e6fa.jpg =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/project-manager/www/resources/tr-e6e6fa.jpg,v diff -u Binary files differ