|
@@ -8,7 +8,6 @@ import Alert from 'sentry/components/alert';
|
|
|
import TransparentLoadingMask from 'sentry/components/charts/transparentLoadingMask';
|
|
|
import EmptyMessage from 'sentry/components/emptyMessage';
|
|
|
import LoadingIndicator from 'sentry/components/loadingIndicator';
|
|
|
-import {normalizeDateTimeParams} from 'sentry/components/organizations/pageFilters/parse';
|
|
|
import Panel from 'sentry/components/panels/panel';
|
|
|
import PanelBody from 'sentry/components/panels/panelBody';
|
|
|
import {IconSearch} from 'sentry/icons';
|
|
@@ -25,6 +24,7 @@ import {parseMRI} from 'sentry/utils/metrics/mri';
|
|
|
import {useMetricsDataZoom} from 'sentry/utils/metrics/useMetricsData';
|
|
|
import theme from 'sentry/utils/theme';
|
|
|
import {MetricChart} from 'sentry/views/ddm/chart';
|
|
|
+import {FocusArea} from 'sentry/views/ddm/chartBrush';
|
|
|
import {MetricWidgetContextMenu} from 'sentry/views/ddm/contextMenu';
|
|
|
import {QueryBuilder} from 'sentry/views/ddm/queryBuilder';
|
|
|
import {SummaryTable} from 'sentry/views/ddm/summaryTable';
|
|
@@ -41,19 +41,26 @@ export const MetricWidget = memo(
|
|
|
isSelected,
|
|
|
onSelect,
|
|
|
onChange,
|
|
|
- numberOfSiblings,
|
|
|
+ hasSiblings,
|
|
|
+ addFocusArea,
|
|
|
+ removeFocusArea,
|
|
|
+ focusArea,
|
|
|
}: {
|
|
|
+ addFocusArea: (area: FocusArea) => void;
|
|
|
datetime: PageFilters['datetime'];
|
|
|
environments: PageFilters['environments'];
|
|
|
+ focusArea: FocusArea | null;
|
|
|
+ hasSiblings: boolean;
|
|
|
index: number;
|
|
|
isSelected: boolean;
|
|
|
- numberOfSiblings: number;
|
|
|
onChange: (index: number, data: Partial<MetricWidgetQueryParams>) => void;
|
|
|
onSelect: (index: number) => void;
|
|
|
projects: PageFilters['projects'];
|
|
|
+ removeFocusArea: () => void;
|
|
|
widget: MetricWidgetQueryParams;
|
|
|
}) => {
|
|
|
const [isEdit, setIsEdit] = useState(true);
|
|
|
+
|
|
|
const handleChange = useCallback(
|
|
|
(data: Partial<MetricWidgetQueryParams>) => {
|
|
|
onChange(index, data);
|
|
@@ -80,7 +87,16 @@ export const MetricWidget = memo(
|
|
|
environments,
|
|
|
title: widget.title,
|
|
|
}),
|
|
|
- [widget, projects, datetime, environments]
|
|
|
+ [
|
|
|
+ widget.mri,
|
|
|
+ widget.query,
|
|
|
+ widget.op,
|
|
|
+ widget.groupBy,
|
|
|
+ widget.title,
|
|
|
+ projects,
|
|
|
+ datetime,
|
|
|
+ environments,
|
|
|
+ ]
|
|
|
);
|
|
|
|
|
|
const shouldDisplayEditControls = (isEdit && isSelected) || !metricsQuery.mri;
|
|
@@ -88,8 +104,8 @@ export const MetricWidget = memo(
|
|
|
return (
|
|
|
<MetricWidgetPanel
|
|
|
// show the selection border only if we have more widgets than one
|
|
|
- isHighlighted={isSelected && !!numberOfSiblings}
|
|
|
- isHighlightable={!!numberOfSiblings}
|
|
|
+ isHighlighted={isSelected && !!hasSiblings}
|
|
|
+ isHighlightable={!!hasSiblings}
|
|
|
onClick={() => onSelect(index)}
|
|
|
>
|
|
|
<PanelBody>
|
|
@@ -117,6 +133,9 @@ export const MetricWidget = memo(
|
|
|
projects={projects}
|
|
|
environments={environments}
|
|
|
onChange={handleChange}
|
|
|
+ addFocusArea={addFocusArea}
|
|
|
+ focusArea={focusArea}
|
|
|
+ removeFocusArea={removeFocusArea}
|
|
|
{...widget}
|
|
|
/>
|
|
|
) : (
|
|
@@ -136,12 +155,14 @@ export const MetricWidget = memo(
|
|
|
|
|
|
const MetricWidgetHeader = styled('div')`
|
|
|
display: flex;
|
|
|
-
|
|
|
justify-content: space-between;
|
|
|
`;
|
|
|
|
|
|
interface MetricWidgetProps extends MetricWidgetQueryParams {
|
|
|
+ addFocusArea: (area: FocusArea) => void;
|
|
|
+ focusArea: FocusArea | null;
|
|
|
onChange: (data: Partial<MetricWidgetQueryParams>) => void;
|
|
|
+ removeFocusArea: () => void;
|
|
|
widgetIndex: number;
|
|
|
}
|
|
|
|
|
@@ -152,6 +173,9 @@ const MetricWidgetBody = memo(
|
|
|
focusedSeries,
|
|
|
sort,
|
|
|
widgetIndex,
|
|
|
+ addFocusArea,
|
|
|
+ focusArea,
|
|
|
+ removeFocusArea,
|
|
|
...metricsQuery
|
|
|
}: MetricWidgetProps & PageFilters) => {
|
|
|
const {mri, op, query, groupBy, projects, environments, datetime} = metricsQuery;
|
|
@@ -192,16 +216,23 @@ const MetricWidgetBody = memo(
|
|
|
[focusedSeries, onChange, setHoveredSeries]
|
|
|
);
|
|
|
|
|
|
- const chartSeries = useMemo(
|
|
|
- () =>
|
|
|
+ const chartSeries = useMemo(() => {
|
|
|
+ return (
|
|
|
data &&
|
|
|
getChartSeries(data, {
|
|
|
mri,
|
|
|
focusedSeries,
|
|
|
groupBy: metricsQuery.groupBy,
|
|
|
displayType,
|
|
|
- }),
|
|
|
- [data, displayType, focusedSeries, metricsQuery.groupBy, mri]
|
|
|
+ })
|
|
|
+ );
|
|
|
+ }, [data, displayType, focusedSeries, metricsQuery.groupBy, mri]);
|
|
|
+
|
|
|
+ const handleSortChange = useCallback(
|
|
|
+ newSort => {
|
|
|
+ onChange({sort: newSort});
|
|
|
+ },
|
|
|
+ [onChange]
|
|
|
);
|
|
|
|
|
|
if (!chartSeries || !data || isError) {
|
|
@@ -237,15 +268,15 @@ const MetricWidgetBody = memo(
|
|
|
series={chartSeries}
|
|
|
displayType={displayType}
|
|
|
operation={metricsQuery.op}
|
|
|
- {...normalizeChartTimeParams(data)}
|
|
|
widgetIndex={widgetIndex}
|
|
|
+ addFocusArea={addFocusArea}
|
|
|
+ focusArea={focusArea}
|
|
|
+ removeFocusArea={removeFocusArea}
|
|
|
/>
|
|
|
{metricsQuery.showSummaryTable && (
|
|
|
<SummaryTable
|
|
|
series={chartSeries}
|
|
|
- onSortChange={newSort => {
|
|
|
- onChange({sort: newSort});
|
|
|
- }}
|
|
|
+ onSortChange={handleSortChange}
|
|
|
sort={sort}
|
|
|
operation={metricsQuery.op}
|
|
|
onRowClick={toggleSeriesVisibility}
|
|
@@ -342,39 +373,6 @@ function getChartColorPalette(displayType: MetricDisplayType, length: number) {
|
|
|
return palette.toReversed();
|
|
|
}
|
|
|
|
|
|
-function normalizeChartTimeParams(data: MetricsApiResponse) {
|
|
|
- const {
|
|
|
- start,
|
|
|
- end,
|
|
|
- utc: utcString,
|
|
|
- statsPeriod,
|
|
|
- } = normalizeDateTimeParams(data, {
|
|
|
- allowEmptyPeriod: true,
|
|
|
- allowAbsoluteDatetime: true,
|
|
|
- allowAbsolutePageDatetime: true,
|
|
|
- });
|
|
|
-
|
|
|
- const utc = utcString === 'true';
|
|
|
-
|
|
|
- if (start && end) {
|
|
|
- return utc
|
|
|
- ? {
|
|
|
- start: moment.utc(start).format(),
|
|
|
- end: moment.utc(end).format(),
|
|
|
- utc,
|
|
|
- }
|
|
|
- : {
|
|
|
- start: moment(start).utc().format(),
|
|
|
- end: moment(end).utc().format(),
|
|
|
- utc,
|
|
|
- };
|
|
|
- }
|
|
|
-
|
|
|
- return {
|
|
|
- period: statsPeriod ?? '90d',
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
export type Series = {
|
|
|
color: string;
|
|
|
data: {name: number; value: number}[];
|