[Rt-commit] rt branch, 4.6/txn-query-builder-with-new-themes, repushed
? sunnavy
sunnavy at bestpractical.com
Mon Dec 9 16:51:48 EST 2019
The branch 4.6/txn-query-builder-with-new-themes was deleted and repushed:
was 644931a63b1b0c0aa02fc5d2ca0eb9a4e70c7705
now 127c50b88f0ee4540d2b9c890fbd7ea707c19c28
1: 87fe8ee2a7 ! 1: 457762464c Initial ticket transaction query builder
@@ -330,6 +330,14 @@
--- a/lib/RT/Transactions.pm
+++ b/lib/RT/Transactions.pm
@@
+ use base 'RT::SearchBuilder';
+
+ use RT::Transaction;
++use 5.010;
+
+ sub Table { 'Transactions'}
+
+@@
return $self->SUPER::AddRecord($record);
}
@@ -376,6 +384,7 @@
+ TicketPriority => ['TICKETFIELD'], #loc_left_pair
+ TicketInitialPriority => ['TICKETFIELD'], #loc_left_pair
+ TicketFinalPriority => ['TICKETFIELD'], #loc_left_pair
++ TicketQueueLifecycle => ['TICKETQUEUEFIELD'], #loc_left_pair
+
+ CustomFieldName => ['CUSTOMFIELDNAME'], #loc_left_pair
+ CFName => ['CUSTOMFIELDNAME'], #loc_left_pair
@@ -397,6 +406,7 @@
+ ATTACHFIELD => \&_AttachLimit,
+ ATTACHCONTENT => \&_AttachContentLimit,
+ TICKETFIELD => \&_TicketLimit,
++ TICKETQUEUEFIELD => \&_TicketQueueLimit,
+ OBJECTCUSTOMFIELDVALUE => \&_ObjectCustomFieldValueLimit,
+ CUSTOMFIELDNAME => \&_CustomFieldNameLimit,
+);
@@ -990,20 +1000,6 @@
+ my ( $self, $field, $op, $value, %rest ) = @_;
+ $field =~ s!^Ticket!!;
+
-+ unless ( defined $self->{_sql_ticketalias} ) {
-+ $self->{_sql_ticketalias} = $self->Join(
-+ TYPE => 'LEFT',
-+ FIELD1 => 'ObjectId',
-+ TABLE2 => 'Tickets',
-+ FIELD2 => 'id',
-+ );
-+ $self->Limit(
-+ FIELD => 'ObjectType',
-+ VALUE => 'RT::Ticket',
-+ ENTRYAGGREGATOR => 'AND',
-+ );
-+ }
-+
+ if ( $field eq 'Queue' && $value =~ /\D/ ) {
+ my $queue = RT::Queue->new($self->CurrentUser);
+ $queue->Load($value);
@@ -1016,13 +1012,39 @@
+ $value = $user->id if $user->id;
+ }
+
++ if ( $field eq 'Status' && $value =~ /^(?:__(?:in)?active__)$/i ) {
++ my $user = RT::User->new( $self->CurrentUser );
++ $user->Load($value);
++ $value = $user->id if $user->id;
++ }
++
+ $self->Limit(
+ %rest,
-+ ALIAS => $self->{_sql_ticketalias},
++ ALIAS => $self->_JoinTickets,
+ FIELD => $field,
+ OPERATOR => $op,
+ VALUE => $value,
+ CASESENSITIVE => 0,
++ );
++}
++
++sub _TicketQueueLimit {
++ my ( $self, $field, $op, $value, %rest ) = @_;
++ $field =~ s!^TicketQueue!!;
++
++ my $queue = $self->{_sql_aliases}{ticket_queues} ||= $_[0]->Join(
++ ALIAS1 => $self->_JoinTickets,
++ FIELD1 => 'Queue',
++ TABLE2 => 'Queues',
++ FIELD2 => 'id',
++ );
++
++ $self->Limit(
++ ALIAS => $queue,
++ FIELD => $field,
++ OPERATOR => $op,
++ VALUE => $value,
++ %rest,
+ );
+}
+
@@ -1073,6 +1095,111 @@
+ Class => ref $self || $self,
+ );
+ die join "; ", map { ref $_ eq 'ARRAY' ? $_->[ 0 ] : $_ } @results if @results;
++
++
++ # To handle __Active__ and __InActive__ statuses, copied from
++ # RT::Tickets::_parser with field name updates, i.e.
++ # Lifecycle => TicketQueueLifecycle
++ # Status => TicketStatus
++
++ state ( $active_status_node, $inactive_status_node );
++ my $escape_quotes = sub {
++ my $text = shift;
++ $text =~ s{(['\\])}{\\$1}g;
++ return $text;
++ };
++
++ $tree->traverse(
++ sub {
++ my $node = shift;
++ return unless $node->isLeaf and $node->getNodeValue;
++ my ($key, $subkey, $meta, $op, $value, $bundle)
++ = @{$node->getNodeValue}{qw/Key Subkey Meta Op Value Bundle/};
++ return unless $key eq "TicketStatus" && $value =~ /^(?:__(?:in)?active__)$/i;
++
++ my $parent = $node->getParent;
++ my $index = $node->getIndex;
++
++ if ( ( lc $value eq '__inactive__' && $op eq '=' ) || ( lc $value eq '__active__' && $op eq '!=' ) ) {
++ unless ( $inactive_status_node ) {
++ my %lifecycle =
++ map { $_ => $RT::Lifecycle::LIFECYCLES{ $_ }{ inactive } }
++ grep { @{ $RT::Lifecycle::LIFECYCLES{ $_ }{ inactive } || [] } }
++ grep { $RT::Lifecycle::LIFECYCLES_CACHE{ $_ }{ type } eq 'ticket' }
++ keys %RT::Lifecycle::LIFECYCLES;
++ return unless %lifecycle;
++
++ my $sql;
++ if ( keys %lifecycle == 1 ) {
++ $sql = join ' OR ', map { qq{ TicketStatus = '$_' } } map { $escape_quotes->($_) } map { @$_ } values %lifecycle;
++ }
++ else {
++ my @inactive_sql;
++ for my $name ( keys %lifecycle ) {
++ my $escaped_name = $escape_quotes->($name);
++ my $inactive_sql =
++ qq{TicketQueueLifecycle = '$escaped_name'}
++ . ' AND ('
++ . join( ' OR ', map { qq{ TicketStatus = '$_' } } map { $escape_quotes->($_) } @{ $lifecycle{ $name } } ) . ')';
++ push @inactive_sql, qq{($inactive_sql)};
++ }
++ $sql = join ' OR ', @inactive_sql;
++ }
++ $inactive_status_node = RT::Interface::Web::QueryBuilder::Tree->new;
++ $inactive_status_node->ParseSQL(
++ Class => ref $self,
++ Query => $sql,
++ CurrentUser => $self->CurrentUser,
++ );
++ }
++ $parent->removeChild( $node );
++ $parent->insertChild( $index, $inactive_status_node );
++ }
++ else {
++ unless ( $active_status_node ) {
++ my %lifecycle =
++ map {
++ $_ => [
++ @{ $RT::Lifecycle::LIFECYCLES{ $_ }{ initial } || [] },
++ @{ $RT::Lifecycle::LIFECYCLES{ $_ }{ active } || [] },
++ ]
++ }
++ grep {
++ @{ $RT::Lifecycle::LIFECYCLES{ $_ }{ initial } || [] }
++ || @{ $RT::Lifecycle::LIFECYCLES{ $_ }{ active } || [] }
++ }
++ grep { $RT::Lifecycle::LIFECYCLES_CACHE{ $_ }{ type } eq 'ticket' }
++ keys %RT::Lifecycle::LIFECYCLES;
++ return unless %lifecycle;
++
++ my $sql;
++ if ( keys %lifecycle == 1 ) {
++ $sql = join ' OR ', map { qq{ TicketStatus = '$_' } } map { $escape_quotes->($_) } map { @$_ } values %lifecycle;
++ }
++ else {
++ my @active_sql;
++ for my $name ( keys %lifecycle ) {
++ my $escaped_name = $escape_quotes->($name);
++ my $active_sql =
++ qq{TicketQueueLifecycle = '$escaped_name'}
++ . ' AND ('
++ . join( ' OR ', map { qq{ TicketStatus = '$_' } } map { $escape_quotes->($_) } @{ $lifecycle{ $name } } ) . ')';
++ push @active_sql, qq{($active_sql)};
++ }
++ $sql = join ' OR ', @active_sql;
++ }
++ $active_status_node = RT::Interface::Web::QueryBuilder::Tree->new;
++ $active_status_node->ParseSQL(
++ Class => ref $self,
++ Query => $sql,
++ CurrentUser => $self->CurrentUser,
++ );
++ }
++ $parent->removeChild( $node );
++ $parent->insertChild( $index, $active_status_node );
++ }
++ }
++ );
+
+ my $ea = '';
+ $tree->traverse(
@@ -1129,10 +1256,32 @@
+ return (0, $error);
+ }
+
++ $self->Limit( FIELD => 'ObjectType', VALUE => 'RT::Ticket' );
++ $self->Limit(
++ ALIAS => $self->_JoinTickets,
++ FIELD => 'Type',
++ OPERATOR => '=',
++ VALUE => 'ticket',
++ CASESENSITIVE => 0,
++ );
++
+ # set SB's dirty flag
+ $self->{'must_redo_search'} = 1;
+
+ return (1, $self->loc("Valid Query"));
++}
++
++sub _JoinTickets {
++ my $self = shift;
++ unless ( defined $self->{_sql_aliases}{tickets} ) {
++ $self->{_sql_aliases}{tickets} = $self->Join(
++ TYPE => 'LEFT',
++ FIELD1 => 'ObjectId',
++ TABLE2 => 'Tickets',
++ FIELD2 => 'id',
++ );
++ }
++ return $self->{_sql_aliases}{tickets};
+}
+
+=head2 Query
@@ -1980,8 +2129,12 @@
+ Type => 'component',
+ Path => '/Elements/SelectBoolean',
+ Arguments => { TrueVal=> '=', FalseVal => '!=' },
++ },
++ Value => {
++ Type => 'component',
++ Path => '/Elements/EmailInput',
++ Arguments => { AutocompleteReturn => 'Name' },
},
-+ Value => { Type => 'text', Size => 5 },
},
- Value => { Type => 'text', Size => 20 },
- },
@@ -2036,7 +2189,8 @@
+ Field => loc('Type'),
+ Op => {
+ Type => 'component',
-+ Path => '/Elements/SelectMatch',
++ Path => '/Elements/SelectBoolean',
++ Arguments => { TrueVal=> '=', FalseVal => '!=' },
+ },
+ Value => {
+ Type => 'select',
-: ------- > 2: 9a186b1295 Resolve the inconsistent $Class param in Search and CollectionAsTable
2: 7d5010b358 ! 3: 99f4dcdfda Add support to clip long search result columns
@@ -1,9 +1,9 @@
Author: sunnavy <sunnavy at bestpractical.com>
- Add support to clamp long search result columns
+ Add support to clip long search result columns
This is initially for transaction's Content column, which could be very
- long and we need to clamp it.
+ long and we need to clip it.
To get real height of the column value, this feature requires the value
to be wrapped into an HTML tag, like '<small>__Content__</small>'
@@ -15,7 +15,7 @@
contains => "Contains", # loc
lower_disabled => "disabled", # loc
history_scroll_error => "Could not load ticket history. Reason:", #loc
-+ unclamp => "Show all", #loc
++ unclip => "Show all", #loc
};
$_ = loc($_) for values %$Catalog;
@@ -32,7 +32,7 @@
+ overflow-y: hidden;
+}
+
-+.collection-as-table a.unclamp {
++.collection-as-table a.unclip {
+ font-size: smaller;
+ font-weight: normal;
+}
@@ -51,11 +51,11 @@
+ if ( jQuery(this).children().height() > max_height ) {
+ jQuery(this).children().wrapAll('<div class="clamp">');
+ jQuery(this).children('div.clamp').height('' + max_height + 'px');
-+ jQuery(this).append('<a href="#" class="unclamp button btn btn-primary">' + loc_key('unclamp') + '</a>');
++ jQuery(this).append('<a href="#" class="unclip button btn btn-primary">' + loc_key('unclip') + '</a>');
+ }
+ }
+ });
-+ jQuery('a.unclamp').click(function() {
++ jQuery('a.unclip').click(function() {
+ jQuery(this).siblings('div.clamp').css('height', 'auto');
+ jQuery(this).hide();
+ return false;
3: 37b156ed02 ! 4: 1b6abdd28c Add transaction search tests
@@ -29,6 +29,21 @@
+for my $field ( keys %field_value ) {
+ is( $txn->$field, $field_value{$field}, $field );
+}
++
++$txns->FromSQL('Type="Create" AND TicketStatus="__Active__"');
++is( $txns->Count, 2, 'Found the 2 create txns of active tickets' );
++
++$txns->FromSQL('Type="Create" AND TicketStatus="__Inactive__"');
++is( $txns->Count, 0, 'Found the 0 create txns of inactive tickets' );
++
++ok( $frodo->SetStatus('resolved'), 'Resolved 1 ticket' );
++$txns->FromSQL('Type="Create" AND TicketStatus="__Active__"');
++is( $txns->Count, 1, 'Found the 1 create txn of active tickets' );
++is( $txns->Next->ObjectId, $bilbo->id, 'Active ticket is bilbo' );
++
++$txns->FromSQL('Type="Create" AND TicketStatus="__Inactive__"');
++is( $txns->Count, 1, 'Found the 1 create txn of inactive tickets' );
++is( $txns->Next->ObjectId, $frodo->id, 'Inactive ticket is frodo' );
+
+my $cf_age = RT::Test->load_or_create_custom_field(
+ Name => 'Age',
4: 116ffe73f2 = 5: f6e4814f80 Add transaction query builder tests
5: 644931a63b = 6: 127c50b88f Add Transactions to query builder docs
More information about the rt-commit
mailing list