mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tag filters in search (#10521)
* tag filter: initial react component * dashboard: move tag filter to filterbox * tag filter: customize value rendering * tag filter: get color from name * tag filter: custom option renderer * tag filter: mode with tags in different container * tag filter: refactor * refactoring PR #10519 * tag filter: refactor of PR #10521
This commit is contained in:
@@ -5,6 +5,7 @@ import EmptyListCTA from './components/EmptyListCTA/EmptyListCTA';
|
||||
import LoginBackground from './components/Login/LoginBackground';
|
||||
import { SearchResult } from './components/search/SearchResult';
|
||||
import UserPicker from './components/UserPicker/UserPicker';
|
||||
import { TagFilter } from './components/TagFilter/TagFilter';
|
||||
|
||||
export function registerAngularDirectives() {
|
||||
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
||||
@@ -13,4 +14,9 @@ export function registerAngularDirectives() {
|
||||
react2AngularDirective('loginBackground', LoginBackground, []);
|
||||
react2AngularDirective('searchResult', SearchResult, []);
|
||||
react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'teamId', 'refreshList']);
|
||||
react2AngularDirective('tagFilter', TagFilter, [
|
||||
'tags',
|
||||
['onSelect', { watchDepth: 'reference' }],
|
||||
['tagOptions', { watchDepth: 'reference' }],
|
||||
]);
|
||||
}
|
||||
|
||||
37
public/app/core/components/TagFilter/TagBadge.tsx
Normal file
37
public/app/core/components/TagFilter/TagBadge.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
import tags from 'app/core/utils/tags';
|
||||
|
||||
export interface IProps {
|
||||
label: string;
|
||||
removeIcon: boolean;
|
||||
count: number;
|
||||
onClick: any;
|
||||
}
|
||||
|
||||
export class TagBadge extends React.Component<IProps, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
this.props.onClick(event);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { label, removeIcon, count } = this.props;
|
||||
const { color, borderColor } = tags.getTagColorsFromName(label);
|
||||
const tagStyle = {
|
||||
backgroundColor: color,
|
||||
borderColor: borderColor,
|
||||
};
|
||||
const countLabel = count !== 0 && <span className="tag-count-label">{`(${count})`}</span>;
|
||||
|
||||
return (
|
||||
<span className={`label label-tag`} onClick={this.onClick} style={tagStyle}>
|
||||
{removeIcon && <i className="fa fa-remove" />}
|
||||
{label} {countLabel}
|
||||
</span>
|
||||
);
|
||||
}
|
||||
}
|
||||
69
public/app/core/components/TagFilter/TagFilter.tsx
Normal file
69
public/app/core/components/TagFilter/TagFilter.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
import _ from 'lodash';
|
||||
import React from 'react';
|
||||
import { Async } from 'react-select';
|
||||
import { TagValue } from './TagValue';
|
||||
import { TagOption } from './TagOption';
|
||||
|
||||
export interface IProps {
|
||||
tags: string[];
|
||||
tagOptions: () => any;
|
||||
onSelect: (tag: string) => void;
|
||||
}
|
||||
|
||||
export class TagFilter extends React.Component<IProps, any> {
|
||||
inlineTags: boolean;
|
||||
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.searchTags = this.searchTags.bind(this);
|
||||
this.onChange = this.onChange.bind(this);
|
||||
this.onTagRemove = this.onTagRemove.bind(this);
|
||||
}
|
||||
|
||||
searchTags(query) {
|
||||
return this.props.tagOptions().then(options => {
|
||||
const tags = _.map(options, tagOption => {
|
||||
return { value: tagOption.term, label: tagOption.term, count: tagOption.count };
|
||||
});
|
||||
return { options: tags };
|
||||
});
|
||||
}
|
||||
|
||||
onChange(newTags) {
|
||||
this.props.onSelect(newTags);
|
||||
}
|
||||
|
||||
onTagRemove(tag) {
|
||||
let newTags = _.without(this.props.tags, tag.label);
|
||||
newTags = _.map(newTags, tag => {
|
||||
return { value: tag };
|
||||
});
|
||||
this.props.onSelect(newTags);
|
||||
}
|
||||
|
||||
render() {
|
||||
let selectOptions = {
|
||||
loadOptions: this.searchTags,
|
||||
onChange: this.onChange,
|
||||
value: this.props.tags,
|
||||
multi: true,
|
||||
className: 'gf-form-input gf-form-input--form-dropdown',
|
||||
placeholder: 'Tags',
|
||||
loadingPlaceholder: 'Loading...',
|
||||
noResultsText: 'No tags found',
|
||||
optionComponent: TagOption,
|
||||
};
|
||||
|
||||
selectOptions['valueComponent'] = TagValue;
|
||||
|
||||
return (
|
||||
<div className="gf-form gf-form--has-input-icon gf-form--grow">
|
||||
<div className="tag-filter">
|
||||
<Async {...selectOptions} />
|
||||
</div>
|
||||
<i className="gf-form-input-icon fa fa-tag" />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
52
public/app/core/components/TagFilter/TagOption.tsx
Normal file
52
public/app/core/components/TagFilter/TagOption.tsx
Normal file
@@ -0,0 +1,52 @@
|
||||
import React from 'react';
|
||||
import { TagBadge } from './TagBadge';
|
||||
|
||||
export interface IProps {
|
||||
onSelect: any;
|
||||
onFocus: any;
|
||||
option: any;
|
||||
isFocused: any;
|
||||
className: any;
|
||||
}
|
||||
|
||||
export class TagOption extends React.Component<IProps, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.handleMouseDown = this.handleMouseDown.bind(this);
|
||||
this.handleMouseEnter = this.handleMouseEnter.bind(this);
|
||||
this.handleMouseMove = this.handleMouseMove.bind(this);
|
||||
}
|
||||
|
||||
handleMouseDown(event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
this.props.onSelect(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseEnter(event) {
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
|
||||
handleMouseMove(event) {
|
||||
if (this.props.isFocused) {
|
||||
return;
|
||||
}
|
||||
this.props.onFocus(this.props.option, event);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { option, className } = this.props;
|
||||
|
||||
return (
|
||||
<button
|
||||
onMouseDown={this.handleMouseDown}
|
||||
onMouseEnter={this.handleMouseEnter}
|
||||
onMouseMove={this.handleMouseMove}
|
||||
title={option.title}
|
||||
className={`tag-filter-option btn btn-link ${className || ''}`}
|
||||
>
|
||||
<TagBadge label={option.label} removeIcon={false} count={option.count} onClick={this.handleMouseDown} />
|
||||
</button>
|
||||
);
|
||||
}
|
||||
}
|
||||
26
public/app/core/components/TagFilter/TagValue.tsx
Normal file
26
public/app/core/components/TagFilter/TagValue.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import React from 'react';
|
||||
import { TagBadge } from './TagBadge';
|
||||
|
||||
export interface IProps {
|
||||
value: any;
|
||||
className: any;
|
||||
onClick: any;
|
||||
onRemove: any;
|
||||
}
|
||||
|
||||
export class TagValue extends React.Component<IProps, any> {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.onClick = this.onClick.bind(this);
|
||||
}
|
||||
|
||||
onClick(event) {
|
||||
this.props.onRemove(this.props.value, event);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { value } = this.props;
|
||||
|
||||
return <TagBadge label={value.label} removeIcon={true} count={0} onClick={this.onClick} />;
|
||||
}
|
||||
}
|
||||
@@ -31,28 +31,18 @@
|
||||
</div>
|
||||
|
||||
<div class="search-dropdown__col_2">
|
||||
<!-- <div class="search-filter-box"> -->
|
||||
<!-- <div class="search-filter-box__header"> -->
|
||||
<!-- <i class="fa fa-filter"></i> -->
|
||||
<!-- Filter by: -->
|
||||
<!-- <a class="pointer pull-right small"> -->
|
||||
<!-- <i class="fa fa-remove"></i> Clear -->
|
||||
<!-- </a> -->
|
||||
<!-- </div> -->
|
||||
<!-- -->
|
||||
<!-- <div class="gf-form"> -->
|
||||
<!-- <folder-picker initial-title="ctrl.initialFolderFilterTitle" -->
|
||||
<!-- on-change="ctrl.onFolderChange($folder)" -->
|
||||
<!-- label-class="width-4"> -->
|
||||
<!-- </folder-picker> -->
|
||||
<!-- </div> -->
|
||||
<!-- -->
|
||||
<!-- <div class="gf-form"> -->
|
||||
<!-- <label class="gf-form-label width-4">Tags</label> -->
|
||||
<!-- <bootstrap-tagsinput ng-model="ctrl.dashboard.tags" tagclass="label label-tag" placeholder="add tags"> -->
|
||||
<!-- </bootstrap-tagsinput> -->
|
||||
<!-- </div> -->
|
||||
<!-- </div> -->
|
||||
<div class="search-filter-box" ng-click="ctrl.onFilterboxClick()">
|
||||
<div class="search-filter-box__header">
|
||||
<i class="fa fa-filter"></i>
|
||||
Filter by:
|
||||
<a class="pointer pull-right small" ng-click="ctrl.clearSearchFilter()">
|
||||
<i class="fa fa-remove"></i> Clear
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<tag-filter tags="ctrl.query.tag" tagOptions="ctrl.getTags" onSelect="ctrl.onTagSelect">
|
||||
</tag-filter>
|
||||
</div>
|
||||
|
||||
<div class="search-filter-box">
|
||||
<a href="dashboard/new" class="search-filter-box-link">
|
||||
|
||||
@@ -22,6 +22,8 @@ export class SearchCtrl {
|
||||
appEvents.on('hide-dash-search', this.closeSearch.bind(this), $scope);
|
||||
|
||||
this.initialFolderFilterTitle = 'All';
|
||||
this.getTags = this.getTags.bind(this);
|
||||
this.onTagSelect = this.onTagSelect.bind(this);
|
||||
}
|
||||
|
||||
closeSearch() {
|
||||
@@ -88,6 +90,23 @@ export class SearchCtrl {
|
||||
}
|
||||
}
|
||||
|
||||
searchInputBlur() {
|
||||
this.search();
|
||||
}
|
||||
|
||||
onFilterboxClick() {
|
||||
this.giveSearchFocus = 0;
|
||||
this.preventClose();
|
||||
}
|
||||
|
||||
preventClose() {
|
||||
this.ignoreClose = true;
|
||||
|
||||
this.$timeout(() => {
|
||||
this.ignoreClose = false;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
moveSelection(direction) {
|
||||
if (this.results.length === 0) {
|
||||
return;
|
||||
@@ -160,7 +179,6 @@ export class SearchCtrl {
|
||||
if (_.indexOf(this.query.tag, tag) === -1) {
|
||||
this.query.tag.push(tag);
|
||||
this.search();
|
||||
this.giveSearchFocus = this.giveSearchFocus + 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,10 +191,17 @@ export class SearchCtrl {
|
||||
}
|
||||
|
||||
getTags() {
|
||||
return this.searchSrv.getDashboardTags().then(results => {
|
||||
this.results = results;
|
||||
this.giveSearchFocus = this.giveSearchFocus + 1;
|
||||
});
|
||||
return this.searchSrv.getDashboardTags();
|
||||
}
|
||||
|
||||
onTagSelect(newTags) {
|
||||
this.query.tag = _.map(newTags, tag => tag.value);
|
||||
this.search();
|
||||
}
|
||||
|
||||
clearSearchFilter() {
|
||||
this.query.tag = [];
|
||||
this.search();
|
||||
}
|
||||
|
||||
showStarred() {
|
||||
|
||||
@@ -1,82 +1,11 @@
|
||||
import angular from 'angular';
|
||||
import $ from 'jquery';
|
||||
import coreModule from '../core_module';
|
||||
import tags from 'app/core/utils/tags';
|
||||
import 'vendor/tagsinput/bootstrap-tagsinput.js';
|
||||
|
||||
function djb2(str) {
|
||||
var hash = 5381;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
hash = (hash << 5) + hash + str.charCodeAt(i); /* hash * 33 + c */
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
function setColor(name, element) {
|
||||
var hash = djb2(name.toLowerCase());
|
||||
var colors = [
|
||||
'#E24D42',
|
||||
'#1F78C1',
|
||||
'#BA43A9',
|
||||
'#705DA0',
|
||||
'#466803',
|
||||
'#508642',
|
||||
'#447EBC',
|
||||
'#C15C17',
|
||||
'#890F02',
|
||||
'#757575',
|
||||
'#0A437C',
|
||||
'#6D1F62',
|
||||
'#584477',
|
||||
'#629E51',
|
||||
'#2F4F4F',
|
||||
'#BF1B00',
|
||||
'#806EB7',
|
||||
'#8a2eb8',
|
||||
'#699e00',
|
||||
'#000000',
|
||||
'#3F6833',
|
||||
'#2F575E',
|
||||
'#99440A',
|
||||
'#E0752D',
|
||||
'#0E4AB4',
|
||||
'#58140C',
|
||||
'#052B51',
|
||||
'#511749',
|
||||
'#3F2B5B',
|
||||
];
|
||||
var borderColors = [
|
||||
'#FF7368',
|
||||
'#459EE7',
|
||||
'#E069CF',
|
||||
'#9683C6',
|
||||
'#6C8E29',
|
||||
'#76AC68',
|
||||
'#6AA4E2',
|
||||
'#E7823D',
|
||||
'#AF3528',
|
||||
'#9B9B9B',
|
||||
'#3069A2',
|
||||
'#934588',
|
||||
'#7E6A9D',
|
||||
'#88C477',
|
||||
'#557575',
|
||||
'#E54126',
|
||||
'#A694DD',
|
||||
'#B054DE',
|
||||
'#8FC426',
|
||||
'#262626',
|
||||
'#658E59',
|
||||
'#557D84',
|
||||
'#BF6A30',
|
||||
'#FF9B53',
|
||||
'#3470DA',
|
||||
'#7E3A32',
|
||||
'#2B5177',
|
||||
'#773D6F',
|
||||
'#655181',
|
||||
];
|
||||
var color = colors[Math.abs(hash % colors.length)];
|
||||
var borderColor = borderColors[Math.abs(hash % borderColors.length)];
|
||||
const { color, borderColor } = tags.getTagColorsFromName(name);
|
||||
element.css('background-color', color);
|
||||
element.css('border-color', borderColor);
|
||||
}
|
||||
|
||||
86
public/app/core/utils/tags.ts
Normal file
86
public/app/core/utils/tags.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
const TAG_COLORS = [
|
||||
'#E24D42',
|
||||
'#1F78C1',
|
||||
'#BA43A9',
|
||||
'#705DA0',
|
||||
'#466803',
|
||||
'#508642',
|
||||
'#447EBC',
|
||||
'#C15C17',
|
||||
'#890F02',
|
||||
'#757575',
|
||||
'#0A437C',
|
||||
'#6D1F62',
|
||||
'#584477',
|
||||
'#629E51',
|
||||
'#2F4F4F',
|
||||
'#BF1B00',
|
||||
'#806EB7',
|
||||
'#8a2eb8',
|
||||
'#699e00',
|
||||
'#000000',
|
||||
'#3F6833',
|
||||
'#2F575E',
|
||||
'#99440A',
|
||||
'#E0752D',
|
||||
'#0E4AB4',
|
||||
'#58140C',
|
||||
'#052B51',
|
||||
'#511749',
|
||||
'#3F2B5B',
|
||||
];
|
||||
|
||||
const TAG_BORDER_COLORS = [
|
||||
'#FF7368',
|
||||
'#459EE7',
|
||||
'#E069CF',
|
||||
'#9683C6',
|
||||
'#6C8E29',
|
||||
'#76AC68',
|
||||
'#6AA4E2',
|
||||
'#E7823D',
|
||||
'#AF3528',
|
||||
'#9B9B9B',
|
||||
'#3069A2',
|
||||
'#934588',
|
||||
'#7E6A9D',
|
||||
'#88C477',
|
||||
'#557575',
|
||||
'#E54126',
|
||||
'#A694DD',
|
||||
'#B054DE',
|
||||
'#8FC426',
|
||||
'#262626',
|
||||
'#658E59',
|
||||
'#557D84',
|
||||
'#BF6A30',
|
||||
'#FF9B53',
|
||||
'#3470DA',
|
||||
'#7E3A32',
|
||||
'#2B5177',
|
||||
'#773D6F',
|
||||
'#655181',
|
||||
];
|
||||
|
||||
/**
|
||||
* Returns tag badge background and border colors based on hashed tag name.
|
||||
* @param name tag name
|
||||
*/
|
||||
export function getTagColorsFromName(name: string): { color: string; borderColor: string } {
|
||||
let hash = djb2(name.toLowerCase());
|
||||
let color = TAG_COLORS[Math.abs(hash % TAG_COLORS.length)];
|
||||
let borderColor = TAG_BORDER_COLORS[Math.abs(hash % TAG_BORDER_COLORS.length)];
|
||||
return { color, borderColor };
|
||||
}
|
||||
|
||||
function djb2(str) {
|
||||
let hash = 5381;
|
||||
for (var i = 0; i < str.length; i++) {
|
||||
hash = (hash << 5) + hash + str.charCodeAt(i); /* hash * 33 + c */
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
export default {
|
||||
getTagColorsFromName,
|
||||
};
|
||||
@@ -413,4 +413,5 @@ a.external-link {
|
||||
.highlight-search-match {
|
||||
background: transparent;
|
||||
color: $yellow;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
@@ -26,18 +26,41 @@ $select-menu-box-shadow: $menu-dropdown-shadow;
|
||||
@include box-shadow($shadow);
|
||||
}
|
||||
|
||||
// react-select tweaks
|
||||
.gf-form-input--form-dropdown {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
overflow: visible;
|
||||
|
||||
.Select-placeholder {
|
||||
color: $gray-4;
|
||||
color: $input-color-placeholder;
|
||||
}
|
||||
|
||||
> .Select-control {
|
||||
@include select-control();
|
||||
border-color: $dark-3;
|
||||
|
||||
input {
|
||||
min-width: 1rem;
|
||||
}
|
||||
|
||||
.Select-clear,
|
||||
.Select-arrow {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.Select-value {
|
||||
display: inline-block;
|
||||
padding: 2px 4px;
|
||||
font-size: $font-size-base * 0.846;
|
||||
font-weight: bold;
|
||||
line-height: 14px; // ensure proper line-height if floated
|
||||
color: $white;
|
||||
vertical-align: baseline;
|
||||
white-space: nowrap;
|
||||
text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
|
||||
background-color: $gray-1;
|
||||
}
|
||||
}
|
||||
|
||||
&.is-open > .Select-control {
|
||||
@@ -50,6 +73,11 @@ $select-menu-box-shadow: $menu-dropdown-shadow;
|
||||
@include select-control-focus();
|
||||
}
|
||||
|
||||
&.is-focused:not(.is-open) > .Select-control {
|
||||
background-color: $input-bg;
|
||||
@include select-control-focus();
|
||||
}
|
||||
|
||||
.Select-menu-outer {
|
||||
border: 0;
|
||||
width: auto;
|
||||
|
||||
@@ -51,6 +51,11 @@ $input-border: 1px solid $input-border-color;
|
||||
color: $text-muted;
|
||||
}
|
||||
}
|
||||
|
||||
.Select--multi .Select-multi-value-wrapper,
|
||||
.Select-placeholder {
|
||||
padding-left: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
.gf-form-disabled {
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
box-shadow: $navbarShadow;
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
& > input {
|
||||
max-width: 653px;
|
||||
//padding: 0.5rem 1.5rem 0.5rem 0;
|
||||
padding: 1rem 1rem 0.75rem 1rem;
|
||||
@@ -38,6 +38,13 @@
|
||||
background-color: $navbarButtonBackground;
|
||||
flex-grow: 10;
|
||||
}
|
||||
|
||||
// .tag-filter {
|
||||
// .Select-control {
|
||||
// width: 300px;
|
||||
// background-color: $navbarBackground;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
.search-field-spacer {
|
||||
@@ -67,13 +74,16 @@
|
||||
flex-grow: 1;
|
||||
height: 100%;
|
||||
padding-top: 16px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.search-filter-box {
|
||||
background: $search-filter-box-bg;
|
||||
border-radius: 2px;
|
||||
padding: $spacer*1.5;
|
||||
max-width: 340px;
|
||||
min-width: 340px;
|
||||
margin-bottom: $spacer * 1.5;
|
||||
margin-left: $spacer * 1.5;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
border-radius: 3px;
|
||||
text-shadow: none;
|
||||
font-size: 13px;
|
||||
padding: 2px 6px;
|
||||
padding: 3px 6px 1px 6px;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
box-shadow: 0 0 1px rgba($white, 0.2);
|
||||
|
||||
@@ -21,16 +21,15 @@
|
||||
margin-right: 2px;
|
||||
color: white;
|
||||
|
||||
[data-role="remove"] {
|
||||
[data-role='remove'] {
|
||||
margin-left: 8px;
|
||||
cursor: pointer;
|
||||
&::after {
|
||||
content: "x";
|
||||
content: 'x';
|
||||
padding: 0px 2px;
|
||||
}
|
||||
&:hover {
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
|
||||
0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
&:active {
|
||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
||||
}
|
||||
@@ -38,3 +37,51 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-filter {
|
||||
line-height: 22px;
|
||||
flex-grow: 1;
|
||||
|
||||
.label-tag {
|
||||
margin-left: 6px;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
|
||||
.fa.fa-remove {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.tag-filter-option {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
width: 100%;
|
||||
display: block;
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
.tag-count-label {
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.gf-form-input--form-dropdown {
|
||||
.Select-menu-outer {
|
||||
border: 0;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.tag-filter-values {
|
||||
display: inline;
|
||||
|
||||
.label-tag {
|
||||
margin: 6px 6px 0px 0px;
|
||||
font-size: 11px;
|
||||
cursor: pointer;
|
||||
|
||||
.fa.fa-remove {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user