[Jifty-commit] r4473 - in apps/spensive: . lib lib/Spensive lib/Spensive/Action lib/Spensive/View

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Tue Nov 20 12:09:35 EST 2007


Author: jesse
Date: Tue Nov 20 12:09:34 2007
New Revision: 4473

Added:
   apps/spensive/lib/
   apps/spensive/lib/Spensive/
   apps/spensive/lib/Spensive/Action/
   apps/spensive/lib/Spensive/Dispatcher.pm
   apps/spensive/lib/Spensive/Model/
   apps/spensive/lib/Spensive/Model/Attachment.pm
   apps/spensive/lib/Spensive/Model/Expense.pm
   apps/spensive/lib/Spensive/Model/ExpenseReport.pm
   apps/spensive/lib/Spensive/Model/Organization.pm
   apps/spensive/lib/Spensive/Model/OrganizationMember.pm
   apps/spensive/lib/Spensive/Model/SubmissionAddress.pm
   apps/spensive/lib/Spensive/Model/Team.pm
   apps/spensive/lib/Spensive/Model/TeamMember.pm
   apps/spensive/lib/Spensive/Model/User.pm
   apps/spensive/lib/Spensive/Record.pm
   apps/spensive/lib/Spensive/View/
   apps/spensive/lib/Spensive/View.pm
   apps/spensive/lib/Spensive/View/CRUD.pm
   apps/spensive/lib/Spensive/View/Expenses.pm
   apps/spensive/lib/Spensive/View/string.pm
   apps/spensive/lib/Spensive/View/translation.pm
Modified:
   apps/spensive/   (props changed)

Log:
 r53651 at pinglin (orig r6179):  jesse | 2007-03-19 22:20:11 -0400
 


Added: apps/spensive/lib/Spensive/Dispatcher.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Dispatcher.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,8 @@
+package Spensive::Dispatcher;
+use Jifty::Dispatcher -base;
+
+
+use strict;
+use warnings;
+
+1;

Added: apps/spensive/lib/Spensive/Model/Attachment.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/Attachment.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,14 @@
+use strict;
+use warnings;
+
+package Spensive::Model::Attachment;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/Expense.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/Expense.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,25 @@
+use strict;
+use warnings;
+
+package Spensive::Model::Expense;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+    
+    column title => type is 'text';
+    column description => type is 'text';
+    column date_incurred => type is 'datetime';
+    column date_claimed => type is 'datetime';
+    column tags => type is 'text';
+    column expense_report=> references Spensive::Model::ExpenseReport;
+    column local_cost => type is 'float';
+    column cost => type is 'float';
+    column payment_currency => type is 'text', valid_values are qw(USD CAD UKP EUR TWD NZD HKD);
+    column payment_method => type is 'text', valid_values are qw(personal_credit corporate_credit cash);
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/ExpenseReport.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/ExpenseReport.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,23 @@
+use strict;
+use warnings;
+
+package Spensive::Model::ExpenseReport;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+    column title => type is 'text';
+    column description => type is 'text';
+    column expenses_by => references Spensive::Model::User;
+    column submitted => type is 'datetime';
+    column approved => type is 'datetime';
+    column status => type is 'text', valid are qw(unsubmitted approved denied);
+    column approver => type is 'text';
+    column submit_to => type is 'text';
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/Organization.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/Organization.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+package Spensive::Model::Organization;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+    column name => type is 'text';
+    column description => type is 'text';
+
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/OrganizationMember.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/OrganizationMember.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+package Spensive::Model::OrganizationMember;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+    column organization => references Spensive::Model::Organization;
+    column person => references Spensive::Model::User;
+    column access_level => valid are qw(admin user);
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/SubmissionAddress.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/SubmissionAddress.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,14 @@
+use strict;
+use warnings;
+
+package Spensive::Model::SubmissionAddress;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/Team.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/Team.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,18 @@
+use strict;
+use warnings;
+
+package Spensive::Model::Team;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+    column name => type is 'text', since is '0.0.3';
+    
+    column description => type is 'text', since is '0.0.3';
+    column organization => references Spensive::Model::Organization, since is '0.0.3';
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/TeamMember.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/TeamMember.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,17 @@
+use strict;
+use warnings;
+
+package Spensive::Model::TeamMember;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+    column team => references Spensive::Model::Team;
+    column person => references Spensive::Model::User;
+
+};
+
+# Your model-specific methods go here.
+
+1;
+

