mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Search/migrate search filter actions (#23133)
* Search: Initial setup * Search: Use icon prop * Search: Add button variants * Search: Enable toggle all * Search: Fix starred filter * Search: update tests * Search: Enable filters * Search: Use emotion styling * Search: Enable dashboard deleting * Search: Enable dashboard moving * Search: Update tests * Search: Add SearchResultsFilter.test.tsx * Search: Tweak types * Search: Remove onReset * Search: Remove redundant fragment * Search: Use HorizontalGroup * Search: Alight top checkbox
This commit is contained in:
parent
9c9f6f168b
commit
ce3a1fc56c
@ -28,7 +28,7 @@ import {
|
|||||||
SaveDashboardButtonConnected,
|
SaveDashboardButtonConnected,
|
||||||
} from '../features/dashboard/components/SaveDashboard/SaveDashboardButton';
|
} from '../features/dashboard/components/SaveDashboard/SaveDashboardButton';
|
||||||
import { VariableEditorContainer } from '../features/variables/editor/VariableEditorContainer';
|
import { VariableEditorContainer } from '../features/variables/editor/VariableEditorContainer';
|
||||||
import { SearchField, SearchResults } from '../features/search';
|
import { SearchField, SearchResults, SearchResultsFilter } from '../features/search';
|
||||||
|
|
||||||
export function registerAngularDirectives() {
|
export function registerAngularDirectives() {
|
||||||
react2AngularDirective('footer', Footer, []);
|
react2AngularDirective('footer', Footer, []);
|
||||||
@ -66,6 +66,19 @@ export function registerAngularDirectives() {
|
|||||||
['onFolderExpanding', { watchDepth: 'reference' }],
|
['onFolderExpanding', { watchDepth: 'reference' }],
|
||||||
['onToggleSelection', { watchDepth: 'reference' }],
|
['onToggleSelection', { watchDepth: 'reference' }],
|
||||||
]);
|
]);
|
||||||
|
react2AngularDirective('searchFilters', SearchResultsFilter, [
|
||||||
|
'allChecked',
|
||||||
|
'canMove',
|
||||||
|
'canDelete',
|
||||||
|
'tagFilterOptions',
|
||||||
|
'selectedStarredFilter',
|
||||||
|
'selectedTagFilter',
|
||||||
|
['onSelectAllChanged', { watchDepth: 'reference' }],
|
||||||
|
['deleteItem', { watchDepth: 'reference' }],
|
||||||
|
['moveTo', { watchDepth: 'reference' }],
|
||||||
|
['onStarredFilterChange', { watchDepth: 'reference' }],
|
||||||
|
['onTagFilterChange', { watchDepth: 'reference' }],
|
||||||
|
]);
|
||||||
react2AngularDirective('tagFilter', TagFilter, [
|
react2AngularDirective('tagFilter', TagFilter, [
|
||||||
'tags',
|
'tags',
|
||||||
['onChange', { watchDepth: 'reference' }],
|
['onChange', { watchDepth: 'reference' }],
|
||||||
|
@ -60,47 +60,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="search-results" ng-show="ctrl.sections.length > 0">
|
<div class="search-results" ng-show="ctrl.sections.length > 0">
|
||||||
<div class="search-results-filter-row">
|
<search-filters
|
||||||
<gf-form-checkbox
|
on-select-all-changed="ctrl.onSelectAllChanged"
|
||||||
on-change="ctrl.onSelectAllChanged()"
|
all-checked="ctrl.selectAllChecked"
|
||||||
checked="ctrl.selectAllChecked"
|
can-move="ctrl.canMove"
|
||||||
switch-class="gf-form-checkbox--transparent"
|
can-delete="ctrl.canDelete"
|
||||||
/>
|
move-to="ctrl.moveTo"
|
||||||
<div class="search-results-filter-row__filters">
|
delete-item="ctrl.delete"
|
||||||
<div class="gf-form-select-wrapper" ng-show="!(ctrl.canMove || ctrl.canDelete)">
|
tag-filter-options="ctrl.tagFilterOptions"
|
||||||
<select
|
selected-starred-filter="ctrl.selectedStarredFilter"
|
||||||
class="search-results-filter-row__filters-item gf-form-input"
|
on-starred-filter-change="ctrl.onStarredFilterChange"
|
||||||
ng-model="ctrl.selectedStarredFilter"
|
selected-tag-filter="ctrl.selectedTagFilter"
|
||||||
ng-options="t.text disable when t.disabled for t in ctrl.starredFilterOptions"
|
on-tagfilter-change="ctrl.onTagFilterChange"
|
||||||
ng-change="ctrl.onStarredFilterChange()"
|
/>
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form-select-wrapper" ng-show="!(ctrl.canMove || ctrl.canDelete)">
|
|
||||||
<select
|
|
||||||
class="search-results-filter-row__filters-item gf-form-input"
|
|
||||||
ng-model="ctrl.selectedTagFilter"
|
|
||||||
ng-options="t.term disable when t.disabled for t in ctrl.tagFilterOptions"
|
|
||||||
ng-change="ctrl.onTagFilterChange()"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="gf-form-button-row" ng-show="ctrl.canMove || ctrl.canDelete">
|
|
||||||
<button type="button"
|
|
||||||
class="btn gf-form-button btn-inverse"
|
|
||||||
ng-disabled="!ctrl.canMove"
|
|
||||||
ng-click="ctrl.moveTo()"
|
|
||||||
bs-tooltip="ctrl.canMove ? '' : 'Select a dashboard to move (cannot move folders)'"
|
|
||||||
data-placement="bottom">
|
|
||||||
<i class="fa fa-exchange"></i> Move
|
|
||||||
</button>
|
|
||||||
<button type="button"
|
|
||||||
class="btn gf-form-button btn-danger"
|
|
||||||
ng-click="ctrl.delete()"
|
|
||||||
ng-disabled="!ctrl.canDelete">
|
|
||||||
<i class="fa fa-trash"></i> Delete
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="search-results-container">
|
<div class="search-results-container">
|
||||||
<search-results
|
<search-results
|
||||||
results="ctrl.sections"
|
results="ctrl.sections"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { IScope } from 'angular';
|
import { IScope } from 'angular';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import { SelectableValue } from '@grafana/data';
|
||||||
import coreModule from 'app/core/core_module';
|
import coreModule from 'app/core/core_module';
|
||||||
import appEvents from 'app/core/app_events';
|
import appEvents from 'app/core/app_events';
|
||||||
import { SearchSrv } from 'app/core/services/search_srv';
|
import { SearchSrv } from 'app/core/services/search_srv';
|
||||||
@ -54,7 +55,6 @@ export class ManageDashboardsCtrl {
|
|||||||
hasFilters = false;
|
hasFilters = false;
|
||||||
tagFilterOptions: any[];
|
tagFilterOptions: any[];
|
||||||
selectedTagFilter: any;
|
selectedTagFilter: any;
|
||||||
starredFilterOptions = [{ text: 'Filter by Starred', disabled: true }, { text: 'Yes' }, { text: 'No' }];
|
|
||||||
selectedStarredFilter: any;
|
selectedStarredFilter: any;
|
||||||
|
|
||||||
// used when managing dashboards for a specific folder
|
// used when managing dashboards for a specific folder
|
||||||
@ -88,8 +88,6 @@ export class ManageDashboardsCtrl {
|
|||||||
this.query.folderIds = [this.folderId];
|
this.query.folderIds = [this.folderId];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.selectedStarredFilter = this.starredFilterOptions[0];
|
|
||||||
|
|
||||||
this.refreshList().then(() => {
|
this.refreshList().then(() => {
|
||||||
this.initTagFilter();
|
this.initTagFilter();
|
||||||
});
|
});
|
||||||
@ -185,7 +183,7 @@ export class ManageDashboardsCtrl {
|
|||||||
return ids;
|
return ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
delete() {
|
delete = () => {
|
||||||
const data = this.getFoldersAndDashboardsToDelete();
|
const data = this.getFoldersAndDashboardsToDelete();
|
||||||
const folderCount = data.folderUids.length;
|
const folderCount = data.folderUids.length;
|
||||||
const dashCount = data.dashboardUids.length;
|
const dashCount = data.dashboardUids.length;
|
||||||
@ -211,7 +209,7 @@ export class ManageDashboardsCtrl {
|
|||||||
this.deleteFoldersAndDashboards(data.folderUids, data.dashboardUids);
|
this.deleteFoldersAndDashboards(data.folderUids, data.dashboardUids);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
private deleteFoldersAndDashboards(folderUids: string[], dashboardUids: string[]) {
|
private deleteFoldersAndDashboards(folderUids: string[], dashboardUids: string[]) {
|
||||||
promiseToDigest(this.$scope)(
|
promiseToDigest(this.$scope)(
|
||||||
@ -232,7 +230,7 @@ export class ManageDashboardsCtrl {
|
|||||||
return selectedDashboards;
|
return selectedDashboards;
|
||||||
}
|
}
|
||||||
|
|
||||||
moveTo() {
|
moveTo = () => {
|
||||||
const selectedDashboards = this.getDashboardsToMove();
|
const selectedDashboards = this.getDashboardsToMove();
|
||||||
|
|
||||||
const template =
|
const template =
|
||||||
@ -247,12 +245,11 @@ export class ManageDashboardsCtrl {
|
|||||||
afterSave: this.refreshList.bind(this),
|
afterSave: this.refreshList.bind(this),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
initTagFilter() {
|
initTagFilter() {
|
||||||
return this.searchSrv.getDashboardTags().then((results: any) => {
|
return this.searchSrv.getDashboardTags().then((results: any) => {
|
||||||
this.tagFilterOptions = [{ term: 'Filter By Tag', disabled: true }].concat(results);
|
this.tagFilterOptions = results.map((result: any) => ({ value: result.term, label: result.term }));
|
||||||
this.selectedTagFilter = this.tagFilterOptions[0];
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,11 +266,11 @@ export class ManageDashboardsCtrl {
|
|||||||
return this.refreshList();
|
return this.refreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
onTagFilterChange() {
|
onTagFilterChange = (filter: SelectableValue) => {
|
||||||
const res = this.filterByTag(this.selectedTagFilter.term);
|
const res = this.filterByTag(filter.value);
|
||||||
this.selectedTagFilter = this.tagFilterOptions[0];
|
this.selectedTagFilter = filter.value;
|
||||||
return res;
|
return res;
|
||||||
}
|
};
|
||||||
|
|
||||||
removeTag(tag: any, evt: Event) {
|
removeTag(tag: any, evt: Event) {
|
||||||
this.query.tag = _.without(this.query.tag, tag);
|
this.query.tag = _.without(this.query.tag, tag);
|
||||||
@ -289,13 +286,15 @@ export class ManageDashboardsCtrl {
|
|||||||
return this.refreshList();
|
return this.refreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
onStarredFilterChange() {
|
onStarredFilterChange = (filter: SelectableValue) => {
|
||||||
this.query.starred = this.selectedStarredFilter.text === 'Yes';
|
this.query.starred = filter.value;
|
||||||
this.selectedStarredFilter = this.starredFilterOptions[0];
|
this.selectedStarredFilter = filter.value;
|
||||||
return this.refreshList();
|
return this.refreshList();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
onSelectAllChanged = () => {
|
||||||
|
this.selectAllChecked = !this.selectAllChecked;
|
||||||
|
|
||||||
onSelectAllChanged() {
|
|
||||||
for (const section of this.sections) {
|
for (const section of this.sections) {
|
||||||
if (!section.hideHeader) {
|
if (!section.hideHeader) {
|
||||||
section.checked = this.selectAllChecked;
|
section.checked = this.selectAllChecked;
|
||||||
@ -306,14 +305,15 @@ export class ManageDashboardsCtrl {
|
|||||||
return item;
|
return item;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.selectionChanged();
|
this.selectionChanged();
|
||||||
}
|
};
|
||||||
|
|
||||||
clearFilters() {
|
clearFilters() {
|
||||||
this.query.query = '';
|
this.query.query = '';
|
||||||
this.query.tag = [];
|
this.query.tag = [];
|
||||||
this.query.starred = false;
|
this.query.starred = false;
|
||||||
|
this.selectedStarredFilter = 'starred';
|
||||||
|
this.selectedTagFilter = 'tag';
|
||||||
this.refreshList();
|
this.refreshList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ describe('ManageDashboards', () => {
|
|||||||
|
|
||||||
describe('when select all is checked', () => {
|
describe('when select all is checked', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctrl.selectAllChecked = true;
|
ctrl.selectAllChecked = false;
|
||||||
ctrl.onSelectAllChanged();
|
ctrl.onSelectAllChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -245,10 +245,10 @@ describe('ManageDashboards', () => {
|
|||||||
|
|
||||||
describe('with starred filter', () => {
|
describe('with starred filter', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
const yesOption: any = ctrl.starredFilterOptions[1];
|
const yesOption: any = { label: 'Yes', value: true };
|
||||||
|
|
||||||
ctrl.selectedStarredFilter = yesOption;
|
ctrl.selectedStarredFilter = yesOption;
|
||||||
return ctrl.onStarredFilterChange();
|
return ctrl.onStarredFilterChange(yesOption);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should set starred filter', () => {
|
it('should set starred filter', () => {
|
||||||
@ -306,7 +306,7 @@ describe('ManageDashboards', () => {
|
|||||||
|
|
||||||
describe('when select all is checked', () => {
|
describe('when select all is checked', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctrl.selectAllChecked = true;
|
ctrl.selectAllChecked = false;
|
||||||
ctrl.onSelectAllChanged();
|
ctrl.onSelectAllChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -354,7 +354,7 @@ describe('ManageDashboards', () => {
|
|||||||
|
|
||||||
describe('when select all is unchecked', () => {
|
describe('when select all is unchecked', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
ctrl.selectAllChecked = false;
|
ctrl.selectAllChecked = true;
|
||||||
ctrl.onSelectAllChanged();
|
ctrl.onSelectAllChanged();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -0,0 +1,97 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { mount, shallow } from 'enzyme';
|
||||||
|
import { SearchResultsFilter, Props } from './SearchResultsFilter';
|
||||||
|
|
||||||
|
const noop = jest.fn();
|
||||||
|
|
||||||
|
const findBtnByText = (wrapper: any, text: string) =>
|
||||||
|
wrapper.findWhere((c: any) => c.name() === 'Button' && c.text() === text);
|
||||||
|
|
||||||
|
const setup = (propOverrides?: Partial<Props>, renderMethod = shallow) => {
|
||||||
|
const props: Props = {
|
||||||
|
//@ts-ignore
|
||||||
|
allChecked: false,
|
||||||
|
canDelete: false,
|
||||||
|
canMove: false,
|
||||||
|
deleteItem: noop,
|
||||||
|
moveTo: noop,
|
||||||
|
onSelectAllChanged: noop,
|
||||||
|
onStarredFilterChange: noop,
|
||||||
|
onTagFilterChange: noop,
|
||||||
|
selectedStarredFilter: 'starred',
|
||||||
|
selectedTagFilter: 'tag',
|
||||||
|
tagFilterOptions: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
Object.assign(props, propOverrides);
|
||||||
|
|
||||||
|
const wrapper = renderMethod(<SearchResultsFilter {...props} />);
|
||||||
|
const instance = wrapper.instance();
|
||||||
|
|
||||||
|
return {
|
||||||
|
wrapper,
|
||||||
|
instance,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('SearchResultsFilter', () => {
|
||||||
|
it('should render "filter by starred" and "filter by tag" filters by default', () => {
|
||||||
|
const { wrapper } = setup();
|
||||||
|
expect(wrapper.find({ placeholder: 'Filter by starred' })).toHaveLength(1);
|
||||||
|
expect(wrapper.find({ placeholder: 'Filter by tag' })).toHaveLength(1);
|
||||||
|
expect(findBtnByText(wrapper, 'Move')).toHaveLength(0);
|
||||||
|
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render Move and Delete buttons when canDelete is true', () => {
|
||||||
|
const { wrapper } = setup({ canDelete: true });
|
||||||
|
expect(wrapper.find({ placeholder: 'Filter by starred' })).toHaveLength(0);
|
||||||
|
expect(wrapper.find({ placeholder: 'Filter by tag' })).toHaveLength(0);
|
||||||
|
expect(findBtnByText(wrapper, 'Move')).toHaveLength(1);
|
||||||
|
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should render Move and Delete buttons when canMove is true', () => {
|
||||||
|
const { wrapper } = setup({ canMove: true });
|
||||||
|
expect(wrapper.find({ placeholder: 'Filter by starred' })).toHaveLength(0);
|
||||||
|
expect(wrapper.find({ placeholder: 'Filter by tag' })).toHaveLength(0);
|
||||||
|
expect(findBtnByText(wrapper, 'Move')).toHaveLength(1);
|
||||||
|
expect(findBtnByText(wrapper, 'Delete')).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be called with proper filter option when "filter by starred" is changed', () => {
|
||||||
|
const mockFilterStarred = jest.fn();
|
||||||
|
const option = { value: true, label: 'Yes' };
|
||||||
|
//@ts-ignore
|
||||||
|
const { wrapper } = setup({ onStarredFilterChange: mockFilterStarred }, mount);
|
||||||
|
wrapper
|
||||||
|
.find({ placeholder: 'Filter by starred' })
|
||||||
|
.at(0)
|
||||||
|
.prop('onChange')(option);
|
||||||
|
expect(mockFilterStarred).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockFilterStarred).toHaveBeenCalledWith(option);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be called with proper filter option when "filter by tags" is changed', () => {
|
||||||
|
const mockFilterByTags = jest.fn();
|
||||||
|
const tags = [
|
||||||
|
{ value: 'tag1', label: 'Tag 1' },
|
||||||
|
{ value: 'tag2', label: 'Tag 2' },
|
||||||
|
];
|
||||||
|
//@ts-ignore
|
||||||
|
const { wrapper } = setup({ onTagFilterChange: mockFilterByTags, tagFilterOptions: tags }, mount);
|
||||||
|
wrapper
|
||||||
|
.find({ placeholder: 'Filter by tag' })
|
||||||
|
.at(0)
|
||||||
|
.prop('onChange')(tags[0]);
|
||||||
|
expect(mockFilterByTags).toHaveBeenCalledTimes(1);
|
||||||
|
expect(mockFilterByTags).toHaveBeenCalledWith(tags[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should call "onSelectAllChanged" when checkbox is changed', () => {
|
||||||
|
const mockSelectAll = jest.fn();
|
||||||
|
const { wrapper } = setup({ onSelectAllChanged: mockSelectAll });
|
||||||
|
wrapper.find('Checkbox').simulate('change');
|
||||||
|
expect(mockSelectAll).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
});
|
@ -0,0 +1,93 @@
|
|||||||
|
import React, { FC } from 'react';
|
||||||
|
import { css } from 'emotion';
|
||||||
|
import { Button, Forms, stylesFactory, useTheme, HorizontalGroup } from '@grafana/ui';
|
||||||
|
import { GrafanaTheme, SelectableValue } from '@grafana/data';
|
||||||
|
|
||||||
|
type onSelectChange = (value: SelectableValue) => void;
|
||||||
|
|
||||||
|
export interface Props {
|
||||||
|
allChecked?: boolean;
|
||||||
|
canDelete?: boolean;
|
||||||
|
canMove?: boolean;
|
||||||
|
deleteItem: () => void;
|
||||||
|
moveTo: () => void;
|
||||||
|
onSelectAllChanged: any;
|
||||||
|
onStarredFilterChange: onSelectChange;
|
||||||
|
onTagFilterChange: onSelectChange;
|
||||||
|
selectedStarredFilter: string;
|
||||||
|
selectedTagFilter: string;
|
||||||
|
tagFilterOptions: SelectableValue[];
|
||||||
|
}
|
||||||
|
|
||||||
|
const starredFilterOptions = [
|
||||||
|
{ label: 'Yes', value: true },
|
||||||
|
{ label: 'No', value: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
export const SearchResultsFilter: FC<Props> = ({
|
||||||
|
allChecked,
|
||||||
|
canDelete,
|
||||||
|
canMove,
|
||||||
|
deleteItem,
|
||||||
|
moveTo,
|
||||||
|
onSelectAllChanged,
|
||||||
|
onStarredFilterChange,
|
||||||
|
onTagFilterChange,
|
||||||
|
selectedStarredFilter,
|
||||||
|
selectedTagFilter,
|
||||||
|
tagFilterOptions,
|
||||||
|
}) => {
|
||||||
|
const showActions = canDelete || canMove;
|
||||||
|
const theme = useTheme();
|
||||||
|
const styles = getStyles(theme);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={styles.wrapper}>
|
||||||
|
<Forms.Checkbox value={allChecked} onChange={onSelectAllChanged} />
|
||||||
|
{showActions ? (
|
||||||
|
<HorizontalGroup spacing="md">
|
||||||
|
<Button disabled={!canMove} onClick={moveTo} icon="fa fa-exchange" variant="secondary">
|
||||||
|
Move
|
||||||
|
</Button>
|
||||||
|
<Button disabled={!canDelete} onClick={deleteItem} icon="fa fa-trash" variant="destructive">
|
||||||
|
Delete
|
||||||
|
</Button>
|
||||||
|
</HorizontalGroup>
|
||||||
|
) : (
|
||||||
|
<HorizontalGroup spacing="md">
|
||||||
|
<Forms.Select
|
||||||
|
size="sm"
|
||||||
|
placeholder="Filter by starred"
|
||||||
|
key={selectedStarredFilter}
|
||||||
|
options={starredFilterOptions}
|
||||||
|
onChange={onStarredFilterChange}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Forms.Select
|
||||||
|
size="sm"
|
||||||
|
placeholder="Filter by tag"
|
||||||
|
key={selectedTagFilter}
|
||||||
|
options={tagFilterOptions}
|
||||||
|
onChange={onTagFilterChange}
|
||||||
|
/>
|
||||||
|
</HorizontalGroup>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const getStyles = stylesFactory((theme: GrafanaTheme) => {
|
||||||
|
return {
|
||||||
|
wrapper: css`
|
||||||
|
height: 35px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
label {
|
||||||
|
height: 20px;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
};
|
||||||
|
});
|
@ -2,4 +2,5 @@ export { SearchResults } from './components/SearchResults';
|
|||||||
export { SearchField } from './components/SearchField';
|
export { SearchField } from './components/SearchField';
|
||||||
export { SearchItem } from './components/SearchItem';
|
export { SearchItem } from './components/SearchItem';
|
||||||
export { SearchCheckbox } from './components/SearchCheckbox';
|
export { SearchCheckbox } from './components/SearchCheckbox';
|
||||||
|
export { SearchResultsFilter } from './components/SearchResultsFilter';
|
||||||
export * from './types';
|
export * from './types';
|
||||||
|
Loading…
Reference in New Issue
Block a user