Prev | Chapter 10. Advanced Topics | Next

## Categories

You can associate any ACS Object with one or more categories. In this tutorial we'll show how to equip your application with user interface to take advantage of the Categories service.

We'll start by installing the Categories service. Go to `/acs/admin` and install it. This step won't be necessary for the users of your applications because you'll create a dependency with the Package Manager which will take care that the Categories service always gets installed when your application gets installed.

Now that we have installed the Categories service we can proceed to modifying our application so that it can take advantage of it. We'll do it in three steps:

1. The Categories service provides a mechanism to associate one or more category trees that are relevant to your application. One example of such tree is a tree of geographical locations. Continents are on the top of such tree, each continent containing countries etc. Another tree might contain market segments etc. Before users of your application can take advantage of the Categories service there needs to be a way for administrators of your application to choose which category trees are applicable for the application.

   The way to achieve this is is to provide a link to the Category Management pages. Add the following snippet to your `/var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/myfirstpackage/www/admin/index.tcl` file:

       set category_map_url [export_vars -base \
           "[site_node::get_package_url -package_key categories]cadmin/one-object" \
               { { object_id $package_id } }]

   and the following snippet to your `/var/lib/aolserver/$OPENACS_SERVICE_NAME/packages/myfirstpackage/www/admin/index.adp` file:

       <li><a href="@category_map_url@"
             class="action_link">Site-Wide Categories</a>

   The link created by the above code will take the admin to the generic admin UI where he can pick category trees that make sense for this application. The same UI also includes facilities to build and edit category trees. Notice that the only parameter in this example is `package_id` so that category trees will be associated with the object identified by this `package_id`. The categorization service is actually more general than that: instead of `package_id` you could use an ID of some other object that serves as a "container" in your application. For example, if your discussion forums application supports multiple forums you would use `forum_id` to associate category trees with just that one forum rather than the entire application instance.

2. Once the category trees have been selected users need a way to categorize items. The easiest way to do this is by adding the `category` widget type of the form builder to `note-edit.tcl`. To achieve this we'll need to use the `-extend` switch to the `ad_form` command. Here's the "meat" of the `note-edit.tcl` page:

       ad_form -name note -form {
           {item_id:key}
           {title:text {label Title}}
       }

       set package_id [ad_conn package_id]

       set category_trees [category_tree::get_mapped_trees $package_id]

       foreach tree $category_trees {
           foreach { tree_id name subtree_id } $tree {}
           ad_form -extend -name note -form \
               [list [list category_id_${tree_id}:integer(category),optional \
                          {label $name} \
                          {html {single single}} \
                          {category_tree_id $tree_id} \
                          {category_subtree_id $subtree_id} \
                          {category_object_id {[value_if_exists entry_id]}}]]
       }

       ad_form -extend \
         -name note \
         -new_request {
           permission::require_permission -object_id [ad_conn package_id] -privilege create
           set page_title "Add a Note"
           set context [list $page_title]
       } -edit_request {
           permission::require_write_permission -object_id $item_id
           mfp::note::get \
           -item_id $item_id \
           -array note_array

           set title $note_array(title)

           set page_title "Edit a Note"
           set context [list $page_title]
       } -new_data {
           mfp::note::add \
           -title $title
       } -after_submit {
           ad_returnredirect "."
           ad_script_abort
       }

   This page requires a `note_id` to determine which record should be deleted. It also looks for a confirmation variable, which should initially be absert. If it is absent, we create a form to allow the user to confirm the deletion. Note that in `entry-edit.tcl` we used `ad_form` to access the Form Template commands; here, we call them directly because we don't need the extra features of ad_form. The form calls itself, but with hidden variables carrying both `note_id` and `confirm_p`. If confirm_p is present, we delete the record, set redirection back to the index, and abort script execution.

   The database commands:

       [$OPENACS_SERVICE_NAME@yourserver www]$ emacs note-delete.xql

       <?xml version="1.0"?>
       <queryset>
         <fullquery name="do_delete">
           <querytext>
             select samplenote__delete(:note_id)
           </querytext>
         </fullquery>
         <fullquery name="get_name">
           <querytext>
             select samplenote__name(:note_id)
           </querytext>
         </fullquery>
       </queryset>

   And the adp page:

       [$OPENACS_SERVICE_NAME@yourserver www]$ emacs note-delete.adp

       <master>
       <property name="title">@title@</property>
       <property name="context">{@title@}</property>
       <h2>@title@</h2>
       <formtemplate id="note-del-confirm"></formtemplate>
       </form>

   The ADP is very simple. The `formtemplate` tag outputs the HTML form generated by the ad_form command with the matching name. Test it by adding the new files in the APM and then deleting a few samplenotes.

Prev | Home | Next
Admin Pages | Up | Profile your code

View comments on this page at openacs.org