Now that we have the Gadgets framework downloaded and installed, lets get our application up and running. We'll install the Gadgets Wiki (which relies on ATemplate, APost, APeopleManager and JUtils), and then we'll write a new text-only version of the wiki which uses our new text-only template.
First we build the par files from source that we'll be using:
from our Gadgets checkout directory
cd misc/gadgets
perl -le 'qx|perl mkpars.pl $_| for ( qw( AEditor APeopleManager APost ATemplate JUtils Wiki ) )'
perl ../admin/install_gadget.pl --par AEditor.par --uri_path /admin/aeditor/ --pars_path /ob/webtree/
perl ../admin/install_gadget.pl --par APost.par --uri_path /admin/apost/ --pars_path /ob/webtree/
perl ../admin/install_gadget.pl --par JUtils.par --uri_path /admin/jutils/ --pars_path /ob/webtree/
perl ../admin/install_gadget.pl --par ATemplate.par --uri_path /admin/atemplate/ --pars_path /ob/webtree/
perl ../admin/install_gadget.pl --par Wiki.par --uri_path / --pars_path /ob/webtree/
restart apache to prime the gadget cache
And add an admin user:
perl ../admin/add_user.pl --email 'dug@allafrica.com' --password 'xxx'
prints:
"added user GadgetsGroup|main|08VVCyVsfo9OnuZ"
and the special 'admin' group
perl ../admin/add_group.pl --groupname admin --add_user 'dug@allafrica.com'
adds our new user to the newly created "admin" group and prints:
"added group GadgetsGroup|main|08VVCyVsfo9OnuZ"
Now we can configure the people admin interface to be only readable by people in the admin group, securing our installation:
perl ../admin/add_config.pl --gadget "core_auth" --path "/admin/people/" --key "read" --value "GadgetsGroup|main|08VVCyVsfo9OnuZE"
We'll talk more about the configuration API in a bit, but for now suffice it to say that the Gadgets authentication layer will only allow members of the admin group we created to read the /admin/people/ uri (or any of its descendants).
Now that we're off and running with a full blown Gadgets wiki stack, let's make some changes. Historically the Gadgets Wiki web interface has required JavaScript in order to function. In these new days of hope and change we hope to change that, making it easy for interface writers to layer whichever brand of JS-fu they like on top of the web interface.
Looking at the source of our wiki, for instance the index page misc/gadgets/wiki-source/mason/index.html, notice the HTML::Mason inheritance flag set at the bottom of the page:
<%flags>
inherit => '/&TemplateMain/autohandler-main'
</%flags>
This tells our wiki to wrap itself using the "autohandler-main" component provided by our "TemplateMain" gadget. A quick peek at misc/gadgets/atemplate-source/mason/autohandler-main reveals that it
simply re-dispatches to misc/gadgets/atemplate-source/mason/autohandler-postpage. We'll start our hacking by creating our own "autohandler-textonly" wrapper that doesn't load any components from the JUtils gadget.
First we turn ATemplate into a development gadget, so we can make our updates directly on the filesystem.
./misc/admin/create_devel_gadget.pl --name ATemplate --implements ATemplate --implements TemplateMain --implements TemplateEditorPage --implements TemplatePostPage --uri_path /admin/template/devel/ --comp_path template-devel
followed by a symlink to put the Mason components down our web path:
ln -s /home/dug/rcs/comma/Gadgets-Oblong/misc/gadgets/atemplate-source/mason/ /ob/webtree/template-devel
Next we duplicate and modify the wiki sources, like so:
cp -a misc/gadgets/wiki-source/ misc/gadgets/wiki-textonly-source
mv misc/gadgets/wiki-textonly-source/Wiki.devel misc/gadgets/wiki-textonly-source/Wiki-TextOnly.devel
And in Wiki-TextOnly.devel, s/Wiki/Wiki-TextOnly/g; s/wiki/wiki-textonly/g; except for the app-string which remains "Wiki"
./misc/admin/create_devel_gadget.pl --name Wiki-TextOnly --implements Wiki --implements Wiki-TextOnly --uri_path /wiki-to --comp_path wiki-textonly-devel
ln -s /home/dug/rcs/comma/Gadgets-Oblong/misc/gadgets/wiki-textonly-source/mason/ /ob/webtree/wiki-textonly-devel
Now that we've created our new development gadgets, we need to tell the configuration system that for our new /wiki-to/ URI we want to use our new non-javascript templates that live in /template-to/, like so:
./misc/admin/add_config.pl --gadget ATemplate --path /wiki-to/ --key template_dir --value /template-to/
And cp -a /webtree/template/ /webtree/template-to/. Now we can start hacking on our newly configured development templates.
Our original "nav" template, which is included by the autohandler that is eventually inherited by our Wiki gadget looks like so:
<a id="login-link" href="/me/">sign in</a>
<script language="javascript" type="text/javascript"><!--
login_widget ( 'login-link', '/util/login-widget' );
//--></script>
<a href="/">home page</a>
<a id="new-post-link" href="/new-post/">new post</a>
<script language="javascript" type="text/javascript"><!--
new_post_widget ( 'new-post-link', '/util/new-post-widget' );
//--></script>
<a href="/pub/stat/">recent activity</a>
<a href="/pub/tag/">tags</a>
<a href="/pub/search.html">search</a>
There is some javascript in there, but also the links are static, which means if we want to relocate our wiki (as we did with our development wiki, relocating it to /wiki-to/) we need to change the paths. We'll fix that by making the links dynamic and eliminating the javascript, leaving us with our new /webtree/template-to/nav component:
<a id="login-link" href="<% $g->root %>me/">sign in</a>
<a href="<% $g->root %>">home page</a>
<a id="new-post-link" href="<% $g->root %>new-post/">new post</a>
<a href="<% $g->root %>pub/stat/">recent activity</a>
<a href="<% $g->root %>pub/tag/">tags</a>
<a href="<% $g->root %>pub/search.html">search</a>`
These nav components are loaded by the autohandler that the wiki inherits from. Looking at /webtree/wiki-textonly-devel/index.html we see this block:
<%flags>
inherit => '/&TemplateMain/autohandler-postpage'
</%flags>
Our new development ATemplate gadget is implementing the "TemplateMain" api, and we can see in /webtree/template-devel/autohandler-postpage that there are javascript libraries loaded there, and that our template header/footer/nav/css files are not being served through Mason, but through the send_file component which sends the content byte for byte.
Let's make a new autohandler-postpage-to template, use it to serve the newly dynamic nav component:
cp /webtree/template-devel/autohandler-postpage /webtree/template-devel/autohandler-postpage-to
And modivy the new text-only authohandler-postpage component to be:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<title><% $title %></title>
<link rel="stylesheet" type="text/css" href="<% $css_file %>"></link>
%# <link rel="alternate" type="application/rss+xml" title="<% loc("RSS Feed") %>" href="<% $g->root %>pub/feed/index.xml" />
<link rel="alternate" type="text/xml" title="<% loc("RSS Feed") %>" href="<% $g->root %>pub/feed/index.xml" />
</head>
<div id="all">
<div id="header"><& $header_file &></div>
<div id="nav"><& $nav_file &></div>
<div id="main">
<% $m->call_next %>
</div> <!-- end main div -->
<div id="footer"><& $footer_file &></div>
</div> <!-- end all div -->
</body>
</html>
%
%
<%init>
my $title = $g->gadget ? $g->gadget->gadget_name : '';
if ( $m->request_comp->method_exists('title') ) {
$title .= ' - ' . $m->request_comp->call_method('title');
}
my $template_dir = $g->in_interface->conf_get ( 'template_dir' );
my $header_file = "$template_dir/header";
my $nav_file = "$template_dir/nav";
my $footer_file = "$template_dir/footer";
my $css_file = "$template_dir/base.css";
</%init>
%
%
%
<%flags>
inherit => undef
</%flags>`
Go ahead and load http://localhost/wiki-to/ in your browser. You may see some errors or omissions due to our partially lobotomized JavaScript. Don't worry, we'll continue our surgery, eliminating this needless hunk of coretex.
The first error we encounter is that in a list of posts the "created" and "latest activity" fields are blank, because we don't load the "Ago" code anymore.
This is simple to fix. On the CPAN there is a module called
Time::Duration that contains a "ago" method that performs a similar
enough function. After installing that module, adding a use
Time::Duration (); line to /webtree/handler.pl, we can replace the
contents of /webtree/template-devel/util/ago with this:
<%args>
$timestamp => undef
</%args>
%
% if ( $timestamp ) {
<% Time::Duration::ago( time - $timestamp ) %>
% }
%
Refreshing the page should get us back to a proper display. Moving
down the line by clicking on the "new post" link brings us to the next
problem. /webtree/wiki-textonly-devel/index.html inherits from a
javascripty autohandler. Changing the "inherit" flag from
autohandler-editorpage-wiki to autohandler-postpage-to will solve
that particular problem, leaving us with these remaining problems.
What to do with tags, attachments and permissions?
Currently the edit page inside the "APost" gadget has some inlined JavaScript. We'll devel-ify this gadget and make a textonly version, using some delimeted syntax for tags and permissions, and show three upload entries for new attachments.
Make a devel post gadget:
./misc/admin/create_devel_gadget.pl --name APost --implements APost --uri_path /admin/apost/devel/ --comp_path apost-devel
and symlink the components:
ln -s /home/dug/rcs/comma/Gadgets-Oblong/misc/gadgets/apost-source/mason/ /ob/webtree/apost-devel
In /ob/webtree/wiki-textonly-devel/new-post/index.html, change the call from
'/&APost/edit' to '/&APost/edit-to', and then
cp /ob/webtree/apost-devel/edit /ob/webtree/apost-devel/edit-to
so we have a new edit-to textonly component to work on.
ADGETS