[Jifty-commit] r4484 - in apps/spensive: . etc lib/Spensive lib/Spensive/View share/web/static/css share/web/static/images t

jifty-commit at lists.jifty.org jifty-commit at lists.jifty.org
Tue Nov 20 12:10:43 EST 2007


Author: jesse
Date: Tue Nov 20 12:10:41 2007
New Revision: 4484

Added:
   apps/spensive/share/web/static/css/base.css
   apps/spensive/share/web/static/css/expensereport.css
   apps/spensive/share/web/static/images/
   apps/spensive/share/web/static/images/logo.png   (contents, props changed)
Modified:
   apps/spensive/   (props changed)
   apps/spensive/etc/config.yml
   apps/spensive/lib/Spensive/Dispatcher.pm
   apps/spensive/lib/Spensive/Model/Email.pm
   apps/spensive/lib/Spensive/Model/EmailAttachment.pm
   apps/spensive/lib/Spensive/Model/Expense.pm
   apps/spensive/lib/Spensive/Model/ExpenseReport.pm
   apps/spensive/lib/Spensive/View.pm
   apps/spensive/lib/Spensive/View/Expenses.pm
   apps/spensive/lib/Spensive/View/Reports.pm
   apps/spensive/share/web/static/css/app.css
   apps/spensive/share/web/static/css/main.css
   apps/spensive/share/web/static/css/nav.css
   apps/spensive/t/00-model-Expense.t
   apps/spensive/t/mailbox

Log:
 r67314 at pinglin (orig r7324):  jesse | 2007-09-14 14:40:59 -0400
 * basic expense report view


Modified: apps/spensive/etc/config.yml
==============================================================================
--- apps/spensive/etc/config.yml	(original)
+++ apps/spensive/etc/config.yml	Tue Nov 20 12:10:41 2007
@@ -13,7 +13,7 @@
     Password: ''
     RecordBaseClass: Jifty::DBI::Record::Cachable
     User: ''
-    Version: 0.0.3
+    Version: 0.0.5
   DevelMode: 0
   L10N: 
     PoDir: share/po
@@ -27,7 +27,9 @@
         - REST: {}
         - LetMe: {}
         - User: {}
-        - Feedback: {}
+        - Feedback:
+            from: spensive-feedback at spensive.fsck.com
+            to: sarohapri at my.hiveminder.com
         - CompressedCSSandJS:
             css: 0
             js: 1

Modified: apps/spensive/lib/Spensive/Dispatcher.pm
==============================================================================
--- apps/spensive/lib/Spensive/Dispatcher.pm	(original)
+++ apps/spensive/lib/Spensive/Dispatcher.pm	Tue Nov 20 12:10:41 2007
@@ -6,7 +6,7 @@
 use warnings;
 
 
-before qr'^/(?!(?:login|static|signup|__jifty))' => run {
+before qr'^/(?!(?:login|static|feedback|signup|__jifty))' => run {
     unless ( Jifty->web->current_user->id ) {
         Jifty->web->tangent( url => '/login' );
     }
@@ -22,12 +22,13 @@
 }
 };
 
-on qr'/report/(\d+)/build' => run {
+on qr'/report/(\d+)/' => run {
     my $report = Spensive::Model::ExpenseReport->new();
     $report->load($1);
     set( report => $report );
-    show 'report/build';
-    };
+};
+
+on qr'/report/(\d+)/(build|show)' => run { show 'report/'.$2; };
 
 # Change a password
 on '/prefs' => run {
@@ -38,4 +39,20 @@
         request => Jifty::Request->new( path => "/" ) );
 
 };
-1;
+on '/expense/#' => run {
+    my $id = $1;
+    my $expense = Spensive::Model::Expense->new();
+    $expense->load($id);
+    set 'expense' => $expense;
+    show '/expenses/show_details';
+
+}; 
+
+on '/attachment/view/#' => run {
+    my $id = $1;
+    my $attach = Spensive::Model::EmailAttachment->new();
+    $attach->load($id);
+    set attachment => $attach;
+    show '/attachment/image';
+};
+    1;

Modified: apps/spensive/lib/Spensive/Model/Email.pm
==============================================================================
--- apps/spensive/lib/Spensive/Model/Email.pm	(original)
+++ apps/spensive/lib/Spensive/Model/Email.pm	Tue Nov 20 12:10:41 2007
@@ -28,24 +28,24 @@
 
     my $mime = Email::MIME->new($self->__value('message'));
 
