Enable pagination in tag value lists
Co-authored-by: Andrew Watkins <andrew.watkinz@gmail.com> Co-authored-by: Chris Henn <chris.henn@influxdata.com>pull/10616/head
parent
a86c2817a8
commit
c254a8b5da
|
@ -8,19 +8,19 @@ const LoaderSkeleton: SFC = () => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div className="ifql-schema-tree ifql-tree-node" onClick={handleClick}>
|
<div className="ifql-schema-tree ifql-tree-node" onClick={handleClick}>
|
||||||
<div className="ifql-schema-item skeleton">
|
<div className="ifql-schema-item no-hover">
|
||||||
<div className="ifql-schema-item-toggle" />
|
<div className="ifql-schema-item-toggle" />
|
||||||
<div className="ifql-schema-item-skeleton" style={{width: '160px'}} />
|
<div className="ifql-schema-item-skeleton" style={{width: '160px'}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ifql-schema-tree ifql-tree-node">
|
<div className="ifql-schema-tree ifql-tree-node">
|
||||||
<div className="ifql-schema-item skeleton">
|
<div className="ifql-schema-item no-hover">
|
||||||
<div className="ifql-schema-item-toggle" />
|
<div className="ifql-schema-item-toggle" />
|
||||||
<div className="ifql-schema-item-skeleton" style={{width: '200px'}} />
|
<div className="ifql-schema-item-skeleton" style={{width: '200px'}} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="ifql-schema-tree ifql-tree-node">
|
<div className="ifql-schema-tree ifql-tree-node">
|
||||||
<div className="ifql-schema-item skeleton">
|
<div className="ifql-schema-item no-hover">
|
||||||
<div className="ifql-schema-item-toggle" />
|
<div className="ifql-schema-item-toggle" />
|
||||||
<div className="ifql-schema-item-skeleton" style={{width: '120px'}} />
|
<div className="ifql-schema-item-skeleton" style={{width: '120px'}} />
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
import React, {SFC, CSSProperties} from 'react'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
style?: CSSProperties
|
||||||
|
}
|
||||||
|
|
||||||
|
const LoadingSpinner: SFC<Props> = ({style}) => {
|
||||||
|
return (
|
||||||
|
<div className="loading-spinner" style={style}>
|
||||||
|
<div className="spinner">
|
||||||
|
<div className="bounce1" />
|
||||||
|
<div className="bounce2" />
|
||||||
|
<div className="bounce3" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LoadingSpinner
|
|
@ -1,15 +0,0 @@
|
||||||
import React, {SFC} from 'react'
|
|
||||||
|
|
||||||
const SearchSpinner: SFC = () => {
|
|
||||||
return (
|
|
||||||
<div className="search-spinner">
|
|
||||||
<div className="spinner">
|
|
||||||
<div className="bounce1" />
|
|
||||||
<div className="bounce2" />
|
|
||||||
<div className="bounce3" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default SearchSpinner
|
|
|
@ -30,7 +30,7 @@ export default class TagList extends PureComponent<Props, State> {
|
||||||
<TagListItem
|
<TagListItem
|
||||||
key={t}
|
key={t}
|
||||||
db={db}
|
db={db}
|
||||||
tag={t}
|
tagKey={t}
|
||||||
service={service}
|
service={service}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
/>
|
/>
|
||||||
|
|
|
@ -1,16 +1,22 @@
|
||||||
import React, {PureComponent, ChangeEvent, MouseEvent} from 'react'
|
import React, {
|
||||||
|
PureComponent,
|
||||||
|
CSSProperties,
|
||||||
|
ChangeEvent,
|
||||||
|
MouseEvent,
|
||||||
|
} from 'react'
|
||||||
|
|
||||||
import _ from 'lodash'
|
import _ from 'lodash'
|
||||||
|
|
||||||
import {Service, SchemaFilter, RemoteDataState} from 'src/types'
|
import {Service, SchemaFilter, RemoteDataState} from 'src/types'
|
||||||
import {tagValues as fetchTagValues} from 'src/shared/apis/v2/metaQueries'
|
import {tagValues as fetchTagValues} from 'src/shared/apis/v2/metaQueries'
|
||||||
|
import {explorer} from 'src/ifql/constants'
|
||||||
import parseValuesColumn from 'src/shared/parsing/v2/tags'
|
import parseValuesColumn from 'src/shared/parsing/v2/tags'
|
||||||
import TagValueList from 'src/ifql/components/TagValueList'
|
import TagValueList from 'src/ifql/components/TagValueList'
|
||||||
import LoaderSkeleton from 'src/ifql/components/LoaderSkeleton'
|
import LoaderSkeleton from 'src/ifql/components/LoaderSkeleton'
|
||||||
import SearchSpinner from 'src/ifql/components/SearchSpinner'
|
import LoadingSpinner from 'src/ifql/components/LoadingSpinner'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
tag: string
|
tagKey: string
|
||||||
db: string
|
db: string
|
||||||
service: Service
|
service: Service
|
||||||
filter: SchemaFilter[]
|
filter: SchemaFilter[]
|
||||||
|
@ -20,8 +26,11 @@ interface State {
|
||||||
isOpen: boolean
|
isOpen: boolean
|
||||||
loadingAll: RemoteDataState
|
loadingAll: RemoteDataState
|
||||||
loadingSearch: RemoteDataState
|
loadingSearch: RemoteDataState
|
||||||
|
loadingMore: RemoteDataState
|
||||||
tagValues: string[]
|
tagValues: string[]
|
||||||
searchTerm: string
|
searchTerm: string
|
||||||
|
limit: number
|
||||||
|
count: number | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TagListItem extends PureComponent<Props, State> {
|
export default class TagListItem extends PureComponent<Props, State> {
|
||||||
|
@ -32,30 +41,41 @@ export default class TagListItem extends PureComponent<Props, State> {
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
loadingAll: RemoteDataState.NotStarted,
|
loadingAll: RemoteDataState.NotStarted,
|
||||||
loadingSearch: RemoteDataState.NotStarted,
|
loadingSearch: RemoteDataState.NotStarted,
|
||||||
|
loadingMore: RemoteDataState.NotStarted,
|
||||||
tagValues: [],
|
tagValues: [],
|
||||||
|
count: null,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
|
limit: explorer.TAG_VALUES_LIMIT,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.debouncedSearch = _.debounce(this.searchTagValues, 250)
|
this.debouncedOnSearch = _.debounce(() => {
|
||||||
|
this.searchTagValues()
|
||||||
|
this.getCount()
|
||||||
|
}, 250)
|
||||||
|
}
|
||||||
|
|
||||||
|
public async componentDidMount() {
|
||||||
|
this.getCount()
|
||||||
}
|
}
|
||||||
|
|
||||||
public render() {
|
public render() {
|
||||||
const {tag, db, service, filter} = this.props
|
const {tagKey, db, service, filter} = this.props
|
||||||
const {tagValues, searchTerm} = this.state
|
const {tagValues, searchTerm, loadingMore, count, limit} = this.state
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={this.className}>
|
<div className={this.className}>
|
||||||
<div className="ifql-schema-item" onClick={this.handleClick}>
|
<div className="ifql-schema-item" onClick={this.handleClick}>
|
||||||
<div className="ifql-schema-item-toggle" />
|
<div className="ifql-schema-item-toggle" />
|
||||||
{tag}
|
{tagKey}
|
||||||
<span className="ifql-schema-type">Tag Key</span>
|
<span className="ifql-schema-type">Tag Key</span>
|
||||||
</div>
|
</div>
|
||||||
{this.state.isOpen && (
|
{this.state.isOpen && (
|
||||||
<>
|
<>
|
||||||
|
<div className="tag-value-list--header">
|
||||||
<div className="ifql-schema--filter">
|
<div className="ifql-schema--filter">
|
||||||
<input
|
<input
|
||||||
className="form-control input-sm"
|
className="form-control input-sm"
|
||||||
placeholder={`Filter within ${tag}`}
|
placeholder={`Filter within ${tagKey}`}
|
||||||
type="text"
|
type="text"
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
|
@ -63,17 +83,26 @@ export default class TagListItem extends PureComponent<Props, State> {
|
||||||
onClick={this.handleInputClick}
|
onClick={this.handleInputClick}
|
||||||
onChange={this.onSearch}
|
onChange={this.onSearch}
|
||||||
/>
|
/>
|
||||||
{this.isSearching && <SearchSpinner />}
|
{this.isSearching && (
|
||||||
|
<LoadingSpinner style={this.spinnerStyle} />
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{!!count && `${count} total`}
|
||||||
</div>
|
</div>
|
||||||
{this.isLoading && <LoaderSkeleton />}
|
{this.isLoading && <LoaderSkeleton />}
|
||||||
{!this.isLoading && (
|
{!this.isLoading && (
|
||||||
|
<>
|
||||||
<TagValueList
|
<TagValueList
|
||||||
db={db}
|
db={db}
|
||||||
service={service}
|
service={service}
|
||||||
values={tagValues}
|
values={tagValues}
|
||||||
tag={tag}
|
tagKey={tagKey}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
|
onLoadMoreValues={this.handleLoadMoreValues}
|
||||||
|
isLoadingMoreValues={loadingMore === RemoteDataState.Loading}
|
||||||
|
shouldShowMoreValues={limit < count}
|
||||||
/>
|
/>
|
||||||
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -81,6 +110,14 @@ export default class TagListItem extends PureComponent<Props, State> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private get spinnerStyle(): CSSProperties {
|
||||||
|
return {
|
||||||
|
position: 'absolute',
|
||||||
|
right: '15px',
|
||||||
|
top: '6px',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private get isSearching(): boolean {
|
private get isSearching(): boolean {
|
||||||
return this.state.loadingSearch === RemoteDataState.Loading
|
return this.state.loadingSearch === RemoteDataState.Loading
|
||||||
}
|
}
|
||||||
|
@ -93,11 +130,11 @@ export default class TagListItem extends PureComponent<Props, State> {
|
||||||
const searchTerm = e.target.value
|
const searchTerm = e.target.value
|
||||||
|
|
||||||
this.setState({searchTerm, loadingSearch: RemoteDataState.Loading}, () =>
|
this.setState({searchTerm, loadingSearch: RemoteDataState.Loading}, () =>
|
||||||
this.debouncedSearch()
|
this.debouncedOnSearch()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private debouncedSearch() {} // See constructor
|
private debouncedOnSearch() {} // See constructor
|
||||||
|
|
||||||
private handleInputClick = (e: MouseEvent<HTMLInputElement>): void => {
|
private handleInputClick = (e: MouseEvent<HTMLInputElement>): void => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
|
@ -133,10 +170,33 @@ export default class TagListItem extends PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getMoreTagValues = async () => {
|
||||||
|
this.setState({loadingMore: RemoteDataState.Loading})
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tagValues = await this.getTagValues()
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
tagValues,
|
||||||
|
loadingMore: RemoteDataState.Done,
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
this.setState({loadingMore: RemoteDataState.Error})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private getTagValues = async () => {
|
private getTagValues = async () => {
|
||||||
const {db, service, tag, filter} = this.props
|
const {db, service, tagKey, filter} = this.props
|
||||||
const {searchTerm} = this.state
|
const {searchTerm, limit} = this.state
|
||||||
const response = await fetchTagValues(service, db, filter, tag, searchTerm)
|
const response = await fetchTagValues({
|
||||||
|
service,
|
||||||
|
db,
|
||||||
|
filter,
|
||||||
|
tagKey,
|
||||||
|
limit,
|
||||||
|
searchTerm,
|
||||||
|
})
|
||||||
|
|
||||||
return parseValuesColumn(response)
|
return parseValuesColumn(response)
|
||||||
}
|
}
|
||||||
|
@ -151,6 +211,43 @@ export default class TagListItem extends PureComponent<Props, State> {
|
||||||
this.setState({isOpen: !this.state.isOpen})
|
this.setState({isOpen: !this.state.isOpen})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private handleLoadMoreValues = (): void => {
|
||||||
|
const {limit} = this.state
|
||||||
|
|
||||||
|
this.setState(
|
||||||
|
{limit: limit + explorer.TAG_VALUES_LIMIT},
|
||||||
|
this.getMoreTagValues
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getCount() {
|
||||||
|
const {service, db, filter, tagKey} = this.props
|
||||||
|
const {limit, searchTerm} = this.state
|
||||||
|
try {
|
||||||
|
const response = await fetchTagValues({
|
||||||
|
service,
|
||||||
|
db,
|
||||||
|
filter,
|
||||||
|
tagKey,
|
||||||
|
limit,
|
||||||
|
searchTerm,
|
||||||
|
count: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const parsed = parseValuesColumn(response)
|
||||||
|
|
||||||
|
if (parsed.length !== 1) {
|
||||||
|
throw new Error('Unexpected count response')
|
||||||
|
}
|
||||||
|
|
||||||
|
const count = Number(parsed[0])
|
||||||
|
|
||||||
|
this.setState({count})
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private get isFetchable(): boolean {
|
private get isFetchable(): boolean {
|
||||||
const {isOpen, loadingAll} = this.state
|
const {isOpen, loadingAll} = this.state
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,72 @@
|
||||||
import React, {PureComponent} from 'react'
|
import React, {PureComponent, MouseEvent} from 'react'
|
||||||
|
|
||||||
import TagValueListItem from 'src/ifql/components/TagValueListItem'
|
import TagValueListItem from 'src/ifql/components/TagValueListItem'
|
||||||
|
import LoadingSpinner from 'src/ifql/components/LoadingSpinner'
|
||||||
import {Service, SchemaFilter} from 'src/types'
|
import {Service, SchemaFilter} from 'src/types'
|
||||||
|
import {explorer} from 'src/ifql/constants'
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
service: Service
|
service: Service
|
||||||
db: string
|
db: string
|
||||||
tag: string
|
tagKey: string
|
||||||
values: string[]
|
values: string[]
|
||||||
filter: SchemaFilter[]
|
filter: SchemaFilter[]
|
||||||
|
isLoadingMoreValues: boolean
|
||||||
|
onLoadMoreValues: () => void
|
||||||
|
shouldShowMoreValues: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class TagValueList extends PureComponent<Props> {
|
export default class TagValueList extends PureComponent<Props> {
|
||||||
public render() {
|
public render() {
|
||||||
const {db, service, values, tag, filter} = this.props
|
const {
|
||||||
|
db,
|
||||||
|
service,
|
||||||
|
values,
|
||||||
|
tagKey,
|
||||||
|
filter,
|
||||||
|
shouldShowMoreValues,
|
||||||
|
} = this.props
|
||||||
|
|
||||||
return values.map((v, i) => (
|
return (
|
||||||
|
<>
|
||||||
|
{values.map((v, i) => (
|
||||||
<TagValueListItem
|
<TagValueListItem
|
||||||
key={i}
|
key={i}
|
||||||
db={db}
|
db={db}
|
||||||
tag={tag}
|
|
||||||
value={v}
|
value={v}
|
||||||
|
tagKey={tagKey}
|
||||||
service={service}
|
service={service}
|
||||||
filter={filter}
|
filter={filter}
|
||||||
/>
|
/>
|
||||||
))
|
))}
|
||||||
|
{shouldShowMoreValues && (
|
||||||
|
<div className="ifql-schema-tree ifql-tree-node">
|
||||||
|
<div className="ifql-schema-item no-hover">
|
||||||
|
<button
|
||||||
|
className="btn btn-xs btn-default increase-values-limit"
|
||||||
|
onClick={this.handleClick}
|
||||||
|
>
|
||||||
|
{this.buttonValue}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private handleClick = (e: MouseEvent<HTMLButtonElement>) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
this.props.onLoadMoreValues()
|
||||||
|
}
|
||||||
|
|
||||||
|
private get buttonValue(): string | JSX.Element {
|
||||||
|
const {isLoadingMoreValues} = this.props
|
||||||
|
|
||||||
|
if (isLoadingMoreValues) {
|
||||||
|
return <LoadingSpinner />
|
||||||
|
}
|
||||||
|
|
||||||
|
return `Load next ${explorer.TAG_VALUES_LIMIT} values`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import {Service, SchemaFilter, RemoteDataState} from 'src/types'
|
||||||
interface Props {
|
interface Props {
|
||||||
db: string
|
db: string
|
||||||
service: Service
|
service: Service
|
||||||
tag: string
|
tagKey: string
|
||||||
value: string
|
value: string
|
||||||
filter: SchemaFilter[]
|
filter: SchemaFilter[]
|
||||||
}
|
}
|
||||||
|
@ -79,9 +79,9 @@ class TagValueListItem extends PureComponent<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private get filter(): SchemaFilter[] {
|
private get filter(): SchemaFilter[] {
|
||||||
const {filter, tag, value} = this.props
|
const {filter, tagKey, value} = this.props
|
||||||
|
|
||||||
return [...filter, {key: tag, value}]
|
return [...filter, {key: tagKey, value}]
|
||||||
}
|
}
|
||||||
|
|
||||||
private get tags(): string[] {
|
private get tags(): string[] {
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
export const TAG_VALUES_LIMIT = 2
|
|
@ -4,5 +4,6 @@ import * as argTypes from 'src/ifql/constants/argumentTypes'
|
||||||
import * as funcNames from 'src/ifql/constants/funcNames'
|
import * as funcNames from 'src/ifql/constants/funcNames'
|
||||||
import * as builder from 'src/ifql/constants/builder'
|
import * as builder from 'src/ifql/constants/builder'
|
||||||
import * as vis from 'src/ifql/constants/vis'
|
import * as vis from 'src/ifql/constants/vis'
|
||||||
|
import * as explorer from 'src/ifql/constants/explorer'
|
||||||
|
|
||||||
export {ast, funcNames, argTypes, editor, builder, vis}
|
export {ast, funcNames, argTypes, editor, builder, vis, explorer}
|
||||||
|
|
|
@ -44,19 +44,34 @@ export const tagKeys = async (
|
||||||
return proxy(service, script)
|
return proxy(service, script)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const tagValues = async (
|
interface TagValuesParams {
|
||||||
service: Service,
|
service: Service
|
||||||
db: string,
|
db: string
|
||||||
filter: SchemaFilter[],
|
tagKey: string
|
||||||
tagKey: string,
|
limit: number
|
||||||
searchTerm: string = ''
|
filter?: SchemaFilter[]
|
||||||
): Promise<any> => {
|
searchTerm?: string
|
||||||
|
count?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
export const tagValues = async ({
|
||||||
|
db,
|
||||||
|
service,
|
||||||
|
tagKey,
|
||||||
|
limit,
|
||||||
|
filter = [],
|
||||||
|
searchTerm = '',
|
||||||
|
count = false,
|
||||||
|
}: TagValuesParams): Promise<any> => {
|
||||||
let regexFilter = ''
|
let regexFilter = ''
|
||||||
|
|
||||||
if (searchTerm) {
|
if (searchTerm) {
|
||||||
regexFilter = `|> filter(fn: (r) => r.${tagKey} =~ /${searchTerm}/)`
|
regexFilter = `|> filter(fn: (r) => r.${tagKey} =~ /${searchTerm}/)`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const limitFunc = count ? '' : `|> limit(n:${limit})`
|
||||||
|
const countFunc = count ? '|> count()' : ''
|
||||||
|
|
||||||
const script = `
|
const script = `
|
||||||
from(db:"${db}")
|
from(db:"${db}")
|
||||||
|> range(start:-1h)
|
|> range(start:-1h)
|
||||||
|
@ -64,8 +79,9 @@ export const tagValues = async (
|
||||||
${tagsetFilter(filter)}
|
${tagsetFilter(filter)}
|
||||||
|> group(by:["${tagKey}"])
|
|> group(by:["${tagKey}"])
|
||||||
|> distinct(column:"${tagKey}")
|
|> distinct(column:"${tagKey}")
|
||||||
|> group(none: true)
|
|> group(by:["_stop","_start"])
|
||||||
|> limit(n:100)
|
${limitFunc}
|
||||||
|
${countFunc}
|
||||||
`
|
`
|
||||||
|
|
||||||
return proxy(service, script)
|
return proxy(service, script)
|
||||||
|
|
|
@ -74,7 +74,7 @@ $ifql-tree-line: 2px;
|
||||||
left: $ifql-tree-indent / 2;
|
left: $ifql-tree-indent / 2;
|
||||||
transform: translate(-50%, -50%);
|
transform: translate(-50%, -50%);
|
||||||
}
|
}
|
||||||
&:not(.skeleton):hover {
|
&:not(.no-hover):hover {
|
||||||
color: $g17-whisper;
|
color: $g17-whisper;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
background-color: $g4-onyx;
|
background-color: $g4-onyx;
|
||||||
|
@ -111,6 +111,10 @@ $ifql-tree-line: 2px;
|
||||||
color: $g11-sidewalk;
|
color: $g11-sidewalk;
|
||||||
cursor: default;
|
cursor: default;
|
||||||
}
|
}
|
||||||
|
.increase-values-limit {
|
||||||
|
margin-left: 8px;
|
||||||
|
width: 160px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes skeleton-animation {
|
@keyframes skeleton-animation {
|
||||||
|
@ -194,10 +198,22 @@ $ifql-tree-line: 2px;
|
||||||
margin-right: $ifql-tree-indent / 2;
|
margin-right: $ifql-tree-indent / 2;
|
||||||
margin-top: 1px;
|
margin-top: 1px;
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
input {
|
max-width: 220px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ifql-schema--filter>input.input-sm {
|
||||||
height: 25px;
|
height: 25px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.tag-value-list--header>.ifql-schema--filter {
|
||||||
|
display: inline-block;
|
||||||
|
margin-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-value-list--header {
|
||||||
|
font-size: 12px;
|
||||||
|
color: $g11-sidewalk;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -207,18 +223,13 @@ $ifql-tree-line: 2px;
|
||||||
From http: //tobiasahlin.com/spinkit/.
|
From http: //tobiasahlin.com/spinkit/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
.search-spinner {
|
.loading-spinner .spinner {
|
||||||
position: absolute;
|
|
||||||
right: 15px;
|
|
||||||
top: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-spinner .spinner {
|
|
||||||
width: 25px;
|
width: 25px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-spinner .spinner>div {
|
.loading-spinner .spinner>div {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
background-color: $g8-storm;
|
background-color: $g8-storm;
|
||||||
|
@ -227,11 +238,11 @@ $ifql-tree-line: 2px;
|
||||||
animation: sk-bouncedelay 1s infinite ease-in-out both;
|
animation: sk-bouncedelay 1s infinite ease-in-out both;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-spinner .spinner .bounce1 {
|
.loading-spinner .spinner .bounce1 {
|
||||||
animation-delay: -0.32s;
|
animation-delay: -0.32s;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-spinner .spinner .bounce2 {
|
.loading-spinner .spinner .bounce2 {
|
||||||
animation-delay: -0.16s;
|
animation-delay: -0.16s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue