[Bps-public-commit] rt-extension-timetracking branch, time-search, created. 0.09-11-gbfaf166

? sunnavy sunnavy at bestpractical.com
Tue Jul 10 17:01:43 EDT 2018


The branch, time-search has been created
        at  bfaf16615629e508d46ffc3c0b2c1ee1058f9a47 (commit)

- Log -----------------------------------------------------------------
commit bfaf16615629e508d46ffc3c0b2c1ee1058f9a47
Author: sunnavy <sunnavy at bestpractical.com>
Date:   Wed Jul 11 04:40:02 2018 +0800

    Initial version of time search page
    
    This page makes it easier to get worked time for specified tickets(via
    search query) between 2 dates.

diff --git a/html/Callbacks/RT-Extension-TimeTracking/Elements/Tabs/Privileged b/html/Callbacks/RT-Extension-TimeTracking/Elements/Tabs/Privileged
index 3aeeb1f..9450664 100644
--- a/html/Callbacks/RT-Extension-TimeTracking/Elements/Tabs/Privileged
+++ b/html/Callbacks/RT-Extension-TimeTracking/Elements/Tabs/Privileged
@@ -7,6 +7,14 @@ Menu()->child('tools')->child(
     sort_order  => 2.5,
 );
 
+Menu()->child('tools')->child(
+    'time_search',
+    title       => loc("Time Search"),
+    description => loc("Find time worked for specified tickets between dates"),
+    path        => '/Tools/TimeSearch.html',
+    sort_order  => 2.6,
+);
+
 my $request_path = $HTML::Mason::Commands::r->path_info;
 $request_path =~ s!/{2,}!/!g;
 if ( $request_path =~ m{^/Tools/MyWeek.html} && $DECODED_ARGS->{'User'} && $DECODED_ARGS->{'User'} != $session{CurrentUser}->id ) {
diff --git a/html/Tools/TimeSearch.html b/html/Tools/TimeSearch.html
new file mode 100644
index 0000000..b8693b3
--- /dev/null
+++ b/html/Tools/TimeSearch.html
@@ -0,0 +1,232 @@
+<& /Elements/Header, Title => loc("Time Search") &>
+
+<& /Elements/Tabs &>
+
+<& /Elements/ListActions, actions => \@results &>
+
+<div class="time_tracking time_search">
+
+<form>
+<table>
+<tr>
+    <td class="label"><&|/l&>Ticket Query</&>:</td>
+    <td class="value"><textarea name="Query" rows="8" cols="72"><% $Query %></textarea></td>
+</tr>
+<tr>
+    <td class="label"><&|/l&>Start Date</&>:</td>
+    <td class="value"><& /Elements/SelectDate, ShowTime => 0, Name => 'StartDate', Default => $start_date->Date(Format=>'ISO', Timezone => 'user') &></td>
+</tr>
+<tr>
+    <td class="label"><&|/l&>End Date</&>:</td>
+    <td class="value"><& /Elements/SelectDate, ShowTime => 0, Name => 'EndDate', Default => $end_date->Date(Format=>'ISO', Timezone => 'user') &></td>
+</tr>
+</table>
+<& /Elements/Submit, Name => 'DoSearch', Label => loc("Search") &>
+</form>
+
+% if ( $ARGS{DoSearch} ) {
+
+<div>
+
+% if ( %ticket_worked ) {
+<table class="ticket-list collection-as-table">
+    <tr class="collection-as-table">
+        <th class="collection-as-table"><&|/l&>id</&></th>
+        <th class="collection-as-table"><&|/l&>Subject</&></th>
+        <th class="collection-as-table"><&|/l&>Queue</&></th>
+        <th class="collection-as-table"><&|/l&>Status</&></th>
+        <th class="collection-as-table"><&|/l&>Owner</&></th>
+% if ( $display_cf ){
+        <th class="collection-as-table"><% $display_cf %></th>
+% }
+        <th class="collection-as-table"><&|/l&>Time Worked</&></th>
+        <th class="collection-as-table"><&|/l&>Time Estimated</&></th>
+    </tr>
+% my $i = 1;
+% for my $ticket_id ( sort { $a <=> $b } keys %ticket_worked ) {
+% my $entry = $ticket_worked{$ticket_id};
+% my $ticket = $entry->{ticket};
+    <tr class="<% $i++ % 2 ? 'oddline' : 'evenline' %>">
+        <td class="collection-as-table">
+        <a href="<% RT->Config->Get('WebPath') %>/Ticket/Display.html?id=<% $ticket->id %>"><% $ticket->id %></a>
+        </td>
+        <td class="collection-as-table">
+        <a href="<% RT->Config->Get('WebPath') %>/Ticket/Display.html?id=<% $ticket->id %>"><% $ticket->Subject %></a>
+        </td>
+        <td class="collection-as-table"><% $ticket->QueueObj->Name %></td>
+        <td class="collection-as-table"><% $ticket->Status %></td>
+        <td class="collection-as-table"><% $ticket->OwnerObj->Name %></td>
+% if ( $display_cf ){
+        <td class="collection-as-table"><% $ticket->FirstCustomFieldValue($display_cf) %></td>
+% }
+        <td class="collection-as-table"><& /Ticket/Elements/ShowTime, minutes => $entry->{time_worked} &></td>
+        <td class="collection-as-table"><& /Ticket/Elements/ShowTime, minutes => $ticket->TimeEstimated &></td>
+    </tr>
+% }
+</table>
+% }
+
+</div>
+
+<hr />
+<div class="time_worked">
+<span class="label"><&|/l&>Total Time Worked</&>:</span> <span class="value"><& /Ticket/Elements/ShowTime, minutes => $total_time_worked &></span>
+</div>
+% }
+
+% $m->callback( CallbackName => 'End', Query => $Query, StartDate => $start_date, EndDate => $end_date, TicketWorked => \%ticket_worked );
+
+</div>
+<%INIT>
+
+my @results;
+my $user = $session{CurrentUser};
+
+my $start_date = RT::Date->new( $user );
+if ( $StartDate ) {
+    $start_date->Set( Value => $StartDate, Format => 'unknown' );
+}
+else {
+    $start_date->SetToNow;
+    my ( $ret, $week_start_date ) =
+      RT::Extension::TimeTracking::WeekStartDate( $user, $start_date, RT->Config->Get( 'TimeTrackingFirstDayOfWeek' ) );
+    $start_date = $week_start_date if $ret;
+}
+$start_date->SetToMidnight( Timezone => 'user' );
+
+my $end_date = RT::Date->new( $user );
+if ( $EndDate ) {
+    $end_date->Set( Value => $EndDate, Format => 'unknown' );
+}
+else {
+    $end_date->SetToNow;
+}
+$end_date->SetToMidnight( Timezone => 'user' );
+
+my $exclusive_end_date = RT::Date->new( $user );
+$exclusive_end_date->Set( Value => $end_date->Unix, Format => 'Unix' );
+$exclusive_end_date->AddDays( 1 );
+
+my %ticket_worked;
+my $total_time_worked = 0;
+
+# Do we need to load a CF for display?
+my $display_cf;
+if ( $display_cf = RT->Config->Get( 'TimeTrackingDisplayCF' ) ) {
+    my $confirm_cf = RT::CustomField->new( RT->SystemUser );
+    my ( $ret, $msg ) = $confirm_cf->Load( $display_cf );
+
+    if ( not $ret ) {
+        RT::Logger->error(
+            "Unable to load custom field $display_cf " . "defined via config option TimeTrackingDisplayCF: $msg" );
+        undef $display_cf;
+    }
+}
+
+if ( $ARGS{DoSearch} ) {
+    my $tickets = RT::Tickets->new( $user );
+    if ( $Query ) {
+        my ( $ret, $msg ) = $tickets->FromSQL( $Query );
+        push @results, $msg unless $ret;
+    }
+    else {
+        push @results, loc( 'No query' );
+    }
+    MaybeRedirectForResults(
+        Actions   => \@results,
+        Arguments => { StartDate => $StartDate, EndDate => $EndDate, Query => $Query },
+    );
+    my @ticket_ids = map { $_->id } @{ $tickets->ItemsArrayRef };
+
+    my $txns = RT::Transactions->new( $user );
+    $txns->Limit(
+        FIELD => 'ObjectType',
+        VALUE => 'RT::Ticket',
+    );
+    $txns->Limit(
+        FIELD    => 'ObjectID',
+        VALUE    => \@ticket_ids,
+        OPERATOR => 'IN',
+    );
+
+    $txns->Limit(
+        FIELD    => 'TimeTaken',
+        VALUE    => 0,
+        OPERATOR => '!=',
+    );
+
+    $txns->Limit(
+        FIELD    => 'Created',
+        VALUE    => $start_date->ISO(),
+        OPERATOR => '>=',
+    );
+    $txns->Limit(
+        FIELD           => 'Created',
+        VALUE           => $exclusive_end_date->ISO(),
+        OPERATOR        => '<',
+        ENTRYAGGREGATOR => 'AND',
+    );
+
+    while ( my $txn = $txns->Next ) {
+        my $ticket = $txn->Object;
+        next if $txn->FirstCustomFieldValue( 'Worked Date' );    # we handle this in the next part
+        $ticket_worked{ $ticket->id } ||= { ticket => $ticket, };
+        $ticket_worked{ $ticket->id }{time_worked} += $txn->TimeTaken;
+        $total_time_worked += $txn->TimeTaken;
+    }
+
+    $txns = RT::Transactions->new( $user );
+    $txns->Limit(
+        FIELD => 'ObjectType',
+        VALUE => 'RT::Ticket',
+    );
+    $txns->Limit(
+        FIELD    => 'ObjectID',
+        VALUE    => \@ticket_ids,
+        OPERATOR => 'IN',
+    );
+
+    $txns->Limit(
+        FIELD    => 'TimeTaken',
+        VALUE    => 0,
+        OPERATOR => '!=',
+    );
+
+    my $cf = RT::CustomField->new( $user );
+    $cf->Load( 'Worked Date' );
+    my $cf_alias = $txns->Join(
+        ALIAS1 => 'main',
+        FIELD1 => 'id',
+        TABLE2 => 'ObjectCustomFieldValues',
+        FIELD2 => 'ObjectId'
+    );
+    $txns->Limit( ALIAS => $cf_alias, FIELD => 'CustomField', VALUE => $cf->id );
+    $txns->Limit( ALIAS => $cf_alias, FIELD => 'ObjectType',  VALUE => 'RT::Transaction' );
+    $txns->Limit(
+        ALIAS    => $cf_alias,
+        FIELD    => 'Content',
+        VALUE    => $start_date->ISO( Time => 0, Timezone => 'user' ),
+        OPERATOR => '>='
+    );
+    $txns->Limit(
+        ALIAS           => $cf_alias,
+        FIELD           => 'Content',
+        VALUE           => $exclusive_end_date->ISO( Time => 0, Timezone => 'user' ),
+        OPERATOR        => '<',
+        ENTRYAGGREGATOR => 'AND',
+    );
+
+    while ( my $txn = $txns->Next ) {
+        my $ticket = $txn->Object;
+        $ticket_worked{ $ticket->id } ||= { ticket => $ticket, };
+        $ticket_worked{ $ticket->id }{time_worked} += $txn->TimeTaken;
+        $total_time_worked += $txn->TimeTaken;
+    }
+}
+</%INIT>
+
+<%ARGS>
+$Query => undef
+$StartDate => undef
+$EndDate => undef
+</%ARGS>
diff --git a/static/css/time_tracking.css b/static/css/time_tracking.css
index 7e70767..5a6dba1 100644
--- a/static/css/time_tracking.css
+++ b/static/css/time_tracking.css
@@ -24,6 +24,7 @@ div.time_worked_day {
     right: 5px;
 }
 
+div.time_search div.time_worked,
 div.time_worked_week {
     text-align: right;
 }

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


More information about the Bps-public-commit mailing list