-    $self->_create_subparts($mime);
+    $self->_create_subparts(mime_obj => $mime);
 
 }
 
 sub _create_subparts {
-    my $self = shift;
-    my $top_part = shift;
-    my @subparts = $top_part->subparts;
+    my $self       = shift;
+    my %args       = ( mime_obj => undef, parent_attachment_obj => undef, @_ );
+    my $attachment = Spensive::Model::EmailAttachment->new();
+    $attachment->create( mime_obj => $args{'mime_obj'}, parent => $args{'parent_attachment_obj'}, email => $self->id );
+    
+    
+    my @subparts = $args{'mime_obj'}->subparts;
     if (@subparts) {
-        foreach my $part (@subparts) {
-            $self->_create_subparts($part);
+        foreach my $child_part (@subparts) {
+            $self->_create_subparts( mime_obj => $child_part, parent_attachment_obj => $attachment);
         }
-    } else {
-        my $attachment = Spensive::Model::EmailAttachment->new();
-        $attachment->create(mime_obj => $top_part);
     }
 
-
 }
 
 1;

Modified: apps/spensive/lib/Spensive/Model/EmailAttachment.pm
==============================================================================
--- apps/spensive/lib/Spensive/Model/EmailAttachment.pm	(original)
+++ apps/spensive/lib/Spensive/Model/EmailAttachment.pm	Tue Nov 20 12:10:41 2007
@@ -5,9 +5,11 @@
 use Jifty::DBI::Schema;
 
 use Spensive::Record schema {
+    column parent => references Spensive::Model::EmailAttachment;
     column content_type => type is 'text';
     column filename => type is 'text';
     column content => type is 'blob';
+    column email => references Spensive::Model::Email;
 };
 
 # Your model-specific methods go here.
@@ -17,10 +19,14 @@
     my $args = shift;
     my $mime_obj = delete $args->{'mime_obj'};
 
+    warn "My PARENT IS " .$args->{parent};
 
+    warn "Creating ". $mime_obj->content_type;
     $args->{content_type} = $mime_obj->content_type;
     $args->{filename} =$mime_obj->filename;
     $args->{content} = $mime_obj->body;
+
+    return 1;
 }
 
 

Modified: apps/spensive/lib/Spensive/Model/Expense.pm
==============================================================================
--- apps/spensive/lib/Spensive/Model/Expense.pm	(original)
+++ apps/spensive/lib/Spensive/Model/Expense.pm	Tue Nov 20 12:10:41 2007
@@ -13,6 +13,8 @@
     column tags => type is 'text';
     column local_cost => type is 'float';
     column cost => type is 'float';
+    column category => type is 'text', valid_values are qw(airfare hotel travel communication meals entertainment other), since '0.0.5';
+
     column payment_currency => type is 'text', valid_values are qw(USD CAD UKP EUR TWD NZD HKD), default is 'USD';
     #column payment_method => type is 'text', valid_values are qw(personal_credit corporate_credit cash);
     column expense_report=> references Spensive::Model::ExpenseReport;
@@ -33,7 +35,6 @@
 sub after_create {
     my $self = shift;
       my $insert_return_value_ref = shift;
-
       return unless $$insert_return_value_ref;    # bail if insert failed
       $self->load($$insert_return_value_ref);     # load ourselves from db
     
@@ -41,6 +42,7 @@
     my $e = Spensive::Model::Email->new();
     $e->create( message => $self->{'_email_content'}, expense => $self->id);
     }
