NAME
    CatalystX::ListFramework::Builder - Instant AJAX web front-end for
    DBIx::Class, using Catalyst

VERSION
    This document refers to version 0.31 of
    CatalystX::ListFramework::Builder

WARNING
    This is an *ALPHA RELEASE*. I'd really appreciate any bug reports; you
    can use the CPAN RT bug tracking system, or email me (Oliver) directly
    at the address at the bottom of this page. Please also be aware that the
    configuration file content has changed from previous releases of the
    module.

PURPOSE
    You have a database, and wish to have a basic web interface supporting
    Create, Retrieve, Update, Delete and Search, with little effort.

    This module, with only a few lines of configuration, is able to create
    such interfaces on the fly. They are a bit whizzy and all Web 2.0-ish.

SYNOPSIS
    A configuration file somewhere on your system:

     # [listframeworkuser.conf] in Config::General format
 
     extjs2   /javascript/extjs-2
 
     <Model::LFB::DBIC>
         schema_class   My::Database::Schema
         connect_info   dbi:Pg:dbname=mydbname;host=mydbhost.example.com;
         connect_info   username
         connect_info   password
         <connect_info>
             AutoCommit   1
         </connect_info>
     </Model::LFB::DBIC>

    And in the CGI area of your web server:

     package ListFrameworkUser;
     use Catalyst qw(ConfigLoader +CatalystX::ListFramework::Builder);
 
     __PACKAGE__->setup;
     1;

    Now going to the CGI area's URL will display a list of the tables in
    your database. Each item is a link to the web interface for that table.

DESCRIPTION
    This module contains an application which will automatically construct a
    web interface for a database on the fly. The web interface supports
    Create, Retrieve, Update, Delete and Search operations.

    The interface is not written to static files on your system, and uses
    AJAX to act upon the database without reloading your web page (much like
    other Web 2.0 appliactions, for example Google Mail).

    Almost all the information required by the application is retrieved from
    the DBIx::Class ORM frontend to your database, which it is expected that
    you have already set up (although see "USAGE", below). This means that
    any change in database schema ought to be reflected immediately in the
    web interface after a page refresh.

