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 LoginBackground from './components/Login/LoginBackground';
|
||||||
import { SearchResult } from './components/search/SearchResult';
|
import { SearchResult } from './components/search/SearchResult';
|
||||||
import UserPicker from './components/UserPicker/UserPicker';
|
import UserPicker from './components/UserPicker/UserPicker';
|
||||||
|
import { TagFilter } from './components/TagFilter/TagFilter';
|
||||||
|
|
||||||
export function registerAngularDirectives() {
|
export function registerAngularDirectives() {
|
||||||
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
react2AngularDirective('passwordStrength', PasswordStrength, ['password']);
|
||||||
@@ -13,4 +14,9 @@ export function registerAngularDirectives() {
|
|||||||
react2AngularDirective('loginBackground', LoginBackground, []);
|
react2AngularDirective('loginBackground', LoginBackground, []);
|
||||||
react2AngularDirective('searchResult', SearchResult, []);
|
react2AngularDirective('searchResult', SearchResult, []);
|
||||||
react2AngularDirective('selectUserPicker', UserPicker, ['backendSrv', 'teamId', 'refreshList']);
|
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>
|
||||||
|
|
||||||
<div class="search-dropdown__col_2">
|
<div class="search-dropdown__col_2">
|
||||||
<!-- <div class="search-filter-box"> -->
|
<div class="search-filter-box" ng-click="ctrl.onFilterboxClick()">
|
||||||
<!-- <div class="search-filter-box__header"> -->
|
<div class="search-filter-box__header">
|
||||||
<!-- <i class="fa fa-filter"></i> -->
|
<i class="fa fa-filter"></i>
|
||||||
<!-- Filter by: -->
|
Filter by:
|
||||||
<!-- <a class="pointer pull-right small"> -->
|
<a class="pointer pull-right small" ng-click="ctrl.clearSearchFilter()">
|
||||||
<!-- <i class="fa fa-remove"></i> Clear -->
|
<i class="fa fa-remove"></i> Clear
|
||||||
<!-- </a> -->
|
</a>
|
||||||
<!-- </div> -->
|
</div>
|
||||||
<!-- -->
|
|
||||||
<!-- <div class="gf-form"> -->
|
<tag-filter tags="ctrl.query.tag" tagOptions="ctrl.getTags" onSelect="ctrl.onTagSelect">
|
||||||
<!-- <folder-picker initial-title="ctrl.initialFolderFilterTitle" -->
|
</tag-filter>
|
||||||
<!-- on-change="ctrl.onFolderChange($folder)" -->
|
</div>
|
||||||
<!-- 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">
|
<div class="search-filter-box">
|
||||||
<a href="dashboard/new" class="search-filter-box-link">
|
<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);
|
appEvents.on('hide-dash-search', this.closeSearch.bind(this), $scope);
|
||||||
|
|
||||||
this.initialFolderFilterTitle = 'All';
|
this.initialFolderFilterTitle = 'All';
|
||||||
|
this.getTags = this.getTags.bind(this);
|
||||||
|
this.onTagSelect = this.onTagSelect.bind(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
closeSearch() {
|
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) {
|
moveSelection(direction) {
|
||||||
if (this.results.length === 0) {
|
if (this.results.length === 0) {
|
||||||
return;
|
return;
|
||||||
@@ -160,7 +179,6 @@ export class SearchCtrl {
|
|||||||
if (_.indexOf(this.query.tag, tag) === -1) {
|
if (_.indexOf(this.query.tag, tag) === -1) {
|
||||||
this.query.tag.push(tag);
|
this.query.tag.push(tag);
|
||||||
this.search();
|
this.search();
|
||||||
this.giveSearchFocus = this.giveSearchFocus + 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,10 +191,17 @@ export class SearchCtrl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getTags() {
|
getTags() {
|
||||||
return this.searchSrv.getDashboardTags().then(results => {
|
return this.searchSrv.getDashboardTags();
|
||||||
this.results = results;
|
}
|
||||||
this.giveSearchFocus = this.giveSearchFocus + 1;
|
|
||||||
});
|
onTagSelect(newTags) {
|
||||||
|
this.query.tag = _.map(newTags, tag => tag.value);
|
||||||
|
this.search();
|
||||||
|
}
|
||||||
|
|
||||||
|
clearSearchFilter() {
|
||||||
|
this.query.tag = [];
|
||||||
|
this.search();
|
||||||
}
|
}
|
||||||
|
|
||||||
showStarred() {
|
showStarred() {
|
||||||
|
|||||||
@@ -1,82 +1,11 @@
|
|||||||
import angular from 'angular';
|
import angular from 'angular';
|
||||||
import $ from 'jquery';
|
import $ from 'jquery';
|
||||||
import coreModule from '../core_module';
|
import coreModule from '../core_module';
|
||||||
|
import tags from 'app/core/utils/tags';
|
||||||
import 'vendor/tagsinput/bootstrap-tagsinput.js';
|
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) {
|
function setColor(name, element) {
|
||||||
var hash = djb2(name.toLowerCase());
|
const { color, borderColor } = tags.getTagColorsFromName(name);
|
||||||
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)];
|
|
||||||
element.css('background-color', color);
|
element.css('background-color', color);
|
||||||
element.css('border-color', borderColor);
|
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 {
|
.highlight-search-match {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
color: $yellow;
|
color: $yellow;
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,18 +26,41 @@ $select-menu-box-shadow: $menu-dropdown-shadow;
|
|||||||
@include box-shadow($shadow);
|
@include box-shadow($shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// react-select tweaks
|
||||||
.gf-form-input--form-dropdown {
|
.gf-form-input--form-dropdown {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
border: 0;
|
border: 0;
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
|
|
||||||
.Select-placeholder {
|
.Select-placeholder {
|
||||||
color: $gray-4;
|
color: $input-color-placeholder;
|
||||||
}
|
}
|
||||||
|
|
||||||
> .Select-control {
|
> .Select-control {
|
||||||
@include select-control();
|
@include select-control();
|
||||||
border-color: $dark-3;
|
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 {
|
&.is-open > .Select-control {
|
||||||
@@ -50,6 +73,11 @@ $select-menu-box-shadow: $menu-dropdown-shadow;
|
|||||||
@include select-control-focus();
|
@include select-control-focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.is-focused:not(.is-open) > .Select-control {
|
||||||
|
background-color: $input-bg;
|
||||||
|
@include select-control-focus();
|
||||||
|
}
|
||||||
|
|
||||||
.Select-menu-outer {
|
.Select-menu-outer {
|
||||||
border: 0;
|
border: 0;
|
||||||
width: auto;
|
width: auto;
|
||||||
|
|||||||
@@ -51,6 +51,11 @@ $input-border: 1px solid $input-border-color;
|
|||||||
color: $text-muted;
|
color: $text-muted;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Select--multi .Select-multi-value-wrapper,
|
||||||
|
.Select-placeholder {
|
||||||
|
padding-left: 30px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.gf-form-disabled {
|
.gf-form-disabled {
|
||||||
|
|||||||
@@ -26,7 +26,7 @@
|
|||||||
box-shadow: $navbarShadow;
|
box-shadow: $navbarShadow;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
input {
|
& > input {
|
||||||
max-width: 653px;
|
max-width: 653px;
|
||||||
//padding: 0.5rem 1.5rem 0.5rem 0;
|
//padding: 0.5rem 1.5rem 0.5rem 0;
|
||||||
padding: 1rem 1rem 0.75rem 1rem;
|
padding: 1rem 1rem 0.75rem 1rem;
|
||||||
@@ -38,6 +38,13 @@
|
|||||||
background-color: $navbarButtonBackground;
|
background-color: $navbarButtonBackground;
|
||||||
flex-grow: 10;
|
flex-grow: 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// .tag-filter {
|
||||||
|
// .Select-control {
|
||||||
|
// width: 300px;
|
||||||
|
// background-color: $navbarBackground;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-field-spacer {
|
.search-field-spacer {
|
||||||
@@ -67,13 +74,16 @@
|
|||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding-top: 16px;
|
padding-top: 16px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-filter-box {
|
.search-filter-box {
|
||||||
background: $search-filter-box-bg;
|
background: $search-filter-box-bg;
|
||||||
border-radius: 2px;
|
border-radius: 2px;
|
||||||
padding: $spacer*1.5;
|
padding: $spacer*1.5;
|
||||||
max-width: 340px;
|
min-width: 340px;
|
||||||
margin-bottom: $spacer * 1.5;
|
margin-bottom: $spacer * 1.5;
|
||||||
margin-left: $spacer * 1.5;
|
margin-left: $spacer * 1.5;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
padding: 2px 6px;
|
padding: 3px 6px 1px 6px;
|
||||||
border-width: 1px;
|
border-width: 1px;
|
||||||
border-style: solid;
|
border-style: solid;
|
||||||
box-shadow: 0 0 1px rgba($white, 0.2);
|
box-shadow: 0 0 1px rgba($white, 0.2);
|
||||||
|
|||||||
@@ -21,16 +21,15 @@
|
|||||||
margin-right: 2px;
|
margin-right: 2px;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
[data-role="remove"] {
|
[data-role='remove'] {
|
||||||
margin-left: 8px;
|
margin-left: 8px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&::after {
|
&::after {
|
||||||
content: "x";
|
content: 'x';
|
||||||
padding: 0px 2px;
|
padding: 0px 2px;
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2),
|
box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||||
0 1px 2px rgba(0, 0, 0, 0.05);
|
|
||||||
&:active {
|
&:active {
|
||||||
box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
|
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