[freeside-commits] branch FREESIDE_3_BRANCH updated. e7bad3b31830cd1c838c607a3336413a4c5ed50c

Mark Wells mark at 420.am
Thu Dec 10 01:04:00 PST 2015


The branch, FREESIDE_3_BRANCH has been updated
       via  e7bad3b31830cd1c838c607a3336413a4c5ed50c (commit)
       via  1b821166888962897d6f4b0c87acb00d6b9f392d (commit)
       via  5f2c6bcae77fc9c1b723bae954ef09547da712ee (commit)
       via  991011f4ffc62b739f123a2124ca93f461d398ce (commit)
       via  d0c5ecc6d52a28f583ec45afc3460dc613b38eba (commit)
      from  311a694bf1cb816a48efca116e260d940c5a646f (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit e7bad3b31830cd1c838c607a3336413a4c5ed50c
Merge: 1b82116 311a694
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Dec 10 01:01:29 2015 -0800

    Merge branch 'FREESIDE_3_BRANCH' of git.freeside.biz:/home/git/freeside into 3.x


commit 1b821166888962897d6f4b0c87acb00d6b9f392d
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Dec 10 01:01:21 2015 -0800

    fix some problems with creation of subtask tickets, #34061

diff --git a/rt/lib/RT/Condition/CustomFieldEquals.pm b/rt/lib/RT/Condition/CustomFieldEquals.pm
index 69dedcb..8ebf94b 100644
--- a/rt/lib/RT/Condition/CustomFieldEquals.pm
+++ b/rt/lib/RT/Condition/CustomFieldEquals.pm
@@ -28,9 +28,10 @@ sub IsApplicable {
     if ($trans->Type eq 'CustomField') {
         my $cf = RT::CustomField->new($self->CurrentUser);
         $cf->Load($field);
-        return $trans->Field == $cf->Id
-               and ($trans->NewValue eq $value)
-               and ($trans->OldValue ne $value)
+        return (   $trans->Field == $cf->Id
+               and $trans->NewValue eq $value
+               and $trans->OldValue ne $value
+               );
     }
     return undef;
 }
diff --git a/rt/lib/RT/Template_Vendor.pm b/rt/lib/RT/Template_Vendor.pm
new file mode 100644
index 0000000..f1a276c
--- /dev/null
+++ b/rt/lib/RT/Template_Vendor.pm
@@ -0,0 +1,34 @@
+package RT::Template;
+
+=item LoadByName
+
+Takes Name and Queue arguments. Tries to load queue specific template
+first, then global. If Queue argument is omitted then global template
+is tried, not template with the name in any queue.
+
+=cut
+
+sub LoadByName {
+    my $self = shift;
+    my %args = (
+        Queue => undef,
+        Name  => undef,
+        @_
+    );
+    my $queue = $args{'Queue'};
+    if ( blessed $queue ) {
+        $queue = $queue->id;
+    } elsif ( defined $queue and $queue =~ /\D/ ) {
+        my $tmp = RT::Queue->new( $self->CurrentUser );
+        $tmp->Load($queue);
+        $queue = $tmp->id;
+    }
+
+    return $self->LoadGlobalTemplate( $args{'Name'} ) unless $queue;
+
+    $self->LoadQueueTemplate( Queue => $queue, Name => $args{'Name'} );
+    return $self->id if $self->id;
+    return $self->LoadGlobalTemplate( $args{'Name'} );
+}
+
+1;
diff --git a/rt/share/html/Admin/Queues/Tasks.html b/rt/share/html/Admin/Queues/Tasks.html
index 30ec12b..94df549 100755
--- a/rt/share/html/Admin/Queues/Tasks.html
+++ b/rt/share/html/Admin/Queues/Tasks.html
@@ -92,7 +92,7 @@ my $title = loc("Set up subtasks for queue [_1]", $QueueObj->Name);
 
 my $TEMPLATE_NAME = '[Subtask]';
 my $SCRIPCONDITION_NAME = '[Subtask] Queue='.$Queue;
-my $SUBJECT_PREFIX = q({ $Tickets{'TOP'}->Subject }-);
+my $SUBJECT_PREFIX = q({ $TOP->Subject }-);
 
 my ($Scrip, $ScripCondition, $Template, $CustomField);
 
@@ -112,7 +112,7 @@ $Scrip = RT::Scrip->new($RT::SystemUser);
 {
   my $Scrips = RT::Scrips->new($RT::SystemUser);
   $Scrips->LimitToQueue($Queue);
-  $Scrips->Limit( FIELD => 'Template', VALUE => $TEMPLATE_NAME );
+  $Scrips->Limit( FIELD => 'Template', VALUE => $Template->Id );
   if ( $Scrips->Count > 0 ) {
     $Scrip = $Scrips->First;
   }
@@ -138,12 +138,13 @@ if ( $ARGS{task_id} ) { # actually contains numeric indices
     my %task_opts = map { $_ => $ARGS{$_} }
                     grep /^$task_id-/, keys(%ARGS);
     my $task_content = "===Create-Ticket: $task_id
+CF-$cfname:" . q[
 Depended-On-By: TOP
-CF-$cfname: 
-";
-    # any other static content can go here, but we always want the child
-    # ticket relationship, and we want to force the ConditionCF to be empty
-    # to avoid recursion.
+Owner: { $TOP->Owner }
+{ join("\n", map { "Requestor: $_" }
+  $TOP->Requestors->MemberEmailAddresses) }
+];
+    # any other attributes to put on subtask tickets should go here also.
 
     my $has_content = 0;
 
@@ -171,7 +172,6 @@ CF-$cfname:
       $new_content .= $task_content;
     }
   }
