Index: openacs-4/packages/acs-core-docs/www/tutorial-advanced.html =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/tutorial-advanced.html,v diff -u -r1.14.2.7 -r1.14.2.8 --- openacs-4/packages/acs-core-docs/www/tutorial-advanced.html 11 Jan 2004 12:45:48 -0000 1.14.2.7 +++ openacs-4/packages/acs-core-docs/www/tutorial-advanced.html 16 Jan 2004 14:35:54 -0000 1.14.2.8 @@ -1,15 +1,15 @@ Advanced Topics

Advanced Topics

Important

This section is a work in progress.

by Joel Aufrecht


OpenACS docs are written by the named authors, and may be edited by OpenACS documentation staff. -

Overview

This tutorial covers topics which are not essential to +

Overview

This tutorial covers topics which are not essential to creating a minimal working package. Each section can be used independently of all of the others; all sections assume that you've completed the basic tutorial.

  • How to enforce security so that users can't change other users records

  • How to use the content management tables so that ... what?

  • How to change the default stylesheets for Form Builder HTML forms.

  • How to make your package searchable with OpenFTS/Oracle

  • How to make your package send email notifications

  • How to prepare pagelets for inclusion in other pages

  • How and when to put procedures in a tcl procedure library

  • How to add general_comments to your pages

  • More on ad_form - data validation, other stuff. (plan to draw from Jon Griffin's doc)

  • How and when to implement caching

  • partialquery in xql

  • How to use the html/text entry widget to get the - "does this look right" confirm page

  • APM package dependencies

Write the Requirements and Design Specs

It's time to document. For the tutorial we'll use + "does this look right" confirm page

  • APM package dependencies

  • Write the Requirements and Design Specs

    It's time to document. For the tutorial we'll use pre-written documentation. When creating a package from scratch, start by copying the documentation template from /var/lib/aolserver/openacs-dev/packages/acs-core-docs/xml/docs/xml/package-documentation-template.xml @@ -22,11 +22,11 @@ www/doc directory.

    For this tutorial, you should instead install the pre-written documentation files for the tutorial app. Log in as service0, create the standard - directories, and copy the prepared documentation:

    [service0 service0]$ cd /var/lib/aolserver/service0/packages/samplenote/
    -[service0 samplenote]$ mkdir -p www/doc/xml
    -[service0 samplenote]$ cd www/doc/xml
    -[service0 xml]$ cp /var/lib/aolserver/service0/packages/acs-core-docs/www/files/samplenote/* .
    -[service0 xml]$

    OpenACS uses DocBook for documentation. DocBook is + directories, and copy the prepared documentation:

    [service0@yourserver service0]$ cd /var/lib/aolserver/service0/packages/samplenote/
    +[service0@yourserver samplenote]$ mkdir -p www/doc/xml
    +[service0@yourserver samplenote]$ cd www/doc/xml
    +[service0@yourserver xml]$ cp /var/lib/aolserver/service0/packages/acs-core-docs/www/files/samplenote/* .
    +[service0@yourserver xml]$

    OpenACS uses DocBook for documentation. DocBook is an XML standard for semantic markup of documentation. That means that the tags you use indicate meaning, not intended appearance. The style sheet will determine appearance. You @@ -42,7 +42,7 @@ is stored in the www/docs/ directory. A Makefile is provided to generate html from the xml, and copy all of the supporting files. If Docbook is set up correctly, all you need - to do is:

    [service0 xml]$ make
    +      to do is:

    [service0@yourserver xml]$ make
     cd .. ; /usr/bin/xsltproc ../../../acs-core-docs/www/xml/openacs.xsl xml/index.xml
     Writing requirements-introduction.html for sect1(requirements-introduction)
     Writing requirements-overview.html for sect1(requirements-overview)
    @@ -58,25 +58,25 @@
     Writing admin-guide.html for chapter(admin-guide)
     Writing bi01.html for bibliography
     Writing index.html for book
    -[service0 xml]$

    Verify that the documentation was generated and reflects - your changes by browsing to http://yoursite:8000/samplenote/doc

    Add the new package to CVS

    Before you do any more work, make sure that your work is +[service0@yourserver xml]$

    Verify that the documentation was generated and reflects + your changes by browsing to http://yoursite:8000/samplenote/doc

    Add the new package to CVS

    Before you do any more work, make sure that your work is protected by putting it all into cvs. The cvs add command is not recursive, so you'll have to traverse the directory tree manually and add as you go. (More on - CVS)

    [service0 xml]$ cd ..
    -[service0 doc]$ cd ..
    -[service0 www]$ cd ..
    -[service0 samplenote]$ cd ..
    -[service0 packages]$ cvs add samplenote/
    +      CVS)

    [service0@yourserver xml]$ cd ..
    +[service0@yourserver doc]$ cd ..
    +[service0@yourserver www]$ cd ..
    +[service0@yourserver samplenote]$ cd ..
    +[service0@yourserver packages]$ cvs add samplenote/
     Directory /cvsroot/service0/packages/samplenote added to the repository
    -[service0 packages]$ cd samplenote/
    -[service0 samplenote]$ cvs add www
    +[service0@yourserver packages]$ cd samplenote/
    +[service0@yourserver samplenote]$ cvs add www
     Directory /cvsroot/service0/packages/samplenote/www added to the repository
    -[service0 samplenote]$ cd www
    -[service0 www]$ cvs add doc
    +[service0@yourserver samplenote]$ cd www
    +[service0@yourserver www]$ cvs add doc
     Directory /cvsroot/service0/packages/samplenote/www/doc added to the repository
    -[service0 www]$ cd doc
    -[service0 doc]$ cvs add *
    +[service0@yourserver www]$ cd doc
    +[service0@yourserver doc]$ cvs add *
     cvs add: cannot add special file `CVS'; skipping
     cvs add: scheduling file `admin-guide.html' for addition
     cvs add: scheduling file `bi01.html' for addition
    @@ -101,13 +101,13 @@
     cvs add: scheduling file `user-interface.png' for addition
     Directory /cvsroot/service0/packages/samplenote/www/doc/xml added to the repository
     cvs add: use 'cvs commit' to add these files permanently
    -[service0 doc]$ cd xml
    -[service0 xml]$ cvs add Makefile index.xml
    +[service0@yourserver doc]$ cd xml
    +[service0@yourserver xml]$ cvs add Makefile index.xml
     cvs add: scheduling file `Makefile' for addition
     cvs add: scheduling file `index.xml' for addition
     cvs add: use 'cvs commit' to add these files permanently
    -[service0 xml]$ cd ../../..
    -[service0 samplenote]$ cvs commit -m "new package"
    +[service0@yourserver xml]$ cd ../../..
    +[service0@yourserver samplenote]$ cvs commit -m "new package"
     cvs commit: Examining .
     cvs commit: Examining www
     cvs commit: Examining www/doc
    @@ -119,8 +119,8 @@
     initial revision: 1.1
     done
     (many lines omitted)
    -[service0 samplenote]$

    Delete with confirmation

    We need a way to delete records. We'll create a - recursive confirmation page.

    Add this column to the table_def in index.tcl

    {delete "" {} {<td><a href="note-delete?note_id=$note_id">Delete</a></td>}}

    Create the delete confirmation/execution page.

    [service0 www]$ emacs note-delete.tcl
    ad_page_contract {
    +[service0@yourserver samplenote]$

    Delete with confirmation

    We need a way to delete records. We'll create a + recursive confirmation page.

    Add this column to the table_def in index.tcl

    {delete "" {} {<td><a href="note-delete?note_id=$note_id">Delete</a></td>}}

    Create the delete confirmation/execution page.

    [service0@yourserver www]$ emacs note-delete.tcl
    ad_page_contract {
         A page that gets confirmation and then delete notes.
     
         @author joel@aufrecht.org
    @@ -160,7 +160,7 @@
     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:

    [service0 www]$ emacs note-delete.xql
    <?xml version="1.0"?>
    +script execution.

    The database commands:

    [service0@yourserver www]$ emacs note-delete.xql
    <?xml version="1.0"?>
     <queryset>
       <fullquery name="do_delete">
         <querytext>
    @@ -172,14 +172,14 @@
           select samplenote__name(:note_id)
         </querytext>
       </fullquery>
    -</queryset>

    And the adp page:

    [service0 www]$ emacs note-delete.adp
    <master>
    +</queryset>

    And the adp page:

    [service0@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.

    General_comments

    You can track comments for any ACS Object. Here we'll track +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.

    General_comments

    You can track comments for any ACS Object. Here we'll track comments for notes. On the notes.tcl/adp pair, which is used to display individual notes, we want to put a link to add comments at the bottom of the screen. If there are any comments, we want to @@ -200,13 +200,120 @@ there are comments. Then you pass the note id, which is also the acs_object id.

    We put our two new variables in the notes.adp page.

    <a href="@comment_add_url@">Add a comment</a>
    -@comments_html@

    Prepare the package for distribution.

    Browse to the package manager. Click on +@comments_html@

    Prepare the package for distribution.

    Browse to the package manager. Click on tutorialapp.

    Click on Generate a distribution file for this package from the filesystem.

    Click on the file size (37.1KB) after the label Distribution File: and save the file to - /tmp.

    -

    View comments on this page at openacs.org
    + /tmp.

    +

    Notifications

    by David Bell and Simon Carstensen


    + OpenACS docs are written by the named authors, and may be edited + by OpenACS documentation staff. +

    The notifications package allows you to send notifications through any + defined communications medium (e.g. email, sms) upon some event occuring within + the system.

    This tutorial steps through the process of integrating the notifications + package with your package.

    First step is to create the notification types. To do this a script similar + to the one below needs to be loaded into Postgresql. I create this script in a + package-name/sql/postgresql/package-name-notifications-init.sql file. I then load + this file from my create sql file. The following code snippet is taken from + Weblogger. It creates a lars_blogger_notif notification type (which was created + above).

    +    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'',
    +                      ''lars_blogger_notif_type'',
    +                      ''lars-blogger''
    +        );
    +
    +        v_foo := acs_sc_impl_alias__new (
    +                    ''NotificationType'',
    +                    ''lars_blogger_notif_type'',
    +                    ''GetURL'',
    +                    ''lars_blogger::notification::get_url'',
    +                    ''TCL''
    +        );
    +
    +        v_foo := acs_sc_impl_alias__new (
    +                    ''NotificationType'',
    +                    ''lars_blogger_notif_type'',
    +                    ''ProcessReply'',
    +                    ''lars_blogger::notification::process_reply'',
    +                    ''TCL''
    +        );
    +
    +        PERFORM acs_sc_binding__new (
    +                    ''NotificationType'',
    +                    ''lars_blogger_notif_type''
    +        );
    +
    +        v_foo:= notification_type__new (
    +	        NULL,
    +                impl_id,
    +                ''lars_blogger_notif'',
    +                ''Blog Notification'',
    +                ''Notifications for Blog'',
    +		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();
    +    

    The next step is to setup our notification creation. A new notification must + be added to the notification table for each blog entry added. We do this using the + notification::new procedure

    +        notification::new \
    +            -type_id [notification::type::get_type_id \
    +            -short_name lars_blogger_notif] \
    +            -object_id $blog(package_id) \
    +            -response_id $blog(entry_id) \
    +            -notif_subject $blog(title) \
    +            -notif_text $new_content
    +    

    This code is placed in the tcl procedure that creates blog entries, right after + the entry gets created in the code. The $blog(package_id) + is the OpenACS object_id of the Weblogger instance to which the entry has been posted to + and the $new_content is the content of the entry.

    The final step is to setup the notification subscription process. In this + example we want to let a user find out when a new entry has been posted to the blog. To + do this we put a link on the blog that allows them to subscribe to notifications of new + entries. The notifications/requests-new page is very handy in this situation.

    Such a link can be created using the notification::display::request_widget + proc:

    +    set notification_chunk [notification::display::request_widget \
    +        -type lars_blogger_notif \
    +        -object_id $package_id \
    +        -pretty_name [lars_blog_name] \
    +        -url [lars_blog_public_package_url] \
    +    ]
    +    

    which will return something like + +

    +    You may <a href="/notifications/request-new?...">request notification</a> for Weblogger.

    + + which can be readily put on the blog index page. The pretty_name + parameter is what appears at the end of the text returned (i.e. "... request notification</a> for pretty_name"), + The url parameter should be set to the address we want the user + to be redirected to after they have finished the subscription process.

    This should be all you need to implement a notification system. For more examples + look at the forums package.

    View comments on this page at openacs.org
    Index: openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml,v diff -u -r1.4.2.2 -r1.4.2.3 --- openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml 15 Dec 2003 14:18:48 -0000 1.4.2.2 +++ openacs-4/packages/acs-core-docs/www/xml/developers-guide/tutorial-advanced.xml 16 Jan 2004 14:27:49 -0000 1.4.2.3 @@ -61,11 +61,11 @@ pre-written documentation files for the tutorial app. Log in as service0, create the standard directories, and copy the prepared documentation: - [service0 service0]$ cd /var/lib/aolserver/service0/packages/samplenote/ -[service0 samplenote]$ mkdir -p www/doc/xml -[service0 samplenote]$ cd www/doc/xml -[service0 xml]$ cp /var/lib/aolserver/service0/packages/acs-core-docs/www/files/samplenote/* . -[service0 xml]$ + [service0@yourserver service0]$ cd /var/lib/aolserver/service0/packages/samplenote/ +[service0@yourserver samplenote]$ mkdir -p www/doc/xml +[service0@yourserver samplenote]$ cd www/doc/xml +[service0@yourserver xml]$ cp /var/lib/aolserver/service0/packages/acs-core-docs/www/files/samplenote/* . +[service0@yourserver xml]$ OpenACS uses DocBook for documentation. DocBook is an XML standard for semantic markup of documentation. That means that the tags you use indicate meaning, not intended @@ -86,7 +86,7 @@ directory. A Makefile is provided to generate html from the xml, and copy all of the supporting files. If Docbook is set up correctly, all you need to do is: - [service0 xml]$ make + [service0@yourserver xml]$ make cd .. ; /usr/bin/xsltproc ../../../acs-core-docs/www/xml/openacs.xsl xml/index.xml Writing requirements-introduction.html for sect1(requirements-introduction) Writing requirements-overview.html for sect1(requirements-overview) @@ -102,7 +102,7 @@ Writing admin-guide.html for chapter(admin-guide) Writing bi01.html for bibliography Writing index.html for book -[service0 xml]$ +[service0@yourserver xml]$ Verify that the documentation was generated and reflects your changes by browsing to http://yoursite:8000/samplenote/doc @@ -114,20 +114,20 @@ traverse the directory tree manually and add as you go. (More on CVS) - [service0 xml]$ cd .. -[service0 doc]$ cd .. -[service0 www]$ cd .. -[service0 samplenote]$ cd .. -[service0 packages]$ cvs add samplenote/ + [service0@yourserver xml]$ cd .. +[service0@yourserver doc]$ cd .. +[service0@yourserver www]$ cd .. +[service0@yourserver samplenote]$ cd .. +[service0@yourserver packages]$ cvs add samplenote/ Directory /cvsroot/service0/packages/samplenote added to the repository -[service0 packages]$ cd samplenote/ -[service0 samplenote]$ cvs add www +[service0@yourserver packages]$ cd samplenote/ +[service0@yourserver samplenote]$ cvs add www Directory /cvsroot/service0/packages/samplenote/www added to the repository -[service0 samplenote]$ cd www -[service0 www]$ cvs add doc +[service0@yourserver samplenote]$ cd www +[service0@yourserver www]$ cvs add doc Directory /cvsroot/service0/packages/samplenote/www/doc added to the repository -[service0 www]$ cd doc -[service0 doc]$ cvs add * +[service0@yourserver www]$ cd doc +[service0@yourserver doc]$ cvs add * cvs add: cannot add special file `CVS'; skipping cvs add: scheduling file `admin-guide.html' for addition cvs add: scheduling file `bi01.html' for addition @@ -152,13 +152,13 @@ cvs add: scheduling file `user-interface.png' for addition Directory /cvsroot/service0/packages/samplenote/www/doc/xml added to the repository cvs add: use 'cvs commit' to add these files permanently -[service0 doc]$ cd xml -[service0 xml]$ cvs add Makefile index.xml +[service0@yourserver doc]$ cd xml +[service0@yourserver xml]$ cvs add Makefile index.xml cvs add: scheduling file `Makefile' for addition cvs add: scheduling file `index.xml' for addition cvs add: use 'cvs commit' to add these files permanently -[service0 xml]$ cd ../../.. -[service0 samplenote]$ cvs commit -m "new package" +[service0@yourserver xml]$ cd ../../.. +[service0@yourserver samplenote]$ cvs commit -m "new package" cvs commit: Examining . cvs commit: Examining www cvs commit: Examining www/doc @@ -170,7 +170,7 @@ initial revision: 1.1 done (many lines omitted) -[service0 samplenote]$ +[service0@yourserver samplenote]$ Delete with confirmation @@ -179,7 +179,7 @@ Add this column to the table_def in index.tcl {delete "" {} {<td><a href="note-delete?note_id=$note_id">Delete</a></td>}} Create the delete confirmation/execution page. - [service0 www]$ emacs note-delete.tcl + [service0@yourserver www]$ emacs note-delete.tcl ad_page_contract { A page that gets confirmation and then delete notes. @@ -224,7 +224,7 @@ script execution. The database commands: - [service0 www]$ emacs note-delete.xql + [service0@yourserver www]$ emacs note-delete.xql <?xml version="1.0"?> <queryset> <fullquery name="do_delete"> @@ -239,7 +239,7 @@ </fullquery> </queryset> And the adp page: - [service0 www]$ emacs note-delete.adp + [service0@yourserver www]$ emacs note-delete.adp <master> <property name="title">@title@</property> <property name="context">{@title@}</property> @@ -304,4 +304,137 @@ + + Notifications + + by David Bell and Simon Carstensen + + + The notifications package allows you to send notifications through any + defined communications medium (e.g. email, sms) upon some event occuring within + the system. + This tutorial steps through the process of integrating the notifications + package with your package. + + First step is to create the notification types. To do this a script similar + to the one below needs to be loaded into Postgresql. I create this script in a + package-name/sql/postgresql/package-name-notifications-init.sql file. I then load + this file from my create sql file. The following code snippet is taken from + Weblogger. It creates a lars_blogger_notif notification type (which was created + above). + + + 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'', + ''lars_blogger_notif_type'', + ''lars-blogger'' + ); + + v_foo := acs_sc_impl_alias__new ( + ''NotificationType'', + ''lars_blogger_notif_type'', + ''GetURL'', + ''lars_blogger::notification::get_url'', + ''TCL'' + ); + + v_foo := acs_sc_impl_alias__new ( + ''NotificationType'', + ''lars_blogger_notif_type'', + ''ProcessReply'', + ''lars_blogger::notification::process_reply'', + ''TCL'' + ); + + PERFORM acs_sc_binding__new ( + ''NotificationType'', + ''lars_blogger_notif_type'' + ); + + v_foo:= notification_type__new ( + NULL, + impl_id, + ''lars_blogger_notif'', + ''Blog Notification'', + ''Notifications for Blog'', + 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(); + + + The next step is to setup our notification creation. A new notification must + be added to the notification table for each blog entry added. We do this using the + notification::new procedure + + + notification::new \ + -type_id [notification::type::get_type_id \ + -short_name lars_blogger_notif] \ + -object_id $blog(package_id) \ + -response_id $blog(entry_id) \ + -notif_subject $blog(title) \ + -notif_text $new_content + + + This code is placed in the tcl procedure that creates blog entries, right after + the entry gets created in the code. The $blog(package_id) + is the OpenACS object_id of the Weblogger instance to which the entry has been posted to + and the $new_content is the content of the entry. + + The final step is to setup the notification subscription process. In this + example we want to let a user find out when a new entry has been posted to the blog. To + do this we put a link on the blog that allows them to subscribe to notifications of new + entries. The notifications/requests-new page is very handy in this situation. + + Such a link can be created using the notification::display::request_widget + proc: + + set notification_chunk [notification::display::request_widget \ + -type lars_blogger_notif \ + -object_id $package_id \ + -pretty_name [lars_blog_name] \ + -url [lars_blog_public_package_url] \ + ] + + + which will return something like + + + You may <a href="/notifications/request-new?...">request notification</a> for Weblogger. + + which can be readily put on the blog index page. The pretty_name + parameter is what appears at the end of the text returned (i.e. "... request notification</a> for pretty_name"), + The url parameter should be set to the address we want the user + to be redirected to after they have finished the subscription process. + + This should be all you need to implement a notification system. For more examples + look at the forums package. + +