datatrails: Remove prefix filter (#84661)
* fix: use cascader's clear button * fix: remove the prefix filter from metric select * fix: remove supporting code in metric select scene - For the removed prefix filter * fix: spacing
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
import React, { useMemo, useReducer, useState } from 'react';
|
import React, { useMemo } from 'react';
|
||||||
|
|
||||||
import { Cascader, CascaderOption, HorizontalGroup, Button } from '@grafana/ui';
|
import { Cascader, CascaderOption } from '@grafana/ui';
|
||||||
|
|
||||||
import { useMetricCategories } from './useMetricCategories';
|
import { useMetricCategories } from './useMetricCategories';
|
||||||
|
|
||||||
@@ -15,36 +15,19 @@ export function MetricCategoryCascader({ metricNames, onSelect, disabled, initia
|
|||||||
const categoryTree = useMetricCategories(metricNames);
|
const categoryTree = useMetricCategories(metricNames);
|
||||||
const options = useMemo(() => createCasaderOptions(categoryTree), [categoryTree]);
|
const options = useMemo(() => createCasaderOptions(categoryTree), [categoryTree]);
|
||||||
|
|
||||||
const [disableClear, setDisableClear] = useState(initialValue == null);
|
|
||||||
|
|
||||||
// Increments whenever clear is pressed, to reset the Cascader component
|
|
||||||
const [cascaderKey, resetCascader] = useReducer((x) => x + 1, 0);
|
|
||||||
|
|
||||||
const clear = () => {
|
|
||||||
resetCascader();
|
|
||||||
setDisableClear(true);
|
|
||||||
onSelect(undefined);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HorizontalGroup>
|
<Cascader
|
||||||
<Cascader
|
displayAllSelectedLevels={true}
|
||||||
key={cascaderKey} // To reset the component to `undefined`
|
width={40}
|
||||||
displayAllSelectedLevels={true}
|
separator="_"
|
||||||
width={40}
|
hideActiveLevelLabel={false}
|
||||||
separator="_"
|
placeholder={'No filter'}
|
||||||
hideActiveLevelLabel={false}
|
isClearable
|
||||||
placeholder={'No filter'}
|
onSelect={(prefix) => {
|
||||||
onSelect={(prefix) => {
|
onSelect(prefix);
|
||||||
setDisableClear(!prefix);
|
}}
|
||||||
onSelect(prefix);
|
{...{ options, disabled, initialValue }}
|
||||||
}}
|
/>
|
||||||
{...{ options, disabled, initialValue }}
|
|
||||||
/>
|
|
||||||
<Button disabled={disableClear || disabled} onClick={clear} variant="secondary">
|
|
||||||
Clear
|
|
||||||
</Button>
|
|
||||||
</HorizontalGroup>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ import { VariableHide } from '@grafana/schema';
|
|||||||
import { Input, InlineSwitch, Field, Alert, Icon, useStyles2 } from '@grafana/ui';
|
import { Input, InlineSwitch, Field, Alert, Icon, useStyles2 } from '@grafana/ui';
|
||||||
|
|
||||||
import { getPreviewPanelFor } from './AutomaticMetricQueries/previewPanel';
|
import { getPreviewPanelFor } from './AutomaticMetricQueries/previewPanel';
|
||||||
import { MetricCategoryCascader } from './MetricCategory/MetricCategoryCascader';
|
|
||||||
import { MetricScene } from './MetricScene';
|
import { MetricScene } from './MetricScene';
|
||||||
import { SelectMetricAction } from './SelectMetricAction';
|
import { SelectMetricAction } from './SelectMetricAction';
|
||||||
import { StatusWrapper } from './StatusWrapper';
|
import { StatusWrapper } from './StatusWrapper';
|
||||||
@@ -44,9 +43,7 @@ export interface MetricSelectSceneState extends SceneObjectState {
|
|||||||
body: SceneCSSGridLayout;
|
body: SceneCSSGridLayout;
|
||||||
searchQuery?: string;
|
searchQuery?: string;
|
||||||
showPreviews?: boolean;
|
showPreviews?: boolean;
|
||||||
prefixFilter?: string;
|
|
||||||
metricsAfterSearch?: string[];
|
metricsAfterSearch?: string[];
|
||||||
metricsAfterFilter?: string[];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const ROW_PREVIEW_HEIGHT = '175px';
|
const ROW_PREVIEW_HEIGHT = '175px';
|
||||||
@@ -158,32 +155,15 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private applyMetricPrefixFilter() {
|
|
||||||
// This should occur after an `applyMetricSearch`, or if the prefix filter has changed
|
|
||||||
const { metricsAfterSearch, prefixFilter } = this.state;
|
|
||||||
|
|
||||||
if (!prefixFilter || !metricsAfterSearch) {
|
|
||||||
this.setState({ metricsAfterFilter: metricsAfterSearch });
|
|
||||||
} else {
|
|
||||||
const metricsAfterFilter = metricsAfterSearch.filter((metric) => metric.startsWith(prefixFilter));
|
|
||||||
this.setState({ metricsAfterFilter });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private updateMetrics(applySearchAndFilter = true) {
|
private updateMetrics(applySearchAndFilter = true) {
|
||||||
if (applySearchAndFilter) {
|
if (applySearchAndFilter) {
|
||||||
// Set to false if these are not required (because they can be assumed to have been suitably called).
|
// Set to false if these are not required (because they can be assumed to have been suitably called).
|
||||||
this.applyMetricSearch();
|
this.applyMetricSearch();
|
||||||
this.applyMetricPrefixFilter();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { metricsAfterFilter } = this.state;
|
const { metricsAfterSearch } = this.state;
|
||||||
|
|
||||||
if (!metricsAfterFilter) {
|
const metricNames = metricsAfterSearch || [];
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const metricNames = metricsAfterFilter;
|
|
||||||
const trail = getTrailFor(this);
|
const trail = getTrailFor(this);
|
||||||
const sortedMetricNames =
|
const sortedMetricNames =
|
||||||
trail.state.metric !== undefined ? sortRelatedMetrics(metricNames, trail.state.metric) : metricNames;
|
trail.state.metric !== undefined ? sortRelatedMetrics(metricNames, trail.state.metric) : metricNames;
|
||||||
@@ -302,29 +282,18 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
|
|||||||
this.buildLayout();
|
this.buildLayout();
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
public onPrefixFilterChange = (prefixFilter: string | undefined) => {
|
|
||||||
this.setState({ prefixFilter });
|
|
||||||
this.prefixFilterChangedDebounced();
|
|
||||||
};
|
|
||||||
|
|
||||||
private prefixFilterChangedDebounced = debounce(() => {
|
|
||||||
this.applyMetricPrefixFilter();
|
|
||||||
this.updateMetrics(false); // Only needed to applyMetricPrefixFilter
|
|
||||||
this.buildLayout();
|
|
||||||
}, 1000);
|
|
||||||
|
|
||||||
public onTogglePreviews = () => {
|
public onTogglePreviews = () => {
|
||||||
this.setState({ showPreviews: !this.state.showPreviews });
|
this.setState({ showPreviews: !this.state.showPreviews });
|
||||||
this.buildLayout();
|
this.buildLayout();
|
||||||
};
|
};
|
||||||
|
|
||||||
public static Component = ({ model }: SceneComponentProps<MetricSelectScene>) => {
|
public static Component = ({ model }: SceneComponentProps<MetricSelectScene>) => {
|
||||||
const { searchQuery, showPreviews, body, metricsAfterSearch, metricsAfterFilter, prefixFilter } = model.useState();
|
const { searchQuery, showPreviews, body } = model.useState();
|
||||||
const { children } = body.useState();
|
const { children } = body.useState();
|
||||||
const styles = useStyles2(getStyles);
|
const styles = useStyles2(getStyles);
|
||||||
|
|
||||||
const metricNamesStatus = useVariableStatus(VAR_METRIC_NAMES, model);
|
const metricNamesStatus = useVariableStatus(VAR_METRIC_NAMES, model);
|
||||||
const tooStrict = children.length === 0 && (searchQuery || prefixFilter);
|
const tooStrict = children.length === 0 && searchQuery;
|
||||||
const noMetrics = !metricNamesStatus.isLoading && model.currentMetricNames.size === 0;
|
const noMetrics = !metricNamesStatus.isLoading && model.currentMetricNames.size === 0;
|
||||||
|
|
||||||
const isLoading = metricNamesStatus.isLoading && children.length === 0;
|
const isLoading = metricNamesStatus.isLoading && children.length === 0;
|
||||||
@@ -335,11 +304,6 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
|
|||||||
(tooStrict && 'There are no results found. Try adjusting your search or filters.') ||
|
(tooStrict && 'There are no results found. Try adjusting your search or filters.') ||
|
||||||
undefined;
|
undefined;
|
||||||
|
|
||||||
const prefixError =
|
|
||||||
prefixFilter && metricsAfterSearch != null && !metricsAfterFilter?.length
|
|
||||||
? 'The current prefix filter is not available with the current search terms.'
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const disableSearch = metricNamesStatus.error || metricNamesStatus.isLoading;
|
const disableSearch = metricNamesStatus.error || metricNamesStatus.isLoading;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -362,16 +326,6 @@ export class MetricSelectScene extends SceneObjectBase<MetricSelectSceneState> {
|
|||||||
disabled={disableSearch}
|
disabled={disableSearch}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className={styles.header}>
|
|
||||||
<Field label="Filter by prefix" error={prefixError} invalid={!!prefixError}>
|
|
||||||
<MetricCategoryCascader
|
|
||||||
metricNames={metricsAfterSearch || []}
|
|
||||||
onSelect={model.onPrefixFilterChange}
|
|
||||||
disabled={disableSearch}
|
|
||||||
initialValue={prefixFilter}
|
|
||||||
/>
|
|
||||||
</Field>
|
|
||||||
</div>
|
|
||||||
{metricNamesStatus.error && (
|
{metricNamesStatus.error && (
|
||||||
<Alert title="Unable to retrieve metric names" severity="error">
|
<Alert title="Unable to retrieve metric names" severity="error">
|
||||||
<div>We are unable to connect to your data source. Double check your data source URL and credentials.</div>
|
<div>We are unable to connect to your data source. Double check your data source URL and credentials.</div>
|
||||||
@@ -425,7 +379,7 @@ function getStyles(theme: GrafanaTheme2) {
|
|||||||
flexGrow: 0,
|
flexGrow: 0,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
gap: theme.spacing(2),
|
gap: theme.spacing(2),
|
||||||
marginBottom: theme.spacing(1),
|
marginBottom: theme.spacing(2),
|
||||||
alignItems: 'flex-end',
|
alignItems: 'flex-end',
|
||||||
}),
|
}),
|
||||||
searchField: css({
|
searchField: css({
|
||||||
|
|||||||
Reference in New Issue
Block a user