mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
ManageDashboards: Fixes and improvements (#23879)
* ManageDashboards: Fixes and improvements * Fixed tests * Fixed issue with item height and margin
This commit is contained in:
parent
d6ba6440e4
commit
e505babbf4
@ -19,6 +19,7 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
labelStyles.label,
|
labelStyles.label,
|
||||||
css`
|
css`
|
||||||
padding-left: ${theme.spacing.formSpacingBase}px;
|
padding-left: ${theme.spacing.formSpacingBase}px;
|
||||||
|
white-space: nowrap;
|
||||||
`
|
`
|
||||||
),
|
),
|
||||||
description: cx(
|
description: cx(
|
||||||
@ -50,11 +51,13 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
* */
|
* */
|
||||||
&:checked + span {
|
&:checked + span {
|
||||||
background: blue;
|
background: blue;
|
||||||
background: ${theme.colors.formInputBg};
|
background: ${theme.colors.formCheckboxBgChecked};
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: ${theme.colors.formCheckboxBgCheckedHover};
|
background: ${theme.colors.formCheckboxBgCheckedHover};
|
||||||
}
|
}
|
||||||
|
|
||||||
&:after {
|
&:after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@ -79,6 +82,7 @@ export const getCheckboxStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
top: 1px;
|
top: 1px;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-color: ${theme.colors.formInputBorderHover};
|
border-color: ${theme.colors.formInputBorderHover};
|
||||||
|
@ -20,7 +20,12 @@ export const simple = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{renderScenario('body', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
|
{renderScenario(
|
||||||
|
'dashboard',
|
||||||
|
theme,
|
||||||
|
['sm', 'md', 'lg', 'xl', 'xxl'],
|
||||||
|
['search', 'trash-alt', 'arrow-left', 'times']
|
||||||
|
)}
|
||||||
{renderScenario('panel', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
|
{renderScenario('panel', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
|
||||||
{renderScenario('header', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
|
{renderScenario('header', theme, ['sm', 'md', 'lg', 'xl', 'xxl'], ['search', 'trash-alt', 'arrow-left', 'times'])}
|
||||||
</div>
|
</div>
|
||||||
@ -31,8 +36,8 @@ function renderScenario(surface: string, theme: GrafanaTheme, sizes: IconSize[],
|
|||||||
let bg: string = 'red';
|
let bg: string = 'red';
|
||||||
|
|
||||||
switch (surface) {
|
switch (surface) {
|
||||||
case 'body':
|
case 'dashboard':
|
||||||
bg = theme.colors.bodyBg;
|
bg = theme.colors.dashboardBg;
|
||||||
break;
|
break;
|
||||||
case 'panel':
|
case 'panel':
|
||||||
bg = theme.colors.bodyBg;
|
bg = theme.colors.bodyBg;
|
||||||
|
@ -18,7 +18,7 @@ export interface Props extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
|||||||
tooltipPlacement?: TooltipPlacement;
|
tooltipPlacement?: TooltipPlacement;
|
||||||
}
|
}
|
||||||
|
|
||||||
type SurfaceType = 'body' | 'panel' | 'header';
|
type SurfaceType = 'dashboard' | 'panel' | 'header';
|
||||||
|
|
||||||
export const IconButton = React.forwardRef<HTMLButtonElement, Props>(
|
export const IconButton = React.forwardRef<HTMLButtonElement, Props>(
|
||||||
({ name, size = 'md', surface = 'panel', iconType, tooltip, tooltipPlacement, className, ...restProps }, ref) => {
|
({ name, size = 'md', surface = 'panel', iconType, tooltip, tooltipPlacement, className, ...restProps }, ref) => {
|
||||||
@ -47,7 +47,7 @@ IconButton.displayName = 'IconButton';
|
|||||||
|
|
||||||
function getHoverColor(theme: GrafanaTheme, surface: SurfaceType): string {
|
function getHoverColor(theme: GrafanaTheme, surface: SurfaceType): string {
|
||||||
switch (surface) {
|
switch (surface) {
|
||||||
case 'body':
|
case 'dashboard':
|
||||||
return theme.isLight ? theme.palette.gray95 : theme.palette.gray15;
|
return theme.isLight ? theme.palette.gray95 : theme.palette.gray15;
|
||||||
case 'panel':
|
case 'panel':
|
||||||
return theme.isLight ? theme.palette.gray6 : theme.palette.gray15;
|
return theme.isLight ? theme.palette.gray6 : theme.palette.gray15;
|
||||||
|
@ -3,7 +3,7 @@ import { IconButton } from '@grafana/ui';
|
|||||||
import { e2e } from '@grafana/e2e';
|
import { e2e } from '@grafana/e2e';
|
||||||
|
|
||||||
export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
export interface Props extends ButtonHTMLAttributes<HTMLButtonElement> {
|
||||||
surface: 'body' | 'panel';
|
surface: 'dashboard' | 'panel' | 'header';
|
||||||
}
|
}
|
||||||
|
|
||||||
export const BackButton: React.FC<Props> = ({ surface, onClick }) => {
|
export const BackButton: React.FC<Props> = ({ surface, onClick }) => {
|
||||||
|
@ -143,7 +143,7 @@ class DashNav extends PureComponent<Props> {
|
|||||||
renderBackButton() {
|
renderBackButton() {
|
||||||
return (
|
return (
|
||||||
<div className="navbar-edit">
|
<div className="navbar-edit">
|
||||||
<BackButton surface="body" onClick={this.onClose} />
|
<BackButton surface="dashboard" onClick={this.onClose} />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ export class DashboardSettings extends PureComponent<Props> {
|
|||||||
<div className="dashboard-settings">
|
<div className="dashboard-settings">
|
||||||
<div className="navbar navbar--edit">
|
<div className="navbar navbar--edit">
|
||||||
<div className="navbar-edit">
|
<div className="navbar-edit">
|
||||||
<BackButton surface="body" onClick={this.onClose} />
|
<BackButton surface="panel" onClick={this.onClose} />
|
||||||
</div>
|
</div>
|
||||||
<div className="navbar-page-btn">
|
<div className="navbar-page-btn">
|
||||||
{haveFolder && <div className="navbar-page-btn__folder">{folderTitle} / </div>}
|
{haveFolder && <div className="navbar-page-btn__folder">{folderTitle} / </div>}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { Dispatch, FC, SetStateAction } from 'react';
|
import React, { Dispatch, FC, SetStateAction } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { HorizontalGroup, RadioButtonGroup, Select, stylesFactory, useTheme } from '@grafana/ui';
|
import { HorizontalGroup, RadioButtonGroup, stylesFactory, useTheme, Checkbox } from '@grafana/ui';
|
||||||
import { GrafanaTheme, SelectableValue } from '@grafana/data';
|
import { GrafanaTheme, SelectableValue } from '@grafana/data';
|
||||||
import { SortPicker } from 'app/core/components/Select/SortPicker';
|
import { SortPicker } from 'app/core/components/Select/SortPicker';
|
||||||
import { TagFilter } from 'app/core/components/TagFilter/TagFilter';
|
import { TagFilter } from 'app/core/components/TagFilter/TagFilter';
|
||||||
@ -8,11 +8,6 @@ import { SearchSrv } from 'app/core/services/search_srv';
|
|||||||
import { layoutOptions } from '../hooks/useSearchLayout';
|
import { layoutOptions } from '../hooks/useSearchLayout';
|
||||||
import { DashboardQuery } from '../types';
|
import { DashboardQuery } from '../types';
|
||||||
|
|
||||||
const starredFilterOptions = [
|
|
||||||
{ label: 'Yes', value: true },
|
|
||||||
{ label: 'No', value: false },
|
|
||||||
];
|
|
||||||
|
|
||||||
const searchSrv = new SearchSrv();
|
const searchSrv = new SearchSrv();
|
||||||
|
|
||||||
type onSelectChange = (value: SelectableValue) => void;
|
type onSelectChange = (value: SelectableValue) => void;
|
||||||
@ -24,7 +19,6 @@ interface Props {
|
|||||||
onTagFilterChange: onSelectChange;
|
onTagFilterChange: onSelectChange;
|
||||||
query: DashboardQuery;
|
query: DashboardQuery;
|
||||||
showStarredFilter?: boolean;
|
showStarredFilter?: boolean;
|
||||||
hideSelectedTags?: boolean;
|
|
||||||
hideLayout?: boolean;
|
hideLayout?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +30,6 @@ export const ActionRow: FC<Props> = ({
|
|||||||
onTagFilterChange,
|
onTagFilterChange,
|
||||||
query,
|
query,
|
||||||
showStarredFilter,
|
showStarredFilter,
|
||||||
hideSelectedTags,
|
|
||||||
hideLayout,
|
hideLayout,
|
||||||
}) => {
|
}) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@ -48,24 +41,13 @@ export const ActionRow: FC<Props> = ({
|
|||||||
{!hideLayout ? <RadioButtonGroup options={layoutOptions} onChange={onLayoutChange} value={layout} /> : null}
|
{!hideLayout ? <RadioButtonGroup options={layoutOptions} onChange={onLayoutChange} value={layout} /> : null}
|
||||||
<SortPicker onChange={onSortChange} value={query.sort} />
|
<SortPicker onChange={onSortChange} value={query.sort} />
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
<HorizontalGroup spacing="md" justify="space-between">
|
<HorizontalGroup spacing="md" width="auto">
|
||||||
{showStarredFilter && (
|
{showStarredFilter && <Checkbox label="Filter by starred" onChange={onStarredFilterChange} />}
|
||||||
<Select
|
|
||||||
width={20}
|
|
||||||
placeholder="Filter by starred"
|
|
||||||
key={starredFilterOptions?.find(f => f.value === query.starred)?.label}
|
|
||||||
options={starredFilterOptions}
|
|
||||||
onChange={onStarredFilterChange}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<TagFilter
|
<TagFilter
|
||||||
placeholder="Filter by tag"
|
placeholder="Filter by tag"
|
||||||
tags={query.tag}
|
tags={query.tag}
|
||||||
tagOptions={searchSrv.getDashboardTags}
|
tagOptions={searchSrv.getDashboardTags}
|
||||||
onChange={onTagFilterChange}
|
onChange={onTagFilterChange}
|
||||||
hideValues={hideSelectedTags}
|
|
||||||
isClearable={!hideSelectedTags}
|
|
||||||
/>
|
/>
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
</div>
|
</div>
|
||||||
|
@ -76,8 +76,10 @@ describe('DashboardSearch', () => {
|
|||||||
|
|
||||||
wrapper.update();
|
wrapper.update();
|
||||||
expect(
|
expect(
|
||||||
wrapper.findWhere((c: any) => c.type() === 'h6' && c.text() === 'No dashboards matching your query were found.')
|
wrapper
|
||||||
).toHaveLength(1);
|
.findWhere((c: any) => c.type() === 'div' && c.text() === 'No dashboards matching your query were found.')
|
||||||
|
.exists()
|
||||||
|
).toBe(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render search results', async () => {
|
it('should render search results', async () => {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React, { FC, memo, useState } from 'react';
|
import React, { FC, memo, useState } from 'react';
|
||||||
import { css } from 'emotion';
|
import { css } from 'emotion';
|
||||||
import { HorizontalGroup, Icon, stylesFactory, TagList, useTheme } from '@grafana/ui';
|
import { HorizontalGroup, stylesFactory, useTheme } from '@grafana/ui';
|
||||||
import { GrafanaTheme } from '@grafana/data';
|
import { GrafanaTheme } from '@grafana/data';
|
||||||
import { contextSrv } from 'app/core/services/context_srv';
|
import { contextSrv } from 'app/core/services/context_srv';
|
||||||
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA';
|
||||||
@ -32,9 +32,6 @@ export const ManageDashboards: FC<Props> = memo(({ folderId, folderUid }) => {
|
|||||||
query,
|
query,
|
||||||
hasFilters,
|
hasFilters,
|
||||||
onQueryChange,
|
onQueryChange,
|
||||||
onRemoveStarred,
|
|
||||||
onTagRemove,
|
|
||||||
onClearFilters,
|
|
||||||
onTagFilterChange,
|
onTagFilterChange,
|
||||||
onStarredFilterChange,
|
onStarredFilterChange,
|
||||||
onTagAdd,
|
onTagAdd,
|
||||||
@ -102,72 +99,24 @@ export const ManageDashboards: FC<Props> = memo(({ folderId, folderUid }) => {
|
|||||||
/>
|
/>
|
||||||
<DashboardActions isEditor={isEditor} canEdit={hasEditPermissionInFolders || canSave} folderId={folderId} />
|
<DashboardActions isEditor={isEditor} canEdit={hasEditPermissionInFolders || canSave} folderId={folderId} />
|
||||||
</HorizontalGroup>
|
</HorizontalGroup>
|
||||||
|
|
||||||
{hasFilters && (
|
|
||||||
<HorizontalGroup>
|
|
||||||
<div className="gf-form-inline">
|
|
||||||
{query.tag.length > 0 && (
|
|
||||||
<div className="gf-form">
|
|
||||||
<label className="gf-form-label width-4">Tags</label>
|
|
||||||
<TagList tags={query.tag} onClick={onTagRemove} />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{query.starred && (
|
|
||||||
<div className="gf-form">
|
|
||||||
<label className="gf-form-label">
|
|
||||||
<a className="pointer" onClick={onRemoveStarred}>
|
|
||||||
<Icon name="check" />
|
|
||||||
Starred
|
|
||||||
</a>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
{query.sort && (
|
|
||||||
<div className="gf-form">
|
|
||||||
<label className="gf-form-label">
|
|
||||||
<a className="pointer" onClick={() => onSortChange(null)}>
|
|
||||||
Sort: {query.sort.label}
|
|
||||||
</a>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="gf-form">
|
|
||||||
<label className="gf-form-label">
|
|
||||||
<a
|
|
||||||
className="pointer"
|
|
||||||
onClick={() => {
|
|
||||||
onClearFilters();
|
|
||||||
setLayout(SearchLayout.Folders);
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Icon name="times" />
|
|
||||||
Clear
|
|
||||||
</a>
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</HorizontalGroup>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={styles.results}>
|
<div className={styles.results}>
|
||||||
{results?.length > 0 && (
|
<SearchResultsFilter
|
||||||
<SearchResultsFilter
|
allChecked={allChecked}
|
||||||
allChecked={allChecked}
|
canDelete={canDelete}
|
||||||
canDelete={canDelete}
|
canMove={canMove}
|
||||||
canMove={canMove}
|
deleteItem={onItemDelete}
|
||||||
deleteItem={onItemDelete}
|
moveTo={onMoveTo}
|
||||||
moveTo={onMoveTo}
|
onToggleAllChecked={onToggleAllChecked}
|
||||||
onToggleAllChecked={onToggleAllChecked}
|
onStarredFilterChange={onStarredFilterChange}
|
||||||
onStarredFilterChange={onStarredFilterChange}
|
onSortChange={onSortChange}
|
||||||
onSortChange={onSortChange}
|
onTagFilterChange={onTagFilterChange}
|
||||||
onTagFilterChange={onTagFilterChange}
|
query={query}
|
||||||
query={query}
|
layout={layout}
|
||||||
layout={layout}
|
hideLayout={!!folderUid}
|
||||||
hideLayout={!!folderUid}
|
onLayoutChange={onLayoutChange}
|
||||||
onLayoutChange={onLayoutChange}
|
/>
|
||||||
/>
|
|
||||||
)}
|
|
||||||
<SearchResults
|
<SearchResults
|
||||||
loading={loading}
|
loading={loading}
|
||||||
results={results}
|
results={results}
|
||||||
|
@ -68,7 +68,13 @@ export const SearchResults: FC<Props> = ({
|
|||||||
>
|
>
|
||||||
{({ index, style }) => {
|
{({ index, style }) => {
|
||||||
const item = items[index];
|
const item = items[index];
|
||||||
return <SearchItem key={item.id} {...itemProps} item={item} style={style} />;
|
// The wrapper div is needed as the inner SearchItem has margin-bottom spacing
|
||||||
|
// And without this wrapper there is no room for that margin
|
||||||
|
return (
|
||||||
|
<div style={style}>
|
||||||
|
<SearchItem key={item.id} {...itemProps} item={item} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
}}
|
}}
|
||||||
</FixedSizeList>
|
</FixedSizeList>
|
||||||
)}
|
)}
|
||||||
@ -80,7 +86,7 @@ export const SearchResults: FC<Props> = ({
|
|||||||
if (loading) {
|
if (loading) {
|
||||||
return <Spinner className={styles.spinner} />;
|
return <Spinner className={styles.spinner} />;
|
||||||
} else if (!results || !results.length) {
|
} else if (!results || !results.length) {
|
||||||
return <h6>No dashboards matching your query were found.</h6>;
|
return <div className={styles.noResults}>No dashboards matching your query were found.</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -120,6 +126,11 @@ const getSectionStyles = stylesFactory((theme: GrafanaTheme) => {
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
`,
|
`,
|
||||||
|
noResults: css`
|
||||||
|
padding: ${md};
|
||||||
|
background: ${theme.colors.bg2};
|
||||||
|
text-style: italic;
|
||||||
|
`,
|
||||||
listModeWrapper: css`
|
listModeWrapper: css`
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -38,24 +38,21 @@ describe('SearchResultsFilter', () => {
|
|||||||
it('should render "filter by starred" and "filter by tag" filters by default', () => {
|
it('should render "filter by starred" and "filter by tag" filters by default', () => {
|
||||||
const { wrapper } = setup();
|
const { wrapper } = setup();
|
||||||
const ActionRow = wrapper.find('ActionRow').shallow();
|
const ActionRow = wrapper.find('ActionRow').shallow();
|
||||||
expect(ActionRow.find({ placeholder: 'Filter by starred' })).toHaveLength(1);
|
expect(ActionRow.find('Checkbox')).toHaveLength(1);
|
||||||
expect(ActionRow.find({ placeholder: 'Filter by tag' })).toHaveLength(1);
|
|
||||||
expect(findBtnByText(wrapper, 'Move')).toHaveLength(0);
|
expect(findBtnByText(wrapper, 'Move')).toHaveLength(0);
|
||||||
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(0);
|
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Move and Delete buttons when canDelete is true', () => {
|
it('should render Move and Delete buttons when canDelete is true', () => {
|
||||||
const { wrapper } = setup({ canDelete: true });
|
const { wrapper } = setup({ canDelete: true });
|
||||||
expect(wrapper.find({ placeholder: 'Filter by starred' })).toHaveLength(0);
|
expect(wrapper.find('Checkbox')).toHaveLength(1);
|
||||||
expect(wrapper.find({ placeholder: 'Filter by tag' })).toHaveLength(0);
|
|
||||||
expect(findBtnByText(wrapper, 'Move')).toHaveLength(1);
|
expect(findBtnByText(wrapper, 'Move')).toHaveLength(1);
|
||||||
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(1);
|
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render Move and Delete buttons when canMove is true', () => {
|
it('should render Move and Delete buttons when canMove is true', () => {
|
||||||
const { wrapper } = setup({ canMove: true });
|
const { wrapper } = setup({ canMove: true });
|
||||||
expect(wrapper.find({ placeholder: 'Filter by starred' })).toHaveLength(0);
|
expect(wrapper.find('Checkbox')).toHaveLength(1);
|
||||||
expect(wrapper.find({ placeholder: 'Filter by tag' })).toHaveLength(0);
|
|
||||||
expect(findBtnByText(wrapper, 'Move')).toHaveLength(1);
|
expect(findBtnByText(wrapper, 'Move')).toHaveLength(1);
|
||||||
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(1);
|
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(1);
|
||||||
});
|
});
|
||||||
@ -66,9 +63,10 @@ describe('SearchResultsFilter', () => {
|
|||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
const { wrapper } = setup({ onStarredFilterChange: mockFilterStarred }, mount);
|
const { wrapper } = setup({ onStarredFilterChange: mockFilterStarred }, mount);
|
||||||
wrapper
|
wrapper
|
||||||
.find({ placeholder: 'Filter by starred' })
|
.find('Checkbox')
|
||||||
.at(0)
|
.at(1)
|
||||||
.prop('onChange')(option);
|
.prop('onChange')(option as any);
|
||||||
|
|
||||||
expect(mockFilterStarred).toHaveBeenCalledTimes(1);
|
expect(mockFilterStarred).toHaveBeenCalledTimes(1);
|
||||||
expect(mockFilterStarred).toHaveBeenCalledWith(option);
|
expect(mockFilterStarred).toHaveBeenCalledWith(option);
|
||||||
});
|
});
|
||||||
|
@ -66,7 +66,6 @@ export const SearchResultsFilter: FC<Props> = ({
|
|||||||
query,
|
query,
|
||||||
}}
|
}}
|
||||||
showStarredFilter
|
showStarredFilter
|
||||||
hideSelectedTags
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,16 +1,7 @@
|
|||||||
import { useReducer } from 'react';
|
import { useReducer } from 'react';
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { defaultQuery, queryReducer } from '../reducers/searchQueryReducer';
|
import { defaultQuery, queryReducer } from '../reducers/searchQueryReducer';
|
||||||
import {
|
import { ADD_TAG, CLEAR_FILTERS, QUERY_CHANGE, SET_TAGS, TOGGLE_SORT, TOGGLE_STARRED } from '../reducers/actionTypes';
|
||||||
ADD_TAG,
|
|
||||||
CLEAR_FILTERS,
|
|
||||||
QUERY_CHANGE,
|
|
||||||
REMOVE_STARRED,
|
|
||||||
REMOVE_TAG,
|
|
||||||
SET_TAGS,
|
|
||||||
TOGGLE_SORT,
|
|
||||||
TOGGLE_STARRED,
|
|
||||||
} from '../reducers/actionTypes';
|
|
||||||
import { DashboardQuery } from '../types';
|
import { DashboardQuery } from '../types';
|
||||||
import { hasFilters } from '../utils';
|
import { hasFilters } from '../utils';
|
||||||
|
|
||||||
@ -22,14 +13,6 @@ export const useSearchQuery = (queryParams: Partial<DashboardQuery>) => {
|
|||||||
dispatch({ type: QUERY_CHANGE, payload: query });
|
dispatch({ type: QUERY_CHANGE, payload: query });
|
||||||
};
|
};
|
||||||
|
|
||||||
const onRemoveStarred = () => {
|
|
||||||
dispatch({ type: REMOVE_STARRED });
|
|
||||||
};
|
|
||||||
|
|
||||||
const onTagRemove = (tag: string) => {
|
|
||||||
dispatch({ type: REMOVE_TAG, payload: tag });
|
|
||||||
};
|
|
||||||
|
|
||||||
const onTagFilterChange = (tags: string[]) => {
|
const onTagFilterChange = (tags: string[]) => {
|
||||||
dispatch({ type: SET_TAGS, payload: tags });
|
dispatch({ type: SET_TAGS, payload: tags });
|
||||||
};
|
};
|
||||||
@ -54,8 +37,6 @@ export const useSearchQuery = (queryParams: Partial<DashboardQuery>) => {
|
|||||||
query,
|
query,
|
||||||
hasFilters: hasFilters(query),
|
hasFilters: hasFilters(query),
|
||||||
onQueryChange,
|
onQueryChange,
|
||||||
onRemoveStarred,
|
|
||||||
onTagRemove,
|
|
||||||
onClearFilters,
|
onClearFilters,
|
||||||
onTagFilterChange,
|
onTagFilterChange,
|
||||||
onStarredFilterChange,
|
onStarredFilterChange,
|
||||||
|
Loading…
Reference in New Issue
Block a user