From 278a532401f7fc09370f967a5d84463ee0c9a1c1 Mon Sep 17 00:00:00 2001 From: Brandon Farmer Date: Tue, 17 Apr 2018 10:53:13 -0700 Subject: [PATCH] Convert admin components to have proper error handling --- ui/.babelrc | 8 +++-- ui/package.json | 6 ++-- ui/src/admin/components/ChangePassRow.js | 2 ++ ui/src/admin/components/DatabaseRow.js | 2 ++ ui/src/admin/components/FilterBar.js | 2 ++ ui/src/admin/components/RoleEditingRow.js | 2 ++ ui/src/admin/components/UserEditName.js | 2 ++ ui/src/admin/components/UserNewPassword.js | 2 ++ .../components/UserPermissionsDropdown.tsx | 2 ++ ui/src/admin/components/UserRoleDropdown.tsx | 2 ++ ui/src/admin/components/UserRow.tsx | 2 ++ .../components/chronograf/AllUsersTable.js | 3 ++ .../chronograf/AllUsersTableRow.tsx | 2 ++ .../chronograf/AllUsersTableRowNew.js | 2 ++ .../chronograf/OrganizationsTable.js | 2 ++ .../chronograf/OrganizationsTableRow.tsx | 2 ++ .../chronograf/OrganizationsTableRowNew.js | 2 ++ .../components/chronograf/ProvidersTable.js | 2 ++ .../chronograf/ProvidersTableRow.js | 2 ++ .../chronograf/ProvidersTableRowNew.tsx | 2 ++ .../admin/components/chronograf/UsersTable.js | 2 ++ .../components/chronograf/UsersTableHeader.js | 2 ++ .../components/chronograf/UsersTableRow.tsx | 2 ++ .../components/chronograf/UsersTableRowNew.js | 2 ++ ui/src/admin/containers/AdminInfluxDBPage.js | 2 ++ .../admin/containers/DatabaseManagerPage.js | 2 ++ ui/src/admin/containers/ProvidersPage.js | 2 ++ ui/src/admin/containers/QueriesPage.js | 2 ++ .../containers/chronograf/AllUsersPage.tsx | 2 ++ .../chronograf/OrganizationsPage.js | 2 ++ .../admin/containers/chronograf/UsersPage.js | 2 ++ .../data_explorer/components/QueryMaker.tsx | 2 ++ .../components/KapacitorRulesTable.tsx | 2 ++ ui/src/shared/components/TableGraph.js | 6 ++-- ui/src/shared/decorators/errors.tsx | 32 +++++++++++++++++++ ui/webpack/dev.config.js | 1 + 36 files changed, 108 insertions(+), 8 deletions(-) create mode 100644 ui/src/shared/decorators/errors.tsx diff --git a/ui/.babelrc b/ui/.babelrc index 172c135869..9648f57f2f 100644 --- a/ui/.babelrc +++ b/ui/.babelrc @@ -8,10 +8,14 @@ ], "presets": ["env", "react", "stage-0"], "env": { + "development": { + "plugins": ["transform-decorators-legacy"] + }, "production": { "plugins": [ - "transform-react-remove-prop-types" + "transform-react-remove-prop-types", + "transform-decorators-legacy" ] - }, + } } } diff --git a/ui/package.json b/ui/package.json index 5bf8ab7c39..f04e817142 100644 --- a/ui/package.json +++ b/ui/package.json @@ -12,8 +12,7 @@ "build": "yarn run clean && webpack --config ./webpack/prod.config.js", "build:dev": "webpack --config ./webpack/dev.config.js", "build:vendor": "webpack --config webpack/vendor.config.js", - "start": - "yarn run clean && yarn run build:vendor && webpack --watch --config ./webpack/dev.config.js --progress", + "start": "yarn run clean && yarn run build:vendor && webpack --watch --config ./webpack/dev.config.js --progress", "start:fast": "webpack --watch --config ./webpack/dev.config.js", "start:hmr": "webpack-dev-server --open --config ./webpack/dev.config.js", "lint": "esw src/", @@ -23,8 +22,7 @@ "clean": "rm -rf ./build/*", "eslint:fix": "eslint src --fix", "tslint:fix": "tslint --fix -c ./tslint.json '{src,test}/**/*.ts?(x)'", - "prettier": - "prettier --single-quote --trailing-comma es5 --bracket-spacing false --semi false --write \"{src,spec}/**/*.js\"", + "prettier": "prettier --single-quote --trailing-comma es5 --bracket-spacing false --semi false --write \"{src,spec}/**/*.js\"", "lint:fix": "yarn run prettier && yarn run eslint:fix && yarn run tslint:fix", "eslint-check": "eslint --print-config .eslintrc | eslint-config-prettier-check" }, diff --git a/ui/src/admin/components/ChangePassRow.js b/ui/src/admin/components/ChangePassRow.js index bc83dac80b..e898b98a10 100644 --- a/ui/src/admin/components/ChangePassRow.js +++ b/ui/src/admin/components/ChangePassRow.js @@ -3,7 +3,9 @@ import PropTypes from 'prop-types' import OnClickOutside from 'shared/components/OnClickOutside' import ConfirmOrCancel from 'shared/components/ConfirmOrCancel' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class ChangePassRow extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/DatabaseRow.js b/ui/src/admin/components/DatabaseRow.js index 16e4a9894e..9a0e7ff2a5 100644 --- a/ui/src/admin/components/DatabaseRow.js +++ b/ui/src/admin/components/DatabaseRow.js @@ -11,7 +11,9 @@ import {formatRPDuration} from 'utils/formatting' import ConfirmButton from 'shared/components/ConfirmButton' import {DATABASE_TABLE} from 'src/admin/constants/tableSizing' import {notifyRetentionPolicyCantHaveEmptyFields} from 'shared/copy/notifications' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class DatabaseRow extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/FilterBar.js b/ui/src/admin/components/FilterBar.js index 314924d78f..bdce296537 100644 --- a/ui/src/admin/components/FilterBar.js +++ b/ui/src/admin/components/FilterBar.js @@ -1,6 +1,8 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class FilterBar extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/RoleEditingRow.js b/ui/src/admin/components/RoleEditingRow.js index 8395f05163..8e02c63e82 100644 --- a/ui/src/admin/components/RoleEditingRow.js +++ b/ui/src/admin/components/RoleEditingRow.js @@ -2,7 +2,9 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import {ROLES_TABLE} from 'src/admin/constants/tableSizing' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class RoleEditingRow extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/UserEditName.js b/ui/src/admin/components/UserEditName.js index 90fa184656..357ae65f55 100644 --- a/ui/src/admin/components/UserEditName.js +++ b/ui/src/admin/components/UserEditName.js @@ -2,7 +2,9 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import {USERS_TABLE} from 'src/admin/constants/tableSizing' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class UserEditName extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/UserNewPassword.js b/ui/src/admin/components/UserNewPassword.js index 1375fccb04..3d50067cad 100644 --- a/ui/src/admin/components/UserNewPassword.js +++ b/ui/src/admin/components/UserNewPassword.js @@ -2,7 +2,9 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' import {USERS_TABLE} from 'src/admin/constants/tableSizing' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class UserNewPassword extends Component { handleKeyPress = user => { return e => { diff --git a/ui/src/admin/components/UserPermissionsDropdown.tsx b/ui/src/admin/components/UserPermissionsDropdown.tsx index d3345341ef..c26bbc1a62 100644 --- a/ui/src/admin/components/UserPermissionsDropdown.tsx +++ b/ui/src/admin/components/UserPermissionsDropdown.tsx @@ -6,6 +6,7 @@ import MultiSelectDropdown from 'src/shared/components/MultiSelectDropdown' import {USERS_TABLE} from 'src/admin/constants/tableSizing' import {User} from 'src/types/influxAdmin' +import {ErrorHandling} from 'src/shared/decorators/errors' interface Props { user: User @@ -13,6 +14,7 @@ interface Props { onUpdatePermissions: (user: User, permissions: any[]) => void } +@ErrorHandling class UserPermissionsDropdown extends PureComponent { public render() { return ( diff --git a/ui/src/admin/components/UserRoleDropdown.tsx b/ui/src/admin/components/UserRoleDropdown.tsx index e287934051..46ded3322a 100644 --- a/ui/src/admin/components/UserRoleDropdown.tsx +++ b/ui/src/admin/components/UserRoleDropdown.tsx @@ -7,6 +7,7 @@ import MultiSelectDropdown from 'src/shared/components/MultiSelectDropdown' import {USERS_TABLE} from 'src/admin/constants/tableSizing' import {User, UserRole} from 'src/types/influxAdmin' +import {ErrorHandling} from 'src/shared/decorators/errors' interface Props { user: User @@ -14,6 +15,7 @@ interface Props { onUpdateRoles: (user: User, roles: UserRole[]) => void } +@ErrorHandling class UserRoleDropdown extends PureComponent { public render() { const {allRoles} = this.props diff --git a/ui/src/admin/components/UserRow.tsx b/ui/src/admin/components/UserRow.tsx index a2e908c6c6..e4c1bd004d 100644 --- a/ui/src/admin/components/UserRow.tsx +++ b/ui/src/admin/components/UserRow.tsx @@ -8,6 +8,7 @@ import {USERS_TABLE} from 'src/admin/constants/tableSizing' import UserRowEdit from 'src/admin/components/UserRowEdit' import {User} from 'src/types/influxAdmin' +import {ErrorHandling} from 'src/shared/decorators/errors' interface UserRowProps { user: User @@ -25,6 +26,7 @@ interface UserRowProps { onUpdatePassword: (user: User, password: string) => void } +@ErrorHandling class UserRow extends PureComponent { public render() { const { diff --git a/ui/src/admin/components/chronograf/AllUsersTable.js b/ui/src/admin/components/chronograf/AllUsersTable.js index ec73494298..e0e0283e0f 100644 --- a/ui/src/admin/components/chronograf/AllUsersTable.js +++ b/ui/src/admin/components/chronograf/AllUsersTable.js @@ -8,6 +8,8 @@ import AllUsersTableRowNew from 'src/admin/components/chronograf/AllUsersTableRo import AllUsersTableRow from 'src/admin/components/chronograf/AllUsersTableRow' import {ALL_USERS_TABLE} from 'src/admin/constants/chronografTableSizing' +import {ErrorHandling} from 'src/shared/decorators/errors' + const { colOrganizations, colProvider, @@ -21,6 +23,7 @@ import { notifyChronografUserRemovedFromOrg, } from 'shared/copy/notifications' +@ErrorHandling class AllUsersTable extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/AllUsersTableRow.tsx b/ui/src/admin/components/chronograf/AllUsersTableRow.tsx index 49d30db815..479433eac0 100644 --- a/ui/src/admin/components/chronograf/AllUsersTableRow.tsx +++ b/ui/src/admin/components/chronograf/AllUsersTableRow.tsx @@ -6,6 +6,7 @@ import SlideToggle from 'src/shared/components/SlideToggle' import ConfirmButton from 'src/shared/components/ConfirmButton' import {ALL_USERS_TABLE} from 'src/admin/constants/chronografTableSizing' +import {ErrorHandling} from 'src/shared/decorators/errors' const { colOrganizations, @@ -44,6 +45,7 @@ interface Props { organizations: Organization[] } +@ErrorHandling export default class AllUsersTableRow extends PureComponent { public render() { const { diff --git a/ui/src/admin/components/chronograf/AllUsersTableRowNew.js b/ui/src/admin/components/chronograf/AllUsersTableRowNew.js index da2a0a85c8..070326de5d 100644 --- a/ui/src/admin/components/chronograf/AllUsersTableRowNew.js +++ b/ui/src/admin/components/chronograf/AllUsersTableRowNew.js @@ -5,6 +5,7 @@ import {bindActionCreators} from 'redux' import {notify as notifyAction} from 'shared/actions/notifications' import Dropdown from 'shared/components/Dropdown' +import {ErrorHandling} from 'src/shared/decorators/errors' import {notifyChronografUserMissingNameAndProvider} from 'shared/copy/notifications' import {ALL_USERS_TABLE} from 'src/admin/constants/chronografTableSizing' @@ -19,6 +20,7 @@ const { const nullOrganization = {id: undefined, name: 'None'} const nullRole = {name: '*', organization: undefined} +@ErrorHandling class AllUsersTableRowNew extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/OrganizationsTable.js b/ui/src/admin/components/chronograf/OrganizationsTable.js index aca6866f36..5cb53c7d40 100644 --- a/ui/src/admin/components/chronograf/OrganizationsTable.js +++ b/ui/src/admin/components/chronograf/OrganizationsTable.js @@ -6,7 +6,9 @@ import _ from 'lodash' import OrganizationsTableRow from 'src/admin/components/chronograf/OrganizationsTableRow' import OrganizationsTableRowNew from 'src/admin/components/chronograf/OrganizationsTableRowNew' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class OrganizationsTable extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/OrganizationsTableRow.tsx b/ui/src/admin/components/chronograf/OrganizationsTableRow.tsx index 091146a38f..2f3fcb5fee 100644 --- a/ui/src/admin/components/chronograf/OrganizationsTableRow.tsx +++ b/ui/src/admin/components/chronograf/OrganizationsTableRow.tsx @@ -11,6 +11,7 @@ import InputClickToEdit from 'src/shared/components/InputClickToEdit' import {meChangeOrganizationAsync} from 'src/shared/actions/auth' +import {ErrorHandling} from 'src/shared/decorators/errors' import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin' import {USER_ROLES} from 'src/admin/constants/chronografAdmin' import {Organization} from 'src/types' @@ -43,6 +44,7 @@ interface Props { router: InjectedRouter } +@ErrorHandling class OrganizationsTableRow extends PureComponent { public shouldComponentUpdate(nextProps) { return !_.isEqual(this.props, nextProps) diff --git a/ui/src/admin/components/chronograf/OrganizationsTableRowNew.js b/ui/src/admin/components/chronograf/OrganizationsTableRowNew.js index ddadb6cc1b..22e8ab7e52 100644 --- a/ui/src/admin/components/chronograf/OrganizationsTableRowNew.js +++ b/ui/src/admin/components/chronograf/OrganizationsTableRowNew.js @@ -6,7 +6,9 @@ import Dropdown from 'shared/components/Dropdown' import {USER_ROLES} from 'src/admin/constants/chronografAdmin' import {MEMBER_ROLE} from 'src/auth/Authorized' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class OrganizationsTableRowNew extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/ProvidersTable.js b/ui/src/admin/components/chronograf/ProvidersTable.js index f44ea8c79b..4d3b622a21 100644 --- a/ui/src/admin/components/chronograf/ProvidersTable.js +++ b/ui/src/admin/components/chronograf/ProvidersTable.js @@ -4,7 +4,9 @@ import PropTypes from 'prop-types' import uuid from 'uuid' import ProvidersTableRow from 'src/admin/components/chronograf/ProvidersTableRow' import ProvidersTableRowNew from 'src/admin/components/chronograf/ProvidersTableRowNew' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class ProvidersTable extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/ProvidersTableRow.js b/ui/src/admin/components/chronograf/ProvidersTableRow.js index d39c16b3ab..56caa1dd8f 100644 --- a/ui/src/admin/components/chronograf/ProvidersTableRow.js +++ b/ui/src/admin/components/chronograf/ProvidersTableRow.js @@ -6,7 +6,9 @@ import Dropdown from 'shared/components/Dropdown' import InputClickToEdit from 'shared/components/InputClickToEdit' import {DEFAULT_MAPPING_ID} from 'src/admin/constants/chronografAdmin' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class ProvidersTableRow extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/ProvidersTableRowNew.tsx b/ui/src/admin/components/chronograf/ProvidersTableRowNew.tsx index 501e1db90a..7f08d6747d 100644 --- a/ui/src/admin/components/chronograf/ProvidersTableRowNew.tsx +++ b/ui/src/admin/components/chronograf/ProvidersTableRowNew.tsx @@ -3,6 +3,7 @@ import React, {PureComponent} from 'react' import ConfirmOrCancel from 'src/shared/components/ConfirmOrCancel' import Dropdown from 'src/shared/components/Dropdown' import InputClickToEdit from 'src/shared/components/InputClickToEdit' +import {ErrorHandling} from 'src/shared/decorators/errors' interface Organization { id: string @@ -28,6 +29,7 @@ interface State { organizationId: string } +@ErrorHandling class ProvidersTableRowNew extends PureComponent { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/UsersTable.js b/ui/src/admin/components/chronograf/UsersTable.js index f02be5f736..63177d9aaa 100644 --- a/ui/src/admin/components/chronograf/UsersTable.js +++ b/ui/src/admin/components/chronograf/UsersTable.js @@ -9,7 +9,9 @@ import UsersTableRowNew from 'src/admin/components/chronograf/UsersTableRowNew' import UsersTableRow from 'src/admin/components/chronograf/UsersTableRow' import {USERS_TABLE} from 'src/admin/constants/chronografTableSizing' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class UsersTable extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/UsersTableHeader.js b/ui/src/admin/components/chronograf/UsersTableHeader.js index 229ee83a64..13b78f9a22 100644 --- a/ui/src/admin/components/chronograf/UsersTableHeader.js +++ b/ui/src/admin/components/chronograf/UsersTableHeader.js @@ -1,6 +1,8 @@ import React, {Component} from 'react' import PropTypes from 'prop-types' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class UsersTableHeader extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/components/chronograf/UsersTableRow.tsx b/ui/src/admin/components/chronograf/UsersTableRow.tsx index d0fce70bd4..ee1bafb17d 100644 --- a/ui/src/admin/components/chronograf/UsersTableRow.tsx +++ b/ui/src/admin/components/chronograf/UsersTableRow.tsx @@ -3,6 +3,7 @@ import React, {PureComponent} from 'react' import Dropdown from 'src/shared/components/Dropdown' import ConfirmButton from 'src/shared/components/ConfirmButton' +import {ErrorHandling} from 'src/shared/decorators/errors' import {USER_ROLES} from 'src/admin/constants/chronografAdmin' import {USERS_TABLE} from 'src/admin/constants/chronografTableSizing' import {User, Role} from 'src/types' @@ -25,6 +26,7 @@ interface Props { meID: string } +@ErrorHandling class UsersTableRow extends PureComponent { public render() { const {user, onChangeUserRole} = this.props diff --git a/ui/src/admin/components/chronograf/UsersTableRowNew.js b/ui/src/admin/components/chronograf/UsersTableRowNew.js index 2a756e6b5d..969517314b 100644 --- a/ui/src/admin/components/chronograf/UsersTableRowNew.js +++ b/ui/src/admin/components/chronograf/UsersTableRowNew.js @@ -7,10 +7,12 @@ import {notify as notifyAction} from 'shared/actions/notifications' import Dropdown from 'shared/components/Dropdown' +import {ErrorHandling} from 'src/shared/decorators/errors' import {notifyChronografUserMissingNameAndProvider} from 'shared/copy/notifications' import {USERS_TABLE} from 'src/admin/constants/chronografTableSizing' import {USER_ROLES} from 'src/admin/constants/chronografAdmin' +@ErrorHandling class UsersTableRowNew extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/containers/AdminInfluxDBPage.js b/ui/src/admin/containers/AdminInfluxDBPage.js index 3b593ebcc8..5f95977285 100644 --- a/ui/src/admin/containers/AdminInfluxDBPage.js +++ b/ui/src/admin/containers/AdminInfluxDBPage.js @@ -28,6 +28,7 @@ import { import AdminTabs from 'src/admin/components/AdminTabs' import SourceIndicator from 'shared/components/SourceIndicator' import FancyScrollbar from 'shared/components/FancyScrollbar' +import {ErrorHandling} from 'src/shared/decorators/errors' import {notify as notifyAction} from 'shared/actions/notifications' @@ -46,6 +47,7 @@ const isValidRole = role => { return role.name.length >= minLen } +@ErrorHandling class AdminInfluxDBPage extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/containers/DatabaseManagerPage.js b/ui/src/admin/containers/DatabaseManagerPage.js index 29ae1bec61..5ea3ca6f8f 100644 --- a/ui/src/admin/containers/DatabaseManagerPage.js +++ b/ui/src/admin/containers/DatabaseManagerPage.js @@ -8,6 +8,7 @@ import DatabaseManager from 'src/admin/components/DatabaseManager' import * as adminActionCreators from 'src/admin/actions/influxdb' import {notify as notifyAction} from 'shared/actions/notifications' +import {ErrorHandling} from 'src/shared/decorators/errors' import { notifyDatabaseDeleteConfirmationRequired, @@ -15,6 +16,7 @@ import { notifyDatabaseNameInvalid, } from 'shared/copy/notifications' +@ErrorHandling class DatabaseManagerPage extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/containers/ProvidersPage.js b/ui/src/admin/containers/ProvidersPage.js index 64bcef0de7..91f123b49b 100644 --- a/ui/src/admin/containers/ProvidersPage.js +++ b/ui/src/admin/containers/ProvidersPage.js @@ -7,7 +7,9 @@ import * as adminChronografActionCreators from 'src/admin/actions/chronograf' import {notify as notifyAction} from 'shared/actions/notifications' import ProvidersTable from 'src/admin/components/chronograf/ProvidersTable' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class ProvidersPage extends Component { constructor(props) { super(props) diff --git a/ui/src/admin/containers/QueriesPage.js b/ui/src/admin/containers/QueriesPage.js index f39c7cefab..133235a928 100644 --- a/ui/src/admin/containers/QueriesPage.js +++ b/ui/src/admin/containers/QueriesPage.js @@ -13,6 +13,7 @@ import showDatabasesParser from 'shared/parsing/showDatabases' import showQueriesParser from 'shared/parsing/showQueries' import {TIMES} from 'src/admin/constants' import {notifyQueriesError} from 'shared/copy/notifications' +import {ErrorHandling} from 'src/shared/decorators/errors' import { loadQueries as loadQueriesAction, @@ -22,6 +23,7 @@ import { import {notify as notifyAction} from 'shared/actions/notifications' +@ErrorHandling class QueriesPage extends Component { componentDidMount() { this.updateQueries() diff --git a/ui/src/admin/containers/chronograf/AllUsersPage.tsx b/ui/src/admin/containers/chronograf/AllUsersPage.tsx index 295a3fb7e7..edb33285d4 100644 --- a/ui/src/admin/containers/chronograf/AllUsersPage.tsx +++ b/ui/src/admin/containers/chronograf/AllUsersPage.tsx @@ -5,6 +5,7 @@ import {bindActionCreators} from 'redux' import * as adminChronografActionCreators from 'src/admin/actions/chronograf' import * as configActionCreators from 'src/shared/actions/config' import {notify as notifyAction} from 'src/shared/actions/notifications' +import {ErrorHandling} from 'src/shared/decorators/errors' import AllUsersTable from 'src/admin/components/chronograf/AllUsersTable' import {AuthLinks, Organization, Role, User} from 'src/types' @@ -38,6 +39,7 @@ interface State { isLoading: boolean } +@ErrorHandling export class AllUsersPage extends PureComponent { constructor(props) { super(props) diff --git a/ui/src/admin/containers/chronograf/OrganizationsPage.js b/ui/src/admin/containers/chronograf/OrganizationsPage.js index d0f7514bd7..491cf1845c 100644 --- a/ui/src/admin/containers/chronograf/OrganizationsPage.js +++ b/ui/src/admin/containers/chronograf/OrganizationsPage.js @@ -5,9 +5,11 @@ import {bindActionCreators} from 'redux' import * as adminChronografActionCreators from 'src/admin/actions/chronograf' import {getMeAsync} from 'shared/actions/auth' +import {ErrorHandling} from 'src/shared/decorators/errors' import OrganizationsTable from 'src/admin/components/chronograf/OrganizationsTable' +@ErrorHandling class OrganizationsPage extends Component { componentDidMount() { const {links, actionsAdmin: {loadOrganizationsAsync}} = this.props diff --git a/ui/src/admin/containers/chronograf/UsersPage.js b/ui/src/admin/containers/chronograf/UsersPage.js index 44fe06d1aa..d2fb102191 100644 --- a/ui/src/admin/containers/chronograf/UsersPage.js +++ b/ui/src/admin/containers/chronograf/UsersPage.js @@ -5,9 +5,11 @@ import {bindActionCreators} from 'redux' import * as adminChronografActionCreators from 'src/admin/actions/chronograf' import {notify as notifyAction} from 'shared/actions/notifications' +import {ErrorHandling} from 'src/shared/decorators/errors' import UsersTable from 'src/admin/components/chronograf/UsersTable' +@ErrorHandling class UsersPage extends PureComponent { constructor(props) { super(props) diff --git a/ui/src/data_explorer/components/QueryMaker.tsx b/ui/src/data_explorer/components/QueryMaker.tsx index b53e7ac2f9..decdb8c1cf 100644 --- a/ui/src/data_explorer/components/QueryMaker.tsx +++ b/ui/src/data_explorer/components/QueryMaker.tsx @@ -3,6 +3,7 @@ import React, {PureComponent} from 'react' import QueryEditor from './QueryEditor' import SchemaExplorer from 'src/shared/components/SchemaExplorer' import {Source, Query} from 'src/types' +import {ErrorHandling} from 'src/shared/decorators/errors' const rawTextBinder = (links, id, action) => text => action(links.queries, id, text) @@ -15,6 +16,7 @@ interface Props { initialGroupByTime: string } +@ErrorHandling class QueryMaker extends PureComponent { public render() { const { diff --git a/ui/src/kapacitor/components/KapacitorRulesTable.tsx b/ui/src/kapacitor/components/KapacitorRulesTable.tsx index f0ab9369b5..7a3933b114 100644 --- a/ui/src/kapacitor/components/KapacitorRulesTable.tsx +++ b/ui/src/kapacitor/components/KapacitorRulesTable.tsx @@ -1,6 +1,7 @@ import React, {PureComponent, SFC} from 'react' import {Link} from 'react-router' import _ from 'lodash' +import {ErrorHandling} from 'src/shared/decorators/errors' import {AlertRule, Source} from 'src/types' @@ -65,6 +66,7 @@ const KapacitorRulesTable: SFC = ({ ) +@ErrorHandling export class RuleRow extends PureComponent { constructor(props) { super(props) diff --git a/ui/src/shared/components/TableGraph.js b/ui/src/shared/components/TableGraph.js index 096f06bd09..9a1db53e48 100644 --- a/ui/src/shared/components/TableGraph.js +++ b/ui/src/shared/components/TableGraph.js @@ -7,6 +7,8 @@ import {MultiGrid, ColumnSizer} from 'react-virtualized' import moment from 'moment' import {reduce} from 'fast.js' +const {arrayOf, bool, shape, string, func} = PropTypes + import { timeSeriesToTableGraph, processTableData, @@ -26,7 +28,9 @@ import { import {generateThresholdsListHexs} from 'shared/constants/colorOperations' import {colorsStringSchema} from 'shared/schemas' +import {ErrorHandling} from 'src/shared/decorators/errors' +@ErrorHandling class TableGraph extends Component { constructor(props) { super(props) @@ -387,8 +391,6 @@ class TableGraph extends Component { } } -const {arrayOf, bool, shape, string, func} = PropTypes - TableGraph.propTypes = { data: arrayOf(shape()), tableOptions: shape({ diff --git a/ui/src/shared/decorators/errors.tsx b/ui/src/shared/decorators/errors.tsx new file mode 100644 index 0000000000..1eca1a4b1b --- /dev/null +++ b/ui/src/shared/decorators/errors.tsx @@ -0,0 +1,32 @@ +import React from 'react' + +export function ErrorHandling< + P, + S, + T extends {new (...args: any[]): React.Component} +>(constructor: T) { + class Wrapped extends constructor { + private error: boolean = false + + public componentDidCatch(error, info) { + console.error(error) + console.error(info) + this.error = true + this.forceUpdate() + } + + public render() { + if (this.error) { + return ( +

+ A Chronograf error has occurred. Please report the issue + here +

+ ) + } + + return super.render() + } + } + return Wrapped +} diff --git a/ui/webpack/dev.config.js b/ui/webpack/dev.config.js index f2fc06d6ff..2876a8ce83 100644 --- a/ui/webpack/dev.config.js +++ b/ui/webpack/dev.config.js @@ -117,6 +117,7 @@ module.exports = { loader: 'babel-loader', options: { presets: ['env', 'react', 'stage-0'], + plugins: ['transform-decorators-legacy'], cacheDirectory: true, // use a cache directory to speed up compilation }, },