-  warn "NEW CONTENT:\n$new_content\n\n"; # XXX
 
   if ( ! $Template->Id ) {
     my ( $val, $msg ) = $Template->Create(
@@ -252,12 +252,10 @@ my $Action = $action_class->new(
   CurrentUser    => $session{'CurrentUser'},
 );
 # this will populate $Action with the 'create_tickets' hash
-warn $Template->Content;
 $Action->Parse(
   Content         => $Template->Content,
   _ActiveContent  => 0,
 );
-warn Dumper \$Action;
 my @task_ids;
 @task_ids = @{ $Action->{create_tickets} } if exists $Action->{create_tickets};
 

commit 5f2c6bcae77fc9c1b723bae954ef09547da712ee
Author: Mark Wells <mark at freeside.biz>
Date:   Thu Dec 10 00:23:01 2015 -0800

    and also for CKEditor < 4.5

diff --git a/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
index 96c0f42..d0c9a02 100644
--- a/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
+++ b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
@@ -134,7 +134,7 @@
                           } // elements
                         });
 
-                        editor.on( 'afterInsertHtml', function( evt ) {
+                        editor.on( 'insertHtml', function( evt ) {
                           // if this leaves an open SPAN, move the cursor
                           // to after it
                           var range = editor.getSelection().getRanges()[0];
@@ -144,7 +144,8 @@
                             range.collapse();
                             editor.getSelection().selectRanges([ range ]);
                           }
-                        });
+                        }, null, null, 30);
+                        // actually inserting the HTML happens at priority 10.
 
                 } // afterInit
         }); // plugins.add

commit 991011f4ffc62b739f123a2124ca93f461d398ce
Author: Mark Wells <mark at freeside.biz>
Date:   Wed Dec 9 17:23:46 2015 -0800

    fix strange behavior after inserting a substitution, #38803, fallout from #24331

diff --git a/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
index e4ef391..96c0f42 100644
--- a/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
+++ b/httemplate/elements/ckeditor/plugins/blockprotect/plugin.js
@@ -133,7 +133,20 @@
                             } // span function
                           } // elements
                         });
