[Bps-public-commit] r16153 - in sd/trunk: . lib/App/SD/CLI/Command/Ticket lib/App/SD/CLI/Model

spang at bestpractical.com spang at bestpractical.com
Mon Sep 29 18:16:23 EDT 2008


Author: spang
Date: Mon Sep 29 18:16:23 2008
New Revision: 16153

Modified:
   sd/trunk/   (props changed)
   sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm
   sd/trunk/lib/App/SD/CLI/Model/Ticket.pm
   sd/trunk/lib/App/SD/Model/Ticket.pm

Log:
 r50154 at loki:  spang | 2008-09-28 15:52:20 -0400
 revamp sd ticket create to use sections to differentiate editable/uneditable props


Modified: sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm
==============================================================================
--- sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm	(original)
+++ sd/trunk/lib/App/SD/CLI/Command/Ticket/Create.pm	Mon Sep 29 18:16:23 2008
@@ -9,44 +9,23 @@
 # props are specified on the commandline
 override run => sub {
     my $self = shift;
-    my $record = $self->_get_record_object;
     my @prop_set = $self->prop_set;
+    my $record = $self->_get_record_object;
 
     # only invoke editor if no props specified on the commandline or edit arg
     # specified
     if (!@prop_set || $self->has_arg('edit')) {
-        my $do_not_edit = $record->props_not_to_edit;
-        my @props = grep {!/$do_not_edit/} $record->props_to_show;
-
-        my %prefill_props;
-        # these props must exist in the hash, even if they have no value
-        map { $prefill_props{$_} = undef } @props;
-        # set default props
-        $record->default_props(\%prefill_props);
-        if ($self->has_arg('edit')) {
-            # override with props specified on the commandline
-            map { $prefill_props{$_} = $self->prop($_) if $self->has_prop($_) } @props;
-            $self->delete_arg('edit');
-        }
-        # undef values are noisy later when we want to interpolate the hash
-        map { $prefill_props{$_} = '' if !defined($prefill_props{$_}) } @props;
-
-        my $footer = comment_separator();
+        my $ticket_string_to_edit = $self->create_record_string();
 
-        my $ticket = $self->get_content( type => 'ticket', default_edit => 1,
-                                         prefill_props => \%prefill_props,
-                                         props_order => \@props,
-                                         footer => $footer,
-                                       );
+        my $ticket = $self->edit_text($ticket_string_to_edit);
 
         die "Aborted.\n"
-            if length($ticket) == 0;
+            if $ticket eq $ticket_string_to_edit; # user didn't change anything
 
-        (my $props_ref, my $comment) = $self->parse_record($ticket);
+        (my $props_ref, my $comment) = $self->parse_record_string($ticket);
 
         foreach my $prop (keys %$props_ref) {
-            $self->set_prop($prop => $props_ref->{$prop})
-                unless $prop =~ /$do_not_edit/; # don't let users create ids
+            $self->set_prop($prop => $props_ref->{$prop});
         }
 
         super();

Modified: sd/trunk/lib/App/SD/CLI/Model/Ticket.pm
==============================================================================
--- sd/trunk/lib/App/SD/CLI/Model/Ticket.pm	(original)
+++ sd/trunk/lib/App/SD/CLI/Model/Ticket.pm	Mon Sep 29 18:16:23 2008
@@ -29,18 +29,140 @@
     $command->run();
 }
 
+=head2 metadata_separator_text
 
-=head2 comment_separator
+Returns a string of text that goes in the comment denoting the beginning of
+uneditable ticket metadata in a string representing a ticket.
 
-Returns a string that separates the prop: value lines from the comment,
-which will be free text to the end of the new ticket. May contain
-arbitrary newlines.
+Uneditable ticket metadata includes things such as ticket id and
+creation date that are useful to display to the user when editing a
+ticket but are automatically assigned by sd and are not intended to
+be changed manually.
 
 =cut
 
-sub comment_separator { "\n\n=== add new ticket comment below ===\n"; }
+sub metadata_separator_text {
+    'required ticket metadata (changes here will not be saved)'
+}
+
+=head2 editable_props_separator_text
+
+Returns a string that denotes the text that goes in the comment denoting the
+beginning of prop: value pairs that are updatable in a string representing a
+ticket.
+
+=cut
+
+sub editable_props_separator_text { 'edit ticket details below' }
+
+=head2 comment_separator_text
+
+Returns a string that goes in the comment that separates the prop: value lines
+from the ticket comment in a string representing a ticket. The ticket comment
+will be free text to the end of the new ticket. May contain arbitrary newlines.
+
+=cut
+
+sub comment_separator_text { 'add new ticket comment below' }
+
+=head2 separator_pattern
+
+A pattern that will match on lines that count as section separators
+in tickets represented as strings. Separator string text is remembered
+as C<$1>.
+
+=cut
+
+sub separator_pattern { qr/^=== (.*) ===$/ }
+
+=head2 create_separator $text
+
+Takes a string and returns it in separator form.
+
+=cut
+
+sub create_separator {
+    my $self = shift;
+    my $text = shift;
 
-=head2 parse_record $str
+    return "=== $text ===";
+}
+
+=head2 comment_pattern
+
+Returns a pattern that will match on lines that count as comments in
+tickets represented as strings.
+
+=cut
+
+sub comment_pattern { qr/^\s*#/ }
+
+=head2 create_record_string
+
+Creates a string representing a new record, prefilling default props
+and props specified on the command line. Intended to be presented to
+the user for editing using L<Prophet::CLI::Command->edit_text>
+and then parsed using L</create_record_string>.
+
+=cut
+
+sub create_record_string {
+    my $self = shift;
+    my $record = $self->_get_record_object;
+
+    my $props_not_to_edit = $record->props_not_to_edit;
+    my (@metadata_order, @editable_order);
+    my (%metadata_props, %editable_props);
+
+    # separate out user-editable props so we can both show all
+    # the props that will be added to the new ticket and prevent
+    # users from being able to break things by changing props
+    # that shouldn't be changed, such as uuid
+    foreach my $prop ($record->props_to_show) {
+        if ($prop =~ $props_not_to_edit) {
+            push @metadata_order, $prop;
+            $metadata_props{$prop} = undef;
+        } else {
+            push @editable_order, $prop;
+            $editable_props{$prop} = undef;
+        }
+    }
+
+    # fill in prop defaults
+    $record->default_props(\%metadata_props);
+    $record->default_props(\%editable_props);
+
+    # fill in props specified on the commandline (overrides defaults)
+    if ($self->has_arg('edit')) {
+        map { $editable_props{$_} = $self->prop($_) if $self->has_prop($_) } @editable_order;
+        $self->delete_arg('edit');
+    }
+
+    # make undef values empty strings to avoid interpolation warnings
+    # (we can't do this earlier because $record->default_props only
+    # overrides undefined props)
+    map { $metadata_props{$_} = '' if !defined($metadata_props{$_}) }
+        @metadata_order;
+    map { $editable_props{$_} = '' if !defined($editable_props{$_}) }
+        @editable_order;
+
+    my $metadata_separator = $self->create_separator(metadata_separator_text());
+    my $editable_separator = $self->create_separator(editable_props_separator_text());
+    my $comment_separator = $self->create_separator(comment_separator_text());
+
+    my $metadata_props_string = join "\n",
+                        map { "$_: $metadata_props{$_}" } @metadata_order;
+    my $editable_props_string = join "\n",
+                        map { "$_: $editable_props{$_}" } @editable_order;
+
+    # glue all the parts together
+    my $ticket_string = $metadata_separator . "\n\n" . $metadata_props_string
+                    . "\n\n" . $editable_separator . "\n\n" .
+                    $editable_props_string . "\n\n" . $comment_separator
+                    . "\n";
+}
+
+=head2 parse_record_string $str
 
 Takes a string containing a ticket record consisting of prop: value pairs
 followed by a separator, followed by an optional comment.
@@ -50,22 +172,35 @@
 
 =cut
 
-sub parse_record {
+sub parse_record_string {
     my $self = shift;
     my $ticket = shift;
 
-    my %props;
-    my ($new_props, $comment) = split comment_separator(), $ticket;
-    my @lines = split "\n", $new_props;
+    my @lines = split "\n", $ticket;
+    my $last_seen_sep = '';
+    my %new_props;
+    my $comment = '';
+
     foreach my $line (@lines) {
-        # match prop: value pairs. whitespace in between is ignored.
-        if ($line =~ m/^([^:]+):\s*(.*)$/) {
-            my $prop = $1;
-            my $val = $2;
-            $props{$prop} = $val unless !($val);
+        if ($line =~ separator_pattern()) {
+            $last_seen_sep = $1;
+        } elsif ($line =~ comment_pattern() or
+            # skip comments and unchangeable props
+            $last_seen_sep eq metadata_separator_text()) {
+            next;
+        } elsif ($last_seen_sep eq editable_props_separator_text()) {
+            # match prop: value pairs. whitespace in between is ignored.
+            if ($line =~ m/^([^:]+):\s*(.*)$/) {
+                my $prop = $1;
+                my $val = $2;
+                $new_props{$prop} = $val unless !($val);
+            }
+        } elsif ($last_seen_sep eq comment_separator_text()) {
+            $comment .= $line;
         }
     }
-    return \%props, $comment;
+
+    return \%new_props, $comment;
 }
 
 no Moose::Role;

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	Mon Sep 29 18:16:23 2008
@@ -101,7 +101,7 @@
 
 =cut
 
-sub props_not_to_edit { qr/^(id|created|creator)$/ }
+sub props_not_to_edit { qr/^(id|creator|created|original_replica)$/ }
 
 =head2 is_overdue [$date]
 



More information about the Bps-public-commit mailing list