mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Loki: Add improvements to loki label browser (#59387)
* improvements * refactor label browser modal * feat(label-browser-modal): fetch labels on modal open * apply suggestions * check for log labels after languageProvider start Co-authored-by: Matias Chomicki <matyax@gmail.com>
This commit is contained in:
parent
37c14bd6bd
commit
6b5ebf2b4b
@ -31,7 +31,6 @@ export const LokiQueryEditor = React.memo<LokiQueryEditorProps>((props) => {
|
||||
const [queryPatternsModalOpen, setQueryPatternsModalOpen] = useState(false);
|
||||
const [dataIsStale, setDataIsStale] = useState(false);
|
||||
const [labelBrowserVisible, setLabelBrowserVisible] = useState(false);
|
||||
const [labelsLoaded, setLabelsLoaded] = useState(false);
|
||||
const { flag: explain, setFlag: setExplain } = useFlag(lokiQueryEditorExplainKey);
|
||||
|
||||
const query = getQueryWithDefaults(props.query);
|
||||
@ -73,30 +72,10 @@ export const LokiQueryEditor = React.memo<LokiQueryEditorProps>((props) => {
|
||||
onChange(query);
|
||||
};
|
||||
|
||||
const onClickChooserButton = () => {
|
||||
const onClickLabelBrowserButton = () => {
|
||||
setLabelBrowserVisible((visible) => !visible);
|
||||
};
|
||||
|
||||
const getChooserText = (logLabelsLoaded: boolean, hasLogLabels: boolean) => {
|
||||
if (!logLabelsLoaded) {
|
||||
return 'Loading labels...';
|
||||
}
|
||||
if (!hasLogLabels) {
|
||||
return '(No labels found)';
|
||||
}
|
||||
return 'Label browser';
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
datasource.languageProvider.start().then(() => {
|
||||
setLabelsLoaded(true);
|
||||
});
|
||||
}, [datasource]);
|
||||
|
||||
const hasLogLabels = datasource.languageProvider.getLabelKeys().length > 0;
|
||||
const labelBrowserText = getChooserText(labelsLoaded, hasLogLabels);
|
||||
const buttonDisabled = !(labelsLoaded && hasLogLabels);
|
||||
|
||||
return (
|
||||
<>
|
||||
<ConfirmModal
|
||||
@ -119,16 +98,16 @@ export const LokiQueryEditor = React.memo<LokiQueryEditorProps>((props) => {
|
||||
onChange={onChange}
|
||||
onAddQuery={onAddQuery}
|
||||
/>
|
||||
<LabelBrowserModal
|
||||
isOpen={labelBrowserVisible}
|
||||
datasource={datasource}
|
||||
query={query}
|
||||
app={app}
|
||||
onClose={() => setLabelBrowserVisible(false)}
|
||||
onChange={onChangeInternal}
|
||||
onRunQuery={onRunQuery}
|
||||
/>
|
||||
<EditorHeader>
|
||||
<LabelBrowserModal
|
||||
isOpen={labelBrowserVisible}
|
||||
languageProvider={datasource.languageProvider}
|
||||
query={query}
|
||||
app={app}
|
||||
onClose={() => setLabelBrowserVisible(false)}
|
||||
onChange={onChangeInternal}
|
||||
onRunQuery={onRunQuery}
|
||||
/>
|
||||
<Stack gap={1}>
|
||||
<Button
|
||||
aria-label={selectors.components.QueryBuilder.queryPatterns}
|
||||
@ -149,14 +128,8 @@ export const LokiQueryEditor = React.memo<LokiQueryEditorProps>((props) => {
|
||||
>
|
||||
Kick start your query
|
||||
</Button>
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={onClickChooserButton}
|
||||
disabled={buttonDisabled}
|
||||
data-testid="label-browser-button"
|
||||
>
|
||||
{labelBrowserText}
|
||||
<Button variant="secondary" size="sm" onClick={onClickLabelBrowserButton} data-testid="label-browser-button">
|
||||
Label browser
|
||||
</Button>
|
||||
</Stack>
|
||||
<QueryHeaderSwitch label="Explain" value={explain} onChange={onExplainChange} />
|
||||
|
@ -20,7 +20,7 @@ describe('LabelBrowserModal', () => {
|
||||
|
||||
props = {
|
||||
isOpen: true,
|
||||
languageProvider: datasource.languageProvider,
|
||||
datasource: datasource,
|
||||
query: {} as LokiQuery,
|
||||
onClose: jest.fn(),
|
||||
onChange: jest.fn(),
|
||||
@ -30,13 +30,17 @@ describe('LabelBrowserModal', () => {
|
||||
jest.spyOn(datasource, 'metadataRequest').mockResolvedValue({});
|
||||
});
|
||||
|
||||
it('renders the label browser modal when open', () => {
|
||||
it('renders the label browser modal when open', async () => {
|
||||
render(<LabelBrowserModal {...props} />);
|
||||
|
||||
expect(await screen.findByText(/Loading/)).not.toBeInTheDocument();
|
||||
|
||||
expect(screen.getByRole('heading', { name: /label browser/i })).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it("doesn't render the label browser modal when closed", () => {
|
||||
it("doesn't render the label browser modal when closed", async () => {
|
||||
render(<LabelBrowserModal {...props} isOpen={false} />);
|
||||
|
||||
expect(screen.queryByRole('heading', { name: /label browser/i })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
@ -1,16 +1,16 @@
|
||||
import React from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
|
||||
import { CoreApp } from '@grafana/data';
|
||||
import { Modal } from '@grafana/ui';
|
||||
import { LoadingPlaceholder, Modal } from '@grafana/ui';
|
||||
import { LocalStorageValueProvider } from 'app/core/components/LocalStorageValueProvider';
|
||||
|
||||
import LanguageProvider from '../../LanguageProvider';
|
||||
import { LokiLabelBrowser } from '../../components/LokiLabelBrowser';
|
||||
import { LokiDatasource } from '../../datasource';
|
||||
import { LokiQuery } from '../../types';
|
||||
|
||||
export interface Props {
|
||||
isOpen: boolean;
|
||||
languageProvider: LanguageProvider;
|
||||
datasource: LokiDatasource;
|
||||
query: LokiQuery;
|
||||
app?: CoreApp;
|
||||
onClose: () => void;
|
||||
@ -19,13 +19,24 @@ export interface Props {
|
||||
}
|
||||
|
||||
export const LabelBrowserModal = (props: Props) => {
|
||||
const { isOpen, onClose, languageProvider, app } = props;
|
||||
|
||||
const { isOpen, onClose, datasource, app } = props;
|
||||
const [labelsLoaded, setLabelsLoaded] = useState(false);
|
||||
const [hasLogLabels, setHasLogLabels] = useState(false);
|
||||
const LAST_USED_LABELS_KEY = 'grafana.datasources.loki.browser.labels';
|
||||
|
||||
useEffect(() => {
|
||||
if (!isOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
datasource.languageProvider.start().then(() => {
|
||||
setLabelsLoaded(true);
|
||||
setHasLogLabels(datasource.languageProvider.getLabelKeys().length > 0);
|
||||
});
|
||||
}, [datasource, isOpen]);
|
||||
|
||||
const changeQuery = (value: string) => {
|
||||
const { query, onChange, onRunQuery } = props;
|
||||
|
||||
const nextQuery = { ...query, expr: value };
|
||||
onChange(nextQuery);
|
||||
onRunQuery();
|
||||
@ -38,20 +49,24 @@ export const LabelBrowserModal = (props: Props) => {
|
||||
|
||||
return (
|
||||
<Modal isOpen={isOpen} title="Label browser" onDismiss={onClose}>
|
||||
<LocalStorageValueProvider<string[]> storageKey={LAST_USED_LABELS_KEY} defaultValue={[]}>
|
||||
{(lastUsedLabels, onLastUsedLabelsSave, onLastUsedLabelsDelete) => {
|
||||
return (
|
||||
<LokiLabelBrowser
|
||||
languageProvider={languageProvider}
|
||||
onChange={onChange}
|
||||
lastUsedLabels={lastUsedLabels}
|
||||
storeLastUsedLabels={onLastUsedLabelsSave}
|
||||
deleteLastUsedLabels={onLastUsedLabelsDelete}
|
||||
app={app}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</LocalStorageValueProvider>
|
||||
{!labelsLoaded && <LoadingPlaceholder text="Loading labels..." />}
|
||||
{labelsLoaded && !hasLogLabels && <p>No labels found.</p>}
|
||||
{labelsLoaded && hasLogLabels && (
|
||||
<LocalStorageValueProvider<string[]> storageKey={LAST_USED_LABELS_KEY} defaultValue={[]}>
|
||||
{(lastUsedLabels, onLastUsedLabelsSave, onLastUsedLabelsDelete) => {
|
||||
return (
|
||||
<LokiLabelBrowser
|
||||
languageProvider={datasource.languageProvider}
|
||||
onChange={onChange}
|
||||
lastUsedLabels={lastUsedLabels}
|
||||
storeLastUsedLabels={onLastUsedLabelsSave}
|
||||
deleteLastUsedLabels={onLastUsedLabelsDelete}
|
||||
app={app}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
</LocalStorageValueProvider>
|
||||
)}
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user