Merge branch 'master' into ifql/join
commit
9902cf295d
|
@ -61,6 +61,7 @@
|
|||
1. [#3166](https://github.com/influxdata/chronograf/pull/3166): Fixes naming of new TICKScripts
|
||||
1. [#3449](https://github.com/influxdata/chronograf/pull/3449): Fixes data explorer query error reporting regression
|
||||
1. [#3453](https://github.com/influxdata/chronograf/pull/3453): Fix Kapacitor Logs fetch regression
|
||||
1. [#3500](https://github.com/influxdata/chronograf/pull/3500): Fix switching sources for a dashboard cell
|
||||
|
||||
## v1.4.4.1 [2018-04-16]
|
||||
|
||||
|
|
|
@ -140,7 +140,7 @@ type Talk struct{}
|
|||
// Kafka sends alerts to any Kafka brokers specified in the handler config
|
||||
type Kafka struct {
|
||||
Cluster string `json:"cluster"`
|
||||
Topic string `json:"topic"`
|
||||
Topic string `json:"kafka-topic"`
|
||||
Template string `json:"template"`
|
||||
}
|
||||
|
||||
|
|
|
@ -128,9 +128,12 @@ export class CheckSources extends Component<Props, State> {
|
|||
const source = sources.find(s => s.id === params.sourceID)
|
||||
const defaultSource = sources.find(s => s.default === true)
|
||||
|
||||
const role = _.get(this.props, 'auth.me.role', '')
|
||||
const nextRole = _.get(nextProps, 'auth.me.role', '')
|
||||
|
||||
if (
|
||||
isUserAuthorized(this.props.auth.me.role, ADMIN_ROLE) &&
|
||||
!isUserAuthorized(nextProps.auth.me.role, ADMIN_ROLE)
|
||||
isUserAuthorized(role, ADMIN_ROLE) &&
|
||||
!isUserAuthorized(nextRole, ADMIN_ROLE)
|
||||
) {
|
||||
return router.push('/')
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ import React, {Component} from 'react'
|
|||
|
||||
import _ from 'lodash'
|
||||
import uuid from 'uuid'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
import ResizeContainer from 'src/shared/components/ResizeContainer'
|
||||
import QueryMaker from 'src/dashboards/components/QueryMaker'
|
||||
|
@ -16,7 +17,6 @@ import defaultQueryConfig from 'src/utils/defaultQueryConfig'
|
|||
import {buildQuery} from 'src/utils/influxql'
|
||||
import {getQueryConfigAndStatus} from 'src/shared/apis'
|
||||
import {IS_STATIC_LEGEND} from 'src/shared/constants'
|
||||
import {ColorString, ColorNumber} from 'src/types/colors'
|
||||
import {nextSource} from 'src/dashboards/utils/sources'
|
||||
|
||||
import {
|
||||
|
@ -43,6 +43,9 @@ import {
|
|||
Legend,
|
||||
Status,
|
||||
} from 'src/types'
|
||||
import {ColorString, ColorNumber} from 'src/types/colors'
|
||||
import {SourceOption} from 'src/dashboards/components/OverlayControls'
|
||||
|
||||
type QueryTransitions = typeof queryTransitions
|
||||
type EditRawTextAsyncFunc = (
|
||||
url: string,
|
||||
|
@ -96,37 +99,29 @@ interface State {
|
|||
isStaticLegend: boolean
|
||||
}
|
||||
|
||||
const createWorkingDraft = (
|
||||
sourceLink: string,
|
||||
query: CellQuery
|
||||
): QueryConfig => {
|
||||
const createWorkingDraft = (source: Source, query: CellQuery): QueryConfig => {
|
||||
const {queryConfig} = query
|
||||
const draft: QueryConfig = {
|
||||
...queryConfig,
|
||||
id: uuid.v4(),
|
||||
sourceLink,
|
||||
source,
|
||||
}
|
||||
|
||||
return draft
|
||||
}
|
||||
|
||||
const createWorkingDrafts = (
|
||||
sourceLink: string,
|
||||
source: Source,
|
||||
queries: CellQuery[]
|
||||
): QueryConfig[] =>
|
||||
_.cloneDeep(
|
||||
queries.map((query: CellQuery) => createWorkingDraft(sourceLink, query))
|
||||
queries.map((query: CellQuery) => createWorkingDraft(source, query))
|
||||
)
|
||||
|
||||
@ErrorHandling
|
||||
class CellEditorOverlay extends Component<Props, State> {
|
||||
private overlayRef: HTMLDivElement
|
||||
|
||||
private formattedSources = this.props.sources.map(s => ({
|
||||
...s,
|
||||
text: `${s.name} @ ${s.url}`,
|
||||
}))
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
||||
|
@ -142,7 +137,7 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
queries = [{id: uuid.v4()}]
|
||||
}
|
||||
|
||||
const queriesWorkingDraft = createWorkingDrafts(this.sourceLink, queries)
|
||||
const queriesWorkingDraft = createWorkingDrafts(this.initialSource, queries)
|
||||
|
||||
this.state = {
|
||||
queriesWorkingDraft,
|
||||
|
@ -254,6 +249,14 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
)
|
||||
}
|
||||
|
||||
private get formattedSources(): SourceOption[] {
|
||||
const {sources} = this.props
|
||||
return sources.map(s => ({
|
||||
...s,
|
||||
text: `${s.name} @ ${s.url}`,
|
||||
}))
|
||||
}
|
||||
|
||||
private onRef = (r: HTMLDivElement) => {
|
||||
this.overlayRef = r
|
||||
}
|
||||
|
@ -284,7 +287,7 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
this.setState({
|
||||
queriesWorkingDraft: [
|
||||
...queriesWorkingDraft,
|
||||
{...defaultQueryConfig({id: uuid.v4()}), sourceLink: null},
|
||||
{...defaultQueryConfig({id: uuid.v4()}), source: this.initialSource},
|
||||
],
|
||||
})
|
||||
this.handleSetActiveQueryIndex(newIndex)
|
||||
|
@ -301,13 +304,13 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
const {queriesWorkingDraft, isStaticLegend} = this.state
|
||||
const {cell, thresholdsListColors, gaugeColors, lineColors} = this.props
|
||||
|
||||
const queries = queriesWorkingDraft.map(q => {
|
||||
const queries: CellQuery[] = queriesWorkingDraft.map(q => {
|
||||
const timeRange = q.range || {upper: null, lower: TEMP_VAR_DASHBOARD_TIME}
|
||||
|
||||
const source = getDeep<string | null>(q.source, 'links.self', null)
|
||||
return {
|
||||
queryConfig: q,
|
||||
query: q.rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, q),
|
||||
sourceLink: q.sourceLink,
|
||||
source,
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -318,12 +321,14 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
lineColors,
|
||||
})
|
||||
|
||||
this.props.onSave({
|
||||
const newCell: Cell = {
|
||||
...cell,
|
||||
queries,
|
||||
colors,
|
||||
legend: isStaticLegend ? staticLegend : {},
|
||||
})
|
||||
}
|
||||
|
||||
this.props.onSave(newCell)
|
||||
}
|
||||
|
||||
private handleClickDisplayOptionsTab = isDisplayOptionsTabActive => () => {
|
||||
|
@ -342,10 +347,9 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
const queriesWorkingDraft: QueryConfig[] = this.state.queriesWorkingDraft.map(
|
||||
q => ({
|
||||
..._.cloneDeep(q),
|
||||
sourceLink: source.links.self,
|
||||
source,
|
||||
})
|
||||
)
|
||||
|
||||
this.setState({queriesWorkingDraft})
|
||||
}
|
||||
|
||||
|
@ -427,7 +431,7 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
|
||||
return {
|
||||
...config.queryConfig,
|
||||
sourceLink: q.sourceLink,
|
||||
source: q.source,
|
||||
isQuerySupportedByExplorer,
|
||||
}
|
||||
}
|
||||
|
@ -445,14 +449,20 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
private findSelectedSource = (): string => {
|
||||
const {source} = this.props
|
||||
const sources = this.formattedSources
|
||||
const currentSource = _.get(this.state.queriesWorkingDraft, '0.sourceLink')
|
||||
const currentSource = getDeep<Source | null>(
|
||||
this.state.queriesWorkingDraft,
|
||||
'0.source',
|
||||
null
|
||||
)
|
||||
|
||||
if (!currentSource) {
|
||||
const defaultSource = sources.find(s => s.id === source.id)
|
||||
const defaultSource: Source = sources.find(s => s.id === source.id)
|
||||
return (defaultSource && defaultSource.text) || 'No sources'
|
||||
}
|
||||
|
||||
const selected = sources.find(s => s.links.self === currentSource)
|
||||
const selected: Source = sources.find(
|
||||
s => s.links.self === currentSource.links.self
|
||||
)
|
||||
return (selected && selected.text) || 'No sources'
|
||||
}
|
||||
|
||||
|
@ -514,23 +524,42 @@ class CellEditorOverlay extends Component<Props, State> {
|
|||
return result
|
||||
}
|
||||
|
||||
private get sourceLink(): string {
|
||||
private get initialSource(): Source {
|
||||
const {
|
||||
cell: {queries},
|
||||
source: {links},
|
||||
source,
|
||||
sources,
|
||||
} = this.props
|
||||
return _.get(queries, '0.source.links.self', links.self)
|
||||
|
||||
const initialSourceLink: string = getDeep<string>(queries, '0.source', null)
|
||||
|
||||
if (initialSourceLink) {
|
||||
const initialSource = sources.find(
|
||||
s => s.links.self === initialSourceLink
|
||||
)
|
||||
|
||||
return initialSource
|
||||
}
|
||||
return source
|
||||
}
|
||||
|
||||
private get source(): Source {
|
||||
const {source, sources} = this.props
|
||||
const query = _.get(this.state.queriesWorkingDraft, 0, {sourceLink: null})
|
||||
const query = _.get(this.state.queriesWorkingDraft, 0, {source: null})
|
||||
|
||||
if (!query.sourceLink) {
|
||||
if (!query.source) {
|
||||
return source
|
||||
}
|
||||
|
||||
return sources.find(s => s.links.self === query.sourceLink) || source
|
||||
const foundSource = sources.find(
|
||||
s =>
|
||||
s.links.self ===
|
||||
getDeep<string | null>(query, 'source.links.self', null)
|
||||
)
|
||||
if (foundSource) {
|
||||
return foundSource
|
||||
}
|
||||
return source
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,135 +0,0 @@
|
|||
import React from 'react'
|
||||
import PropTypes from 'prop-types'
|
||||
import {connect} from 'react-redux'
|
||||
|
||||
import RefreshingGraph from 'src/shared/components/RefreshingGraph'
|
||||
import buildQueries from 'utils/buildQueriesForGraphs'
|
||||
import VisualizationName from 'src/dashboards/components/VisualizationName'
|
||||
|
||||
import {getCellTypeColors} from 'src/dashboards/constants/cellEditor'
|
||||
import {colorsStringSchema, colorsNumberSchema} from 'shared/schemas'
|
||||
|
||||
const DashVisualization = (
|
||||
{
|
||||
axes,
|
||||
type,
|
||||
templates,
|
||||
timeRange,
|
||||
lineColors,
|
||||
autoRefresh,
|
||||
gaugeColors,
|
||||
queryConfigs,
|
||||
editQueryStatus,
|
||||
resizerTopHeight,
|
||||
staticLegend,
|
||||
thresholdsListColors,
|
||||
tableOptions,
|
||||
timeFormat,
|
||||
decimalPlaces,
|
||||
fieldOptions,
|
||||
isInCEO,
|
||||
},
|
||||
{
|
||||
source: {
|
||||
links: {proxy},
|
||||
},
|
||||
}
|
||||
) => {
|
||||
const colors = getCellTypeColors({
|
||||
cellType: type,
|
||||
gaugeColors,
|
||||
thresholdsListColors,
|
||||
lineColors,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="graph">
|
||||
<VisualizationName />
|
||||
<div className="graph-container">
|
||||
<RefreshingGraph
|
||||
colors={colors}
|
||||
axes={axes}
|
||||
type={type}
|
||||
tableOptions={tableOptions}
|
||||
queries={buildQueries(proxy, queryConfigs, timeRange)}
|
||||
templates={templates}
|
||||
autoRefresh={autoRefresh}
|
||||
editQueryStatus={editQueryStatus}
|
||||
resizerTopHeight={resizerTopHeight}
|
||||
staticLegend={staticLegend}
|
||||
timeFormat={timeFormat}
|
||||
decimalPlaces={decimalPlaces}
|
||||
fieldOptions={fieldOptions}
|
||||
isInCEO={isInCEO}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {arrayOf, bool, func, number, shape, string} = PropTypes
|
||||
|
||||
DashVisualization.propTypes = {
|
||||
type: string.isRequired,
|
||||
autoRefresh: number.isRequired,
|
||||
templates: arrayOf(shape()),
|
||||
timeRange: shape({
|
||||
upper: string,
|
||||
lower: string,
|
||||
}).isRequired,
|
||||
queryConfigs: arrayOf(shape({})).isRequired,
|
||||
editQueryStatus: func.isRequired,
|
||||
axes: shape({
|
||||
y: shape({
|
||||
bounds: arrayOf(string),
|
||||
}),
|
||||
}),
|
||||
tableOptions: shape({}),
|
||||
timeFormat: string.isRequired,
|
||||
decimalPlaces: shape({
|
||||
isEnforced: bool,
|
||||
digits: number,
|
||||
}),
|
||||
fieldOptions: arrayOf(
|
||||
shape({
|
||||
internalName: string.isRequired,
|
||||
displayName: string.isRequired,
|
||||
visible: bool.isRequired,
|
||||
})
|
||||
),
|
||||
resizerTopHeight: number,
|
||||
thresholdsListColors: colorsNumberSchema,
|
||||
gaugeColors: colorsNumberSchema,
|
||||
lineColors: colorsStringSchema,
|
||||
staticLegend: bool,
|
||||
isInCEO: bool,
|
||||
}
|
||||
|
||||
DashVisualization.contextTypes = {
|
||||
source: PropTypes.shape({
|
||||
links: PropTypes.shape({
|
||||
proxy: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
}).isRequired,
|
||||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
cellEditorOverlay: {
|
||||
thresholdsListColors,
|
||||
gaugeColors,
|
||||
lineColors,
|
||||
cell: {type, axes, tableOptions, fieldOptions, timeFormat, decimalPlaces},
|
||||
},
|
||||
}) => ({
|
||||
gaugeColors,
|
||||
thresholdsListColors,
|
||||
lineColors,
|
||||
type,
|
||||
axes,
|
||||
tableOptions,
|
||||
fieldOptions,
|
||||
timeFormat,
|
||||
decimalPlaces,
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(DashVisualization)
|
|
@ -0,0 +1,119 @@
|
|||
import React, {SFC} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import _ from 'lodash'
|
||||
|
||||
import RefreshingGraph from 'src/shared/components/RefreshingGraph'
|
||||
import buildQueries from 'src/utils/buildQueriesForGraphs'
|
||||
import VisualizationName from 'src/dashboards/components/VisualizationName'
|
||||
import {SourceContext} from 'src/CheckSources'
|
||||
|
||||
import {getCellTypeColors} from 'src/dashboards/constants/cellEditor'
|
||||
|
||||
import {TimeRange, QueryConfig, Axes, Template, Source} from 'src/types'
|
||||
import {
|
||||
TableOptions,
|
||||
DecimalPlaces,
|
||||
FieldName,
|
||||
CellType,
|
||||
} from 'src/types/dashboard'
|
||||
import {ColorString, ColorNumber} from 'src/types/colors'
|
||||
|
||||
interface Props {
|
||||
type: CellType
|
||||
autoRefresh: number
|
||||
templates: Template[]
|
||||
timeRange: TimeRange
|
||||
queryConfigs: QueryConfig[]
|
||||
editQueryStatus: () => void
|
||||
axes: Axes
|
||||
tableOptions: TableOptions
|
||||
timeFormat: string
|
||||
decimalPlaces: DecimalPlaces
|
||||
fieldOptions: FieldName[]
|
||||
resizerTopHeight: number
|
||||
thresholdsListColors: ColorNumber[]
|
||||
gaugeColors: ColorNumber[]
|
||||
lineColors: ColorString[]
|
||||
staticLegend: boolean
|
||||
isInCEO: boolean
|
||||
}
|
||||
|
||||
const DashVisualization: SFC<Props> = ({
|
||||
axes,
|
||||
type,
|
||||
templates,
|
||||
timeRange,
|
||||
lineColors,
|
||||
autoRefresh,
|
||||
gaugeColors,
|
||||
queryConfigs,
|
||||
editQueryStatus,
|
||||
resizerTopHeight,
|
||||
staticLegend,
|
||||
thresholdsListColors,
|
||||
tableOptions,
|
||||
timeFormat,
|
||||
decimalPlaces,
|
||||
fieldOptions,
|
||||
isInCEO,
|
||||
}) => {
|
||||
const colors: ColorString[] = getCellTypeColors({
|
||||
cellType: type,
|
||||
gaugeColors,
|
||||
thresholdsListColors,
|
||||
lineColors,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className="graph">
|
||||
<VisualizationName />
|
||||
<div className="graph-container">
|
||||
<SourceContext.Consumer>
|
||||
{(source: Source) => (
|
||||
<RefreshingGraph
|
||||
colors={colors}
|
||||
axes={axes}
|
||||
type={type}
|
||||
tableOptions={tableOptions}
|
||||
queries={buildQueries(
|
||||
_.get(source, 'links.proxy'),
|
||||
queryConfigs,
|
||||
timeRange
|
||||
)}
|
||||
templates={templates}
|
||||
autoRefresh={autoRefresh}
|
||||
editQueryStatus={editQueryStatus}
|
||||
resizerTopHeight={resizerTopHeight}
|
||||
staticLegend={staticLegend}
|
||||
timeFormat={timeFormat}
|
||||
decimalPlaces={decimalPlaces}
|
||||
fieldOptions={fieldOptions}
|
||||
isInCEO={isInCEO}
|
||||
/>
|
||||
)}
|
||||
</SourceContext.Consumer>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
cellEditorOverlay: {
|
||||
thresholdsListColors,
|
||||
gaugeColors,
|
||||
lineColors,
|
||||
cell: {type, axes, tableOptions, fieldOptions, timeFormat, decimalPlaces},
|
||||
},
|
||||
}) => ({
|
||||
gaugeColors,
|
||||
thresholdsListColors,
|
||||
lineColors,
|
||||
type,
|
||||
axes,
|
||||
tableOptions,
|
||||
fieldOptions,
|
||||
timeFormat,
|
||||
decimalPlaces,
|
||||
})
|
||||
|
||||
export default connect(mapStateToProps, null)(DashVisualization)
|
|
@ -1,6 +1,7 @@
|
|||
import {DEFAULT_TABLE_OPTIONS} from 'src/dashboards/constants'
|
||||
import {stringifyColorValues} from 'src/shared/constants/colorOperations'
|
||||
import {CellType} from 'src/types/dashboard'
|
||||
import {ColorString, ColorNumber} from 'src/types/colors'
|
||||
|
||||
export const initializeOptions = (cellType: CellType) => {
|
||||
switch (cellType) {
|
||||
|
@ -21,18 +22,20 @@ export const AXES_SCALE_OPTIONS = {
|
|||
export const TOOLTIP_Y_VALUE_FORMAT =
|
||||
'<p><strong>K/M/B</strong> = Thousand / Million / Billion<br/><strong>K/M/G</strong> = Kilo / Mega / Giga </p>'
|
||||
|
||||
interface Color {
|
||||
cellType: CellType
|
||||
thresholdsListColors: ColorNumber[]
|
||||
gaugeColors: ColorNumber[]
|
||||
lineColors: ColorString[]
|
||||
}
|
||||
|
||||
export const getCellTypeColors = ({
|
||||
cellType,
|
||||
gaugeColors,
|
||||
thresholdsListColors,
|
||||
lineColors,
|
||||
}: {
|
||||
cellType: CellType
|
||||
gaugeColors
|
||||
thresholdsListColors
|
||||
lineColors
|
||||
}) => {
|
||||
let colors = []
|
||||
}: Color): ColorString[] => {
|
||||
let colors: ColorString[] = []
|
||||
|
||||
switch (cellType) {
|
||||
case CellType.Gauge: {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import {QueryConfig} from 'src/types'
|
||||
import {QueryConfig, Source} from 'src/types'
|
||||
|
||||
export const nextSource = (
|
||||
prevQuery: QueryConfig,
|
||||
nextQuery: QueryConfig
|
||||
): string => {
|
||||
if (nextQuery.sourceLink) {
|
||||
return nextQuery.sourceLink
|
||||
): Source => {
|
||||
if (nextQuery.source) {
|
||||
return nextQuery.source
|
||||
}
|
||||
|
||||
return prevQuery.sourceLink
|
||||
return prevQuery.source
|
||||
}
|
||||
|
|
|
@ -4,12 +4,12 @@ import Table from './Table'
|
|||
import RefreshingGraph from 'src/shared/components/RefreshingGraph'
|
||||
import {DEFAULT_LINE_COLORS} from 'src/shared/constants/graphColorPalettes'
|
||||
|
||||
import {QueryConfig, Template} from 'src/types'
|
||||
import {Query, Template} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
view: string
|
||||
query?: QueryConfig
|
||||
queries: QueryConfig[]
|
||||
query?: Query
|
||||
queries: Query[]
|
||||
templates: Template[]
|
||||
autoRefresh: number
|
||||
editQueryStatus: () => void
|
||||
|
|
|
@ -9,7 +9,7 @@ import {GRAPH, TABLE} from 'src/shared/constants'
|
|||
import buildQueries from 'src/utils/buildQueriesForGraphs'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
import {Source, QueryConfig, Template, TimeRange} from 'src/types'
|
||||
import {Source, Query, QueryConfig, Template, TimeRange} from 'src/types'
|
||||
|
||||
const META_QUERY_REGEX = /^(show|create|drop)/i
|
||||
|
||||
|
@ -101,12 +101,12 @@ class DataExplorerVisualization extends PureComponent<Props, State> {
|
|||
})
|
||||
}
|
||||
|
||||
private get queries(): QueryConfig[] {
|
||||
private get queries(): Query[] {
|
||||
const {source, queryConfigs, timeRange} = this.props
|
||||
return buildQueries(source.links.proxy, queryConfigs, timeRange)
|
||||
}
|
||||
|
||||
private get query(): QueryConfig {
|
||||
private get query(): Query {
|
||||
const {activeQueryIndex} = this.props
|
||||
const activeQuery = this.queries[activeQueryIndex]
|
||||
const defaultQuery = this.queries[0]
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import {modeIFQL, modeTickscript} from 'src/shared/constants/codeMirrorModes'
|
||||
|
||||
/* eslint-disable */
|
||||
const CodeMirror = require('codemirror')
|
||||
|
||||
|
@ -309,79 +311,9 @@ function indentFunction(states, meta) {
|
|||
}
|
||||
}
|
||||
|
||||
CodeMirror.defineSimpleMode('tickscript', {
|
||||
// The start state contains the rules that are intially used
|
||||
start: [
|
||||
// The regex matches the token, the token property contains the type
|
||||
{
|
||||
regex: /"(?:[^\\]|\\.)*?(?:"|$)/,
|
||||
token: 'string.double'
|
||||
},
|
||||
{
|
||||
regex: /'(?:[^\\]|\\.)*?(?:'|$)/,
|
||||
token: 'string.single'
|
||||
},
|
||||
{
|
||||
regex: /(function)(\s+)([a-z$][\w$]*)/,
|
||||
token: ['keyword', null, 'variable-2'],
|
||||
},
|
||||
// Rules are matched in the order in which they appear, so there is
|
||||
// no ambiguity between this one and the one above
|
||||
{
|
||||
regex: /(?:var|return|if|for|while|else|do|this|stream|batch|influxql|lambda)/,
|
||||
token: 'keyword',
|
||||
},
|
||||
{
|
||||
regex: /true|false|null|undefined|TRUE|FALSE/,
|
||||
token: 'atom'
|
||||
},
|
||||
{
|
||||
regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
|
||||
token: 'number',
|
||||
},
|
||||
{
|
||||
regex: /\/\/.*/,
|
||||
token: 'comment'
|
||||
},
|
||||
{
|
||||
regex: /\/(?:[^\\]|\\.)*?\//,
|
||||
token: 'variable-3'
|
||||
},
|
||||
// A next property will cause the mode to move to a different state
|
||||
{
|
||||
regex: /\/\*/,
|
||||
token: 'comment',
|
||||
next: 'comment'
|
||||
},
|
||||
{
|
||||
regex: /[-+\/*=<>!]+/,
|
||||
token: 'operator'
|
||||
},
|
||||
{
|
||||
regex: /[a-z$][\w$]*/,
|
||||
token: 'variable'
|
||||
},
|
||||
],
|
||||
// The multi-line comment state.
|
||||
comment: [{
|
||||
regex: /.*?\*\//,
|
||||
token: 'comment',
|
||||
next: 'start'
|
||||
},
|
||||
{
|
||||
regex: /.*/,
|
||||
token: 'comment'
|
||||
},
|
||||
],
|
||||
// The meta property contains global information about the mode. It
|
||||
// can contain properties like lineComment, which are supported by
|
||||
// all modes, and also directives like dontIndentStates, which are
|
||||
// specific to simple modes.
|
||||
meta: {
|
||||
dontIndentStates: ['comment'],
|
||||
lineComment: '//',
|
||||
},
|
||||
})
|
||||
// Modes
|
||||
CodeMirror.defineSimpleMode('ifql', modeIFQL)
|
||||
CodeMirror.defineSimpleMode('tickscript', modeTickscript)
|
||||
|
||||
// CodeMirror Hints
|
||||
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
export type Action = ActionUpdateScript
|
||||
|
||||
export enum ActionTypes {
|
||||
UpdateScript = 'UPDATE_SCRIPT',
|
||||
}
|
||||
|
||||
export interface ActionUpdateScript {
|
||||
type: ActionTypes.UpdateScript
|
||||
payload: {
|
||||
script: string
|
||||
}
|
||||
}
|
||||
|
||||
export type UpdateScript = (script: string) => ActionUpdateScript
|
||||
|
||||
export const updateScript = (script: string): ActionUpdateScript => {
|
||||
return {
|
||||
type: ActionTypes.UpdateScript,
|
||||
payload: {script},
|
||||
}
|
||||
}
|
|
@ -1,4 +1,6 @@
|
|||
import AJAX from 'src/utils/ajax'
|
||||
import {Service} from 'src/types'
|
||||
import {updateService} from 'src/shared/apis'
|
||||
|
||||
export const getSuggestions = async (url: string) => {
|
||||
try {
|
||||
|
@ -34,17 +36,24 @@ export const getAST = async (request: ASTRequest) => {
|
|||
}
|
||||
}
|
||||
|
||||
export const getTimeSeries = async (script: string) => {
|
||||
export const getTimeSeries = async (service: Service, script: string) => {
|
||||
const and = encodeURIComponent('&')
|
||||
const mark = encodeURIComponent('?')
|
||||
const garbage = script.replace(/\s/g, '') // server cannot handle whitespace
|
||||
|
||||
try {
|
||||
const data = await AJAX({
|
||||
method: 'POST',
|
||||
url: `http://localhost:8093/query?q=${script}`,
|
||||
url: `${
|
||||
service.links.proxy
|
||||
}?path=/v1/query${mark}orgName=defaulorgname${and}q=${garbage}`,
|
||||
headers: {'Content-Type': 'text/plain'},
|
||||
})
|
||||
|
||||
return data
|
||||
} catch (error) {
|
||||
console.error('Problem fetching data', error)
|
||||
throw error
|
||||
throw error.data.message
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,3 +91,19 @@ export const getTagValues = async () => {
|
|||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
export const updateScript = async (service: Service, script: string) => {
|
||||
const updates = {...service, metadata: {script}}
|
||||
|
||||
try {
|
||||
const response = await updateService(updates)
|
||||
return response
|
||||
} catch (error) {
|
||||
if (error.data) {
|
||||
console.error('Could not update script', error.data)
|
||||
throw error.data
|
||||
}
|
||||
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ class TimeMachine extends PureComponent<Props> {
|
|||
headerButtons: [
|
||||
<div
|
||||
key="analyze"
|
||||
className="btn btn-default btn-sm analyze--button"
|
||||
className="btn btn-default btn-xs analyze--button"
|
||||
onClick={onAnalyze}
|
||||
>
|
||||
Analyze
|
||||
|
|
|
@ -60,12 +60,13 @@ class TimeMachineEditor extends PureComponent<Props> {
|
|||
|
||||
const options = {
|
||||
lineNumbers: true,
|
||||
theme: 'material',
|
||||
theme: 'time-machine',
|
||||
tabIndex: 1,
|
||||
readonly: false,
|
||||
extraKeys: {'Ctrl-Space': 'autocomplete'},
|
||||
completeSingle: false,
|
||||
autoRefresh: true,
|
||||
mode: 'ifql',
|
||||
gutters: ['error-gutter'],
|
||||
}
|
||||
|
||||
|
|
|
@ -58,3 +58,6 @@ export const EXCLUDED_KEYS = [
|
|||
'Meta',
|
||||
' ',
|
||||
]
|
||||
|
||||
export const DEFAULT_SCRIPT =
|
||||
'fil = (r) => r._measurement == "cpu"\ntele = from(db: "telegraf") \n\t\t|> filter(fn: fil)\n |> range(start: -1m)\n |> sum()\n\n'
|
||||
|
|
|
@ -10,11 +10,14 @@ import KeyboardShortcuts from 'src/shared/components/KeyboardShortcuts'
|
|||
|
||||
import {notify as notifyAction} from 'src/shared/actions/notifications'
|
||||
import {analyzeSuccess} from 'src/shared/copy/notifications'
|
||||
import {
|
||||
updateScript as updateScriptAction,
|
||||
UpdateScript,
|
||||
} from 'src/ifql/actions'
|
||||
|
||||
import {bodyNodes} from 'src/ifql/helpers'
|
||||
import {getSuggestions, getAST, getTimeSeries} from 'src/ifql/apis'
|
||||
import {builder, argTypes} from 'src/ifql/constants'
|
||||
import {funcNames} from 'src/ifql/constants'
|
||||
import {funcNames, builder, argTypes} from 'src/ifql/constants'
|
||||
|
||||
import {Source, Service, Notification} from 'src/types'
|
||||
import {
|
||||
|
@ -37,6 +40,11 @@ interface Props {
|
|||
services: Service[]
|
||||
sources: Source[]
|
||||
notify: (message: Notification) => void
|
||||
script: string
|
||||
updateScript: UpdateScript
|
||||
params: {
|
||||
sourceID: string
|
||||
}
|
||||
}
|
||||
|
||||
interface Body extends FlatBody {
|
||||
|
@ -46,7 +54,6 @@ interface Body extends FlatBody {
|
|||
interface State {
|
||||
body: Body[]
|
||||
ast: object
|
||||
script: string
|
||||
data: string
|
||||
suggestions: Suggestion[]
|
||||
status: Status
|
||||
|
@ -63,7 +70,6 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
ast: null,
|
||||
data: 'Hit "Get Data!" or Ctrl + Enter to run your script',
|
||||
suggestions: [],
|
||||
script: `fil = (r) => r._measurement == \"cpu\"\ntele = from(db: \"telegraf\") \n\t\t|> filter(fn: fil)\n |> range(start: -1m)\n |> sum()\n\n`,
|
||||
status: {
|
||||
type: 'none',
|
||||
text: '',
|
||||
|
@ -72,7 +78,7 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
public async componentDidMount() {
|
||||
const {links} = this.props
|
||||
const {links, script} = this.props
|
||||
|
||||
try {
|
||||
const suggestions = await getSuggestions(links.suggestions)
|
||||
|
@ -81,11 +87,12 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
console.error('Could not get function suggestions: ', error)
|
||||
}
|
||||
|
||||
this.getASTResponse(this.state.script)
|
||||
this.getASTResponse(script)
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {suggestions, script, data, body, status} = this.state
|
||||
const {suggestions, data, body, status} = this.state
|
||||
const {script} = this.props
|
||||
|
||||
return (
|
||||
<CheckServices>
|
||||
|
@ -140,7 +147,7 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private handleSubmitScript = () => {
|
||||
this.getASTResponse(this.state.script)
|
||||
this.getASTResponse(this.props.script)
|
||||
}
|
||||
|
||||
private handleGenerateScript = (): void => {
|
||||
|
@ -260,21 +267,21 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private handleAppendFrom = (): void => {
|
||||
const {script} = this.state
|
||||
const {script} = this.props
|
||||
const newScript = `${script.trim()}\n\n${builder.NEW_FROM}\n\n`
|
||||
|
||||
this.getASTResponse(newScript)
|
||||
}
|
||||
|
||||
private handleAppendJoin = (): void => {
|
||||
const {script} = this.state
|
||||
const {script} = this.props
|
||||
const newScript = `${script.trim()}\n\n${builder.NEW_JOIN}\n\n`
|
||||
|
||||
this.getASTResponse(newScript)
|
||||
}
|
||||
|
||||
private handleChangeScript = (script: string): void => {
|
||||
this.setState({script})
|
||||
this.props.updateScript(script)
|
||||
}
|
||||
|
||||
private handleAddNode = (
|
||||
|
@ -376,10 +383,10 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private handleAnalyze = async () => {
|
||||
const {links, notify} = this.props
|
||||
const {links, notify, script} = this.props
|
||||
|
||||
try {
|
||||
const ast = await getAST({url: links.ast, body: this.state.script})
|
||||
const ast = await getAST({url: links.ast, body: script})
|
||||
const body = bodyNodes(ast, this.state.suggestions)
|
||||
const status = {type: 'success', text: ''}
|
||||
notify(analyzeSuccess)
|
||||
|
@ -411,7 +418,8 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
})
|
||||
const body = bodyNodes(ast, suggestions)
|
||||
const status = {type: 'success', text: ''}
|
||||
this.setState({ast, script, body, status})
|
||||
this.setState({ast, body, status})
|
||||
this.props.updateScript(script)
|
||||
} catch (error) {
|
||||
this.setState({status: this.parseError(error)})
|
||||
return console.error('Could not parse AST', error)
|
||||
|
@ -419,14 +427,14 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private getTimeSeries = async () => {
|
||||
const {script} = this.state
|
||||
const {script} = this.props
|
||||
this.setState({data: 'fetching data...'})
|
||||
|
||||
try {
|
||||
const {data} = await getTimeSeries(script)
|
||||
const {data} = await getTimeSeries(this.service, script)
|
||||
this.setState({data})
|
||||
} catch (error) {
|
||||
this.setState({data: 'Error fetching data'})
|
||||
this.setState({data: error})
|
||||
console.error('Could not get timeSeries', error)
|
||||
}
|
||||
|
||||
|
@ -440,12 +448,13 @@ export class IFQLPage extends PureComponent<Props, State> {
|
|||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({links, services, sources}) => {
|
||||
return {links: links.ifql, services, sources}
|
||||
const mapStateToProps = ({links, services, sources, script}) => {
|
||||
return {links: links.ifql, services, sources, script}
|
||||
}
|
||||
|
||||
const mapDispatchToProps = {
|
||||
notify: notifyAction,
|
||||
updateScript: updateScriptAction,
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(IFQLPage)
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
import {Action, ActionTypes} from 'src/ifql/actions'
|
||||
import {editor} from 'src/ifql/constants'
|
||||
|
||||
const scriptReducer = (
|
||||
state: string = editor.DEFAULT_SCRIPT,
|
||||
action: Action
|
||||
): string => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.UpdateScript: {
|
||||
return action.payload.script
|
||||
}
|
||||
}
|
||||
|
||||
return state
|
||||
}
|
||||
|
||||
export default scriptReducer
|
|
@ -26,6 +26,7 @@ import {StatusPage} from 'src/status'
|
|||
import {HostsPage, HostPage} from 'src/hosts'
|
||||
import DataExplorerPage from 'src/data_explorer'
|
||||
import {DashboardsPage, DashboardPage} from 'src/dashboards'
|
||||
import {LogsPage} from 'src/logs'
|
||||
import AlertsApp from 'src/alerts'
|
||||
import {
|
||||
KapacitorPage,
|
||||
|
@ -119,6 +120,9 @@ class Root extends PureComponent<{}, State> {
|
|||
<Route path="/" component={UserIsAuthenticated(CheckSources)} />
|
||||
<Route path="/login" component={UserIsNotAuthenticated(Login)} />
|
||||
<Route path="/purgatory" component={UserIsAuthenticated(Purgatory)} />
|
||||
<Route component={UserIsAuthenticated(App)}>
|
||||
<Route path="/logs" component={LogsPage} />
|
||||
</Route>
|
||||
<Route
|
||||
path="/sources/new"
|
||||
component={UserIsAuthenticated(SourcePage)}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import React, {PureComponent, MouseEvent} from 'react'
|
||||
|
||||
import _ from 'lodash'
|
||||
import {get} from 'src/utils/wrappers'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
import {
|
||||
Tab,
|
||||
|
@ -431,12 +431,12 @@ class AlertTabs extends PureComponent<Props, State> {
|
|||
|
||||
private get isMultipleConfigsSupported(): boolean {
|
||||
const {configSections} = this.state
|
||||
const hasPagerDuty2: Section = get(
|
||||
const hasPagerDuty2 = getDeep<Section>(
|
||||
configSections,
|
||||
AlertTypes.pagerduty2,
|
||||
undefined
|
||||
)
|
||||
const hasOpsGenie2: Section = get(
|
||||
const hasOpsGenie2 = getDeep<Section>(
|
||||
configSections,
|
||||
AlertTypes.opsgenie2,
|
||||
undefined
|
||||
|
@ -454,9 +454,13 @@ class AlertTabs extends PureComponent<Props, State> {
|
|||
|
||||
private getConfigEnabled = (sections: Sections, section: string): boolean => {
|
||||
if (section === AlertTypes.slack || section === AlertTypes.kafka) {
|
||||
const configElements: Section[] = get(sections, `${section}.elements`, [])
|
||||
const configElements = getDeep<Section[]>(
|
||||
sections,
|
||||
`${section}.elements`,
|
||||
[]
|
||||
)
|
||||
const enabledConfigElements = configElements.filter(e => {
|
||||
const enabled: boolean = get(e, 'options.enabled', false)
|
||||
const enabled = getDeep<boolean>(e, 'options.enabled', false)
|
||||
return enabled
|
||||
})
|
||||
return enabledConfigElements.length > 0
|
||||
|
|
|
@ -19,9 +19,10 @@ class TickscriptEditor extends Component {
|
|||
|
||||
const options = {
|
||||
lineNumbers: true,
|
||||
theme: 'material',
|
||||
theme: 'tickscript',
|
||||
tabIndex: 1,
|
||||
readonly: false,
|
||||
mode: 'tickscript',
|
||||
}
|
||||
|
||||
return (
|
||||
|
|
|
@ -8,7 +8,7 @@ import {Notification, NotificationFunc} from 'src/types'
|
|||
import {KafkaProperties} from 'src/types/kapacitor'
|
||||
import {notifyInvalidBatchSizeValue} from 'src/shared/copy/notifications'
|
||||
|
||||
import {get} from 'src/utils/wrappers'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
interface Config {
|
||||
options: KafkaProperties
|
||||
|
@ -62,7 +62,7 @@ class KafkaConfig extends PureComponent<Props, State> {
|
|||
this.state = {
|
||||
currentBrokers: brokers || [],
|
||||
testEnabled: this.props.enabled,
|
||||
enabled: get(this.props, 'config.options.enabled', false),
|
||||
enabled: getDeep<boolean>(this.props, 'config.options.enabled', false),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -244,7 +244,7 @@ class KafkaConfig extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private get isNewConfig(): boolean {
|
||||
return get(this.props, 'config.isNewConfig', false)
|
||||
return getDeep<boolean>(this.props, 'config.isNewConfig', false)
|
||||
}
|
||||
|
||||
private get isDefaultConfig(): boolean {
|
||||
|
|
|
@ -7,7 +7,7 @@ import {ErrorHandling} from 'src/shared/decorators/errors'
|
|||
import {KafkaProperties} from 'src/types/kapacitor'
|
||||
import {Notification, NotificationFunc} from 'src/types'
|
||||
|
||||
import {get} from 'src/utils/wrappers'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
const DEFAULT_CONFIG = {
|
||||
options: {
|
||||
|
@ -63,8 +63,8 @@ class KafkaConfigs extends Component<Props, State> {
|
|||
return (
|
||||
<div>
|
||||
{this.configs.map(c => {
|
||||
const enabled = get(c, 'options.enabled', false)
|
||||
const id = get(c, 'options.id', '')
|
||||
const enabled = getDeep<boolean>(c, 'options.enabled', false)
|
||||
const id = getDeep<string>(c, 'options.id', '')
|
||||
return (
|
||||
<KafkaConfig
|
||||
config={c}
|
||||
|
@ -93,7 +93,7 @@ class KafkaConfigs extends Component<Props, State> {
|
|||
}
|
||||
private get configs(): Config[] {
|
||||
return _.sortBy(this.state.configs, c => {
|
||||
const id = get<string>(c, 'options.id', '')
|
||||
const id = getDeep<string>(c, 'options.id', '')
|
||||
const {isNewConfig} = c
|
||||
if (id === 'default') {
|
||||
return ''
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import React, {PureComponent, MouseEvent} from 'react'
|
||||
import _ from 'lodash'
|
||||
import {get} from 'src/utils/wrappers'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import SlackConfig from 'src/kapacitor/components/config/SlackConfig'
|
||||
|
@ -98,7 +98,7 @@ class SlackConfigs extends PureComponent<Props, State> {
|
|||
}
|
||||
|
||||
private isNewConfig = (config: Config): boolean => {
|
||||
return get(config, 'isNewConfig', false)
|
||||
return getDeep(config, 'isNewConfig', false)
|
||||
}
|
||||
|
||||
private isDefaultConfig = (config: Config): boolean => {
|
||||
|
|
|
@ -61,7 +61,7 @@ const KafkaHandler: SFC<Props> = ({
|
|||
<HandlerInput
|
||||
selectedHandler={handler}
|
||||
handleModifyHandler={handleModifyHandler}
|
||||
fieldName="topic"
|
||||
fieldName="kafka-topic"
|
||||
fieldDisplay="Topic"
|
||||
placeholder=""
|
||||
/>
|
||||
|
|
|
@ -242,7 +242,7 @@ export const HANDLERS_TO_RULE_THEM_ALL: FieldsFromAllAlerts = {
|
|||
'service',
|
||||
],
|
||||
hipChat: ['room'],
|
||||
kafka: ['id', 'cluster', 'topic', 'template'],
|
||||
kafka: ['id', 'cluster', 'kafka-topic', 'template'],
|
||||
opsGenie: ['teams', 'recipients'],
|
||||
opsGenie2: ['teams', 'recipients'],
|
||||
pagerDuty: [],
|
||||
|
|
|
@ -56,6 +56,7 @@ export const saveToLocalStorage = ({
|
|||
timeRange,
|
||||
dataExplorer,
|
||||
dashTimeV1: {ranges},
|
||||
script,
|
||||
}: LocalStorage): void => {
|
||||
try {
|
||||
const appPersisted = {app: {persisted}}
|
||||
|
@ -70,6 +71,7 @@ export const saveToLocalStorage = ({
|
|||
dashTimeV1,
|
||||
dataExplorer,
|
||||
dataExplorerQueryConfigs,
|
||||
script,
|
||||
})
|
||||
)
|
||||
} catch (err) {
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
import {Source, Namespace, TimeRange} from 'src/types'
|
||||
import {getSource} from 'src/shared/apis'
|
||||
import {getDatabasesWithRetentionPolicies} from 'src/shared/apis/databases'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
export enum ActionTypes {
|
||||
SetSource = 'LOGS_SET_SOURCE',
|
||||
SetNamespaces = 'LOGS_SET_NAMESPACES',
|
||||
SetTimeRange = 'LOGS_SET_TIMERANGE',
|
||||
SetNamespace = 'LOGS_SET_NAMESPACE',
|
||||
}
|
||||
|
||||
interface SetSourceAction {
|
||||
type: ActionTypes.SetSource
|
||||
payload: {
|
||||
source: Source
|
||||
}
|
||||
}
|
||||
|
||||
interface SetNamespacesAction {
|
||||
type: ActionTypes.SetNamespaces
|
||||
payload: {
|
||||
namespaces: Namespace[]
|
||||
}
|
||||
}
|
||||
|
||||
interface SetNamespaceAction {
|
||||
type: ActionTypes.SetNamespace
|
||||
payload: {
|
||||
namespace: Namespace
|
||||
}
|
||||
}
|
||||
|
||||
interface SetTimeRangeAction {
|
||||
type: ActionTypes.SetTimeRange
|
||||
payload: {
|
||||
timeRange: TimeRange
|
||||
}
|
||||
}
|
||||
|
||||
export type Action =
|
||||
| SetSourceAction
|
||||
| SetNamespacesAction
|
||||
| SetTimeRangeAction
|
||||
| SetNamespaceAction
|
||||
|
||||
export const setSource = (source: Source): SetSourceAction => ({
|
||||
type: ActionTypes.SetSource,
|
||||
payload: {
|
||||
source,
|
||||
},
|
||||
})
|
||||
|
||||
export const setNamespace = (namespace: Namespace): SetNamespaceAction => ({
|
||||
type: ActionTypes.SetNamespace,
|
||||
payload: {
|
||||
namespace,
|
||||
},
|
||||
})
|
||||
|
||||
export const setNamespaces = (
|
||||
namespaces: Namespace[]
|
||||
): SetNamespacesAction => ({
|
||||
type: ActionTypes.SetNamespaces,
|
||||
payload: {
|
||||
namespaces,
|
||||
},
|
||||
})
|
||||
|
||||
export const setTimeRange = (timeRange: TimeRange): SetTimeRangeAction => ({
|
||||
type: ActionTypes.SetTimeRange,
|
||||
payload: {
|
||||
timeRange,
|
||||
},
|
||||
})
|
||||
|
||||
export const getSourceAsync = (sourceID: string) => async dispatch => {
|
||||
const response = await getSource(sourceID)
|
||||
const source = response.data
|
||||
|
||||
const proxyLink = getDeep<string | null>(source, 'links.proxy', null)
|
||||
|
||||
if (proxyLink) {
|
||||
const namespaces = await getDatabasesWithRetentionPolicies(proxyLink)
|
||||
|
||||
if (namespaces && namespaces.length > 0) {
|
||||
dispatch(setNamespaces(namespaces))
|
||||
dispatch(setNamespace(namespaces[0]))
|
||||
}
|
||||
|
||||
dispatch(setSource(source))
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
import _ from 'lodash'
|
||||
import React, {PureComponent} from 'react'
|
||||
import {Source, Namespace} from 'src/types'
|
||||
import Dropdown from 'src/shared/components/Dropdown'
|
||||
import TimeRangeDropdown from 'src/logs/components/TimeRangeDropdown'
|
||||
|
||||
import {TimeRange} from 'src/types'
|
||||
|
||||
interface SourceItem {
|
||||
id: string
|
||||
text: string
|
||||
}
|
||||
|
||||
interface Props {
|
||||
currentNamespace: Namespace
|
||||
availableSources: Source[]
|
||||
currentSource: Source | null
|
||||
currentNamespaces: Namespace[]
|
||||
timeRange: TimeRange
|
||||
onChooseSource: (sourceID: string) => void
|
||||
onChooseNamespace: (namespace: Namespace) => void
|
||||
onChooseTimerange: (timeRange: TimeRange) => void
|
||||
}
|
||||
|
||||
class LogViewerHeader extends PureComponent<Props> {
|
||||
public render(): JSX.Element {
|
||||
const {timeRange} = this.props
|
||||
return (
|
||||
<>
|
||||
<Dropdown
|
||||
className="dropdown-300"
|
||||
items={this.sourceDropDownItems}
|
||||
selected={this.selectedSource}
|
||||
onChoose={this.handleChooseSource}
|
||||
/>
|
||||
<Dropdown
|
||||
className="dropdown-300"
|
||||
items={this.namespaceDropDownItems}
|
||||
selected={this.selectedNamespace}
|
||||
onChoose={this.handleChooseNamespace}
|
||||
/>
|
||||
<TimeRangeDropdown
|
||||
onChooseTimeRange={this.handleChooseTimeRange}
|
||||
selected={timeRange}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
private handleChooseTimeRange = (timerange: TimeRange) => {
|
||||
this.props.onChooseTimerange(timerange)
|
||||
}
|
||||
|
||||
private handleChooseSource = (item: SourceItem) => {
|
||||
this.props.onChooseSource(item.id)
|
||||
}
|
||||
|
||||
private handleChooseNamespace = (namespace: Namespace) => {
|
||||
this.props.onChooseNamespace(namespace)
|
||||
}
|
||||
|
||||
private get selectedSource(): string {
|
||||
if (_.isEmpty(this.sourceDropDownItems)) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return this.sourceDropDownItems[0].text
|
||||
}
|
||||
|
||||
private get selectedNamespace(): string {
|
||||
const {currentNamespace} = this.props
|
||||
|
||||
if (!currentNamespace) {
|
||||
return ''
|
||||
}
|
||||
|
||||
return `${currentNamespace.database}.${currentNamespace.retentionPolicy}`
|
||||
}
|
||||
|
||||
private get namespaceDropDownItems() {
|
||||
const {currentNamespaces} = this.props
|
||||
|
||||
return currentNamespaces.map(namespace => {
|
||||
return {
|
||||
text: `${namespace.database}.${namespace.retentionPolicy}`,
|
||||
...namespace,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private get sourceDropDownItems(): SourceItem[] {
|
||||
const {availableSources} = this.props
|
||||
|
||||
return availableSources.map(source => {
|
||||
return {
|
||||
text: `${source.name} @ ${source.url}`,
|
||||
id: source.id,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default LogViewerHeader
|
|
@ -0,0 +1,174 @@
|
|||
import React, {Component} from 'react'
|
||||
import classnames from 'classnames'
|
||||
import moment from 'moment'
|
||||
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
import timeRanges from 'src/logs/data/timeRanges'
|
||||
import {DROPDOWN_MENU_MAX_HEIGHT} from 'src/shared/constants/index'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
import {ClickOutside} from 'src/shared/components/ClickOutside'
|
||||
import CustomTimeRange from 'src/shared/components/CustomTimeRange'
|
||||
|
||||
import {TimeRange} from 'src/types'
|
||||
|
||||
const dateFormat = 'YYYY-MM-DD HH:mm'
|
||||
const emptyTime = {lower: '', upper: ''}
|
||||
const format = t => moment(t.replace(/\'/g, '')).format(dateFormat)
|
||||
|
||||
interface Props {
|
||||
selected: {
|
||||
lower: string
|
||||
upper?: string
|
||||
}
|
||||
|
||||
onChooseTimeRange: (timeRange: TimeRange) => void
|
||||
preventCustomTimeRange?: boolean
|
||||
page?: string
|
||||
}
|
||||
|
||||
interface State {
|
||||
autobind: boolean
|
||||
isOpen: boolean
|
||||
isCustomTimeRangeOpen: boolean
|
||||
customTimeRange: TimeRange
|
||||
}
|
||||
|
||||
@ErrorHandling
|
||||
class TimeRangeDropdown extends Component<Props, State> {
|
||||
public static defaultProps = {
|
||||
page: 'default',
|
||||
}
|
||||
|
||||
constructor(props) {
|
||||
super(props)
|
||||
const {lower, upper} = props.selected
|
||||
|
||||
const isTimeValid = moment(upper).isValid() && moment(lower).isValid()
|
||||
const customTimeRange = isTimeValid ? {lower, upper} : emptyTime
|
||||
|
||||
this.state = {
|
||||
autobind: false,
|
||||
isOpen: false,
|
||||
isCustomTimeRangeOpen: false,
|
||||
customTimeRange,
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
const {selected, preventCustomTimeRange, page} = this.props
|
||||
const {customTimeRange, isCustomTimeRangeOpen, isOpen} = this.state
|
||||
|
||||
return (
|
||||
<ClickOutside onClickOutside={this.handleClickOutside}>
|
||||
<div className="time-range-dropdown">
|
||||
<div
|
||||
className={classnames('dropdown dropdown-290', {
|
||||
open: isOpen,
|
||||
})}
|
||||
>
|
||||
<div
|
||||
className="btn btn-sm btn-default dropdown-toggle"
|
||||
onClick={this.toggleMenu}
|
||||
>
|
||||
<span className="icon clock" />
|
||||
<span className="dropdown-selected">
|
||||
{this.findTimeRangeInputValue(selected)}
|
||||
</span>
|
||||
<span className="caret" />
|
||||
</div>
|
||||
<ul className="dropdown-menu">
|
||||
<FancyScrollbar
|
||||
autoHide={false}
|
||||
autoHeight={true}
|
||||
maxHeight={DROPDOWN_MENU_MAX_HEIGHT}
|
||||
>
|
||||
{preventCustomTimeRange ? null : (
|
||||
<div>
|
||||
<li className="dropdown-header">Absolute Time</li>
|
||||
<li
|
||||
className={
|
||||
isCustomTimeRangeOpen
|
||||
? 'active dropdown-item custom-timerange'
|
||||
: 'dropdown-item custom-timerange'
|
||||
}
|
||||
>
|
||||
<a href="#" onClick={this.showCustomTimeRange}>
|
||||
Date Picker
|
||||
</a>
|
||||
</li>
|
||||
</div>
|
||||
)}
|
||||
<li className="dropdown-header">
|
||||
{preventCustomTimeRange ? '' : 'Relative '}Time
|
||||
</li>
|
||||
{timeRanges.map(item => {
|
||||
return (
|
||||
<li className="dropdown-item" key={item.menuOption}>
|
||||
<a href="#" onClick={this.handleSelection(item)}>
|
||||
{item.menuOption}
|
||||
</a>
|
||||
</li>
|
||||
)
|
||||
})}
|
||||
</FancyScrollbar>
|
||||
</ul>
|
||||
</div>
|
||||
{isCustomTimeRangeOpen ? (
|
||||
<ClickOutside onClickOutside={this.handleCloseCustomTimeRange}>
|
||||
<div className="custom-time--overlay">
|
||||
<CustomTimeRange
|
||||
onApplyTimeRange={this.handleApplyCustomTimeRange}
|
||||
timeRange={customTimeRange}
|
||||
onClose={this.handleCloseCustomTimeRange}
|
||||
isVisible={isCustomTimeRangeOpen}
|
||||
timeInterval={60}
|
||||
page={page}
|
||||
/>
|
||||
</div>
|
||||
</ClickOutside>
|
||||
) : null}
|
||||
</div>
|
||||
</ClickOutside>
|
||||
)
|
||||
}
|
||||
|
||||
private findTimeRangeInputValue = ({upper, lower}: TimeRange) => {
|
||||
if (upper && lower) {
|
||||
if (upper === 'now()') {
|
||||
return `${format(lower)} - Now`
|
||||
}
|
||||
|
||||
return `${format(lower)} - ${format(upper)}`
|
||||
}
|
||||
|
||||
const selected = timeRanges.find(range => range.lower === lower)
|
||||
return selected ? selected.inputValue : 'Custom'
|
||||
}
|
||||
|
||||
private handleClickOutside = () => {
|
||||
this.setState({isOpen: false})
|
||||
}
|
||||
|
||||
private handleSelection = timeRange => () => {
|
||||
this.props.onChooseTimeRange(timeRange)
|
||||
this.setState({customTimeRange: emptyTime, isOpen: false})
|
||||
}
|
||||
|
||||
private toggleMenu = () => {
|
||||
this.setState({isOpen: !this.state.isOpen})
|
||||
}
|
||||
|
||||
private showCustomTimeRange = () => {
|
||||
this.setState({isCustomTimeRangeOpen: true})
|
||||
}
|
||||
|
||||
private handleApplyCustomTimeRange = customTimeRange => {
|
||||
this.props.onChooseTimeRange({...customTimeRange})
|
||||
this.setState({customTimeRange, isOpen: false})
|
||||
}
|
||||
|
||||
private handleCloseCustomTimeRange = () => {
|
||||
this.setState({isCustomTimeRangeOpen: false})
|
||||
}
|
||||
}
|
||||
export default TimeRangeDropdown
|
|
@ -0,0 +1,101 @@
|
|||
import React, {PureComponent} from 'react'
|
||||
import {connect} from 'react-redux'
|
||||
import {getSourceAsync, setTimeRange, setNamespace} from 'src/logs/actions'
|
||||
import {getSourcesAsync} from 'src/shared/actions/sources'
|
||||
import {Source, Namespace, TimeRange} from 'src/types'
|
||||
import LogViewerHeader from 'src/logs/components/LogViewerHeader'
|
||||
|
||||
interface Props {
|
||||
sources: Source[]
|
||||
currentSource: Source | null
|
||||
currentNamespaces: Namespace[]
|
||||
currentNamespace: Namespace
|
||||
getSource: (sourceID: string) => void
|
||||
getSources: () => void
|
||||
setTimeRange: (timeRange: TimeRange) => void
|
||||
setNamespace: (namespace: Namespace) => void
|
||||
timeRange: TimeRange
|
||||
}
|
||||
|
||||
class LogsPage extends PureComponent<Props> {
|
||||
public componentDidUpdate() {
|
||||
if (!this.props.currentSource) {
|
||||
this.props.getSource(this.props.sources[0].id)
|
||||
}
|
||||
}
|
||||
|
||||
public componentDidMount() {
|
||||
this.props.getSources()
|
||||
}
|
||||
|
||||
public render() {
|
||||
return (
|
||||
<div className="page hosts-list-page">
|
||||
<div className="page-header full-width">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">Log Viewer</h1>
|
||||
</div>
|
||||
<div className="page-header__right">{this.header}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private get header(): JSX.Element {
|
||||
const {
|
||||
sources,
|
||||
currentSource,
|
||||
currentNamespaces,
|
||||
timeRange,
|
||||
currentNamespace,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<LogViewerHeader
|
||||
availableSources={sources}
|
||||
timeRange={timeRange}
|
||||
onChooseSource={this.handleChooseSource}
|
||||
onChooseNamespace={this.handleChooseNamespace}
|
||||
onChooseTimerange={this.handleChooseTimerange}
|
||||
currentSource={currentSource}
|
||||
currentNamespaces={currentNamespaces}
|
||||
currentNamespace={currentNamespace}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
private handleChooseTimerange = (timeRange: TimeRange) => {
|
||||
this.props.setTimeRange(timeRange)
|
||||
}
|
||||
|
||||
private handleChooseSource = (sourceID: string) => {
|
||||
this.props.getSource(sourceID)
|
||||
}
|
||||
|
||||
private handleChooseNamespace = (namespace: Namespace) => {
|
||||
// Do flip
|
||||
this.props.setNamespace(namespace)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
sources,
|
||||
logs: {currentSource, currentNamespaces, timeRange, currentNamespace},
|
||||
}) => ({
|
||||
sources,
|
||||
currentSource,
|
||||
currentNamespaces,
|
||||
timeRange,
|
||||
currentNamespace,
|
||||
})
|
||||
|
||||
const mapDispatchToProps = {
|
||||
getSource: getSourceAsync,
|
||||
getSources: getSourcesAsync,
|
||||
setTimeRange,
|
||||
setNamespace,
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(LogsPage)
|
|
@ -0,0 +1,74 @@
|
|||
export default [
|
||||
{
|
||||
defaultGroupBy: '10s',
|
||||
seconds: 60,
|
||||
inputValue: 'Past 1m',
|
||||
lower: 'now() - 1m',
|
||||
upper: null,
|
||||
menuOption: 'Past 1m',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '10s',
|
||||
seconds: 300,
|
||||
inputValue: 'Past 5m',
|
||||
lower: 'now() - 5m',
|
||||
upper: null,
|
||||
menuOption: 'Past 5m',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '1m',
|
||||
seconds: 900,
|
||||
inputValue: 'Past 15m',
|
||||
lower: 'now() - 15m',
|
||||
upper: null,
|
||||
menuOption: 'Past 15m',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '1m',
|
||||
seconds: 1800,
|
||||
inputValue: 'Past 30m',
|
||||
lower: 'now() - 30m',
|
||||
upper: null,
|
||||
menuOption: 'Past 30m',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '1m',
|
||||
seconds: 3600,
|
||||
inputValue: 'Past 1h',
|
||||
lower: 'now() - 1h',
|
||||
upper: null,
|
||||
menuOption: 'Past 1h',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '1m',
|
||||
seconds: 5200,
|
||||
inputValue: 'Past 2h',
|
||||
lower: 'now() - 2h',
|
||||
upper: null,
|
||||
menuOption: 'Past 2h',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '1m',
|
||||
seconds: 21600,
|
||||
inputValue: 'Past 6h',
|
||||
lower: 'now() - 6h',
|
||||
upper: null,
|
||||
menuOption: 'Past 6h',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '5m',
|
||||
seconds: 43200,
|
||||
inputValue: 'Past 12h',
|
||||
lower: 'now() - 12h',
|
||||
upper: null,
|
||||
menuOption: 'Past 12h',
|
||||
},
|
||||
{
|
||||
defaultGroupBy: '10m',
|
||||
seconds: 86400,
|
||||
inputValue: 'Past 24h',
|
||||
lower: 'now() - 24h',
|
||||
upper: null,
|
||||
menuOption: 'Past 24h',
|
||||
},
|
||||
]
|
|
@ -0,0 +1,3 @@
|
|||
import LogsPage from 'src/logs/containers/LogsPage'
|
||||
|
||||
export {LogsPage}
|
|
@ -0,0 +1,31 @@
|
|||
import {Source, Namespace, TimeRange} from 'src/types'
|
||||
import {ActionTypes, Action} from 'src/logs/actions'
|
||||
|
||||
interface LogsState {
|
||||
currentSource: Source | null
|
||||
currentNamespaces: Namespace[]
|
||||
currentNamespace: Namespace | null
|
||||
timeRange: TimeRange
|
||||
}
|
||||
|
||||
const defaultState = {
|
||||
currentSource: null,
|
||||
currentNamespaces: [],
|
||||
timeRange: {lower: 'now() - 1m', upper: null},
|
||||
currentNamespace: null,
|
||||
}
|
||||
|
||||
export default (state: LogsState = defaultState, action: Action) => {
|
||||
switch (action.type) {
|
||||
case ActionTypes.SetSource:
|
||||
return {...state, currentSource: action.payload.source}
|
||||
case ActionTypes.SetNamespaces:
|
||||
return {...state, currentNamespaces: action.payload.namespaces}
|
||||
case ActionTypes.SetTimeRange:
|
||||
return {...state, timeRange: action.payload.timeRange}
|
||||
case ActionTypes.SetNamespace:
|
||||
return {...state, currentNamespace: action.payload.namespace}
|
||||
default:
|
||||
return state
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
import _ from 'lodash'
|
||||
|
||||
import {showDatabases, showRetentionPolicies} from 'src/shared/apis/metaQuery'
|
||||
import showDatabasesParser from 'src/shared/parsing/showDatabases'
|
||||
import showRetentionPoliciesParser from 'src/shared/parsing/showRetentionPolicies'
|
||||
|
||||
import {Namespace} from 'src/types/query'
|
||||
|
||||
export const getDatabasesWithRetentionPolicies = async (
|
||||
proxy: string
|
||||
): Promise<Namespace[]> => {
|
||||
try {
|
||||
const {data} = await showDatabases(proxy)
|
||||
const {databases} = showDatabasesParser(data)
|
||||
const rps = await showRetentionPolicies(proxy, databases)
|
||||
const namespaces = rps.data.results.reduce((acc, result, index) => {
|
||||
const {retentionPolicies} = showRetentionPoliciesParser(result)
|
||||
|
||||
const dbrp = retentionPolicies.map(rp => ({
|
||||
database: databases[index],
|
||||
retentionPolicy: rp.name,
|
||||
}))
|
||||
|
||||
return [...acc, ...dbrp]
|
||||
}, [])
|
||||
|
||||
const sorted = _.sortBy(namespaces, ({database}: Namespace) =>
|
||||
database.toLowerCase()
|
||||
)
|
||||
|
||||
return sorted
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
}
|
||||
}
|
|
@ -53,7 +53,6 @@ export const fetchTimeSeries = async (
|
|||
// it may be used, but this slight modification is intended to allow for the use of
|
||||
// `database` while moving over to `db` for consistency over time
|
||||
const db = _.get(query, 'db', database)
|
||||
|
||||
const templatesWithIntervalVals = templates.map(temp => {
|
||||
if (temp.tempVar === ':interval:') {
|
||||
if (resolution) {
|
||||
|
|
|
@ -17,7 +17,7 @@ class CustomTimeRange extends Component {
|
|||
}
|
||||
|
||||
componentDidMount() {
|
||||
const {timeRange} = this.props
|
||||
const {timeRange, timeInterval} = this.props
|
||||
|
||||
const lower = rome(this.lower, {
|
||||
dateValidator: rome.val.beforeEq(this.upper),
|
||||
|
@ -26,6 +26,7 @@ class CustomTimeRange extends Component {
|
|||
autoClose: false,
|
||||
autoHideOnBlur: false,
|
||||
autoHideOnClick: false,
|
||||
timeInterval,
|
||||
})
|
||||
|
||||
const upper = rome(this.upper, {
|
||||
|
@ -35,6 +36,7 @@ class CustomTimeRange extends Component {
|
|||
initialValue: this.getInitialDate(timeRange.upper),
|
||||
autoHideOnBlur: false,
|
||||
autoHideOnClick: false,
|
||||
timeInterval,
|
||||
})
|
||||
|
||||
this.lowerCal = lower
|
||||
|
@ -239,7 +241,11 @@ class CustomTimeRange extends Component {
|
|||
}
|
||||
}
|
||||
|
||||
const {func, shape, string} = PropTypes
|
||||
CustomTimeRange.defaultProps = {
|
||||
timeInterval: 1800,
|
||||
}
|
||||
|
||||
const {func, shape, string, number} = PropTypes
|
||||
|
||||
CustomTimeRange.propTypes = {
|
||||
onApplyTimeRange: func.isRequired,
|
||||
|
@ -247,6 +253,7 @@ CustomTimeRange.propTypes = {
|
|||
lower: string.isRequired,
|
||||
upper: string,
|
||||
}).isRequired,
|
||||
timeInterval: number,
|
||||
onClose: func,
|
||||
page: string,
|
||||
}
|
||||
|
|
|
@ -6,14 +6,12 @@ import _ from 'lodash'
|
|||
import {QueryConfig, Source} from 'src/types'
|
||||
import {Namespace} from 'src/types/query'
|
||||
|
||||
import {showDatabases, showRetentionPolicies} from 'src/shared/apis/metaQuery'
|
||||
import showDatabasesParser from 'src/shared/parsing/showDatabases'
|
||||
import showRetentionPoliciesParser from 'src/shared/parsing/showRetentionPolicies'
|
||||
|
||||
import DatabaseListItem from 'src/shared/components/DatabaseListItem'
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
import {getDatabasesWithRetentionPolicies} from 'src/shared/apis/databases'
|
||||
|
||||
interface DatabaseListProps {
|
||||
query: QueryConfig
|
||||
querySource?: Source
|
||||
|
@ -80,24 +78,7 @@ class DatabaseList extends Component<DatabaseListProps, DatabaseListState> {
|
|||
const proxy = _.get(querySource, ['links', 'proxy'], source.links.proxy)
|
||||
|
||||
try {
|
||||
const {data} = await showDatabases(proxy)
|
||||
const {databases} = showDatabasesParser(data)
|
||||
const rps = await showRetentionPolicies(proxy, databases)
|
||||
const namespaces = rps.data.results.reduce((acc, result, index) => {
|
||||
const {retentionPolicies} = showRetentionPoliciesParser(result)
|
||||
|
||||
const dbrp = retentionPolicies.map(rp => ({
|
||||
database: databases[index],
|
||||
retentionPolicy: rp.name,
|
||||
}))
|
||||
|
||||
return [...acc, ...dbrp]
|
||||
}, [])
|
||||
|
||||
const sorted = _.sortBy(namespaces, ({database}: Namespace) =>
|
||||
database.toLowerCase()
|
||||
)
|
||||
|
||||
const sorted = await getDatabasesWithRetentionPolicies(proxy)
|
||||
this.setState({namespaces: sorted})
|
||||
} catch (err) {
|
||||
console.error(err)
|
||||
|
|
|
@ -59,7 +59,7 @@ class Division extends PureComponent<Props> {
|
|||
fontSize: '16px',
|
||||
fontWeight: '500',
|
||||
})
|
||||
const NAME_OFFSET = 66
|
||||
const NAME_OFFSET = 96
|
||||
|
||||
this.collapseThreshold = width + NAME_OFFSET
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ class DivisionMenu extends PureComponent<Props, State> {
|
|||
private get buttonClass(): string {
|
||||
const {expanded} = this.state
|
||||
|
||||
return classnames('btn btn-sm btn-square btn-default', {
|
||||
return classnames('btn btn-xs btn-square btn-default', {
|
||||
active: expanded,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
export const modeIFQL = {
|
||||
// The start state contains the rules that are intially used
|
||||
start: [
|
||||
// IFQL Syntax
|
||||
{
|
||||
regex: /[|][>]/,
|
||||
token: 'pipe-forward',
|
||||
},
|
||||
{
|
||||
regex: /\w+(?=[(])/,
|
||||
token: 'function',
|
||||
},
|
||||
{
|
||||
regex: /[\w\d]+(?=\s[=]\s)/,
|
||||
token: 'variable',
|
||||
},
|
||||
{
|
||||
regex: /[=][>]/,
|
||||
token: 'arrow-function',
|
||||
},
|
||||
{
|
||||
regex: /\w+(?=[)]\s[=][>])(?![(])/,
|
||||
token: 'function-arg',
|
||||
},
|
||||
{
|
||||
regex: /\w+(?=[[]["]|[.])/,
|
||||
token: 'function-arg-ref',
|
||||
},
|
||||
{
|
||||
regex: /AND|OR|[=][=]|[!][=]|[<][=]|[>][=]/,
|
||||
token: 'operator',
|
||||
},
|
||||
{
|
||||
regex: /\w+[:]/,
|
||||
token: 'argument',
|
||||
},
|
||||
// The regex matches the token, the token property contains the type
|
||||
{
|
||||
regex: /"(?:[^\\]|\\.)*?(?:"|$)/,
|
||||
token: 'string-double',
|
||||
},
|
||||
{
|
||||
regex: /'(?:[^\\]|\\.)*?(?:'|$)/,
|
||||
token: 'string-single',
|
||||
},
|
||||
{
|
||||
regex: /(function)(\s+)([a-z$][\w$]*)/,
|
||||
token: ['keyword', null, 'variable-2'],
|
||||
},
|
||||
{
|
||||
regex: /true|false|TRUE|FALSE/,
|
||||
token: 'boolean',
|
||||
},
|
||||
{
|
||||
regex: /null|undefined/,
|
||||
token: 'null',
|
||||
},
|
||||
{
|
||||
regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
|
||||
token: 'number',
|
||||
},
|
||||
{
|
||||
regex: /\/\/.*/,
|
||||
token: 'comment',
|
||||
},
|
||||
// A next property will cause the mode to move to a different state
|
||||
{
|
||||
regex: /\/\*/,
|
||||
token: 'comment',
|
||||
next: 'comment',
|
||||
},
|
||||
{
|
||||
regex: /[-+\/*=<>!]+/,
|
||||
token: 'operator',
|
||||
},
|
||||
],
|
||||
// The multi-line comment state.
|
||||
comment: [
|
||||
{
|
||||
regex: /.*?\*\//,
|
||||
token: 'comment',
|
||||
next: 'start',
|
||||
},
|
||||
{
|
||||
regex: /.*/,
|
||||
token: 'comment',
|
||||
},
|
||||
],
|
||||
// The meta property contains global information about the mode. It
|
||||
// can contain properties like lineComment, which are supported by
|
||||
// all modes, and also directives like dontIndentStates, which are
|
||||
// specific to simple modes.
|
||||
meta: {
|
||||
dontIndentStates: ['comment'],
|
||||
lineComment: '//',
|
||||
},
|
||||
}
|
||||
|
||||
export const modeTickscript = {
|
||||
// The start state contains the rules that are intially used
|
||||
start: [
|
||||
// The regex matches the token, the token property contains the type
|
||||
{
|
||||
regex: /"(?:[^\\]|\\.)*?(?:"|$)/,
|
||||
token: 'string.double',
|
||||
},
|
||||
{
|
||||
regex: /'(?:[^\\]|\\.)*?(?:'|$)/,
|
||||
token: 'string.single',
|
||||
},
|
||||
{
|
||||
regex: /(function)(\s+)([a-z$][\w$]*)/,
|
||||
token: ['keyword', null, 'variable-2'],
|
||||
},
|
||||
// Rules are matched in the order in which they appear, so there is
|
||||
// no ambiguity between this one and the one above
|
||||
{
|
||||
regex: /(?:var|return|if|for|while|else|do|this|stream|batch|influxql|lambda)/,
|
||||
token: 'keyword',
|
||||
},
|
||||
{
|
||||
regex: /true|false|null|undefined|TRUE|FALSE/,
|
||||
token: 'atom',
|
||||
},
|
||||
{
|
||||
regex: /0x[a-f\d]+|[-+]?(?:\.\d+|\d+\.?\d*)(?:e[-+]?\d+)?/i,
|
||||
token: 'number',
|
||||
},
|
||||
{
|
||||
regex: /\/\/.*/,
|
||||
token: 'comment',
|
||||
},
|
||||
{
|
||||
regex: /\/(?:[^\\]|\\.)*?\//,
|
||||
token: 'variable-3',
|
||||
},
|
||||
// A next property will cause the mode to move to a different state
|
||||
{
|
||||
regex: /\/\*/,
|
||||
token: 'comment',
|
||||
next: 'comment',
|
||||
},
|
||||
{
|
||||
regex: /[-+\/*=<>!]+/,
|
||||
token: 'operator',
|
||||
},
|
||||
{
|
||||
regex: /[a-z$][\w$]*/,
|
||||
token: 'variable',
|
||||
},
|
||||
],
|
||||
// The multi-line comment state.
|
||||
comment: [
|
||||
{
|
||||
regex: /.*?\*\//,
|
||||
token: 'comment',
|
||||
next: 'start',
|
||||
},
|
||||
{
|
||||
regex: /.*/,
|
||||
token: 'comment',
|
||||
},
|
||||
],
|
||||
// The meta property contains global information about the mode. It
|
||||
// can contain properties like lineComment, which are supported by
|
||||
// all modes, and also directives like dontIndentStates, which are
|
||||
// specific to simple modes.
|
||||
meta: {
|
||||
dontIndentStates: ['comment'],
|
||||
lineComment: '//',
|
||||
},
|
||||
}
|
|
@ -479,6 +479,6 @@ export const REQUIRED_HALVES = 2
|
|||
export const HANDLE_VERTICAL = 'vertical'
|
||||
export const HANDLE_HORIZONTAL = 'horizontal'
|
||||
export const HANDLE_NONE = 'none'
|
||||
export const HANDLE_PIXELS = 30
|
||||
export const HANDLE_PIXELS = 20
|
||||
export const MAX_SIZE = 1
|
||||
export const MIN_SIZE = 0
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import _ from 'lodash'
|
||||
import React, {PureComponent} from 'react'
|
||||
import {withRouter, Link} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
|
@ -14,10 +15,13 @@ import {
|
|||
} from 'src/side_nav/components/NavItems'
|
||||
|
||||
import {DEFAULT_HOME_PAGE} from 'src/shared/constants'
|
||||
import {Params, Location, Links, Me} from 'src/types/sideNav'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
import {Params, Location, Links, Me} from 'src/types/sideNav'
|
||||
import {Source} from 'src/types'
|
||||
|
||||
interface Props {
|
||||
sources: Source[]
|
||||
params: Params
|
||||
location: Location
|
||||
isHidden: boolean
|
||||
|
@ -42,9 +46,13 @@ class SideNav extends PureComponent<Props> {
|
|||
logoutLink,
|
||||
links,
|
||||
me,
|
||||
sources = [],
|
||||
} = this.props
|
||||
|
||||
const sourcePrefix = `/sources/${sourceID}`
|
||||
const defaultSource = sources.find(s => s.default)
|
||||
const id = sourceID || _.get(defaultSource, 'id', 0)
|
||||
|
||||
const sourcePrefix = `/sources/${id}`
|
||||
const dataExplorerLink = `${sourcePrefix}/chronograf/data-explorer`
|
||||
|
||||
const isDefaultPage = location.split('/').includes(DEFAULT_HOME_PAGE)
|
||||
|
@ -69,6 +77,16 @@ class SideNav extends PureComponent<Props> {
|
|||
>
|
||||
<NavHeader link={`${sourcePrefix}/hosts`} title="Host List" />
|
||||
</NavBlock>
|
||||
<FeatureFlag name="log-viewer">
|
||||
<NavBlock
|
||||
highlightWhen={['logs']}
|
||||
icon="cubo-node"
|
||||
link={'/logs'}
|
||||
location={location}
|
||||
>
|
||||
<NavHeader link={'/logs'} title="Log Viewer" />
|
||||
</NavBlock>
|
||||
</FeatureFlag>
|
||||
<NavBlock
|
||||
highlightWhen={['data-explorer', 'delorean']}
|
||||
icon="graphline"
|
||||
|
@ -164,12 +182,14 @@ class SideNav extends PureComponent<Props> {
|
|||
}
|
||||
|
||||
const mapStateToProps = ({
|
||||
sources,
|
||||
auth: {isUsingAuth, logoutLink, me},
|
||||
app: {
|
||||
ephemeral: {inPresentationMode},
|
||||
},
|
||||
links,
|
||||
}) => ({
|
||||
sources,
|
||||
isHidden: inPresentationMode,
|
||||
isUsingAuth,
|
||||
logoutLink,
|
||||
|
|
|
@ -7,6 +7,7 @@ import errorsMiddleware from 'shared/middleware/errors'
|
|||
import {resizeLayout} from 'shared/middleware/resizeLayout'
|
||||
import {queryStringConfig} from 'shared/middleware/queryStringConfig'
|
||||
import statusReducers from 'src/status/reducers'
|
||||
import logsReducer from 'src/logs/reducers'
|
||||
import sharedReducers from 'shared/reducers'
|
||||
import dataExplorerReducers from 'src/data_explorer/reducers'
|
||||
import adminReducers from 'src/admin/reducers'
|
||||
|
@ -17,6 +18,7 @@ import overlayTechnology from 'src/shared/reducers/overlayTechnology'
|
|||
import dashTimeV1 from 'src/dashboards/reducers/dashTimeV1'
|
||||
import persistStateEnhancer from './persistStateEnhancer'
|
||||
import servicesReducer from 'src/shared/reducers/services'
|
||||
import scriptReducer from 'src/ifql/reducers/script'
|
||||
|
||||
const rootReducer = combineReducers({
|
||||
...statusReducers,
|
||||
|
@ -28,8 +30,10 @@ const rootReducer = combineReducers({
|
|||
cellEditorOverlay,
|
||||
overlayTechnology,
|
||||
dashTimeV1,
|
||||
logs: logsReducer,
|
||||
routing: routerReducer,
|
||||
services: servicesReducer,
|
||||
script: scriptReducer,
|
||||
})
|
||||
|
||||
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
@import 'components/ceo-display-options';
|
||||
@import 'components/confirm-button';
|
||||
@import 'components/confirm-or-cancel';
|
||||
@import 'components/code-mirror-theme';
|
||||
@import 'components/code-mirror/theme';
|
||||
@import 'components/color-dropdown';
|
||||
@import 'components/custom-time-range';
|
||||
@import 'components/customize-fields';
|
||||
|
|
|
@ -1,209 +0,0 @@
|
|||
/*
|
||||
|
||||
Name: CHRONOGRAF YO
|
||||
Author: Michael Kaminsky (http://github.com/mkaminsky11)
|
||||
|
||||
Original material color scheme by Mattia Astorino (https://github.com/equinusocio/material-theme)
|
||||
|
||||
*/
|
||||
|
||||
.react-codemirror2 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.cm-s-material.CodeMirror {
|
||||
border-radius: 0 0 $radius $radius;
|
||||
font-family: $code-font;
|
||||
background-color: transparent;
|
||||
color: $g13-mist;
|
||||
font-weight: 600;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar {
|
||||
@include custom-scrollbar-round($g2-kevlar, $g6-smoke);
|
||||
}
|
||||
|
||||
.CodeMirror-hscrollbar {
|
||||
@include custom-scrollbar-round($g0-obsidian, $g6-smoke);
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-gutters {
|
||||
@include gradient-v($g2-kevlar, $g0-obsidian) border: none;
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-gutters .CodeMirror-gutter {
|
||||
background-color: fade-out($g4-onyx, 0.75);
|
||||
height: calc(100% + 30px);
|
||||
}
|
||||
|
||||
.CodeMirror-gutter.CodeMirror-linenumbers {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.cm-s-material.CodeMirror .CodeMirror-sizer {
|
||||
margin-left: 60px;
|
||||
}
|
||||
|
||||
.cm-s-material.CodeMirror .CodeMirror-linenumber.CodeMirror-gutter-elt {
|
||||
padding-right: 9px;
|
||||
width: 46px;
|
||||
color: $g8-storm;
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-guttermarker,
|
||||
.cm-s-material .CodeMirror-guttermarker-subtle,
|
||||
.cm-s-material .CodeMirror-linenumber {
|
||||
color: rgb(83, 127, 126);
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-cursor {
|
||||
width: 2px;
|
||||
border: 0;
|
||||
background-color: $g20-white;
|
||||
box-shadow: 0 0 3px $c-laser, 0 0 6px $c-ocean, 0 0 11px $c-amethyst;
|
||||
}
|
||||
|
||||
.cm-s-material div.CodeMirror-selected,
|
||||
.cm-s-material.CodeMirror-focused div.CodeMirror-selected {
|
||||
background-color: fade-out($g8-storm, 0.7);
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-line::selection,
|
||||
.cm-s-material .CodeMirror-line>span::selection,
|
||||
.cm-s-material .CodeMirror-line>span>span::selection {
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-line::-moz-selection,
|
||||
.cm-s-material .CodeMirror-line>span::-moz-selection,
|
||||
.cm-s-material .CodeMirror-line>span>span::-moz-selection {
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-activeline-background {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.cm-s-material .cm-keyword {
|
||||
color: $c-comet;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-operator {
|
||||
color: $c-dreamsicle;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-variable-2 {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-variable-3,
|
||||
.cm-s-material .cm-type {
|
||||
color: $c-laser;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-builtin {
|
||||
color: #DECB6B;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-atom {
|
||||
color: $c-viridian;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-number {
|
||||
color: $c-daisy;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-def {
|
||||
color: rgba(233, 237, 237, 1);
|
||||
}
|
||||
|
||||
.cm-s-material .cm-string {
|
||||
color: $c-krypton;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-string-2 {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-comment {
|
||||
color: $g10-wolf;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-variable {
|
||||
color: $c-laser;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-tag {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-meta {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-attribute {
|
||||
color: #FFCB6B;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-property {
|
||||
color: #80CBAE;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-qualifier {
|
||||
color: #DECB6B;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-variable-3,
|
||||
.cm-s-material .cm-type {
|
||||
color: #DECB6B;
|
||||
}
|
||||
|
||||
.cm-s-material .cm-tag {
|
||||
color: rgba(255, 83, 112, 1);
|
||||
}
|
||||
|
||||
.cm-s-material .cm-error {
|
||||
color: rgba(255, 255, 255, 1.0);
|
||||
background-color: #EC5F67;
|
||||
}
|
||||
|
||||
.cm-s-material .CodeMirror-matchingbracket {
|
||||
text-decoration: underline;
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
// CodeMirror hints
|
||||
.CodeMirror-hints {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 2px;
|
||||
-webkit-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
|
||||
-moz-box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
|
||||
box-shadow: 2px 3px 5px rgba(0, 0, 0, .2);
|
||||
border-radius: 3px;
|
||||
border: 1px solid silver;
|
||||
background: white;
|
||||
font-size: 90%;
|
||||
font-family: monospace;
|
||||
max-height: 20em;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.CodeMirror-hint {
|
||||
margin: 0;
|
||||
padding: 0 4px;
|
||||
border-radius: 2px;
|
||||
white-space: pre;
|
||||
color: black;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li.CodeMirror-hint-active {
|
||||
background: #08f;
|
||||
color: white;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
CodeMirror Hints Styles
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.CodeMirror-hints {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
overflow: hidden;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-shadow: 0 2px 5px 0.6px fade-out($g0-obsidian, 0.8);
|
||||
border-radius: $radius;
|
||||
font-size: 12px;
|
||||
font-family: $code-font;
|
||||
font-weight: 600;
|
||||
max-height: 20em;
|
||||
overflow-y: auto;
|
||||
@include gradient-h($c-star, $c-pool);
|
||||
}
|
||||
|
||||
li.CodeMirror-hint {
|
||||
margin: 0;
|
||||
padding: 6px 7px;
|
||||
line-height: 12px;
|
||||
white-space: pre;
|
||||
color: $c-neutrino;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li.CodeMirror-hint-active {
|
||||
@include gradient-h($c-comet, $c-laser);
|
||||
color: $g20-white;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
CodeMirror "TICKscript" Theme
|
||||
------------------------------------------------------------------------------
|
||||
Intended for use with the TICKscript CodeMirror Mode
|
||||
*/
|
||||
|
||||
.cm-s-tickscript {
|
||||
.cm-keyword {
|
||||
color: $c-comet;
|
||||
}
|
||||
|
||||
.cm-operator {
|
||||
color: $c-dreamsicle;
|
||||
}
|
||||
|
||||
.cm-variable-2 {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-variable-3,
|
||||
.cm-type {
|
||||
color: $c-laser;
|
||||
}
|
||||
|
||||
.cm-builtin {
|
||||
color: #DECB6B;
|
||||
}
|
||||
|
||||
.cm-atom {
|
||||
color: $c-viridian;
|
||||
}
|
||||
|
||||
.cm-number {
|
||||
color: $c-daisy;
|
||||
}
|
||||
|
||||
.cm-def {
|
||||
color: rgba(233, 237, 237, 1);
|
||||
}
|
||||
|
||||
.cm-string {
|
||||
color: $c-krypton;
|
||||
}
|
||||
|
||||
.cm-string-2 {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-comment {
|
||||
color: $g10-wolf;
|
||||
}
|
||||
|
||||
.cm-variable {
|
||||
color: $c-laser;
|
||||
}
|
||||
|
||||
.cm-tag {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-meta {
|
||||
color: #80CBC4;
|
||||
}
|
||||
|
||||
.cm-attribute {
|
||||
color: #FFCB6B;
|
||||
}
|
||||
|
||||
.cm-property {
|
||||
color: #80CBAE;
|
||||
}
|
||||
|
||||
.cm-qualifier {
|
||||
color: #DECB6B;
|
||||
}
|
||||
|
||||
.cm-variable-3,
|
||||
.cm-type {
|
||||
color: #DECB6B;
|
||||
}
|
||||
|
||||
.cm-tag {
|
||||
color: rgba(255, 83, 112, 1);
|
||||
}
|
||||
|
||||
.cm-error {
|
||||
color: rgba(255, 255, 255, 1.0);
|
||||
background-color: #EC5F67;
|
||||
}
|
||||
|
||||
.CodeMirror-matchingbracket {
|
||||
text-decoration: underline;
|
||||
color: white !important;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
CodeMirror "Time Machine" Theme
|
||||
------------------------------------------------------------------------------
|
||||
Intended for use with the IFQL CodeMirror Mode
|
||||
*/
|
||||
|
||||
.cm-s-time-machine {
|
||||
color: $g11-sidewalk;
|
||||
|
||||
.cm-variable {
|
||||
color: $c-pool;
|
||||
font-weight: 700;
|
||||
}
|
||||
.cm-function,
|
||||
.cm-pipe-forward {
|
||||
color: $c-comet;
|
||||
font-weight: 700;
|
||||
}
|
||||
.cm-arrow-function,
|
||||
.cm-function-arg,
|
||||
.cm-function-arg-ref {
|
||||
color: #ff4d96;
|
||||
}
|
||||
.cm-operator {
|
||||
color: $g15-platinum;
|
||||
}
|
||||
.cm-argument {
|
||||
color: $g11-sidewalk;
|
||||
}
|
||||
.cm-string-single,
|
||||
.cm-string-double {
|
||||
color: $c-honeydew;
|
||||
}
|
||||
.cm-boolean {
|
||||
color: $c-viridian;
|
||||
}
|
||||
.cm-null {
|
||||
color: $c-dreamsicle;
|
||||
}
|
||||
.cm-number {
|
||||
color: $c-hydrogen;
|
||||
}
|
||||
.cm-comment {
|
||||
color: $g8-storm;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
CodeMirror Styles
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.react-codemirror2 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.CodeMirror {
|
||||
border-radius: 0 0 $radius $radius;
|
||||
font-family: $code-font;
|
||||
background-color: transparent;
|
||||
color: $g13-mist;
|
||||
font-weight: 500;
|
||||
font-size: 13px;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.CodeMirror-vscrollbar {
|
||||
@include custom-scrollbar-round($g2-kevlar, $g6-smoke);
|
||||
}
|
||||
|
||||
.CodeMirror-hscrollbar {
|
||||
@include custom-scrollbar-round($g0-obsidian, $g6-smoke);
|
||||
}
|
||||
|
||||
.CodeMirror-gutters {
|
||||
@include gradient-v($g2-kevlar, $g0-obsidian);
|
||||
border: none;
|
||||
}
|
||||
|
||||
.CodeMirror-gutters .CodeMirror-gutter {
|
||||
background-color: fade-out($g4-onyx, 0.75);
|
||||
height: calc(100% + 30px);
|
||||
}
|
||||
|
||||
.CodeMirror-gutter.CodeMirror-linenumbers {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-sizer {
|
||||
margin-left: 60px;
|
||||
}
|
||||
|
||||
.CodeMirror .CodeMirror-linenumber.CodeMirror-gutter-elt {
|
||||
padding-right: 9px;
|
||||
width: 46px;
|
||||
color: $g8-storm;
|
||||
}
|
||||
|
||||
.CodeMirror-guttermarker,
|
||||
.CodeMirror-guttermarker-subtle,
|
||||
.CodeMirror-linenumber {
|
||||
color: rgb(83, 127, 126);
|
||||
}
|
||||
|
||||
.CodeMirror-cursor {
|
||||
width: 2px;
|
||||
border: 0;
|
||||
background-color: $g20-white;
|
||||
box-shadow: 0 0 3px $c-laser, 0 0 6px $c-ocean, 0 0 11px $c-amethyst;
|
||||
}
|
||||
|
||||
div.CodeMirror-selected,
|
||||
.CodeMirror-focused div.CodeMirror-selected {
|
||||
background-color: fade-out($g8-storm, 0.7);
|
||||
}
|
||||
|
||||
.CodeMirror-line::selection,
|
||||
.CodeMirror-line>span::selection,
|
||||
.CodeMirror-line>span>span::selection {
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
}
|
||||
|
||||
.CodeMirror-line::-moz-selection,
|
||||
.CodeMirror-line>span::-moz-selection,
|
||||
.CodeMirror-line>span>span::-moz-selection {
|
||||
background: rgba(255, 255, 255, 0.10);
|
||||
}
|
||||
|
||||
.CodeMirror-activeline-background {
|
||||
background: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
Themes & Sub-Components
|
||||
------------------------------------------------------------------------------
|
||||
*/
|
||||
@import 'time-machine';
|
||||
@import 'tickscript';
|
||||
@import 'hints';
|
|
@ -3,7 +3,6 @@
|
|||
------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
$threesizer-handle: 30px;
|
||||
.threesizer {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
@ -73,16 +72,19 @@ $threesizer-handle: 30px;
|
|||
.threesizer--title {
|
||||
padding-left: 14px;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
white-space: nowrap;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
color: $g11-sidewalk;
|
||||
z-index: 1;
|
||||
transition: transform 0.25s ease;
|
||||
transition: transform 0.25s ease, letter-spacing 0.25s ease;
|
||||
&.vertical {
|
||||
transform: translate(28px, 14px);
|
||||
transform: translate(20px, 14px);
|
||||
&.threesizer--collapsed {
|
||||
transform: translate(0, 3px) rotate(90deg);
|
||||
transform: translate(0, 5px) rotate(90deg) scale(0.75);
|
||||
letter-spacing: 0.15em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -138,11 +140,11 @@ $threesizer-shadow-stop: fade-out($g0-obsidian, 1);
|
|||
padding: 0 11px;
|
||||
background-color: $g2-kevlar;
|
||||
.horizontal>& {
|
||||
width: 50px;
|
||||
width: 44px;
|
||||
border-right: 2px solid $g4-onyx;
|
||||
}
|
||||
.vertical>& {
|
||||
height: 50px;
|
||||
height: 44px;
|
||||
border-bottom: 2px solid $g4-onyx;
|
||||
}
|
||||
}
|
||||
|
|
Binary file not shown.
|
@ -19,36 +19,35 @@
|
|||
<glyph unicode="" glyph-name="group" d="M742.4 327.68c58.88 28.16 99.84 89.6 99.84 161.28 0 99.84-79.36 179.2-179.2 179.2-64 0-120.32-33.28-153.6-84.48 46.080-40.96 76.8-102.4 76.8-171.52 0-56.32-20.48-110.080-56.32-151.040 71.68-51.2 133.12-140.8 133.12-243.2v-94.72h238.080c10.24 0 17.92 10.24 17.92 25.6v145.92c0 112.64-89.6 209.92-176.64 232.96zM435.2 250.88c58.88 28.16 99.84 89.6 99.84 161.28 0 99.84-79.36 179.2-179.2 179.2s-179.2-79.36-179.2-179.2c0-71.68 40.96-130.56 99.84-161.28-81.92-23.040-174.080-120.32-174.080-235.52v-143.36c0-12.8 7.68-25.6 17.92-25.6h476.16c10.24 0 17.92 10.24 17.92 25.6v145.92c-2.56 112.64-92.16 209.92-179.2 232.96z" />
|
||||
<glyph unicode="" glyph-name="remove" d="M870.4 23.040l-215.040 215.040c-10.24 10.24-10.24 25.6 0 35.84l215.040 215.040c33.28 33.28 38.4 89.6 7.68 128-35.84 38.4-94.72 38.4-130.56 2.56l-217.6-217.6c-10.24-10.24-25.6-10.24-35.84 0l-215.040 212.48c-33.28 33.28-89.6 38.4-125.44 7.68-38.4-35.84-38.4-94.72-2.56-130.56l217.6-217.6c10.24-10.24 10.24-25.6 0-35.84l-215.040-215.040c-33.28-33.28-38.4-89.6-7.68-128 35.84-38.4 94.72-38.4 130.56-2.56l217.6 217.6c10.24 10.24 25.6 10.24 35.84 0l217.6-217.6c35.84-35.84 94.72-35.84 130.56 2.56 30.72 38.4 25.6 94.72-7.68 128z" />
|
||||
<glyph unicode="" glyph-name="plus" d="M929.28 345.6h-302.080c-12.8 0-25.6 10.24-25.6 25.6v302.080c0 48.64-35.84 92.16-84.48 94.72-51.2 2.56-94.72-38.4-94.72-89.6v-307.2c0-12.8-10.24-25.6-25.6-25.6h-302.080c-48.64 0-92.16-35.84-94.72-84.48-2.56-51.2 38.4-94.72 89.6-94.72h307.2c12.8 0 25.6-10.24 25.6-25.6v-302.080c0-48.64 35.84-92.16 84.48-94.72 51.2-2.56 94.72 38.4 94.72 89.6v307.2c0 12.8 10.24 25.6 25.6 25.6h307.2c51.2 0 92.16 43.52 89.6 94.72-2.56 48.64-46.080 84.48-94.72 84.48z" />
|
||||
<glyph unicode="" glyph-name="arrow-up" d="M934.4 89.6c0-7.68-2.56-17.92-10.24-25.6-12.8-15.36-38.4-17.92-53.76-5.12l-358.4 312.32-358.4-309.76c-15.36-12.8-40.96-12.8-53.76 5.12-12.8 15.36-12.8 40.96 5.12 53.76l384 332.8c15.36 12.8 35.84 12.8 51.2 0l384-332.8c5.12-10.24 10.24-20.48 10.24-30.72z" />
|
||||
<glyph unicode="" glyph-name="arrow-left" d="M678.4 678.4c7.68 0 17.92-2.56 25.6-10.24 15.36-12.8 17.92-38.4 5.12-53.76l-312.32-358.4 309.76-358.4c12.8-15.36 12.8-40.96-5.12-53.76-15.36-12.8-40.96-12.8-53.76 5.12l-332.8 384c-12.8 15.36-12.8 35.84 0 51.2l332.8 384c10.24 5.12 20.48 10.24 30.72 10.24z" />
|
||||
<glyph unicode="" glyph-name="cube" d="M985.6 496.64c0 0 0 2.56-2.56 2.56 0 2.56-2.56 5.12-2.56 5.12s-2.56 2.56-2.56 2.56c0 2.56-2.56 2.56-2.56 5.12 0 0-2.56 2.56-2.56 2.56s-2.56 2.56-2.56 2.56c0 0 0 0 0 0s0 0 0 0l-437.76 230.4c-10.24 5.12-25.6 5.12-35.84 0l-437.76-230.4c-5.12 2.56-7.68 0-10.24-2.56 0 0 0 0-2.56-2.56s-2.56-2.56-5.12-5.12c0 0 0-2.56-2.56-2.56 0 0 0 0 0 0 0-2.56-2.56-5.12-2.56-7.68 0 0 0 0 0 0 0-2.56 0-5.12 0-7.68 0 0 0 0 0 0v-460.8c0-15.36 7.68-28.16 20.48-33.28l437.76-230.4c2.56 0 2.56-2.56 5.12-2.56 0 0 2.56 0 2.56 0 2.56 0 7.68-2.56 10.24-2.56 5.12 0 12.8 2.56 17.92 5.12l437.76 230.4c12.8 7.68 20.48 20.48 20.48 33.28v458.24c0 2.56 0 7.68-2.56 10.24zM512 673.28l355.84-186.88-355.84-186.88-355.84 186.88 355.84 186.88zM112.64 422.4l360.96-189.44v-373.76l-360.96 189.44v373.76z" />
|
||||
<glyph unicode="" glyph-name="export" d="M204.8 729.6h230.4c20.48 0 38.4-17.92 38.4-38.4s-17.92-38.4-38.4-38.4h-230.4c-48.64 0-89.6-40.96-89.6-89.6v-614.4c0-48.64 40.96-89.6 89.6-89.6h614.4c48.64 0 89.6 40.96 89.6 89.6v230.4c0 20.48 17.92 38.4 38.4 38.4s38.4-17.92 38.4-38.4v-230.4c0-92.16-74.24-166.4-166.4-166.4h-614.4c-92.16 0-166.4 74.24-166.4 166.4v614.4c0 92.16 74.24 166.4 166.4 166.4zM678.4 568.32l-89.6 89.6c-25.6 25.6-7.68 71.68 30.72 71.68h368.64v-368.64c0-38.4-46.080-56.32-71.68-30.72l-89.6 89.6-250.88-250.88c-40.96-40.96-104.96-40.96-145.92 0s-40.96 104.96 0 145.92l248.32 253.44z" />
|
||||
<glyph unicode="" glyph-name="user" d="M588.8 289.28c58.88 28.16 99.84 89.6 99.84 161.28 0 99.84-79.36 179.2-179.2 179.2s-179.2-79.36-179.2-179.2c0-71.68 40.96-130.56 99.84-161.28-84.48-20.48-176.64-120.32-176.64-232.96v-145.92c0-12.8 7.68-25.6 17.92-25.6h476.16c10.24 0 17.92 10.24 17.92 25.6v145.92c0 112.64-89.6 209.92-176.64 232.96z" />
|
||||
<glyph unicode="" glyph-name="graphline" d="M888.32 465.92c-17.92 0-33.28-5.12-48.64-12.8l-76.8 79.36c10.24 15.36 15.36 33.28 15.36 53.76 0 56.32-46.080 104.96-104.96 104.96s-104.96-46.080-104.96-104.96c0-33.28 15.36-64 40.96-81.92l-192-476.16c-2.56 0-7.68 0-10.24 0-20.48 0-40.96-7.68-58.88-17.92l-117.76 99.84c5.12 12.8 10.24 28.16 10.24 43.52 0 56.32-46.080 104.96-104.96 104.96s-104.96-46.080-104.96-104.96 46.080-104.96 104.96-104.96c20.48 0 40.96 7.68 58.88 17.92l117.76-99.84c-5.12-12.8-10.24-28.16-10.24-43.52 0-56.32 46.080-104.96 104.96-104.96s104.96 46.080 104.96 104.96c0 33.28-15.36 64-40.96 81.92l192 476.16c2.56 0 7.68 0 10.24 0 17.92 0 33.28 5.12 48.64 12.8l76.8-79.36c-10.24-15.36-15.36-33.28-15.36-53.76 0-56.32 46.080-104.96 104.96-104.96s104.96 46.080 104.96 104.96-48.64 104.96-104.96 104.96z" />
|
||||
<glyph unicode="" glyph-name="collapse" d="M560.64 189.44c-2.56 2.56-5.12 5.12-7.68 7.68 0 0-2.56 2.56-2.56 2.56-2.56 0-2.56 2.56-5.12 2.56s-2.56 0-5.12 2.56c-2.56 0-2.56 0-5.12 2.56-2.56 0-7.68 0-10.24 0 0 0 0 0 0 0s0 0 0 0c-2.56 0-7.68 0-10.24 0s-2.56 0-5.12 0-2.56 0-5.12-2.56c-2.56 0-2.56-2.56-5.12-2.56s-2.56-2.56-5.12-2.56-5.12-5.12-7.68-7.68l-204.8-204.8c-20.48-20.48-20.48-51.2 0-71.68s51.2-20.48 71.68 0l117.76 117.76v-238.080c0-28.16 23.040-51.2 51.2-51.2s51.2 23.040 51.2 51.2v235.52l117.76-117.76c10.24-10.24 23.040-15.36 35.84-15.36s25.6 5.12 35.84 15.36c20.48 20.48 20.48 51.2 0 71.68l-202.24 204.8zM488.96 322.56c2.56-2.56 5.12-5.12 7.68-7.68 0 0 2.56-2.56 5.12-2.56s2.56-2.56 5.12-2.56c2.56 0 2.56 0 5.12-2.56 2.56 0 2.56 0 5.12-2.56 2.56 0 7.68 0 10.24 0s7.68 0 10.24 0c2.56 0 2.56 0 5.12 2.56 2.56 0 2.56 0 5.12 2.56 2.56 0 2.56 2.56 5.12 2.56 0 0 2.56 0 2.56 2.56 2.56 2.56 5.12 5.12 7.68 7.68l204.8 204.8c20.48 20.48 20.48 51.2 0 71.68s-51.2 20.48-71.68 0l-117.76-117.76v235.52c0 28.16-23.040 51.2-51.2 51.2s-51.2-23.040-51.2-51.2v-235.52l-117.76 117.76c-20.48 20.48-51.2 20.48-71.68 0s-20.48-51.2 0-71.68l202.24-204.8z" />
|
||||
<glyph unicode="" glyph-name="arrow-down" d="M89.6 422.4c0 7.68 2.56 17.92 10.24 25.6 12.8 15.36 38.4 17.92 53.76 5.12l358.4-309.76 358.4 309.76c15.36 12.8 40.96 12.8 53.76-5.12 12.8-15.36 12.8-40.96-5.12-53.76l-384-332.8c-15.36-12.8-35.84-12.8-51.2 0l-384 332.8c-5.12 7.68-10.24 17.92-10.24 28.16z" />
|
||||
<glyph unicode="" glyph-name="arrow-right" d="M345.6-166.4c-7.68 0-17.92 2.56-25.6 10.24-15.36 12.8-17.92 38.4-5.12 53.76l309.76 358.4-307.2 358.4c-12.8 15.36-12.8 40.96 5.12 53.76 15.36 12.8 40.96 12.8 53.76-5.12l332.8-384c12.8-15.36 12.8-35.84 0-51.2l-332.8-384c-10.24-5.12-20.48-10.24-30.72-10.24z" />
|
||||
<glyph unicode="" glyph-name="import" d="M819.2 729.6h-358.4c-20.48 0-38.4-17.92-38.4-38.4s17.92-38.4 38.4-38.4h358.4c48.64 0 89.6-40.96 89.6-89.6v-614.4c0-48.64-40.96-89.6-89.6-89.6h-614.4c-48.64 0-89.6 40.96-89.6 89.6v358.4c0 20.48-17.92 38.4-38.4 38.4s-38.4-17.92-38.4-38.4v-358.4c0-92.16 74.24-166.4 166.4-166.4h614.4c92.16 0 166.4 74.24 166.4 166.4v614.4c0 92.16-74.24 166.4-166.4 166.4zM384 238.080l-89.6-89.6c-25.6-25.6-7.68-71.68 30.72-71.68h366.080v368.64c0 38.4-46.080 56.32-71.68 30.72l-89.6-92.16-304.64 302.080c-40.96 40.96-104.96 40.96-145.92 0s-40.96-104.96 0-145.92l304.64-302.080z" />
|
||||
<glyph unicode="" glyph-name="text-block" d="M1024 614.4c0-15.36-12.8-25.6-25.6-25.6h-537.6c-12.8 0-25.6 10.24-25.6 25.6v128c0 15.36 12.8 25.6 25.6 25.6h537.6c12.8 0 25.6-10.24 25.6-25.6v-128zM1024 332.8c0-12.8-12.8-25.6-25.6-25.6h-972.8c-15.36 0-25.6 12.8-25.6 25.6v128c0 15.36 10.24 25.6 25.6 25.6h972.8c12.8 0 25.6-10.24 25.6-25.6v-128zM1024 51.2c0-12.8-12.8-25.6-25.6-25.6h-972.8c-15.36 0-25.6 12.8-25.6 25.6v128c0 12.8 10.24 25.6 25.6 25.6h972.8c12.8 0 25.6-12.8 25.6-25.6v-128zM588.8-230.4c0-12.8-12.8-25.6-25.6-25.6h-537.6c-15.36 0-25.6 12.8-25.6 25.6v128c0 12.8 10.24 25.6 25.6 25.6h537.6c12.8 0 25.6-12.8 25.6-25.6v-128z" />
|
||||
<glyph unicode="" glyph-name="okta" d="M816.64 642.56v-286.72c69.12 10.24 125.44 71.68 125.44 143.36s-56.32 135.68-125.44 143.36zM650.24 499.2c0-71.68 53.76-133.12 125.44-143.36v286.72c-71.68-7.68-125.44-69.12-125.44-143.36zM1024 499.2c0 125.44-102.4 227.84-227.84 227.84-48.64 0-94.72-15.36-130.56-40.96-58.88 25.6-125.44 40.96-194.56 40.96-258.56 0-471.040-209.92-471.040-471.040s212.48-471.040 471.040-471.040c261.12 0 471.040 212.48 471.040 471.040 0 23.040-2.56 46.080-5.12 66.56 53.76 43.52 87.040 107.52 87.040 176.64zM471.040-133.12c-215.040 0-389.12 174.080-389.12 389.12s176.64 389.12 389.12 389.12c46.080 0 89.6-7.68 130.56-23.040-15.36-23.040-25.6-48.64-30.72-76.8-30.72 10.24-64 17.92-99.84 17.92-168.96 0-307.2-138.24-307.2-307.2s138.24-307.2 307.2-307.2c168.96 0 307.2 138.24 307.2 307.2 0 5.12 0 12.8 0 17.92 5.12 0 12.8 0 17.92 0 23.040 0 43.52 2.56 64 10.24 0-7.68 2.56-17.92 2.56-25.6 0-217.6-176.64-391.68-391.68-391.68zM796.16 314.88c-102.4 0-186.88 84.48-186.88 186.88s84.48 186.88 186.88 186.88 186.88-84.48 186.88-186.88-84.48-186.88-186.88-186.88z" />
|
||||
<glyph unicode="" glyph-name="bar-chart" d="M179.2 179.2c0 12.8-10.24 25.6-25.6 25.6h-128c-15.36 0-25.6-12.8-25.6-25.6v-409.6c0-12.8 10.24-25.6 25.6-25.6h128c15.36 0 25.6 12.8 25.6 25.6v409.6zM460.8 742.4c0 15.36-12.8 25.6-25.6 25.6h-128c-15.36 0-25.6-10.24-25.6-25.6v-972.8c0-12.8 10.24-25.6 25.6-25.6h128c12.8 0 25.6 12.8 25.6 25.6v972.8zM742.4 460.8c0 15.36-12.8 25.6-25.6 25.6h-128c-12.8 0-25.6-10.24-25.6-25.6v-691.2c0-12.8 12.8-25.6 25.6-25.6h128c12.8 0 25.6 12.8 25.6 25.6v691.2zM1024-51.2c0 12.8-12.8 25.6-25.6 25.6h-128c-12.8 0-25.6-12.8-25.6-25.6v-179.2c0-12.8 12.8-25.6 25.6-25.6h128c12.8 0 25.6 12.8 25.6 25.6v179.2z" />
|
||||
<glyph unicode="" glyph-name="search" d="M993.28-99.84l-202.24 202.24c40.96 64 64 135.68 64 217.6 0 225.28-181.76 407.040-407.040 407.040s-404.48-184.32-404.48-407.040 181.76-407.040 407.040-407.040c79.36 0 153.6 23.040 217.6 64l202.24-202.24c17.92-17.92 40.96-25.6 64-25.6s46.080 7.68 64 25.6c30.72 33.28 30.72 92.16-5.12 125.44zM145.92 320c0 166.4 135.68 302.080 302.080 302.080s304.64-135.68 304.64-304.64c0-79.36-30.72-151.040-79.36-204.8-2.56-2.56-7.68-5.12-10.24-7.68s-5.12-7.68-7.68-10.24c-53.76-48.64-125.44-79.36-204.8-79.36-168.96 0-304.64 135.68-304.64 304.64z" />
|
||||
<glyph unicode="" glyph-name="duplicate" d="M921.6 768h-563.2c-56.32 0-102.4-46.080-102.4-102.4v-153.6h-153.6c-56.32 0-102.4-46.080-102.4-102.4v-563.2c0-56.32 46.080-102.4 102.4-102.4h563.2c56.32 0 102.4 46.080 102.4 102.4v153.6h153.6c56.32 0 102.4 46.080 102.4 102.4v563.2c0 56.32-46.080 102.4-102.4 102.4zM691.2-153.6c0-12.8-12.8-25.6-25.6-25.6h-563.2c-12.8 0-25.6 12.8-25.6 25.6v563.2c0 12.8 12.8 25.6 25.6 25.6h153.6v-332.8c0-56.32 46.080-102.4 102.4-102.4h332.8v-153.6z" />
|
||||
<glyph unicode="" glyph-name="checkmark" d="M345.6-87.040l-271.36 271.36c-33.28 33.28-38.4 89.6-7.68 128 35.84 38.4 94.72 38.4 130.56 2.56l168.96-168.96c5.12-5.12 12.8-5.12 15.36 0l442.88 442.88c35.84 35.84 94.72 35.84 130.56-2.56 33.28-35.84 28.16-92.16-7.68-128l-542.72-542.72c-15.36-20.48-43.52-20.48-58.88-2.56z" />
|
||||
<glyph unicode="" glyph-name="cubo-node" horiz-adv-x="1008" d="M917.78 487.468c-8.792 2.928-20.512 2.928-29.296 5.856l-23.44 108.408c-2.928 8.792-8.792 17.576-20.512 20.512l-451.208 137.704c-8.792 2.928-20.512 0-29.296-5.856l-82.040-76.176c-8.792 5.856-17.576 11.72-29.296 14.648-64.456 20.512-131.848-17.576-149.424-79.112-8.792-32.232-5.856-64.456 8.792-93.76l-93.76-87.896c-8.792-5.856-11.72-17.576-8.792-29.296l105.48-460c2.928-8.792 8.792-17.576 20.512-20.512l114.264-35.16c-2.928-52.736 29.296-105.48 84.968-120.128 52.736-17.576 108.408 5.856 137.704 52.736l114.264-35.16c2.928 0 5.856 0 8.792 0 5.856 0 14.648 2.928 20.512 8.792l345.736 322.296c8.792 5.856 11.72 17.576 8.792 29.296l-29.296 125.984c26.368 14.648 46.88 38.088 55.672 70.32 20.512 58.6-17.576 125.984-79.112 146.496zM698.028 45.052l143.568 32.232-184.584-172.864 41.016 140.64zM577.9-151.26l-87.896 26.368c2.928 52.736-32.232 105.48-84.968 120.128-52.736 17.576-108.408-5.856-137.704-52.736l-84.968 26.368 61.528 202.168 395.544-120.128-61.528-202.168zM182.364 461.1c64.456-20.512 131.848 17.576 149.424 79.112 8.792 32.232 5.856 64.456-8.792 93.76l58.6 55.672 143.568-155.288-301.784-281.272-143.568 155.288 73.248 67.392c8.792-5.856 20.512-11.72 29.296-14.648zM281.98 220.844l269.552 251.976 82.040-360.384-351.592 108.408zM577.9 563.652l-99.616 108.408 243.184-73.248-143.568-35.16zM91.532 308.74l99.616-105.48-41.016-137.704-58.6 243.184zM906.060 153.46l-208.024-49.808-93.76 401.4 208.024 49.808 17.576-76.176c-29.296-14.648-52.736-38.088-64.456-73.248-20.512-64.456 17.576-131.848 79.112-149.424 11.72-2.928 23.44-5.856 35.16-5.856l26.368-96.688z" />
|
||||
<glyph unicode="" glyph-name="cubo-uniform" d="M1004.192 120.646l-109.376 470.316c-2.736 10.936-10.936 19.14-21.876 21.876l-462.112 142.188c-10.936 2.736-21.876 0-30.080-5.468l-352.736-330.86c-8.204-8.204-10.936-19.14-8.204-30.080l109.376-470.316c2.736-10.936 10.936-19.14 19.14-21.876l462.112-142.188c2.736 0 5.468 0 8.204 0 8.204 0 13.672 2.736 19.14 8.204l352.736 330.86c10.936 5.468 16.408 16.408 13.672 27.344zM574.896 462.442l84.764-369.144-363.672 112.108 278.908 257.032zM602.24 552.678l-101.172 109.376 248.828-76.564-147.656-32.812zM550.284 522.598l-308.984-289.844-147.656 161.328 308.984 289.844 147.656-161.328zM257.708 153.458l404.688-123.048-62.892-207.812-404.688 123.048 62.892 207.812zM725.288 24.942l147.656 32.812-188.672-177.736 41.016 144.924zM938.568 137.050l-213.284-49.22-95.704 412.892 213.284 49.22 95.704-412.892zM104.58 292.91l101.172-109.376-43.752-142.188-57.424 251.564z" />
|
||||
<glyph unicode="" glyph-name="clock" d="M512 768c-281.6 0-512-230.4-512-512s230.4-512 512-512 512 230.4 512 512-230.4 512-512 512zM512-179.2c-240.64 0-435.2 194.56-435.2 435.2s194.56 435.2 435.2 435.2 435.2-194.56 435.2-435.2-194.56-435.2-435.2-435.2zM742.4 268.8h-217.6v217.6c0 20.48-17.92 38.4-38.4 38.4s-38.4-17.92-38.4-38.4v-256c0-20.48 17.92-38.4 38.4-38.4h256c20.48 0 38.4 17.92 38.4 38.4s-17.92 38.4-38.4 38.4z" />
|
||||
<glyph unicode="" glyph-name="download" d="M985.6-256h-947.2c-20.48 0-38.4 17.92-38.4 38.4v307.2c0 20.48 17.92 38.4 38.4 38.4s38.4-17.92 38.4-38.4v-268.8h870.4v268.8c0 20.48 17.92 38.4 38.4 38.4s38.4-17.92 38.4-38.4v-307.2c0-20.48-17.92-38.4-38.4-38.4zM512-71.68c-10.24 0-23.040 5.12-30.72 12.8l-337.92 412.16c-10.24 10.24-10.24 28.16-5.12 40.96s20.48 23.040 35.84 23.040h145.92v312.32c0 20.48 17.92 38.4 38.4 38.4h307.2c20.48 0 38.4-17.92 38.4-38.4v-312.32h145.92c15.36 0 28.16-7.68 35.84-23.040 5.12-12.8 5.12-28.16-5.12-40.96l-337.92-412.16c-7.68-7.68-20.48-12.8-30.72-12.8zM256 337.92l256-312.32 256 312.32h-102.4c-20.48 0-38.4 17.92-38.4 38.4v314.88h-230.4v-312.32c0-20.48-17.92-38.4-38.4-38.4h-102.4z" />
|
||||
<glyph unicode="" glyph-name="clock" d="M512 768c-281.6 0-512-230.4-512-512s230.4-512 512-512 512 230.4 512 512-230.4 512-512 512zM768 179.2h-281.6c-28.16 0-51.2 23.040-51.2 51.2v281.6c0 28.16 23.040 51.2 51.2 51.2s51.2-23.040 51.2-51.2v-230.4h230.4c28.16 0 51.2-23.040 51.2-51.2s-23.040-51.2-51.2-51.2z" />
|
||||
<glyph unicode="" glyph-name="download" d="M407.040 235.52h-125.44c-35.84 0-56.32-46.080-28.16-71.68l258.56-258.56 261.12 261.12c28.16 28.16 7.68 71.68-28.16 71.68l-128-2.56-5.12 430.080c0 58.88-46.080 102.4-102.4 102.4-58.88 0-102.4-46.080-102.4-102.4v-430.080zM908.8 0v-51.2c0-48.64-40.96-89.6-89.6-89.6h-614.4c-48.64 0-89.6 40.96-89.6 89.6v51.2c0 20.48-17.92 38.4-38.4 38.4s-38.4-17.92-38.4-38.4v-51.2c0-92.16 74.24-166.4 166.4-166.4h614.4c92.16 0 166.4 74.24 166.4 166.4v51.2c0 20.48-17.92 38.4-38.4 38.4v0c-20.48 0-38.4-17.92-38.4-38.4z" />
|
||||
<glyph unicode="" glyph-name="dash-f" d="M320 345.6c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2zM320 678.4c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2zM601.6 448c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2zM652.8 345.6c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2zM89.6 64c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2zM422.4 64c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2zM755.2 729.6c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2zM704 166.4c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2zM704-166.4c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2z" />
|
||||
<glyph unicode="" glyph-name="dash-h" d="M320 512c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2zM89.6 230.4c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2zM422.4 230.4c-28.16 0-51.2-23.040-51.2-51.2v-179.2c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2zM371.2 332.8c0-28.16 23.040-51.2 51.2-51.2h512c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-512c-28.16 0-51.2-23.040-51.2-51.2v-179.2zM704 0c0-28.16 23.040-51.2 51.2-51.2h179.2c28.16 0 51.2 23.040 51.2 51.2v179.2c0 28.16-23.040 51.2-51.2 51.2h-179.2c-28.16 0-51.2-23.040-51.2-51.2v-179.2z" />
|
||||
<glyph unicode="" glyph-name="triangle" d="M832-153.6h-640c-53.76 0-97.28 20.48-120.32 58.88-20.48 35.84-17.92 84.48 10.24 133.12l320 552.96c28.16 46.080 66.56 74.24 110.080 74.24s81.92-28.16 110.080-74.24l320-552.96c28.16-46.080 30.72-94.72 10.24-133.12-23.040-35.84-66.56-58.88-120.32-58.88zM512 588.8c-15.36 0-30.72-12.8-43.52-35.84l-320-552.96c-12.8-23.040-15.36-43.52-10.24-56.32 7.68-12.8 25.6-20.48 53.76-20.48h640c25.6 0 46.080 7.68 53.76 20.48s5.12 33.28-10.24 56.32l-320 552.96c-12.8 23.040-28.16 35.84-43.52 35.84z" />
|
||||
<glyph unicode="" glyph-name="octagon" d="M686.080-204.8h-350.72c-10.24 0-20.48 5.12-28.16 10.24l-248.32 248.32c-7.68 7.68-10.24 17.92-10.24 28.16v350.72c0 10.24 5.12 20.48 10.24 28.16l248.32 248.32c7.68 7.68 17.92 10.24 28.16 10.24h350.72c10.24 0 20.48-5.12 28.16-10.24l248.32-248.32c7.68-7.68 10.24-17.92 10.24-28.16v-350.72c0-10.24-5.12-20.48-10.24-28.16l-248.32-248.32c-7.68-5.12-17.92-10.24-28.16-10.24zM353.28-128h317.44l225.28 225.28v317.44l-225.28 225.28h-317.44l-225.28-225.28v-317.44l225.28-225.28z" />
|
||||
<glyph unicode="" glyph-name="cube" horiz-adv-x="896" d="M417.28 295.68c17.92-10.24 40.96-10.24 58.88 0l348.16 202.24c7.68 5.12 7.68 15.36 0 20.48l-343.040 197.12c-23.040 12.8-51.2 12.8-74.24 0l-343.040-197.12c-7.68-5.12-7.68-15.36 0-20.48l353.28-202.24zM422.4 200.96c0 20.48-10.24 40.96-30.72 51.2l-348.16 202.24c-7.68 5.12-17.92 0-17.92-10.24v-394.24c0-25.6 12.8-51.2 35.84-64l343.040-197.12c7.68-5.12 17.92 0 17.92 10.24v401.92zM504.32 252.16c-17.92-10.24-30.72-30.72-30.72-51.2v-401.92c0-7.68 10.24-15.36 17.92-10.24l343.040 197.12c23.040 12.8 35.84 38.4 35.84 64v394.24c0 7.68-10.24 15.36-17.92 10.24l-348.16-202.24z" />
|
||||
<glyph unicode="" glyph-name="pulse-c" d="M399.36 202.24v104.96c0 7.68 5.12 15.36 10.24 20.48l92.16 53.76c7.68 5.12 15.36 5.12 23.040 0l92.16-53.76c7.68-5.12 10.24-12.8 10.24-20.48v-104.96c0-7.68-5.12-15.36-10.24-20.48l-92.16-53.76c-7.68-5.12-15.36-5.12-23.040 0l-92.16 53.76c-7.68 5.12-10.24 12.8-10.24 20.48zM732.16 186.88v69.12c0 15.36-12.8 28.16-28.16 25.6v0c-12.8-2.56-23.040-12.8-23.040-25.6v-69.12c0-17.92-10.24-33.28-23.040-40.96l-58.88-33.28c-10.24-5.12-15.36-20.48-10.24-30.72v0c5.12-15.36 23.040-20.48 35.84-12.8l58.88 33.28c30.72 15.36 48.64 48.64 48.64 84.48zM460.8 614.4l-128-74.24c-12.8-7.68-17.92-25.6-7.68-38.4v0c7.68-10.24 23.040-12.8 33.28-7.68l128 74.24c7.68 5.12 17.92 7.68 25.6 7.68 10.24 0 17.92-2.56 25.6-7.68l128-74.24c10.24-5.12 25.6-2.56 33.28 7.68v0c10.24 12.8 5.12 30.72-7.68 38.4l-128 74.24c-30.72 17.92-71.68 17.92-102.4 0zM340.48 99.84l58.88-33.28c12.8-7.68 30.72-2.56 35.84 12.8v0c5.12 12.8 0 25.6-10.24 30.72l-58.88 33.28c-15.36 7.68-23.040 25.6-23.040 40.96v69.12c0 12.8-10.24 23.040-23.040 25.6v0c-15.36 2.56-28.16-10.24-28.16-25.6v-69.12c0-33.28 17.92-66.56 48.64-84.48zM463.36 481.28l-58.88-33.28c-12.8-7.68-17.92-25.6-7.68-38.4v0c7.68-10.24 23.040-12.8 33.28-7.68l71.68 40.96c2.56 2.56 7.68 2.56 12.8 2.56s7.68 0 12.8-2.56l71.68-40.96c10.24-5.12 25.6-2.56 33.28 7.68v0c10.24 12.8 5.12 30.72-7.68 38.4l-58.88 33.28c-35.84 17.92-71.68 17.92-102.4 0zM286.72 588.8l163.84 94.72c38.4 23.040 87.040 23.040 125.44 0l163.84-94.72c10.24-5.12 25.6-2.56 33.28 7.68v0c10.24 12.8 5.12 30.72-7.68 38.4l-176.64 102.4c-46.080 28.16-104.96 28.16-151.040 0l-176.64-102.4c-12.8-7.68-17.92-25.6-7.68-38.4v0c7.68-10.24 23.040-12.8 33.28-7.68zM913.92 284.16v-186.88c0-43.52-23.040-87.040-61.44-107.52l-163.84-94.72c-10.24-5.12-15.36-20.48-10.24-30.72v0c5.12-15.36 23.040-20.48 35.84-12.8l163.84 94.72c53.76 30.72 87.040 89.6 87.040 153.6v186.88c0 15.36-12.8 28.16-28.16 25.6v0c-12.8-5.12-23.040-15.36-23.040-28.16zM240.64 25.6l115.2-66.56c12.8-7.68 30.72-2.56 35.84 12.8v0c5.12 12.8 0 25.6-10.24 30.72l-115.2 66.56c-23.040 12.8-38.4 38.4-38.4 66.56v133.12c0 12.8-10.24 23.040-23.040 25.6v0c-15.36 2.56-28.16-10.24-28.16-25.6v-133.12c0-46.080 25.6-87.040 64-110.080zM335.36-104.96l-163.84 94.72c-38.4 23.040-61.44 64-61.44 107.52v186.88c0 12.8-10.24 23.040-23.040 25.6v0c-15.36 2.56-28.16-10.24-28.16-25.6v-186.88c0-64 33.28-120.32 87.040-153.6l163.84-94.72c12.8-7.68 30.72-2.56 35.84 12.8v0c5.12 12.8 2.56 25.6-10.24 33.28zM847.36 135.68v133.12c0 15.36-12.8 28.16-28.16 25.6v0c-12.8-2.56-23.040-12.8-23.040-25.6v-133.12c0-28.16-15.36-53.76-38.4-66.56l-115.2-66.56c-10.24-5.12-15.36-20.48-10.24-30.72v0c5.12-15.36 23.040-20.48 35.84-12.8l115.2 66.56c38.4 23.040 64 64 64 110.080z" />
|
||||
<glyph unicode="" glyph-name="brush" d="M819.2 332.8v99.84c0 15.36-12.8 28.16-28.16 28.16h-133.12c-23.040 0-43.52 20.48-43.52 43.52v161.28c0 56.32-46.080 102.4-102.4 102.4s-102.4-46.080-102.4-102.4v-161.28c0-23.040-20.48-43.52-43.52-43.52h-133.12c-15.36 0-28.16-12.8-28.16-28.16v-99.84h614.4zM512 716.8c28.16 0 51.2-23.040 51.2-51.2s-23.040-51.2-51.2-51.2-51.2 23.040-51.2 51.2 23.040 51.2 51.2 51.2zM204.8 281.6v-537.6l76.8 76.8 76.8-76.8 76.8 76.8 76.8-76.8 76.8 76.8 76.8-76.8 76.8 76.8 76.8-76.8v537.6z" />
|
||||
<glyph unicode="" glyph-name="square" d="M819.2-166.4h-614.4c-64 0-115.2 51.2-115.2 115.2v614.4c0 64 51.2 115.2 115.2 115.2h614.4c64 0 115.2-51.2 115.2-115.2v-614.4c0-64-51.2-115.2-115.2-115.2zM204.8 601.6c-20.48 0-38.4-17.92-38.4-38.4v-614.4c0-20.48 17.92-38.4 38.4-38.4h614.4c20.48 0 38.4 17.92 38.4 38.4v614.4c0 20.48-17.92 38.4-38.4 38.4h-614.4z" />
|
||||
<glyph unicode="" glyph-name="circle" d="M512-140.8c-217.6 0-396.8 179.2-396.8 396.8s179.2 396.8 396.8 396.8 396.8-179.2 396.8-396.8-179.2-396.8-396.8-396.8zM512 576c-176.64 0-320-143.36-320-320s143.36-320 320-320 320 143.36 320 320-143.36 320-320 320z" />
|
||||
<glyph unicode="" glyph-name="export" d="M921.6-153.6c0-28.16-23.040-51.2-51.2-51.2h-768c-28.16 0-51.2 23.040-51.2 51.2v768c0 28.16 23.040 51.2 51.2 51.2h281.6c15.36 0 25.6 10.24 25.6 25.6v0c0 15.36-10.24 25.6-25.6 25.6h-281.6c-56.32 0-102.4-46.080-102.4-102.4v-768c0-56.32 46.080-102.4 102.4-102.4h768c56.32 0 102.4 46.080 102.4 102.4v281.6c0 15.36-10.24 25.6-25.6 25.6v0c-15.36 0-25.6-10.24-25.6-25.6v-281.6zM921.6 768h-384c-15.36 0-25.6-10.24-25.6-25.6v-102.4c0-15.36 10.24-25.6 25.6-25.6h225.28l-414.72-414.72c-10.24-10.24-10.24-25.6 0-35.84l71.68-71.68c10.24-10.24 25.6-10.24 35.84 0l414.72 414.72v-225.28c0-15.36 10.24-25.6 25.6-25.6h102.4c15.36 0 25.6 10.24 25.6 25.6v384c0 56.32-46.080 102.4-102.4 102.4z" />
|
||||
<glyph unicode="" glyph-name="expand-b" d="M947.2 665.6h-870.4c-43.52 0-76.8-33.28-76.8-76.8v-665.6c0-43.52 33.28-76.8 76.8-76.8h870.4c43.52 0 76.8 33.28 76.8 76.8v665.6c0 43.52-33.28 76.8-76.8 76.8zM307.2-64c0-7.68-5.12-12.8-12.8-12.8h-192c-15.36 0-25.6 10.24-25.6 25.6v192c0 7.68 5.12 12.8 12.8 12.8h51.2c7.68 0 12.8-5.12 12.8-12.8v-140.8h140.8c7.68 0 12.8-5.12 12.8-12.8v-51.2zM307.2 524.8c0-7.68-5.12-12.8-12.8-12.8h-140.8v-140.8c0-7.68-5.12-12.8-12.8-12.8h-51.2c-7.68 0-12.8 5.12-12.8 12.8v192c0 15.36 10.24 25.6 25.6 25.6h192c7.68 0 12.8-5.12 12.8-12.8v-51.2zM947.2-51.2c0-15.36-10.24-25.6-25.6-25.6h-192c-7.68 0-12.8 5.12-12.8 12.8v51.2c0 7.68 5.12 12.8 12.8 12.8h140.8v140.8c0 7.68 5.12 12.8 12.8 12.8h51.2c7.68 0 12.8-5.12 12.8-12.8v-192zM947.2 371.2c0-7.68-5.12-12.8-12.8-12.8h-51.2c-7.68 0-12.8 5.12-12.8 12.8v140.8h-140.8c-7.68 0-12.8 5.12-12.8 12.8v51.2c0 7.68 5.12 12.8 12.8 12.8h192c15.36 0 25.6-10.24 25.6-25.6v-192z" />
|
||||
<glyph unicode="" glyph-name="expand-a" d="M870.4 25.6c0-12.8-12.8-25.6-25.6-25.6h-665.6c-12.8 0-25.6 12.8-25.6 25.6v460.8c0 12.8 12.8 25.6 25.6 25.6h665.6c12.8 0 25.6-12.8 25.6-25.6v-460.8zM89.6 588.8h153.6c7.68 0 12.8 5.12 12.8 12.8v51.2c0 7.68-5.12 12.8-12.8 12.8h-166.4c-43.52 0-76.8-33.28-76.8-76.8v-166.4c0-7.68 5.12-12.8 12.8-12.8h51.2c7.68 0 12.8 5.12 12.8 12.8v153.6c0 7.68 5.12 12.8 12.8 12.8zM76.8-64v153.6c0 7.68-5.12 12.8-12.8 12.8h-51.2c-7.68 0-12.8-5.12-12.8-12.8v-166.4c0-43.52 33.28-76.8 76.8-76.8h166.4c7.68 0 12.8 5.12 12.8 12.8v51.2c0 7.68-5.12 12.8-12.8 12.8h-153.6c-7.68 0-12.8 5.12-12.8 12.8zM934.4-76.8h-153.6c-7.68 0-12.8-5.12-12.8-12.8v-51.2c0-7.68 5.12-12.8 12.8-12.8h166.4c43.52 0 76.8 33.28 76.8 76.8v166.4c0 7.68-5.12 12.8-12.8 12.8h-51.2c-7.68 0-12.8-5.12-12.8-12.8v-153.6c0-7.68-5.12-12.8-12.8-12.8zM947.2 576v-153.6c0-7.68 5.12-12.8 12.8-12.8h51.2c7.68 0 12.8 5.12 12.8 12.8v166.4c0 43.52-33.28 76.8-76.8 76.8h-166.4c-7.68 0-12.8-5.12-12.8-12.8v-51.2c0-7.68 5.12-12.8 12.8-12.8h153.6c7.68 0 12.8-5.12 12.8-12.8z" />
|
||||
<glyph unicode="" glyph-name="heroku" d="M819.2 768h-614.4c-43.52 0-76.8-33.28-76.8-76.8v-870.4c0-43.52 33.28-76.8 76.8-76.8h614.4c43.52 0 76.8 33.28 76.8 76.8v870.4c0 43.52-33.28 76.8-76.8 76.8zM399.36-2.56l-115.2-92.16c0 0-2.56-2.56-5.12-2.56 0 0-2.56 0-2.56 0-2.56 0-2.56 2.56-2.56 5.12v194.56c0 2.56 2.56 5.12 2.56 5.12 2.56 0 5.12 0 7.68 0l115.2-102.4c2.56 0 2.56-2.56 2.56-5.12 0 0 0-2.56-2.56-2.56zM750.080-89.6c0-2.56-2.56-5.12-5.12-5.12h-115.2c-2.56 0-5.12 2.56-5.12 5.12v268.8c0 23.040 0 43.52-15.36 56.32-12.8 10.24-35.84 12.8-71.68 7.68-46.080-7.68-97.28-20.48-143.36-33.28-2.56 0-5.12-2.56-7.68-2.56s-7.68-2.56-10.24-2.56c-2.56 0-5.12-2.56-7.68-2.56s-7.68-2.56-10.24-2.56c-2.56 0-5.12-2.56-7.68-2.56s-5.12-2.56-7.68-2.56c-2.56 0-5.12-2.56-7.68-2.56s-5.12-2.56-7.68-2.56c-2.56 0-5.12-2.56-7.68-2.56s-2.56-2.56-5.12-2.56-5.12-2.56-7.68-5.12c0 0-2.56 0-2.56-2.56-2.56-2.56-5.12-2.56-7.68-5.12 0 0-2.56 0-2.56 0-2.56-2.56-5.12-5.12-7.68-5.12 0 0-2.56 0-2.56 0s0 0 0 0 0 0 0 0-2.56 0-2.56 0c0 0 0 0 0 0s0 0 0 0 0 0 0 0 0 2.56 0 2.56c0 0 0 0 0 2.56 0 0 0 0 0 0v432.64c0 2.56 2.56 5.12 5.12 5.12h115.2c2.56 0 5.12-2.56 5.12-5.12v-261.12c58.88 17.92 138.24 33.28 212.48 23.040 81.92-10.24 135.68-48.64 135.68-189.44v-266.24zM668.16 435.2c0-2.56-2.56-2.56-5.12-2.56h-115.2c-2.56 0-5.12 2.56-5.12 2.56s0 5.12 0 7.68c28.16 38.4 79.36 107.52 79.36 158.72 0 2.56 2.56 5.12 5.12 5.12h115.2c2.56 0 5.12-2.56 5.12-5.12 2.56-53.76-51.2-125.44-79.36-166.4z" />
|
||||
<glyph unicode="" glyph-name="heroku-simple" d="M348.16-120.32l-166.4-133.12c-2.56-2.56-2.56-2.56-5.12-2.56s-2.56 0-5.12 0c-2.56 2.56-5.12 5.12-5.12 7.68v281.6c0 2.56 2.56 7.68 5.12 7.68 2.56 2.56 7.68 0 10.24-2.56l166.4-148.48c2.56-2.56 2.56-5.12 2.56-7.68 2.56 0 0-2.56-2.56-2.56zM857.6-245.76c0-5.12-5.12-10.24-10.24-10.24h-166.4c-5.12 0-10.24 5.12-10.24 10.24v391.68c0 30.72 0 64-20.48 81.92-17.92 15.36-53.76 20.48-102.4 12.8-66.56-10.24-140.8-28.16-207.36-48.64-5.12 0-7.68-2.56-10.24-2.56-5.12-2.56-10.24-2.56-15.36-5.12-2.56 0-7.68-2.56-10.24-2.56-5.12-2.56-10.24-2.56-12.8-5.12-2.56 0-7.68-2.56-10.24-2.56-5.12-2.56-7.68-2.56-12.8-5.12-2.56-2.56-7.68-2.56-10.24-5.12s-7.68-2.56-10.24-5.12c-5.12-2.56-7.68-2.56-12.8-5.12-2.56 0-5.12-2.56-7.68-2.56-5.12-2.56-7.68-5.12-12.8-7.68-2.56 0-2.56-2.56-5.12-2.56-5.12-2.56-7.68-5.12-12.8-7.68 0 0-2.56 0-2.56-2.56-5.12-2.56-7.68-5.12-12.8-7.68-2.56 0-2.56-2.56-5.12-2.56 0 0 0 0 0 0s0 0 0 0-2.56 0-2.56 0c0 0 0 0 0 0s0 0 0 0 0 0 0 0-2.56 2.56-2.56 2.56c0 0 0 0 0 2.56 0 0 0 0 0 0v629.76c0 5.12 5.12 10.24 10.24 10.24h166.4c5.12 0 10.24-5.12 10.24-10.24v-378.88c87.040 25.6 202.24 48.64 307.2 33.28 117.76-15.36 197.12-69.12 197.12-276.48v-378.88zM739.84 517.12c-2.56-2.56-5.12-5.12-7.68-5.12h-166.4c-2.56 0-7.68 2.56-7.68 5.12s-2.56 7.68 0 10.24c40.96 56.32 115.2 158.72 115.2 230.4 0 5.12 5.12 10.24 10.24 10.24h166.4c5.12 0 10.24-5.12 10.24-10.24-2.56-76.8-79.36-181.76-120.32-240.64z" />
|
||||
<glyph unicode="" glyph-name="refresh" d="M417.28 442.88l-261.12 28.16c-15.36 2.56-25.6 15.36-25.6 30.72l28.16 261.12c0 7.68 10.24 10.24 17.92 5.12l248.32-307.2c5.12-10.24 0-20.48-7.68-17.92zM865.28-248.32l28.16 261.12c2.56 15.36-10.24 28.16-25.6 30.72l-261.12 28.16c-7.68 0-12.8-7.68-7.68-15.36l248.32-307.2c5.12-7.68 15.36-5.12 17.92 2.56zM834.56 578.56c-87.040 87.040-202.24 133.12-322.56 133.12-110.080 0-217.6-40.96-302.080-112.64l-10.24-10.24 58.88-58.88 10.24 7.68c84.48 74.24 199.68 104.96 314.88 81.92 51.2-10.24 99.84-30.72 143.36-61.44 130.56-94.72 186.88-253.44 145.92-404.48-5.12-20.48 5.12-43.52 23.040-51.2 5.12-2.56 10.24-2.56 17.92-2.56 5.12 0 12.8 2.56 17.92 5.12 10.24 5.12 20.48 15.36 23.040 28.16 43.52 161.28-2.56 327.68-120.32 445.44zM755.2-28.16c-84.48-74.24-199.68-104.96-314.88-81.92-51.2 10.24-99.84 30.72-143.36 61.44-130.56 94.72-186.88 250.88-145.92 404.48 5.12 20.48-5.12 43.52-23.040 51.2-10.24 5.12-23.040 5.12-35.84 0-10.24-5.12-17.92-15.36-20.48-25.6-46.080-161.28-2.56-327.68 117.76-445.44 87.040-87.040 202.24-133.12 322.56-133.12 110.080 0 217.6 40.96 302.080 112.64l10.24 10.24-58.88 58.88-10.24-12.8z" />
|
||||
<glyph unicode="" glyph-name="refresh" d="M829.44 2.56l-225.28 23.040c-7.68 0-10.24-7.68-7.68-12.8l69.12-84.48c-69.12-33.28-145.92-43.52-222.72-25.6-51.2 10.24-97.28 30.72-138.24 58.88-128 92.16-181.76 240.64-140.8 391.68 7.68 25.6-7.68 56.32-30.72 66.56-12.8 7.68-30.72 7.68-46.080 0-12.8-7.68-23.040-20.48-28.16-33.28-46.080-168.96-2.56-337.92 120.32-460.8 87.040-87.040 204.8-135.68 332.8-135.68 76.8 0 153.6 20.48 222.72 56.32l79.36-97.28c5.12-7.68 12.8-5.12 15.36 2.56l23.040 225.28c2.56 12.8-7.68 23.040-23.040 25.6zM844.8 588.8c-87.040 87.040-204.8 135.68-332.8 135.68-76.8 0-153.6-20.48-222.72-56.32l-79.36 97.28c-5.12 5.12-15.36 2.56-15.36-5.12l-23.040-225.28c0-12.8 7.68-23.040 23.040-25.6l225.28-23.040c7.68-2.56 10.24 7.68 7.68 15.36l-66.56 81.92c66.56 30.72 143.36 40.96 220.16 25.6 51.2-10.24 97.28-30.72 138.24-58.88 125.44-92.16 181.76-243.2 140.8-391.68-7.68-25.6 7.68-56.32 30.72-66.56 7.68-5.12 15.36-5.12 23.040-5.12s17.92 2.56 23.040 7.68c12.8 5.12 25.6 17.92 30.72 35.84 43.52 163.84-2.56 335.36-122.88 458.24z" />
|
||||
<glyph unicode="" glyph-name="pause" d="M435.2-115.2c0-20.48-17.92-38.4-38.4-38.4h-153.6c-20.48 0-38.4 17.92-38.4 38.4v742.4c0 20.48 17.92 38.4 38.4 38.4h153.6c20.48 0 38.4-17.92 38.4-38.4v-742.4zM819.2-115.2c0-20.48-17.92-38.4-38.4-38.4h-153.6c-20.48 0-38.4 17.92-38.4 38.4v742.4c0 20.48 17.92 38.4 38.4 38.4h153.6c20.48 0 38.4-17.92 38.4-38.4v-742.4z" />
|
||||
<glyph unicode="" glyph-name="crown2" d="M882.4-64.4l135.2 523.4c2.2 8.4-7 15.2-14.4 10.4l-262.4-168.2c-10.4-6.6-24.2-3.8-31.2 6.4l-189.8 276.4c-3.8 5.6-12 5.6-15.8 0l-189.6-276.6c-7-10.2-20.8-13-31.2-6.4l-262.4 168.2c-7.4 4.6-16.6-2-14.4-10.4l135.2-523.4c2.8-11 12.8-18.8 24.2-18.8h692.6c11.2 0.2 21.2 8 24 19z" />
|
||||
<glyph unicode="" glyph-name="server2" d="M992.4 729.2h-960.8c-10.2 0-20.4-10.2-20.4-20.4v-203.8c0-10.2 10.2-20.4 20.4-20.4h960.6c10.2 0 20.4 10.2 20.4 20.4v203.8c0.2 10.2-10 20.4-20.2 20.4zM241.6 556.4c0-7.4-6-13.6-13.6-13.6h-101c-7.4 0-13.6 6-13.6 13.6v101c0 7.4 6 13.6 13.6 13.6h101c7.4 0 13.6-6 13.6-13.6v-101zM992.4 378.4h-960.8c-10.2 0-20.4-10.2-20.4-20.4v-204c0-10.2 10.2-20.4 20.4-20.4h960.6c10.2 0 20.4 10.2 20.4 20.4v204c0.2 10.2-10 20.4-20.2 20.4zM241.6 205.6c0-7.4-6-13.6-13.6-13.6h-101c-7.4 0-13.6 6-13.6 13.6v100.8c0 7.4 6 13.6 13.6 13.6h101c7.4 0 13.6-6 13.6-13.6v-100.8zM992.4 47.6h-960.8c-10.2 0-20.4-10.2-20.4-20.4v-203.8c0-10.2 10.2-20.4 20.4-20.4h960.6c10.2 0 20.4 10.2 20.4 20.4v203.8c0.2 10.2-10 20.4-20.2 20.4zM241.6-125.2c0-7.4-6-13.6-13.6-13.6h-101c-7.4 0-13.6 6-13.6 13.6v101c0 7.4 6 13.6 13.6 13.6h101c7.4 0 13.6-6 13.6-13.6v-101z" />
|
||||
|
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -30,19 +30,8 @@
|
|||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
|
||||
&.collapse:before {content: "\e90f";}
|
||||
&.okta:before {content: "\e912";}
|
||||
&.user-remove:before {content: "\e904";}
|
||||
&.user-add:before {content: "\e907";}
|
||||
&.group:before {content: "\e908";}
|
||||
&.user:before {content: "\e90d";}
|
||||
&.eye-closed:before {content: "\e956";}
|
||||
&.eye-open:before {content: "\e957";}
|
||||
&.arrow-down:before {content: "\e910";}
|
||||
&.arrow-left:before {content: "\e90c";}
|
||||
&.arrow-right:before {content: "\e911";}
|
||||
&.arrow-up:before {content: "\e90b";}
|
||||
&.authzero:before {content: "\e951";}
|
||||
&.bar-chart:before {content: "\e913";}
|
||||
&.brush:before {content: "\e939";}
|
||||
&.caret-down:before {content: "\e902";}
|
||||
&.caret-left:before {content: "\e900";}
|
||||
|
@ -52,8 +41,9 @@
|
|||
&.circle:before {content: "\e940";}
|
||||
&.clock:before {content: "\e91b";}
|
||||
&.cog-thick:before {content: "\e906";}
|
||||
&.collapse:before {content: "\e90f";}
|
||||
&.crown2:before {content: "\e94b";}
|
||||
&.cube:before {content: "\e92e";}
|
||||
&.cube:before {content: "\e90b";}
|
||||
&.cubo-node:before {content: "\e919";}
|
||||
&.cubo-uniform:before {content: "\e91a";}
|
||||
&.dash-f:before {content: "\e927";}
|
||||
|
@ -63,12 +53,17 @@
|
|||
&.duplicate:before {content: "\e917";}
|
||||
&.expand-a:before {content: "\e944";}
|
||||
&.expand-b:before {content: "\e942";}
|
||||
&.export:before {content: "\e941";}
|
||||
&.export:before {content: "\e90c";}
|
||||
&.eye-closed:before {content: "\e956";}
|
||||
&.eye-open:before {content: "\e957";}
|
||||
&.graphline:before {content: "\e90e";}
|
||||
&.group:before {content: "\e908";}
|
||||
&.heroku:before {content: "\e947";}
|
||||
&.heroku-simple:before {content: "\e948";}
|
||||
&.import:before {content: "\e910";}
|
||||
&.oauth:before {content: "\e94f";}
|
||||
&.octagon:before {content: "\e92d";}
|
||||
&.okta:before {content: "\e912";}
|
||||
&.pause:before {content: "\e94a";}
|
||||
&.plus:before {content: "\e90a";}
|
||||
&.pulse-c:before {content: "\e936";}
|
||||
|
@ -78,8 +73,12 @@
|
|||
&.server2:before {content: "\e94c";}
|
||||
&.shuffle:before {content: "\e94e";}
|
||||
&.square:before {content: "\e93e";}
|
||||
&.text-block:before {content: "\e911";}
|
||||
&.trash:before {content: "\e905";}
|
||||
&.triangle:before {content: "\e92c";}
|
||||
&.user:before {content: "\e90d";}
|
||||
&.user-add:before {content: "\e907";}
|
||||
&.user-remove:before {content: "\e904";}
|
||||
&.alert-triangle:before {content: "\f02d";}
|
||||
&.link:before {content: "\f05c";}
|
||||
&.pencil:before {content: "\f058";}
|
||||
|
|
|
@ -30,7 +30,7 @@ $dash-ceo-z: $dygraph-legend-z + 10;
|
|||
|
||||
&:only-child {
|
||||
top: 0;
|
||||
height: 100%;
|
||||
height: 100% !important;
|
||||
}
|
||||
}
|
||||
.page-contents--split {
|
||||
|
|
|
@ -45,9 +45,12 @@ interface CellLinks {
|
|||
self: string
|
||||
}
|
||||
|
||||
// corresponds to DashboardQuery on the backend
|
||||
export interface CellQuery {
|
||||
query: string
|
||||
queryConfig: QueryConfig
|
||||
source: string
|
||||
text?: string // doesn't come from server
|
||||
}
|
||||
|
||||
export interface Legend {
|
||||
|
|
|
@ -3,6 +3,7 @@ import {AuthLinks, Organization, Role, User, Me} from './auth'
|
|||
import {Template, Cell, CellQuery, Legend, Axes} from './dashboard'
|
||||
import {
|
||||
GroupBy,
|
||||
Query,
|
||||
QueryConfig,
|
||||
Status,
|
||||
TimeRange,
|
||||
|
@ -32,6 +33,7 @@ export {
|
|||
CellQuery,
|
||||
Legend,
|
||||
Status,
|
||||
Query,
|
||||
QueryConfig,
|
||||
TimeShift,
|
||||
ApplyFuncsToFieldArgs,
|
||||
|
|
|
@ -7,6 +7,7 @@ export interface LocalStorage {
|
|||
dataExplorer: DataExplorer
|
||||
dataExplorerQueryConfigs: DataExplorerQueryConfigs
|
||||
timeRange: TimeRange
|
||||
script: string
|
||||
}
|
||||
|
||||
export type VERSION = string
|
||||
|
|
|
@ -1,3 +1,12 @@
|
|||
import {Source} from 'src/types'
|
||||
|
||||
export interface Query {
|
||||
host: string[] // doesn't come from server - is set in buildQueriesForGraphs
|
||||
text: string
|
||||
id: string
|
||||
queryConfig: QueryConfig
|
||||
}
|
||||
|
||||
export interface QueryConfig {
|
||||
id?: string
|
||||
database?: string
|
||||
|
@ -9,7 +18,7 @@ export interface QueryConfig {
|
|||
areTagsAccepted: boolean
|
||||
rawText?: string
|
||||
range?: DurationRange | null
|
||||
sourceLink?: string
|
||||
source?: Source | null // doesn't come from server -- is set in CellEditorOverlay
|
||||
fill?: string
|
||||
status?: Status
|
||||
shifts?: TimeShift[]
|
||||
|
|
|
@ -10,6 +10,7 @@ export interface NewService {
|
|||
|
||||
export interface Service {
|
||||
id?: string
|
||||
sourceID: string
|
||||
url: string
|
||||
name: string
|
||||
type: string
|
||||
|
@ -17,6 +18,9 @@ export interface Service {
|
|||
password?: string
|
||||
active: boolean
|
||||
insecureSkipVerify: boolean
|
||||
metadata: {
|
||||
[x: string]: any
|
||||
}
|
||||
links: {
|
||||
source: string
|
||||
self: string
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface Source {
|
|||
defaultRP: string
|
||||
links: SourceLinks
|
||||
kapacitors?: Kapacitor[] // this field does not exist on the server type for Source and is added in the client in the reducer for loading kapacitors.
|
||||
text?: string // added client-side for dropdowns
|
||||
services?: Service[]
|
||||
}
|
||||
|
||||
|
|
|
@ -1,45 +0,0 @@
|
|||
import _ from 'lodash'
|
||||
import {buildQuery} from 'utils/influxql'
|
||||
import {TYPE_QUERY_CONFIG, TYPE_SHIFTED} from 'src/dashboards/constants'
|
||||
|
||||
const buildQueries = (proxy, queryConfigs, tR) => {
|
||||
const statements = queryConfigs.map(query => {
|
||||
const {rawText, range, id, shifts, database, measurement, fields} = query
|
||||
const timeRange = range || tR
|
||||
const text = rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, query)
|
||||
const isParsable = database && measurement && fields.length
|
||||
|
||||
if (shifts && shifts.length && isParsable) {
|
||||
const shiftedQueries = shifts
|
||||
.filter(s => s.unit)
|
||||
.map(s => buildQuery(TYPE_SHIFTED, timeRange, query, s))
|
||||
|
||||
return {
|
||||
text: `${text};${shiftedQueries.join(';')}`,
|
||||
id,
|
||||
queryConfig: query,
|
||||
}
|
||||
}
|
||||
|
||||
return {text, id, queryConfig: query}
|
||||
})
|
||||
|
||||
const queries = statements
|
||||
.filter(s => s.text !== null)
|
||||
.map(({queryConfig, text, id}) => {
|
||||
const queryProxy = _.get(queryConfig, 'source.links.proxy', '')
|
||||
|
||||
const host = [queryProxy || proxy]
|
||||
|
||||
return {
|
||||
host,
|
||||
text,
|
||||
id,
|
||||
queryConfig,
|
||||
}
|
||||
})
|
||||
|
||||
return queries
|
||||
}
|
||||
|
||||
export default buildQueries
|
|
@ -0,0 +1,59 @@
|
|||
import _ from 'lodash'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
import {buildQuery} from 'src/utils/influxql'
|
||||
import {TYPE_QUERY_CONFIG, TYPE_SHIFTED} from 'src/dashboards/constants'
|
||||
|
||||
import {Query, QueryConfig, TimeRange} from 'src/types'
|
||||
|
||||
interface Statement {
|
||||
queryConfig: QueryConfig
|
||||
id: string
|
||||
text: string
|
||||
}
|
||||
|
||||
const buildQueries = (
|
||||
proxy: string,
|
||||
queryConfigs: QueryConfig[],
|
||||
tR: TimeRange
|
||||
): Query[] => {
|
||||
const statements: Statement[] = queryConfigs.map((query: QueryConfig) => {
|
||||
const {rawText, range, id, shifts, database, measurement, fields} = query
|
||||
const timeRange: TimeRange = range || tR
|
||||
const text: string =
|
||||
rawText || buildQuery(TYPE_QUERY_CONFIG, timeRange, query)
|
||||
const isParsable: boolean =
|
||||
!_.isEmpty(database) && !_.isEmpty(measurement) && fields.length > 0
|
||||
|
||||
if (shifts && shifts.length && isParsable) {
|
||||
const shiftedQueries: string[] = shifts
|
||||
.filter(s => s.unit)
|
||||
.map(s => buildQuery(TYPE_SHIFTED, timeRange, query, s))
|
||||
|
||||
return {
|
||||
text: `${text};${shiftedQueries.join(';')}`,
|
||||
id,
|
||||
queryConfig: query,
|
||||
}
|
||||
}
|
||||
|
||||
return {text, id, queryConfig: query}
|
||||
})
|
||||
|
||||
const queries: Query[] = statements
|
||||
.filter(s => s.text !== null)
|
||||
.map(({queryConfig, text, id}) => {
|
||||
const queryProxy = getDeep<string>(queryConfig, 'source.links.proxy', '')
|
||||
const host: string[] = [queryProxy || proxy]
|
||||
|
||||
return {
|
||||
host,
|
||||
text,
|
||||
id,
|
||||
queryConfig,
|
||||
}
|
||||
})
|
||||
|
||||
return queries
|
||||
}
|
||||
|
||||
export default buildQueries
|
|
@ -16,7 +16,7 @@ import {
|
|||
TimeSeriesSuccessfulResult,
|
||||
TimeSeries,
|
||||
} from 'src/types/series'
|
||||
import {get} from 'src/utils/wrappers'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
interface Result {
|
||||
series: TimeSeriesSeries[]
|
||||
|
@ -60,7 +60,7 @@ const flattenGroupBySeries = (
|
|||
}
|
||||
|
||||
const tagsKeys = _.keys(tags)
|
||||
const seriesArray = get<TimeSeriesSeries[]>(results, '[0].series', [])
|
||||
const seriesArray = getDeep<TimeSeriesSeries[]>(results, '[0].series', [])
|
||||
|
||||
const accumulatedValues = fastReduce<TimeSeriesSeries, TimeSeriesValue[][]>(
|
||||
seriesArray,
|
||||
|
@ -76,7 +76,7 @@ const flattenGroupBySeries = (
|
|||
},
|
||||
[]
|
||||
)
|
||||
const firstColumns = get<string[]>(results, '[0].series[0]columns', [])
|
||||
const firstColumns = getDeep<string[]>(results, '[0].series[0]columns', [])
|
||||
|
||||
const flattenedSeries: Result[] = [
|
||||
{
|
||||
|
@ -102,7 +102,11 @@ const constructResults = (
|
|||
const MappedResponse = fastMap<TimeSeriesServerResponse, Result[]>(
|
||||
raw,
|
||||
(response, index) => {
|
||||
const results = get<TimeSeriesResult[]>(response, 'response.results', [])
|
||||
const results = getDeep<TimeSeriesResult[]>(
|
||||
response,
|
||||
'response.results',
|
||||
[]
|
||||
)
|
||||
|
||||
const successfulResults = results.filter(
|
||||
r => 'series' in r && !('error' in r)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import _ from 'lodash'
|
||||
|
||||
export function get<T = any>(obj: any, path: string, fallack: T): T {
|
||||
return _.get<T>(obj, path, fallack)
|
||||
export function getDeep<T = any>(obj: any, path: string, fallback: T): T {
|
||||
return _.get<T>(obj, path, fallback)
|
||||
}
|
||||
|
|
|
@ -91,6 +91,7 @@ export const query: CellQuery = {
|
|||
query:
|
||||
'SELECT mean("usage_idle") AS "mean_usage_idle", mean("usage_user") AS "mean_usage_user" FROM "telegraf"."autogen"."cpu" WHERE time > :dashboardTime: GROUP BY time(:interval:) FILL(null)',
|
||||
queryConfig,
|
||||
source: '',
|
||||
}
|
||||
|
||||
export const axes: Axes = {
|
||||
|
|
|
@ -3,6 +3,7 @@ import {shallow} from 'enzyme'
|
|||
|
||||
import {IFQLPage} from 'src/ifql/containers/IFQLPage'
|
||||
import TimeMachine from 'src/ifql/components/TimeMachine'
|
||||
import {ActionTypes} from 'src/ifql/actions'
|
||||
|
||||
jest.mock('src/ifql/apis', () => require('mocks/ifql/apis'))
|
||||
|
||||
|
@ -15,7 +16,19 @@ const setup = () => {
|
|||
},
|
||||
services: [],
|
||||
sources: [],
|
||||
script: '',
|
||||
notify: () => {},
|
||||
params: {
|
||||
sourceID: '',
|
||||
},
|
||||
updateScript: (script: string) => {
|
||||
return {
|
||||
type: ActionTypes.UpdateScript,
|
||||
payload: {
|
||||
script,
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
const wrapper = shallow(<IFQLPage {...props} />)
|
||||
|
|
|
@ -96,6 +96,7 @@ export const kapacitor = {
|
|||
|
||||
export const service = {
|
||||
id: '1',
|
||||
sourceID: '1',
|
||||
url: 'localhost:8082',
|
||||
type: 'ifql',
|
||||
name: 'IFQL',
|
||||
|
@ -108,6 +109,7 @@ export const service = {
|
|||
proxy: '/chronograf/v1/sources/1/services/2/proxy',
|
||||
self: '/chronograf/v1/sources/1/services/2',
|
||||
},
|
||||
metadata: {},
|
||||
}
|
||||
|
||||
export const kapacitorRules = [
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
import {get} from 'src/utils/wrappers'
|
||||
import {getDeep} from 'src/utils/wrappers'
|
||||
|
||||
describe('utils.wrappers', () => {
|
||||
describe('get', () => {
|
||||
it('gets a nested value', () => {
|
||||
const example = {a: {b: 'hello'}}
|
||||
|
||||
expect(get(example, 'a.b', 'default')).toEqual('hello')
|
||||
expect(getDeep(example, 'a.b', 'default')).toEqual('hello')
|
||||
})
|
||||
|
||||
it('gets the default value when key is empty', () => {
|
||||
const example = {a: {b: 'hello'}}
|
||||
|
||||
expect(get(example, 'a.c', 'default')).toEqual('default')
|
||||
expect(getDeep(example, 'a.c', 'default')).toEqual('default')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
Loading…
Reference in New Issue