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
5 changes: 5 additions & 0 deletions .changeset/short-wombats-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hyperdx/app": patch
---

fix: Fix minor bugs in chart editor
45 changes: 23 additions & 22 deletions packages/app/src/DBDashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -367,27 +367,28 @@ const Tile = forwardRef(
>
{(chart.config.displayType === DisplayType.Line ||
chart.config.displayType === DisplayType.StackedBar ||
chart.config.displayType === DisplayType.Number) && (
<Indicator
size={alert?.state === AlertState.OK ? 6 : 8}
zIndex={1}
color={alertIndicatorColor}
processing={alert?.state === AlertState.ALERT}
label={!alert && <span className="fs-8">+</span>}
mr={4}
>
<Tooltip label={alertTooltip} withArrow>
<ActionIcon
data-testid={`tile-alerts-button-${chart.id}`}
variant="subtle"
size="sm"
onClick={onEditClick}
>
<IconBell size={16} />
</ActionIcon>
</Tooltip>
</Indicator>
)}
chart.config.displayType === DisplayType.Number) &&
!isRawSqlSavedChartConfig(chart.config) && (
<Indicator
size={alert?.state === AlertState.OK ? 6 : 8}
zIndex={1}
color={alertIndicatorColor}
processing={alert?.state === AlertState.ALERT}
label={!alert && <span className="fs-8">+</span>}
mr={4}
>
<Tooltip label={alertTooltip} withArrow>
<ActionIcon
data-testid={`tile-alerts-button-${chart.id}`}
variant="subtle"
size="sm"
onClick={onEditClick}
>
<IconBell size={16} />
</ActionIcon>
</Tooltip>
</Indicator>
)}

