[Bps-public-commit] r17160 - in sd/trunk/lib/App/SD: Server
jesse at bestpractical.com
jesse at bestpractical.com
Tue Dec 9 15:19:27 EST 2008
Author: jesse
Date: Tue Dec 9 15:19:02 2008
New Revision: 17160
Modified:
sd/trunk/lib/App/SD/Model/Ticket.pm
sd/trunk/lib/App/SD/Server/Dispatcher.pm
sd/trunk/lib/App/SD/Server/View.pm
Log:
* more of a pass at a webui. some code cleanup in Model::Ticket
Modified: sd/trunk/lib/App/SD/Model/Ticket.pm
==============================================================================
--- sd/trunk/lib/App/SD/Model/Ticket.pm (original)
+++ sd/trunk/lib/App/SD/Model/Ticket.pm Tue Dec 9 15:19:02 2008
@@ -7,6 +7,11 @@
use constant collection_class => 'App::SD::Collection::Ticket';
has type => ( default => 'ticket');
+__PACKAGE__->register_reference( comments => 'App::SD::Collection::Comment', by => 'ticket');
+__PACKAGE__->register_reference( attachments => 'App::SD::Collection::Attachment', by => 'ticket');
+
+
+
sub default_prop_milestone {
my $self = shift;
@@ -19,8 +24,6 @@
=cut
-
-
sub default_prop_status {
my $self = shift;
return $self->app_handle->setting(label => 'default_status')->get()->[0];
@@ -87,28 +90,52 @@
sub validate_prop_status {
my ( $self, %args ) = @_;
- return $self->_validate_prop_from_setting('status', 'statuses', \%args);
+ return $self->validate_prop_from_recommended_values( 'status', \%args );
}
-
sub validate_prop_milestone {
my ( $self, %args ) = @_;
+ return $self->validate_prop_from_recommended_values( 'milestone', \%args );
+}
+
+sub validate_prop_from_recommended_values {
+ my $self = shift;
+ my $prop = shift;
+ my $args = shift;
+
+ if ( my @options = $self->recommended_values_for_prop($prop) ) {
+ return 1 if scalar grep { $args->{props}{$prop} eq $_ } @options;
+
+ $args->{errors}{$prop}
+ = "'" . $args->{props}->{$prop} . "' is not a valid $prop";
+ return 0;
+ }
return 1;
- return $self->_validate_prop_from_setting('milestone', 'milestones', \%args);
+
}
-sub _validate_prop_from_setting {
- my ( $self, $prop, $setting, $args ) = @_;
- # XXX: validater not called when a value is unset, so can't do mandatory check here
- return 1 if scalar grep { $args->{props}{$prop} eq $_ }
- @{ $self->app_handle->setting( label => $setting )->get() };
- $args->{errors}{$prop} = "'" . $args->{props}->{$prop} . "' is not a valid $prop";
- return 0;
+
+sub recommended_values_for_prop {
+ my $self = shift;
+ my $prop = shift;
+
+ if (my $code = $self->can("_recommended_values_for_prop_".$prop)) {
+ $code->($self, @_);
+ } else {
+ return undef;
+ }
+
}
+sub _recommended_values_for_prop_milestone {
+ return @{ shift->app_handle->setting( label => 'milestones' )->get() };
+}
+sub _recommended_values_for_prop_status {
+ return @{ shift->app_handle->setting( label => 'statuses' )->get() };
+}
=head2 color_prop_status $value
@@ -193,8 +220,6 @@
return $now > $then;
}
-__PACKAGE__->register_reference( comments => 'App::SD::Collection::Comment', by => 'ticket');
-__PACKAGE__->register_reference( attachments => 'App::SD::Collection::Attachment', by => 'ticket');
__PACKAGE__->meta->make_immutable;
no Moose;
Modified: sd/trunk/lib/App/SD/Server/Dispatcher.pm
==============================================================================
--- sd/trunk/lib/App/SD/Server/Dispatcher.pm (original)
+++ sd/trunk/lib/App/SD/Server/Dispatcher.pm Tue Dec 9 15:19:02 2008
@@ -1,13 +1,18 @@
package App::SD::Server::Dispatcher;
use Prophet::Server::Dispatcher -base;
-on qr'^GET/bug/([\w\d-]+)' => sub {
- my $self = shift;
- warn "my bug is $1";
- $self->show_template('show_bug', $1);
-
+under 'GET' => sub {
+ on qr'^milestone/([\w\d-]+)$' => sub {
+ my $milestone = $1;
+ shift->show_template( 'milestone', $milestone );
+
+ };
+
+ on qr'^issue/([\w\d-]+)' => sub {
+ my $self = shift;
+ $self->show_template( 'show_issue', $1 );
};
-on qr'^GET/(.*)$' => sub {show_template($1)->(@_)};
+};
redispatch_to 'Prophet::Server::Dispatcher';
Modified: sd/trunk/lib/App/SD/Server/View.pm
==============================================================================
--- sd/trunk/lib/App/SD/Server/View.pm (original)
+++ sd/trunk/lib/App/SD/Server/View.pm Tue Dec 9 15:19:02 2008
@@ -27,19 +27,19 @@
font-family: sans-serif;
}
-div.buglist {
+div.issue_list {
border: 1px solid grey;
-moz-border-radius: 0.5em;
-webkit-botder-radius: 0.5em;
}
- div.buglist ul {
+ div.issue_list ul {
list-style-type:none;
}
- div.buglist ul li {
+ div.issue_list ul li {
clear: both;
padding-bottom: 2em;
border-bottom: 1px solid #ccc;
@@ -50,23 +50,23 @@
- div.buglist ul li span {
+ div.issue_list ul li span {
float: left;
padding: 0.2em;
}
-div.buglist ul li span.summary {
+div.issue_list ul li span.summary {
width: 70%;
}
-div.buglist ul li span.bug-link {
+div.issue_list ul li span.issue-link {
width: 2em;
text-align: right;
}
-div.buglist ul li span.status {
+div.issue_list ul li span.status {
width: 3em;
}
@@ -77,36 +77,84 @@
template '/' => page {'SD'}
content {
- p {'sd is a P2P bug tracking system.'};
- show('/bugs/open');
+ p {'sd is a P2P issue tracking system.'};
+ show('milestones');
+ show('/issues/open');
};
-template '/bugs/open' => sub {
+template 'milestones' => sub {
my $self = shift;
- my $bugs = App::SD::Collection::Ticket->new(
+ my $milestones = $self->app_handle->setting( label => 'milestones' )->get();
+
+ div { { class is 'pagesection'};
+ h2 { 'Current milestones' };
+ ul{
+ foreach my $milestone (@$milestones) {
+ li {
+ a {{ href is '/milestone/'.$milestone} $milestone }
+
+ }
+
+ }
+ }
+ }
+
+
+
+
+
+};
+
+template 'milestone' => page { 'Milestone: '.$_[1] } content {
+ my $self = shift;
+ my $milestone = shift;
+
+ h1 { $milestone };
+ h2 { 'Open issues for this milestone' } ;
+
+ $self->show_issues(sub { (shift->prop('milestone')||'') eq $milestone});
+
+ };
+
+sub show_issues {
+ my $self = shift;
+ my $callback = shift;
+
+ my $issues = App::SD::Collection::Ticket->new(
app_handle => $self->app_handle,
handle => $self->app_handle->handle
);
- $bugs->matching( sub { my $item = shift;
-
- return $item->has_active_status ? 1 : 0;
-
- });
- h2 {'Open bugs'};
+ $issues->matching($callback);
+ show( '/issue_list', $issues );
+}
+
+
+
+
+template '/issues/open' => sub {
+ my $self = shift;
+ h2 {'Open issues'};
+
+ $self->show_issues (sub { my $item = shift; return $item->has_active_status ? 1 : 0; });
+
+};
+private template 'issue_list' => sub {
+ my $self = shift;
+ my $issues = shift;
div {
- class is 'buglist';
+ class is 'issue_list';
- for my $bug (@$bugs) {
+ for my $issue (@$issues) {
ul {
li {
- bug_link( $bug => $bug->luid );
- span { class is 'status'; $bug->prop('status') };
- span { class is 'summary'; $bug->prop('summary') };
- span { class is 'created'; $bug->prop('created') };
+ issue_link( $issue => $issue->luid );
+ span { class is 'status'; $issue->prop('status') };
+ span { class is 'summary'; $issue->prop('summary') };
+ span { class is 'created'; $issue->prop('created') };
}
@@ -116,40 +164,111 @@
}
};
-template 'show_bug' => page {
+template 'show_issue' => page {
my $self = shift;
my $id = shift;
- warn "SELF Is $self";
- warn "ID IS $id";
- warn $self->app_handle;
- my $bug = App::SD::Model::Ticket->new(
+ my $issue = App::SD::Model::Ticket->new(
app_handle => $self->app_handle,
handle => $self->app_handle->handle
);
- $bug->load(uuid =>$id);
+ $issue->load(uuid =>$id);
- title is $bug->luid.":".$bug->summary;
+ $issue->luid.":".$issue->prop('summary');
} content {
my $self = shift;
my $id = shift;
- my $bug = App::SD::Model::Ticket->new(
+ my $issue = App::SD::Model::Ticket->new(
app_handle => $self->app_handle,
handle => $self->app_handle->handle
);
- $bug->load(uuid => $id);
- h1 { 'this is a bug' };
- p {$bug->prop('summary')};
+ $issue->load(uuid => $id);
+ h1 { 'this is a issue' };
+ p {$issue->prop('summary')};
+
+ my $props = $issue->get_props;
+ dl { { class is 'issue-props'};
+ for my $key (sort keys %$props) {
+ dt{ $key };
+ dd { $props->{$key}};
+ }
+ };
+
+ show ( 'issue_attachments' => $issue);
+ show ( 'issue_comments' => $issue);
+ show ( 'issue_history' => $issue);
+
};
-sub bug_link {
- my $bug = shift;
+
+sub _by_creation_date { $a->prop('created') cmp $b->prop('created') };
+
+template issue_attachments => sub {
+ my $self = shift;
+ my $issue = shift;
+
+
+};
+template issue_history => sub {
+ my $self = shift;
+ my $issue = shift;
+
+
+ h2 { 'History'};
+
+ ul {
+ for my $changeset (sort {$a->created cmp $b->created} $issue->changesets) {
+ li {
+ ul {
+ li { $changeset->created. " ". $changeset->creator };
+ li { $changeset->original_sequence_no. ' @ ' . $changeset->original_source_uuid };
+
+ for my $change ($changeset->changes) {
+ next unless $change->record_uuid eq $issue->uuid;
+ li {
+ ul {
+ map { li {$_->summary} } $change->prop_changes;
+ };
+ }
+
+ }
+ }
+ }
+}
+ };
+
+};
+
+template issue_comments => sub {
+ my $self = shift;
+ my $issue = shift;
+ my @comments = sort _by_creation_date @{$issue->comments};
+ if (@comments) {
+
+ h2 { 'Comments'};
+
+ ul {
+ for my $comment (@comments) {
+ li {
+span {
+ $comment->prop('created') ." " .
+$comment->prop('creator') }
+blockquote { $comment->prop('content');};
+ }
+ }
+ }}
+
+};
+
+
+sub issue_link {
+ my $issue = shift;
my $label = shift;
span {
- class is 'bug-link';
+ class is 'issue-link';
a {
{
- class is 'bug';
- href is '/bug/' . $bug->uuid;
+ class is 'issue';
+ href is '/issue/' . $issue->uuid;
};
$label;
}
More information about the Bps-public-commit
mailing list