Index: openacs-4/packages/logger/lib/entries.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/logger/lib/entries.tcl,v
diff -u -r1.3 -r1.4
--- openacs-4/packages/logger/lib/entries.tcl	5 Jan 2004 21:05:27 -0000	1.3
+++ openacs-4/packages/logger/lib/entries.tcl	11 Jan 2004 17:52:40 -0000	1.4
@@ -27,6 +27,17 @@
 set weekdayno [clock format [clock seconds] -format %w]
 set monthdayno [string trimleft [clock format [clock seconds] -format %d] 0]
 
+# 1. get category-trees mapped to projects in this logger
+set project_ids [logger::package::all_projects_in_package -package_id [ad_conn package_id]]
+array set tree_id_array [list]
+foreach id $project_ids {
+    foreach elm [category_tree::get_mapped_trees $id] {
+        set tree_id_array([lindex $elm 0]) .
+    }
+}
+set tree_ids [array names tree_id_array]
+
+
 # Projections
 set projection_values [list]
 if { [exists_and_not_null project_id] } {
@@ -40,9 +51,79 @@
 # Projects
 set project_values [db_list_of_lists select_projects {}]
 
-
 # Define the list
 
+set elements {
+    edit {
+        label {}
+        display_template {
+           <if @entries.edit_p@ true>
+            <a href="@entries.edit_url@" title="Edit this log entry"
+            ><img src="/shared/images/Edit16.gif" height="16" width="16" 
+            alt="Edit" border="0"></a>
+            </if>        
+        }
+    }
+    project_id {
+        display_col project_name
+        label "Project"
+        hide_p {[ad_decode [exists_and_not_null project_id] 1 1 0]}
+    }
+    user_id {
+        label "User"
+        display_col user_name
+        link_url_eval {[acs_community_member_url -user_id $user_id]}
+        csv_col user_name
+        hide_p {[ad_decode [exists_and_not_null user_id] 1 1 0]}
+    }
+    time_stamp {
+        label "Date"
+        display_col time_stamp_pretty
+        aggregate_label {[ad_decode $variable(type) "additive" "Total" "Average"]}
+        aggregate_group_label {[ad_decode $variable(type) "additive" "Group total" "Group Average"]}
+    }
+    value {
+        label $variable(name)
+        link_url_eval {log?[export_vars { entry_id }]}
+        link_html { title "View this entry" }
+        aggregate {[ad_decode $variable(type) "additive" sum average]}
+        html { align right }
+        display_eval {[lc_numeric $value]}
+    }
+    description {
+        label "Description"
+        display_eval {[string_truncate -len 50 -- $description]}
+        link_url_eval {log?[export_vars { entry_id }]}
+        link_html { title "View this entry" }
+    }
+    description_long {
+        label "Description"
+        display_eval {[string_truncate -len 400 -- $description]}
+        hide_p 1
+        link_url_eval {log?[export_vars { entry_id }]}
+        link_html { title "View this entry" }
+    }
+}
+
+set normal_row {
+    checkbox {}
+    edit {}
+    project_id {}
+    user_id {}
+    time_stamp {}
+}
+
+foreach id $tree_ids {
+    set id_var c_${id}_category_id
+    set cmd "join \[category::get_names \$$id_var\] \", \""
+    lappend elements c_${id}_category_id \
+        [list label \[[list category_tree::get_name $id]\] \
+             display_eval \[$cmd\]]
+    lappend normal_row c_${id}_category_id {}
+}
+
+lappend normal_row value {} description {}
+
 list::create \
     -name entries \
     -multirow entries \
@@ -59,58 +140,8 @@
         "Add Entry" "project-select" "Add new log entry"
     } -bulk_actions {
         "Delete" "log-delete" "Delete checked entries"
-    } -elements {
-        edit {
-            label {}
-            display_template {
-               <if @entries.edit_p@ true>
-                <a href="@entries.edit_url@" title="Edit this log entry"
-                ><img src="/shared/images/Edit16.gif" height="16" width="16" 
-                alt="Edit" border="0"></a>
-                </if>        
-            }
-        }
+    } -elements $elements -filters {
         project_id {
-            display_col project_name
-            label "Project"
-            hide_p {[ad_decode [exists_and_not_null project_id] 1 1 0]}
-        }
-        user_id {
-            label "User"
-            display_col user_name
-            link_url_eval {[acs_community_member_url -user_id $user_id]}
-            csv_col user_name
-            hide_p {[ad_decode [exists_and_not_null user_id] 1 1 0]}
-        }
-        time_stamp {
-            label "Date"
-            display_col time_stamp_pretty
-            aggregate_label {[ad_decode $variable(type) "additive" "Total" "Average"]}
-            aggregate_group_label {[ad_decode $variable(type) "additive" "Group total" "Group Average"]}
-        }
-        value {
-            label $variable(name)
-            link_url_eval {log?[export_vars { entry_id }]}
-            link_html { title "View this entry" }
-            aggregate {[ad_decode $variable(type) "additive" sum average]}
-            html { align right }
-            display_eval {[lc_numeric $value]}
-        }
-        description {
-            label "Description"
-            display_eval {[string_truncate -len 50 -- $description]}
-            link_url_eval {log?[export_vars { entry_id }]}
-            link_html { title "View this entry" }
-        }
-        description_long {
-            label "Description"
-            display_eval {[string_truncate -len 400 -- $description]}
-            hide_p 1
-            link_url_eval {log?[export_vars { entry_id }]}
-            link_html { title "View this entry" }
-        }
-    } -filters {
-        project_id {
             label "Projects"
             values $project_values
             where_clause {
@@ -247,15 +278,7 @@
         normal {
             label "Table"
             layout table
-            row {
-                checkbox {}
-                edit {}
-                project_id {}
-                user_id {}
-                time_stamp {}
-                value {}
-                description {}
-            }
+            row $normal_row
         }
         detailed {
             label "Detailed table"
@@ -309,20 +332,71 @@
         }
     }
 
+# TODO: Filter by category
 
+# TODO: Order by category tree
 
-# This query will override the ad_page_contract value entry_id
+# TODO: With multiple categories from the same tree, make sure they're listed in correct sort_order
 
-db_multirow -extend { edit_url delete_url delete_onclick } -unclobber entries select_entries "
+
+# We add a virtual column per category tree
+
+set extend  { edit_url delete_url delete_onclick time_stamp_pretty }
+foreach id $tree_ids {
+    lappend extend c_${id}_category_id
+}
+
+array set row_categories [list]
+
+db_multirow -extend $extend -unclobber entries select_entries2 "
+    select le.entry_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, 'YYYY-MM-DD HH24:MI:SS') as time_stamp_ansi,
+           to_char(le.time_stamp, 'IW-YYYY') as time_stamp_week,
+           le.value,
+           le.description,
+           lp.project_id,               
+           lp.name as project_name,
+           submitter.user_id,
+           submitter.first_names || ' ' || submitter.last_name as user_name,
+           c.category_id,
+           c.tree_id
+    from   logger_entries le left outer join 
+           category_object_map_tree c on (c.object_id = le.entry_id),
+           logger_projects lp,
+           acs_objects ao,
+           cc_users submitter
+    where  le.project_id = lp.project_id
+    and    ao.object_id = le.entry_id 
+    and    ao.creation_user = submitter.user_id
+    [list::filter_where_clauses -and -name "entries"]
+    [list::orderby_clause -orderby -name "entries"]
 " {
-    set selected_p [string equal [ns_queryget entry_id] $entry_id]
-    set edit_url "log?[export_vars { entry_id { edit t } }]"
-    set edit_p [ad_decode [expr [ad_decode $edit_p "t" 1 0]  || ($user_id == [ad_conn user_id])] 1 "t" "f"]
-    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 "log-delete?[export_vars { entry_id }]"
+    if { ![empty_string_p $tree_id] && ![empty_string_p $category_id] } {
+        lappend row_categories($tree_id) $category_id
+    }
+    
+    if { ![db_multirow_group_last_row_p -column entry_id] } {
+        continue
     } else {
-        set delete_url ""
+        set selected_p [string equal [ns_queryget entry_id] $entry_id]
+        set edit_url [export_vars -base log { entry_id { edit t } { return_url [ad_return_url] } }]
+        set edit_p [ad_decode [expr [ad_decode $edit_p "t" 1 0]  || ($user_id == [ad_conn user_id])] 1 "t" "f"]
+        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 [export_vars -base log-delete { entry_id }]
+        } else {
+            set delete_url {}
+        }
+        set time_stamp_pretty [lc_time_fmt $time_stamp_ansi "%x"]
+
+        foreach tree_id [array names row_categories] {
+            set c_${tree_id}_category_id $row_categories($tree_id)
+        }
+        
+        array unset row_categories
     }
 }
 
