[Koha-patches] [PATCH] Brand New UI for Alert Configuration

Daniel Sweeney daniel.sweeney at liblime.com
Tue Feb 3 23:02:08 CET 2009


From: John Beppu <john.beppu at liblime.com>

- grid layout (javascript required now)
- makes distinction between checkin and checkout messages
- no longer have to click on a button to submit the branch selection form

Signed-off-by: Daniel Sweeney <daniel.sweeney at liblime.com>
---
 C4/ItemCirculationAlertPreference.pm               |  150 +++++++++++++---
 admin/item_circulation_alerts.pl                   |  142 ++++++---------
 .../en/modules/admin/item_circulation_alerts.tmpl  |  190 ++++++++++++--------
 3 files changed, 298 insertions(+), 184 deletions(-)

diff --git a/C4/ItemCirculationAlertPreference.pm b/C4/ItemCirculationAlertPreference.pm
index df231a4..7ade3df 100644
--- a/C4/ItemCirculationAlertPreference.pm
+++ b/C4/ItemCirculationAlertPreference.pm
@@ -18,6 +18,8 @@ package C4::ItemCirculationAlertPreference;
 use strict;
 use warnings;
 use C4::Context;
+use C4::Category;
+use C4::ItemType;
 use Carp qw(carp croak);
 
 our $AUTOLOAD;