+    return 1;
 }
 
 sub autocomplete_title {

Modified: apps/spensive/lib/Spensive/Model/ExpenseReport.pm
==============================================================================
--- apps/spensive/lib/Spensive/Model/ExpenseReport.pm	(original)
+++ apps/spensive/lib/Spensive/Model/ExpenseReport.pm	Tue Nov 20 12:10:41 2007
@@ -16,7 +16,8 @@
 
 # Your model-specific methods go here.
 
-# Your model-specific methods go here.
+
+sub categories { @{Spensive::Model::Expense->new()->column('category')->valid_values()} }
 
 sub before_create {
     my $self = shift;
@@ -35,5 +36,28 @@
     return 1;
 }
 
+sub expenses {
+    my $self = shift;
+    my %args = ( category => undef, @_ );
+    my $expenses = Spensive::Model::ExpenseCollection->new();
+    $expenses->limit(
+        column => 'incurred_by',
+        value  => Jifty->web->current_user->id
+    );
+    $expenses->limit(
+        column   => 'expense_report',
+        operator => '=',
+        value    => $self->id
+    );
+    if ( $args{'category'} ) {
+
+        $expenses->limit(
+            column   => 'category',
+            operator => '=',
+            value    => $args{'category'}
+        );
+    }
+    return $expenses;
+}
 1;
 

Modified: apps/spensive/lib/Spensive/View.pm
==============================================================================
--- apps/spensive/lib/Spensive/View.pm	(original)
+++ apps/spensive/lib/Spensive/View.pm	Tue Nov 20 12:10:41 2007
@@ -3,6 +3,7 @@
 package Spensive::View;
 use Jifty::View::Declare -base;
 
+use List::Util;
 
 template 'index.html' => page {
 
@@ -61,6 +62,58 @@
 
 use Jifty::Plugin::TabView::View;
 
+
+template 'report/show' => page {
+    my $report = get('report');
+    h1 { $report->title };
+
+    my %category_totals = ();
+    my %category_items = ();
+    foreach my $cat ( $report->categories ) {
+        my $expenses = $report->expenses( category => $cat );
+        div { { class is 'expense-category'};
+        h2 {$cat};
+
+        while ( my $expense = $expenses->next ) {
+            div  { { class is 'expense-entry'};
+            for (qw(date_incurred title description cost)) {
+                span { {class is 'expense-'.$_};  $expense->$_() };
+            }
+            };
+            $category_totals{$cat} += $expense->cost;
+            push @{$category_items{$cat}},$expense;
+        }
+
+        if ($category_items{$cat}->[0]) {
+
+
+        div {
+            { class is 'subtotal' };
+            span { { class is 'label' }; _('Subtotal: '); };
+            outs( $category_totals{$cat});
+
+            };
+        } else {
+        div { {class is 'subtotal-empty'};
+            outs("Nothing to report"); 
+        }
+    }
+    }
+}
+    div {
+        h2 { 'Totals' };
+
+        { class is 'total' };
+        span {
+            { class is 'label' };
+            _('Total');
+        };
+        outs( List::Util::sum (values %category_totals) );
+    };
+
+};
+
+
 template 'report/build' => page {
            my $self = shift;
     h1 { get('report')->title };
@@ -148,4 +201,15 @@
     outs_raw($action->button( label => 'Remove', onclick=> [{submit => $action, }, { delete => Jifty->web->current_region}] ));
 }
 };
+
+template 'attachment/image' => sub {
+    my $item = get('attachment');
+     Jifty->handler->apache->content_type($item->content_type);
+    outs_raw($item->content);
+
+};
+
+
+private template app_page_footer => sub { show '/feedback/request_feedback'; };
+
 1;

Modified: apps/spensive/lib/Spensive/View/Expenses.pm
==============================================================================
--- apps/spensive/lib/Spensive/View/Expenses.pm	(original)
+++ apps/spensive/lib/Spensive/View/Expenses.pm	Tue Nov 20 12:10:41 2007
@@ -9,9 +9,28 @@
 
 sub object_type { 'Expense' }
  
-sub display_columns { return (qw(title cost date_incurred description)); };
+sub display_columns { return (qw(title cost date_incurred category description)); };
 
 private template search_region => sub {};
 
 
+template show_details => page {
+    my $expense = get('expense');
+
+    my $collateral = Spensive::Model::EmailAttachmentCollection->new();
+    my $email_alias = $collateral->join( alias1 => 'main', column1 => 'email', table2 => 'emails', column2 => 'id');
+
+    my $expenses =$collateral->join(alias1 => $email_alias, column1 => 'expense', table2 => 'expenses', column2 => 'id');
+    $collateral->limit(alias => $expenses, column => 'id', value => $expense->id);
+
+    while (my $item = $collateral->next) {
+    
+        if ($item->content_type =~ /^image/i) {
+            img { { src is '/attachment/view/'.$item->id} };
+        } elsif ($item->content_type eq 'text/plain' || $item->content eq 'message/rfc822' ) {
+            div { $item->content };
+        }
+    }
+};
+
 1;

Modified: apps/spensive/lib/Spensive/View/Reports.pm
==============================================================================
--- apps/spensive/lib/Spensive/View/Reports.pm	(original)
+++ apps/spensive/lib/Spensive/View/Reports.pm	Tue Nov 20 12:10:41 2007
@@ -4,7 +4,6 @@
 use Jifty::View::Declare -base;
 use base 'Jifty::View::Declare::CRUD';
 
-sub fragment_base_path {'/reports'}
 sub object_type { 'ExpenseReport' }
 
 private template search_region => sub {};

Modified: apps/spensive/share/web/static/css/app.css
==============================================================================
--- apps/spensive/share/web/static/css/app.css	(original)
+++ apps/spensive/share/web/static/css/app.css	Tue Nov 20 12:10:41 2007
@@ -10,27 +10,35 @@
 background-color: white;
 
 margin-left: 10em;
-margin-right: 10em;
+margin-right: 17em;
 
 padding: 2em;
-border-top: 1px solid #333;
+border-top: 1px solid #ccc;
 
-border-left: 1px solid #333;
-border-right: 2px solid #ccc;
-border-bottom: 3px solid #ccc;
+border-left: 1px solid #ccc;
+border-right: 2px solid #999;
+border-bottom: 3px solid #999;
 
 
 }
 
