mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
158 lines
4.7 KiB
TypeScript
158 lines
4.7 KiB
TypeScript
import { css } from '@emotion/css';
|
|
import React, { FormEvent } from 'react';
|
|
|
|
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
|
import { config } from '@grafana/runtime';
|
|
import { Button, Checkbox, Stack, RadioButtonGroup, useStyles2 } from '@grafana/ui';
|
|
import { SortPicker } from 'app/core/components/Select/SortPicker';
|
|
import { TagFilter, TermCount } from 'app/core/components/TagFilter/TagFilter';
|
|
import { t, Trans } from 'app/core/internationalization';
|
|
|
|
import { SearchLayout, SearchState } from '../../types';
|
|
|
|
function getLayoutOptions() {
|
|
return [
|
|
{
|
|
value: SearchLayout.Folders,
|
|
icon: 'folder',
|
|
description: t('search.actions.view-as-folders', 'View by folders'),
|
|
},
|
|
{ value: SearchLayout.List, icon: 'list-ul', description: t('search.actions.view-as-list', 'View as list') },
|
|
];
|
|
}
|
|
|
|
interface Props {
|
|
onLayoutChange: (layout: SearchLayout) => void;
|
|
onSortChange: (value?: string) => void;
|
|
onStarredFilterChange?: (event: FormEvent<HTMLInputElement>) => void;
|
|
onTagFilterChange: (tags: string[]) => void;
|
|
getTagOptions: () => Promise<TermCount[]>;
|
|
getSortOptions: () => Promise<SelectableValue[]>;
|
|
sortPlaceholder?: string;
|
|
onDatasourceChange: (ds?: string) => void;
|
|
onPanelTypeChange: (pt?: string) => void;
|
|
includePanels: boolean;
|
|
onSetIncludePanels: (v: boolean) => void;
|
|
state: SearchState;
|
|
showStarredFilter?: boolean;
|
|
hideLayout?: boolean;
|
|
}
|
|
|
|
export function getValidQueryLayout(q: SearchState): SearchLayout {
|
|
const layout = q.layout ?? SearchLayout.Folders;
|
|
|
|
// Folders is not valid when a query exists
|
|
if (layout === SearchLayout.Folders) {
|
|
if (q.query || q.sort || q.starred || q.tag.length > 0) {
|
|
return SearchLayout.List;
|
|
}
|
|
}
|
|
|
|
return layout;
|
|
}
|
|
|
|
export const ActionRow = ({
|
|
onLayoutChange,
|
|
onSortChange,
|
|
onStarredFilterChange = () => {},
|
|
onTagFilterChange,
|
|
getTagOptions,
|
|
getSortOptions,
|
|
sortPlaceholder,
|
|
onDatasourceChange,
|
|
onPanelTypeChange,
|
|
onSetIncludePanels,
|
|
state,
|
|
showStarredFilter,
|
|
hideLayout,
|
|
}: Props) => {
|
|
const styles = useStyles2(getStyles);
|
|
const layout = getValidQueryLayout(state);
|
|
|
|
// Disabled folder layout option when query is present
|
|
const disabledOptions =
|
|
state.tag.length || state.starred || state.query || state.datasource || state.panel_type
|
|
? [SearchLayout.Folders]
|
|
: [];
|
|
|
|
return (
|
|
<div className={styles.actionRow}>
|
|
<Stack gap={2} alignItems="center">
|
|
<TagFilter isClearable={false} tags={state.tag} tagOptions={getTagOptions} onChange={onTagFilterChange} />
|
|
{config.featureToggles.panelTitleSearch && (
|
|
<Checkbox
|
|
data-testid="include-panels"
|
|
disabled={layout === SearchLayout.Folders}
|
|
value={state.includePanels}
|
|
onChange={() => onSetIncludePanels(!state.includePanels)}
|
|
label={t('search.actions.include-panels', 'Include panels')}
|
|
/>
|
|
)}
|
|
|
|
{showStarredFilter && (
|
|
<div className={styles.checkboxWrapper}>
|
|
<Checkbox
|
|
label={t('search.actions.starred', 'Starred')}
|
|
onChange={onStarredFilterChange}
|
|
value={state.starred}
|
|
/>
|
|
</div>
|
|
)}
|
|
{state.datasource && (
|
|
<Button icon="times" variant="secondary" onClick={() => onDatasourceChange(undefined)}>
|
|
<Trans i18nKey="search.actions.remove-datasource-filter">
|
|
Datasource: {{ datasource: state.datasource }}
|
|
</Trans>
|
|
</Button>
|
|
)}
|
|
{state.panel_type && (
|
|
<Button icon="times" variant="secondary" onClick={() => onPanelTypeChange(undefined)}>
|
|
Panel: {state.panel_type}
|
|
</Button>
|
|
)}
|
|
</Stack>
|
|
|
|
<Stack gap={2}>
|
|
{!hideLayout && (
|
|
<RadioButtonGroup
|
|
options={getLayoutOptions()}
|
|
disabledOptions={disabledOptions}
|
|
onChange={onLayoutChange}
|
|
value={layout}
|
|
/>
|
|
)}
|
|
<SortPicker
|
|
onChange={(change) => onSortChange(change?.value)}
|
|
value={state.sort}
|
|
getSortOptions={getSortOptions}
|
|
placeholder={sortPlaceholder || t('search.actions.sort-placeholder', 'Sort')}
|
|
isClearable
|
|
/>
|
|
</Stack>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
ActionRow.displayName = 'ActionRow';
|
|
|
|
export const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
actionRow: css`
|
|
display: none;
|
|
|
|
${theme.breakpoints.up('md')} {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding-bottom: ${theme.spacing(2)};
|
|
width: 100%;
|
|
}
|
|
`,
|
|
checkboxWrapper: css`
|
|
label {
|
|
line-height: 1.2;
|
|
}
|
|
`,
|
|
};
|
|
};
|