@@ -25,7 +27,7 @@ our $AUTOLOAD;
 # helper function for validating \%opts
 our $valid = sub {
     my $opts = shift;
-    for (qw(branchcode categorycode item_type)) {
+    for (qw(branchcode categorycode item_type notification)) {
         exists($opts->{$_}) || croak("'$_' is a required parameter.");
     }
 };
@@ -46,20 +48,22 @@ Basics:
     # a short-cut to reduce typing the long package name over and over again
     my $preferences = 'C4::ItemCirculationAlertPreference';
 
-Creating Rules:
+Creating a restriction on sending messages:
 
     my $pref = $preferences->create({
         branchcode   => 'CPL',
         categorycode => 'YA',
         item_type    => 'BK',
+        notification => 'CHECKOUT',
     });
 
-Deleting Rules:
+Removing a restriction on sending messages:
 
     $preferences->delete({
         branchcode   => 'CPL',
         categorycode => 'YA',
         item_type    => 'BK',
+        notification => 'CHECKOUT',
     });
 
 =head1 DESCRIPTION
@@ -96,7 +100,28 @@ sub new {
 =head3 C4::ItemCirculationAlertPreference->create(\%opts)
 
 This will find or create an item circulation alert preference.  You must pass
-it a B<branchcode>, B<categorycode>, and B<item_type>.
+it a B<branchcode>, B<categorycode>, B<item_type>, and B<notification>.  Valid
+values for these attributes are as follows:
+
+=over 4
+
+=item branchcode
+
+branches.branchcode
+
+=item categorycode
+
+category.categorycode
+
+=item item_type
+
+itemtypes.itemtype
+
+=item notification
+
+This can be "CHECKIN" or "CHECKOUT"
+
+=back
 
 =cut
 
@@ -109,22 +134,25 @@ sub create {
         FROM  item_circulation_alert_preferences
         WHERE branchcode   = ?
         AND   categorycode = ?
-        AND   item_type    = ?",
+        AND   item_type    = ?
+        AND   notification = ?",
         { Slice => {} },
         $opts->{branchcode},
         $opts->{categorycode},
         $opts->{item_type},
+        $opts->{notification},
     );
     if (@$prefs) {
         return $class->new($prefs->[0]);
     } else {
         my $success = $dbh->do(
             "INSERT INTO item_circulation_alert_preferences
-            (branchcode, categorycode, item_type) VALUES (?, ?, ?)",
+            (branchcode, categorycode, item_type, notification) VALUES (?, ?, ?, ?)",
             {},
             $opts->{branchcode},
             $opts->{categorycode},
             $opts->{item_type},
+            $opts->{notification},
         );
         if ($success) {
             my $self = {
@@ -132,6 +160,7 @@ sub create {
                 branchcode   => $opts->{branchcode},
                 categorycode => $opts->{categorycode},
                 item_type    => $opts->{item_type},
+                notification => $opts->{notification},
             };
             return $class->new($self);
         } else {
@@ -163,15 +192,19 @@ sub delete {
         );
     } else {
         $valid->($opts);
-        $dbh->do(
+        my $sql =
             "DELETE FROM item_circulation_alert_preferences
             WHERE branchcode   = ?
             AND   categorycode = ?
-            AND   item_type    = ?",
+            AND   item_type    = ?
+            AND   notification = ?";
+        $dbh->do(
+            $sql,
             {},
             $opts->{branchcode},
             $opts->{categorycode},
-            $opts->{item_type}
+            $opts->{item_type},
+            $opts->{notification},
         );
     }
 }
@@ -200,48 +233,52 @@ B<Example>:
 
 =cut
 
-sub is_enabled_for {
+sub is_disabled_for {
     my ($class, $opts) = @_;
     $valid->($opts);
     my $dbh = C4::Context->dbh;
 
     # Does a preference exist to block this alert?
     my $query = qq{
-        SELECT id
+        SELECT id, branchcode, categorycode, item_type, notification
           FROM item_circulation_alert_preferences
          WHERE (branchcode   = ? OR branchcode   = '*')
            AND (categorycode = ? OR categorycode = '*')
            AND (item_type    = ? OR item_type    = '*')
+           AND (notification = ? OR notification = '*')
     };
 
     my $preferences = $dbh->selectall_arrayref(
         $query,
-        { },
+        { Slice => {} },
         $opts->{branchcode},
         $opts->{categorycode},
         $opts->{item_type},
+        $opts->{notification},
     );
 
     # If any preferences showed up, we are NOT enabled.
-    if (@$preferences) {
-        return undef;
-    } else {
-        return 1;
-    }
+    return @$preferences;
+}
+
+sub is_enabled_for {
+    my ($class, $opts) = @_;
+    return not $class->is_disabled_for($opts);
 }
 
 
 
 
-=head3 C4::ItemCirculationAlertPreference->find({ branchcode => $bc })
+=head3 C4::ItemCirculationAlertPreference->find({ branchcode => $bc, notification => $type })
 
 This method returns all the item circulation alert preferences for a given
-branch.
+branch and notification.
 
 B<Example>:
 
     my @branch_prefs = C4::ItemCirculationAlertPreference->find({
-        branchcode => 'CPL',
+        branchcode   => 'CPL',
+        notification => 'CHECKIN',
     });
 
 =cut
@@ -250,21 +287,83 @@ sub find {
     my ($class, $where) = @_;
     my $dbh = C4::Context->dbh;
     my $query = qq{
-        SELECT id, branchcode, categorycode, item_type
+        SELECT id, branchcode, categorycode, item_type, notification
           FROM item_circulation_alert_preferences
-         WHERE branchcode = ?
+         WHERE branchcode = ? AND notification = ?
          ORDER BY categorycode, item_type
     };
     return    map { $class->new($_) }    @{$dbh->selectall_arrayref(
         $query,
         { Slice => {} },
-        $where->{branchcode}
+        $where->{branchcode},
+        $where->{notification},
     )};
 }
 
 
 
 
+=head3 C4::ItemCirculationAlertPreference->grid({ branchcode => $c, notification => $type })
+
+Return a 2D arrayref for the grid view in F<admin/item_circulation_alert_preferences.pl>.
+Each row represents a category (like 'Patron' or 'Young Adult') and
+each column represents an itemtype (like 'Book' or 'Music').
+
+Each cell contains...
+
+B<Example>:
+
+    use Data::Dump 'pp';
+    my $grid = C4::ItemCirculationAlertPreference->grid({
+        branchcode   => 'CPL',
+        notification => 'CHECKOUT',
+    });
+    warn pp($grid);
+
+See F<admin/item_circulation_alerts.pl> to see how this method is used.
+
+=cut
+
+sub grid {
+    my ($class, $where) = @_;
+    my @branch_prefs = $class->find($where);
+    my @default_prefs = $class->find({ branchcode => '*', notification => $where->{notification} });
+    my @cc = C4::Category->all;
+    my @it = C4::ItemType->all;
+    my $notification = $where->{notification};
+    my %disabled = map {
+        my $key = $_->categorycode . "-" . $_->item_type . "-" . $notification;
+        $key =~ s/\*/_/g;
+        ($key => 1);
+    } @branch_prefs;
+    my %default = map {
+        my $key = $_->categorycode . "-" . $_->item_type . "-" . $notification;
+        $key =~ s/\*/_/g;
+        ($key => 1);
+    } @default_prefs;
+    my @grid;
+    for my $c (@cc) {
+        my $row = { description => $c->description, items => [] };
+        push @grid, $row;
+        for my $i (@it) {
+            my $key = $c->categorycode . "-" . $i->itemtype . "-" . $notification;
+            $key =~ s/\*/_/g;
+            my @classes;
+            if ($disabled{$key}) {
+                push @classes, 'disabled';
+            }
+            if ($default{$key}) {
+                push @classes, 'default';
+            }
+            push @{$row->{items}}, { class => join(' ', @classes),  id => $key };
+        }
+    }
+    return \@grid;
+}
+
+
+
+
 =head2 Object Methods
 
 These are read-only accessors for the various attributes of a preference.
@@ -277,6 +376,8 @@ These are read-only accessors for the various attributes of a preference.
 
 =head3 $pref->item_type
 
+=head3 $pref->notification
+
 =cut
 
 sub AUTOLOAD {
@@ -290,12 +391,13 @@ sub AUTOLOAD {
     }
 }
 
+sub DESTROY { }
 
 
 
 =head1 SEE ALSO
 
-L<C4::Circulation>, C<admin/item_circulation_alerts.pl>
+L<C4::Circulation>, F<admin/item_circulation_alerts.pl>
 
 =head1 AUTHOR
 
diff --git a/admin/item_circulation_alerts.pl b/admin/item_circulation_alerts.pl
index f8c1227..f2a9ace 100755
--- a/admin/item_circulation_alerts.pl
+++ b/admin/item_circulation_alerts.pl
@@ -22,6 +22,7 @@ use CGI;
 use File::Basename;
 use Encode;
 use URI::Escape 'uri_escape_utf8';
+use JSON;
 #use Data::Dump 'pp';
 
 use C4::Auth;
@@ -35,15 +36,6 @@ use C4::Output;
 # shortcut for long package name
 my $preferences = 'C4::ItemCirculationAlertPreference';
 
-# common redirect code
-sub redirect {
-    my ($input) = @_;
-    my $path = defined($input->param('redirect_to'))
-        ? $input->param('redirect_to')
-        : basename($0);
-    print $input->redirect($path);
-}
-
 # utf8 filter
 sub utf8 {
     my ($data, @keys) = @_;
@@ -53,15 +45,15 @@ sub utf8 {
     $data;
 }
 
-# add long category and itemtype descriptions to preferences
-sub category_and_itemtype {
-    my ($categories, $item_types, @prefs) = @_;
-    my %c = map { $_->{categorycode} => $_->{description} } @$categories;
-    my %i = map { $_->{itemtype}     => $_->{description} } @$item_types;
-    for (@prefs) {
-        $_->{category_description} = $c{$_->{categorycode}} || 'Default';
-        $_->{item_type_description} = $i{$_->{item_type}} || 'Default';
+# prepend "br_" to column name and replace spaces with "<br/>"
+sub br {
+    my ($data, @keys) = @_;
+    for (@keys) {
+        my $br = $data->{$_};
+        $br =~ s{\s+}{<br/>}g;
+        $data->{'br_'.$_} = $br;
     }
+    $data;
 }
 
 # display item circulation alerts
@@ -94,61 +86,72 @@ sub show {
     my $branch_name = exists($br->{$branch}) && $br->{$branch}->{branchname};
 
     my @categories = map { utf8($_, 'description') }  (
-        C4::Category->new({ categorycode => '*', description => 'Default' }),
         C4::Category->all
     );
-    my @item_types = map { utf8($_, 'description') }  (
-        C4::ItemType->new({ itemtype => '*', description => 'Default' }),
+    my @item_types = map { utf8($_, 'description'); br($_, 'description') }  (
         C4::ItemType->all
     );
-    my @default_prefs = $preferences->find({ branchcode => '*' });
-    my @branch_prefs;
-    my $redirect_to = "?branch=$branch";
+    my $grid_checkout = $preferences->grid({ branchcode => $branch, notification => 'CHECKOUT' });
+    my $grid_checkin  = $preferences->grid({ branchcode => $branch, notification => 'CHECKIN' });
 
-    $template->param(redirect_to        => $redirect_to);
-    $template->param(redirect_to_x      => uri_escape_utf8($redirect_to));
     $template->param(branch             => $branch);
-    $template->param(branch_name        => $branch_name);
+    $template->param(branch_name        => $branch_name || 'Default');
     $template->param(branches           => \@branches);
     $template->param(categories         => \@categories);
     $template->param(item_types         => \@item_types);
-    $template->param(default_prefs      => \@default_prefs);
-    if ($branch ne '*') {
-        @branch_prefs = $preferences->find({ branchcode => $branch });
-        $template->param(branch_prefs => \@branch_prefs);
-    }
-    category_and_itemtype(\@categories, \@item_types, (@default_prefs, @branch_prefs));
+    $template->param(grid_checkout      => $grid_checkout);
+    $template->param(grid_checkin       => $grid_checkin);
+
     output_html_with_http_headers $input, $cookie, $template->output;
 }
 
-# create item circulation alert preference and redirect
-sub create {
+# toggle a preference via ajax
+sub toggle {
     my ($input) = @_;
-    my $branchcode   = $input->param('branchcode');
-    my $categorycode = $input->param('categorycode');
-    my $item_type    = $input->param('item_type');
-    $preferences->create({
-        branchcode   => $branchcode,
-        categorycode => $categorycode,
+    my $id = $input->param('id');
+    my $branch = $input->param('branch');
+    my ($category, $item_type, $notification) = split('-', $id);
+    $category  =~ s/_/*/;
+    $item_type =~ s/_/*/;
+
+    my $settings = {
+        branchcode   => $branch,
+        categorycode => $category,
         item_type    => $item_type,
-    });
-    redirect($input);
-}
+        notification => $notification,
+    };
+
+    my $restrictions = $preferences;  # all the same thing...
+    my $notifications = $preferences; #
+    if ($notifications->is_enabled_for($settings)) {
+        # toggle by adding a restriction
+        $restrictions->create($settings);
+    } else {
+        # toggle by removing the restriction
+        $restrictions->delete($settings);
+    }
 
-# delete preference and redirect
-sub delete {
-    my ($input) = @_;
-    my $id = $input->param('id');
-    $preferences->delete({ id => $id });
-    redirect($input);
+    my $response = { success => 1 };
+    my @reasons  = $notifications->is_disabled_for($settings);
+    if (@reasons == 0) {
+        $response->{class} = '';
+    } else {
+        my $default_exists   = grep { $_->{branchcode} eq '*' } @reasons;
+        my $non_default_also = grep { $_->{branchcode} ne '*' } @reasons;
+        my @classes;
+        push @classes, 'default'  if $default_exists;
+        push @classes, 'disabled' if $non_default_also;
+        $response->{class} = join(' ', @classes);
+    }
+    print $input->header;
+    print encode_json($response);
 }
 
 # dispatch to various actions based on CGI parameter 'action'
 sub dispatch {
     my %handler = (
         show   => \&show,
-        create => \&create,
-        delete => \&delete,
+        toggle => \&toggle,
     );
     my $input  = new CGI;
     my $action = $input->param('action') || 'show';
@@ -203,35 +206,9 @@ branch '*' is used.
 
 
 
+=head3 ?action=toggle
 
-=head3 ?action=create
-
-Create an item circulation alert preference.
-
-Parameters:
-
-=over 4
-
-=item branchcode
-
-Branch code
-
-=item categorycode
-
-Patron category
-
-=item item_type
-
-Item type
-
-=back
-
-
-
-
-=head3 ?action=delete
-
-Delete an item circulation alert preference.
+Toggle a preference via AJAX
 
 Parameters:
 
@@ -239,12 +216,13 @@ Parameters:
 
 =item id
 
-The id of the preference to delete.
-
-=back
+"$categorycode-$item_type-$notification"
 
+=item branch
 
+Branch code to apply this preference to
 
+=back
 
 =cut
 
diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/item_circulation_alerts.tmpl b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/item_circulation_alerts.tmpl
index 26d2779..49bf688 100644
--- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/item_circulation_alerts.tmpl
+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/item_circulation_alerts.tmpl
@@ -8,7 +8,68 @@ div.circulation-alert h2 {
 div.circulation-alert h3 {
   margin-top: 1em;
 }
+
+table.grid thead th {
+  vertical-align: bottom;
+}
+
+table.grid tbody th {
+  text-align: right;
+}
+
+table.grid tbody td.info {
+  background: #fff;
+}
+
+table.grid.active tbody td {
+  width: 10%;
+  cursor: pointer;
+}
+
+table.grid tbody td {
+  background: #cfc;
+  color: #111;
+}
+
+table.grid td.disabled {
+  background: #fcc;
+}
+
+table.grid td.default {
+  background: #f88;
+}
 </style>
+<script>
+var $branch = "<!-- TMPL_VAR NAME="branch" -->";
+$(function(){
+
+    $('#branch_selector input:submit').hide();
+    $('#branch').change(function(){
+        $('#branch_selector').submit();
+    });
+
+    $('table.grid.active tbody td').click(function(ev){
+        var id = this.id;
+        var td = $(this);
+        if (td.hasClass('default') && $branch != '*') {
+            td.html(_('Blocked'));
+        } else {
+            td.html(_('Saving...'));
+            $.ajax({
+                url      : '/cgi-bin/koha/admin/item_circulation_alerts.pl',
+                type     : 'POST',
+                dataType : 'json',
+                data     : { action: 'toggle', id: id, branch: $branch },
+                success  : function(response){
+                    td.html(' ');
+                    td.attr('class', response.class);
+                }
+            });
+        }
+    });
+
+});
+</script>
 </head>
 <body>
 <!-- TMPL_INCLUDE NAME="header.inc" -->
@@ -24,9 +85,9 @@ div.circulation-alert h3 {
 <h1>Item Circulation Alerts</h1>
 
 
-<h2>Pick a branch:</h2>
-<form method="GET">
-<select name="branch">
+<h2>Select a library:</h2>
+<form id="branch_selector" method="GET">
+<select id="branch" name="branch">
 <!-- TMPL_LOOP NAME="branches" -->
 <!-- TMPL_IF NAME="selected" -->
 <option value="<!-- TMPL_VAR NAME="branchcode" -->" selected="selected"><!-- TMPL_VAR NAME="branchname" --></option>
@@ -35,105 +96,78 @@ div.circulation-alert h3 {
 <!-- /TMPL_IF -->
 <!-- /TMPL_LOOP -->
 </select>
-<input type="submit" name="submit" value="Pick" />
+<input type="submit" name="pick" value="Pick" />
 </form>
 
 
-<h2>Circulation alerts are disabled for the following conditions:</h2>
-<form method="POST">
-<input type="hidden" name="action" value="create" />
-<input type="hidden" name="branchcode" value="*" />
-<input type="hidden" name="redirect_to" value="<!-- TMPL_VAR NAME="redirect_to" -->" />
-<h3>Default (for all branches)</h3>
-<table>
+<h2>Circulation Alerts for <!-- TMPL_VAR NAME="branch_name" --></h2>
+<p>Click on the grid to toggle the settings.</p>
+
+<h3>Checkout</h3>
+<table class="grid active" width="100%">
 <thead>
 <tr>
-<th>Patron Category</th>
-<th>Item Type</th>
-<th>Action</th>
+  <th>&nbsp;</th>
+  <!-- TMPL_LOOP NAME="item_types" -->
+  <th><!-- TMPL_VAR NAME="br_description" --></th>
+  <!-- /TMPL_LOOP -->
 </tr>
 </thead>
 <tbody>
-<!-- TMPL_LOOP NAME="default_prefs" -->
+<!-- TMPL_LOOP NAME="grid_checkout" -->
 <tr>
-<td><!-- TMPL_VAR NAME="category_description" --></td>
-<td><!-- TMPL_VAR NAME="item_type_description" --></td>
-<td><a href="?action=delete&id=<!-- TMPL_VAR NAME="id" -->&redirect_to=<!-- TMPL_VAR NAME="redirect_to_x" -->">delete</a></td>
+  <th><!-- TMPL_VAR NAME="description" --></th>
+  <!-- TMPL_LOOP NAME="items" -->
+  <td class="<!-- TMPL_VAR NAME="class" -->" id="<!-- TMPL_VAR NAME="id" -->">&nbsp;</td>
+  <!-- /TMPL_LOOP -->
 </tr>
 <!-- /TMPL_LOOP -->
 </tbody>
-<tfoot>
-<tr>
-<td>
-<select name="categorycode">
-<!-- TMPL_LOOP NAME="categories" -->
-<option value="<!-- TMPL_VAR NAME="categorycode" -->"><!-- TMPL_VAR NAME="description" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-</td>
-<td>
-<select name="item_type">
-<!-- TMPL_LOOP NAME="item_types" -->
-<option value="<!-- TMPL_VAR NAME="itemtype" -->"><!-- TMPL_VAR NAME="description" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-</td>
-<td>
-<input type="submit" name="submit" value="Disable Alert" />
-</td>
-</tr>
-</tfoot>
 </table>
-</form>
 
-
-<!-- TMPL_IF NAME="branch_name" -->
-<form method="POST">
-<input type="hidden" name="action" value="create" />
-<input type="hidden" name="branchcode" value="<!-- TMPL_VAR NAME="branch" -->" />
-<input type="hidden" name="redirect_to" value="<!-- TMPL_VAR NAME="redirect_to" -->" />
-<h3><!-- TMPL_VAR NAME="branch_name" --></h3>
-<table>
+<h3>Check-in</h3>
+<table class="grid active" width="100%">
 <thead>
 <tr>
-<th>Patron Category</th>
-<th>Item Type</th>
-<th>Action</th>
+  <th>&nbsp;</th>
+  <!-- TMPL_LOOP NAME="item_types" -->
+  <th><!-- TMPL_VAR NAME="br_description" --></th>
+  <!-- /TMPL_LOOP -->
 </tr>
 </thead>
 <tbody>
-<!-- TMPL_LOOP NAME="branch_prefs" -->
+<!-- TMPL_LOOP NAME="grid_checkin" -->
 <tr>
-<td><!-- TMPL_VAR NAME="category_description" --></td>
-<td><!-- TMPL_VAR NAME="item_type_description" --></td>
-<td><a href="?action=delete&id=<!-- TMPL_VAR NAME="id" -->&redirect_to=<!-- TMPL_VAR NAME="redirect_to_x" -->">delete</a></td>
+  <th><!-- TMPL_VAR NAME="description" --></th>
+  <!-- TMPL_LOOP NAME="items" -->
+  <td class="<!-- TMPL_VAR NAME="class" -->" id="<!-- TMPL_VAR NAME="id" -->">&nbsp;</td>
+  <!-- /TMPL_LOOP -->
 </tr>
 <!-- /TMPL_LOOP -->
 </tbody>
-<tfoot>
-<tr>
-<td>
-<select name="categorycode">
-<!-- TMPL_LOOP NAME="categories" -->
-<option value="<!-- TMPL_VAR NAME="categorycode" -->"><!-- TMPL_VAR NAME="description" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-</td>
-<td>
-<select name="item_type">
-<!-- TMPL_LOOP NAME="item_types" -->
-<option value="<!-- TMPL_VAR NAME="itemtype" -->"><!-- TMPL_VAR NAME="description" --></option>
-<!-- /TMPL_LOOP -->
-</select>
-</td>
-<td>
-<input type="submit" name="submit" value="Disable Alert" />
-</td>
-</tr>
-</tfoot>
 </table>
-</form>
-<!-- /TMPL_IF -->
+
+<h3>Legend</h3>
+<table class="grid">
+<thead>
+  <th>Color</th>
+  <th>Meaning</th>
+</thead>
+<tbody>
+  <tr>
+    <td width="100" class="default">&nbsp;</td>
+    <td class="info">These are disabled for ALL libraries.  To change these settings, choose the "Default" library.</td>
+  </tr>
+  <tr>
+    <td class="disabled">&nbsp;</td>
+    <td class="info">These are disabled for the current library.</td>
+  </tr>
+  <tr>
+    <td class="">&nbsp;</td>
+    <td class="info">These are enabled.</td>
+  </tr>
+</tbody>
+</table>
 
 
 </div>
-- 
1.5.5.GIT



More information about the Koha-patches mailing list