-ul.menu {
-list-style: none;
-border: 0;
-background-color: #fff;
 
-}
+#feedback_wrapper {
 
-ul.menu li {
-background-color: #fff;
-color: #000;
+ border-top: 1px solid #ccc;
 
+ position: absolute;
+ margin-top: 1em;
+ right: 0.5em;
+ width: 210px;
+ 
+ font-size: 0.8em;
+ 
+ top: 8em;
 }
+
+#feedback_wrapper textarea {
+ font-size: 1em;
+ font-family:  arial, sans-serif; 
+width: 17em;
+}
\ No newline at end of file

Added: apps/spensive/share/web/static/css/base.css
==============================================================================
--- (empty file)
+++ apps/spensive/share/web/static/css/base.css	Tue Nov 20 12:10:41 2007
@@ -0,0 +1,89 @@
+body {
+}
+
+body.calpopup {
+}
+
+.error {
+    color: #a00000;
+}
+
+.warning {
+    color: #00a0a0;
+}
+
+.canonicalization_note {
+    color: #009966;
+}
+
+hr {
+    clear: both;
+} 
+
+.messages .message {
+    display: block;
+}
+
+div#messages,  div#errors {
+     background-color: rgb(240,234,183);
+     border: 1px solid rgb(230,224,173);
+     margin-top: 10px;
+     margin-bottom: 10px;
+     padding: 5px;
+     font-size: 1.2em;
+
+}
+
+div.spacer {
+    clear: both;
+}
+
+.next-page, .prev-page {
+    display: block;
+    float: left;
+    margin: 0.5em 0;
+    padding: 0.2em 0.5em 0.5em 0.5em;
+    border-top: 1px solid gray;
+}
+
+.next-page { padding-right: 1em; }
+.prev-page { padding-left: 1em; }
+
+div#jifty-wait-message {
+    color: black;
+    background: #ccc;
+    font-size: 2em;
+    position: fixed;;
+    top: 10px;
+    left: 1em;  padding: 0.5em;
+    z-index: 42;
+    float: right;
+}
+
+
+
+div.warning {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ right: 0;
+
+ background-color: red;
+ color: white;
+ padding: .5em;
+ border-bottom: 1px solid #000;
+}
+
+div.warning a {
+ color: white;
+
+}
+
+ul.menu {
+  display: block;
+
+}
+
+h1.title {
+  border-bottom: 1px solid black;
+}

Added: apps/spensive/share/web/static/css/expensereport.css
==============================================================================
--- (empty file)
+++ apps/spensive/share/web/static/css/expensereport.css	Tue Nov 20 12:10:41 2007
@@ -0,0 +1,23 @@
+
+.expense-category h2 {
+
+ width:100%;
+ border-bottom: 1px solid black;
+
+}
+
+.expense-entry {
+ width: 100%;
+}
+.expense-entry .expense-cost {
+   border: 1px solid red;
+   font-weight: bold;
+   right:0;
+
+}
+
+.expense-category .subtotal {
+ 
+text-align: right;
+font-weight: bold;
+

Modified: apps/spensive/share/web/static/css/main.css
==============================================================================
--- apps/spensive/share/web/static/css/main.css	(original)
+++ apps/spensive/share/web/static/css/main.css	Tue Nov 20 12:10:41 2007
@@ -15,3 +15,4 @@
 @import "yui/tabview/tabs.css";
 @import "yui/tabview/tabview.css";
 @import "notices.css";
+ at import "expensereport.css";

Modified: apps/spensive/share/web/static/css/nav.css
==============================================================================
--- apps/spensive/share/web/static/css/nav.css	(original)
+++ apps/spensive/share/web/static/css/nav.css	Tue Nov 20 12:10:41 2007
@@ -1,8 +1,13 @@
 #salutation {
- position: absolute;
-left: 1em;
-top: 4em;
+ background: url(/static/images/logo.png) no-repeat;
 
+ padding-top: 6em;
+ position: absolute;
+ right: 0.5em;
+ top: 0.7em;
+ width: 210px;
+ padding-left: 1em;
+ font-size: 0.8em;
 }
 
 #navigation {
