diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.test.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.test.tsx index 9a3b74b0f52..2aa0735fd2a 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.test.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.test.tsx @@ -78,19 +78,6 @@ describe('MetricEncyclopediaModal', () => { expect(screen.getByText('all-metrics-help')).toBeInTheDocument(); }); - it('displays no metadata for a metric missing metadata when the metric is clicked', async () => { - setup(defaultQuery, listOfMetrics); - await waitFor(() => { - expect(screen.getByText('b')).toBeInTheDocument(); - }); - - const interactiveMetric = screen.getByText('b'); - - await userEvent.click(interactiveMetric); - - expect(screen.getByText('No metadata available')).toBeInTheDocument(); - }); - // Filtering it('has a filter for selected type', async () => { setup(defaultQuery, listOfMetrics); diff --git a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx index 90ad6fa1464..c4659af4c26 100644 --- a/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx +++ b/public/app/plugins/datasource/prometheus/querybuilder/components/MetricEncyclopediaModal.tsx @@ -9,16 +9,17 @@ import { EditorField } from '@grafana/experimental'; import { reportInteraction } from '@grafana/runtime'; import { Button, - Card, - Collapse, + CellProps, + Column, InlineField, - InlineSwitch, + Switch, Input, + InteractiveTable, Modal, MultiSelect, Select, Spinner, - useStyles2, + useTheme2, } from '@grafana/ui'; import { PrometheusDatasource } from '../../datasource'; @@ -110,7 +111,6 @@ export const MetricEncyclopediaModal = (props: Props) => { const [hasMetadata, setHasMetadata] = useState(true); const [metaHaystack, setMetaHaystack] = useState([]); const [nameHaystack, setNameHaystack] = useState([]); - const [openTabs, setOpenTabs] = useState([]); // pagination const [resultsPerPage, setResultsPerPage] = useState(DEFAULT_RESULTS_PER_PAGE); @@ -129,6 +129,7 @@ export const MetricEncyclopediaModal = (props: Props) => { const [filteredMetricCount, setFilteredMetricCount] = useState(); // backend search metric names by text const [useBackend, setUseBackend] = useState(false); + const [disableTextWrap, setDisableTextWrap] = useState(false); const updateMetricsMetadata = useCallback(async () => { // *** Loading Gif @@ -197,7 +198,8 @@ export const MetricEncyclopediaModal = (props: Props) => { updateMetricsMetadata(); }, [updateMetricsMetadata]); - const styles = useStyles2(getStyles); + const theme = useTheme2(); + const styles = getStyles(theme, disableTextWrap); const typeOptions: SelectableValue[] = promTypes.map((t: PromFilterOption) => { return { @@ -272,6 +274,12 @@ export const MetricEncyclopediaModal = (props: Props) => { }); } + if (excludeNullMetadata) { + filteredMetrics = filteredMetrics.filter((m: MetricData) => { + return m.type !== undefined && m.description !== undefined; + }); + } + return filteredMetrics; } @@ -410,6 +418,69 @@ export const MetricEncyclopediaModal = (props: Props) => { return results ?? 10; }; + const ButtonCell = ({ + row: { + original: { value }, + }, + }: CellProps) => { + return ( + + ); + }; + + function tableResults(metrics: MetricsData) { + const tableData: MetricsData = metrics; + + const columns: Array> = [ + { id: '', header: 'Select', cell: ButtonCell }, + { id: 'value', header: 'Name' }, + { id: 'type', header: 'Type' }, + { id: 'description', header: 'Description' }, + ]; + + return r.value} />; + } + + function fuzzySearchCallback(query: string, fullMetaSearchVal: boolean) { + if (useBackend && query === '') { + // get all metrics data if a user erases everything in the input + updateMetricsMetadata(); + } else if (useBackend) { + debouncedBackendSearch(query); + } else { + // search either the names or all metadata + // fuzzy search go! + + if (fullMetaSearchVal) { + debouncedFuzzySearch(metaHaystack, query, setFuzzyMetaSearchResults); + } else { + debouncedFuzzySearch(nameHaystack, query, setFuzzyNameSearchResults); + } + } + } + return ( { onInput={(e) => { const value = e.currentTarget.value ?? ''; setFuzzySearchQuery(value); - if (useBackend && value === '') { - // get all metrics data if a user erases everything in the input - updateMetricsMetadata(); - } else if (useBackend) { - debouncedBackendSearch(value); - } else { - // search either the names or all metadata - // fuzzy search go! - if (fullMetaSearch) { - debouncedFuzzySearch(metaHaystack, value, setFuzzyMetaSearchResults); - } else { - debouncedFuzzySearch(nameHaystack, value, setFuzzyNameSearchResults); - } - } + fuzzySearchCallback(value, fullMetaSearch); setPageNum(1); }} @@ -490,23 +548,23 @@ export const MetricEncyclopediaModal = (props: Props) => { <>
- { - setFullMetaSearch(!fullMetaSearch); + const newVal = !fullMetaSearch; + setFullMetaSearch(newVal); + + fuzzySearchCallback(fuzzySearchQuery, newVal); + setPageNum(1); }} />

