Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion static/app/components/modals/widgetViewerModal.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ describe('Modals -> WidgetViewerModal', function () {
expect.objectContaining({
option: expect.objectContaining({
legend: expect.objectContaining({
selected: {[`Query Name:${mockWidget.id}`]: false},
selected: {[`Query Name;${mockWidget.id}`]: false},
}),
}),
}),
Expand Down
10 changes: 9 additions & 1 deletion static/app/views/dashboards/widgetCard/chart.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,10 @@ class WidgetCardChart extends Component<WidgetCardChartProps> {
const bucketSize = getBucketSize(timeseriesResults);

const valueFormatter = (value: number, seriesName?: string) => {
const aggregateName = seriesName?.split(':').pop()?.trim();
const decodedSeriesName = seriesName
? WidgetLegendNameEncoderDecoder.decodeSeriesNameForLegend(seriesName)
: seriesName;
const aggregateName = decodedSeriesName?.split(':').pop()?.trim();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not entirely sure if this line is related to your change or not, but does the ':' also have to get replaced with your delimiter here?

Also, are we using , in any special way? I saw something about a series list delimiter. If you group by multiple values those groupings (e.g. group by organization_slug and project) and you get a legend item like org_slug,project iirc.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this : is not related to the change, that has to do with other legend names :)

also , is fine because we're encoding all the series names before using that delimiter so it doesn't get messed up.

if (aggregateName) {
return timeseriesResultsTypes
? tooltipFormatter(value, timeseriesResultsTypes[aggregateName])
Expand All @@ -379,6 +382,10 @@ class WidgetCardChart extends Component<WidgetCardChartProps> {
return tooltipFormatter(value, 'number');
};

const nameFormatter = (name: string) => {
return WidgetLegendNameEncoderDecoder.decodeSeriesNameForLegend(name);
};

const chartOptions = {
autoHeightResize: shouldResize ?? true,
grid: {
Expand Down Expand Up @@ -408,6 +415,7 @@ class WidgetCardChart extends Component<WidgetCardChartProps> {

return getFormatter({
valueFormatter,
nameFormatter,
isGroupedByDate: true,
bucketSize,
addSecondsToTimeFormat: false,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import type {Series} from 'sentry/types/echarts';
import type {Widget} from 'sentry/views/dashboards/types';

const SERIES_NAME_DELIMITER = ';';

class WidgetLegendNameEncoderDecoder {
static encodeSeriesNameForLegend(seriesName: string, widgetId?: string) {
return `${seriesName}:${widgetId}`;
return `${seriesName}${SERIES_NAME_DELIMITER}${widgetId}`;
}

static decodeSeriesNameForLegend(encodedSeriesName: string) {
return encodedSeriesName.split(':')[0];
return encodedSeriesName.split(SERIES_NAME_DELIMITER)[0];
}

// change timeseries names to SeriesName:widgetID
Expand Down
14 changes: 10 additions & 4 deletions static/app/views/dashboards/widgetLegendSelectionState.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {DisplayType, WidgetType} from 'sentry/views/dashboards/types';
import WidgetLegendSelectionState from './widgetLegendSelectionState';

const WIDGET_ID_DELIMITER = ':';
const SERIES_NAME_DELIMITER = ';';

describe('WidgetLegend functions util', () => {
let legendFunctions: WidgetLegendSelectionState;
Expand Down Expand Up @@ -69,7 +70,7 @@ describe('WidgetLegend functions util', () => {

it('set initial unselected legend options', () => {
expect(legendFunctions.getWidgetSelectionState(widget)).toEqual({
'Releases:12345': false,
[`Releases${SERIES_NAME_DELIMITER}12345`]: false,
});
});

Expand All @@ -84,7 +85,10 @@ describe('WidgetLegend functions util', () => {
location = {...location, query: {...location.query, unselectedSeries: []}};

legendFunctions.setWidgetSelectionState(
{'Releases:12345': false, 'count():12345': true},
{
[`Releases${SERIES_NAME_DELIMITER}12345`]: false,
[`count()${SERIES_NAME_DELIMITER}12345`]: true,
},
widget
);
expect(router.replace).toHaveBeenCalledWith({
Expand Down Expand Up @@ -124,13 +128,15 @@ describe('WidgetLegend functions util', () => {

it('formats to query param format from selected', () => {
expect(
legendFunctions.encodeLegendQueryParam(widget, {[`Releases:${widget.id}`]: false})
legendFunctions.encodeLegendQueryParam(widget, {
[`Releases${SERIES_NAME_DELIMITER}${widget.id}`]: false,
})
).toEqual(`${widget.id}${WIDGET_ID_DELIMITER}Releases`);
});

it('formats to selected format from query param', () => {
expect(legendFunctions.decodeLegendQueryParam(widget)).toEqual({
[`Releases:${widget.id}`]: false,
[`Releases${SERIES_NAME_DELIMITER}${widget.id}`]: false,
});
});
});
Expand Down
12 changes: 7 additions & 5 deletions static/app/views/dashboards/widgetLegendSelectionState.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@ type Props = {

type LegendSelection = Record<string, boolean>;

const SERIES_DELIMITER = ',';
const SERIES_LIST_DELIMITER = ',';
const WIDGET_ID_DELIMITER = ':';

const SERIES_NAME_DELIMITER = ';';

class WidgetLegendSelectionState {
dashboard: DashboardDetails | null;
location: Location;
Expand Down Expand Up @@ -49,10 +51,10 @@ class WidgetLegendSelectionState {

const thisWidgetWithReleasesWasSelected =
Object.values(selected).filter(value => value === false).length !== 1 &&
Object.keys(selected).includes(`Releases:${widget.id}`);
Object.keys(selected).includes(`Releases${SERIES_NAME_DELIMITER}${widget.id}`);

const thisWidgetWithoutReleasesWasSelected =
!Object.keys(selected).includes(`Releases:${widget.id}`) &&
!Object.keys(selected).includes(`Releases${SERIES_NAME_DELIMITER}${widget.id}`) &&
Object.values(selected).filter(value => value === false).length === 1;

if (thisWidgetWithReleasesWasSelected || thisWidgetWithoutReleasesWasSelected) {
Expand Down Expand Up @@ -164,7 +166,7 @@ class WidgetLegendSelectionState {
WidgetLegendNameEncoderDecoder.decodeSeriesNameForLegend(series)
)
)
.join(SERIES_DELIMITER)
.join(SERIES_LIST_DELIMITER)
);
}

Expand All @@ -177,7 +179,7 @@ class WidgetLegendSelectionState {
);
if (widgetLegendString) {
const [_, seriesNameString] = widgetLegendString.split(WIDGET_ID_DELIMITER);
const seriesNames = seriesNameString.split(SERIES_DELIMITER);
const seriesNames = seriesNameString.split(SERIES_LIST_DELIMITER);
return seriesNames.reduce((acc, series) => {
acc[
decodeURIComponent(
Expand Down