[Rt-commit] rt branch, 4.6/jschart, repushed

? sunnavy sunnavy at bestpractical.com
Wed Jun 26 14:31:39 EDT 2019


The branch 4.6/jschart was deleted and repushed:
       was 5c7a3b5bf4da574ca9d977d9e7d53758fb106420
       now a45902e8eeb3c1b5578990c9dfa96f425e19d7ad

 1: b70293b5e !  1: 332d2d5f2 Add Chart.js 2.8.0 dependency
    @@ -864,155 +864,155 @@
     +
     +var colorConvert = convert;
     +
    -+var colorName = {
    -+	"aliceblue": [240, 248, 255],
    -+	"antiquewhite": [250, 235, 215],
    -+	"aqua": [0, 255, 255],
    -+	"aquamarine": [127, 255, 212],
    -+	"azure": [240, 255, 255],
    -+	"beige": [245, 245, 220],
    -+	"bisque": [255, 228, 196],
    -+	"black": [0, 0, 0],
    -+	"blanchedalmond": [255, 235, 205],
    -+	"blue": [0, 0, 255],
    -+	"blueviolet": [138, 43, 226],
    -+	"brown": [165, 42, 42],
    -+	"burlywood": [222, 184, 135],
    -+	"cadetblue": [95, 158, 160],
    -+	"chartreuse": [127, 255, 0],
    -+	"chocolate": [210, 105, 30],
    -+	"coral": [255, 127, 80],
    -+	"cornflowerblue": [100, 149, 237],
    -+	"cornsilk": [255, 248, 220],
    -+	"crimson": [220, 20, 60],
    -+	"cyan": [0, 255, 255],
    -+	"darkblue": [0, 0, 139],
    -+	"darkcyan": [0, 139, 139],
    -+	"darkgoldenrod": [184, 134, 11],
    -+	"darkgray": [169, 169, 169],
    -+	"darkgreen": [0, 100, 0],
    -+	"darkgrey": [169, 169, 169],
    -+	"darkkhaki": [189, 183, 107],
    -+	"darkmagenta": [139, 0, 139],
    -+	"darkolivegreen": [85, 107, 47],
    -+	"darkorange": [255, 140, 0],
    -+	"darkorchid": [153, 50, 204],
    -+	"darkred": [139, 0, 0],
    -+	"darksalmon": [233, 150, 122],
    -+	"darkseagreen": [143, 188, 143],
    -+	"darkslateblue": [72, 61, 139],
    -+	"darkslategray": [47, 79, 79],
    -+	"darkslategrey": [47, 79, 79],
    -+	"darkturquoise": [0, 206, 209],
    -+	"darkviolet": [148, 0, 211],
    -+	"deeppink": [255, 20, 147],
    -+	"deepskyblue": [0, 191, 255],
    -+	"dimgray": [105, 105, 105],
    -+	"dimgrey": [105, 105, 105],
    -+	"dodgerblue": [30, 144, 255],
    -+	"firebrick": [178, 34, 34],
    -+	"floralwhite": [255, 250, 240],
    -+	"forestgreen": [34, 139, 34],
    -+	"fuchsia": [255, 0, 255],
    -+	"gainsboro": [220, 220, 220],
    -+	"ghostwhite": [248, 248, 255],
    -+	"gold": [255, 215, 0],
    -+	"goldenrod": [218, 165, 32],
    -+	"gray": [128, 128, 128],
    -+	"green": [0, 128, 0],
    -+	"greenyellow": [173, 255, 47],
    -+	"grey": [128, 128, 128],
    -+	"honeydew": [240, 255, 240],
    -+	"hotpink": [255, 105, 180],
    -+	"indianred": [205, 92, 92],
    -+	"indigo": [75, 0, 130],
    -+	"ivory": [255, 255, 240],
    -+	"khaki": [240, 230, 140],
    -+	"lavender": [230, 230, 250],
    -+	"lavenderblush": [255, 240, 245],
    -+	"lawngreen": [124, 252, 0],
    -+	"lemonchiffon": [255, 250, 205],
    -+	"lightblue": [173, 216, 230],
    -+	"lightcoral": [240, 128, 128],
    -+	"lightcyan": [224, 255, 255],
    -+	"lightgoldenrodyellow": [250, 250, 210],
    -+	"lightgray": [211, 211, 211],
    -+	"lightgreen": [144, 238, 144],
    -+	"lightgrey": [211, 211, 211],
    -+	"lightpink": [255, 182, 193],
    -+	"lightsalmon": [255, 160, 122],
    -+	"lightseagreen": [32, 178, 170],
    -+	"lightskyblue": [135, 206, 250],
    -+	"lightslategray": [119, 136, 153],
    -+	"lightslategrey": [119, 136, 153],
    -+	"lightsteelblue": [176, 196, 222],
    -+	"lightyellow": [255, 255, 224],
    -+	"lime": [0, 255, 0],
    -+	"limegreen": [50, 205, 50],
    -+	"linen": [250, 240, 230],
    -+	"magenta": [255, 0, 255],
    -+	"maroon": [128, 0, 0],
    -+	"mediumaquamarine": [102, 205, 170],
    -+	"mediumblue": [0, 0, 205],
    -+	"mediumorchid": [186, 85, 211],
    -+	"mediumpurple": [147, 112, 219],
    -+	"mediumseagreen": [60, 179, 113],
    -+	"mediumslateblue": [123, 104, 238],
    -+	"mediumspringgreen": [0, 250, 154],
    -+	"mediumturquoise": [72, 209, 204],
    -+	"mediumvioletred": [199, 21, 133],
    -+	"midnightblue": [25, 25, 112],
    -+	"mintcream": [245, 255, 250],
    -+	"mistyrose": [255, 228, 225],
    -+	"moccasin": [255, 228, 181],
    -+	"navajowhite": [255, 222, 173],
    -+	"navy": [0, 0, 128],
    -+	"oldlace": [253, 245, 230],
    -+	"olive": [128, 128, 0],
    -+	"olivedrab": [107, 142, 35],
    -+	"orange": [255, 165, 0],
    -+	"orangered": [255, 69, 0],
    -+	"orchid": [218, 112, 214],
    -+	"palegoldenrod": [238, 232, 170],
    -+	"palegreen": [152, 251, 152],
    -+	"paleturquoise": [175, 238, 238],
    -+	"palevioletred": [219, 112, 147],
    -+	"papayawhip": [255, 239, 213],
    -+	"peachpuff": [255, 218, 185],
    -+	"peru": [205, 133, 63],
    -+	"pink": [255, 192, 203],
    -+	"plum": [221, 160, 221],
    -+	"powderblue": [176, 224, 230],
    -+	"purple": [128, 0, 128],
    -+	"rebeccapurple": [102, 51, 153],
    -+	"red": [255, 0, 0],
    -+	"rosybrown": [188, 143, 143],
    -+	"royalblue": [65, 105, 225],
    -+	"saddlebrown": [139, 69, 19],
    -+	"salmon": [250, 128, 114],
    -+	"sandybrown": [244, 164, 96],
    -+	"seagreen": [46, 139, 87],
    -+	"seashell": [255, 245, 238],
    -+	"sienna": [160, 82, 45],
    -+	"silver": [192, 192, 192],
    -+	"skyblue": [135, 206, 235],
    -+	"slateblue": [106, 90, 205],
    -+	"slategray": [112, 128, 144],
    -+	"slategrey": [112, 128, 144],
    -+	"snow": [255, 250, 250],
    -+	"springgreen": [0, 255, 127],
    -+	"steelblue": [70, 130, 180],
    -+	"tan": [210, 180, 140],
    -+	"teal": [0, 128, 128],
    -+	"thistle": [216, 191, 216],
    -+	"tomato": [255, 99, 71],
    -+	"turquoise": [64, 224, 208],
    -+	"violet": [238, 130, 238],
    -+	"wheat": [245, 222, 179],
    -+	"white": [255, 255, 255],
    -+	"whitesmoke": [245, 245, 245],
    -+	"yellow": [255, 255, 0],
    -+	"yellowgreen": [154, 205, 50]
    ++var colorName = {
    ++	"aliceblue": [240, 248, 255],
    ++	"antiquewhite": [250, 235, 215],
    ++	"aqua": [0, 255, 255],
    ++	"aquamarine": [127, 255, 212],
    ++	"azure": [240, 255, 255],
    ++	"beige": [245, 245, 220],
    ++	"bisque": [255, 228, 196],
    ++	"black": [0, 0, 0],
    ++	"blanchedalmond": [255, 235, 205],
    ++	"blue": [0, 0, 255],
    ++	"blueviolet": [138, 43, 226],
    ++	"brown": [165, 42, 42],
    ++	"burlywood": [222, 184, 135],
    ++	"cadetblue": [95, 158, 160],
    ++	"chartreuse": [127, 255, 0],
    ++	"chocolate": [210, 105, 30],
    ++	"coral": [255, 127, 80],
    ++	"cornflowerblue": [100, 149, 237],
    ++	"cornsilk": [255, 248, 220],
    ++	"crimson": [220, 20, 60],
    ++	"cyan": [0, 255, 255],
    ++	"darkblue": [0, 0, 139],
    ++	"darkcyan": [0, 139, 139],
    ++	"darkgoldenrod": [184, 134, 11],
    ++	"darkgray": [169, 169, 169],
    ++	"darkgreen": [0, 100, 0],
    ++	"darkgrey": [169, 169, 169],
    ++	"darkkhaki": [189, 183, 107],
    ++	"darkmagenta": [139, 0, 139],
    ++	"darkolivegreen": [85, 107, 47],
    ++	"darkorange": [255, 140, 0],
    ++	"darkorchid": [153, 50, 204],
    ++	"darkred": [139, 0, 0],
    ++	"darksalmon": [233, 150, 122],
    ++	"darkseagreen": [143, 188, 143],
    ++	"darkslateblue": [72, 61, 139],
    ++	"darkslategray": [47, 79, 79],
    ++	"darkslategrey": [47, 79, 79],
    ++	"darkturquoise": [0, 206, 209],
    ++	"darkviolet": [148, 0, 211],
    ++	"deeppink": [255, 20, 147],
    ++	"deepskyblue": [0, 191, 255],
    ++	"dimgray": [105, 105, 105],
    ++	"dimgrey": [105, 105, 105],
    ++	"dodgerblue": [30, 144, 255],
    ++	"firebrick": [178, 34, 34],
    ++	"floralwhite": [255, 250, 240],
    ++	"forestgreen": [34, 139, 34],
    ++	"fuchsia": [255, 0, 255],
    ++	"gainsboro": [220, 220, 220],
    ++	"ghostwhite": [248, 248, 255],
    ++	"gold": [255, 215, 0],
    ++	"goldenrod": [218, 165, 32],
    ++	"gray": [128, 128, 128],
    ++	"green": [0, 128, 0],
    ++	"greenyellow": [173, 255, 47],
    ++	"grey": [128, 128, 128],
    ++	"honeydew": [240, 255, 240],
    ++	"hotpink": [255, 105, 180],
    ++	"indianred": [205, 92, 92],
    ++	"indigo": [75, 0, 130],
    ++	"ivory": [255, 255, 240],
    ++	"khaki": [240, 230, 140],
    ++	"lavender": [230, 230, 250],
    ++	"lavenderblush": [255, 240, 245],
    ++	"lawngreen": [124, 252, 0],
    ++	"lemonchiffon": [255, 250, 205],
    ++	"lightblue": [173, 216, 230],
    ++	"lightcoral": [240, 128, 128],
    ++	"lightcyan": [224, 255, 255],
    ++	"lightgoldenrodyellow": [250, 250, 210],
    ++	"lightgray": [211, 211, 211],
    ++	"lightgreen": [144, 238, 144],
    ++	"lightgrey": [211, 211, 211],
    ++	"lightpink": [255, 182, 193],
    ++	"lightsalmon": [255, 160, 122],
    ++	"lightseagreen": [32, 178, 170],
    ++	"lightskyblue": [135, 206, 250],
    ++	"lightslategray": [119, 136, 153],
    ++	"lightslategrey": [119, 136, 153],
    ++	"lightsteelblue": [176, 196, 222],
    ++	"lightyellow": [255, 255, 224],
    ++	"lime": [0, 255, 0],
    ++	"limegreen": [50, 205, 50],
    ++	"linen": [250, 240, 230],
    ++	"magenta": [255, 0, 255],
    ++	"maroon": [128, 0, 0],
    ++	"mediumaquamarine": [102, 205, 170],
    ++	"mediumblue": [0, 0, 205],
    ++	"mediumorchid": [186, 85, 211],
    ++	"mediumpurple": [147, 112, 219],
    ++	"mediumseagreen": [60, 179, 113],
    ++	"mediumslateblue": [123, 104, 238],
    ++	"mediumspringgreen": [0, 250, 154],
    ++	"mediumturquoise": [72, 209, 204],
    ++	"mediumvioletred": [199, 21, 133],
    ++	"midnightblue": [25, 25, 112],
    ++	"mintcream": [245, 255, 250],
    ++	"mistyrose": [255, 228, 225],
    ++	"moccasin": [255, 228, 181],
    ++	"navajowhite": [255, 222, 173],
    ++	"navy": [0, 0, 128],
    ++	"oldlace": [253, 245, 230],
    ++	"olive": [128, 128, 0],
    ++	"olivedrab": [107, 142, 35],
    ++	"orange": [255, 165, 0],
    ++	"orangered": [255, 69, 0],
    ++	"orchid": [218, 112, 214],
    ++	"palegoldenrod": [238, 232, 170],
    ++	"palegreen": [152, 251, 152],
    ++	"paleturquoise": [175, 238, 238],
    ++	"palevioletred": [219, 112, 147],
    ++	"papayawhip": [255, 239, 213],
    ++	"peachpuff": [255, 218, 185],
    ++	"peru": [205, 133, 63],
    ++	"pink": [255, 192, 203],
    ++	"plum": [221, 160, 221],
    ++	"powderblue": [176, 224, 230],
    ++	"purple": [128, 0, 128],
    ++	"rebeccapurple": [102, 51, 153],
    ++	"red": [255, 0, 0],
    ++	"rosybrown": [188, 143, 143],
    ++	"royalblue": [65, 105, 225],
    ++	"saddlebrown": [139, 69, 19],
    ++	"salmon": [250, 128, 114],
    ++	"sandybrown": [244, 164, 96],
    ++	"seagreen": [46, 139, 87],
    ++	"seashell": [255, 245, 238],
    ++	"sienna": [160, 82, 45],
    ++	"silver": [192, 192, 192],
    ++	"skyblue": [135, 206, 235],
    ++	"slateblue": [106, 90, 205],
    ++	"slategray": [112, 128, 144],
    ++	"slategrey": [112, 128, 144],
    ++	"snow": [255, 250, 250],
    ++	"springgreen": [0, 255, 127],
    ++	"steelblue": [70, 130, 180],
    ++	"tan": [210, 180, 140],
    ++	"teal": [0, 128, 128],
    ++	"thistle": [216, 191, 216],
    ++	"tomato": [255, 99, 71],
    ++	"turquoise": [64, 224, 208],
    ++	"violet": [238, 130, 238],
    ++	"wheat": [245, 222, 179],
    ++	"white": [255, 255, 255],
    ++	"whitesmoke": [245, 245, 245],
    ++	"yellow": [255, 255, 0],
    ++	"yellowgreen": [154, 205, 50]
     +};
     +
     +/* MIT license */
 2: 967b700b2 =  2: e0a072e3a Add chartjs-plugin-colorschemes.min.js 0.03 dependency
 3: 10f7cf364 =  3: cf7f0e9b9 Initial js chart support
 4: f67715ebb =  4: bcd82d747 Use different colors for bars if the chart only contains a single dataset
 5: ea6ab6cc4 =  5: 88f9f70f5 Set y-axis label only for bar charts
 6: fe85dafee !  6: 21951f2d9 Redirect to ticket search result page via click on each bar/pie
    @@ -14,22 +14,15 @@
      });
     +
     +var group_by = <% JSON( \@GroupBy ) |n %>;
    -+var group_by_values = <% JSON( \@group_by_values ) |n %>;
    ++var data_queries = <% JSON( \@data_queries ) |n %>;
     +
     +jQuery('#search-chart').click(function(e) {
     +    var slice = searchChart.getElementAtEvent(e);
     +    if ( !slice[0] ) return;
     +
     +    var query = <% $Query =~ /^\s*\(.*\)$/ ? $Query : "( $Query )" |n,j %>;
    -+    for ( var i=0; i < group_by.length; i++ ) {
    -+        var value = group_by_values[slice[0]._index][i];
    -+        if ( value == null ) {
    -+            query += ' AND ' + group_by[i] + ' IS NULL';
    -+        }
    -+        else {
    -+            value = value.replace("'", "\\'");
    -+            query += ' AND ' + group_by[i] + ' = ' + "'" + value + "'";
    -+        }
    ++    if ( data_queries[slice[0]._index] ) {
    ++        query += ' AND ( ' + data_queries[slice[0]._index] + ')';
     +    }
     +    window.open(RT.Config.WebPath + '/Search/Results.html?Query=' + encodeURIComponent(query)
     +        + '&' + <% $m->comp('/Elements/QueryString', map { $_ => $DECODED_ARGS->{$_} } grep { $_ ne 'Query' } keys %$DECODED_ARGS) |n,j%>);
    @@ -53,10 +46,10 @@
      
      my @data = ([],[]);
      my @data_labels;
    -+my @group_by_values;
    ++my @data_queries;
      while ( my $entry = $report->Next ) {
          push @{ $data[0] }, [ map $entry->LabelValue( $_ ), @{ $columns{'Groups'} } ];
    -+    push @group_by_values, [ map $entry->RawValue( $_ ), @{ $columns{'Groups'} } ];
    ++    push @data_queries, $entry->Query;
      
          my @values;
          my @label_values;
 8: 2defd29ee !  7: 22873c690 Rename durations like "Created-Started" to "Created to Started" for charts
    @@ -106,129 +106,6 @@
          push @STATISTICS, (
              "ALL($pair)" => ["Summary of $pair", 'DateTimeIntervalAll', $from, $to ],
              "SUM($pair)" => ["Total $pair", 'DateTimeInterval', 'SUM', $from, $to ],
    -@@
    -                     }
    -                 }
    -                 elsif ( $group->{INFO} eq 'Duration' ) {
    --                    my ($start, $end) = split /-/, $group->{FIELD};
    -+                    my ($start, $end) = split / to /, $group->{FIELD}, 2;
    -                     my $start_method = $start . 'Obj';
    -                     my $end_method   = $end . 'Obj';
    - 
    -@@
    -                     elsif ( $field->{INFO}[1] eq 'Time' ) {
    -                         if ( $field->{NAME} =~ /^(TimeWorked|TimeEstimated|TimeLeft)$/ ) {
    -                             my $method = $1;
    -+                            my $type   = $field->{INFO}[2];
    -+                            my $name   = lc $field->{NAME};
    - 
    --                            if ( $field->{INFO}[2] eq 'SUM' ) {
    --                                $info{$key}{ lc $field->{NAME} } += $ticket->$method * 60;
    --                            }
    --                            elsif ( $field->{INFO}[2] eq 'AVG' ) {
    --                                $info{$key}{ lc $field->{NAME} }{total} += $ticket->$method * 60;
    --                                $info{$key}{ lc $field->{NAME} }{count}++;
    --                                $info{$key}{ lc $field->{NAME} }{calculate} = sub {
    --                                    my $item = shift;
    --                                    return sprintf '%.0f', $item->{total} / $item->{count};
    --                                };
    --                            }
    --                            elsif ( $field->{INFO}[2] eq 'MAX' ) {
    --                                $info{$key}{ lc $field->{NAME} } = $ticket->$method * 60
    --                                    unless $info{$key}{ lc $field->{NAME} }
    --                                    && $info{$key}{ lc $field->{NAME} } > $ticket->$method * 60;
    --                            }
    --                            elsif ( $field->{INFO}[2] eq 'MIN' ) {
    --                                $info{$key}{ lc $field->{NAME} } = $ticket->$method * 60
    --                                    unless $info{$key}{ lc $field->{NAME} }
    --                                    && $info{$key}{ lc $field->{NAME} } < $ticket->$method * 60;
    --                            }
    --                            else {
    --                                RT->Logger->error("Unsupported type $field->{INFO}[2]");
    --                            }
    -+                            $info{$key}{$name}
    -+                                = $self->_CalculateTime( $type, $ticket->$method * 60, $info{$key}{$name} ) || 0;
    -                         }
    -                         else {
    -                             RT->Logger->error("Unsupported field $field->{NAME}");
    -@@
    -                     }
    -                     elsif ( $field->{INFO}[1] eq 'DateTimeInterval' ) {
    -                         my ( undef, undef, $type, $start, $end ) = @{ $field->{INFO} };
    -+                        my $name = lc $field->{NAME};
    -+                        $info{$key}{$name} ||= 0;
    - 
    -                         my $start_method = $start . 'Obj';
    -                         my $end_method   = $end . 'Obj';
    -                         next unless $ticket->$end_method->Unix > 0 && $ticket->$start_method->Unix > 0;
    -+
    -                         my $value = $ticket->$end_method->Unix - $ticket->$start_method->Unix;
    --                        if ( $type eq 'SUM' ) {
    --                            $info{$key}{ lc $field->{NAME} } += $value;
    --                        }
    --                        elsif ( $type eq 'AVG' ) {
    --                            $info{$key}{ lc $field->{NAME} }{total} += $value;
    --                            $info{$key}{ lc $field->{NAME} }{count}++;
    --                            $info{$key}{ lc $field->{NAME} }{calculate} = sub {
    --                                my $item = shift;
    --                                return sprintf '%.0f', $item->{total} / $item->{count};
    --                            };
    --                        }
    --                        elsif ( $type eq 'MAX' ) {
    --                            $info{$key}{ lc $field->{NAME} } = $value
    --                                unless $info{$key}{ lc $field->{NAME} }
    --                                && $info{$key}{ lc $field->{NAME} } > $value;
    --                        }
    --                        elsif ( $type eq 'MIN' ) {
    --                            $info{$key}{ lc $field->{NAME} } = $value
    --                                unless $info{$key}{ lc $field->{NAME} }
    --                                && $info{$key}{ lc $field->{NAME} } < $value;
    --                        }
    --                        else {
    --                            RT->Logger->error("Unsupported type $type");
    --                        }
    -+                        next unless $value;
    -+                        $info{$key}{$name} = $self->_CalculateTime( $type, $value, $info{$key}{$name} );
    -                     }
    -                     else {
    -                         RT->Logger->error("Unsupported field $field->{INFO}[1]");
    -@@
    -     return thead => \@head, tbody => \@body, tfoot => \@footer;
    - }
    - 
    -+sub _CalculateTime {
    -+    my $self = shift;
    -+    my ( $type, $value, $current ) = @_;
    -+
    -+    return $current unless defined $value;
    -+
    -+    if ( $type eq 'SUM' ) {
    -+        $current += $value;
    -+    }
    -+    elsif ( $type eq 'AVG' ) {
    -+        $current ||= {};
    -+        $current->{total} += $value;
    -+        $current->{count}++;
    -+        $current->{calculate} ||= sub {
    -+            my $item = shift;
    -+            return sprintf '%.0f', $item->{total} / $item->{count};
    -+        };
    -+    }
    -+    elsif ( $type eq 'MAX' ) {
    -+        $current = $value unless $current && $current > $value;
    -+    }
    -+    elsif ( $type eq 'MIN' ) {
    -+        $current = $value unless $current && $current < $value;
    -+    }
    -+    else {
    -+        RT->Logger->error("Unsupported type $type");
    -+    }
    -+    return $current;
    -+}
    -+
    - RT::Base->_ImportOverlays();
    - 
    - 1;
     
     diff --git a/t/charts/compound-sql-function.t b/t/charts/compound-sql-function.t
     --- a/t/charts/compound-sql-function.t
 7: 48098f16e !  8: 7ff12bab0 Add duration group bys like "Created to Resolved" for charts
    @@ -1,6 +1,6 @@
     Author: sunnavy <sunnavy at bestpractical.com>
     
    -    Support group by durations like "Created-Resolved" for charts
    +    Add duration group bys like "Created to Resolved" for charts
     
     diff --git a/lib/RT/Report/Tickets.pm b/lib/RT/Report/Tickets.pm
     --- a/lib/RT/Report/Tickets.pm
    @@ -131,7 +131,7 @@
     +                    }
     +                }
     +                elsif ( $group->{INFO} eq 'Duration' ) {
    -+                    my ($start, $end) = split /-/, $group->{FIELD};
    ++                    my ($start, $end) = split / to /, $group->{FIELD}, 2;
     +                    my $start_method = $start . 'Obj';
     +                    my $end_method   = $end . 'Obj';
     +
    @@ -212,31 +212,11 @@
     +                    elsif ( $field->{INFO}[1] eq 'Time' ) {
     +                        if ( $field->{NAME} =~ /^(TimeWorked|TimeEstimated|TimeLeft)$/ ) {
     +                            my $method = $1;
    -+
    -+                            if ( $field->{INFO}[2] eq 'SUM' ) {
    -+                                $info{$key}{ lc $field->{NAME} } += $ticket->$method * 60;
    -+                            }
    -+                            elsif ( $field->{INFO}[2] eq 'AVG' ) {
    -+                                $info{$key}{ lc $field->{NAME} }{total} += $ticket->$method * 60;
    -+                                $info{$key}{ lc $field->{NAME} }{count}++;
    -+                                $info{$key}{ lc $field->{NAME} }{calculate} = sub {
    -+                                    my $item = shift;
    -+                                    return sprintf '%.0f', $item->{total} / $item->{count};
    -+                                };
    -+                            }
    -+                            elsif ( $field->{INFO}[2] eq 'MAX' ) {
    -+                                $info{$key}{ lc $field->{NAME} } = $ticket->$method * 60
    -+                                    unless $info{$key}{ lc $field->{NAME} }
    -+                                    && $info{$key}{ lc $field->{NAME} } > $ticket->$method * 60;
    -+                            }
    -+                            elsif ( $field->{INFO}[2] eq 'MIN' ) {
    -+                                $info{$key}{ lc $field->{NAME} } = $ticket->$method * 60
    -+                                    unless $info{$key}{ lc $field->{NAME} }
    -+                                    && $info{$key}{ lc $field->{NAME} } < $ticket->$method * 60;
    -+                            }
    -+                            else {
    -+                                RT->Logger->error("Unsupported type $field->{INFO}[2]");
    -+                            }
    ++                            my $type   = $field->{INFO}[2];
    ++                            my $name   = lc $field->{NAME};
    ++
    ++                            $info{$key}{$name}
    ++                                = $self->_CalculateTime( $type, $ticket->$method * 60, $info{$key}{$name} ) || 0;
     +                        }
     +                        else {
     +                            RT->Logger->error("Unsupported field $field->{NAME}");
    @@ -244,40 +224,26 @@
     +                    }
     +                    elsif ( $field->{INFO}[1] eq 'DateTimeInterval' ) {
     +                        my ( undef, undef, $type, $start, $end ) = @{ $field->{INFO} };
    ++                        my $name = lc $field->{NAME};
    ++                        $info{$key}{$name} ||= 0;
     +
     +                        my $start_method = $start . 'Obj';
     +                        my $end_method   = $end . 'Obj';
     +                        next unless $ticket->$end_method->Unix > 0 && $ticket->$start_method->Unix > 0;
    ++
     +                        my $value = $ticket->$end_method->Unix - $ticket->$start_method->Unix;
    -+                        if ( $type eq 'SUM' ) {
    -+                            $info{$key}{ lc $field->{NAME} } += $value;
    -+                        }
    -+                        elsif ( $type eq 'AVG' ) {
    -+                            $info{$key}{ lc $field->{NAME} }{total} += $value;
    -+                            $info{$key}{ lc $field->{NAME} }{count}++;
    -+                            $info{$key}{ lc $field->{NAME} }{calculate} = sub {
    -+                                my $item = shift;
    -+                                return sprintf '%.0f', $item->{total} / $item->{count};
    -+                            };
    -+                        }
    -+                        elsif ( $type eq 'MAX' ) {
    -+                            $info{$key}{ lc $field->{NAME} } = $value
    -+                                unless $info{$key}{ lc $field->{NAME} }
    -+                                && $info{$key}{ lc $field->{NAME} } > $value;
    -+                        }
    -+                        elsif ( $type eq 'MIN' ) {
    -+                            $info{$key}{ lc $field->{NAME} } = $value
    -+                                unless $info{$key}{ lc $field->{NAME} }
    -+                                && $info{$key}{ lc $field->{NAME} } < $value;
    -+                        }
    -+                        else {
    -+                            RT->Logger->error("Unsupported type $type");
    -+                        }
    ++                        next unless $value;
    ++                        $info{$key}{$name} = $self->_CalculateTime( $type, $value, $info{$key}{$name} );
     +                    }
     +                    else {
     +                        RT->Logger->error("Unsupported field $field->{INFO}[1]");
     +                    }
     +                }
    ++            }
    ++
    ++            for my $keys (@all_keys) {
    ++                my $key = join ';;;', @$keys;
    ++                push @{ $info{$key}{ids} }, $ticket->id;
     +            }
     +        }
     +
    @@ -322,11 +288,59 @@
              } else {
                  $RT::Logger->error("Unknown sorting function '$order'");
                  next;
    +@@
    +     return thead => \@head, tbody => \@body, tfoot => \@footer;
    + }
    + 
    ++sub _CalculateTime {
    ++    my $self = shift;
    ++    my ( $type, $value, $current ) = @_;
    ++
    ++    return $current unless defined $value;
    ++
    ++    if ( $type eq 'SUM' ) {
    ++        $current += $value;
    ++    }
    ++    elsif ( $type eq 'AVG' ) {
    ++        $current ||= {};
    ++        $current->{total} += $value;
    ++        $current->{count}++;
    ++        $current->{calculate} ||= sub {
    ++            my $item = shift;
    ++            return sprintf '%.0f', $item->{total} / $item->{count};
    ++        };
    ++    }
    ++    elsif ( $type eq 'MAX' ) {
    ++        $current = $value unless $current && $current > $value;
    ++    }
    ++    elsif ( $type eq 'MIN' ) {
    ++        $current = $value unless $current && $current < $value;
    ++    }
    ++    else {
    ++        RT->Logger->error("Unsupported type $type");
    ++    }
    ++    return $current;
    ++}
    ++
    + RT::Base->_ImportOverlays();
    + 
    + 1;
     
     diff --git a/lib/RT/Report/Tickets/Entry.pm b/lib/RT/Report/Tickets/Entry.pm
     --- a/lib/RT/Report/Tickets/Entry.pm
     +++ b/lib/RT/Report/Tickets/Entry.pm
     @@
    + sub Query {
    +     my $self = shift;
    + 
    ++    if ( my $ids = $self->{values}{ids} ) {
    ++        return join ' OR ', map "id=$_", @$ids;
    ++    }
    ++
    +     my @parts;
    +     foreach my $column ( $self->Report->ColumnsList ) {
    +         my $info = $self->Report->ColumnInfo( $column );
    +@@
          return $_[0]->{'report'};
      }
      
    @@ -336,27 +350,47 @@
     +
     +    return 0 unless $value;
     +
    -+    if ( $value =~ /(\d+)(?:s| second)/ ) {
    -+        return $1;
    -+    }
    -+    elsif ( $value =~ /(\d+)(?:m| minute)/ ) {
    -+        return $1 * $RT::Date::MINUTE;
    -+    }
    -+    elsif ( $value =~ /(\d+)(?:h| hour)/ ) {
    -+        return $1 * $RT::Date::HOUR;
    -+    }
    -+    elsif ( $value =~ /(\d+)(?:d| day)/ ) {
    -+        return $1 * $RT::Date::DAY;
    -+    }
    -+    elsif ( $value =~ /(\d+)(?:W| week)/ ) {
    -+        return $1 * $RT::Date::WEEK;
    -+    }
    -+    elsif ( $value =~ /(\d+)(?:M| month)/ ) {
    -+        return $1 * $RT::Date::MONTH;
    -+    }
    -+    elsif ( $value =~ /(\d+)(?:Y| year)/ ) {
    -+        return $1 * $RT::Date::YEAR;
    -+    }
    ++    my $number;
    ++    my $unit;
    ++    if ( $value =~ /([\d,]+)(?:s| second)/ ) {
    ++        $number = $1;
    ++        $unit = 1;
    ++    }
    ++    elsif ( $value =~ /([\d,]+)(?:m| minute)/ ) {
    ++        $number = $1;
    ++        $unit = $RT::Date::MINUTE;
    ++    }
    ++    elsif ( $value =~ /([\d,]+)(?:h| hour)/ ) {
    ++        $number = $1;
    ++        $unit = $RT::Date::HOUR;
    ++    }
    ++    elsif ( $value =~ /([\d,]+)(?:d| day)/ ) {
    ++        $number = $1;
    ++        $unit = $RT::Date::DAY;
    ++    }
    ++    elsif ( $value =~ /([\d,]+)(?:W| week)/ ) {
    ++        $number = $1;
    ++        $unit = $RT::Date::WEEK;
    ++    }
    ++    elsif ( $value =~ /([\d,]+)(?:M| month)/ ) {
    ++        $number = $1;
    ++        $unit = $RT::Date::MONTH;
    ++    }
    ++    elsif ( $value =~ /([\d,]+)(?:Y| year)/ ) {
    ++        $number = $1;
    ++        $unit = $RT::Date::YEAR;
    ++    }
    ++    else {
    ++        return -.1; # Mark "(no value)" as -1 so it comes before 0
    ++    }
    ++
    ++    $number =~ s!,!!g;
    ++    my $seconds = $number * $unit;
    ++
    ++    if ( $value =~ /([<|>])/ ) {
    ++        $seconds += $1 eq '<' ? -1 : 1;
    ++    }
    ++    return $seconds;
     +}
     +
      RT::Base->_ImportOverlays();
 9: 8c92acc4e < --:  ------- Add business hours support for charts
--:  ------- >  9: cb17cf350 Enhance DurationAsString with various unit limitations
--:  ------- > 10: 55e33782c Add business hours support for charts
--:  ------- > 11: fc0cb9188 Add Subfields support to duration group bys for charts
10: 7cafd9330 ! 12: 8fd829ea4 Add custom date ranges support for charts
    @@ -15,22 +15,13 @@
      
      __PACKAGE__->RegisterCustomFieldJoin(@$_) for
     @@
    -         Show     => 1,
    -         Sort     => 'duration',
    -     },
    -+    CustomDateRange => {
    -+        Localize => 1,
    -+        Short    => 0,
    -+        Show     => 1,
    -+        Sort     => 'duration',
    -+    },
    - );
    - 
    - # loc'able strings below generated with (s/loq/loc/):
    -@@
              },
              Display => 'DurationAsString',
          },
    ++    CustomDateRange => {
    ++        Display => 'DurationAsString',
    ++        Function => sub {}, # Placeholder to use the same DateTimeInterval handling
    ++    },
     +    CustomDateRangeAll => {
     +        SubValues => sub { return ('Minimum', 'Average', 'Maximum', 'Total') },
     +        Function => sub {
    @@ -46,10 +37,6 @@
     +        },
     +        Display => 'DurationAsString',
     +    },
    -+    CustomDateRange => {
    -+        Display => 'DurationAsString',
    -+        Function => sub {}, # Placeholder to use the same DateTimeInterval handling
    -+    },
      );
      
      sub Groupings {
    @@ -61,24 +48,39 @@
     +        && ( grep( { $_->{INFO} =~ /Duration|CustomDateRange/ } map { $column_info{$_} } @{ $res{Groups} } )
     +            || grep( { $_->{TYPE} eq 'statistic' && ref $_->{INFO} && $_->{INFO}[1] =~ /CustomDateRange/ }
     +                values %column_info )
    -             || grep( { $_->{TYPE} eq 'statistic' && ref $_->{INFO} && $_->{INFO}[-1] eq 'business_time' }
    +             || grep( { $_->{TYPE} eq 'statistic' && ref $_->{INFO} && ref $_->{INFO}[-1] && $_->{INFO}[-1]{business_time} }
                      values %column_info ) )
             )
     @@
    -                         $value = $self->loc('(no value)');
    +                             }
    +                         }
                          }
    -                 }
    -+                elsif ( $group->{INFO} eq 'CustomDateRange' ) {
    -+                    if ( my $config = RT->Config->Get('CustomDateRanges') ) {
    -+                        if ( my $spec = $config->{'RT::Ticket'}{$group->{FIELD}} ) {
    -+                            $value = $ticket->CustomDateRange($group->{FIELD}, $spec );
    ++                    else {
    ++                        my %ranges = RT::Ticket->CustomDateRanges;
    ++                        if ( my $spec = $ranges{$group->{FIELD}} ) {
    ++                            if ( $group->{SUBKEY} eq 'Default' ) {
    ++                                $value = $ticket->CustomDateRange( $group->{FIELD}, $spec );
    ++                            }
    ++                            else {
    ++                                my $seconds = $ticket->CustomDateRange( $group->{FIELD},
    ++                                    { ref $spec ? %$spec : ( value => $spec ), format => sub { $_[0] } } );
    ++
    ++                                if ( defined $seconds ) {
    ++                                    $value = RT::Date->new( $self->CurrentUser )->DurationAsString(
    ++                                        $seconds,
    ++                                        Show    => $group->{META}{Show} // 3,
    ++                                        Short   => $group->{META}{Short} // 1,
    ++                                        MaxUnit => lc $group->{SUBKEY},
    ++                                        MinUnit => lc $group->{SUBKEY},
    ++                                        Unit    => lc $group->{SUBKEY},
    ++                                    );
    ++                                }
    ++                            }
     +                        }
     +                    }
    -+                    $value //= $self->loc('(no value)');
    -+                }
    -                 else {
    -                     RT->Logger->error("Unsupported group by $group->{KEY}");
    -                     next;
    + 
    +                     $value //= $self->loc('(no value)');
    +                 }
     @@
      
                              $info{$key}{$name} = $self->_CalculateTime( $type, $value, $info{$key}{$name} );
    @@ -89,16 +91,15 @@
     +                        $info{$key}{$name} ||= 0;
     +
     +                        my $value;
    -+                        if ( my $config = RT->Config->Get('CustomDateRanges') ) {
    -+                            if ( my $spec = $config->{'RT::Ticket'}{$range_name} ) {
    -+                                $value = $ticket->CustomDateRange(
    -+                                    $range_name,
    -+                                    {
    -+                                        ref $spec eq 'HASH' ? %$spec : ( value => $spec ),
    -+                                        format => sub { $_[0] },
    -+                                    }
    -+                                );
    -+                            }
    ++                        my %ranges = RT::Ticket->CustomDateRanges;
    ++                        if ( my $spec = $ranges{$range_name} ) {
    ++                            $value = $ticket->CustomDateRange(
    ++                                $range_name,
    ++                                {
    ++                                    ref $spec eq 'HASH' ? %$spec : ( value => $spec ),
    ++                                    format => sub { $_[0] },
    ++                                }
    ++                            );
     +                        }
     +                        $info{$key}{$name} = $self->_CalculateTime( $type, $value, $info{$key}{$name} );
     +                    }
    @@ -113,27 +114,25 @@
     +    my $self = shift;
     +    state $setup_custom_date_ranges = 1;
     +    if ($setup_custom_date_ranges) {
    -+        if ( my $config = RT->Config->Get('CustomDateRanges') ) {
    -+            if ( $config->{'RT::Ticket'} ) {
    -+                for my $name ( sort keys %{ $config->{'RT::Ticket'} } ) {
    -+                    my @extra_info;
    -+                    if ( ref $config->{'RT::Ticket'}{$name}
    -+                        && $config->{'RT::Ticket'}{$name}{business_time} )
    -+                    {
    -+                        push @extra_info, 'business_time';
    -+                    }
     +
    -+                    push @GROUPINGS, $name => 'CustomDateRange';
    -+                    push @STATISTICS,
    -+                        (
    -+                        "ALL($name)" => [ "Summary of $name", 'CustomDateRangeAll', $name, @extra_info ],
    -+                        "SUM($name)" => [ "Total $name",   'CustomDateRange', 'SUM', $name, @extra_info ],
    -+                        "AVG($name)" => [ "Average $name", 'CustomDateRange', 'AVG', $name, @extra_info ],
    -+                        "MIN($name)" => [ "Minimum $name", 'CustomDateRange', 'MIN', $name, @extra_info ],
    -+                        "MAX($name)" => [ "Maximum $name", 'CustomDateRange', 'MAX', $name, @extra_info ],
    -+                        );
    -+                }
    ++        my %ranges = RT::Ticket->CustomDateRanges;
    ++        for my $name ( sort keys %ranges ) {
    ++            my %extra_info;
    ++            my $spec = $ranges{$name};
    ++            if ( ref $spec && $spec->{business_time} )
    ++            {
    ++                $extra_info{business_time} = 1;
     +            }
    ++
    ++            push @GROUPINGS, $name => $extra_info{business_time} ? 'DurationInBusinessHours' : 'Duration';
    ++            push @STATISTICS,
    ++                (
    ++                "ALL($name)" => [ "Summary of $name", 'CustomDateRangeAll', $name, \%extra_info ],
    ++                "SUM($name)" => [ "Total $name",   'CustomDateRange', 'SUM', $name, \%extra_info ],
    ++                "AVG($name)" => [ "Average $name", 'CustomDateRange', 'AVG', $name, \%extra_info ],
    ++                "MIN($name)" => [ "Minimum $name", 'CustomDateRange', 'MIN', $name, \%extra_info ],
    ++                "MAX($name)" => [ "Maximum $name", 'CustomDateRange', 'MAX', $name, \%extra_info ],
    ++                );
     +        }
     +        $setup_custom_date_ranges = 0;
     +    }
11: 5c7a3b5bf < --:  ------- Use hour as the max unit of business time
--:  ------- > 13: 713b5478e Use hour as the max unit of business time for custom date ranges
--:  ------- > 14: dc6ffc60e Drop background colors in table head for ChartTable
--:  ------- > 15: a45902e8e Add line chart type support



More information about the rt-commit mailing list