Index: openacs-4/packages/logger/tcl/package-procs.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/logger/tcl/package-procs.tcl,v
diff -u -r1.5 -r1.6
--- openacs-4/packages/logger/tcl/package-procs.tcl	5 Jan 2004 20:54:25 -0000	1.5
+++ openacs-4/packages/logger/tcl/package-procs.tcl	11 Jan 2004 17:52:40 -0000	1.6
@@ -1,17 +1,13 @@
 ad_library {
-    <p>
-    Procedures in the logger::package namespace. Those procedures
+    Procedures the logger::package namespace. Those procedures
     operate on logger package objects.
-    </p>
 
-   <p>
-     Unlike many other -procs.tcl files in the logger package this
-     file contains no ::new and ::delete procedures. The reason
-     is that packages are created by the APM proc apm_package_instance_new.
-     When the logger application needs extra data to be setup for package
-     instances this would be done in an after-instantiate callback in
-     the file apm-callback-procs.tcl.
-   </p>
+   Unlike many other -procs.tcl files in the logger package this
+   file contains no ::new and ::delete procedures. The reason
+   is that packages are created by the APM proc apm_package_instance_new.
+   When the logger application needs extra data to be setup for package
+   instances this would be done in an after-instantiate callback in
+   the file apm-callback-procs.tcl.
 
     @creation-date 4:th of April 2003
     @author Peter Marklund (peter@collaboraid.biz)
@@ -39,7 +35,7 @@
 ad_proc -public logger::package::all_projects_in_package {
     {-package_id:required}
 } {
-    Return a list of ids for all logger projects mapped to the given package.x
+    Return a list of ids for all logger projects mapped to the given package.
 
     @param package_id The id of the package to return projects for
 
Index: openacs-4/packages/logger/www/log.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/logger/www/log.adp,v
diff -u -r1.11 -r1.12
--- openacs-4/packages/logger/www/log.adp	5 Jan 2004 20:23:50 -0000	1.11
+++ openacs-4/packages/logger/www/log.adp	11 Jan 2004 17:52:40 -0000	1.12
@@ -1,7 +1,7 @@
 <master src="/packages/logger/lib/master">
 <property name="title">@page_title;noquote@</property>
 <property name="context">@context;noquote@</property>
-<property name="focus">log_entry_form.value</property>
+<property name="focus">log_entry_form.category_id</property>
 
 <script language="javascript">
    function project_change() {
Index: openacs-4/packages/logger/www/log.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/logger/www/log.tcl,v
diff -u -r1.13 -r1.14
--- openacs-4/packages/logger/www/log.tcl	4 Jan 2004 21:27:48 -0000	1.13
+++ openacs-4/packages/logger/www/log.tcl	11 Jan 2004 17:52:40 -0000	1.14
@@ -123,20 +123,28 @@
 # form or an initial request (could also be with error message after unaccepted submit)
 set submit_p [form is_valid log_entry_form]
 
-ad_form -extend -name log_entry_form -form {
+ad_form -extend -name log_entry_form -export { project_id variable_id return_url } -form {
     {project:text(inform)
         {label Project}
         {value $project_array(name)}
     }
-    {project_id:integer(hidden)
-        {value $project_id}
-    }
-    {variable_id:integer(hidden)
-        {value $variable_id}
-    }
-    {return_url:text(hidden) {value $return_url}}
-}    
+}
 
+if { $entry_exists_p } {
+    set category_trees [category_tree::get_mapped_trees $entry_array(project_id)]
+} else {
+    set category_trees [category_tree::get_mapped_trees $project_id]
+}
+foreach elm $category_trees {
+    foreach { tree_id name dummy } $elm {}
+    ad_form -extend -name log_entry_form -form \
+        [list [list category_id_${tree_id}:integer(category) \
+                   {label $name} \
+                   {html {single single}} \
+                   {category_tree_id $tree_id} \
+                   {category_object_id {[value_if_exists entry_id]}}]]
+}   
+
 # Add form elements common to all modes
 # The form builder date datatype doesn't take ANSI format date strings
 # but wants dates in list format
@@ -173,26 +181,46 @@
         set time_stamp [clock format [clock seconds] -format "%Y-%m-%d"]
     }
     set time_stamp [template::util::date::acquire ansi $time_stamp]
+} -on_submit {
+    # Collect categories from all the category widgets
+    set category_ids [list]
+    foreach elm $category_trees {
+        foreach { tree_id name dummy } $elm {}
+        set category_ids [concat $category_ids [set category_id_${tree_id}]]
+    }
 } -new_data {
     
     # jarkko: check to see if user has already added this entry and has come
-    # back with her back button. If the entry exists, we give the user a complaint
-    # LARS: took out the edit link, because the new templated ad_return_complaint quotes
+    # back with her back button. If the entry exists, we edit it
 
-    if { [string match [db_string check_if_exists "
-	select 1
-	from logger_entries
-	where entry_id = :entry_id
-    " -default "0"] "0"]} {
-        logger::entry::new \
-            -entry_id $entry_id \
-            -project_id $project_id \
-            -variable_id $variable_id \
-            -value $value \
-            -time_stamp $time_stamp \
-            -description $description
-    } else {
-	ad_return_complaint {} "You have already added this entry once."
+    db_transaction {
+        set exists_p [db_string check_if_exists {
+            select 1
+            from   logger_entries
+            where  entry_id = :entry_id
+        } -default "0"]
+        
+        if { !$exists_p } {
+            logger::entry::new \
+                -entry_id $entry_id \
+                -project_id $project_id \
+                -variable_id $variable_id \
+                -value $value \
+                -time_stamp $time_stamp \
+                -description $description
+        } else {
+            logger::entry::edit \
+                -entry_id $entry_id \
+                -value $value \
+                -time_stamp $time_stamp \
+                -description $description
+        }
+        
+
+        category::map_object \
+            -remove_old \
+            -object_id $entry_id \
+            $category_ids
     }
     
     # Remember this date, as the next entry is likely to be for the same date
@@ -203,13 +231,22 @@
     ad_script_abort
 
 } -edit_data {
-    logger::entry::edit \
-        -entry_id $entry_id \
-        -value $value \
-        -time_stamp $time_stamp \
-        -description $description
+    db_transaction {
+        logger::entry::edit \
+            -entry_id $entry_id \
+            -value $value \
+            -time_stamp $time_stamp \
+            -description $description
+        
+        category::map_object \
+            -remove_old \
+            -object_id $entry_id \
+            $category_ids
+    }
+
 } -after_submit {
-    ad_returnredirect "[ad_conn url]?[export_vars -base [ad_conn url] { project_id variable_id return_url }]"
+
+    ad_returnredirect $return_url
     ad_script_abort
 }
 
@@ -281,6 +318,6 @@
 #####
 
 db_multirow -extend { url selected_p } variables select_variables {} {
-    set url "log?[export_vars -override { {variable_id $unique_id} } { project_id }]"
+    set url [export_vars -base log -override { {variable_id $unique_id} } { project_id }]
     set selected_p [string equal $variable_id $unique_id]
 }
Index: openacs-4/packages/logger/www/admin/project.adp
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/logger/www/admin/project.adp,v
diff -u -r1.8 -r1.9
--- openacs-4/packages/logger/www/admin/project.adp	5 Jan 2004 20:23:50 -0000	1.8
+++ openacs-4/packages/logger/www/admin/project.adp	11 Jan 2004 17:52:40 -0000	1.9
@@ -8,6 +8,8 @@
 </blockquote>
 
 <if @project_exists_p@ and @edit_mode_p@ eq 0>
+  <a href="@category_map_url@" class="action">Define categories</a>
+
   <h2>Variables</h2>
 
   <listtemplate name="variables"></listtemplate>
Index: openacs-4/packages/logger/www/admin/project.tcl
===================================================================
RCS file: /usr/local/cvsroot/openacs-4/packages/logger/www/admin/project.tcl,v
diff -u -r1.13 -r1.14
--- openacs-4/packages/logger/www/admin/project.tcl	4 Jan 2004 17:24:38 -0000	1.13
+++ openacs-4/packages/logger/www/admin/project.tcl	11 Jan 2004 17:52:40 -0000	1.14
@@ -213,3 +213,7 @@
             html { align center }
         }
     }
+
+
+# TODO: Get category base URL dynamically
+set category_map_url [export_vars -base "/categories/cadmin/one-object" { { object_id $project_id } }]