Merge branch 'master' into bugfix/basepath-logout
commit
625b2f8c3f
|
@ -14,6 +14,8 @@
|
|||
### Bug Fixes
|
||||
|
||||
1. [#3252](https://github.com/influxdata/chronograf/pull/3252): Allows users to select tickscript editor with mouse
|
||||
1. [#3279](https://github.com/influxdata/chronograf/pull/3279): Change color when value is equal to or greater than threshold value
|
||||
1. [#3281](https://github.com/influxdata/chronograf/pull/3281): Fix base path for kapacitor logs
|
||||
1. [#3284](https://github.com/influxdata/chronograf/pull/3284): Fix logout when using basepath & simplify basepath usage (deprecates `PREFIX_ROUTES`)
|
||||
|
||||
## v1.4.4.1 [2018-04-16]
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import React, {ReactElement, Component} from 'react'
|
||||
import _ from 'lodash'
|
||||
import PropTypes from 'prop-types'
|
||||
import {withRouter, InjectedRouter} from 'react-router'
|
||||
import {Location} from 'history'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
import {ErrorHandling} from 'src/shared/decorators/errors'
|
||||
|
||||
import {
|
||||
isUserAuthorized,
|
||||
|
@ -52,6 +54,7 @@ interface Props {
|
|||
// Acts as a 'router middleware'. The main `App` component is responsible for
|
||||
// getting the list of data sources, but not every page requires them to function.
|
||||
// Routes that do require data sources can be nested under this component.
|
||||
@ErrorHandling
|
||||
export class CheckSources extends Component<Props, State> {
|
||||
public static childContextTypes = {
|
||||
source: PropTypes.shape({
|
||||
|
@ -111,9 +114,11 @@ export class CheckSources extends Component<Props, State> {
|
|||
params,
|
||||
errorThrown,
|
||||
sources,
|
||||
auth: {isUsingAuth, me, me: {organizations = [], currentOrganization}},
|
||||
auth: {isUsingAuth, me},
|
||||
notify,
|
||||
} = nextProps
|
||||
const organizations = _.get(me, 'organizations', [])
|
||||
const currentOrganization = _.get(me, 'currentOrganization')
|
||||
const {isFetching} = nextState
|
||||
const source = sources.find(s => s.id === params.sourceID)
|
||||
const defaultSource = sources.find(s => s.default === true)
|
||||
|
|
|
@ -299,7 +299,7 @@ export const addDashboardCellAsync = (
|
|||
getNewDashboardCell(dashboard, cellType)
|
||||
)
|
||||
dispatch(addDashboardCell(dashboard, data))
|
||||
dispatch(notify(notifyCellAdded()))
|
||||
dispatch(notify(notifyCellAdded(data.name)))
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
dispatch(errorThrown(error))
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import React, {PureComponent, ChangeEvent} from 'react'
|
||||
import React, {Component, ChangeEvent} from 'react'
|
||||
import {findDOMNode} from 'react-dom'
|
||||
import {
|
||||
DragSourceSpec,
|
||||
|
@ -112,7 +112,7 @@ function MyDragSource(dragv1, dragv2, dragfunc1) {
|
|||
isDragging: monitor.isDragging(),
|
||||
})
|
||||
)
|
||||
export default class GraphOptionsCustomizableField extends PureComponent<
|
||||
export default class GraphOptionsCustomizableField extends Component<
|
||||
GraphOptionsCustomizableFieldProps
|
||||
> {
|
||||
constructor(props) {
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
import {DEFAULT_TABLE_OPTIONS} from 'src/shared/constants/tableGraph'
|
||||
import {CELL_TYPE_LINE, UNTITLED_CELL_LINE} from 'src/dashboards/graphics/graph'
|
||||
import {CELL_TYPE_LINE} from 'src/dashboards/graphics/graph'
|
||||
|
||||
export const UNTITLED_CELL_LINE = 'Untitled Line Graph'
|
||||
export const UNTITLED_CELL_STACKED = 'Untitled Stacked Gracph'
|
||||
export const UNTITLED_CELL_STEPPLOT = 'Untitled Step-Plot Graph'
|
||||
export const UNTITLED_CELL_BAR = 'Untitled Bar Graph'
|
||||
export const UNTITLED_CELL_LINE_PLUS_SINGLE_STAT =
|
||||
'Untitled Line Graph + Single Stat'
|
||||
export const UNTITLED_CELL_SINGLE_STAT = 'Untitled Single Stat'
|
||||
export const UNTITLED_CELL_GAUGE = 'Untitled Gauge'
|
||||
export const UNTITLED_CELL_TABLE = 'Untitled Table'
|
||||
|
||||
export const NEW_DEFAULT_DASHBOARD_CELL = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 4,
|
||||
h: 4,
|
||||
name: UNTITLED_CELL_LINE,
|
||||
type: CELL_TYPE_LINE,
|
||||
queries: [],
|
||||
tableOptions: DEFAULT_TABLE_OPTIONS,
|
||||
}
|
||||
|
||||
export const EMPTY_DASHBOARD = {
|
||||
id: 0,
|
||||
|
@ -15,17 +36,6 @@ export const EMPTY_DASHBOARD = {
|
|||
],
|
||||
}
|
||||
|
||||
export const NEW_DEFAULT_DASHBOARD_CELL = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
w: 4,
|
||||
h: 4,
|
||||
name: UNTITLED_CELL_LINE,
|
||||
type: CELL_TYPE_LINE,
|
||||
queries: [],
|
||||
tableOptions: DEFAULT_TABLE_OPTIONS,
|
||||
}
|
||||
|
||||
export const NEW_DASHBOARD = {
|
||||
name: 'Name This Dashboard',
|
||||
cells: [NEW_DEFAULT_DASHBOARD_CELL],
|
||||
|
|
|
@ -1,16 +1,21 @@
|
|||
import _ from 'lodash'
|
||||
import calculateSize from 'calculate-size'
|
||||
|
||||
export const minDropdownWidth = 146
|
||||
export const maxDropdownWidth = 300
|
||||
export const minDropdownWidth = 120
|
||||
export const maxDropdownWidth = 330
|
||||
export const dropdownPadding = 30
|
||||
|
||||
const valueLength = a => _.size(a.value)
|
||||
|
||||
export const calculateDropdownWidth = (values = []) => {
|
||||
const longestValue = _.maxBy(values, valueLength)
|
||||
export const calculateDropdownWidth = values => {
|
||||
if (!values || !values.length) {
|
||||
return minDropdownWidth
|
||||
}
|
||||
|
||||
const longest = _.maxBy(values, valueLength)
|
||||
|
||||
const longestValuePixels =
|
||||
calculateSize(longestValue, {
|
||||
calculateSize(longest.value, {
|
||||
font: 'Monospace',
|
||||
fontSize: '12px',
|
||||
}).width + dropdownPadding
|
||||
|
|
|
@ -19,7 +19,7 @@ class DashboardsPage extends Component {
|
|||
this.props.handleGetDashboards()
|
||||
}
|
||||
|
||||
handleCreateDashbord = async () => {
|
||||
handleCreateDashboard = async () => {
|
||||
const {source: {id}, router: {push}} = this.props
|
||||
const {data} = await createDashboard(NEW_DASHBOARD)
|
||||
push(`/sources/${id}/dashboards/${data.id}`)
|
||||
|
@ -49,7 +49,7 @@ class DashboardsPage extends Component {
|
|||
dashboardLink={dashboardLink}
|
||||
dashboards={dashboards}
|
||||
onDeleteDashboard={this.handleDeleteDashboard}
|
||||
onCreateDashboard={this.handleCreateDashbord}
|
||||
onCreateDashboard={this.handleCreateDashboard}
|
||||
onCloneDashboard={this.handleCloneDashboard}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -9,6 +9,16 @@ import {
|
|||
CELL_TYPE_GAUGE,
|
||||
CELL_TYPE_TABLE,
|
||||
} from 'src/dashboards/graphics/graph'
|
||||
import {
|
||||
UNTITLED_CELL_LINE,
|
||||
UNTITLED_CELL_STACKED,
|
||||
UNTITLED_CELL_STEPPLOT,
|
||||
UNTITLED_CELL_BAR,
|
||||
UNTITLED_CELL_LINE_PLUS_SINGLE_STAT,
|
||||
UNTITLED_CELL_SINGLE_STAT,
|
||||
UNTITLED_CELL_GAUGE,
|
||||
UNTITLED_CELL_TABLE,
|
||||
} from 'src/dashboards/constants'
|
||||
|
||||
const getMostCommonValue = values => {
|
||||
const results = values.reduce(
|
||||
|
@ -30,16 +40,6 @@ const getMostCommonValue = values => {
|
|||
return results.mostCommonValue
|
||||
}
|
||||
|
||||
export const UNTITLED_CELL_LINE = 'Untitled Line Graph'
|
||||
export const UNTITLED_CELL_STACKED = 'Untitled Stacked Graph'
|
||||
export const UNTITLED_CELL_STEPPLOT = 'Untitled Step-Plot Graph'
|
||||
export const UNTITLED_CELL_BAR = 'Untitled Bar Graph'
|
||||
export const UNTITLED_CELL_LINE_PLUS_SINGLE_STAT =
|
||||
'Untitled Line Graph + Single Stat'
|
||||
export const UNTITLED_CELL_SINGLE_STAT = 'Untitled Single Stat'
|
||||
export const UNTITLED_CELL_GAUGE = 'Untitled Gauge'
|
||||
export const UNTITLED_CELL_TABLE = 'Untitled Table'
|
||||
|
||||
const getNewTypedCellName = type => {
|
||||
switch (type) {
|
||||
case CELL_TYPE_LINE:
|
||||
|
|
|
@ -107,21 +107,22 @@ const kapacitorLogHeaders = {
|
|||
}
|
||||
|
||||
export const getLogStream = kapacitor =>
|
||||
fetch(`${kapacitor.links.proxy}?path=/kapacitor/v1preview/logs`, {
|
||||
AJAX({
|
||||
url: `${kapacitor.links.proxy}?path=/kapacitor/v1preview/logs`,
|
||||
method: 'GET',
|
||||
headers: kapacitorLogHeaders,
|
||||
credentials: 'include',
|
||||
})
|
||||
|
||||
export const getLogStreamByRuleID = (kapacitor, ruleID) =>
|
||||
fetch(
|
||||
`${kapacitor.links.proxy}?path=/kapacitor/v1preview/logs?task=${ruleID}`,
|
||||
{
|
||||
method: 'GET',
|
||||
headers: kapacitorLogHeaders,
|
||||
credentials: 'include',
|
||||
}
|
||||
)
|
||||
AJAX({
|
||||
url: `${
|
||||
kapacitor.links.proxy
|
||||
}?path=/kapacitor/v1preview/logs?task=${ruleID}`,
|
||||
method: 'GET',
|
||||
headers: kapacitorLogHeaders,
|
||||
credentials: 'include',
|
||||
})
|
||||
|
||||
export const pingKapacitorVersion = async kapacitor => {
|
||||
try {
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import React, {ChangeEvent, MouseEvent, SFC} from 'react'
|
||||
import React, {ChangeEvent, MouseEvent, PureComponent} from 'react'
|
||||
|
||||
import AlertOutputs from 'src/kapacitor/components/AlertOutputs'
|
||||
import Input from 'src/kapacitor/components/KapacitorFormInput'
|
||||
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||
|
||||
import {insecureSkipVerifyText} from 'src/shared/copy/tooltipText'
|
||||
import {Kapacitor, Source} from 'src/types'
|
||||
import KapacitorFormSkipVerify from 'src/kapacitor/components/KapacitorFormSkipVerify'
|
||||
|
||||
export interface Notification {
|
||||
id?: string
|
||||
|
@ -30,125 +30,149 @@ interface Props {
|
|||
notify: (message: Notification | NotificationFunc) => void
|
||||
}
|
||||
|
||||
const KapacitorForm: SFC<Props> = ({
|
||||
onChangeUrl,
|
||||
onReset,
|
||||
kapacitor,
|
||||
kapacitor: {url, name, username, password, insecureSkipVerify},
|
||||
onSubmit,
|
||||
exists,
|
||||
onInputChange,
|
||||
onCheckboxChange,
|
||||
source,
|
||||
hash,
|
||||
notify,
|
||||
}) => (
|
||||
<div className="page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">{`${
|
||||
exists ? 'Configure' : 'Add a New'
|
||||
} Kapacitor Connection`}</h1>
|
||||
class KapacitorForm extends PureComponent<Props> {
|
||||
public render() {
|
||||
const {
|
||||
onChangeUrl,
|
||||
onReset,
|
||||
kapacitor,
|
||||
kapacitor: {name, username, password},
|
||||
onSubmit,
|
||||
exists,
|
||||
onInputChange,
|
||||
onCheckboxChange,
|
||||
source,
|
||||
hash,
|
||||
notify,
|
||||
} = this.props
|
||||
|
||||
return (
|
||||
<div className="page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">{this.headerText}</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<FancyScrollbar className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">Connection Details</h2>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<form onSubmit={onSubmit}>
|
||||
<div>
|
||||
<Input
|
||||
name="kapaUrl"
|
||||
label="Kapacitor URL"
|
||||
value={url}
|
||||
placeholder={url}
|
||||
onChange={onChangeUrl}
|
||||
/>
|
||||
<Input
|
||||
name="name"
|
||||
label="Name"
|
||||
value={name}
|
||||
placeholder={name}
|
||||
onChange={onInputChange}
|
||||
maxLength={33}
|
||||
/>
|
||||
<Input
|
||||
name="username"
|
||||
label="Username"
|
||||
value={username || ''}
|
||||
placeholder={username}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
<Input
|
||||
name="password"
|
||||
label="password"
|
||||
placeholder="password"
|
||||
value={password || ''}
|
||||
onChange={onInputChange}
|
||||
inputType="password"
|
||||
/>
|
||||
<FancyScrollbar className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-3">
|
||||
<div className="panel">
|
||||
<div className="panel-heading">
|
||||
<h2 className="panel-title">Connection Details</h2>
|
||||
</div>
|
||||
{url &&
|
||||
url.startsWith('https') && (
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="insecureSkipVerifyCheckbox"
|
||||
name="insecureSkipVerify"
|
||||
checked={insecureSkipVerify}
|
||||
onChange={onCheckboxChange}
|
||||
/>
|
||||
<label htmlFor="insecureSkipVerifyCheckbox">
|
||||
Unsafe SSL
|
||||
</label>
|
||||
</div>
|
||||
<label className="form-helper">
|
||||
{insecureSkipVerifyText}
|
||||
</label>
|
||||
<div className="panel-body">
|
||||
<form onSubmit={onSubmit}>
|
||||
<div>
|
||||
<Input
|
||||
name="kapaUrl"
|
||||
label="Kapacitor URL"
|
||||
value={this.url}
|
||||
placeholder={this.url}
|
||||
onChange={onChangeUrl}
|
||||
/>
|
||||
<Input
|
||||
name="name"
|
||||
label="Name"
|
||||
value={name}
|
||||
placeholder={name}
|
||||
onChange={onInputChange}
|
||||
maxLength={33}
|
||||
/>
|
||||
<Input
|
||||
name="username"
|
||||
label="Username"
|
||||
value={username || ''}
|
||||
placeholder={username}
|
||||
onChange={onInputChange}
|
||||
/>
|
||||
<Input
|
||||
name="password"
|
||||
label="password"
|
||||
placeholder="password"
|
||||
value={password || ''}
|
||||
onChange={onInputChange}
|
||||
inputType="password"
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
<div className="form-group form-group-submit col-xs-12 text-center">
|
||||
<button
|
||||
className="btn btn-default"
|
||||
type="button"
|
||||
onClick={onReset}
|
||||
data-test="reset-button"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-success"
|
||||
type="submit"
|
||||
data-test="submit-button"
|
||||
>
|
||||
{exists ? 'Update' : 'Connect'}
|
||||
</button>
|
||||
{this.isSecure && (
|
||||
<KapacitorFormSkipVerify
|
||||
kapacitor={kapacitor}
|
||||
onCheckboxChange={onCheckboxChange}
|
||||
/>
|
||||
)}
|
||||
<div className="form-group form-group-submit col-xs-12 text-center">
|
||||
<button
|
||||
className="btn btn-default"
|
||||
type="button"
|
||||
onClick={onReset}
|
||||
data-test="reset-button"
|
||||
>
|
||||
Reset
|
||||
</button>
|
||||
<button
|
||||
className="btn btn-success"
|
||||
type="submit"
|
||||
data-test="submit-button"
|
||||
>
|
||||
{this.buttonText}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-9">
|
||||
<AlertOutputs
|
||||
hash={hash}
|
||||
exists={exists}
|
||||
source={source}
|
||||
kapacitor={kapacitor}
|
||||
notify={notify}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="col-md-9">
|
||||
<AlertOutputs
|
||||
hash={hash}
|
||||
exists={exists}
|
||||
source={source}
|
||||
kapacitor={kapacitor}
|
||||
notify={notify}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private get buttonText(): string {
|
||||
const {exists} = this.props
|
||||
|
||||
if (exists) {
|
||||
return 'Update'
|
||||
}
|
||||
|
||||
return 'Connect'
|
||||
}
|
||||
|
||||
private get headerText(): string {
|
||||
const {exists} = this.props
|
||||
|
||||
let prefix = 'Add a New'
|
||||
if (exists) {
|
||||
prefix = 'Configure'
|
||||
}
|
||||
|
||||
return `${prefix} Kapacitor Connection`
|
||||
}
|
||||
|
||||
private get url(): string {
|
||||
const {kapacitor: {url}} = this.props
|
||||
if (url) {
|
||||
return url
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
private get isSecure(): boolean {
|
||||
return this.url.startsWith('https')
|
||||
}
|
||||
}
|
||||
|
||||
export default KapacitorForm
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
import React, {SFC, ChangeEvent} from 'react'
|
||||
import {Kapacitor} from 'src/types'
|
||||
import {insecureSkipVerifyText} from 'src/shared/copy/tooltipText'
|
||||
|
||||
interface Props {
|
||||
kapacitor: Kapacitor
|
||||
onCheckboxChange: (e: ChangeEvent<HTMLInputElement>) => void
|
||||
}
|
||||
|
||||
const KapacitorFormSkipVerify: SFC<Props> = ({
|
||||
kapacitor: {insecureSkipVerify},
|
||||
onCheckboxChange,
|
||||
}) => {
|
||||
return (
|
||||
<div className="form-group col-xs-12">
|
||||
<div className="form-control-static">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="insecureSkipVerifyCheckbox"
|
||||
name="insecureSkipVerify"
|
||||
checked={insecureSkipVerify}
|
||||
onChange={onCheckboxChange}
|
||||
/>
|
||||
<label htmlFor="insecureSkipVerifyCheckbox">Unsafe SSL</label>
|
||||
</div>
|
||||
<label className="form-helper">{insecureSkipVerifyText}</label>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default KapacitorFormSkipVerify
|
|
@ -27,7 +27,7 @@ const getLegibleTextColor = bgColorHex => {
|
|||
const findNearestCrossedThreshold = (colors, lastValue) => {
|
||||
const sortedColors = _.sortBy(colors, color => Number(color.value))
|
||||
const nearestCrossedThreshold = sortedColors
|
||||
.filter(color => lastValue > color.value)
|
||||
.filter(color => lastValue >= color.value)
|
||||
.pop()
|
||||
|
||||
return nearestCrossedThreshold
|
||||
|
|
|
@ -412,24 +412,24 @@ export const notifyDashboardDeleted = name => ({
|
|||
export const notifyDashboardDeleteFailed = (name, errorMessage) =>
|
||||
`Failed to delete Dashboard ${name}: ${errorMessage}.`
|
||||
|
||||
export const notifyCellAdded = () => ({
|
||||
export const notifyCellAdded = name => ({
|
||||
...defaultSuccessNotification,
|
||||
icon: 'dash-h',
|
||||
duration: 2200,
|
||||
message: 'Added "Untitled Cell" to dashboard.',
|
||||
duration: 1900,
|
||||
message: `Added "${name}" to dashboard.`,
|
||||
})
|
||||
|
||||
export const notifyCellCloned = name => ({
|
||||
...defaultSuccessNotification,
|
||||
icon: 'duplicate',
|
||||
duration: 2200,
|
||||
duration: 1900,
|
||||
message: `Added "${name}" to dashboard.`,
|
||||
})
|
||||
|
||||
export const notifyCellDeleted = name => ({
|
||||
...defaultDeletionNotification,
|
||||
icon: 'dash-h',
|
||||
duration: 2200,
|
||||
duration: 1900,
|
||||
message: `Deleted "${name}" from dashboard.`,
|
||||
})
|
||||
|
||||
|
|
|
@ -1,33 +1,53 @@
|
|||
/* tslint:disable no-console */
|
||||
import React from 'react'
|
||||
/*
|
||||
tslint:disable no-console
|
||||
tslint:disable max-classes-per-file
|
||||
*/
|
||||
|
||||
export function ErrorHandling<
|
||||
P,
|
||||
S,
|
||||
T extends {new (...args: any[]): React.Component<P, S>}
|
||||
>(constructor: T) {
|
||||
class Wrapped extends constructor {
|
||||
private error: boolean = false
|
||||
import React, {ComponentClass, Component} from 'react'
|
||||
|
||||
public componentDidCatch(error, info) {
|
||||
console.error(error)
|
||||
console.warn(info)
|
||||
this.error = true
|
||||
this.forceUpdate()
|
||||
}
|
||||
class DefaultError extends Component {
|
||||
public render() {
|
||||
return (
|
||||
<p className="error">
|
||||
A Chronograf error has occurred. Please report the issue
|
||||
<a href="https://github.com/influxdata/chronograf/issues">here</a>.
|
||||
</p>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.error) {
|
||||
return (
|
||||
<p className="error">
|
||||
A Chronograf error has occurred. Please report the issue
|
||||
<a href="https://github.com/influxdata/chronograf/issues">here</a>.
|
||||
</p>
|
||||
)
|
||||
export function ErrorHandlingWith(
|
||||
Error: ComponentClass, // Must be a class based component and not an SFC
|
||||
alwaysDisplay = false
|
||||
) {
|
||||
return <P, S, T extends {new (...args: any[]): Component<P, S>}>(
|
||||
constructor: T
|
||||
) => {
|
||||
class Wrapped extends constructor {
|
||||
public static get displayName(): string {
|
||||
return constructor.name
|
||||
}
|
||||
|
||||
return super.render()
|
||||
private error: boolean = false
|
||||
|
||||
public componentDidCatch(err, info) {
|
||||
console.error(err)
|
||||
console.warn(info)
|
||||
this.error = true
|
||||
this.forceUpdate()
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (this.error || alwaysDisplay) {
|
||||
return <Error />
|
||||
}
|
||||
|
||||
return super.render()
|
||||
}
|
||||
}
|
||||
|
||||
return Wrapped
|
||||
}
|
||||
return Wrapped
|
||||
}
|
||||
|
||||
export const ErrorHandling = ErrorHandlingWith(DefaultError)
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
*/
|
||||
|
||||
.ReactCodeMirror {
|
||||
.react-codemirror2 {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
|
|
@ -20,7 +20,8 @@ import {
|
|||
} from 'shared/constants/thresholds'
|
||||
import {validateLineColors} from 'src/shared/constants/graphColorPalettes'
|
||||
|
||||
import {CELL_TYPE_LINE, UNTITLED_CELL_LINE} from 'src/dashboards/graphics/graph'
|
||||
import {CELL_TYPE_LINE} from 'src/dashboards/graphics/graph'
|
||||
import {UNTITLED_CELL_LINE} from 'src/dashboards/constants'
|
||||
|
||||
const defaultCellType = CELL_TYPE_LINE
|
||||
const defaultCellName = UNTITLED_CELL_LINE
|
||||
|
|
Loading…
Reference in New Issue