Browse Source

fix(dashboards): Widget Viewer chart y axis formatter for custom metrics (#37810)

Opening a custom metric widget in widget viewer wasn't properly displaying units. Updates widget viewer to accept seriesResultsType for use in yAxis and tooltip formatters.
edwardgou-sentry 2 years ago
parent
commit
564513eec1

+ 3 - 0
static/app/components/modals/widgetViewerModal.tsx

@@ -86,6 +86,7 @@ export interface WidgetViewerModalOptions {
   onEdit?: () => void;
   pageLinks?: string;
   seriesData?: Series[];
+  seriesResultsType?: string;
   tableData?: TableDataWithTitle[];
   totalIssuesCount?: string;
 }
@@ -165,6 +166,7 @@ function WidgetViewerModal(props: Props) {
     tableData,
     totalIssuesCount,
     pageLinks: defaultPageLinks,
+    seriesResultsType,
   } = props;
   const shouldShowSlider = organization.features.includes('widget-viewer-modal-minimap');
   // Get widget zoom from location
@@ -794,6 +796,7 @@ function WidgetViewerModal(props: Props) {
             {(!!seriesData || !!tableData) && chartUnmodified ? (
               <MemoizedWidgetCardChart
                 timeseriesResults={seriesData}
+                timeseriesResultsType={seriesResultsType}
                 tableResults={tableData}
                 errorMessage={undefined}
                 loading={false}

+ 3 - 1
static/app/views/dashboardsV2/detail.tsx

@@ -152,7 +152,8 @@ class DashboardDetail extends Component<Props, State> {
       location,
       router,
     } = this.props;
-    const {seriesData, tableData, pageLinks, totalIssuesCount} = this.state;
+    const {seriesData, tableData, pageLinks, totalIssuesCount, seriesResultsType} =
+      this.state;
     if (isWidgetViewerPath(location.pathname)) {
       const widget =
         defined(widgetId) &&
@@ -163,6 +164,7 @@ class DashboardDetail extends Component<Props, State> {
           organization,
           widget,
           seriesData,
+          seriesResultsType,
           tableData,
           pageLinks,
           totalIssuesCount,

+ 6 - 1
static/app/views/dashboardsV2/widgetCard/genericWidgetQueries.tsx

@@ -38,6 +38,7 @@ export type OnDataFetchedProps = {
   pageLinks?: string;
   tableResults?: TableDataWithTitle[];
   timeseriesResults?: Series[];
+  timeseriesResultsType?: string;
   totalIssuesCount?: string;
 };
 
@@ -76,6 +77,7 @@ export type GenericWidgetQueriesProps<SeriesResponse, TableResponse> = {
     timeseriesResults,
     totalIssuesCount,
     pageLinks,
+    timeseriesResultsType,
   }: OnDataFetchedProps) => void;
 };
 
@@ -345,7 +347,10 @@ class GenericWidgetQueries<SeriesResponse, TableResponse> extends Component<
     );
 
     if (this._isMounted && this.state.queryFetchID === queryFetchID) {
-      onDataFetched?.({timeseriesResults: transformedTimeseriesResults});
+      onDataFetched?.({
+        timeseriesResults: transformedTimeseriesResults,
+        timeseriesResultsType,
+      });
       this.setState({
         timeseriesResults: transformedTimeseriesResults,
         rawResults: rawResultsClone,

+ 7 - 1
static/app/views/dashboardsV2/widgetCard/index.tsx

@@ -72,6 +72,7 @@ type Props = WithRouterProps & {
 type State = {
   pageLinks?: string;
   seriesData?: Series[];
+  seriesResultsType?: string;
   tableData?: TableDataWithTitle[];
   totalIssuesCount?: string;
 };
@@ -163,7 +164,8 @@ class WidgetCard extends Component<Props, State> {
       index,
     } = this.props;
 
-    const {seriesData, tableData, pageLinks, totalIssuesCount} = this.state;
+    const {seriesData, tableData, pageLinks, totalIssuesCount, seriesResultsType} =
+      this.state;
 
     if (isEditing) {
       return null;
@@ -185,6 +187,7 @@ class WidgetCard extends Component<Props, State> {
         location={location}
         index={index}
         seriesData={seriesData}
+        seriesResultsType={seriesResultsType}
         tableData={tableData}
         pageLinks={pageLinks}
         totalIssuesCount={totalIssuesCount}
@@ -197,10 +200,12 @@ class WidgetCard extends Component<Props, State> {
     timeseriesResults,
     totalIssuesCount,
     pageLinks,
+    timeseriesResultsType,
   }: {
     pageLinks?: string;
     tableResults?: TableDataWithTitle[];
     timeseriesResults?: Series[];
+    timeseriesResultsType?: string;
     totalIssuesCount?: string;
   }) => {
     this.setState({
@@ -208,6 +213,7 @@ class WidgetCard extends Component<Props, State> {
       tableData: tableResults,
       totalIssuesCount,
       pageLinks,
+      seriesResultsType: timeseriesResultsType,
     });
   };
 

+ 1 - 0
static/app/views/dashboardsV2/widgetCard/widgetCardChartContainer.tsx

@@ -35,6 +35,7 @@ type Props = WithRouterProps & {
     pageLinks?: string;
     tableResults?: TableDataWithTitle[];
     timeseriesResults?: Series[];
+    timeseriesResultsType?: string;
     totalIssuesCount?: string;
   }) => void;
   onLegendSelectChanged?: EChartEventHandler<{

+ 4 - 0
static/app/views/dashboardsV2/widgetCard/widgetCardContextMenu.tsx

@@ -43,6 +43,7 @@ type Props = {
   onEdit?: () => void;
   pageLinks?: string;
   seriesData?: Series[];
+  seriesResultsType?: string;
   showContextMenu?: boolean;
   showWidgetViewerButton?: boolean;
   tableData?: TableDataWithTitle[];
@@ -67,6 +68,7 @@ function WidgetCardContextMenu({
   tableData,
   pageLinks,
   totalIssuesCount,
+  seriesResultsType,
 }: Props) {
   const {isMetricsData} = useDashboardsMEPContext();
   if (!showContextMenu) {
@@ -134,6 +136,7 @@ function WidgetCardContextMenu({
                       tableData,
                       pageLinks,
                       totalIssuesCount,
+                      seriesResultsType,
                     });
                   openWidgetViewerPath(index);
                 }}
@@ -276,6 +279,7 @@ function WidgetCardContextMenu({
                   tableData,
                   pageLinks,
                   totalIssuesCount,
+                  seriesResultsType,
                 });
                 openWidgetViewerPath(widget.id ?? index);
               }}

+ 2 - 0
static/app/views/dashboardsV2/widgetViewer/widgetViewerContext.tsx

@@ -7,11 +7,13 @@ export type WidgetViewerContextProps = {
   setData: (data: {
     pageLinks?: string;
     seriesData?: Series[];
+    seriesResultsType?: string;
     tableData?: TableDataWithTitle[];
     totalIssuesCount?: string;
   }) => void;
   pageLinks?: string;
   seriesData?: Series[];
+  seriesResultsType?: string;
   tableData?: TableDataWithTitle[];
   totalIssuesCount?: string;
 };

+ 17 - 0
tests/js/spec/components/modals/widgetViewerModal.spec.tsx

@@ -45,11 +45,13 @@ async function renderModal({
   seriesData,
   tableData,
   pageLinks,
+  seriesResultsType,
 }: {
   initialData: any;
   widget: any;
   pageLinks?: string;
   seriesData?: Series[];
+  seriesResultsType?: string;
   tableData?: TableDataWithTitle[];
 }) {
   const rendered = render(
@@ -66,6 +68,7 @@ async function renderModal({
         seriesData={seriesData}
         tableData={tableData}
         pageLinks={pageLinks}
+        seriesResultsType={seriesResultsType}
       />
     </div>,
     {
@@ -509,6 +512,20 @@ describe('Modals -> WidgetViewerModal', function () {
             })
           );
         });
+
+        it('renders widget chart with y axis formatter using provided seriesResultType', async function () {
+          mockEvents();
+          await renderModal({
+            initialData: initialDataWithFlag,
+            widget: mockWidget,
+            seriesData: [],
+            seriesResultsType: 'duration',
+          });
+          const calls = (ReactEchartsCore as jest.Mock).mock.calls;
+          const yAxisFormatter =
+            calls[calls.length - 1][0].option.yAxis.axisLabel.formatter;
+          expect(yAxisFormatter(123)).toEqual('123ms');
+        });
       });
     });