[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