USAGE
  Pre-configuration
    You'll need to download the ExtJS Javascript Library (version 2.2+
    recommended), from this web page:
    <http://extjs.com/products/extjs/download.php>.

    Install it to your web server in a location that it is able to serve as
    static content. Make a note of the path used in a URL to retrieve this
    content, as it will be needed in the application configuration file,
    below.

  Scenario 1: Plugin to an existing Catalyst App
    This mode is for when you have written your Catalyst application, but
    the Views are catering for the users and as an admin you'd like a more
    direct, secondary web interface to the database.

     package ListFrameworkUser;
     use Catalyst qw(ConfigLoader +CatalystX::ListFramework::Builder);
 
     __PACKAGE__->setup;
     1;

    Adding "CatalystX::ListFramework::Builder" (LFB) as a plugin to your
    Catalyst application, as above, causes it to scan your existing Models.
    If any of them are built using Catalyst::Model::DBIC::Schema, they are
    automatically loaded. You still need to provide a small amount of
    configuration:

     extjs2   /javascript/extjs-2
     <Controller::LFB::Root>
         <action>
             <base>
                 PathPart   admin
             </base>
         </action>
     </Controller::LFB::Root>

    First the application needs to know where your copy of ExtJS is, on the
    web server. Use the "extjs2" option as shown above to specify the URL
    path to the libraries. This will be used in the templates in some way
    like this:

     <script type="text/javascript" src="[% c.config.extjs2 %]/ext-all.js" />

    In the above example, the path ".../admin/" will contain the LFB
    application, and all generated links in LFB will also make use of that
    path. Remember this is added to the "base" of your Cataylst application
    which, depending on your web server configuration, might also have a
    leading path.

    This mode of operation works even if you have more than one database.
    You will be offered a Home screen to select the database, and then
    another menu to select the table within that.

  Scenario 2: Frontend for an existing "DBIx::Class::Schema" based class
    In this mode, "CatalystX::ListFramework::Builder" (LFB) is running
    standalone, in a sense as the Catalyst application itself. Your main
    application file looks the same as in Scenario 1, though:

     package ListFrameworkUser;
     use Catalyst qw(ConfigLoader +CatalystX::ListFramework::Builder);
 
     __PACKAGE__->setup;
     1;

    For the configuration, you need to tell LFB which package contains the
    "DBIx::Class" schema, and also provide database connection parameters.

     extjs2   /javascript/extjs-2
     <Model::LFB::DBIC>
         schema_class   My::Database::Schema
         connect_info   dbi:Pg:dbname=mydbname;host=mydbhost.example.com;
         connect_info   username
         connect_info   password
         <connect_info>
             AutoCommit   1
         </connect_info>
     </Model::LFB::DBIC>

    First the application needs to know where your copy of ExtJS is, on the
    web server. Use the "extjs2" option as shown above to specify the URL
    path to the libraries. This will be used in the templates in some way
    like this:

     <script type="text/javascript" src="[% c.config.extjs2 %]/ext-all.js" />

    The "Model::LFB::DBIC" section must look (and be named) exactly like
    that above, except you should of course change the "schema_class" value
    and the values within "connect_info".

   "DBIx::Class" setup
    You will of course need the "DBIx::Class" schema to be created and
    installed on your system. The recommended way to do this quickly is to
    use the excellent DBIx::Class::Schema::Loader module which connects to
    your database and writes "DBIx::Class" Perl modules for it.

    Pick a suitable namespace for your schema, which is not related to this
    application. For example "DBIC::Database::Foo::Schema" for the "Foo"
    database (in the configuration example above we used
    "My::Database::Schema"). Then use the following command-line
    incantation:

     perl -MDBIx::Class::Schema::Loader=make_schema_at,dump_to_dir:. -e \
         'make_schema_at("DBIC::Database::Foo::Schema", { debug => 1 }, \
         ["dbi:Pg:dbname=foodb;host=mydbhost.example.com","user","pass" ])'

    This will create a directory (such as "DBIC") which you need to move
    into your Perl Include path (one of the paths shown at the end of "perl
    -V").

  Scenario 3: Lazy loading a "DBIx::Class" schema
    If you're in such a hurry that you can't create the "DBIx::Class"
    schema, as shown in the previous section, then
    "CatalystX::ListFramework::Builder" (LFB) is able to do this on the fly,
    but it will slow the application down a little.

    The application file and configuration are very similar to those in
    Scenario 2, above, except that you omit the "schema_class" configuration
    option because you want LFB to generate that on the fly (rather than
    reading an existing one from disk).

     package ListFrameworkUser;
     use Catalyst qw(ConfigLoader +CatalystX::ListFramework::Builder);
 
     __PACKAGE__->setup;
     1;

     extjs2   /javascript/extjs-2
     <Model::LFB::DBIC>
         connect_info   dbi:Pg:dbname=mydbname;host=mydbhost.example.com;
         connect_info   username
         connect_info   password
         <connect_info>
             AutoCommit   1
         </connect_info>
     </Model::LFB::DBIC>

    When LFB loads it will connect to the database and use the
    DBIx::Class::Schema::Loader module to reverse engineer its schema. To
    work properly you'll need the very latest version of that module (0.05
    or greater).

    The other drawback to this scenario (other than the slower operation) is
    that you have no ability to customize how foreign, related records are
    shown. A related record will simply be represented as something
    approximating the name of the foreign table, the names of the primary
    keys, and associated values (e.g. id(5)).

