Merge pull request #1309 from influxdata/query-builder-style-refactor

Query Maker Style Refactor
pull/1265/head^2
Andrew Watkins 2017-04-20 10:14:44 -07:00 committed by GitHub
commit 4a784c9718
48 changed files with 1497 additions and 2076 deletions

View File

@ -4,7 +4,7 @@ import _ from 'lodash'
import uuid from 'node-uuid'
import ResizeContainer, {ResizeBottom} from 'src/shared/components/ResizeContainer'
import QueryBuilder from 'src/data_explorer/components/QueryBuilder'
import QueryMaker from 'src/data_explorer/components/QueryMaker'
import Visualization from 'src/data_explorer/components/Visualization'
import OverlayControls from 'src/dashboards/components/OverlayControls'
import * as queryModifiers from 'src/utils/queryTransitions'
@ -159,7 +159,7 @@ class CellEditorOverlay extends Component {
onCancel={onCancel}
onSave={this.handleSaveCell}
/>
<QueryBuilder
<QueryMaker
source={source}
queries={queriesWorkingDraft}
actions={queryActions}

View File

@ -9,7 +9,7 @@ const OverlayControls = (props) => {
const {onCancel, onSave, selectedGraphType, onSelectGraphType} = props
return (
<div className="overlay-controls">
<h3 className="overlay--graph-name">Graph Editor</h3>
<h3 className="overlay--graph-name">Cell Editor</h3>
<div className="overlay-controls--right">
<p>Visualization Type:</p>
<ul className="toggle toggle-sm">

View File

@ -61,19 +61,19 @@ const DatabaseList = React.createClass({
return (
<div className="query-builder--column">
<div className="query-builder--column-heading">Databases</div>
<ul className="qeditor--list">
<div className="query-builder--heading">Databases</div>
<div className="query-builder--list">
{this.state.namespaces.map((namespace) => {
const {database, retentionPolicy} = namespace
const isActive = database === query.database && retentionPolicy === query.retentionPolicy
return (
<li className={classNames('qeditor--list-item qeditor--list-radio', {active: isActive})} key={`${database}..${retentionPolicy}`} onClick={_.wrap(namespace, onChooseNamespace)}>
<div className={classNames('query-builder--list-item', {active: isActive})} key={`${database}..${retentionPolicy}`} onClick={_.wrap(namespace, onChooseNamespace)}>
{database}.{retentionPolicy}
</li>
</div>
)
})}
</ul>
</div>
</div>
)
},

View File

@ -74,17 +74,12 @@ const FieldList = React.createClass({
return (
<div className="query-builder--column">
<div className="query-builder--column-heading">Fields</div>
{
hasAggregates ?
<div className="qeditor--list-header">
<div className="group-by-time">
<p>Group by Time</p>
<GroupByTimeDropdown isOpen={!hasGroupByTime} selected={query.groupBy.time} onChooseGroupByTime={this.handleGroupByTime} />
</div>
</div>
: null
}
<div className="query-builder--heading">
<span>Fields</span>
{hasAggregates ?
<GroupByTimeDropdown isOpen={!hasGroupByTime} selected={query.groupBy.time} onChooseGroupByTime={this.handleGroupByTime} />
: null}
</div>
{this.renderList()}
</div>
)
@ -93,11 +88,15 @@ const FieldList = React.createClass({
renderList() {
const {database, measurement} = this.props.query
if (!database || !measurement) {
return <div className="qeditor--empty">No <strong>Measurement</strong> selected</div>
return (
<div className="query-builder--list-empty">
<span>No <strong>Measurement</strong> selected</span>
</div>
)
}
return (
<ul className="qeditor--list">
<div className="query-builder--list">
{this.state.fields.map((fieldFunc) => {
const selectedField = this.props.query.fields.find((f) => f.field === fieldFunc.field)
return (
@ -111,7 +110,7 @@ const FieldList = React.createClass({
/>
)
})}
</ul>
</div>
)
},

View File

@ -39,16 +39,17 @@ const FieldListItem = React.createClass({
})
return (
<li className={classNames("qeditor--list-item qeditor--list-checkbox", {checked: isSelected})} key={fieldFunc} onClick={_.wrap(fieldFunc, this.handleToggleField)}>
<span className="qeditor--list-checkbox__checkbox">{fieldText}</span>
<div className="qeditor--hidden-dropdown">
{
isKapacitorRule ?
<Dropdown items={items} onChoose={this.handleApplyFunctions} selected={fieldFunc.funcs.length ? fieldFunc.funcs[0] : 'Select a function'} /> :
<MultiSelectDropdown items={INFLUXQL_FUNCTIONS} onApply={this.handleApplyFunctions} selectedItems={fieldFunc.funcs || []} />
}
</div>
</li>
<div className={classNames("query-builder--list-item", {active: isSelected})} key={fieldFunc} onClick={_.wrap(fieldFunc, this.handleToggleField)}>
<span>
<div className="query-builder--checkbox"></div>
{fieldText}
</span>
{
isKapacitorRule ?
<Dropdown items={items} onChoose={this.handleApplyFunctions} selected={fieldFunc.funcs.length ? fieldFunc.funcs[0] : 'Function'} /> :
<MultiSelectDropdown items={INFLUXQL_FUNCTIONS} onApply={this.handleApplyFunctions} selectedItems={fieldFunc.funcs || []} />
}
</div>
)
},
})

View File

@ -16,16 +16,16 @@ const GroupByTimeDropdown = React.createClass({
const {isOpen, selected, onChooseGroupByTime} = this.props
return (
<div className="dropdown group-by-time-dropdown">
<div className={classNames("dropdown group-by-time-dropdown", {open: isOpen})}>
<div className="btn btn-sm btn-info dropdown-toggle" data-toggle="dropdown">
<span className="selected-group-by">{selected || '...'}</span>
<span className="caret" />
<span>Group by {selected || 'time'}</span>
<span className="caret"></span>
</div>
<ul className={classNames("dropdown-menu", {show: isOpen})} aria-labelledby="group-by-dropdown">
<ul className="dropdown-menu">
{groupByTimeOptions.map((groupBy) => {
return (
<li key={groupBy.menuOption}>
<a href="#" onClick={() => onChooseGroupByTime(groupBy)}>
<li className="dropdown-item" key={groupBy.menuOption}onClick={() => onChooseGroupByTime(groupBy)}>
<a href="#">
{groupBy.menuOption}
</a>
</li>

View File

@ -72,11 +72,15 @@ const MeasurementList = React.createClass({
render() {
return (
<div className="query-builder--column">
<div className="query-builder--column-heading">Measurements</div>
{this.props.query.database ? <div className="qeditor--list-header">
<input className="qeditor--filter" ref="filterText" placeholder="Filter" type="text" value={this.state.filterText} onChange={this.handleFilterText} onKeyUp={this.handleEscape} />
<span className="icon search"></span>
</div> : null }
<div className="query-builder--heading">
<span>Measurements</span>
{this.props.query.database ?
<div className="query-builder--filter">
<input className="form-control input-sm" ref="filterText" placeholder="Filter" type="text" value={this.state.filterText} onChange={this.handleFilterText} onKeyUp={this.handleEscape} />
<span className="icon search"></span>
</div>
: null }
</div>
{this.renderList()}
</div>
)
@ -84,20 +88,24 @@ const MeasurementList = React.createClass({
renderList() {
if (!this.props.query.database) {
return <div className="qeditor--empty">No <strong>Database</strong> selected</div>
return (
<div className="query-builder--list-empty">
<span>No <strong>Database</strong> selected</span>
</div>
)
}
const measurements = this.state.measurements.filter((m) => m.match(this.state.filterText))
return (
<ul className="qeditor--list">
<div className="query-builder--list">
{measurements.map((measurement) => {
const isActive = measurement === this.props.query.measurement
return (
<li className={classNames('qeditor--list-item qeditor--list-radio', {active: isActive})} key={measurement} onClick={_.wrap(measurement, this.props.onChooseMeasurement)}>{measurement}</li>
<div className={classNames('query-builder--list-item', {active: isActive})} key={measurement} onClick={_.wrap(measurement, this.props.onChooseMeasurement)}>{measurement}</div>
)
})}
</ul>
</div>
)
},

View File

@ -1,16 +1,16 @@
import React, {PropTypes} from 'react'
import DatabaseList from './DatabaseList'
import MeasurementList from './MeasurementList'
import FieldList from './FieldList'
import TagList from './TagList'
import QueryEditor from './QueryEditor'
import QueryTabItem from './QueryTabItem'
import buildInfluxQLQuery from 'utils/influxql'
const {
arrayOf,
func,
node,
number,
shape,
string,
shape,
func,
} = PropTypes
const QueryBuilder = React.createClass({
@ -20,7 +20,9 @@ const QueryBuilder = React.createClass({
queries: string.isRequired,
}).isRequired,
}).isRequired,
queries: arrayOf(shape({})).isRequired,
query: shape({
id: string,
}).isRequired,
timeRange: shape({
upper: string,
lower: string,
@ -28,103 +30,91 @@ const QueryBuilder = React.createClass({
actions: shape({
chooseNamespace: func.isRequired,
chooseMeasurement: func.isRequired,
applyFuncsToField: func.isRequired,
chooseTag: func.isRequired,
groupByTag: func.isRequired,
addQuery: func.isRequired,
toggleField: func.isRequired,
groupByTime: func.isRequired,
toggleTagAcceptance: func.isRequired,
applyFuncsToField: func.isRequired,
editRawTextAsync: func.isRequired,
}).isRequired,
height: string,
top: string,
setActiveQueryIndex: func.isRequired,
onDeleteQuery: func.isRequired,
activeQueryIndex: number,
children: node,
},
handleAddQuery() {
const newIndex = this.props.queries.length
this.props.actions.addQuery()
this.props.setActiveQueryIndex(newIndex)
handleChooseNamespace(namespace) {
this.props.actions.chooseNamespace(this.props.query.id, namespace)
},
handleAddRawQuery() {
const newIndex = this.props.queries.length
this.props.actions.addQuery({rawText: ''})
this.props.setActiveQueryIndex(newIndex)
handleChooseMeasurement(measurement) {
this.props.actions.chooseMeasurement(this.props.query.id, measurement)
},
getActiveQuery() {
const {queries, activeQueryIndex} = this.props
const activeQuery = queries[activeQueryIndex]
const defaultQuery = queries[0]
handleToggleField(field) {
this.props.actions.toggleField(this.props.query.id, field)
},
return activeQuery || defaultQuery
handleGroupByTime(time) {
this.props.actions.groupByTime(this.props.query.id, time)
},
handleApplyFuncsToField(fieldFunc) {
this.props.actions.applyFuncsToField(this.props.query.id, fieldFunc)
},
handleChooseTag(tag) {
this.props.actions.chooseTag(this.props.query.id, tag)
},
handleToggleTagAcceptance() {
this.props.actions.toggleTagAcceptance(this.props.query.id)
},
handleGroupByTag(tagKey) {
this.props.actions.groupByTag(this.props.query.id, tagKey)
},
handleEditRawText(text) {
const {source: {links}, query} = this.props
this.props.actions.editRawTextAsync(links.queries, query.id, text)
},
render() {
const {height, top} = this.props
const {query, timeRange} = this.props
const q = query.rawText || buildInfluxQLQuery(timeRange, query) || ''
return (
<div className="query-builder" style={{height, top}}>
{this.renderQueryTabList()}
{this.renderQueryEditor()}
<div className="query-maker--tab-contents">
<QueryEditor query={q} config={query} onUpdate={this.handleEditRawText} />
{this.renderLists()}
</div>
)
},
renderQueryEditor() {
const {timeRange, actions, source} = this.props
const query = this.getActiveQuery()
if (!query) {
return (
<div className="qeditor--empty">
<h5 className="no-user-select">This Graph has no Queries</h5>
<br/>
<div className="btn btn-primary" role="button" onClick={this.handleAddQuery}>Add a Query</div>
</div>
)
}
renderLists() {
const {query} = this.props
return (
<QueryEditor
source={source}
timeRange={timeRange}
query={query}
actions={actions}
onAddQuery={this.handleAddQuery}
/>
)
},
renderQueryTabList() {
const {queries, activeQueryIndex, onDeleteQuery, timeRange, setActiveQueryIndex} = this.props
return (
<div className="query-builder--tabs">
<div className="query-builder--tabs-heading">
<h1>Queries</h1>
<div className="panel--tab-new btn btn-sm btn-primary dropdown-toggle" onClick={this.handleAddQuery}>
<span className="icon plus"></span>
</div>
</div>
{queries.map((q, i) => {
return (
<QueryTabItem
isActive={i === activeQueryIndex}
key={i}
queryIndex={i}
query={q}
onSelect={setActiveQueryIndex}
onDelete={onDeleteQuery}
queryTabText={q.rawText || buildInfluxQLQuery(timeRange, q) || `Query ${i + 1}`}
/>
)
})}
{this.props.children}
<div className="query-builder">
<DatabaseList
query={query}
onChooseNamespace={this.handleChooseNamespace}
/>
<MeasurementList
query={query}
onChooseMeasurement={this.handleChooseMeasurement}
/>
<FieldList
query={query}
onToggleField={this.handleToggleField}
onGroupByTime={this.handleGroupByTime}
applyFuncsToField={this.handleApplyFuncsToField}
/>
<TagList
query={query}
onChooseTag={this.handleChooseTag}
onGroupByTag={this.handleGroupByTag}
onToggleTagAcceptance={this.handleToggleTagAcceptance}
/>
</div>
)
},

View File

@ -1,122 +1,102 @@
import React, {PropTypes} from 'react'
import classNames from 'classnames'
import Dropdown from 'src/shared/components/Dropdown'
import LoadingDots from 'src/shared/components/LoadingDots'
import {QUERY_TEMPLATES} from 'src/data_explorer/constants'
import DatabaseList from './DatabaseList'
import MeasurementList from './MeasurementList'
import FieldList from './FieldList'
import TagList from './TagList'
import RawQueryEditor from './RawQueryEditor'
import buildInfluxQLQuery from 'utils/influxql'
const ENTER = 13
const ESCAPE = 27
const {
string,
shape,
func,
shape,
string,
} = PropTypes
const QueryEditor = React.createClass({
propTypes: {
source: shape({
links: shape({
queries: string.isRequired,
}).isRequired,
}).isRequired,
query: shape({
id: string,
}).isRequired,
timeRange: shape({
upper: string,
lower: string,
}).isRequired,
actions: shape({
chooseNamespace: func.isRequired,
chooseMeasurement: func.isRequired,
applyFuncsToField: func.isRequired,
chooseTag: func.isRequired,
groupByTag: func.isRequired,
toggleField: func.isRequired,
groupByTime: func.isRequired,
toggleTagAcceptance: func.isRequired,
editRawTextAsync: func.isRequired,
}).isRequired,
query: string.isRequired,
onUpdate: func.isRequired,
config: shape().isRequired,
},
handleChooseNamespace(namespace) {
this.props.actions.chooseNamespace(this.props.query.id, namespace)
getInitialState() {
return {
value: this.props.query,
}
},
handleChooseMeasurement(measurement) {
this.props.actions.chooseMeasurement(this.props.query.id, measurement)
componentWillReceiveProps(nextProps) {
if (this.props.query !== nextProps.query) {
this.setState({value: nextProps.query})
}
},
handleToggleField(field) {
this.props.actions.toggleField(this.props.query.id, field)
handleKeyDown(e) {
if (e.keyCode === ENTER) {
e.preventDefault()
this.handleUpdate()
} else if (e.keyCode === ESCAPE) {
this.setState({value: this.state.value}, () => {
this.editor.blur()
})
}
},
handleGroupByTime(time) {
this.props.actions.groupByTime(this.props.query.id, time)
handleChange() {
this.setState({
value: this.editor.value,
})
},
handleApplyFuncsToField(fieldFunc) {
this.props.actions.applyFuncsToField(this.props.query.id, fieldFunc)
handleUpdate() {
this.props.onUpdate(this.state.value)
},
handleChooseTag(tag) {
this.props.actions.chooseTag(this.props.query.id, tag)
},
handleToggleTagAcceptance() {
this.props.actions.toggleTagAcceptance(this.props.query.id)
},
handleGroupByTag(tagKey) {
this.props.actions.groupByTag(this.props.query.id, tagKey)
},
handleEditRawText(text) {
const {source: {links}, query} = this.props
this.props.actions.editRawTextAsync(links.queries, query.id, text)
handleChooseTemplate(template) {
this.setState({value: template.query})
},
render() {
const {query, timeRange} = this.props
const q = query.rawText || buildInfluxQLQuery(timeRange, query) || ''
const {config: {status}} = this.props
const {value} = this.state
return (
<div className="query-builder--tab-contents">
<div>
<RawQueryEditor query={q} config={query} onUpdate={this.handleEditRawText} />
{this.renderLists()}
</div>
<div className="query-editor">
<textarea
className="query-editor--field"
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onBlur={this.handleUpdate}
ref={(editor) => this.editor = editor}
value={value}
placeholder="Enter a query or select database, measurement, and field below and have us build one for you..."
autoComplete="off"
spellCheck="false"
/>
{this.renderStatus(status)}
<Dropdown items={QUERY_TEMPLATES} selected={'Query Templates'} onChoose={this.handleChooseTemplate} className="query-editor--templates"/>
</div>
)
},
renderStatus(status) {
if (!status) {
return (
<div className="query-editor--status"></div>
)
}
renderLists() {
const {query} = this.props
if (status.loading) {
return (
<div className="query-editor--status">
<LoadingDots />
</div>
)
}
return (
<div className="query-builder--columns">
<DatabaseList
query={query}
onChooseNamespace={this.handleChooseNamespace}
/>
<MeasurementList
query={query}
onChooseMeasurement={this.handleChooseMeasurement}
/>
<FieldList
query={query}
onToggleField={this.handleToggleField}
onGroupByTime={this.handleGroupByTime}
applyFuncsToField={this.handleApplyFuncsToField}
/>
<TagList
query={query}
onChooseTag={this.handleChooseTag}
onGroupByTag={this.handleGroupByTag}
onToggleTagAcceptance={this.handleToggleTagAcceptance}
/>
<div className={classNames("query-editor--status", {"query-editor--error": status.error, "query-editor--success": status.success, "query-editor--warning": status.warn})}>
<span className={classNames("icon", {stop: status.error, checkmark: status.success, "alert-triangle": status.warn})}></span>
{status.error || status.warn || status.success}
</div>
)
},

View File

@ -0,0 +1,130 @@
import React, {PropTypes} from 'react'
import QueryBuilder from './QueryBuilder'
import QueryMakerTab from './QueryMakerTab'
import buildInfluxQLQuery from 'utils/influxql'
const {
arrayOf,
func,
node,
number,
shape,
string,
} = PropTypes
const QueryMaker = React.createClass({
propTypes: {
source: shape({
links: shape({
queries: string.isRequired,
}).isRequired,
}).isRequired,
queries: arrayOf(shape({})).isRequired,
timeRange: shape({
upper: string,
lower: string,
}).isRequired,
actions: shape({
chooseNamespace: func.isRequired,
chooseMeasurement: func.isRequired,
chooseTag: func.isRequired,
groupByTag: func.isRequired,
addQuery: func.isRequired,
toggleField: func.isRequired,
groupByTime: func.isRequired,
toggleTagAcceptance: func.isRequired,
applyFuncsToField: func.isRequired,
editRawTextAsync: func.isRequired,
}).isRequired,
height: string,
top: string,
setActiveQueryIndex: func.isRequired,
onDeleteQuery: func.isRequired,
activeQueryIndex: number,
children: node,
},
handleAddQuery() {
const newIndex = this.props.queries.length
this.props.actions.addQuery()
this.props.setActiveQueryIndex(newIndex)
},
handleAddRawQuery() {
const newIndex = this.props.queries.length
this.props.actions.addQuery({rawText: ''})
this.props.setActiveQueryIndex(newIndex)
},
getActiveQuery() {
const {queries, activeQueryIndex} = this.props
const activeQuery = queries[activeQueryIndex]
const defaultQuery = queries[0]
return activeQuery || defaultQuery
},
render() {
const {height, top} = this.props
return (
<div className="query-maker" style={{height, top}}>
{this.renderQueryTabList()}
{this.renderQueryBuilder()}
</div>
)
},
renderQueryBuilder() {
const {timeRange, actions, source} = this.props
const query = this.getActiveQuery()
if (!query) {
return (
<div className="query-maker--empty">
<h5>This Graph has no Queries</h5>
<br/>
<div className="btn btn-primary" role="button" onClick={this.handleAddQuery}>Add a Query</div>
</div>
)
}
return (
<QueryBuilder
source={source}
timeRange={timeRange}
query={query}
actions={actions}
onAddQuery={this.handleAddQuery}
/>
)
},
renderQueryTabList() {
const {queries, activeQueryIndex, onDeleteQuery, timeRange, setActiveQueryIndex} = this.props
return (
<div className="query-maker--tabs">
{queries.map((q, i) => {
return (
<QueryMakerTab
isActive={i === activeQueryIndex}
key={i}
queryIndex={i}
query={q}
onSelect={setActiveQueryIndex}
onDelete={onDeleteQuery}
queryTabText={q.rawText || buildInfluxQLQuery(timeRange, q) || `Query ${i + 1}`}
/>
)
})}
{this.props.children}
<div className="query-maker--new btn btn-sm btn-primary" onClick={this.handleAddQuery}>
<span className="icon plus"></span>
</div>
</div>
)
},
})
export default QueryMaker

View File

@ -1,7 +1,7 @@
import React, {PropTypes} from 'react'
import classNames from 'classnames'
const QueryTabItem = React.createClass({
const QueryMakerTab = React.createClass({
propTypes: {
isActive: PropTypes.bool,
query: PropTypes.shape({
@ -24,12 +24,12 @@ const QueryTabItem = React.createClass({
render() {
return (
<div className={classNames('query-builder--tab', {active: this.props.isActive})} onClick={this.handleSelect}>
<span className="query-builder--tab-label">{this.props.queryTabText}</span>
<span className="query-builder--tab-delete" onClick={this.handleDelete}></span>
<div className={classNames('query-maker--tab', {active: this.props.isActive})} onClick={this.handleSelect}>
<label>{this.props.queryTabText}</label>
<span className="query-maker--delete" onClick={this.handleDelete}></span>
</div>
)
},
})
export default QueryTabItem
export default QueryMakerTab

View File

@ -1,105 +0,0 @@
import React, {PropTypes} from 'react'
import classNames from 'classnames'
import Dropdown from 'src/shared/components/Dropdown'
import LoadingDots from 'src/shared/components/LoadingDots'
import {QUERY_TEMPLATES} from 'src/data_explorer/constants'
const ENTER = 13
const ESCAPE = 27
const {
func,
shape,
string,
} = PropTypes
const RawQueryEditor = React.createClass({
propTypes: {
query: string.isRequired,
onUpdate: func.isRequired,
config: shape().isRequired,
},
getInitialState() {
return {
value: this.props.query,
}
},
componentWillReceiveProps(nextProps) {
if (this.props.query !== nextProps.query) {
this.setState({value: nextProps.query})
}
},
handleKeyDown(e) {
if (e.keyCode === ENTER) {
e.preventDefault()
this.handleUpdate()
} else if (e.keyCode === ESCAPE) {
this.setState({value: this.state.value}, () => {
this.editor.blur()
})
}
},
handleChange() {
this.setState({
value: this.editor.value,
})
},
handleUpdate() {
this.props.onUpdate(this.state.value)
},
handleChooseTemplate(template) {
this.setState({value: template.query})
},
render() {
const {config: {status}} = this.props
const {value} = this.state
return (
<div className="raw-text">
<textarea
className="raw-text--field"
onChange={this.handleChange}
onKeyDown={this.handleKeyDown}
onBlur={this.handleUpdate}
ref={(editor) => this.editor = editor}
value={value}
placeholder="Enter a query or select database, measurement, and field below and have us build one for you..."
autoComplete="off"
spellCheck="false"
/>
{this.renderStatus(status)}
<Dropdown items={QUERY_TEMPLATES} selected={'Query Templates'} onChoose={this.handleChooseTemplate} className="query-template"/>
</div>
)
},
renderStatus(status) {
if (!status) {
return (
<div className="raw-text--status"></div>
)
}
if (status.loading) {
return (
<div className="raw-text--status">
<LoadingDots />
</div>
)
}
return (
<div className={classNames("raw-text--status", {"raw-text--error": status.error, "raw-text--success": status.success, "raw-text--warning": status.warn})}>
<span className={classNames("icon", {stop: status.error, checkmark: status.success, "alert-triangle": status.warn})}></span>
{status.error || status.warn || status.success}
</div>
)
},
})
export default RawQueryEditor

View File

@ -91,13 +91,16 @@ const TagList = React.createClass({
return (
<div className="query-builder--column">
<div className="query-builder--column-heading">Tags</div>
{(!query.database || !query.measurement || !query.retentionPolicy) ? null : <div className="qeditor--list-header">
<div className="toggle toggle-sm">
<div onClick={this.handleAcceptReject} className={cx("toggle-btn", {active: query.areTagsAccepted})}>=</div>
<div onClick={this.handleAcceptReject} className={cx("toggle-btn", {active: !query.areTagsAccepted})}>!=</div>
</div>
</div>}
<div className="query-builder--heading">
<span>Tags</span>
{(!query.database || !query.measurement || !query.retentionPolicy) ? null :
<div className={cx("flip-toggle", {flipped: query.areTagsAccepted})} onClick={this.handleAcceptReject}>
<div className="flip-toggle--container">
<div className="flip-toggle--front">!=</div>
<div className="flip-toggle--back">=</div>
</div>
</div>}
</div>
{this.renderList()}
</div>
)
@ -106,11 +109,15 @@ const TagList = React.createClass({
renderList() {
const {database, measurement, retentionPolicy} = this.props.query
if (!database || !measurement || !retentionPolicy) {
return <div className="qeditor--empty">No <strong>Measurement</strong> selected</div>
return (
<div className="query-builder--list-empty">
<span>No <strong>Measurement</strong> selected</span>
</div>
)
}
return (
<ul className="qeditor--list">
<div className="query-builder--list">
{_.map(this.state.tags, (tagValues, tagKey) => {
return (
<TagListItem
@ -124,7 +131,7 @@ const TagList = React.createClass({
/>
)
})}
</ul>
</div>
)
},
})

View File

@ -55,23 +55,23 @@ const TagListItem = React.createClass({
const filtered = tagValues.filter((v) => v.match(this.state.filterText))
return (
<li>
<div className="tag-value-list__filter-container">
<input className="tag-value-list__filter" ref="filterText" placeholder={`Filter within ${this.props.tagKey}`} type="text" value={this.state.filterText} onChange={this.handleFilterText} onKeyUp={this.handleEscape} />
<div className="query-builder--sub-list">
<div className="query-builder--filter">
<input className="form-control input-sm" ref="filterText" placeholder={`Filter within ${this.props.tagKey}`} type="text" value={this.state.filterText} onChange={this.handleFilterText} onKeyUp={this.handleEscape} />
<span className="icon search"></span>
</div>
<ul className="tag-value-list">
{filtered.map((v) => {
const cx = classNames('tag-value-list__item qeditor--list-item', {active: selectedTagValues.indexOf(v) > -1})
return (
<li className={cx} onClick={_.wrap(v, this.handleChoose)} key={v}>
<div className="tag-value-list__checkbox"></div>
<div className="tag-value-list__item-label">{v}</div>
</li>
)
})}
</ul>
</li>
{filtered.map((v) => {
const cx = classNames('query-builder--list-item', {active: selectedTagValues.indexOf(v) > -1})
return (
<div className={cx} onClick={_.wrap(v, this.handleChoose)} key={v}>
<span>
<div className="query-builder--checkbox"></div>
{v}
</span>
</div>
)
})}
</div>
)
},
@ -83,23 +83,20 @@ const TagListItem = React.createClass({
render() {
const {tagKey, tagValues} = this.props
const {isOpen} = this.state
const itemClasses = classNames("qeditor--list-item tag-list__item", {open: isOpen})
const tagItemLabel = `${tagKey}${tagValues.length}`
return (
<div>
<li className={itemClasses} onClick={this.handleClickKey}>
<div className="tag-list__title">
<div className="tag-list__caret">
<div className="icon caret-right"></div>
</div>
{tagKey}
<span className="badge">{tagValues.length}</span>
</div>
<div className={classNames("query-builder--list-item", {active: isOpen})} onClick={this.handleClickKey}>
<span>
<div className="query-builder--caret icon caret-right"></div>
{tagItemLabel}
</span>
<div
className={classNames('btn btn-info btn-xs tag-list__group-by', {active: this.props.isUsingGroupBy})}
className={classNames('btn btn-info btn-xs group-by-tag', {active: this.props.isUsingGroupBy})}
onClick={this.handleGroupBy}>Group By {tagKey}
</div>
</li>
</div>
{isOpen ? this.renderTagValues() : null}
</div>
)

View File

@ -4,7 +4,7 @@ import {bindActionCreators} from 'redux'
import _ from 'lodash'
import QueryBuilder from '../components/QueryBuilder'
import QueryMaker from '../components/QueryMaker'
import Visualization from '../components/Visualization'
import Header from '../containers/Header'
import ResizeContainer, {ResizeBottom} from 'src/shared/components/ResizeContainer'
@ -94,7 +94,7 @@ const DataExplorer = React.createClass({
timeRange={timeRange}
/>
<ResizeContainer>
<QueryBuilder
<QueryMaker
source={source}
queries={queryConfigs}
actions={queryConfigActions}

View File

@ -40,7 +40,7 @@ const Header = React.createClass({
const {autoRefresh, actions: {handleChooseAutoRefresh}, timeRange} = this.props
return (
<div className="page-header">
<div className="page-header full-width-no-scrollbar">
<div className="page-header__container">
<div className="page-header__left">
<h1>Data Explorer</h1>

View File

@ -1,6 +1,4 @@
import React, {PropTypes} from 'react'
import classNames from 'classnames'
import _ from 'lodash'
import buildInfluxQLQuery from 'utils/influxql'
import DatabaseList from '../../data_explorer/components/DatabaseList'
@ -8,11 +6,6 @@ import MeasurementList from '../../data_explorer/components/MeasurementList'
import FieldList from '../../data_explorer/components/FieldList'
import TagList from '../../data_explorer/components/TagList'
const DB_TAB = 'databases'
const MEASUREMENTS_TAB = 'measurments'
const FIELDS_TAB = 'fields'
const TAGS_TAB = 'tags'
export const DataSection = React.createClass({
propTypes: {
source: PropTypes.shape({
@ -50,22 +43,12 @@ export const DataSection = React.createClass({
return {source: this.props.source}
},
getInitialState() {
return {
activeTab: DB_TAB,
}
},
handleChooseNamespace(namespace) {
this.props.actions.chooseNamespace(this.props.query.id, namespace)
this.setState({activeTab: MEASUREMENTS_TAB})
},
handleChooseMeasurement(measurement) {
this.props.actions.chooseMeasurement(this.props.query.id, measurement)
this.setState({activeTab: FIELDS_TAB})
},
handleToggleField(field) {
@ -92,97 +75,50 @@ export const DataSection = React.createClass({
this.props.actions.groupByTag(this.props.query.id, tagKey)
},
handleClickTab(tab) {
this.setState({activeTab: tab})
},
render() {
const {query, timeRange: {lower}} = this.props
const statement = query.rawText || buildInfluxQLQuery({lower}, query) || `SELECT "fields" FROM "db"."rp"."measurement"`
const statement = query.rawText || buildInfluxQLQuery({lower}, query) || `Build a query below`
return (
<div className="kapacitor-rule-section">
<div className="kapacitor-rule-section kapacitor-metric-selector">
<h3 className="rule-section-heading">Select a Time Series</h3>
<div className="rule-section-body">
<div className="qeditor kapacitor-metric-selector">
<div className="qeditor--query-preview">
<pre className={classNames("", {"rq-mode": query.rawText})}><code>{statement}</code></pre>
</div>
{this.renderEditor()}
</div>
<pre><code>{statement}</code></pre>
{this.renderQueryBuilder()}
</div>
</div>
)
},
renderEditor() {
const {activeTab} = this.state
renderQueryBuilder() {
const {query} = this.props
if (query.rawText) {
return (
<div className="generic-empty-state query-editor-empty-state">
<p className="margin-bottom-zero">
<span className="icon alert-triangle"></span>
&nbsp;Only editable in the <strong>Raw Query</strong> tab.
</p>
</div>
)
}
return (
<div className="kapacitor-tab-list">
<div className="qeditor--tabs">
<div onClick={_.wrap(DB_TAB, this.handleClickTab)} className={classNames("qeditor--tab", {active: activeTab === DB_TAB})}>Databases</div>
<div onClick={_.wrap(MEASUREMENTS_TAB, this.handleClickTab)} className={classNames("qeditor--tab", {active: activeTab === MEASUREMENTS_TAB})}>Measurements</div>
<div onClick={_.wrap(FIELDS_TAB, this.handleClickTab)} className={classNames("qeditor--tab", {active: activeTab === FIELDS_TAB})}>Fields</div>
<div onClick={_.wrap(TAGS_TAB, this.handleClickTab)} className={classNames("qeditor--tab", {active: activeTab === TAGS_TAB})}>Tags</div>
</div>
{this.renderList()}
<div className="query-builder">
<DatabaseList
query={query}
onChooseNamespace={this.handleChooseNamespace}
/>
<MeasurementList
query={query}
onChooseMeasurement={this.handleChooseMeasurement}
/>
<FieldList
query={query}
onToggleField={this.handleToggleField}
onGroupByTime={this.handleGroupByTime}
applyFuncsToField={this.handleApplyFuncsToField}
isKapacitorRule={true}
/>
<TagList
query={query}
onChooseTag={this.handleChooseTag}
onGroupByTag={this.handleGroupByTag}
onToggleTagAcceptance={this.handleToggleTagAcceptance}
/>
</div>
)
},
renderList() {
const {query} = this.props
switch (this.state.activeTab) {
case DB_TAB:
return (
<DatabaseList
query={query}
onChooseNamespace={this.handleChooseNamespace}
/>
)
case MEASUREMENTS_TAB:
return (
<MeasurementList
query={query}
onChooseMeasurement={this.handleChooseMeasurement}
/>
)
case FIELDS_TAB:
return (
<FieldList
query={query}
onToggleField={this.handleToggleField}
onGroupByTime={this.handleGroupByTime}
applyFuncsToField={this.handleApplyFuncsToField}
isKapacitorRule={true}
/>
)
case TAGS_TAB:
return (
<TagList
query={query}
onChooseTag={this.handleChooseTag}
onGroupByTag={this.handleGroupByTag}
onToggleTagAcceptance={this.handleToggleTagAcceptance}
/>
)
default:
return <ul className="qeditor--list"></ul>
}
},
})
export default DataSection

View File

@ -22,11 +22,13 @@ const RuleMessageAlertConfig = ({
<p>{DEFAULT_ALERT_LABELS[alert]}</p>
<input
id="alert-input"
className="form-control size-486"
className="form-control size-486 form-control--green input-sm"
type="text"
placeholder={DEFAULT_ALERT_PLACEHOLDERS[alert]}
onChange={(e) => updateAlertNodes(rule.id, alert, e.target.value)}
value={ALERT_NODES_ACCESSORS[alert](rule)}
autoComplete="off"
spellCheck="false"
/>
</div>
)

View File

@ -101,9 +101,9 @@ const Threshold = React.createClass({
<span>{query.fields.length ? query.fields[0].field : 'Select a Time-Series'}</span>
<p>is</p>
<Dropdown className="size-176 dropdown-kapacitor" items={operators} selected={operator} onChoose={this.handleDropdownChange} />
<input className="form-control input-sm size-166 form-control--green" type="text" ref={(r) => this.valueInput = r} defaultValue={value} onKeyUp={this.handleInputChange} />
<input className="form-control input-sm size-166 form-control--green" type="text" spellCheck="false" ref={(r) => this.valueInput = r} defaultValue={value} onKeyUp={this.handleInputChange} />
{ (operator === 'inside range' || operator === 'outside range') &&
<input className="form-control input-sm size-166 form-control--green" type="text" ref={(r) => this.valueRangeInput = r} defaultValue={rangeValue} onKeyUp={this.handleInputChange} />
<input className="form-control input-sm size-166 form-control--green" type="text" spellCheck="false" ref={(r) => this.valueRangeInput = r} defaultValue={rangeValue} onKeyUp={this.handleInputChange} />
}
</div>
)
@ -153,6 +153,7 @@ const Relative = React.createClass({
onKeyUp={this.handleInputChange}
required={true}
type="text"
spellCheck="false"
/>
<p>{ change === CHANGES[1] ? '%' : '' }</p>
</div>

View File

@ -51,8 +51,8 @@ export const DEFAULT_ALERT_LABELS = {
alerta: 'Paste Alerta TICKscript:',
}
export const DEFAULT_ALERT_PLACEHOLDERS = {
http: 'http://',
tcp: 'Address:',
http: 'Ex: http://example.com/api/alert',
tcp: 'Ex: exampleendpoint.com:5678',
exec: 'Ex: woogie boogie',
smtp: 'Ex: benedict@domain.com delaney@domain.com susan@domain.com',
slack: '#alerts',

View File

@ -47,7 +47,7 @@ const AutoRefreshDropdown = React.createClass({
const {milliseconds, inputValue} = this.findAutoRefreshItem(selected)
return (
<div className="dropdown time-range-dropdown">
<div className="dropdown dropdown-160">
<div className="btn btn-sm btn-info dropdown-toggle" onClick={() => self.toggleMenu()}>
<span className={classnames("icon", +milliseconds > 0 ? "refresh" : "pause")}></span>
<span className="selected-time-range">{inputValue}</span>

View File

@ -54,7 +54,7 @@ const TimeRangeDropdown = React.createClass({
const {isOpen} = self.state
return (
<div className="dropdown time-range-dropdown">
<div className="dropdown dropdown-160">
<div className="btn btn-sm btn-info dropdown-toggle" onClick={() => self.toggleMenu()}>
<span className="icon clock"></span>
<span className="selected-time-range">{self.findTimeRangeInputValue(selected)}</span>

View File

@ -1,9 +1,7 @@
// Modules
@import 'modules/influx-colors';
@import 'modules/variables';
// Mixins
@import 'mixins/mixins';
@import 'modules/mixins';
// Fonts
@import 'fonts/fonts';
@ -23,16 +21,17 @@
// Layout
@import 'layout/page';
@import 'layout/page-header';
@import 'layout/sidebar.scss';
@import 'layout/sidebar';
// Components
@import 'components/dropdown';
@import 'components/input-tag-list';
@import 'components/group-by-time-dropdown';
@import 'components/page-header-dropdown';
@import 'components/page-header-editable';
@import 'components/multi-select-dropdown';
@import 'components/page-spinner';
@import 'components/flash-messages';
@import 'components/flip-toggle';
@import 'components/dygraphs';
@import 'components/react-tooltips';
@import 'components/search-widget';
@ -42,14 +41,13 @@
@import 'components/graph-tips';
@import 'components/confirm-buttons';
@import 'components/custom-time-range';
@import 'components/graph';
@import 'components/query-maker';
// Pages
@import 'pages/alerts';
@import 'pages/signup';
@import 'pages/auth-page';
@import 'pages/hosts';
@import 'pages/kapacitor';
@import 'pages/data-explorer';
@import 'pages/dashboards';
@import 'pages/admin';

View File

@ -0,0 +1,262 @@
/*
Dropdowns
----------------------------------------------
Note: Some of these styles are intended to
override styles from bootstrap-theme
*/
$dropdown-menu-default-width: 100%;
$dropdown-menu-max-height: 290px;
/*
Generic width modifiers
Use instead of creating new classes if possible
*/
.dropdown .dropdown-toggle {
width: 120px; /* Default width */
}
.dropdown {
&-80 .dropdown-toggle {width: 80px;}
&-90 .dropdown-toggle {width: 90px;}
&-100 .dropdown-toggle {width: 100px;}
&-110 .dropdown-toggle {width: 110px;}
&-120 .dropdown-toggle {width: 120px;}
&-130 .dropdown-toggle {width: 130px;}
&-140 .dropdown-toggle {width: 140px;}
&-150 .dropdown-toggle {width: 150px;}
&-160 .dropdown-toggle {width: 160px;}
&-170 .dropdown-toggle {width: 170px;}
&-180 .dropdown-toggle {width: 180px;}
&-190 .dropdown-toggle {width: 190px;}
&-200 .dropdown-toggle {width: 200px;}
&-210 .dropdown-toggle {width: 210px;}
&-220 .dropdown-toggle {width: 220px;}
&-230 .dropdown-toggle {width: 230px;}
&-240 .dropdown-toggle {width: 240px;}
&-250 .dropdown-toggle {width: 250px;}
}
.dropdown-toggle {
position: relative;
text-align: left;
.caret {
position: absolute;
top: calc(50% + 1px);
right: 8px;
transform: translateY(-50%);
}
> .icon {
font-size: 16px;
display: inline-block;
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
}
/*
Dropdown Menu
----------------------------------------------
*/
.dropdown-menu {
float: none !important;
width: $dropdown-menu-default-width;
min-width: $dropdown-menu-default-width;
max-width: $dropdown-menu-default-width;
margin: 0 !important;
padding: 0 !important;
max-height: $dropdown-menu-max-height;
overflow: auto;
@include custom-scrollbar-round($c-pool, $c-laser);
@include gradient-h($c-ocean, $c-pool);
box-shadow: 0 2px 5px 0.6px fade-out($g0-obsidian, 0.8);
> li {
width: 100%;
font-size: 0px;
&:hover {
@include gradient-h($c-laser, $c-pool);
}
}
> li > a {
width: 100%;
border-radius: 0 !important;
display: inline-block;
padding: 7px 9px;
font-size: 13px;
line-height: 15px;
font-weight: 500;
color: $c-yeti !important;
background-color: transparent;
transition:
color 0.25s ease;
&:hover {
cursor: pointer;
background-color: transparent;
color: $g20-white !important;
}
&:active,
&:active:focus {
@include gradient-h($c-sapphire, $c-pool);
}
&:focus {
@include gradient-h($c-ocean, $c-pool);
}
}
> li:last-child a {
border-radius: 0 0 3px 3px;
}
> li:first-child a {
border-radius: 3px 3px 0 0;
}
}
.dropdown.dropdown-kapacitor .dropdown-toggle {
color: $c-rainforest !important;
&:hover {color: $c-honeydew !important;}
}
.dropdown.dropdown-kapacitor .dropdown-menu,
.rule-builder .dropdown .dropdown-menu {
@include custom-scrollbar($c-rainforest, $c-honeydew);
@include gradient-h($c-pool, $c-rainforest);
> li:hover {
@include gradient-h($c-laser, $c-rainforest);
}
> li > a {
color: $c-mint !important;
&:hover {
color: $g20-white !important;
}
}
}
.dropdown.dropdown-chronograf .dropdown-menu {
@include custom-scrollbar($c-comet, $c-potassium);
@include gradient-h($c-ocean, $c-comet);
> li:hover {
@include gradient-h($c-laser, $c-comet);
}
> li > a {
color: $c-cremedeviolette !important;
&:hover {
color: $g20-white !important;
}
}
}
/*
Dropdown Header
----------------------------------------------
*/
.dropdown-header {
height: 32px;
line-height: 30px;
padding: 0 9px;
white-space: nowrap;
font-size: 14px !important;
font-weight: 900;
color: $c-neutrino !important;
text-transform: none !important;
border-bottom: 2px solid $c-pool;
background-color: $c-ocean;
&:hover {
background-image: none !important;
background-color: $c-ocean !important;
cursor: default;
}
}
/*
Dropdown Actions
----------------------------------------------
*/
.dropdown-item {
position: relative;
> a {
position: relative;
z-index: 1;
}
}
.dropdown-item__actions {
z-index: 2;
position: absolute;
top: 0;
right: 3px;
height: 100%;
width: auto;
display: flex;
align-items: center;
justify-content: flex-end;
}
.dropdown-item__action {
padding: 0;
margin: 0;
width: 24px;
height: 24px;
border-radius: 2px;
background-color: transparent;
border: none !important;
font-size: 13px;
transition:
text-shadow 0.25s ease,
color 0.25s ease;
color: $c-sapphire;
&[data-target="#deleteExplorerModal"] .icon {
position: relative;
right: -1px;
}
&:hover {
color: $g20-white;
text-shadow:
0 0 2px $c-hydrogen,
0 0 3px $c-laser,
0 0 6px $c-ocean;
background-color: transparent;
}
}
/*
Group By Time Dropdown
----------------------------------------------
*/
.group-by-time-dropdown {
.dropdown-toggle {
width: 120px;
height: 28px !important;
line-height: 28px !important;
font-size: 12px;
text-transform: none;
border-radius: $radius;
display: block;
}
.dropdown-menu > li.dropdown-item > a {display: block;}
}
.data-explorer .group-by-time-dropdown .dropdown-toggle {
font-weight: 600;
background-color: $g2-kevlar;
line-height: 24px !important;
border: 2px solid $g6-smoke;
transition:
border-color 0.25s ease,
color 0.25s ease,
box-shadow 0.25s ease;
color: $g10-wolf;
&:hover {
border-color: $g7-graphite;
color: $g18-cloud;
}
}
.data-explorer .group-by-time-dropdown.open .dropdown-toggle {
background-color: $g2-kevlar !important;
border-color: $c-pool !important;
box-shadow: 0 0 6px 0px $c-pool !important
}

View File

@ -0,0 +1,65 @@
/*
Flip Toggle
-------------------------------------------------------------
Toggles between 2 options using a 3D transition
Aesthetic and space conservative
*/
$flip-toggle-text: $g11-sidewalk;
$flip-toggle-text-hover: $g18-cloud;
$flip-toggle-bg: $g2-kevlar;
$flip-toggle-border: $g6-smoke;
$flip-toggle-border-hover: $g7-graphite;
$flip-toggle-size: 28px;
.flip-toggle {
width: $flip-toggle-size;
height: $flip-toggle-size;
perspective: 1000px;
&:hover {
cursor: pointer;
.flip-toggle--front,
.flip-toggle--back {
border-color: $flip-toggle-border-hover;
color: $flip-toggle-text-hover;
}
}
}
.flip-toggle--container {
transition: transform 0.6s ease;
transform-style: preserve-3d;
position: relative;
}
.flip-toggle--front,
.flip-toggle--back {
border: 2px solid $flip-toggle-border;
background-color: $flip-toggle-bg;
transition:
color 0.25s ease,
border-color 0.25s ease;
border-radius: $radius-small;
width: $flip-toggle-size;
height: $flip-toggle-size;
text-align: center;
line-height: ($flip-toggle-size - 4px); /* Subtract for border width */
color: $flip-toggle-text;
position: absolute;
top: 0;
left: 0;
backface-visibility: hidden;
}
.flip-toggle--front {
z-index: 2;
transform: rotateY(0deg);
}
.flip-toggle--back {
z-index: 1;
transform: rotateY(180deg);
}
/* Flip Animation happens on class toggle */
.flip-toggle.flipped .flip-toggle--container {
transform: rotateY(180deg);
}

View File

@ -1,22 +1,29 @@
/*
Variables
---------------------------------------------
*/
$graph-heading-height: 44px;
/*
Graph Styles
---------------------------------------------
*/
.graph {
position: absolute;
top: 0;
width: calc(100% - #{($explorer-page-padding * 2)});
left: $explorer-page-padding;
}
/* Special rule for when the graph is in the bottom of resizer */
.resize-bottom .graph {
height: 100%;
width: calc(100% - #{($page-wrapper-padding * 2)});
left: $page-wrapper-padding;
}
.graph-heading {
position: relative;
top: $de-vertical-margin;
background-color: $graph-bg-color;
border-radius: $graph-radius $graph-radius 0 0;
top: 16px;
background-color: $g3-castle;
border-radius: $radius $radius 0 0;
display: flex;
align-items: center;
justify-content: space-between;
height: $de-graph-heading-height;
height: $graph-heading-height;
padding: 0 16px;
transition:
background-color 0.25s ease;
@ -40,12 +47,12 @@
align-items: center;
}
.graph .table-container {
background-color: $graph-bg-color;
border-radius: 0 0 $graph-radius $graph-radius;
background-color: $g3-castle;
border-radius: 0 0 $radius $radius;
padding: 8px 16px;
position: relative;
top: $de-vertical-margin;
height: calc(100% - #{$de-graph-heading-height} - #{($de-vertical-margin * 2)});
top: 16px;
height: calc(100% - #{($graph-heading-height + 32px)});
& > div > div:last-child {
position: absolute;
@ -66,19 +73,16 @@
}
.graph-container {
@include no-user-select();
background-color: $graph-bg-color;
border-radius: 0 0 $graph-radius $graph-radius;
padding: 8px 16px;
background-color: $g3-castle;
border-radius: 0 0 $radius $radius;
position: relative;
height: 316px;
transition:
background-color 0.25s ease;
top: 16px;
height: calc(100% - #{$graph-heading-height + 32px});
}
.data-explorer .graph-container {
top: $de-vertical-margin;
height: calc(100% - #{$de-graph-heading-height} - #{($de-vertical-margin * 2)});
padding: 0;
& > div:not(.graph-panel__refreshing) {
position: absolute;
width: 100%;
@ -127,21 +131,6 @@
background-repeat: no-repeat;
animation: graph-panel-spinner 1s infinite linear;
}
.graph-spinner--small {
width: 58px;
height: 58px;
background-image: url(assets/images/laser-spinner.png);
background-size: 100% 100%;
background-position: center center;
background-repeat: no-repeat;
animation: graph-panel-spinner 1s infinite linear;
position: absolute;
left: 0;
bottom: 0;
right: 0;
top: 0;
margin: auto;
}
@keyframes graph-panel-spinner {
0% {
@ -150,32 +139,4 @@
100% {
transform: rotate(360deg);
}
}
.multi-table__tabs {
display: flex;
}
.multi-table__tab {
white-space: nowrap;
color: $g10-wolf;
background: $g5-pepper;
height: 30px;
line-height: 30px;
margin-right: 2px;
border-radius: 4px 4px 0 0;
cursor: pointer;
padding: 0 10px;
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
color: $g20-white;
background-color: $g6-smoke;
}
&.active {
font-weight: 700;
background-color: $g6-smoke;
color: $g14-chromium;
}
}
}

View File

@ -1,26 +0,0 @@
.group-by-time-dropdown .dropdown-toggle {
width: 70px;
}
.group-by-time {
display: flex;
align-items: center;
p {
padding: 0 6px;
margin: 0;
height: 30px;
line-height: 26px;
font-size: 13px;
color: $g11-sidewalk;
font-weight: 500;
border-radius: 3px 0 0 3px;
border-style: solid;
border-color: $g5-pepper;
border-width: 2px;
background-color: $g3-castle;
white-space: nowrap;
}
.dropdown-toggle {
border-radius: 0px 3px 3px 0;
}
}

View File

@ -0,0 +1,203 @@
/*
Query Builder
-------------------------------------------------------------
NOTE: Variables are located in query-maker.scss
*/
.query-builder {
width: 100%;
flex: 1 0 0;
display: flex;
align-items: stretch;
flex-wrap: nowrap;
overflow-x: auto;
@include custom-scrollbar($query-builder--list-bg,$c-pool);
}
.query-builder--column {
display: flex;
flex-direction: column;
flex: 1 0 0;
}
.query-builder--heading {
@include no-user-select();
width: 100%;
height: $query-builder--heading-height;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
font-weight: 600;
color: $query-builder--heading-text;
background-color: $query-builder--heading-bg;
padding: 0 $scrollbar-width 0 $query-builder--list-gutter;
line-height: $query-builder--heading-height;
/* Accounting for headings w/ optional second item */
& > span {
margin-right: 16px;
}
}
.query-builder--list,
.query-builder--list-empty {
flex: 1 0 0;
}
.query-builder--list {
padding: 0;
overflow: auto;
overflow-x: hidden;
overflow-y: scroll;
@include custom-scrollbar($query-builder--list-bg,$c-pool);
background-color: $query-builder--list-bg;
}
.query-builder--list-empty {
background-color: $query-builder--list-bg;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
color: $query-builder--list-empty-text;
&,
& * {
@include no-user-select();
}
}
.query-builder--list-item {
@include no-user-select();
background-color: $query-builder--list-item-bg;
color: $query-builder--list-item-text;
height: $query-builder--list-item-height;
display: flex;
justify-content: space-between;
align-items: center;
list-style-type: none;
margin: 0;
font-size: 12px;
font-weight: 600;
padding: 0 $query-builder--list-gutter;
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
background-color: $query-builder--list-item-bg-hover;
color: $query-builder--list-item-text-hover;
cursor: pointer;
}
/* Active State */
&.active {
background-color: $query-builder--list-item-bg-active;
color: $query-builder--list-item-text-active;
}
/* Hide dropdowns unless item is active */
& > .dropdown {visibility: hidden;}
&.active > .dropdown {visibility: visible;}
/* Sub-item group for layout purposes */
& > span {
display: flex;
align-items: center;
flex-wrap: nowrap;
white-space: nowrap;
margin-right: 8px;
}
}
/* Filter Element */
.query-builder--filter {
flex: 1 0 0;
display: flex;
& > span {
font-size: 11px;
line-height: 28px;
order: 1;
width: 20px;
margin-right: -20px;
text-align: right;
position: relative;
z-index: 2;
transition: color 0.25s ease;
color: $g9-mountain;
}
& > input {
order: 2;
padding: 0 8px 0 24px;
border-color: $g6-smoke !important;
&:hover {border-color: $g7-graphite !important;}
&:focus {border-color: $c-pool !important;}
&:focus + span {color: $c-pool;}
}
}
/* Checkbox Element */
.query-builder--checkbox {
display: inline-block;
vertical-align: middle;
width: 16px;
height: 16px;
border-radius: 3px;
background-color: $g2-kevlar;
position: relative;
margin-right: 5px;
&:after {
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%) scale(1,1);
width: 20px;
height: 20px;
opacity: 0;
background-color: $c-pool;
border-radius: 50%;
transition:
transform 0.25s ease,
opacity 0.25s ease;
}
}
.query-builder--list-item.active .query-builder--checkbox:after {
opacity: 1;
transform: translate(-50%,-50%) scale(0.4,0.4);
}
/* Caret Element */
.query-builder--caret {
margin-right: 5px;
transform: rotate(0deg);
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}
.query-builder--list-item.active .query-builder--caret {
transform: rotate(90deg);
}
/* Sub lists (Used for the tags list) */
.query-builder--sub-list {
padding: 4px $query-builder--list-gutter 4px $query-builder--sub-list-gutter;
background-color: $query-builder--sub-list-bg;
.query-builder--list-item {padding: 0;}
.query-builder--filter {margin-bottom: 4px;}
}
/* Dropdowns inside query builder list items are forced to "xs" size */
.query-builder--list-item .dropdown-toggle {
height: 22px !important;
line-height: 22px !important;
font-size: 12px !important;
width: 110px !important;
}
/* Toggle for grouping by tags in tags list */
.group-by-tag {
visibility: hidden;
&.active {
visibility: visible;
background: $c-pool;
color: $g20-white;
&:hover {
background: $c-laser;
color: $g20-white;
}
}
}
.query-builder--list-item:hover .group-by-tag,
.query-builder--list-item.active .group-by-tag {
visibility: visible;
}

View File

@ -0,0 +1,106 @@
/*
Query Editor
-------------------------------------
Displays generated query from Query Builder
User can manually type a query as well
NOTE: Variables are located in query-maker.scss
*/
.query-editor {
padding: 8px 8px 0 8px;
border-radius: 0 $radius 0 0;
background-color: $query-editor--bg;
position: relative;
}
.query-editor--field,
.query-editor--status {
font-family: $code-font;
transition:
color 0.25s ease,
background-color 0.25s ease,
border-color 0.25s ease;
border: 2px solid $query-editor--bg;
background-color: $query-editor--field-bg;
}
.query-editor--field {
font-size: 12px;
line-height: 14px;
font-weight: 600;
word-wrap: break-word;
word-break: break-all;
@include custom-scrollbar($query-editor--field-bg, $query-editor--field-text);
display: block;
resize: none;
width: 100%;
height: $query-editor--field-height;
border-bottom: 0;
color: $query-editor--field-text;
padding: 12px 10px 0 10px;
border-radius: $radius $radius 0 0;
margin: 0;
&:hover,
&:hover + .query-editor--status {
border-color: $query-editor--bg;
}
&:focus {
outline: none;
color: $query-editor--field-text !important;
border-color: $c-pool;
}
&:focus + .query-editor--status {
border-color: $c-pool;
}
}
.query-editor--status {
height: $query-editor--status-height;
line-height: $query-editor--status-height;
font-size: 12px;
padding: 0 10px;
padding-right: ($query-editor--templates-width + ($query-editor--templates-offset * 2)) !important;
border-radius: 0 0 $radius $radius;
border-top: 0;
color: $query-editor--status-default;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
span.icon {
margin-right: 5px;
}
/* Error State */
&.query-editor--error { color: $query-editor--status-error; }
/* Warning State */
&.query-editor--warning { color: $query-editor--status-warning; }
/* Success State */
&.query-editor--success { color: $query-editor--status-success; }
/* Loading State */
.loading-dots {
bottom: $query-editor--templates-offset;
left: ($query-editor--templates-offset + 10px);
transform: translateY(50%);
}
}
.dropdown.query-editor--templates {
position: absolute;
bottom: ($query-editor--templates-offset - 8px);
right: $query-editor--templates-offset;
div.dropdown-toggle.btn.btn-sm {
width: $query-editor--templates-width;
padding: 0 9px !important;
height: $query-editor--templates-height !important;
line-height: $query-editor--templates-height !important;
font-size: 12px;
border-radius: $radius-small;
}
.dropdown-menu {
left: initial;
right: 0;
width: $query-editor--templates-menu-width;
min-width: $query-editor--templates-menu-width;
max-width: $query-editor--templates-menu-width;
}
}

View File

@ -0,0 +1,49 @@
$breakpoint-a: 1500px;
$breakpoint-b: 1800px;
$breakpoint-c: 2100px;
@media only screen and (min-width: $breakpoint-a) {
.data-explorer {
.query-builder--list-item {
font-size: 14px;
}
.query-builder--heading {
font-size: 15px;
}
}
}
@media only screen and (min-width: $breakpoint-b) {
.data-explorer {
.query-builder--list-item {
font-size: 15px;
}
.query-builder--heading {
font-size: 16px;
}
.query-editor--field {
font-size: 14px;
line-height: 16px;
}
}
}
@media only screen and (min-width: $breakpoint-c) {
.data-explorer {
.query-builder--list-item {
letter-spacing: 0.3px;
}
.query-builder--heading {
font-size: 17px;
font-weight: 400;
text-transform: uppercase;
}
.query-maker .multi-select-dropdown .dropdown-toggle {
width: 140px;
}
.query-editor--field {
font-size: 16px;
line-height: 18px;
}
}
}

View File

@ -0,0 +1,199 @@
/*
Query Maker
-------------------------------------------------------------
Consists of two parts:
- Query Editor (Manual query entry)
- Query Builder (Asssited query construction)
*/
.query-maker {
position: relative;
left: $explorer-page-padding;
width: calc(100% - #{($explorer-page-padding * 2)});
display: flex;
flex-direction: column;
align-items: stretch;
}
/*
Variables
-------------------------------------------------------------
*/
$query-maker--gutter: 16px;
$query-maker--tabs-height: 44px;
$query-maker--tabs-header-text: $g18-cloud;
$query-maker--tab-width: 138px;
$query-maker--tab-text: $g11-sidewalk;
$query-maker--tab-text-hover: $g15-platinum;
$query-maker--tab-text-active: $g18-cloud;
$query-maker--tab-bg: $g3-castle;
$query-maker--tab-bg-hover: $g4-onyx;
$query-maker--tab-bg-active: $g5-pepper;
$query-maker--tab-contents-bg: $g3-castle;
$query-maker--empty-text: $g10-wolf;
$query-editor--bg: $query-maker--tab-bg-active;
$query-editor--field-text: $c-pool;
$query-editor--field-bg: $g2-kevlar;
$query-editor--field-height: 52px;
$query-editor--status-height: 34px;
/* ^ These 2 should total 86px */
$query-editor--status-default: $g11-sidewalk;
$query-editor--status-success: $c-rainforest;
$query-editor--status-warning: $c-comet;
$query-editor--status-error: $c-dreamsicle;
$query-editor--templates-width: 135px;
$query-editor--templates-height: 22px;
$query-editor--templates-offset: 15px;
$query-editor--templates-menu-width: 200px;
$query-builder--heading-height: 50px;
$query-builder--heading-text: $g13-mist;
$query-builder--heading-bg: $query-maker--tab-bg-active;
$query-builder--list-bg: $g3-castle;
$query-builder--list-empty-text: $g10-wolf;
$query-builder--list-gutter: 11px;
$query-builder--list-item-height: 28px;
$query-builder--list-item-bg: transparent;
$query-builder--list-item-text: $g11-sidewalk;
$query-builder--list-item-bg-hover: $g4-onyx;
$query-builder--list-item-text-hover: $g15-platinum;
$query-builder--list-item-bg-active: $g4-onyx;
$query-builder--list-item-text-active: $g18-cloud;
$query-builder--sub-list-gutter: 24px;
$query-builder--sub-list-bg: $query-builder--list-item-bg-active;
$query-editor-tab-inactive: $g2-kevlar;
$query-editor-tab-active: $g3-castle;
/*
Tabs & Tab Contents
-------------------------------------------------------------
Controls which query is currently being modified
*/
.query-maker--tabs {
margin: $query-maker--gutter 0 0 0;
display: flex;
height: $query-maker--tabs-height;
align-items: center;
}
.query-maker--tabs > div.btn.query-maker--new {
margin-left: 6px;
padding: 0 8px !important;
}
.query-maker--new > span.icon {
margin: 0 !important;
}
.query-maker--tab {
border-radius: $radius $radius 0 0;
height: $query-maker--tabs-height;
margin: 0 2px 0 0;
max-width: $query-maker--tab-width;
flex: 1 0 0;
display: flex;
align-items: center;
justify-content: space-between;
color: $query-maker--tab-text;
background: $query-maker--tab-bg;
cursor: pointer;
padding: 0 9px 0 12px;
transition:
color 0.25s ease,
background-color 0.25s ease;
> label {
font-size: 15px;
font-weight: 600;
margin: 0;
white-space: nowrap;
overflow: hidden;
width: ($query-maker--tab-width - 42px);
text-overflow: ellipsis;
@include no-user-select();
cursor: pointer;
}
&:hover {
color: $query-maker--tab-text-hover;
background-color: $query-maker--tab-bg-hover;
}
&.active {
color: $query-maker--tab-text-active;
background: $query-maker--tab-bg-active;
}
}
.query-maker--delete {
margin: 0;
width: 18px;
height: 18px;
background-color: transparent;
display: inline-block;
vertical-align: text-top;
position: relative;
&:before,
&:after {
display: block;
content: '';
width: 10px;
height: 2px;
border-radius: 1px;
background-color: $g8-storm;
transition:
background-color 0.25s ease;
position: absolute;
top: 50%;
left: 50%;
}
&:before {
transform: translate(-50%,-50%) rotate(45deg);
}
&:after {
transform: translate(-50%,-50%) rotate(-45deg);
}
&:hover {
&:before,
&:after {
background-color: $c-dreamsicle;
}
}
}
.query-maker--tab-contents {
border-radius: 0 $radius $radius $radius;
display: flex;
flex-direction: column;
}
.query-maker--tab-contents,
.query-maker--empty {
flex: 1 0 0;
margin: 0 0 $query-maker--gutter 0;
background-color: $query-maker--tab-contents-bg;
}
.query-maker--empty {
border-radius: $radius;
text-align: center;
color: $query-maker--empty-text;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
&,
& > * {
@include no-user-select();
}
}
/*
Sub-Components
-------------------------------------------------------------
*/
@import 'query-editor';
@import 'query-builder';
@import 'query-maker-responsive';

View File

@ -107,3 +107,8 @@ $resizer-color-active: $c-pool;
width: 100%;
}
}
/* Special rule for when a graph is in the bottom of resizer */
.resize-bottom .graph {
height: 100%;
}

View File

@ -25,6 +25,7 @@
* Table.
*/
.public_fixedDataTable_main {
width: 100% !important;
border-color: $g6-smoke;
border-width: 8px;
border-radius: 0 3px 3px 3px;

View File

@ -2,7 +2,6 @@
Page Header
----------------------------------------------
*/
$page-header-size: 19px;
$page-header-weight: 400 !important;
@ -38,6 +37,7 @@ $page-header-weight: 400 !important;
display: inline-block;
vertical-align: middle;
@include no-user-select();
cursor: default;
}
&__left,
&__right {
@ -64,4 +64,11 @@ $page-header-weight: 400 !important;
&.full-width .page-header__container {
max-width: 100%;
}
&.full-width-no-scrollbar {
padding-right: $page-wrapper-padding;
.page-header__container {
max-width: 100%;
}
}
}

View File

@ -1,9 +0,0 @@
.alert-level-critical {
color: $c-dreamsicle !important;
}
.alert-level-warning {
color: #fdcf30 !important;
}
.alert-level-ok {
color: $c-rainforest !important;
}

View File

@ -378,10 +378,10 @@ $overlay-bg: rgba($c-pool, 0.7);
flex: 0 0 $overlay-controls-height;
width: calc(100% - #{($explorer-page-padding * 2)});
left: $explorer-page-padding;
margin-top: $de-vertical-margin;
margin-top: 16px;
border: 0;
border-radius: $radius;
@include gradient-h($g3-castle,$overlay-controls-bg);
background-color: $g2-kevlar;
border-radius: $radius $radius 0 0;
}
.overlay-controls--right {
display: flex;
@ -433,31 +433,36 @@ $overlay-bg: rgba($c-pool, 0.7);
}
/* Graph editing in Dashboards is a little smaller so the dash can be seen in the background */
.overlay-technology .page-contents {
.overlay-technology .resize-container.page-contents {
background-image: none !important;
}
.overlay-technology .resize-bottom {
background-color: $g0-obsidian !important;
overflow: visible;
}
.overlay-technology .graph {
width: 70%;
left: 15%;
}
.overlay-technology .dash-graph--heading {
top: 0;
height: $dash-graph-heading;
.overlay-technology .graph-heading,
.overlay-technology .graph-container,
.overlay-technology .table-container {
top: -24px;
}
.overlay-technology .dash-graph--container {
height: calc(100% - #{$dash-graph-heading});
top: $dash-graph-heading;
.overlay-technology .graph-heading .graph-actions {
order: 2;
}
.overlay-technology .query-builder {
.overlay-technology .graph-container,
.overlay-technology .table-container {
height: calc(100% - 38px);
}
.overlay-technology .query-maker {
flex: 1 0 0;
margin-bottom: 16px;
margin-top: 2px;
padding: 0 8px;
margin-bottom: 8px;
border-radius: 0 0 $radius $radius;
background-color: $g2-kevlar;
}
.overlay-technology .query-builder--tabs,
.overlay-technology .query-builder--tab-contents,
.overlay-technology .qeditor--empty {
margin: 0;
.overlay-technology .query-maker--tabs {
margin-top: 0;
}
.overlay-technology .query-maker--tab-contents {
margin-bottom: 8px;
}

View File

@ -1,48 +0,0 @@
/**
* Page-wide layout specific styles.
*/
.public_fixedDataTable_main {
width: 100% !important;
}
.data-explorer {
width: 100%;
height: 100%;
position: absolute;
top: 0;
left: 0;
background-color: $g1-raven;
.page-header {
padding-left: $explorer-page-padding;
padding-right: $explorer-page-padding;
}
.page-header__container {
max-width: 100%;
}
.page-contents {
overflow: hidden;
}
}
$query-editor-gutter: 16px;
$query-editor-tab-inactive: $g2-kevlar;
$query-editor-tab-active: $g3-castle;
$query-editor-height: 250px;
$graph-bg-color: $g3-castle;
$graph-active-color: $g4-onyx;
$graph-radius: 4px;
$de-vertical-margin: 16px;
$dygraphs-legend-offset: 32px;
$de-graph-heading-height: 44px;
// DE Specific components
@import 'data-explorer/query-builder';
@import 'data-explorer/page-header';
@import 'data-explorer/query-editor';
@import 'data-explorer/raw-text';
@import 'data-explorer/tag-list';
@import 'data-explorer/visualization';
// Font size in response to screen size
@import 'data-explorer/font-scale';

View File

@ -1,100 +0,0 @@
$breakpoint-a: 1500px;
$breakpoint-b: 1800px;
$breakpoint-c: 2100px;
@media only screen and (min-width: $breakpoint-a) {
.data-explorer {
.qeditor--list-item,
.query-builder--tab-label {
font-size: 14px;
}
.query-builder--tab {
height: 38px;
}
.graph-title {
font-size: 16px;
}
.query-builder--column-heading {
font-size: 15px;
}
}
}
@media only screen and (min-width: $breakpoint-b) {
.data-explorer {
.qeditor--list-item,
.query-builder--tab-label {
font-size: 15px;
}
.query-builder--tab {
height: 42px;
}
.query-builder--column-heading {
font-size: 16px;
}
.toggle-sm .toggle-btn {
font-size: 14px;
}
.btn-xs {
font-size: 13.5px;
}
.query-builder--tab-delete {
width: 20px;
height: 20px;
&:before,
&:after {
width: 10px;
}
}
.raw-text--field,
.query-builder--query-preview pre,
.query-builder--query-preview pre code {
font-size: 14px !important;
line-height: 16px !important;
}
}
}
@media only screen and (min-width: $breakpoint-c) {
.data-explorer {
.qeditor--list-item {
letter-spacing: 0.3px;
}
.query-builder--tab-label {
font-size: 16px;
}
.query-builder--tab {
height: 46px;
}
.query-builder--column-heading {
font-size: 17px;
font-weight: 400;
text-transform: uppercase;
}
.toggle-sm .toggle-btn {
font-size: 14px;
}
.btn-xs {
font-size: 14px;
}
.multi-select-dropdown .dropdown-toggle {
width: 140px;
}
.query-builder--tab-delete {
width: 22px;
height: 22px;
&:before,
&:after {
width: 12px;
}
}
.raw-text--field,
.query-builder--query-preview pre,
.query-builder--query-preview pre code {
font-size: 16px !important;
line-height: 18px !important;
}
}
}

View File

@ -1,27 +0,0 @@
$sessions-dropdown-width: 227px;
.sessions-dropdown {
margin: 0 0 0 4px;
.dropdown-toggle {
width: 227px;
border-radius: 3px 0 0 3px;
}
.dropdown-selected {
display: inline-block;
width: ($sessions-dropdown-width - 28px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
li.dropdown-item > a {
width: ($sessions-dropdown-width - 48px); // 48 is width of 2 actions
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.sessions-dropdown__btn {
margin: 0 16px 0 0;
border-radius: 0 3px 3px 0;
}

View File

@ -1,253 +0,0 @@
/* Variables */
$query-builder-tabs-width: 210px;
$query-builder--column-heading-height: 50px;
.query-builder {
position: relative;
width: calc(100% - #{($explorer-page-padding * 2)});
left: $explorer-page-padding;
border: 0;
display: flex;
align-items: stretch;
justify-content: space-between;
}
// Tabs
.query-builder--tabs {
margin: 16px 0;
display: flex;
width: $query-builder-tabs-width;
flex-direction: column;
align-items: stretch;
background-color: $g3-castle;
border-radius: $radius 0 0 $radius;
}
.query-builder--tabs-heading {
height: 90px;
padding: 0 9px 0 16px;
display: flex;
align-items: center;
justify-content: space-between;
h1 {
@include no-user-select();
font-size: 17px;
font-weight: 400;
text-transform: uppercase;
color: $g18-cloud;
margin: 0;
}
}
.query-builder--tab {
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
color: $g11-sidewalk;
background: transparent;
height: 30px;
cursor: pointer;
padding: 0 8px 0 16px;
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
color: $g15-platinum;
background-color: $g4-onyx;
}
&.active {
color: $g18-cloud;
background: $g5-pepper;
}
&-delete {
margin: 0;
width: 16px;
height: 16px;
background-color: transparent;
display: inline-block;
vertical-align: text-top;
position: relative;
&:before,
&:after {
display: block;
content: '';
width: 8px;
height: 2px;
background-color: $g8-storm;
transition:
background-color 0.25s ease;
position: absolute;
top: 50%;
left: 50%;
}
&:before {
transform: translate(-50%,-50%) rotate(45deg);
}
&:after {
transform: translate(-50%,-50%) rotate(-45deg);
}
&:hover {
&:before,
&:after {
background-color: $c-dreamsicle;
}
}
}
}
.panel--tab-new {
> .dropdown-toggle {
height: 30px !important;
border-radius: $radius;
background-color: $c-pool;
color: $g20-white !important;
padding: 0;
> .icon {
margin: 0 !important;
font-size: 12px;
position: relative;
top: -1px;
}
&:hover {
background-color: $c-laser;
}
}
> .dropdown-menu {
width: 145px !important;
min-width: 108px !important;
max-width: 145px !important;
}
}
.panel--tab-new.open {
> .dropdown-toggle,
> .dropdown-toggle:hover {
background-color: $c-laser !important;
color: $g20-white !important;
}
}
.query-builder--tab-label {
display: inline-block;
font-size: 12px;
font-weight: 600;
white-space: nowrap;
overflow: hidden;
width: ($query-builder-tabs-width - 8px - 16px - 16px);
text-overflow: ellipsis;
@include no-user-select();
}
/*
Tab Contents
-------------------------------------------
*/
.query-builder--tab-contents {
flex: 1 0 0;
margin: 16px 0;
background-color: $g4-onyx;
border-radius: 0 $radius $radius 0;
overflow: hidden;
position: relative;
}
.query-builder--tab-contents > div {
position: absolute;
top: 4px;
left: 4px;
width: calc(100% - 8px);
height: calc(100% - 8px);
}
.query-builder--query-preview {
position: relative;
pre {
display: flex;
align-items: center;
padding: 10px;
border: 2px solid $query-editor-tab-inactive;
background-color: $query-editor-tab-inactive;
color: $c-pool;
border-radius: $radius;
margin-bottom: 0;
overflow: auto;
height: 86px;
@include custom-scrollbar($query-editor-tab-inactive, $c-pool);
code {
margin: 0;
}
}
}
.query-builder--columns {
position: absolute;
width: 100%;
height: calc(100% - 90px);
top: 90px;
}
.query-builder--column-heading {
@include no-user-select();
width: 100%;
height: $query-builder--column-heading-height;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
font-weight: 600;
color: $g13-mist;
padding: 0 9px;
line-height: $query-builder--column-heading-height;
border-bottom: 2px solid $g5-pepper;
}
.query-builder--column {
position: absolute;
width: 25%;
height: 100%;
top: 0;
.qeditor--list {
position: absolute;
top: $query-builder--column-heading-height;
height: calc(100% - #{$query-builder--column-heading-height});
width: 100%;
left: 0;
padding: 0;
overflow: auto;
overflow-x: hidden;
overflow-y: scroll;
@include custom-scrollbar($g4-onyx,$c-pool);
background-color: $g4-onyx;
}
.qeditor--empty {
width: 100%;
margin-top: 0;
height: calc(100% - #{$query-builder--column-heading-height});
position: absolute;
top: $query-builder--column-heading-height;
left: 0;
background-color: transparent;
p,h1,h2,h3,h4,h5,h6 { @include no-user-select(); }
}
}
.query-builder--column:nth-of-type(1) { left: 0; }
.query-builder--column:nth-of-type(2) { left: 25%; }
.query-builder--column:nth-of-type(3) { left: 50%; }
.query-builder--column:nth-of-type(4) { left: 75%; }
/* Time Range Selector */
.time-range-dropdown {
display: inline-block;
.dropdown-toggle {
width: 160px;
}
}
.alert.alert-rawquery {
border-color: $g6-smoke;
color: $g12-forge;
}

View File

@ -1,246 +0,0 @@
/*
Query Editor Styles
-------------------------------------------------
Abbreviated as "qeditor"
*/
// Tabs for switching between queries
.qeditor--tabs {
display: flex;
width: 100%;
justify-content: flex-start;
padding: 8px 9px 0 9px;
background-color: $query-editor-tab-inactive;
flex-wrap: wrap;
&-heading {
flex-basis: 100%;
width: 100%;
font-size: 12px;
color: $g9-mountain;
font-weight: 500;
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.3px;
}
}
.qeditor--tab {
text-align: center;
background-color: $query-editor-tab-inactive;
color: $g13-mist;
height: 28px;
padding: 0 9px;
line-height: 28px;
font-size: 12px;
font-weight: 600;
border-radius: $radius-small $radius-small 0 0;
margin-right: 2px;
@include no-user-select();
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
cursor: pointer;
color: $g20-white;
}
&.active {
background-color: $query-editor-tab-active;
color: $g20-white;
}
}
// List of options
.qeditor--list {
margin: 0;
padding: 9.5px 0 0 0;
background-color: $query-editor-tab-active;
border-radius: 0 0 $radius-small $radius-small;
&-item {
@include no-user-select();
color: $g11-sidewalk;
list-style-type: none;
margin: 0;
font-size: 12px;
font-weight: 500;
padding: 4px 9px;
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
background-color: $g5-pepper;
color: $g15-platinum;
cursor: pointer;
}
}
&-radio {
&.active {
color: $g20-white;
background-color: $g5-pepper;
font-weight: 700;
}
}
&-checkbox {
display: flex;
align-items: center;
justify-content: space-between;
&.checked {
color: $g20-white;
font-weight: 600;
// Animate checked state
.qeditor--list-checkbox__checkbox {
&:before {
opacity: 1;
transform: translate(-50%,-50%) scale(0.4,0.4);
}
}
// Fade in & out dropdowns when checked
.qeditor--hidden-dropdown {
visibility: visible;
.dropdown {
opacity: 1;
}
}
}
&__checkbox {
position: relative;
padding-left: 24px;
&:before {
z-index: 2;
content: '';
position: absolute;
top: 50%;
left: 8px;
transform: translate(-50%,-50%);
width: 20px;
height: 20px;
opacity: 0;
background-color: $c-pool;
border-radius: 50%;
transition:
transform 0.25s ease,
opacity 0.25s ease;
}
&:after {
content: '';
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 16px;
height: 16px;
background-color: $g2-kevlar;
border-radius: 3px;
z-index: 1;
}
}
}
}
.qeditor--list-header {
position: absolute;
top: 7px;
right: 16px;
width: calc(50% - 16px);
height: 30px;
padding: 0;
z-index: 10;
display: flex;
align-items: center;
justify-content: flex-end;
}
// List empty state
.qeditor--empty {
text-align: center;
color: $g10-wolf;
flex: 1 0 0;
margin: 16px 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
background-color: transparent;
background-color: $g3-castle;
border-radius: 0 $radius $radius 0;
&,
& > * {
@include no-user-select();
}
}
// Hidden dropdowns
.qeditor--hidden-dropdown {
visibility: hidden;
transition: all 0.3s all;
.dropdown {
transition: opacity 0.3s ease;
opacity: 0;
}
}
// Filter list results
.qeditor--filter {
position: relative;
width: 100%;
display: block;
background-color: $g3-castle;
border: 2px solid $g6-smoke;
color: $g13-mist;
height: 30px;
border-radius: 15px;
font-size: 13px;
padding-left: 28px;
outline: none;
color: $g20-white;
font-weight: 700;
transition:
border-color 0.25s ease,
color 0.25s ease,
background-color 0.25s ease;
&:focus {
border-color: $c-pool;
& + .icon {
color: $g20-white;
}
}
&::-webkit-input-placeholder {
color: $g10-wolf;
font-weight: 500;
}
&:-moz-placeholder { /* Firefox 18- */
color: $g10-wolf;
font-weight: 500;
}
&::-moz-placeholder { /* Firefox 19+ */
color: $g10-wolf;
font-weight: 500;
}
&:-ms-input-placeholder {
color: $g10-wolf;
font-weight: 500;
}
+ .icon {
position: absolute;
top: 50%;
left: 11px;
transform: translateY(-50%);
color: $g10-wolf;
transition: color 0.25s ease;
font-size: 12px;
z-index: 2;
}
}

View File

@ -1,156 +0,0 @@
/*
Variables
-------------------------------------
*/
$raw-text-color: $c-pool;
$raw-text-height: 52px;
$raw-status-height: 34px;
/* ^ These 2 should total to 86px */
$query-template-dropdown-width: 135px;
$query-template-dropdown-height: 22px;
$query-template-dropdown-offset: 6px;
$query-template-dropdown-menu-width: 200px;
/*
Dropping the metaphorical CSS nuke here,
was experiencing some weird typographic jank
between builder / raw tabs
*/
.raw-text--field,
.query-builder--query-preview pre,
.query-builder--query-preview pre code {
font-style: normal !important;
letter-spacing: 0 !important;
font-size: 12px !important;
font-variant: normal !important;
line-height: 14px !important;
font-family: $code-font !important;
font-weight: 600 !important;
word-wrap: break-word !important;
word-break: break-all !important;
white-space: pre-wrap !important;
-webkit-font-smoothing: antialiased;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
resize: none;
text-size-adjust: 100% !important;
text-shadow: none !important;
}
.raw-text--field {
@include custom-scrollbar($g2-kevlar, $raw-text-color);
display: block;
width: 100%;
height: $raw-text-height;
background-color: $g2-kevlar;
border: 2px solid $g2-kevlar;
border-bottom: 0;
color: $raw-text-color;
padding: 12px 10px 0 10px;
border-radius: $radius $radius 0 0;
margin: 0;
transition:
color 0.25s ease,
background-color 0.25s ease,
border-color 0.25s ease;
&::-webkit-input-placeholder { /* Chrome/Opera/Safari */
color: $g8-storm;
}
&::-moz-placeholder { /* Firefox 19+ */
color: $g8-storm;
}
&:-ms-input-placeholder { /* IE 10+ */
color: $g8-storm;
}
&:-moz-placeholder { /* Firefox 18- */
color: $g8-storm;
}
&:hover,
&:hover + .raw-text--status {
border-color: $g5-pepper;
}
&:focus {
outline: none;
color: $raw-text-color !important;
border-color: $c-pool;
}
&:focus + .raw-text--status {
border-color: $c-pool;
}
}
.raw-text--status {
position: relative;
width: 100%;
height: $raw-status-height;
line-height: $raw-status-height;
font-size: 12px;
background-color: $g2-kevlar;
border: 2px solid $g2-kevlar;
padding: 0 10px;
padding-right: ($query-template-dropdown-width + ($query-template-dropdown-offset * 2)) !important;
border-radius: 0 0 $radius $radius;
border-top: 0;
color: $g11-sidewalk;
font-family: $code-font;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
transition:
color 0.25s ease,
background-color 0.25s ease,
border-color 0.25s ease;
span.icon {
margin-right: 5px;
}
/* Error State */
&.raw-text--error {
color: $c-dreamsicle;
}
/* Warning State */
&.raw-text--warning {
color: $c-comet;
}
/* Success State */
&.raw-text--success {
color: $c-rainforest;
}
/* Loading State */
.loading-dots {
top: calc(50% + 2px);
left: 14px;
transform: translateY(-50%);
}
}
.dropdown.query-template {
position: absolute;
top: ($raw-text-height + (($raw-status-height - $query-template-dropdown-height) / 2));
right: $query-template-dropdown-offset;
div.dropdown-toggle.btn.btn-sm {
width: $query-template-dropdown-width;
padding: 0 9px !important;
height: $query-template-dropdown-height !important;
line-height: $query-template-dropdown-height !important;
font-size: 12px;
border-radius: $radius-small;
}
.dropdown-menu {
left: initial;
right: 0;
width: $query-template-dropdown-menu-width;
min-width: $query-template-dropdown-menu-width;
max-width: $query-template-dropdown-menu-width;
}
}

View File

@ -1,183 +0,0 @@
.tag-list {
&__item {
height: 30px;
display: flex;
align-items: center;
justify-content: space-between;
&:hover .tag-list__group-by {
display: flex;
}
&.open {
font-weight: 600;
color: $g20-white;
.tag-list__caret .icon {
transform: translateY(-50%) rotate(90deg);
}
}
}
&__title {
display: flex;
align-items:center;
justify-content: flex-start;
.badge {
background-color: $g2-kevlar;
color: $c-pool;
margin-left: 5px;
}
}
&__caret {
width: 16px;
position: relative;
.icon {
font-size: 10px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%) rotate(0deg);
transition: transform 0.25s ease;
}
}
}
.tag-value-list {
padding: 0;
&__checkbox {
width: 16px;
height: 16px;
background-color: $g2-kevlar;
border-radius: 3px;
position: relative;
margin-right: 8px;
&:after {
z-index: 2;
content: '';
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
width: 20px;
height: 20px;
opacity: 0;
background-color: $c-pool;
border-radius: 50%;
transition:
transform 0.25s ease,
opacity 0.25s ease;
}
}
&__item {
padding-left: 35px;
position: relative;
display: flex;
align-items: center;
&.active {
background: $g4-onyx;
color: $g20-white;
font-weight: 600;
.tag-value-list__checkbox:after {
transform: translate(-50%,-50%) scale(0.4,0.4);
opacity: 1;
}
}
}
&__filter {
position: relative;
width: 100%;
display: block;
background-color: $g3-castle;
border: 2px solid $g5-pepper;
color: $g13-mist;
height: 30px;
border-radius: 15px;
font-size: 13px;
padding-left: 25px;
outline: none;
color: $g20-white;
font-weight: 700;
transition:
border-color 0.25s ease,
color 0.25s ease,
background-color 0.25s ease;
&:focus {
border-color: $c-pool;
& + .icon {
color: $g20-white;
}
}
&::-webkit-input-placeholder {
color: $g10-wolf;
font-weight: 500;
}
&:-moz-placeholder { /* Firefox 18- */
color: $g10-wolf;
font-weight: 500;
}
&::-moz-placeholder { /* Firefox 19+ */
color: $g10-wolf;
font-weight: 500;
}
&:-ms-input-placeholder {
color: $g10-wolf;
font-weight: 500;
}
+ .icon {
position: absolute;
top: 50%;
left: 39px;
transform: translateY(-50%);
color: $g10-wolf;
transition: color 0.25s ease;
font-size: 12px;
z-index: 2;
}
&-container {
padding: 8px 9.5px 8px 31px;
position: relative;
}
}
}
.tag-list__group-by {
display: none;
background-color: $g5-pepper;
border-color: $g5-pepper;
color: $g13-mist !important;
&:hover {
background-color: $g6-smoke;
border-color: $g6-smoke;
color: $g20-white !important;
}
&:active,
&:active:hover,
&:active:focus {
color: $g20-white !important;
background-color: $g7-graphite;
border-color: $g6-smoke;
}
&.active {
display: flex;
background: $c-pool;
border-color: $c-pool;
&:hover {
background: $c-laser;
border-color: $c-laser;
}
}
}

View File

@ -1,24 +0,0 @@
/*
Styles for Hosts List & Host View
----------------------------------------------
*/
.graph-container.hosts-graph {
padding: 8px 16px;
}
.host-list--active-source {
text-transform: uppercase;
font-size: 15px;
font-weight: 400;
color: $g17-whisper;
span {
font-weight: 900;
}
}
.host-table-header {
display: flex;
align-items: center;
justify-content: space-between;
}

View File

@ -171,218 +171,63 @@ $kapacitor-font-sm: 13px;
div.qeditor.kapacitor-metric-selector {
border-radius: 0;
background-color: transparent;
padding: 0;
// Query sample
.qeditor--query-preview pre {
.kapacitor-metric-selector {
/* Query Preview */
pre {
font-size: $kapacitor-font-sm;
background-color: $kapacitor-graphic-color;
color: $kapacitor-accent;
color: $c-pool;
border-radius: $kap-radius-lg $kap-radius-lg 0 0;
border: 0;
margin: 0;
padding: $kap-padding-md $kap-padding-lg;
}
pre code {
line-height: ($kapacitor-font-sm + 3px);
white-space: pre-wrap;
}
.query-builder {
height: 240px;
margin-top: 2px;
overflow: visible;
}
.query-builder--column {
margin-right: 2px;
&:last-child {margin-right: 0;}
}
.query-builder--column:nth-child(1) .query-builder--list {
border-bottom-left-radius: $kap-radius-lg;
}
.query-builder--column:nth-child(4) .query-builder--list,
.query-builder--column:nth-child(4) .query-builder--list-empty {
border-bottom-right-radius: $kap-radius-lg;
}
.query-builder--heading {
background-color: $kapacitor-graphic-color;
margin-bottom: 2px;
}
.query-builder--list {
@include custom-scrollbar($kapacitor-graphic-color, $kapacitor-accent);
}
// Tabs
.qeditor--tabs {
background-color: $kapacitor-graphic-color;
padding: $kap-padding-sm $kap-padding-lg 0 $kap-padding-lg;
border-top: 2px solid $kapacitor-divider-color;
.group-by-tag.active {
background-color: $c-rainforest !important;
&:hover {background-color: $c-honeydew !important;}
}
.qeditor--tab {
font-size: $kapacitor-font-sm;
background-color: $g3-castle;
font-weight: 700;
padding: 0 $kap-padding-md;
height: $kap-input-height;
line-height: ($kap-input-height - 4px);
margin: 0;
border-radius: 0;
border-style: solid;
border-color: $g5-pepper;
border-width: 2px 0 2px 2px;
color: $g11-sidewalk;
&:first-child {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
&:last-child {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-right-width: 2px;
}
&:hover {
background-color: $g4-onyx;
color: $g20-white;
}
&.active {
background-color: $g5-pepper;
color: $kapacitor-accent;
}
.query-builder--list-item .query-builder--checkbox:after {
background-color: $c-rainforest;
}
// Editor List
.kapacitor-tab-list {
background-color: $kapacitor-graphic-color;
border-radius: 0 0 $kap-radius-lg $kap-radius-lg;
.query-builder--column {
position: relative;
top: initial;
left: initial;
width: 100%;
height: 190px;
.qeditor--list-header {
width: 50%;
top: -34px;
right: 0;
z-index: 5;
.query-builder--filter {
input.form-control {
color: $c-rainforest !important;
&:focus {
color: $g20-white !important;
box-shadow: 0 0 6px 0px $c-rainforest !important;
border-color: $c-rainforest !important;
}
.qeditor--list {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.group-by-time-dropdown {
width: 70px;
&:focus + span.icon {
color: $c-rainforest !important;
}
}
.query-builder--column-heading {
display: none;
}
}
.qeditor--list {
overflow: auto;
padding-top: $kap-padding-sm;
background-color: transparent;
min-height: $metric-selector-height;
max-height: ($metric-selector-height * 2);
// height: $metric-selector-height;
border-radius: 0 0 $kap-radius-lg $kap-radius-lg;
@include custom-scrollbar($kapacitor-graphic-color,$kapacitor-accent);
}
.qeditor--list-header {
background-color: transparent;
padding: $kap-padding-sm $kap-padding-lg 0 $kap-padding-lg;
}
.qeditor--filter,
.tag-value-list__filter {
border-radius: 4px;
padding-left: ($kap-input-height + ($kap-padding-sm / 2));
font-family: 'Roboto', Helvetica, Arial, Tahoma, Verdana, sans-serif;
&::-webkit-input-placeholder { color: $g11-sidewalk; font-weight: 600; }
&::-moz-placeholder { color: $g11-sidewalk; font-weight: 600; }
&:-ms-input-placeholder { color: $g11-sidewalk; font-weight: 600; }
&:-moz-placeholder { color: $g11-sidewalk; font-weight: 600; }
& + .icon {
left: ((($kap-input-height + ($kap-padding-sm / 2)) / 2) + $kap-padding-lg + 3px);
top: calc(50% + #{($kap-padding-sm / 2)});
font-size: ($kapacitor-font-sm + 1px);
transform: translate(-50%,-50%);
color: $g11-sidewalk;
}
&:focus + .icon {
color: $kapacitor-accent;
}
}
.tag-value-list__filter-container {
padding: $kap-padding-sm $kap-padding-lg;
.tag-value-list__filter + .icon {
top: 50%;
}
}
.qeditor--list-item {
font-size: $kapacitor-font-sm;
font-weight: 600;
padding-left: $kap-padding-lg;
padding-right: $kap-padding-lg;
color: $g11-sidewalk;
&:hover {
background-color: $g3-castle;
color: $g20-white;
}
&.active {
font-weight: 600;
background-color: $g5-pepper;
color: $kapacitor-accent;
}
}
.qeditor--hidden-dropdown {
.btn.dropdown-toggle {
width: 260px;
}
}
.qeditor--list-checkbox__checkbox {
&:before {
background-color: $kapacitor-accent;
}
}
.group-by-time-dropdown-label {
font-weight: 600;
font-size: $kapacitor-font-sm;
}
.tag-list__title .badge {
color: $kapacitor-accent;
}
.tag-value-list__checkbox:after {
background-color: $kapacitor-accent;
}
.tag-value-list__item.qeditor--list-item.active {
background-color: transparent;
}
.btn.tag-list__group-by.active {
background-color: $kapacitor-accent;
border-color: $kapacitor-accent;
&:hover {
background-color: $c-honeydew;
border-color: $c-honeydew;
}
}
.tag-list__toggle {
width: auto;
.tag-list__toggle-btn {
border-color: $g5-pepper;
background-color: $kapacitor-graphic-color;
color: $g11-sidewalk;
font-size: $kapacitor-font-sm;
font-weight: 700;
width: auto;
padding: 0 $kap-padding-md;
&:hover {
background-color: $g4-onyx;
color: $g20-white;
}
&.active {
background-color: $g5-pepper;
border-color: $g5-pepper;
color: $kapacitor-accent;
}
}
}
// Empty State
.qeditor--empty {
background-color: $kapacitor-graphic-color;
height: $metric-selector-height;
min-height: $metric-selector-height;
max-height: $metric-selector-height;
}
}
@ -420,6 +265,14 @@ div.qeditor.kapacitor-metric-selector {
&::-moz-placeholder { color: $g9-mountain; }
&:-ms-input-placeholder { color: $g9-mountain; }
&:-moz-placeholder { color: $g9-mountain; }
&::selection {
background-color: $c-rainforest !important;
color: $g20-white !important;
}
&::-moz-selection {
background-color: $c-rainforest !important;
color: $g20-white !important;
}
}
.alert-message--endpoint {
@ -480,7 +333,7 @@ div.qeditor.kapacitor-metric-selector {
border-bottom: 2px solid $kapacitor-divider-color;
& > p {
margin-right: ($kap-padding-sm - 2px);
margin-right: ($kap-padding-sm - 2px) !important;
}
}
.alert-message--email-body {
@ -586,78 +439,26 @@ div.qeditor.kapacitor-metric-selector {
}
}
}
// Overriding form styles in the builder
.rule-builder {
input[type="text"] {
background-color: $kapacitor-graphic-color;
color: $kapacitor-accent !important;
font-weight: 600;
font-size: $kapacitor-font-sm;
font-family: Consolas, "Lucida Console", Monaco, monospace;
height: $kap-input-height;
&:focus {
border-color: $kapacitor-accent;
outline: none;
box-shadow: none;
color: $g20-white !important;
}
}
.dropdown-toggle,
input[type="text"] {
padding-left: $kap-padding-sm;
padding-right: $kap-padding-sm;
height: $kap-input-height;
}
.dropdown-toggle,
.dropdown.group-by-time-dropdown .btn.dropdown-toggle,
.qeditor--list-checkbox .dropdown .btn.dropdown-toggle {
width: 100%;
text-align: left;
position: relative;
color: $kapacitor-accent !important;
text-transform: capitalize;
font-size: $kapacitor-font-sm;
.caret {
position: absolute;
top: 50%;
right: $kap-padding-sm;
transform: translate(0,-50%);
}
&:hover {
color: $c-honeydew !important;
}
}
.size-486 {
width: 486px;
}
.size-384 {
width: 384px;
}
.size-256 {
width: 256px;
}
.size-176 {
width: 176px;
}
.size-166 {
width: 166px;
}
.size-136 {
width: 136px;
}
.size-106 {
width: 106px;
}
.size-66 {
width: 66px;
}
.size-49 {
width: 49px;
}
.rule-builder .form-control--green {
font-weight: 600 !important;
}
input.size-486 {width: 486px;}
input.size-384 {width: 384px;}
input.size-256 {width: 256px;}
input.size-176 {width: 176px;}
input.size-166 {width: 166px;}
input.size-136 {width: 136px;}
input.size-106 {width: 106px;}
input.size-66 {width: 66px;}
input.size-49 {width: 49px;}
.dropdown.size-486 .dropdown-toggle {width: 486px;}
.dropdown.size-384 .dropdown-toggle {width: 384px;}
.dropdown.size-256 .dropdown-toggle {width: 256px;}
.dropdown.size-176 .dropdown-toggle {width: 176px;}
.dropdown.size-166 .dropdown-toggle {width: 166px;}
.dropdown.size-136 .dropdown-toggle {width: 136px;}
.dropdown.size-106 .dropdown-toggle {width: 106px;}
.dropdown.size-66 .dropdown-toggle {width: 66px;}
.dropdown.size-49 .dropdown-toggle {width: 49px;}

View File

@ -217,10 +217,10 @@ button.btn.btn-sm > span.icon {
.form-control,
textarea,
input {
&::-webkit-input-placeholder { color: $g10-wolf; font-weight: 500 !important; }
&::-moz-placeholder { color: $g10-wolf; font-weight: 500 !important; }
&:-ms-input-placeholder { color: $g10-wolf; font-weight: 500 !important; }
&:-moz-placeholder { color: $g10-wolf; font-weight: 500 !important; }
&::-webkit-input-placeholder { color: $g9-mountain; font-weight: 500 !important; }
&::-moz-placeholder { color: $g9-mountain; font-weight: 500 !important; }
&:-ms-input-placeholder { color: $g9-mountain; font-weight: 500 !important; }
&:-moz-placeholder { color: $g9-mountain; font-weight: 500 !important; }
}
/* Text Selection Styling */
@ -233,182 +233,21 @@ input {
color: $g20-white !important;
}
/* Green (Kapacitor) themed inputs */
.form-control--green {
color: $c-rainforest !important;
&:focus {color: $g20-white !important;}
/*
Dark Dropdowns
----------------------------------------------
*/
.dropdown-toggle {
position: relative;
text-align: left;
.caret {
position: absolute;
top: calc(50% + 1px);
right: 8px;
transform: translateY(-50%);
&::selection {
background-color: $c-rainforest !important;
color: $g20-white !important;
}
> .icon {
font-size: 16px;
display: inline-block;
vertical-align: middle;
margin-right: 6px;
position: relative;
top: -1px;
}
}
.dropdown-menu {
float: none !important;
width: 100%;
min-width: 100%;
max-width: 100%;
margin: 0 !important;
padding: 0 !important;
max-height: 290px;
overflow: auto;
@include custom-scrollbar-round($c-pool, $c-laser);
@include gradient-h($c-ocean, $c-pool);
box-shadow: 0 2px 5px 0.6px fade-out($g0-obsidian, 0.8);
> li {
width: 100%;
font-size: 0px;
&:hover {
@include gradient-h($c-laser, $c-pool);
}
}
> li > a {
width: 100%;
border-radius: 0 !important;
display: inline-block;
padding: 7px 9px;
font-size: 13px;
line-height: 15px;
font-weight: 500;
color: $c-yeti !important;
background-color: transparent;
transition:
color 0.25s ease;
&:hover {
cursor: pointer;
background-color: transparent;
color: $g20-white !important;
}
&:active,
&:active:focus {
@include gradient-h($c-sapphire, $c-pool);
}
&:focus {
@include gradient-h($c-ocean, $c-pool);
}
}
> li:last-child a {
border-radius: 0 0 3px 3px;
}
> li:first-child a {
border-radius: 3px 3px 0 0;
}
}
.dropdown.dropdown-kapacitor .dropdown-menu {
@include custom-scrollbar($c-rainforest, $c-honeydew);
@include gradient-h($c-pool, $c-rainforest);
> li:hover {
@include gradient-h($c-laser, $c-rainforest);
}
> li > a {
color: $c-mint !important;
&:hover {
color: $g20-white !important;
}
}
}
.dropdown.dropdown-chronograf .dropdown-menu {
@include custom-scrollbar($c-comet, $c-potassium);
@include gradient-h($c-ocean, $c-comet);
> li:hover {
@include gradient-h($c-laser, $c-comet);
}
> li > a {
color: $c-cremedeviolette !important;
&:hover {
color: $g20-white !important;
}
}
}
.dropdown-header {
height: 32px;
line-height: 30px;
padding: 0 9px;
white-space: nowrap;
font-size: 14px !important;
font-weight: 900;
color: $c-neutrino !important;
text-transform: none !important;
border-bottom: 2px solid $c-pool;
background-color: $c-ocean;
&:hover {
background-image: none !important;
background-color: $c-ocean !important;
cursor: default;
&::-moz-selection {
background-color: $c-rainforest !important;
color: $g20-white !important;
}
}
/* Dropdown Actions */
.dropdown-item {
position: relative;
> a {
position: relative;
z-index: 1;
}
}
.dropdown-item__actions {
z-index: 2;
position: absolute;
top: 0;
right: 3px;
height: 100%;
width: auto;
display: flex;
align-items: center;
justify-content: flex-end;
}
.dropdown-item__action {
padding: 0;
margin: 0;
width: 24px;
height: 24px;
border-radius: 2px;
background-color: transparent;
border: none !important;
font-size: 13px;
transition:
text-shadow 0.25s ease,
color 0.25s ease;
color: $c-sapphire;
&[data-target="#deleteExplorerModal"] .icon {
position: relative;
right: -1px;
}
&:hover {
color: $g20-white;
text-shadow:
0 0 2px $c-hydrogen,
0 0 3px $c-laser,
0 0 6px $c-ocean;
background-color: transparent;
}
}
/*
Dark Code Samples

View File

@ -81,6 +81,52 @@
}
}
// Tabs for switching between queries
.qeditor--tabs {
display: flex;
width: 100%;
justify-content: flex-start;
padding: 8px 9px 0 9px;
background-color: $query-editor-tab-inactive;
flex-wrap: wrap;
&-heading {
flex-basis: 100%;
width: 100%;
font-size: 12px;
color: $g9-mountain;
font-weight: 500;
margin-bottom: 8px;
text-transform: uppercase;
letter-spacing: 0.3px;
}
}
.qeditor--tab {
text-align: center;
background-color: $query-editor-tab-inactive;
color: $g13-mist;
height: 28px;
padding: 0 9px;
line-height: 28px;
font-size: 12px;
font-weight: 600;
border-radius: $radius-small $radius-small 0 0;
margin-right: 2px;
@include no-user-select();
transition:
color 0.25s ease,
background-color 0.25s ease;
&:hover {
cursor: pointer;
color: $g20-white;
}
&.active {
background-color: $query-editor-tab-active;
color: $g20-white;
}
}
/*
Loading Dots
----------------------------------------------