-                }
+
+                        editor.on( 'afterInsertHtml', function( evt ) {
+                          // if this leaves an open SPAN, move the cursor
+                          // to after it
+                          var range = editor.getSelection().getRanges()[0];
+                          var ec = range.endContainer;
+                          if ( ec.hasClass('cke_blockprotect') ) {
+                            range.setEndAfter(ec);
+                            range.collapse();
+                            editor.getSelection().selectRanges([ range ]);
+                          }
+                        });
+
+                } // afterInit
         }); // plugins.add
 }) ();
 
diff --git a/httemplate/elements/htmlarea.html b/httemplate/elements/htmlarea.html
index c98993d..0ba4177 100644
--- a/httemplate/elements/htmlarea.html
+++ b/httemplate/elements/htmlarea.html
@@ -20,7 +20,8 @@ Example:
 
 <SCRIPT TYPE="text/javascript">
 
-  CKEDITOR.replace('<% $opt{'field'} %>',
+  var <% $opt{'field'} %>_editor =
+    CKEDITOR.replace('<% $opt{'field'} %>',
                    <% encode_json($config) %>
   );
 

commit d0c5ecc6d52a28f583ec45afc3460dc613b38eba
Author: Mark Wells <mark at freeside.biz>
Date:   Wed Dec 9 16:00:14 2015 -0800

    automatic creation of subtask tickets, #34061

diff --git a/rt/lib/RT/Condition/CustomFieldEquals.pm b/rt/lib/RT/Condition/CustomFieldEquals.pm
new file mode 100644
index 0000000..69dedcb
--- /dev/null
+++ b/rt/lib/RT/Condition/CustomFieldEquals.pm
@@ -0,0 +1,39 @@
+package RT::Condition::CustomFieldEquals;
+use base 'RT::Condition';
+use strict;
+
+=head2 IsApplicable
+
+If a custom field has a value equal to some specified value.
+
+=cut
+
+# Based on Chuck Boeheim's code posted on the RT Wiki 3/13/06
+# Simplified to avoid carrying old schema around. The new mechanics are that
+# the ScripCondition's "Argument" is the custom field name = value. If the 
+# transaction initially sets the CF value to a the specified value, or 
+# changes it from not equaling to equaling the specified value, the condition
+# returns true.
+# Don't use this on custom fields that allow multiple values.
+
+sub IsApplicable {
+    my $self = shift;
+    my $trans = $self->TransactionObj;
+    my $scrip = $self->ScripObj;
+    my ($field, $value) = split('=', $self->Argument, 2);
+
+    if ($trans->Type eq 'Create') {
+        return ($trans->TicketObj->FirstCustomFieldValue($field) eq $value);
+    }
+    if ($trans->Type eq 'CustomField') {
+        my $cf = RT::CustomField->new($self->CurrentUser);
+        $cf->Load($field);
+        return $trans->Field == $cf->Id
+               and ($trans->NewValue eq $value)
+               and ($trans->OldValue ne $value)
+    }
+    return undef;
+}
+
+1;
+
diff --git a/rt/share/html/Admin/Queues/Tasks.html b/rt/share/html/Admin/Queues/Tasks.html
new file mode 100755
index 0000000..30ec12b
--- /dev/null
+++ b/rt/share/html/Admin/Queues/Tasks.html
@@ -0,0 +1,269 @@
+<& /Admin/Elements/Header, Title => $title &>
+<& /Elements/Tabs &>
+<& /Elements/ListActions, actions => \@results &>
+
+<form action="Tasks.html" method="post">
+<input type="hidden" name="Queue" value="<% $Queue %>" />
+<h2>
+  <label for="ConditionCF"><&|/l&>Enabled if</&>:</label>
+% if ( $PossibleCustomFields->Count > 0 ) {
+  <select name="ConditionCF">
+%   while ( my $thiscf = $PossibleCustomFields->Next ) {
+    <option value="<% $thiscf->Id %>" <% $thiscf->Id == $cfid ? 'selected' : '' %>><% $thiscf->Name %></option>
+%   }
+  </select>
+  <label for="ConditionValue"><&|/l&>equals</&></label>
+  <input name="ConditionValue" value="<% $cfvalue %>" />
+% } else {
+  <select name="no_cfs" disabled>
+    <option value="1">(no custom fields defined)</option>
+  </select>
+% }
+</h2>
+<table>
+% my (@links, @postponed); # not really used here
+% my $idx = 1;
+% foreach my $task_id (@task_ids, 'new') {
+%   # simulate creating the tickets, but don't evaluate any perl inclusions
+%   # in the content (_ActiveContent => 0 earlier)
+%   my ($ticket, $ticketargs);
+%   if ( $task_id eq 'new' ) {
+%     $ticket = RT::Ticket->new($session{'CurrentUser'});
+%     $ticketargs = {
+%       Queue => $Queue,
+%       # any other defaults make sense here?
+%     };
+%   } else {
+%     ($ticket, $ticketargs) =
+%       $Action->ParseLines($task_id, \@links, \@postponed);
+%   }
+%   my $subject = $ticketargs->{Subject};
+%   my $subjectprefix = 0;
+%   if ( $subject =~ s/^\Q$SUBJECT_PREFIX\E// ) {
+%     $subjectprefix = 1;
+%   }
+
+  <tr>
+    <td colspan="2">
+      <h2>
+      <label for="task_id"><&|/l&>Task #</&><% $idx %>
+% # each time these are edited, replace all task IDs with sequential numbers.
+% # no point in letting them be anything else, at least yet.
+      <input type="hidden" name="task_id" value="<% $idx %>">
+      </h2>
+    </td>
+  </tr>
+  <tr>
+    <td class="label"><&|/l&>Subject</&>:</td>
+    <td class="value">
+      <input name="<% $idx %>-Subject" value="<% $subject |h %>" />
+      <input type="checkbox" name="<% $idx %>-SubjectPrefix" <% $subjectprefix ? 'checked' : '' %> /> <&|/l&>Prefix with main subject</&>
+    </td>
+  </tr>
+  <tr>
+    <td class="label"><&|/l&>In queue</&>:</td>
+    <td class="value"><& /Elements/SelectQueue,
+      Name => "$idx-Queue",
+      ShowNullOption => 0,
+      Default => ($ticketargs->{Queue} || $Queue),
+    &></td>
+  </tr>
+  <tr>
+    <td class="label"><&|/l&>Content</&>:</td>
+    <td class="value"><textarea name="<% $idx %>-Content" rows="10" cols="80" wrap="soft"><%
+    ( $ticketargs->{MIMEObj} ? $ticketargs->{MIMEObj}->body_as_string : '' )
+    %></textarea>
+    </td>
+  </tr>
+
+%   $idx++;
+% }
+</table>
+<& /Elements/Submit, Label => 'Save Changes' &>
+</form>
+<%init>
+my @results;
+
+my $QueueObj = RT::Queue->new($session{'CurrentUser'});
+$QueueObj->Load($Queue);
+Abort(loc("Queue [_1] not found",$Queue)) unless $QueueObj->Id;
+
+my $title = loc("Set up subtasks for queue [_1]", $QueueObj->Name);
+
+my $TEMPLATE_NAME = '[Subtask]';
+my $SCRIPCONDITION_NAME = '[Subtask] Queue='.$Queue;
+my $SUBJECT_PREFIX = q({ $Tickets{'TOP'}->Subject }-);
+
+my ($Scrip, $ScripCondition, $Template, $CustomField);
+
+# SystemUser for the scrip so that the user doesn't need ACLs to edit scrips
+# as such.  all the scrip parameters are hardcoded anyway...
+
+$ScripCondition = RT::ScripCondition->new($RT::SystemUser);
+$ScripCondition->LoadByCol('Name', $SCRIPCONDITION_NAME);
+
+$Template = RT::Template->new($session{'CurrentUser'});
+$Template->LoadByName(
+  Name  => $TEMPLATE_NAME,
+  Queue => $Queue,
+);
+
+$Scrip = RT::Scrip->new($RT::SystemUser);
+{
+  my $Scrips = RT::Scrips->new($RT::SystemUser);
+  $Scrips->LimitToQueue($Queue);
+  $Scrips->Limit( FIELD => 'Template', VALUE => $TEMPLATE_NAME );
+  if ( $Scrips->Count > 0 ) {
+    $Scrip = $Scrips->First;
+  }
+}
+
+# The CF name to test, and the value it must have to trigger the scrip.
+my $cfid = $ARGS{ConditionCF};
+my $cfvalue = $ARGS{ConditionValue};
+$CustomField = RT::CustomField->new($session{'CurrentUser'});
+if ( $cfid ) {
+  $CustomField->Load($cfid);
+}
+my $cfname = $CustomField->Name;
+
+# if there's input from the form, process it into a new template content
+my $new_content = '';
+
+if ( $ARGS{task_id} ) { # actually contains numeric indices
+  my @task_ids = $ARGS{task_id};
+  @task_ids = @{ $task_ids[0] } if ref($task_ids[0]);
+  foreach my $task_id (@task_ids) {
+    # find the inputs for this task_id
+    my %task_opts = map { $_ => $ARGS{$_} }
+                    grep /^$task_id-/, keys(%ARGS);
+    my $task_content = "===Create-Ticket: $task_id
+Depended-On-By: TOP
+CF-$cfname: 
+";
+    # any other static content can go here, but we always want the child
+    # ticket relationship, and we want to force the ConditionCF to be empty
+    # to avoid recursion.
+
+    my $has_content = 0;
+
+    # special case: automate prefixing the main ticket subject
+    if ( $task_opts{"$task_id-SubjectPrefix"} ) {
+      $task_opts{"$task_id-Subject"} =
+        $SUBJECT_PREFIX . $task_opts{"$task_id-Subject"};
+    }
+    
+    foreach my $key (sort keys %task_opts) {
+      $key =~ /^$task_id-(.*)/;
+      my $tag = $1;
+      my $value = $task_opts{$key};
+      $value =~ s/^\s*//;
+      $value =~ s/\s*$//;
+      $value =~ s/\r//g;
+      $task_content .= "$tag: $value\n";
+      # only create a task if the ticket has non-whitespace content
+      if ( lc($tag) eq 'content' and length($value) > 0 ) {
+        $task_content .= "ENDOFCONTENT\n";
+        $has_content = 1;
+      }
+    }
+    if ( $has_content ) {
+      $new_content .= $task_content;
+    }
+  }
+  warn "NEW CONTENT:\n$new_content\n\n"; # XXX
+
+  if ( ! $Template->Id ) {
+    my ( $val, $msg ) = $Template->Create(
+      Queue           => $Queue,
+      Name            => $TEMPLATE_NAME,
+      Description     => 'Subtask tickets',
+      Type            => 'Perl',
+      Content         => $new_content,
+    );
+    if (!$val) {
+      push @results, loc("Could not create template: [_1]", $msg);
+    } else {
+      push @results, loc("Template created");
+    }
+  } elsif ( $Template->Content ne $new_content ) { # template needs updating
+    my ( $val, $msg ) = $Template->SetContent($new_content);
+    if (!$val) {
+      push @results, loc("Could not update template: [_1]", $msg);
+    } else {
+      push @results, loc("Template updated");
+    }
+  }
+
+  # Set up ScripCondition
+  if ( !$cfname ) {
+    push @results, loc("No custom field selected");
+  } elsif ( length($cfvalue) == 0 ) {
+    push @results, loc("Custom field value is required");
+  } elsif ( ! $ScripCondition->Id ) {
+    my ( $val, $msg ) = $ScripCondition->Create(
+      Name            => $SCRIPCONDITION_NAME,
+      Description     => "When CF.[$cfname] equals '$cfvalue'",
+      ExecModule      => 'CustomFieldEquals',
+      Argument        => "$cfname=$cfvalue",
+      ApplicableTransTypes => 'Any',
+    );
+    if (!$val) {
+      push @results, loc("Could not create custom field condition: [_1]", $msg);
+    } else {
+      push @results, loc("Custom field condition created");
+    }
+  } elsif ( $ScripCondition->Argument ne "$cfname=$cfvalue" ) {
+    my ( $val, $msg ) = $ScripCondition->SetArgument("$cfname=$cfvalue");
+    if (!$val) {
+      push @results, loc("Could not set custom field condition: [_1]", $msg);
+    } else {
+      push @results, loc("Custom field condition set");
+    }
+  }
+
+  # Set up Scrip
+  if ( $Template->Id and ! $Scrip->Id ) {
+    my ($val, $msg) = $Scrip->Create(
+      Queue           => $Queue,
+      Template        => $Template->Id,
+      Description     => 'Create subtasks for ' . $QueueObj->Name,
+      ScripCondition  => $ScripCondition->Id,
+      ScripAction     => 'Create Tickets',
+    );
+    if (!$val) {
+      push @results, loc("Could not create scrip: [_1]", $msg);
+    } else {
+      push @results, loc("Scrip created");
+    }
+  } # else don't need to create the scrip
+
+  # even if $new_content is empty, there's no harm in letting the scrip and
+  # template exist with empty content. they just won't do anything.
+}
+
+# CHANGES HAVE BEEN SAVED.
+# Now prepare to (re-)display the form.
+
+# ask RT::Action::CreateTickets how it will parse the template
+my $action_class = 'RT::Action::CreateTickets';
+$action_class->require;
+my $Action = $action_class->new(
+  CurrentUser    => $session{'CurrentUser'},
+);
+# this will populate $Action with the 'create_tickets' hash
+warn $Template->Content;
+$Action->Parse(
+  Content         => $Template->Content,
+  _ActiveContent  => 0,
+);
+warn Dumper \$Action;
+my @task_ids;
+ at task_ids = @{ $Action->{create_tickets} } if exists $Action->{create_tickets};
+
+my $PossibleCustomFields = $QueueObj->TicketCustomFields;
+
+</%init>
+<%ARGS>
+$Queue => undef         #queue id
+</%ARGS>
diff --git a/rt/share/html/Elements/Tabs b/rt/share/html/Elements/Tabs
index 3e28e25..bc2badf 100755
--- a/rt/share/html/Elements/Tabs
+++ b/rt/share/html/Elements/Tabs
@@ -289,6 +289,8 @@ my $build_admin_menu = sub {
                 my $txn_cfs = $queue->child( 'transaction-custom-fields' => title => loc('Transaction Custom Fields'),
                     path => '/Admin/Queues/CustomFields.html?SubType=RT::Ticket-RT::Transaction&id='.$id );
 
+                $queue->child( 'tasks' => title => loc('Subtasks'), path => "Admin/Queues/Tasks.html?Queue=".$id );
+
                 $queue->child( 'group-rights' => title => loc('Group Rights'), path => "/Admin/Queues/GroupRights.html?id=".$id );
                 $queue->child( 'user-rights' => title => loc('User Rights'), path => "/Admin/Queues/UserRights.html?id=" . $id );
                 $queue->child( 'history' => title => loc('History'), path => "/Admin/Queues/History.html?id=" . $id );

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

Summary of changes:
 .../ckeditor/plugins/blockprotect/plugin.js        |   16 +-
 httemplate/elements/htmlarea.html                  |    3 +-
 rt/lib/RT/Condition/CustomFieldEquals.pm           |   40 +++
 rt/lib/RT/Template_Vendor.pm                       |   34 +++
 rt/share/html/Admin/Queues/Tasks.html              |  267 ++++++++++++++++++++
 rt/share/html/Elements/Tabs                        |    2 +
 6 files changed, 360 insertions(+), 2 deletions(-)
 create mode 100644 rt/lib/RT/Condition/CustomFieldEquals.pm
 create mode 100644 rt/lib/RT/Template_Vendor.pm
 create mode 100755 rt/share/html/Admin/Queues/Tasks.html




More information about the freeside-commits mailing list