{placeholders.metadataSearchSwitch}

- {/*
- {}} /> -

Disable fuzzy search metadata browsing (HELP!)

-
*/}
- { @@ -531,7 +589,6 @@ export const MetricEncyclopediaModal = (props: Props) => {
-

Results

@@ -547,80 +604,26 @@ export const MetricEncyclopediaModal = (props: Props) => {
{letterSearchComponent()}
-
- { - setExcludeNullMetadata(!excludeNullMetadata); - setPageNum(1); - }} - /> -

{placeholders.excludeNoMetadata}

+
+
+ setDisableTextWrap((p) => !p)} /> +

Disable text wrap

+
+
+ { + setExcludeNullMetadata(!excludeNullMetadata); + setPageNum(1); + }} + /> +

{placeholders.excludeNoMetadata}

+
-
- {metrics && - displayedMetrics(metrics).map((metric: MetricData, idx) => { - return ( - - setOpenTabs((tabs) => - // close tab if it's already open, otherwise open it - tabs.includes(metric.value) ? tabs.filter((t) => t !== metric.value) : [...tabs, metric.value] - ) - } - > -
- - - {metric.description && metric.type ? ( - <> - Type: {metric.type} -
- Description: {metric.description} - - ) : ( - No metadata available - )} -
- - {/* *** Make selecting a metric easier, consider click on text */} - - -
-
-
- ); - })} -
+
{metrics && tableResults(displayedMetrics(metrics))}
@@ -698,7 +701,7 @@ function alphabetically(ascending: boolean, metadataFilters: boolean) { }; } -const getStyles = (theme: GrafanaTheme2) => { +const getStyles = (theme: GrafanaTheme2, disableTextWrap: boolean) => { return { modal: css` width: 85vw; @@ -709,6 +712,7 @@ const getStyles = (theme: GrafanaTheme2) => { inputWrapper: css` display: flex; flex-direction: row; + flex-wrap: wrap; gap: ${theme.spacing(2)}; margin-bottom: ${theme.spacing(2)}; `, @@ -717,6 +721,10 @@ const getStyles = (theme: GrafanaTheme2) => { `, inputItem: css` flex-grow: 1; + flex-basis: 20%; + ${theme.breakpoints.down('md')} { + min-width: 100%; + } `, selectWrapper: css` margin-bottom: ${theme.spacing(2)}; @@ -724,6 +732,7 @@ const getStyles = (theme: GrafanaTheme2) => { selectItem: css` display: flex; flex-direction: row; + align-items: center; `, selectItemLabel: css` margin: 0 0 0 ${theme.spacing(1)}; @@ -746,8 +755,18 @@ const getStyles = (theme: GrafanaTheme2) => { alphabetRow: css` display: flex; flex-direction: row; + flex-wrap: wrap; justify-content: space-between; align-items: center; + column-gap: ${theme.spacing(1)}; + margin-bottom: ${theme.spacing(1)}; + `, + alphabetRowToggles: css` + display: flex; + flex-direction: row; + align-items: center; + flex-wrap: wrap; + column-gap: ${theme.spacing(1)}; `, results: css` height: 300px; @@ -757,24 +776,15 @@ const getStyles = (theme: GrafanaTheme2) => { padding-top: ${theme.spacing(1.5)}; display: flex; flex-direction: row; + flex-wrap: wrap; justify-content: space-between; align-items: center; `, pageSettings: css` - display: flex; - flex-direction: row; - align-items: center; - `, - cardsContainer: css` display: flex; flex-direction: row; flex-wrap: wrap; - justify-content: space-between; - `, - card: css` - width: 100%; - display: flex; - flex-direction: column; + align-items: center; `, selAlpha: css` cursor: pointer; @@ -786,12 +796,15 @@ const getStyles = (theme: GrafanaTheme2) => { gray: css` color: grey; `, - metadata: css` - color: rgb(204, 204, 220); - `, loadingSpinner: css` display: inline-block; `, + table: css` + white-space: ${disableTextWrap ? 'nowrap' : 'normal'}; + td { + vertical-align: baseline; + } + `, }; };