Added: apps/spensive/lib/Spensive/Model/User.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Model/User.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,22 @@
+use strict;
+use warnings;
+
+package Spensive::Model::User;
+use Jifty::DBI::Schema;
+
+use Spensive::Record schema {
+
+
+    column url => type is 'text';
+    column accepted_eula => type is 'boolean';
+
+};
+
+use Jifty::Plugin::User::Mixin::Model::User;
+use Jifty::Plugin::Authentication::Password::Mixin::Model::User;
+
+# Your model-specific methods go here.
+
+sub current_user_can {1}
+1;
+

Added: apps/spensive/lib/Spensive/Record.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/Record.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,6 @@
+package Spensive::Record;
+use base qw/Jifty::Record/;
+
+sub current_user_can { 1}
+
+1;

Added: apps/spensive/lib/Spensive/View.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/View.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,24 @@
+use warnings;
+use strict;
+package Spensive::View;
+use Jifty::View::Declare -base;
+
+
+template 'index.html' => page {
+
+    h1 { _('Spensive helps you keep track of your expenses') };
+    h2 { _('(It also helps you get reimbursed for them)') };
+
+    my $search = Spensive::Model::ExpenseCollection->new();
+    $search->unlimit();
+    with( page => 1, search_collection => $search, id => 'xxx'), 
+    render_region ( name=> 'myregion', path => '/expenses/list');
+
+};
+
+
+require Spensive::View::Expenses;
+import_templates Spensive::View::Expenses under '/expenses/';
+
+
+1;