TIPS AND TRICKS
  Representing related records
    When the web interface wants to display a column which references
    another table, you can make things look much better by adding a custom
    render method to your "DBIx::Class" Result Classes (i.e. the class files
    for each table).

    First, the application will look for a method called "display_name" and
    use that. Here is an example which could be added to your Result Class
    files below the line which reads "DO NOT MODIFY THIS OR ANYTHING ABOVE",
    and in this case returns the data from the "title" column:

     sub display_name {
         my $self = shift;
         return $self->title || '';
     }

    Failing the existence of a "display_name" method, the application
    attempts to stringify the row object. Using stringification is not
    recommended, although some people like it. Here is an example of a
    stringification handler:

     use overload '""' => sub {
         my $self = shift;
         return $self->title || '';
     }, fallback => 1;

    If all else fails the application prints the best hint it can to
    describe the foreign row. This is something approximating the name of
    the foreign table, the names of the primary keys, and associated values.
    It's better than stringifying the object the way Perl does, anyway.

  Columns with auto-increment data types
    For those columns where your database uses an auto-incremented value,
    add the "is_auto_increment => 1," option to the relevant hash in
    add_columns(). This will let the application know you don't need to
    supply a value for new or updated records. The interface will look much
    better as a result.

  Database IO filters
    Buried within one of the modules in this application are some filters
    which are applied to data of certain types as it enters or leaves the
    database. If you find a particular data type is not being rendered
    correctly, please drop the author a line at the email address below,
    explaining what you'd like to see instead.

  Relocating LFB to another URL path
    If you want to use this application as a plugin with another Catalyst
    system, it should work fine, but you probably want to serve pages under
    a different path on your web site. To do that, add the following to your
    configuration file:

     <Controller::LFB::Root>
         <action>
             <base>
                 PathPart   admin
             </base>
         </action>
     </Controller::LFB::Root>

    In the above example, the path ".../admin/" will contain the LFB
    application, and all generated links in LFB will also make use of that
    path. Remember this is added to the "base" of your Cataylst application
    which, depending on your web server configuration, might also have a
    leading path.

EXAMPLES
    There is an "examples" directory included with this distribution which
    includes the files necessary to set up a small demo application with
    SQLite3.

LIMITATIONS
    Single column primary key
        There's no support for multiple column primary keys
        (composite/compound keys). This has saved a lot of time in
        development because it greatly simplifies the Catalyst and
        DBIx::Class code.

    No two columns in a given table may have the same FK constraint
        If you have two columns which both have foreign key constraints to
        the same table, it's very likely LFB will not work. Again this is a
        simplification which speeded the initial development.

    Minor rendering issue in Safari
        One of the drop-down list boxes has its picker icon a bit wonky. If
        you are a CSS wizard, please take a look and send me a patch with a
        fix!

    For the issues above, if you're desperate that the feature be
    implemented soon, please drop me a line at the address below, because
    you might be able to buy some of my time for the development.

REQUIREMENTS
    *   ExtJS Javascript Library (version 2.2+ recommended), from
        <http://extjs.com>.

    *   Catalyst::Runtime >= 5.70

    *   Catalyst::Model::DBIC::Schema

    *   Catalyst::View::JSON

    *   Catalyst::View::TT

    *   Catalyst::Action::RenderView

    *   Class::C3

SEE ALSO
    CatalystX::CRUD and CatalystX::CRUD:YUI are two distributions which
    allow you to create something similar but with full customization, and
    the ability to add more features. So, you trade effort for flexibility
    and power.

    CatalystX::ListFramework is similar but has no dependency on Javascript
    (though it can use it for fancy auto-complete searches), and it also
    allows you to control which columns are rendered in the display.

ACKNOWLEDGEMENTS
    Without the initial work on "CatalystX::ListFramework" by Andrew Payne
    and Peter Edwards this package would not exist. If you are looking for
    something like this module but without the dependency on Javascript,
    please do check out CatalystX::ListFramework.

AUTHOR
    Oliver Gorwits "<oliver.gorwits@oucs.ox.ac.uk>"

COPYRIGHT & LICENSE
    Bundled images are Copyright (c) 2006 Mark James, and are from
    <http://www.famfamfam.com/lab/icons/silk/>.

    This distribution ships with the Ext.ux.form.DateTime Extension Class
    for Ext 2.x Library, Copyright (c) 2008, Ing. Jozef Sakalos, and
    released under the LGPL 3.0 license (library version 289, 2008-06-12
    21:08:08).

    The rest is Copyright (c) Oliver Gorwits 2008.

    This library is free software; you can redistribute it and/or modify it
    under the same terms as Perl itself.