@@ -10,18 +15,23 @@
 margin: 0;
 padding: 0;
 position: absolute;
+width: 9.7em;
+
 left: 1em;
-top: 5em;
+top: 1em;
 }
 
 ul.menu {
  padding: 0;
+list-style: none;
+border: 0;
 
 
 }
 
 ul.menu a {
 
+
  text-decoration: none;
  font-weight: bold;
  color: #000;
@@ -29,37 +39,23 @@
 
 }
 
-
-ul.menu {
-list-style: none;
-border: 0;
-
-}
-
 ul.menu li {
- color: #000;
  border-bottom: 1px solid #ccc;
   padding-bottom: 0.5em;
   padding-top: 0.5em;
   padding-left: 1em;
   padding-right: 1em;
 
+  border-left: 1px solid #ccc;
 }
 
 
 ul.menu li.active { background-color: #fff}
 
-ul.menu li:hover { background-color: #ddd}
+ul.menu li:hover { background-color: #fff; padding-left: 1.1em; }
 
 
-ul.menu li:first-child  { border-top: 1px solid #ccc;}
-
-ul.menu a {
 
-}
-
-
-ul.menu li {
+ul.menu li:first-child  { border-top: 1px solid #ccc;}
 
 
-}
\ No newline at end of file

Added: apps/spensive/share/web/static/images/logo.png
==============================================================================
Binary file. No diff available.

Modified: apps/spensive/t/00-model-Expense.t
==============================================================================
--- apps/spensive/t/00-model-Expense.t	(original)
+++ apps/spensive/t/00-model-Expense.t	Tue Nov 20 12:10:41 2007
@@ -1,6 +1,7 @@
 #!/usr/bin/env perl
 use warnings;
 use strict;
+use File::Slurp;
 
 =head1 DESCRIPTION
 
@@ -13,37 +14,22 @@
 # Make sure we can load the model
 use_ok('Spensive::Model::Expense');
 
+my $msg = read_file('t/mime.msg');
+
 # Grab a system user
 my $system_user = Spensive::CurrentUser->superuser;
 ok($system_user, "Found a system user");
 
+
+my $u = Spensive::Model::User->new(current_user => $system_user);
+my ($val,$ret) = $u->create( email => 'jesse at example.com', name => 'Test jesse', password => 'secret');
+ok($val,$ret);
+$u->set_email_confirmed('1');
+
 # Try testing a create
-my $o = Spensive::Model::Expense->new(current_user => $system_user);
-my ($id) = $o->create();
-ok($id, "Expense create returned success");
+my $o = Spensive::Model::Expense->new(current_user => Spensive::CurrentUser->new(email => 'jesse at example.com'));
+my ($id, $emsg) = $o->create(email_content => $msg, title => 'hi!');
+ok($id, "Expense create returned success - ".$emsg);
 ok($o->id, "New Expense has valid id set");
 is($o->id, $id, "Create returned the right id");
 
-# And another
-$o->create();
-ok($o->id, "Expense create returned another value");
-isnt($o->id, $id, "And it is different from the previous one");
-
-# Searches in general
-my $collection =  Spensive::Model::ExpenseCollection->new(current_user => $system_user);
-$collection->unlimit;
-is($collection->count, 2, "Finds two records");
-
-# Searches in specific
-$collection->limit(column => 'id', value => $o->id);
-is($collection->count, 1, "Finds one record with specific id");
-
-# Delete one of them
-$o->delete;
-$collection->redo_search;
-is($collection->count, 0, "Deleted row is gone");
-
-# And the other one is still there
-$collection->unlimit;
-is($collection->count, 1, "Still one left");
-

Modified: apps/spensive/t/mailbox
==============================================================================
--- apps/spensive/t/mailbox	(original)
+++ apps/spensive/t/mailbox	Tue Nov 20 12:10:41 2007
@@ -0,0 +1,16 @@
+From   Wed Sep 12 21:46:07 2007
+From: Spensive <>
+To: jesse at example.com
+Subject: Welcome to Spensive!
+Date: Wed, 12 Sep 2007 21:46:07 -0400
+MIME-Version: 1.0
+Content-Type: text/plain; charset="UTF-8"
+Content-Transfer-Encoding: 8bit
+
+
+You're getting this message because you (or somebody claiming to be you)
+wants to use Spensive. 
+
+We need to make sure that we got your email address right.  Click on the link below to get started:
+
+http://localhost:10567/let/jesse%40example.com/confirm_email/801a9f0db162ae78


More information about the Jifty-commit mailing list