Browse Source

feat(workflow): Preserve utc in query params from issue stream (#32846)

Scott Cooper 3 years ago
parent
commit
5f1dd17d69

+ 9 - 5
static/app/components/stream/group.tsx

@@ -2,6 +2,7 @@ import * as React from 'react';
 import {css, Theme} from '@emotion/react';
 import styled from '@emotion/styled';
 import classNames from 'classnames';
+import type {LocationDescriptor} from 'history';
 
 import AssigneeSelector from 'sentry/components/assigneeSelector';
 import GuideAnchor from 'sentry/components/assistant/guideAnchor';
@@ -223,7 +224,7 @@ class StreamGroup extends React.Component<Props, State> {
     SelectedGroupStore.toggleSelect(this.state.data.id);
   };
 
-  getDiscoverUrl(isFiltered?: boolean) {
+  getDiscoverUrl(isFiltered?: boolean): LocationDescriptor {
     const {organization, query, selection, customStatsPeriod} = this.props;
     const {data} = this.state;
 
@@ -253,7 +254,7 @@ class StreamGroup extends React.Component<Props, State> {
     const searchQuery = (queryTerms.length ? ' ' : '') + queryTerms.join(' ');
 
     if (hasDiscoverQuery) {
-      const {period, start, end} = customStatsPeriod ?? (selection.datetime || {});
+      const {period, start, end, utc} = customStatsPeriod ?? (selection.datetime || {});
 
       const discoverQuery: NewQuery = {
         ...commonQuery,
@@ -266,8 +267,11 @@ class StreamGroup extends React.Component<Props, State> {
       };
 
       if (!!start && !!end) {
-        discoverQuery.start = String(start);
-        discoverQuery.end = String(end);
+        discoverQuery.start = new Date(start).toISOString();
+        discoverQuery.end = new Date(end).toISOString();
+        if (utc) {
+          discoverQuery.utc = true;
+        }
       } else {
         discoverQuery.range = period || DEFAULT_STATS_PERIOD;
       }
@@ -695,7 +699,7 @@ const StyledDropdownList = styled('ul')`
 `;
 
 interface MenuItemProps extends React.HTMLAttributes<HTMLDivElement> {
-  to?: React.ComponentProps<typeof Link>['to'];
+  to?: LocationDescriptor;
 }
 
 const StyledMenuItem = styled(({to, children, ...p}: MenuItemProps) => (

+ 1 - 0
static/app/types/organization.tsx

@@ -166,6 +166,7 @@ export type NewQuery = {
 
   teams?: Readonly<('myteams' | number)[]>;
   topEvents?: string;
+  utc?: boolean | string;
   widths?: Readonly<string[]>;
 
   // Graph

+ 8 - 2
static/app/utils/discover/eventView.tsx

@@ -268,6 +268,7 @@ class EventView {
   start: string | undefined;
   end: string | undefined;
   statsPeriod: string | undefined;
+  utc?: string | boolean | undefined;
   environment: Readonly<string[]>;
   yAxis: string | undefined;
   display: string | undefined;
@@ -296,6 +297,7 @@ class EventView {
     yAxis: string | undefined;
     expired?: boolean;
     interval?: string;
+    utc?: string | boolean | undefined;
   }) {
     const fields: Field[] = Array.isArray(props.fields) ? props.fields : [];
     let sorts: Sort[] = Array.isArray(props.sorts) ? props.sorts : [];
@@ -334,6 +336,7 @@ class EventView {
     this.start = props.start;
     this.end = props.end;
     this.statsPeriod = props.statsPeriod;
+    this.utc = props.utc;
     this.environment = environment;
     this.yAxis = props.yAxis;
     this.display = props.display;
@@ -411,10 +414,11 @@ class EventView {
   static fromSavedQuery(saved: NewQuery | SavedQuery): EventView {
     const fields = EventView.getFields(saved);
     // normalize datetime selection
-    const {start, end, statsPeriod} = normalizeDateTimeParams({
+    const {start, end, statsPeriod, utc} = normalizeDateTimeParams({
       start: saved.start,
       end: saved.end,
       statsPeriod: saved.range,
+      utc: saved.utc,
     });
 
     return new EventView({
@@ -427,6 +431,7 @@ class EventView {
       start: decodeScalar(start),
       end: decodeScalar(end),
       statsPeriod: decodeScalar(statsPeriod),
+      utc,
       sorts: fromSorts(saved.orderby),
       environment: collectQueryStringByKey(
         {
@@ -449,7 +454,7 @@ class EventView {
     location: Location
   ): EventView {
     let fields = decodeFields(location);
-    const {start, end, statsPeriod} = normalizeDateTimeParams(location.query);
+    const {start, end, statsPeriod, utc} = normalizeDateTimeParams(location.query);
     const id = decodeScalar(location.query.id);
     const teams = decodeTeams(location);
     const projects = decodeProjects(location);
@@ -493,6 +498,7 @@ class EventView {
         start: decodeScalar(start),
         end: decodeScalar(end),
         statsPeriod: decodeScalar(statsPeriod),
+        utc,
       });
     }
     return EventView.fromLocation(location);

+ 1 - 0
static/app/views/alerts/rules/details/constants.tsx

@@ -28,4 +28,5 @@ export type TimePeriodType = {
   period: string;
   start: string;
   custom?: boolean;
+  utc?: boolean;
 };

+ 26 - 1
tests/js/spec/utils/discover/eventView.spec.jsx

@@ -408,7 +408,7 @@ describe('EventView.fromSavedQuery()', function () {
       orderby: '-id',
       environment: ['staging'],
       display: 'previous',
-      yAxis: ['count()', 'failure_count()'],
+      yAxis: ['count()'],
     };
     const eventView = EventView.fromSavedQuery(saved);
 
@@ -431,6 +431,31 @@ describe('EventView.fromSavedQuery()', function () {
       display: 'previous',
     });
   });
+
+  it('preserves utc with start/end', function () {
+    const saved = {
+      name: 'best query',
+      query: 'event.type:transaction',
+      fields: ['count()', 'title'],
+      start: '2019-10-20T21:02:51+0000',
+      end: '2019-10-23T19:27:04+0000',
+      utc: 'true',
+    };
+    const eventView = EventView.fromSavedQuery(saved);
+
+    expect(eventView).toMatchObject({
+      id: saved.id,
+      name: saved.name,
+      fields: [
+        {field: 'count()', width: COL_WIDTH_UNDEFINED},
+        {field: 'title', width: COL_WIDTH_UNDEFINED},
+      ],
+      query: 'event.type:transaction',
+      start: '2019-10-20T21:02:51.000',
+      end: '2019-10-23T19:27:04.000',
+      utc: 'true',
+    });
+  });
 });
 
 describe('EventView.fromNewQueryWithLocation()', function () {