[Bps-public-commit] SD - A distributed issue tracker branch, master, updated. 52350309dde15490d97e52282fefcc68525c5266

jesse jesse at bestpractical.com
Fri Feb 6 01:06:11 EST 2009


The branch, master has been updated
       via  52350309dde15490d97e52282fefcc68525c5266 (commit)
       via  61730bf74296d1e554d1881fc532185281551d76 (commit)
       via  a4462565e214dff4b861addeeea0f4dd0d6be29c (commit)
       via  b07aaa888e94a195d0c867a34ae5361963de4953 (commit)
       via  7336314a1a99297e389eb694cc8fbe4652f5b739 (commit)
       via  e9c8b00e8ef32c2ffb5901a4b089ebf8b09d651b (commit)
       via  65925c18b5d4aa5b5f3e4d4de405af11875c76ea (commit)
      from  bd87dc370c5f8608a6381af6619d81630056190c (commit)

Summary of changes:
 lib/App/SD/CLI/Command/Ticket/Show.pm  |   14 ++-
 lib/App/SD/Replica/trac.pm             |    6 +
 lib/App/SD/Replica/trac/PullEncoder.pm |  264 +++++++++++++++++---------------
 lib/App/SD/Server/Dispatcher.pm        |    4 +-
 lib/App/SD/Server/View.pm              |   78 +++++++---
 5 files changed, 223 insertions(+), 143 deletions(-)

- Log -----------------------------------------------------------------
commit 65925c18b5d4aa5b5f3e4d4de405af11875c76ea
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Thu Feb 5 21:01:06 2009 -0500

    removing dead code

diff --git a/lib/App/SD/Replica/trac/PullEncoder.pm b/lib/App/SD/Replica/trac/PullEncoder.pm
index a6a41e1..97baf05 100644
--- a/lib/App/SD/Replica/trac/PullEncoder.pm
+++ b/lib/App/SD/Replica/trac/PullEncoder.pm
@@ -137,7 +137,6 @@ sub skip_previously_seen_transactions {
     return \@txns;
 }
 