Added: apps/spensive/lib/Spensive/View/CRUD.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/View/CRUD.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,289 @@
+package Spensive::View::CRUD;
+use warnings;
+use strict;
+use Jifty::View::Declare -base;
+
+sub object_type {
+    get('object_type');
+}
+
+sub fragment_for {
+    return "/CRUD/$_[1]";
+}
+
+sub get_record {
+    my ($self, $id) = @_;
+
+    my $record_class = Jifty->app_class("Model", $self->object_type);
+    my $record = $record_class->new();
+    $record->load($id);
+
+    return $record;
+}
+
+template 'view' => sub {
+    my $self = shift;
+    my ( $object_type, $id ) = ( $self->object_type, get('id') );
+    my $update = new_action(
+        class => 'Update' . $object_type,
+        moniker => "update-" . Jifty->web->serial,
+        record  => $self->get_record( $id )
+    );
+
+    div {{ class is 'CRUD read item inline' };
+        outs(
+            Jifty->web->link(
+                label   => "Edit",
+                class   => "editlink",
+                onclick => {
+                    replace_with => $self->fragment_for('update'),
+                    args         => { object_type => $object_type, id => $id }
+                },
+            )
+        );
+
+        my @fields = grep {
+            !( m/_confirm/
+                || lc $update->arguments->{$_}{render_as} eq
+                'password' )
+            } $update->argument_names;
+        render_action( $update, \@fields,
+            { render_mode => 'read' } );
+	hr {};
+    };
+
+};
+
+template 'update' => sub {
+    my $self = shift;
+    my ( $object_type, $id ) = ($self->object_type, get('id'));
+
+    my $record_class = Jifty->app_class( "Model", $object_type );
+    my $record = $record_class->new();
+    $record->load($id);
+    my $update = new_action(
+        class   => "Update" . $object_type,
+        moniker => "update-" . Jifty->web->serial,
+        record  => $record
+    );
+
+    div {{ class is "CRUD update item inline " . $object_type }
+
+        div {{ class is 'CRUD editlink' };
+            outs(
+                Jifty->web->link(
+                    label   => "Save",
+                    onclick => [
+                        { submit => $update },
+                        {   replace_with => $self->fragment_for('view'),
+                            args => { object_type => $object_type, id => $id }
+                        }
+                    ]
+                )
+            );
+            outs(
+                Jifty->web->link(
+                    label   => "Cancel",
+                    onclick => {
+                        replace_with => $self->fragment_for('view'),
+                        args => { object_type => $object_type, id => $id }
+                    },
+                    as_button => 1
+                )
+            );
+        };
+
+        $self->render_action( $update );
+        hr {};
+    }
+};
+
+template 'list' => sub {
+    my ( $page, $new_slot, $item_path, $search_collection )
+        = get(qw(page new_slot id search_collection));
+
+    # XXX: wrong
+    $item_path ||= "/CRUD/view";
+    $new_slot  ||= 1;
+
+    my $object_type = 'Expense';#get('object_type');
+
+    my $collection_class
+        = Jifty->app_class( "Model", $object_type . "Collection" );
+    my $search = $search_collection || Jifty->web->response->result('search');
+    my $collection;
+    if ($search) {
+        $collection = $search->content('search');
+    } else {
+        $collection = $collection_class->new();
+        $collection->unlimit();
+    }
+
+    $collection->set_page_info(
+        current_page => $page,
+        per_page     => 25
+    );
+    my $search_region = Jifty::Web::PageRegion->new(
+        name => 'search',
+        path => '/__jifty/empty',
+    );
+
+    outs(
+        Jifty->web->link(
+            onclick => [
+                {   region       => $search_region->qualified_name,
+                    replace_with => '/CRUD/search',
+                    toggle       => 1,
+                    args         => { object_type => $object_type }
+                },
+            ],
+            label => 'Toggle search'
+        )
+    );
+
+    outs( $search_region->render );
+
+    if ( $collection->pager->last_page > 1 ) {
+        span {
+            { class is 'page-count' };
+            outs(
+                _( "Page %1 of %2", $page, $collection->pager->last_page ) );
+            }
+    }
+
+    if ( $collection->pager->total_entries == 0 ) {
+        outs( _("No items found") );
+    }
+
+    div {
+        { class is 'list' };
+        while ( my $item = $collection->next ) {
+            outs(
+                Jifty->web->region(
+                    name     => 'item-' . $item->id,
+                    path     => $item_path,
+                    defaults =>
+                        { id => $item->id, object_type => $object_type }
+                )
+            );
+        }
+    };
+
+    div {
+        { class is 'paging' };
+        if ( $collection->pager->previous_page ) {
+            span {
+                { class is 'prev-page' };
+                outs(
+                    Jifty->web->link(
+                        label   => "Previous Page",
+                        onclick => {
+                            args =>
+                                { page => $collection->pager->previous_page }
+                        }
+                    )
+                );
+                }
+        }
+        if ( $collection->pager->next_page ) {
+            span {
+                { class is 'next-page' };
+                outs(
+                    Jifty->web->link(
+                        label   => "Next Page",
+                        onclick => {
+                            args => { page => $collection->pager->next_page }
+                        }
+                    )
+                );
+                }
+        }
+    };
+
+    if ($new_slot) {
+        outs(
+            Jifty->web->region(
+                name     => 'new_item',
+                path     => "/CRUD/new_item",
+                defaults => { object_type => $object_type },
+            )
+        );
+    }
+};
+
+
+template 'new_item' => sub {
+    my ( $object_type, $id ) = ($self->object_type, get('id'));
+
+    my $record_class = Jifty->app_class("Model", $object_type);
+    my $create = Jifty->web->new_action(class => 'Create'.$object_type);
+
+    div {{ class is 'crud create item inline' };
+        $self->render_action( $create );
+
+        outs(
+            Jifty->web->form->submit(
+                label   => 'Create',
+                onclick => [
+                    { submit       => $create },
+                    { refresh_self => 1 },
+                    {   element => undef,#$region->parent->get_element('div.list'),
+                        append  => $self->fragment_for('view'),
+                        args    => {
+                            object_type => $object_type,
+                            id => { result_of => $create, name => 'id' },
+                        },
+                    },
+                ]
+            )
+        );
+    }
+};
+
+# render tabview using yui.
+
+# if a tab ends in _tab, it means it should contain a stub region to
+# be replaced by the corresponding fragment onclick to that tab.
+
+sub render_tabs {
+    my ($self, $divname, $args, @tabs) = @_;
+
+    outs_raw(qq'<script type="text/javascript">
+	var myTabs = new YAHOO.widget.TabView("$divname");
+	</script>'  );
+
+
+    div { { id is $divname, class is 'yui-navset'}
+	  ul { { class is 'yui-nav'};
+	       my $i = 0;
+	       for (@tabs) {
+		   my $tab = $_;
+		   li { { class is 'selected' unless $i };
+			hyperlink(url => '#tab'.++$i, label => $tab,
+				  $tab =~ s/_tab$// ? 
+				  (onclick =>
+				  { region       => Jifty->web->current_region->qualified_name."-$tab-tab",
+				    replace_with => $self->fragment_for($tab),
+				    args => { map { $_ => get($_)} @$args },
+				  }) : ()
+				 ) }
+	       }
+	   };
+	  div { {class is 'yui-content' };
+		for (@tabs) {
+		    div { 
+			if (s/_tab$//) {
+			    render_region(name => $_.'-tab');
+			}
+			else {
+			    die $_ unless $self->has_template($_);
+			    $self->has_template($_)->(); 
+			}
+		    }
+		}
+	    }
+      };
+};
+
+1;
+

Added: apps/spensive/lib/Spensive/View/Expenses.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/View/Expenses.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,110 @@
+package Spensive::View::Expenses;
+use strict;
+use warnings;
+use Jifty::View::Declare -base;
+use base 'Spensive::View::CRUD';
+use Template::Declare::Tags;
+use Jifty::Plugin::Yullio::View;
+
+sub object_type { 'Expense' }
+
+sub fragment_for {
+    return object_type()."/$_[1]";
+}
+
+template 'hi' => sub { h1 { 'hi'}};
+
+template 'index.html' => page {
+    my $self = shift;
+    #my $lang = get('lang');
+    #my $organization = __PACKAGE__->get_record( get('organization') );
+    #set( id => $organization->id );
+    with ( width => 'doc', column_template => 'yui-t4' ),
+    yullio {
+        #h1 { $organization->team->name . ' ' . $organization->name };
+#	render_region( name => 'available_languages', path => __PACKAGE__->fragment_for('available_languages'));
+#	render_region( name => 'strings' );
+    } sub { }
+};
+
+template available_languages => sub {
+    my $self = shift;
+    my $lang = get('lang');
+    my $organization = __PACKAGE__->get_record( get('id') );
+    ul {
+	for my $lang ( @{ $organization->available_languages } ) {
+	    li { $self->lang_percentage($organization, $lang);
+		 span { hyperlink( url        => "/translate/untranslated.html",
+			    parameters => { lang => $lang, organization => $organization->id },
+			    label      => $lang,
+			    onclick => { region => 'strings',
+					replace_with => '/organization/viewlang',
+					args => { lang => $lang, id => get('id') } }) }
+		 span { hyperlink( url        => "/organization/download_po",
+			    parameters => { lang => $lang, organization => $organization->id },
+			    label      => 'Download PO' ) };
+	    }
+	}
+    };
+
+
+};
+
+
+
+template new_language_form => sub {
+    my $newlang = new_action(
+        class     => 'NewLanguage',
+        moniker   => "newlanguage-" . Jifty->web->serial,
+        arguments => { organization => get('id') }
+    );
+    Jifty->web->form->start;
+    render_action( $newlang );
+    form_submit( label => 'Create',
+		 onclick => [ {submit => $newlang,
+			       refresh => 'available_languages',
+			       args => { id => get('id')} } ]);
+    Jifty->web->form->end;
+};
+
+template viewlang => sub {
+    my $self = shift;
+    my ( $lang, $id ) = ( get('lang'), get('id') );
+    my $p = $self->get_record( $id );
+    h1 { _('Translating %1 pacakge %2 for %2', $p->team->name, $p->name, $lang) };
+
+    $self->render_tabs('organization-'.$lang, [qw(id lang)], qw( untranslated translated_tab ) );
+};
+
+template translated => sub {
+    my $self = shift;
+    my $p = $self->get_record( get('id') );
+    die unless get('lang');
+    my $strings = $p->translated(get('lang'));
+    div { { id is 'translated-list' };
+	  $self->render_record_collection($strings, 'translated');
+      };
+};
+
+template untranslated => sub {
+    my $self = shift;
+    my $p = $self->get_record( get('id') );
+    my $strings = $p->untranslated(get('lang'));
+    div { { id is 'untranslated-list' };
+	  $self->render_record_collection($strings, 'untranslated');
+      };
+};
+
+sub render_record_collection {
+    my ($self, $strings, $name) = @_;
+    h1 { _('%1 entries', $strings->count) };
+    my $page = get('page');
+    $strings->set_page_info( per_page => 10, current_page => $page );
+    while (my $string = $strings->next) {
+	render_region(name => $name.'-'.$string->id,
+		      force_path=>__PACKAGE__->fragment_for('list'),
+		      force_arguments => { id => $string->id});
+    }
+};
+
+1;

Added: apps/spensive/lib/Spensive/View/string.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/View/string.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,66 @@
+package BabelBee::View::string;
+use strict;
+use Jifty::View::Declare -base;
+use base 'BabelBee::View::cruddy';
+use Template::Declare::Tags;
+
+sub object_type { 'String' }
+
+sub fragment_for {
+    return "/string/$_[1]";
+}
+
+template myview => sub {
+    my $self = shift;
+    $self->render_tabs('string-myview-'.get('id'), ['id', 'lang'], qw(view translate related_tab));
+};
+
+template 'view' => sub {
+    my $self = shift;
+    my ( $object_type, $id ) = ( $self->object_type, get('id') );
+    my $update = new_action(
+        class   => 'Update' . $object_type,
+        moniker => "update-" . Jifty->web->serial,
+        record  => $self->get_record( $id )
+    );
+    render_action( $update,
+        [ 'msgid', 'po_reference' ],
+        { render_mode => 'read' }
+    );
+};
+
+template 'translate' => sub {
+    my $self = shift;
+    my ( $object_type, $id, $lang )
+        = ( $self->object_type, get( 'id', 'lang' ) );
+    return if $self->get_record($id)->translation_for($lang);
+    my $translate = new_action(
+        class     => 'CreateTranslation',
+        moniker   => "translate-new-" . Jifty->web->serial,
+        arguments => { lang => $lang, string => $id }
+    );
+
+    Jifty->web->form->start;
+    render_action( $translate, ['msgstr', 'po_comment', 'lang', 'string'] );
+    form_submit( label => 'Save', onclick => [ {submit => $translate, replace_with => '/__jifty/empty', region => 'translation-view-'.$id}]  );
+    Jifty->web->form->end;
+};
+
+template 'related' => sub {
+    my $self = shift;
+    my ( $object_type, $id, $lang )
+        = ( $self->object_type, get( 'id', 'lang' ) );
+    my $string = $self->get_record($id);
+    my $similar = $string->package->strings_similar_to($lang, $string->msgid);
+    $similar->set_page_info( per_page => 10, current_page => 1);
+    ul {
+	while (my $string = $similar->next) {
+	    li { outs($string->msgid);
+		 div {{class is 'translated'}; $string->translation_for($lang)->msgstr };
+	     };
+	}
+    }
+
+};
+
+1;

Added: apps/spensive/lib/Spensive/View/translation.pm
==============================================================================
--- (empty file)
+++ apps/spensive/lib/Spensive/View/translation.pm	Tue Nov 20 12:09:34 2007
@@ -0,0 +1,13 @@
+package BabelBee::View::translation;
+use strict;
+use base 'BabelBee::View::cruddy';
+
+sub object_type { 'Translation' }
+
+sub fragment_for {
+    return "/translation/$_[1]";
+}
+
+
+1;
+


More information about the Jifty-commit mailing list