<ActionIcon
data-testid={`tile-duplicate-button-${chart.id}`}
Expand Down Expand Up @@ -469,7 +470,7 @@ const Tile = forwardRef(
alertIndicatorColor,
alertTooltip,
availableSections,
chart.config.displayType,
chart.config,
chart.id,
chart.containerId,
hovered,
Expand Down
7 changes: 6 additions & 1 deletion packages/app/src/components/AggFnSelect.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ function AggFnSelect({
value,
defaultValue,
onChange,
hideCustom,
}: {
value: string;
defaultValue: string;
onChange: (value: OnChangeValue) => void;
hideCustom?: boolean;
}) {
const _onChange = useCallback(
(value: string | null) => {
Expand All @@ -42,7 +44,7 @@ function AggFnSelect({
value={value}
defaultValue={defaultValue}
onChange={_onChange}
data={AGG_FNS}
data={hideCustom ? AGG_FNS.filter(fn => fn.value !== 'none') : AGG_FNS}
data-testid="agg-fn-select"
/>
);
Expand All @@ -52,11 +54,13 @@ export function AggFnSelectControlled({
aggFnName,
quantileLevelName,
defaultValue,
hideCustom,
...props
}: {
defaultValue: string;
aggFnName: string;
quantileLevelName: string;
hideCustom?: boolean;
} & Omit<UseControllerProps<any>, 'name'>) {
const {
field: { onChange: onAggFnChange, value: aggFnValue },
Expand Down Expand Up @@ -96,6 +100,7 @@ export function AggFnSelectControlled({
value={value}
defaultValue={defaultValue}
onChange={onChange}
hideCustom={hideCustom}
/>
);
}
15 changes: 11 additions & 4 deletions packages/app/src/components/DBEditTimeChartForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,17 @@ function ChartSeriesEditorComponent({
const metricType = useWatch({ control, name: `${namePrefix}metricType` });

// Initialize metricType to 'gauge' when switching to a metric source
// and reset 'custom' aggFn to 'count' since custom is not supported for metrics
useEffect(() => {
if (tableSource?.kind === SourceKind.Metric && !metricType) {
setValue(`${namePrefix}metricType`, MetricsDataType.Gauge);
if (tableSource?.kind === SourceKind.Metric) {
if (!metricType) {
setValue(`${namePrefix}metricType`, MetricsDataType.Gauge);
}
if (aggFn === 'none') {
setValue(`${namePrefix}aggFn`, 'count');
}
}
}, [tableSource?.kind, metricType, namePrefix, setValue]);
}, [tableSource?.kind, metricType, aggFn, namePrefix, setValue]);

const tableName =
tableSource?.kind === SourceKind.Metric
Expand Down Expand Up @@ -363,6 +369,7 @@ function ChartSeriesEditorComponent({
quantileLevelName={`${namePrefix}level`}
defaultValue={AGG_FNS[0]?.value ?? 'avg'}
control={control}
hideCustom={tableSource?.kind === SourceKind.Metric}
/>
</div>
{tableSource?.kind === SourceKind.Metric && metricType && (
Expand Down Expand Up @@ -496,7 +503,7 @@ function ChartSeriesEditorComponent({
language={aggConditionLanguage === 'sql' ? 'sql' : 'lucene'}
metricMetadata={metricMetadata}
onAddToWhere={handleAddToWhere}
onAddToGroupBy={handleAddToGroupBy}
onAddToGroupBy={showGroupBy ? handleAddToGroupBy : undefined}
/>
)}
</>
Expand Down
24 changes: 13 additions & 11 deletions packages/app/src/components/MetricAttributeHelperPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ interface MetricAttributeHelperPanelProps {
language: 'sql' | 'lucene';
metricMetadata?: MetricMetadata | null;
onAddToWhere: (clause: string) => void;
onAddToGroupBy: (clause: string) => void;
onAddToGroupBy?: (clause: string) => void;
}

const CATEGORY_LABELS: Record<AttributeCategory, string> = {
Expand Down Expand Up @@ -170,7 +170,7 @@ interface AttributeValueListProps {
language: 'sql' | 'lucene';
onAddToWhere: (clause: string) => void;
onBack: () => void;
onAddToGroupBy: (clause: string) => void;
onAddToGroupBy?: (clause: string) => void;
}

function AttributeValueList({
Expand Down Expand Up @@ -217,7 +217,7 @@ function AttributeValueList({
attribute.name,
'sql',
);
onAddToGroupBy(clause);
onAddToGroupBy?.(clause);
}, [attribute, onAddToGroupBy]);

return (
Expand All @@ -234,14 +234,16 @@ function AttributeValueList({
</Badge>
</Group>
</UnstyledButton>
<Button
variant="secondary"
size="xs"
leftSection={<IconPlus size={14} />}
onClick={handleAddToGroupBy}
>
Group By
</Button>
{onAddToGroupBy && (
<Button
variant="secondary"
size="xs"
leftSection={<IconPlus size={14} />}
onClick={handleAddToGroupBy}
>
Group By
</Button>
)}
</Group>

<TextInput
Expand Down
33 changes: 33 additions & 0 deletions packages/app/tests/e2e/components/ChartEditorComponent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export class ChartEditorComponent {
private readonly chartTypeInput: Locator;
private readonly sourceSelector: Locator;
private readonly metricSelector: Locator;
private readonly aggFnSelect: Locator;
private readonly addOrRemoveAlertButton: Locator;
private readonly webhookSelector: Locator;
private readonly runQueryButton: Locator;
Expand All @@ -29,6 +30,7 @@ export class ChartEditorComponent {
this.chartTypeInput = page.getByTestId('chart-type-input');
this.sourceSelector = page.getByTestId('source-selector');
this.metricSelector = page.getByTestId('metric-name-selector');
this.aggFnSelect = page.getByTestId('agg-fn-select');
this.addOrRemoveAlertButton = page.getByTestId('alert-button');
this.webhookSelector = page.getByTestId('select-webhook');
this.addNewWebhookButton = page.getByTestId('add-new-webhook-button');
Expand Down Expand Up @@ -99,6 +101,33 @@ export class ChartEditorComponent {
}
}

/**
* Select an aggregation function from the dropdown
*/
async selectAggFn(label: string) {
await this.aggFnSelect.click();
await this.page.getByRole('option', { name: label }).click();
}

/**
* Get the currently selected aggregation function value
*/
async getSelectedAggFn(): Promise<string | null> {
return this.aggFnSelect.inputValue();
}

/**
* Check if an aggregation function option is available in the dropdown
*/
async isAggFnOptionAvailable(label: string): Promise<boolean> {
await this.aggFnSelect.click();
const option = this.page.getByRole('option', { name: label });
const visible = await option.isVisible().catch(() => false);
// Close the dropdown
await this.page.keyboard.press('Escape');
return visible;
}

async clickAddAlert() {
await this.addOrRemoveAlertButton.click();
this.addNewWebhookButton.waitFor({
Expand Down Expand Up @@ -250,6 +279,10 @@ export class ChartEditorComponent {
return this.metricSelector;
}

get aggFn() {
return this.aggFnSelect;
}

get alertButton() {
return this.addOrRemoveAlertButton;
}
Expand Down
35 changes: 35 additions & 0 deletions packages/app/tests/e2e/features/dashboard.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -786,6 +786,41 @@ test.describe('Dashboard', { tag: ['@dashboard'] }, () => {
});
});

test(
'should deselect and hide the Custom aggregation function when switching to a metric source',
{ tag: '@full-stack' },
async () => {
await test.step('Navigate to dashboard and open new tile editor', async () => {
await dashboardPage.openNewTileEditor();
});

await test.step('Select the "Custom" aggregation function', async () => {
await dashboardPage.chartEditor.selectAggFn('Custom');
const selectedAggFn =
await dashboardPage.chartEditor.getSelectedAggFn();
expect(selectedAggFn).toBe('Custom');
});

await test.step('Switch the source to a metric source', async () => {
await dashboardPage.chartEditor.selectSource(
DEFAULT_METRICS_SOURCE_NAME,
);
});

await test.step('Verify the aggregation function was automatically changed away from "Custom"', async () => {
const selectedAggFn =
await dashboardPage.chartEditor.getSelectedAggFn();
expect(selectedAggFn).toBe('Count of Events');
});

await test.step('Verify the "Custom" option is NOT available in the aggregation dropdown', async () => {
const isCustomAvailable =
await dashboardPage.chartEditor.isAggFnOptionAvailable('Custom');
expect(isCustomAvailable).toBe(false);
});
},
);

test(
'should clear saved query when WHERE input is cleared and saved',
{},
Expand Down
Loading