-
 sub build_initial_ticket_state {
     my $self          = shift;
     my $final_state   = shift;
@@ -157,7 +156,6 @@ sub build_initial_ticket_state {
     return \%initial_state;
 }
 
-
 sub build_create_changeset {
     my $self = shift;
     my $create_data = shift;
@@ -243,49 +241,6 @@ sub _recode_attachment_create {
     $args{'changeset'}->add_change( { change => $change } );
 }
 
-use HTTP::Date;
-
-sub unix_time_to_iso {
-    my $self = shift;
-    my $date = shift;
-
-    return undef if $date eq 'Not set';
-    return HTTP::Date::time2iso($date);
-}
-
-our %PROP_MAP = (
-    subject         => 'summary',
-    status          => 'status',
-    owner           => 'owner',
-    initialpriority => '_delete',
-    finalpriority   => '_delete',
-    told            => '_delete',
-    requestor       => 'reporter',
-    requestors      => 'reporter',
-    cc              => 'cc',
-    ccs             => 'cc',
-    admincc         => 'admin_cc',
-    adminccs        => 'admin_cc',
-    refersto        => 'refers_to',
-    referredtoby    => 'referred_to_by',
-    dependson       => 'depends_on',
-    dependedonby    => 'depended_on_by',
-    hasmember       => 'members',
-    memberof        => 'member_of',
-    priority        => 'priority_integer',
-    resolved        => 'completed',
-    due             => 'due',
-    creator         => 'creator',
-    timeworked      => 'time_worked',
-    timeleft        => 'time_left',
-    timeestimated   => 'time_estimated',
-    lastupdated     => '_delete',
-    created         => 'created',
-    queue           => 'queue',
-    starts          => '_delete',
-    started         => '_delete',
-);
-
 sub translate_status {
     my $self = shift;
     my $status = shift;

commit e9c8b00e8ef32c2ffb5901a4b089ebf8b09d651b
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Thu Feb 5 21:34:00 2009 -0500

    Content of comments gets into the SD replica of a trac db

diff --git a/lib/App/SD/Replica/trac.pm b/lib/App/SD/Replica/trac.pm
index e48e553..4fd2ce3 100644
--- a/lib/App/SD/Replica/trac.pm
+++ b/lib/App/SD/Replica/trac.pm
@@ -85,6 +85,12 @@ sub uuid {
 }
 
 
+sub remote_uri_path_for_comment {
+    my $self = shift;
+    my $id = shift;
+    return "/comment/".$id;
+}
+
 sub remote_uri_path_for_id {
     my $self = shift;
     my $id = shift;
diff --git a/lib/App/SD/Replica/trac/PullEncoder.pm b/lib/App/SD/Replica/trac/PullEncoder.pm
index 97baf05..eb6838b 100644
--- a/lib/App/SD/Replica/trac/PullEncoder.pm
+++ b/lib/App/SD/Replica/trac/PullEncoder.pm
@@ -6,9 +6,10 @@ use Params::Validate qw(:all);
 use Memoize;
 use Time::Progress;
 
-has sync_source => 
-    ( isa => 'App::SD::Replica::trac',
-      is => 'rw');
+has sync_source => (
+    isa => 'App::SD::Replica::trac',
+    is  => 'rw'
+);
 
 sub run {
     my $self = shift;
@@ -36,67 +37,75 @@ sub run {
     for my $ticket (@tickets) {
         $counter++;
         print $progress->report( "%30b %p Est: %E\r", $counter );
-        $self->sync_source->log( "Fetching ticket @{[$ticket->id]} - $counter of " . scalar @tickets );
+        $self->sync_source->log(
+            "Fetching ticket @{[$ticket->id]} - $counter of " . scalar @tickets );
 
-    
         $tickets->{ $ticket->id } = $ticket;
     }
 
     my @changesets;
 
-  
-
     foreach my $ticket ( values %$tickets ) {
-        my $ticket_data = $self->_translate_final_ticket_state($ticket); 
+        my $ticket_data = $self->_translate_final_ticket_state($ticket);
+
         #my $ticket_initial_data = $self->build_initial_ticket_state($ticket_data, $ticket);
         my $ticket_initial_data = {%$ticket_data};
-        my $txns = $self->skip_previously_seen_transactions( ticket => $ticket, transactions => $ticket->history->entries);
+        my $txns                = $self->skip_previously_seen_transactions(
+            ticket       => $ticket,
+            transactions => $ticket->history->entries
+        );
+
         # Walk transactions newest to oldest.
-        for my $txn ( sort { $b->date <=> $a->date } @$txns) { 
-            $self->sync_source->log($ticket->id." - Transcoding transaction  @{[$txn->date]} ");
+        for my $txn ( sort { $b->date <=> $a->date } @$txns ) {
+            $self->sync_source->log( $ticket->id . " - Transcoding transaction  @{[$txn->date]} " );
             my $changeset = $self->transcode_one_txn( $txn, $ticket_initial_data );
-            $changeset->created( $txn->date->ymd." ". $txn->date->hms );
+            $changeset->created( $txn->date->ymd . " " . $txn->date->hms );
             next unless $changeset->has_changes;
+
             # the changeset is older than the one that came before it, so it goes first
             unshift @changesets, $changeset;
             $counter++;
         }
+
         # create is oldest of all
-        unshift @changesets, $self->build_create_changeset($ticket_initial_data, $ticket);
+        unshift @changesets, $self->build_create_changeset( $ticket_initial_data, $ticket );
     }
 
     my $cs_counter = 1;
-    for  my $changeset (@changesets) {
-        $changeset->original_sequence_no($cs_counter++);
-        $self->sync_source->log( "Applying changeset " . $changeset->original_sequence_no . " of " . scalar @changesets );
+    for my $changeset (@changesets) {
+        $changeset->original_sequence_no( $cs_counter++ );
+        $self->sync_source->log( "Applying changeset "
+                . $changeset->original_sequence_no . " of "
+                . scalar @changesets );
         $args{callback}->($changeset);
     }
 }
 
 sub _translate_final_ticket_state {
-    my $self   = shift;
+    my $self          = shift;
     my $ticket_object = shift;
 
     my $ticket_data = {
 
         $self->sync_source->uuid . '-id' => $ticket_object->id,
 
-        owner       => ($ticket_object->owner ||''),
-        created     => ($ticket_object->created->ymd . " " . $ticket_object->created->hms),
-        reporter    => ($ticket_object->reporter ||''),
+        owner => ( $ticket_object->owner || '' ),
+        created     => ( $ticket_object->created->ymd . " " . $ticket_object->created->hms ),
+        reporter    => ( $ticket_object->reporter || '' ),
         status      => $self->translate_status( $ticket_object->status ),
-        summary     => ($ticket_object->summary||''),
-        description => ($ticket_object->description ||''),
+        summary     => ( $ticket_object->summary || '' ),
+        description => ( $ticket_object->description || '' ),
         tags        => ( $ticket_object->keywords || '' ),
-        component   => ($ticket_object->component ||''),
-        milestone   => ($ticket_object->milestone ||''),
-        priority    => ($ticket_object->priority || ''),
-        severity    => ($ticket_object->severity ||''),
-        cc          => ($ticket_object->cc || ''),
+        component   => ( $ticket_object->component || '' ),
+        milestone   => ( $ticket_object->milestone || '' ),
+        priority    => ( $ticket_object->priority || '' ),
+        severity    => ( $ticket_object->severity || '' ),
+        cc          => ( $ticket_object->cc || '' ),
     };
 
     # delete undefined and empty fields
-    delete $ticket_data->{$_} for grep !defined $ticket_data->{$_} || $ticket_data->{$_} eq '', keys %$ticket_data;
+    delete $ticket_data->{$_}
+        for grep !defined $ticket_data->{$_} || $ticket_data->{$_} eq '', keys %$ticket_data;
 
     return $ticket_data;
 }
@@ -108,9 +117,10 @@ Returns a Trac::TicketSearch collection for all tickets found matching your QUER
 =cut
 
 sub find_matching_tickets {
-    my $self   = shift;
-    my %query  = (@_);
-    my $search = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 50 );
+    my $self  = shift;
+    my %query = (@_);
+    my $search
+        = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 20 );
     $search->query(%query);
     return $search->results;
 }
@@ -126,10 +136,11 @@ sub skip_previously_seen_transactions {
     my %args = validate( @_, { ticket => 1, transactions => 1 } );
     my @txns;
 
-    for my $txn ( sort @{$args{transactions}}) {
+    for my $txn ( sort @{ $args{transactions} } ) {
+
         # Skip things we know we've already pulled
-        #next if $txn < $args{'starting_transaction'}; 
-        
+        #next if $txn < $args{'starting_transaction'};
+
         # Skip things we've pushed
         #next if $self->sync_source->foreign_transaction_originated_locally($txn, $args{'ticket'});
         push @txns, $txn;
@@ -147,7 +158,12 @@ sub build_initial_ticket_state {
     for my $txn ( reverse @{ $ticket_object->history->entries } ) {
         for my $pc ( values %{ $txn->prop_changes } ) {
             unless ( $initial_state{ $pc->property } eq $pc->new_value ) {
-                warn "I was expecting " . $pc->property . " to be " . $pc->new_value . " but it was actually " . $initial_state{ $pc->property };
+                warn "I was expecting "
+                    . $pc->property
+                    . " to be "
+                    . $pc->new_value
+                    . " but it was actually "
+                    . $initial_state{ $pc->property };
             }
             $initial_state{ $pc->property } = $pc->old_value;
 
@@ -157,69 +173,89 @@ sub build_initial_ticket_state {
 }
 
 sub build_create_changeset {
-    my $self = shift;
+    my $self        = shift;
     my $create_data = shift;
-    my $ticket = shift;
-    warn "My ticket id is ".$ticket->id;
+    my $ticket      = shift;
+    warn "My ticket id is " . $ticket->id;
     my $changeset = Prophet::ChangeSet->new(
-        {   original_source_uuid =>  $self->sync_source->uuid_for_remote_id( $ticket->id),
+        {   original_source_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id ),
+
             #original_sequence_no => 1, # XXX TODO THIS IS JNOT A VALID SEQUENCE NUMBER
-            creator              => $self->resolve_user_id_to( email_address => $ticket->reporter),
+            creator => $self->resolve_user_id_to( email_address => $ticket->reporter ),
         }
     );
 
-
     my $change = Prophet::Change->new(
         {   record_type => 'ticket',
-            record_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id), 
+            record_uuid => $self->sync_source->uuid_for_remote_id( $ticket->id ),
             change_type => 'add_file'
         }
     );
 
-    for my $prop (keys %$create_data) {
+    for my $prop ( keys %$create_data ) {
         next unless defined $create_data->{$prop};
-        $change->add_prop_change(name => $prop, old => '', new => $create_data->{$prop});
+        $change->add_prop_change( name => $prop, old => '', new => $create_data->{$prop} );
     }
 
-    $changeset->add_change({change => $change});
+    $changeset->add_change( { change => $change } );
     return $changeset;
 }
 
-
-
 sub transcode_one_txn {
     my ( $self, $txn, $ticket, $txn_number ) = (@_);
     my $changeset = Prophet::ChangeSet->new(
-        {   original_source_uuid => $self->sync_source->uuid_for_remote_id( $ticket->{$self->sync_source->uuid . '-id' } ),
-            #        original_sequence_no => $txn_number, #XXX TODO THIS IS NOT A VALID SEQUENCE NUMBER
-            creator              => $self->resolve_user_id_to( email_address => $txn->author),
+        {   original_source_uuid => $self->sync_source->uuid_for_remote_id(
+                $ticket->{ $self->sync_source->uuid . '-id' }
+            ),
+
+         #        original_sequence_no => $txn_number, #XXX TODO THIS IS NOT A VALID SEQUENCE NUMBER
+            creator => $self->resolve_user_id_to( email_address => $txn->author ),
         }
     );
 
     my $change = Prophet::Change->new(
         {   record_type => 'ticket',
-            record_uuid => $self->sync_source->uuid_for_remote_id( $ticket->{$self->sync_source->uuid . '-id' } ),
+            record_uuid => $self->sync_source->uuid_for_remote_id(
+                $ticket->{ $self->sync_source->uuid . '-id' }
+            ),
             change_type => 'update_file'
         }
     );
 
-    foreach my $prop_change ( values %{$txn->prop_changes||{}}) {
-        my $new = $prop_change->new_value;
-        my $old = $prop_change->old_value;
-        my $property = $prop_change->property; 
+    foreach my $prop_change ( values %{ $txn->prop_changes || {} } ) {
+        my $new      = $prop_change->new_value;
+        my $old      = $prop_change->old_value;
+        my $property = $prop_change->property;
 
-        $old = undef if ($old eq '');
-        $new = undef if ($new eq '');
+        $old = undef if ( $old eq '' );
+        $new = undef if ( $new eq '' );
 
         # walk back $ticket's state
-        if ((!defined $new && !defined $ticket->{$property}) || ( defined $new && defined $ticket->{$property} && $ticket->{$property} eq $new)) { $ticket->{$property} = $old }; 
+        if (   ( !defined $new && !defined $ticket->{$property} )
+            || ( defined $new && defined $ticket->{$property} && $ticket->{$property} eq $new ) )
+        {
+            $ticket->{$property} = $old;
+        }
 
-        $change->add_prop_change(name => $property, old => $old, new => $new);
+        $change->add_prop_change( name => $property, old => $old, new => $new );
 
     }
 
-    $changeset->add_change({change =>$change});
+    $changeset->add_change( { change => $change } );
+
+    my $comment = Prophet::Change->new(
+        {   record_type => 'comment',
+            record_uuid => Data::UUID->new->create_str(),
+            change_type => 'add_file'
+        });
+
+    $comment->add_prop_change( name => 'content', new => $txn->content );
+    $comment->add_prop_change(
+        name => 'ticket',
+        new => $self->sync_source->uuid_for_remote_id( $ticket->{ $self->sync_source->uuid . '-id' } )
+    );
 
+    $changeset->add_change({change => $comment});
     return $changeset;
 }
 
@@ -228,27 +264,52 @@ sub _recode_attachment_create {
     my %args   = validate( @_, { ticket => 1, txn => 1, changeset => 1, attachment => 1 } );
     my $change = Prophet::Change->new(
         {   record_type => 'attachment',
-            record_uuid => $self->sync_source->uuid_for_url( $self->sync_source->remote_url . "/attachment/" . $args{'attachment'}->{'id'} ),
+            record_uuid => $self->sync_source->uuid_for_url(
+                $self->sync_source->remote_url . "/attachment/" . $args{'attachment'}->{'id'}
+            ),
             change_type => 'add_file'
         }
     );
-    $change->add_prop_change( name => 'content_type', old  => undef, new  => $args{'attachment'}->{'ContentType'});
-    $change->add_prop_change( name => 'created', old  => undef, new  => $args{'txn'}->{'Created'} );
-    $change->add_prop_change( name => 'creator', old  => undef, new  => $self->resolve_user_id_to( email_address => $args{'attachment'}->{'Creator'}));
-    $change->add_prop_change( name => 'content', old  => undef, new  => $args{'attachment'}->{'Content'});
-    $change->add_prop_change( name => 'name', old  => undef, new  => $args{'attachment'}->{'Filename'});
-    $change->add_prop_change( name => 'ticket', old  => undef, new  => $self->sync_source->uuid_for_remote_id( $args{'ticket'}->{ $self->sync_source->uuid . '-id'} ));
+    $change->add_prop_change(
+        name => 'content_type',
+        old  => undef,
+        new  => $args{'attachment'}->{'ContentType'}
+    );
+    $change->add_prop_change( name => 'created', old => undef, new => $args{'txn'}->{'Created'} );
+    $change->add_prop_change(
+        name => 'creator',
+        old  => undef,
+        new  => $self->resolve_user_id_to( email_address => $args{'attachment'}->{'Creator'} )
+    );
+    $change->add_prop_change(
+        name => 'content',
+        old  => undef,
+        new  => $args{'attachment'}->{'Content'}
+    );
+    $change->add_prop_change(
+        name => 'name',
+        old  => undef,
+        new  => $args{'attachment'}->{'Filename'}
+    );
+    $change->add_prop_change(
+        name => 'ticket',
+        old  => undef,
+        new  => $self->sync_source->uuid_for_remote_id(
+            $args{'ticket'}->{ $self->sync_source->uuid . '-id' }
+        )
+    );
     $args{'changeset'}->add_change( { change => $change } );
 }
 
 sub translate_status {
-    my $self = shift;
+    my $self   = shift;
     my $status = shift;
 
     $status =~ s/^resolved$/closed/;
     return $status;
 }
 
+my %PROP_MAP;
 sub translate_prop_names {
     my $self      = shift;
     my $changeset = shift;
@@ -260,11 +321,12 @@ sub translate_prop_names {
         for my $prop ( $change->prop_changes ) {
             next if ( ( $PROP_MAP{ lc( $prop->name ) } || '' ) eq '_delete' );
             $prop->name( $PROP_MAP{ lc( $prop->name ) } ) if $PROP_MAP{ lc( $prop->name ) };
+
             # Normalize away undef -> "" and vice-versa
             for (qw/new_value old_value/) {
-                $prop->$_("") if !defined ($prop->$_());
-                }
-            next if ( $prop->old_value eq $prop->new_value);
+                $prop->$_("") if !defined( $prop->$_() );
+            }
+            next if ( $prop->old_value eq $prop->new_value );
 
             if ( $prop->name =~ /^cf-(.*)$/ ) {
                 $prop->name( 'custom-' . $1 );
@@ -281,13 +343,12 @@ sub translate_prop_names {
 
 sub resolve_user_id_to {
     my $self = shift;
-    my $to = shift;
-    my $id = shift;
-    return $id.'@trac-instance.local';
+    my $to   = shift;
+    my $id   = shift;
+    return $id . '@trac-instance.local';
 
 }
 
-
 __PACKAGE__->meta->make_immutable;
 no Moose;
 1;

commit 7336314a1a99297e389eb694cc8fbe4652f5b739
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Thu Feb 5 23:52:25 2009 -0500

    Encode comment content as html. Display it correctly

diff --git a/lib/App/SD/CLI/Command/Ticket/Show.pm b/lib/App/SD/CLI/Command/Ticket/Show.pm
index 35a3652..d2ff83d 100644
--- a/lib/App/SD/CLI/Command/Ticket/Show.pm
+++ b/lib/App/SD/CLI/Command/Ticket/Show.pm
@@ -38,9 +38,21 @@ override run => sub {
         for my $comment (@comments) {
             my $creator = $comment->prop('creator');
             my $created = $comment->prop('created');
+            my $content_type = $comment->prop('content_type') ||'text/plain';
+
             my $content = $comment->prop('content') || '';
+            if ($content_type =~ m{text/html}i ){
+
+                $content =~ s|</?b\s*>|*|gismx;
+                $content =~ s|</?i\s*>|_|gismx;
+                $content =~ s|<a(?:.*?)href="(.*?)".*?>(.*?)</a.*?>|$2 [link: $1 ]|gismx;
+                $content =~ s|<.*?>||gismx;
+            }
+
             print "$creator: " if $creator;
-            print "$created\n$content\n\n";
+            print "$created\n";
+            print $content;
+            print "\n\n";
         }
     }
 
diff --git a/lib/App/SD/Replica/trac/PullEncoder.pm b/lib/App/SD/Replica/trac/PullEncoder.pm
index eb6838b..85fe4e6 100644
--- a/lib/App/SD/Replica/trac/PullEncoder.pm
+++ b/lib/App/SD/Replica/trac/PullEncoder.pm
@@ -120,7 +120,7 @@ sub find_matching_tickets {
     my $self  = shift;
     my %query = (@_);
     my $search
-        = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 20 );
+        = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 10 );
     $search->query(%query);
     return $search->results;
 }
@@ -241,7 +241,7 @@ sub transcode_one_txn {
 
     }
 
-    $changeset->add_change( { change => $change } );
+    $changeset->add_change( { change => $change } ) if $change->has_prop_changes;
 
     my $comment = Prophet::Change->new(
         {   record_type => 'comment',
@@ -249,7 +249,12 @@ sub transcode_one_txn {
             change_type => 'add_file'
         });
 
-    $comment->add_prop_change( name => 'content', new => $txn->content );
+    my $content = $txn->content;
+
+    $comment->add_prop_change( name => 'created', new  => $txn->date->ymd. ' ' .$txn->date->hms);
+    $comment->add_prop_change( name => 'creator', new  => $self->resolve_user_id_to( email_address => $txn->author) );
+    $comment->add_prop_change( name => 'content', new => $content );
+    $comment->add_prop_change( name => 'content_type', new => 'text/html' );
     $comment->add_prop_change(
         name => 'ticket',
         new => $self->sync_source->uuid_for_remote_id( $ticket->{ $self->sync_source->uuid . '-id' } )

commit b07aaa888e94a195d0c867a34ae5361963de4953
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Feb 6 00:29:30 2009 -0500

    Added HTML view of ticket comments that started as html; added description and tags fields for trac compat

diff --git a/lib/App/SD/Server/View.pm b/lib/App/SD/Server/View.pm
index d2e7656..260eea2 100644
--- a/lib/App/SD/Server/View.pm
+++ b/lib/App/SD/Server/View.pm
@@ -12,7 +12,7 @@ use App::SD::Model::Comment;
 use App::SD::Collection::Ticket;
 
 
-my @BASIC_PROPS = qw(status milestone component owner reporter due created);
+my @BASIC_PROPS = qw(status milestone component owner reporter due created tags description);
 
 
 template '/css/sd.css' => sub {
@@ -312,11 +312,22 @@ div.widget.status, div.widget.component, div.widget.milestone {
     width: 29%;
 }
 
+div.widget.description {
+    display: block;
+    height: auto;
+}
+
+div.widget.description textarea {
+    width: 100%;
+    font-size: 0.8em;
+    height: 6em;
+}
+
 div.widget.status {
     margin-left: 1em;
 }
 
-div.widget.status label, div.widget.component label, div.widget.milestone label
+div.widget.status label, div.widget.component label, div.widget.milestone label, div.widget.description label
 {
 display: block;
 text-align: left;
@@ -336,6 +347,7 @@ div.widget.milestone .value {
 width: 100%;
 
 }
+/* 
 
 .other-props { 
     margin-top: 0;
@@ -354,6 +366,7 @@ width: 100%;
 .other-props .widget input {
     width: 13em;
 }
+*/
 
 ul.page-nav {
     position: absolute;
@@ -503,12 +516,16 @@ ul.comments .creator:after {
     content: " wrote:";
 }
 
-ul.comments li .content {
-    margin-top: 1em;
+ul.comments li .content-pre {
     white-space: pre;
+    overflow-x: auto;
+}
+
+ul.comments li .content {
     padding: 1em;
+    margin-top: 1em;
     font-size: 0.9em;
-    overflow-x: auto;
+
 }
 
 ul.comments li:nth-child(odd) {
@@ -710,12 +727,16 @@ template edit_ticket => page {
     
         div { class is 'other-props';
         for my $prop (@BASIC_PROPS) {
-            next if $prop =~ /^(?:status|component|milestone|created)$/;
+            next if $prop =~ /^(?:status|component|milestone|created|description)$/;
 
             div { { class is "widget $prop"}; 
                     widget( function => $f, prop => $prop ) };
         }
-        }
+        }; 
+
+            div { { class is "widget description"}; 
+                    widget( function => $f, prop => 'description', type => 'textarea', autocomplete => 0) };
+
         };
         div { class is 'submit';
         input { attr { value => 'Save', type => 'submit' } };
@@ -778,10 +799,14 @@ template new_ticket => page {'Create a new ticket'} content {
         div { class is 'other-props';
 
         for my $prop (@BASIC_PROPS) {
-            next if $prop =~ /^(?:status|component|milestone|created)$/;
+            next if $prop =~ /^(?:status|component|milestone|created|description)$/;
             div { {class is 'widget '.$prop};
                  widget( function => $f, prop => $prop ) };
         }
+
+            div { {class is 'widget description'};
+                 widget( function => $f, prop => 'description', type => 'textarea', autocomplete => '0' ) };
+
         }
         };
 
@@ -997,20 +1022,19 @@ private template 'ticket_basics' => sub {
             div { { class is 'value uuid'}; $ticket->uuid; } 
             };
         for my $key (qw'status component milestone', 
-                        @BASIC_PROPS, (sort keys %props)) {
+                        (grep {$_ ne 'description'} (@BASIC_PROPS, (sort keys %props))), 'description') {
             next unless defined $props{$key}; 
-            next if ($key eq 'summary');
+            next if ($key =~ m{(?:summary)});
             next if ($key =~ /.{8}-.{4}-.{4}-.{12}-id/);
             div { class is 'widget '.$key;
                 label {$key};
                 div { { class is 'value ' . $key }; $props{$key}; }
-            };
 
+            };
             delete $props{$key};
-
-        }
+        
         };
-
+    };
     script { outs_raw('$("div.created,div.due").prettyDateTag();
 setInterval(function(){ $("div.created,div.due").prettyDateTag(); }, 5000);') };
 
@@ -1055,25 +1079,33 @@ template ticket_comments => sub {
     my @comments = sort  @{ $ticket->comments };
     if (@comments) {
         h2 { { class is 'conmments'};  'Comments'};
-        ul { { class is 'comments'}; 
+        ul {
+            { class is 'comments' };
             for my $comment (@comments) {
                 li {
                     span {
                         { class is 'metadata' };
                         span { class is 'created'; $comment->prop('created') };
-                         outs(" ");
-                        span { class is 'creator';  $comment->prop('creator')};
+                        outs(" ");
+                        span { class is 'creator'; $comment->prop('creator') };
                     }
                     div {
                         class is 'content';
-                        $comment->prop('content') || i {'No body was entered for this comment'};
-                    };
+                        if ( !$comment->prop('content') ) {
+                            i {'No body was entered for this comment'};
+
+                        } elsif ( $comment->prop('content_type') =~ m{text/html}i ) {
+                            outs_raw( $comment->prop('content') );
+                        } else {
+                            div { class is 'content-pre';     $comment->prop('content');};
+                        }
+                    }
                 }
             }
         }
-    }
     script { outs_raw('$("span.created").prettyDateTag();
 setInterval(function(){ $("span.created").prettyDateTag(); }, 5000);') };
+    }
 
 };
 

commit a4462565e214dff4b861addeeea0f4dd0d6be29c
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Feb 6 01:01:27 2009 -0500

    Add an 'all tickets' list to the webui

diff --git a/lib/App/SD/Server/Dispatcher.pm b/lib/App/SD/Server/Dispatcher.pm
index b036892..5568eb0 100644
--- a/lib/App/SD/Server/Dispatcher.pm
+++ b/lib/App/SD/Server/Dispatcher.pm
@@ -41,6 +41,7 @@ on qr'.' => sub {
     }
     $components->child('None' => label => 'None', url => '/no_component');
 
+    $tickets->child( all => label => 'All' => url => '/tickets/all');
     $self->server->nav->child( create => label => 'New ticket', url => '/ticket/new') unless($self->server->static);
     $self->server->nav->child( home => label => 'Home', url => '/');
 
@@ -63,7 +64,8 @@ under 'GET' => sub {
         my $type = $2;
         shift->show_template( $name => $type );
     };
-
+    
+    on qr'^tickets/all$' => sub {shift->show_template('all_tickets')};
     under 'ticket' => sub {
         on '' => sub {
             my $self = shift;
diff --git a/lib/App/SD/Server/View.pm b/lib/App/SD/Server/View.pm
index 260eea2..5250333 100644
--- a/lib/App/SD/Server/View.pm
+++ b/lib/App/SD/Server/View.pm
@@ -611,6 +611,10 @@ content {
 
 };
 
+template 'all_tickets' => page {'All tickets'} content {
+   shift->show_tickets( sub {1});
+};
+
 template 'milestones' => page {'Project milestones'} content {
     show 'milestone_list';
 };
@@ -919,7 +923,7 @@ private template 'ticket_list' => sub {
             for my $ticket (@$tickets) {
                 row {
                     cell { class is 'id'; ticket_link( $ticket => $ticket->luid ); };
-                    for (@BASIC_PROPS) {
+                    for (qw|status milestone component order reporter due created|) {
                     
                         cell { class is $_; $ticket->prop($_) };
                     }

commit 61730bf74296d1e554d1881fc532185281551d76
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Feb 6 01:02:00 2009 -0500

    When pulling from trac, date the ticket creation correctly and don't include blank comments

diff --git a/lib/App/SD/Replica/trac/PullEncoder.pm b/lib/App/SD/Replica/trac/PullEncoder.pm
index 85fe4e6..667e974 100644
--- a/lib/App/SD/Replica/trac/PullEncoder.pm
+++ b/lib/App/SD/Replica/trac/PullEncoder.pm
@@ -120,7 +120,7 @@ sub find_matching_tickets {
     my $self  = shift;
     my %query = (@_);
     my $search
-        = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 10 );
+        = Net::Trac::TicketSearch->new( connection => $self->sync_source->trac, limit => 50 );
     $search->query(%query);
     return $search->results;
 }
@@ -182,6 +182,7 @@ sub build_create_changeset {
 
             #original_sequence_no => 1, # XXX TODO THIS IS JNOT A VALID SEQUENCE NUMBER
             creator => $self->resolve_user_id_to( email_address => $ticket->reporter ),
+            created => $ticket->created->ymd ." ".$ticket->created->hms
         }
     );
 
@@ -249,8 +250,8 @@ sub transcode_one_txn {
             change_type => 'add_file'
         });
 
-    my $content = $txn->content;
-
+    if (my $content = $txn->content ) {
+        if ($content !~ /^\s*$/s) {
     $comment->add_prop_change( name => 'created', new  => $txn->date->ymd. ' ' .$txn->date->hms);
     $comment->add_prop_change( name => 'creator', new  => $self->resolve_user_id_to( email_address => $txn->author) );
     $comment->add_prop_change( name => 'content', new => $content );
@@ -261,6 +262,8 @@ sub transcode_one_txn {
     );
 
     $changeset->add_change({change => $comment});
+    }
+    }
     return $changeset;
 }
 

commit 52350309dde15490d97e52282fefcc68525c5266
Merge: 61730bf... bd87dc3...
Author: Jesse Vincent <jesse at bestpractical.com>
Date:   Fri Feb 6 01:06:05 2009 -0500

    Merge branch 'master' of code.bestpractical.com:/git/sd


-----------------------------------------------------------------------



More information about the Bps-public-commit mailing list