[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