Forum OpenACS Development: How to turn a package into a dotlrn applet

Hi folks - here's a first draft of how to turn a package into an applet for dotLRN, done with the notes package. Associated files (you'll want them, for this to make any sense) are in

How to get a package working as a dotlrn portlet, as demonstrated with notes

Warning: I feel like I only marginally understand the whole portlet/applet thing. If it's wrong, please tell me so I can fix it!

Warning #2: Not quite every change I needed to make is documented here. See the actual packages.


  • Get notes.
  • Because we're going to want to use it in dotLRN, we need to have duplicates of it, so set singleton to "t" in the .info file before installing. Notes mostly doesn't mind not being a singleton in my testing, but see the aside at the end.
    WARNING: Some packages that are tagged singleton break badly when double-mounted. Before going further with a singleton package, you might want to double mount the package you're considering and just make sure it doesn't cause any obvious breakage.
  • Make package directories: notes-portlet and dotlrn-notes

Make the notes-portlet package:

  • Take a look at what it takes to display a page in regular notes. The file that does the logic is notes/www/index.tcl. Copy it over to notes-portlet/www/notes-portlet.tcl. Take the accompanying .adp and .xql files too.
  • Now we go looking for what will have to change. Package_id is going to be wrong. So are any URLs. We'll have to figure out the base url. The context_id in acs_objects corresponds to notes' package_id. Add this to the select.
    (select site_node__url(site_nodes.node_id) from site_nodes where site_nodes.object_id = o.context_id) as base_url
    Note: o.context_id is from acs_objects.
    (A different package that tracks package_id itself might look like
    (select site_node__url(site_nodes.node_id) from site_nodes where site_nodes.object_id = some_package.package_id) as base_url
  • We're going to swipe some code from weblogger-portlet/www/weblogger-portlet.tcl. We're adding array set config $cf set list_of_package_ids $config(package_id) set sep_package_ids [join $list_of_package_ids ", "] to the top of the notes-portlet.tcl page. We also remove the line that sets package_id.
  • Then we start looking through the .tcl file for problems. Notes is pretty simple, but here's a spot in the select statement where it does: where..... and o.context_id = :package_id Well, we might have lots of package_ids, and the one package_id we get isn't going to be a notes package! So we're going to make that an IN instead of an equals, and we'll need a , separated list to do it. (That's where $sep_package_ids comes in)

    So our query's where now has: and o.context_id IN ($sep_package_ids) .

  • Now we take our stolen index.adp, rename it to notes-portlet.adp, and look for problems. The <master> line can go, and we may find other spots where we should tidy things up to fit into a portal. Notes makes some odd assumptions about permissions being mounted one directory up from where it is. That's probably wrong in dotlrn, but we can (I think?) assume that /permissions will be there, so we change the URL.

    There are a bunch of URLs to parts of the notes package in the .adp file. We're going to have to fix it so that there's a @notes.base_url@ out in front of them. Track down every a href= and add in @notes.base_url@. Also all the images.

    The former index page is probably too busy still, but we'll leave it for now.

  • We need some callbacks. Grab the -procs and apm-callback-procs from weblogger-portlet/tcl and edit them.
  • Go into the apm and create the necessary info files, etc, or, easier: grab these .info files or weblogger-portlet's) and edit them. You need a bunch of callbacks, so editing an existing .info is easier.
  • That wraps it up for the notes-portlet package for a first pass (unless we want a portlet-admin too, but we'll leave that alone for now.)

Next: Creating the dotlrn-notes package

  • We need dotlrn-notes to finish up the interface between notes and the dotlrn portal system.
  • This part's really easy, as long as you swipe the code from a package that's already done it. At least in the case of notes, we can just grab the dotlrn-weblogger code and substitute in 'notes' for weblogger in both tcl files. Make sure you change every instance.
  • Again, create a .info file with the apm. It should be a singleton service. (Grab and edit dotlrn-weblogger's .info rather than starting from scratch)
  • Navigate to the admin page for a dotlrn class, click 'manage applets' - the notes package should appear and can be added. WAIT! Not yet, see below: Clicking 'add' generates an error because we didn't create the admin portlet. For now, just comment out: # notes_admin_portlet::add_self_to_page \ #-portal_id $admin_portal_id \ #-package_id $package_id from dotlrn-notes-procs.tcl
Aside: I set it up so that just courses and communities have notes packages (users don't). That means that you can see the notes in 'my space', but can't add one (otherwise we'd have to present an 'add' button for each community/course).

Aside #2: Notes is somewhat broken when not mounted at /notes because it assumes that permissions are at ../permissions.