Run eslint to fix issues
parent
ca7c72c695
commit
4dd1cc7418
|
@ -4,12 +4,13 @@ import PropTypes from 'prop-types'
|
||||||
import SideNav from 'src/side_nav'
|
import SideNav from 'src/side_nav'
|
||||||
import Notifications from 'shared/components/Notifications'
|
import Notifications from 'shared/components/Notifications'
|
||||||
|
|
||||||
const App = ({children}) =>
|
const App = ({children}) => (
|
||||||
<div className="chronograf-root">
|
<div className="chronograf-root">
|
||||||
<Notifications />
|
<Notifications />
|
||||||
<SideNav />
|
<SideNav />
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {node} = PropTypes
|
const {node} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -168,9 +168,9 @@ export const createMappingAsync = (url, mapping) => async dispatch => {
|
||||||
const {data} = await createMappingAJAX(url, mapping)
|
const {data} = await createMappingAJAX(url, mapping)
|
||||||
dispatch(updateMapping(mappingWithTempId, data))
|
dispatch(updateMapping(mappingWithTempId, data))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = `${_.upperFirst(
|
const message = `${_.upperFirst(_.toLower(error.data.message))}: Scheme: ${
|
||||||
_.toLower(error.data.message)
|
mapping.scheme
|
||||||
)}: Scheme: ${mapping.scheme} Provider: ${mapping.provider}`
|
} Provider: ${mapping.provider}`
|
||||||
dispatch(errorThrown(error, message))
|
dispatch(errorThrown(error, message))
|
||||||
setTimeout(
|
setTimeout(
|
||||||
() => dispatch(removeMapping(mappingWithTempId)),
|
() => dispatch(removeMapping(mappingWithTempId)),
|
||||||
|
@ -212,9 +212,9 @@ export const createUserAsync = (url, user) => async dispatch => {
|
||||||
const {data} = await createUserAJAX(url, user)
|
const {data} = await createUserAJAX(url, user)
|
||||||
dispatch(syncUser(userWithTempID, data))
|
dispatch(syncUser(userWithTempID, data))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = `${_.upperFirst(
|
const message = `${_.upperFirst(_.toLower(error.data.message))}: ${
|
||||||
_.toLower(error.data.message)
|
user.scheme
|
||||||
)}: ${user.scheme}::${user.provider}::${user.name}`
|
}::${user.provider}::${user.name}`
|
||||||
dispatch(errorThrown(error, message))
|
dispatch(errorThrown(error, message))
|
||||||
// undo optimistic update
|
// undo optimistic update
|
||||||
setTimeout(() => dispatch(removeUser(userWithTempID)), REVERT_STATE_DELAY)
|
setTimeout(() => dispatch(removeUser(userWithTempID)), REVERT_STATE_DELAY)
|
||||||
|
@ -277,9 +277,9 @@ export const createOrganizationAsync = (
|
||||||
const {data} = await createOrganizationAJAX(url, organization)
|
const {data} = await createOrganizationAJAX(url, organization)
|
||||||
dispatch(syncOrganization(organization, data))
|
dispatch(syncOrganization(organization, data))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const message = `${_.upperFirst(
|
const message = `${_.upperFirst(_.toLower(error.data.message))}: ${
|
||||||
_.toLower(error.data.message)
|
organization.name
|
||||||
)}: ${organization.name}`
|
}`
|
||||||
dispatch(errorThrown(error, message))
|
dispatch(errorThrown(error, message))
|
||||||
// undo optimistic update
|
// undo optimistic update
|
||||||
setTimeout(
|
setTimeout(
|
||||||
|
|
|
@ -89,18 +89,12 @@ const AdminTabs = ({
|
||||||
return (
|
return (
|
||||||
<Tabs className="row">
|
<Tabs className="row">
|
||||||
<TabList customClass="col-md-2 admin-tabs">
|
<TabList customClass="col-md-2 admin-tabs">
|
||||||
{tabs.map((t, i) =>
|
{tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
|
||||||
<Tab key={tabs[i].type}>
|
|
||||||
{tabs[i].type}
|
|
||||||
</Tab>
|
|
||||||
)}
|
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels customClass="col-md-10 admin-tabs--content">
|
<TabPanels customClass="col-md-10 admin-tabs--content">
|
||||||
{tabs.map((t, i) =>
|
{tabs.map((t, i) => (
|
||||||
<TabPanel key={tabs[i].type}>
|
<TabPanel key={tabs[i].type}>{t.component}</TabPanel>
|
||||||
{t.component}
|
))}
|
||||||
</TabPanel>
|
|
||||||
)}
|
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)
|
)
|
||||||
|
|
|
@ -41,7 +41,7 @@ const DatabaseManager = ({
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-body">
|
<div className="panel-body">
|
||||||
{databases.map(db =>
|
{databases.map(db => (
|
||||||
<DatabaseTable
|
<DatabaseTable
|
||||||
key={db.links.self}
|
key={db.links.self}
|
||||||
database={db}
|
database={db}
|
||||||
|
@ -62,7 +62,7 @@ const DatabaseManager = ({
|
||||||
onRemoveRetentionPolicy={onRemoveRetentionPolicy}
|
onRemoveRetentionPolicy={onRemoveRetentionPolicy}
|
||||||
onDeleteRetentionPolicy={onDeleteRetentionPolicy}
|
onDeleteRetentionPolicy={onDeleteRetentionPolicy}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -148,19 +148,21 @@ class DatabaseRow extends Component {
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td style={{width: `${DATABASE_TABLE.colRetentionPolicy}px`}}>
|
<td style={{width: `${DATABASE_TABLE.colRetentionPolicy}px`}}>
|
||||||
{isNew
|
{isNew ? (
|
||||||
? <input
|
<input
|
||||||
className="form-control input-xs"
|
className="form-control input-xs"
|
||||||
type="text"
|
type="text"
|
||||||
defaultValue={name}
|
defaultValue={name}
|
||||||
placeholder="Name this RP"
|
placeholder="Name this RP"
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
ref={r => (this.name = r)}
|
ref={r => (this.name = r)}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
autoComplete={false}
|
autoComplete={false}
|
||||||
/>
|
/>
|
||||||
: name}
|
) : (
|
||||||
|
name
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td style={{width: `${DATABASE_TABLE.colDuration}px`}}>
|
<td style={{width: `${DATABASE_TABLE.colDuration}px`}}>
|
||||||
<input
|
<input
|
||||||
|
@ -176,22 +178,22 @@ class DatabaseRow extends Component {
|
||||||
autoComplete={false}
|
autoComplete={false}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
{isRFDisplayed
|
{isRFDisplayed ? (
|
||||||
? <td style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
<td style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
||||||
<input
|
<input
|
||||||
className="form-control input-xs"
|
className="form-control input-xs"
|
||||||
name="name"
|
name="name"
|
||||||
type="number"
|
type="number"
|
||||||
min="1"
|
min="1"
|
||||||
defaultValue={replication || 1}
|
defaultValue={replication || 1}
|
||||||
placeholder="# of Nodes"
|
placeholder="# of Nodes"
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
ref={r => (this.replication = r)}
|
ref={r => (this.replication = r)}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
autoComplete={false}
|
autoComplete={false}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
: null}
|
) : null}
|
||||||
<td
|
<td
|
||||||
className="text-right"
|
className="text-right"
|
||||||
style={{width: `${DATABASE_TABLE.colDelete}px`}}
|
style={{width: `${DATABASE_TABLE.colDelete}px`}}
|
||||||
|
@ -210,9 +212,9 @@ class DatabaseRow extends Component {
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
{`${name} `}
|
{`${name} `}
|
||||||
{isDefault
|
{isDefault ? (
|
||||||
? <span className="default-source-label">default</span>
|
<span className="default-source-label">default</span>
|
||||||
: null}
|
) : null}
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
onClick={this.handleStartEdit}
|
onClick={this.handleStartEdit}
|
||||||
|
@ -220,31 +222,33 @@ class DatabaseRow extends Component {
|
||||||
>
|
>
|
||||||
{formattedDuration}
|
{formattedDuration}
|
||||||
</td>
|
</td>
|
||||||
{isRFDisplayed
|
{isRFDisplayed ? (
|
||||||
? <td
|
<td
|
||||||
onClick={this.handleStartEdit}
|
onClick={this.handleStartEdit}
|
||||||
style={{width: `${DATABASE_TABLE.colReplication}px`}}
|
style={{width: `${DATABASE_TABLE.colReplication}px`}}
|
||||||
>
|
>
|
||||||
{replication}
|
{replication}
|
||||||
</td>
|
</td>
|
||||||
: null}
|
) : null}
|
||||||
<td
|
<td
|
||||||
className="text-right"
|
className="text-right"
|
||||||
style={{width: `${DATABASE_TABLE.colDelete}px`}}
|
style={{width: `${DATABASE_TABLE.colDelete}px`}}
|
||||||
>
|
>
|
||||||
{isDeleting
|
{isDeleting ? (
|
||||||
? <YesNoButtons
|
<YesNoButtons
|
||||||
onConfirm={onDelete(database, retentionPolicy)}
|
onConfirm={onDelete(database, retentionPolicy)}
|
||||||
onCancel={this.handleEndDelete}
|
onCancel={this.handleEndDelete}
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
/>
|
/>
|
||||||
: <button
|
) : (
|
||||||
className="btn btn-danger btn-xs table--show-on-row-hover"
|
<button
|
||||||
style={isDeletable ? {} : {visibility: 'hidden'}}
|
className="btn btn-danger btn-xs table--show-on-row-hover"
|
||||||
onClick={this.handleStartDelete}
|
style={isDeletable ? {} : {visibility: 'hidden'}}
|
||||||
>
|
onClick={this.handleStartDelete}
|
||||||
{`Delete ${name}`}
|
>
|
||||||
</button>}
|
{`Delete ${name}`}
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|
|
@ -57,11 +57,11 @@ const DatabaseTable = ({
|
||||||
<th style={{width: `${DATABASE_TABLE.colDuration}px`}}>
|
<th style={{width: `${DATABASE_TABLE.colDuration}px`}}>
|
||||||
Duration
|
Duration
|
||||||
</th>
|
</th>
|
||||||
{isRFDisplayed
|
{isRFDisplayed ? (
|
||||||
? <th style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
<th style={{width: `${DATABASE_TABLE.colReplication}px`}}>
|
||||||
Replication Factor
|
Replication Factor
|
||||||
</th>
|
</th>
|
||||||
: null}
|
) : null}
|
||||||
<th style={{width: `${DATABASE_TABLE.colDelete}px`}} />
|
<th style={{width: `${DATABASE_TABLE.colDelete}px`}} />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
@ -68,14 +68,14 @@ const Header = ({
|
||||||
>
|
>
|
||||||
<span className="icon plus" /> Add Retention Policy
|
<span className="icon plus" /> Add Retention Policy
|
||||||
</button>
|
</button>
|
||||||
{database.name === '_internal'
|
{database.name === '_internal' ? null : (
|
||||||
? null
|
<button
|
||||||
: <button
|
className="btn btn-xs btn-danger"
|
||||||
className="btn btn-xs btn-danger"
|
onClick={onStartDelete(database)}
|
||||||
onClick={onStartDelete(database)}
|
>
|
||||||
>
|
Delete
|
||||||
Delete
|
</button>
|
||||||
</button>}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -112,15 +112,13 @@ const Header = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="db-manager-header">
|
<div className="db-manager-header">
|
||||||
<h4>
|
<h4>{database.name}</h4>
|
||||||
{database.name}
|
|
||||||
</h4>
|
|
||||||
{database.hasOwnProperty('deleteCode') ? deleteConfirmation : buttons}
|
{database.hasOwnProperty('deleteCode') ? deleteConfirmation : buttons}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) =>
|
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) => (
|
||||||
<div className="db-manager-header db-manager-header--edit">
|
<div className="db-manager-header db-manager-header--edit">
|
||||||
<input
|
<input
|
||||||
className="form-control input-sm"
|
className="form-control input-sm"
|
||||||
|
@ -136,6 +134,7 @@ const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) =>
|
||||||
/>
|
/>
|
||||||
<ConfirmButtons item={database} onConfirm={onConfirm} onCancel={onCancel} />
|
<ConfirmButtons item={database} onConfirm={onConfirm} onCancel={onCancel} />
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, shape, bool} = PropTypes
|
const {func, shape, bool} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const EmptyRow = ({tableName}) =>
|
const EmptyRow = ({tableName}) => (
|
||||||
<tr className="table-empty-state">
|
<tr className="table-empty-state">
|
||||||
<th colSpan="5">
|
<th colSpan="5">
|
||||||
<p>
|
<p>
|
||||||
|
@ -9,6 +9,7 @@ const EmptyRow = ({tableName}) =>
|
||||||
</p>
|
</p>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
|
)
|
||||||
|
|
||||||
const {string} = PropTypes
|
const {string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
|
||||||
import QueryRow from 'src/admin/components/QueryRow'
|
import QueryRow from 'src/admin/components/QueryRow'
|
||||||
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
|
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
|
||||||
|
|
||||||
const QueriesTable = ({queries, onKillQuery}) =>
|
const QueriesTable = ({queries, onKillQuery}) => (
|
||||||
<div>
|
<div>
|
||||||
<div className="panel panel-solid">
|
<div className="panel panel-solid">
|
||||||
<div className="panel-body">
|
<div className="panel-body">
|
||||||
|
@ -20,14 +20,15 @@ const QueriesTable = ({queries, onKillQuery}) =>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{queries.map(q =>
|
{queries.map(q => (
|
||||||
<QueryRow key={q.id} query={q} onKill={onKillQuery} />
|
<QueryRow key={q.id} query={q} onKill={onKillQuery} />
|
||||||
)}
|
))}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, func, shape} = PropTypes
|
const {arrayOf, func, shape} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -37,9 +37,7 @@ class QueryRow extends Component {
|
||||||
{database}
|
{database}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<code>
|
<code>{query}</code>
|
||||||
{query}
|
|
||||||
</code>
|
|
||||||
</td>
|
</td>
|
||||||
<td
|
<td
|
||||||
style={{width: `${QUERIES_TABLE.colRunning}px`}}
|
style={{width: `${QUERIES_TABLE.colRunning}px`}}
|
||||||
|
@ -51,18 +49,20 @@ class QueryRow extends Component {
|
||||||
style={{width: `${QUERIES_TABLE.colKillQuery}px`}}
|
style={{width: `${QUERIES_TABLE.colKillQuery}px`}}
|
||||||
className="text-right"
|
className="text-right"
|
||||||
>
|
>
|
||||||
{this.state.confirmingKill
|
{this.state.confirmingKill ? (
|
||||||
? <ConfirmButtons
|
<ConfirmButtons
|
||||||
onConfirm={this.handleFinishHim}
|
onConfirm={this.handleFinishHim}
|
||||||
onCancel={this.handleShowMercy}
|
onCancel={this.handleShowMercy}
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
/>
|
/>
|
||||||
: <button
|
) : (
|
||||||
className="btn btn-xs btn-danger table--show-on-row-hover"
|
<button
|
||||||
onClick={this.handleInitiateKill}
|
className="btn btn-xs btn-danger table--show-on-row-hover"
|
||||||
>
|
onClick={this.handleInitiateKill}
|
||||||
Kill
|
>
|
||||||
</button>}
|
Kill
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
)
|
)
|
||||||
|
|
|
@ -64,41 +64,36 @@ const RoleRow = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td style={{width: `${ROLES_TABLE.colName}px`}}>
|
<td style={{width: `${ROLES_TABLE.colName}px`}}>{roleName}</td>
|
||||||
{roleName}
|
<td>
|
||||||
|
{allPermissions && allPermissions.length ? (
|
||||||
|
<MultiSelectDropdown
|
||||||
|
items={allPermissions.map(name => ({name}))}
|
||||||
|
selectedItems={perms.map(name => ({name}))}
|
||||||
|
label={perms.length ? '' : 'Select Permissions'}
|
||||||
|
onApply={handleUpdatePermissions}
|
||||||
|
buttonSize="btn-xs"
|
||||||
|
buttonColor="btn-primary"
|
||||||
|
customClass={classnames(`dropdown-${ROLES_TABLE.colPermissions}`, {
|
||||||
|
'admin-table--multi-select-empty': !permissions.length,
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{allPermissions && allPermissions.length
|
{allUsers && allUsers.length ? (
|
||||||
? <MultiSelectDropdown
|
<MultiSelectDropdown
|
||||||
items={allPermissions.map(name => ({name}))}
|
items={allUsers}
|
||||||
selectedItems={perms.map(name => ({name}))}
|
selectedItems={users}
|
||||||
label={perms.length ? '' : 'Select Permissions'}
|
label={users.length ? '' : 'Select Users'}
|
||||||
onApply={handleUpdatePermissions}
|
onApply={handleUpdateUsers}
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
buttonColor="btn-primary"
|
buttonColor="btn-primary"
|
||||||
customClass={classnames(
|
customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
|
||||||
`dropdown-${ROLES_TABLE.colPermissions}`,
|
'admin-table--multi-select-empty': !users.length,
|
||||||
{
|
})}
|
||||||
'admin-table--multi-select-empty': !permissions.length,
|
/>
|
||||||
}
|
) : null}
|
||||||
)}
|
|
||||||
/>
|
|
||||||
: null}
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{allUsers && allUsers.length
|
|
||||||
? <MultiSelectDropdown
|
|
||||||
items={allUsers}
|
|
||||||
selectedItems={users}
|
|
||||||
label={users.length ? '' : 'Select Users'}
|
|
||||||
onApply={handleUpdateUsers}
|
|
||||||
buttonSize="btn-xs"
|
|
||||||
buttonColor="btn-primary"
|
|
||||||
customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
|
|
||||||
'admin-table--multi-select-empty': !users.length,
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
: null}
|
|
||||||
</td>
|
</td>
|
||||||
<DeleteConfirmTableCell
|
<DeleteConfirmTableCell
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
|
|
@ -17,7 +17,7 @@ const RolesTable = ({
|
||||||
onFilter,
|
onFilter,
|
||||||
onUpdateRoleUsers,
|
onUpdateRoleUsers,
|
||||||
onUpdateRolePermissions,
|
onUpdateRolePermissions,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="panel panel-solid">
|
<div className="panel panel-solid">
|
||||||
<FilterBar
|
<FilterBar
|
||||||
type="roles"
|
type="roles"
|
||||||
|
@ -36,30 +36,33 @@ const RolesTable = ({
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{roles.length
|
{roles.length ? (
|
||||||
? roles
|
roles
|
||||||
.filter(r => !r.hidden)
|
.filter(r => !r.hidden)
|
||||||
.map(role =>
|
.map(role => (
|
||||||
<RoleRow
|
<RoleRow
|
||||||
key={role.links.self}
|
key={role.links.self}
|
||||||
allUsers={allUsers}
|
allUsers={allUsers}
|
||||||
allPermissions={permissions}
|
allPermissions={permissions}
|
||||||
role={role}
|
role={role}
|
||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
onUpdateRoleUsers={onUpdateRoleUsers}
|
onUpdateRoleUsers={onUpdateRoleUsers}
|
||||||
onUpdateRolePermissions={onUpdateRolePermissions}
|
onUpdateRolePermissions={onUpdateRolePermissions}
|
||||||
isEditing={role.isEditing}
|
isEditing={role.isEditing}
|
||||||
isNew={role.isNew}
|
isNew={role.isNew}
|
||||||
/>
|
/>
|
||||||
)
|
))
|
||||||
: <EmptyRow tableName={'Roles'} />}
|
) : (
|
||||||
|
<EmptyRow tableName={'Roles'} />
|
||||||
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -22,19 +22,21 @@ class UserNewPassword extends Component {
|
||||||
const {user, isNew} = this.props
|
const {user, isNew} = this.props
|
||||||
return (
|
return (
|
||||||
<td style={{width: `${USERS_TABLE.colPassword}px`}}>
|
<td style={{width: `${USERS_TABLE.colPassword}px`}}>
|
||||||
{isNew
|
{isNew ? (
|
||||||
? <input
|
<input
|
||||||
className="form-control input-xs"
|
className="form-control input-xs"
|
||||||
name="password"
|
name="password"
|
||||||
type="password"
|
type="password"
|
||||||
value={user.password || ''}
|
value={user.password || ''}
|
||||||
placeholder="Password"
|
placeholder="Password"
|
||||||
onChange={this.handleEdit(user)}
|
onChange={this.handleEdit(user)}
|
||||||
onKeyPress={this.handleKeyPress(user)}
|
onKeyPress={this.handleKeyPress(user)}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
autoComplete={false}
|
autoComplete={false}
|
||||||
/>
|
/>
|
||||||
: '--'}
|
) : (
|
||||||
|
'--'
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,9 +75,7 @@ const UserRow = ({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td style={{width: `${USERS_TABLE.colUsername}px`}}>
|
<td style={{width: `${USERS_TABLE.colUsername}px`}}>{name}</td>
|
||||||
{name}
|
|
||||||
</td>
|
|
||||||
<td style={{width: `${USERS_TABLE.colPassword}px`}}>
|
<td style={{width: `${USERS_TABLE.colPassword}px`}}>
|
||||||
<ChangePassRow
|
<ChangePassRow
|
||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
|
@ -86,40 +84,37 @@ const UserRow = ({
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
{hasRoles
|
{hasRoles ? (
|
||||||
? <td>
|
<td>
|
||||||
<MultiSelectDropdown
|
<MultiSelectDropdown
|
||||||
items={allRoles}
|
items={allRoles}
|
||||||
selectedItems={roles.map(r => ({name: r.name}))}
|
selectedItems={roles.map(r => ({name: r.name}))}
|
||||||
label={roles.length ? '' : 'Select Roles'}
|
label={roles.length ? '' : 'Select Roles'}
|
||||||
onApply={handleUpdateRoles}
|
onApply={handleUpdateRoles}
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
buttonColor="btn-primary"
|
buttonColor="btn-primary"
|
||||||
customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, {
|
customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, {
|
||||||
'admin-table--multi-select-empty': !roles.length,
|
'admin-table--multi-select-empty': !roles.length,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
: null}
|
) : null}
|
||||||
<td>
|
<td>
|
||||||
{allPermissions && allPermissions.length
|
{allPermissions && allPermissions.length ? (
|
||||||
? <MultiSelectDropdown
|
<MultiSelectDropdown
|
||||||
items={allPermissions.map(p => ({name: p}))}
|
items={allPermissions.map(p => ({name: p}))}
|
||||||
selectedItems={perms.map(p => ({name: p}))}
|
selectedItems={perms.map(p => ({name: p}))}
|
||||||
label={
|
label={
|
||||||
permissions && permissions.length ? '' : 'Select Permissions'
|
permissions && permissions.length ? '' : 'Select Permissions'
|
||||||
}
|
}
|
||||||
onApply={handleUpdatePermissions}
|
onApply={handleUpdatePermissions}
|
||||||
buttonSize="btn-xs"
|
buttonSize="btn-xs"
|
||||||
buttonColor="btn-primary"
|
buttonColor="btn-primary"
|
||||||
customClass={classnames(
|
customClass={classnames(`dropdown-${USERS_TABLE.colPermissions}`, {
|
||||||
`dropdown-${USERS_TABLE.colPermissions}`,
|
'admin-table--multi-select-empty': !permissions.length,
|
||||||
{
|
})}
|
||||||
'admin-table--multi-select-empty': !permissions.length,
|
/>
|
||||||
}
|
) : null}
|
||||||
)}
|
|
||||||
/>
|
|
||||||
: null}
|
|
||||||
</td>
|
</td>
|
||||||
<DeleteConfirmTableCell
|
<DeleteConfirmTableCell
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
|
|
@ -20,7 +20,7 @@ const UsersTable = ({
|
||||||
onUpdatePermissions,
|
onUpdatePermissions,
|
||||||
onUpdateRoles,
|
onUpdateRoles,
|
||||||
onUpdatePassword,
|
onUpdatePassword,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="panel panel-solid">
|
<div className="panel panel-solid">
|
||||||
<FilterBar
|
<FilterBar
|
||||||
type="users"
|
type="users"
|
||||||
|
@ -40,32 +40,35 @@ const UsersTable = ({
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{users.length
|
{users.length ? (
|
||||||
? users
|
users
|
||||||
.filter(u => !u.hidden)
|
.filter(u => !u.hidden)
|
||||||
.map(user =>
|
.map(user => (
|
||||||
<UserRow
|
<UserRow
|
||||||
key={user.links.self}
|
key={user.links.self}
|
||||||
user={user}
|
user={user}
|
||||||
onEdit={onEdit}
|
onEdit={onEdit}
|
||||||
onSave={onSave}
|
onSave={onSave}
|
||||||
onCancel={onCancel}
|
onCancel={onCancel}
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
isEditing={user.isEditing}
|
isEditing={user.isEditing}
|
||||||
isNew={user.isNew}
|
isNew={user.isNew}
|
||||||
allRoles={allRoles}
|
allRoles={allRoles}
|
||||||
hasRoles={hasRoles}
|
hasRoles={hasRoles}
|
||||||
allPermissions={permissions}
|
allPermissions={permissions}
|
||||||
onUpdatePermissions={onUpdatePermissions}
|
onUpdatePermissions={onUpdatePermissions}
|
||||||
onUpdateRoles={onUpdateRoles}
|
onUpdateRoles={onUpdateRoles}
|
||||||
onUpdatePassword={onUpdatePassword}
|
onUpdatePassword={onUpdatePassword}
|
||||||
/>
|
/>
|
||||||
)
|
))
|
||||||
: <EmptyRow tableName={'Users'} />}
|
) : (
|
||||||
|
<EmptyRow tableName={'Users'} />
|
||||||
|
)}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -51,18 +51,12 @@ const AdminTabs = ({
|
||||||
return (
|
return (
|
||||||
<Tabs className="row">
|
<Tabs className="row">
|
||||||
<TabList customClass="col-md-2 admin-tabs">
|
<TabList customClass="col-md-2 admin-tabs">
|
||||||
{tabs.map((t, i) =>
|
{tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
|
||||||
<Tab key={tabs[i].type}>
|
|
||||||
{tabs[i].type}
|
|
||||||
</Tab>
|
|
||||||
)}
|
|
||||||
</TabList>
|
</TabList>
|
||||||
<TabPanels customClass="col-md-10 admin-tabs--content">
|
<TabPanels customClass="col-md-10 admin-tabs--content">
|
||||||
{tabs.map((t, i) =>
|
{tabs.map((t, i) => (
|
||||||
<TabPanel key={tabs[i].type}>
|
<TabPanel key={tabs[i].type}>{t.component}</TabPanel>
|
||||||
{t.component}
|
))}
|
||||||
</TabPanel>
|
|
||||||
)}
|
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
)
|
)
|
||||||
|
|
|
@ -133,33 +133,33 @@ class AllUsersTable extends Component {
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{users.length
|
{users.length ? (
|
||||||
? users.map(user =>
|
users.map(user => (
|
||||||
<AllUsersTableRow
|
<AllUsersTableRow
|
||||||
user={user}
|
user={user}
|
||||||
key={uuid.v4()}
|
key={uuid.v4()}
|
||||||
organizations={organizations}
|
|
||||||
onAddToOrganization={this.handleAddToOrganization}
|
|
||||||
onRemoveFromOrganization={
|
|
||||||
this.handleRemoveFromOrganization
|
|
||||||
}
|
|
||||||
onChangeSuperAdmin={this.handleChangeSuperAdmin}
|
|
||||||
onDelete={onDeleteUser}
|
|
||||||
meID={meID}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
: <tr className="table-empty-state">
|
|
||||||
<th colSpan="6">
|
|
||||||
<p>No Users to display</p>
|
|
||||||
</th>
|
|
||||||
</tr>}
|
|
||||||
{isCreatingUser
|
|
||||||
? <AllUsersTableRowNew
|
|
||||||
organizations={organizations}
|
organizations={organizations}
|
||||||
onBlur={this.handleBlurCreateUserRow}
|
onAddToOrganization={this.handleAddToOrganization}
|
||||||
onCreateUser={onCreateUser}
|
onRemoveFromOrganization={this.handleRemoveFromOrganization}
|
||||||
|
onChangeSuperAdmin={this.handleChangeSuperAdmin}
|
||||||
|
onDelete={onDeleteUser}
|
||||||
|
meID={meID}
|
||||||
/>
|
/>
|
||||||
: null}
|
))
|
||||||
|
) : (
|
||||||
|
<tr className="table-empty-state">
|
||||||
|
<th colSpan="6">
|
||||||
|
<p>No Users to display</p>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
)}
|
||||||
|
{isCreatingUser ? (
|
||||||
|
<AllUsersTableRowNew
|
||||||
|
organizations={organizations}
|
||||||
|
onBlur={this.handleBlurCreateUserRow}
|
||||||
|
onCreateUser={onCreateUser}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -12,10 +12,9 @@ const AllUsersTableHeader = ({
|
||||||
onChangeAuthConfig,
|
onChangeAuthConfig,
|
||||||
}) => {
|
}) => {
|
||||||
const numUsersString = `${numUsers} User${numUsers === 1 ? '' : 's'}`
|
const numUsersString = `${numUsers} User${numUsers === 1 ? '' : 's'}`
|
||||||
const numOrganizationsString = `${numOrganizations} Org${numOrganizations ===
|
const numOrganizationsString = `${numOrganizations} Org${
|
||||||
1
|
numOrganizations === 1 ? '' : 's'
|
||||||
? ''
|
}`
|
||||||
: 's'}`
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
|
|
|
@ -47,14 +47,14 @@ const AllUsersTableRow = ({
|
||||||
return (
|
return (
|
||||||
<tr className={'chronograf-admin-table--user'}>
|
<tr className={'chronograf-admin-table--user'}>
|
||||||
<td>
|
<td>
|
||||||
{userIsMe
|
{userIsMe ? (
|
||||||
? <strong className="chronograf-user--me">
|
<strong className="chronograf-user--me">
|
||||||
<span className="icon user" />
|
<span className="icon user" />
|
||||||
{user.name}
|
{user.name}
|
||||||
</strong>
|
</strong>
|
||||||
: <strong>
|
) : (
|
||||||
{user.name}
|
<strong>{user.name}</strong>
|
||||||
</strong>}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td style={{width: colOrganizations}}>
|
<td style={{width: colOrganizations}}>
|
||||||
<Tags
|
<Tags
|
||||||
|
@ -65,12 +65,8 @@ const AllUsersTableRow = ({
|
||||||
addMenuChoose={onAddToOrganization(user)}
|
addMenuChoose={onAddToOrganization(user)}
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
<td style={{width: colProvider}}>
|
<td style={{width: colProvider}}>{user.provider}</td>
|
||||||
{user.provider}
|
<td style={{width: colScheme}}>{user.scheme}</td>
|
||||||
</td>
|
|
||||||
<td style={{width: colScheme}}>
|
|
||||||
{user.scheme}
|
|
||||||
</td>
|
|
||||||
<td style={{width: colSuperAdmin}} className="text-center">
|
<td style={{width: colSuperAdmin}} className="text-center">
|
||||||
<SlideToggle
|
<SlideToggle
|
||||||
active={user.superAdmin}
|
active={user.superAdmin}
|
||||||
|
|
|
@ -39,10 +39,9 @@ class OrganizationsTable extends Component {
|
||||||
} = this.props
|
} = this.props
|
||||||
const {isCreatingOrganization} = this.state
|
const {isCreatingOrganization} = this.state
|
||||||
|
|
||||||
const tableTitle = `${organizations.length} Organization${organizations.length ===
|
const tableTitle = `${organizations.length} Organization${
|
||||||
1
|
organizations.length === 1 ? '' : 's'
|
||||||
? ''
|
}`
|
||||||
: 's'}`
|
|
||||||
|
|
||||||
if (!organizations.length) {
|
if (!organizations.length) {
|
||||||
return (
|
return (
|
||||||
|
@ -56,9 +55,7 @@ class OrganizationsTable extends Component {
|
||||||
return (
|
return (
|
||||||
<div className="panel panel-solid">
|
<div className="panel panel-solid">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<h2 className="panel-title">
|
<h2 className="panel-title">{tableTitle}</h2>
|
||||||
{tableTitle}
|
|
||||||
</h2>
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
onClick={this.handleClickCreateOrganization}
|
onClick={this.handleClickCreateOrganization}
|
||||||
|
@ -76,13 +73,13 @@ class OrganizationsTable extends Component {
|
||||||
</div>
|
</div>
|
||||||
<div className="fancytable--th orgs-table--delete" />
|
<div className="fancytable--th orgs-table--delete" />
|
||||||
</div>
|
</div>
|
||||||
{isCreatingOrganization
|
{isCreatingOrganization ? (
|
||||||
? <OrganizationsTableRowNew
|
<OrganizationsTableRowNew
|
||||||
onCreateOrganization={this.handleCreateOrganization}
|
onCreateOrganization={this.handleCreateOrganization}
|
||||||
onCancelCreateOrganization={this.handleCancelCreateOrganization}
|
onCancelCreateOrganization={this.handleCancelCreateOrganization}
|
||||||
/>
|
/>
|
||||||
: null}
|
) : null}
|
||||||
{organizations.map(org =>
|
{organizations.map(org => (
|
||||||
<OrganizationsTableRow
|
<OrganizationsTableRow
|
||||||
key={uuid.v4()}
|
key={uuid.v4()}
|
||||||
organization={org}
|
organization={org}
|
||||||
|
@ -91,7 +88,7 @@ class OrganizationsTable extends Component {
|
||||||
onChooseDefaultRole={onChooseDefaultRole}
|
onChooseDefaultRole={onChooseDefaultRole}
|
||||||
currentOrganization={currentOrganization}
|
currentOrganization={currentOrganization}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -14,19 +14,21 @@ import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin'
|
||||||
import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
|
import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
|
||||||
|
|
||||||
const OrganizationsTableRowDeleteButton = ({organization, onClickDelete}) =>
|
const OrganizationsTableRowDeleteButton = ({organization, onClickDelete}) =>
|
||||||
organization.id === DEFAULT_ORG_ID
|
organization.id === DEFAULT_ORG_ID ? (
|
||||||
? <button
|
<button
|
||||||
className="btn btn-sm btn-default btn-square orgs-table--delete"
|
className="btn btn-sm btn-default btn-square orgs-table--delete"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
>
|
>
|
||||||
<span className="icon trash" />
|
<span className="icon trash" />
|
||||||
</button>
|
</button>
|
||||||
: <button
|
) : (
|
||||||
className="btn btn-sm btn-default btn-square"
|
<button
|
||||||
onClick={onClickDelete}
|
className="btn btn-sm btn-default btn-square"
|
||||||
>
|
onClick={onClickDelete}
|
||||||
<span className="icon trash" />
|
>
|
||||||
</button>
|
<span className="icon trash" />
|
||||||
|
</button>
|
||||||
|
)
|
||||||
|
|
||||||
class OrganizationsTableRow extends Component {
|
class OrganizationsTableRow extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
@ -81,16 +83,18 @@ class OrganizationsTableRow extends Component {
|
||||||
return (
|
return (
|
||||||
<div className="fancytable--row">
|
<div className="fancytable--row">
|
||||||
<div className="fancytable--td orgs-table--active">
|
<div className="fancytable--td orgs-table--active">
|
||||||
{organization.id === currentOrganization.id
|
{organization.id === currentOrganization.id ? (
|
||||||
? <button className="btn btn-sm btn-success">
|
<button className="btn btn-sm btn-success">
|
||||||
<span className="icon checkmark" /> Current
|
<span className="icon checkmark" /> Current
|
||||||
</button>
|
</button>
|
||||||
: <button
|
) : (
|
||||||
className="btn btn-sm btn-default"
|
<button
|
||||||
onClick={this.handleChangeCurrentOrganization}
|
className="btn btn-sm btn-default"
|
||||||
>
|
onClick={this.handleChangeCurrentOrganization}
|
||||||
<span className="icon shuffle" /> Switch to
|
>
|
||||||
</button>}
|
<span className="icon shuffle" /> Switch to
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<InputClickToEdit
|
<InputClickToEdit
|
||||||
value={organization.name}
|
value={organization.name}
|
||||||
|
@ -105,19 +109,21 @@ class OrganizationsTableRow extends Component {
|
||||||
className="dropdown-stretch"
|
className="dropdown-stretch"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{isDeleting
|
{isDeleting ? (
|
||||||
? <ConfirmButtons
|
<ConfirmButtons
|
||||||
item={organization}
|
item={organization}
|
||||||
onCancel={this.handleDismissDeleteConfirmation}
|
onCancel={this.handleDismissDeleteConfirmation}
|
||||||
onConfirm={this.handleDeleteOrg}
|
onConfirm={this.handleDeleteOrg}
|
||||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||||
confirmLeft={true}
|
confirmLeft={true}
|
||||||
confirmTitle="Delete"
|
confirmTitle="Delete"
|
||||||
/>
|
/>
|
||||||
: <OrganizationsTableRowDeleteButton
|
) : (
|
||||||
organization={organization}
|
<OrganizationsTableRowDeleteButton
|
||||||
onClickDelete={this.handleDeleteClick}
|
organization={organization}
|
||||||
/>}
|
onClickDelete={this.handleDeleteClick}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,9 +55,7 @@ class ProvidersTable extends Component {
|
||||||
return (
|
return (
|
||||||
<div className="panel panel-solid">
|
<div className="panel panel-solid">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<h2 className="panel-title">
|
<h2 className="panel-title">{tableTitle}</h2>
|
||||||
{tableTitle}
|
|
||||||
</h2>
|
|
||||||
<button
|
<button
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
onClick={this.handleClickCreateMap}
|
onClick={this.handleClickCreateMap}
|
||||||
|
@ -66,58 +64,58 @@ class ProvidersTable extends Component {
|
||||||
<span className="icon plus" /> Create Mapping
|
<span className="icon plus" /> Create Mapping
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{mappings.length || isCreatingMap
|
{mappings.length || isCreatingMap ? (
|
||||||
? <div className="panel-body">
|
<div className="panel-body">
|
||||||
<div className="fancytable--labels">
|
<div className="fancytable--labels">
|
||||||
<div className="fancytable--th provider--scheme">Scheme</div>
|
<div className="fancytable--th provider--scheme">Scheme</div>
|
||||||
<div className="fancytable--th provider--provider">
|
<div className="fancytable--th provider--provider">Provider</div>
|
||||||
Provider
|
<div className="fancytable--th provider--providerorg">
|
||||||
</div>
|
Provider Org
|
||||||
<div className="fancytable--th provider--providerorg">
|
|
||||||
Provider Org
|
|
||||||
</div>
|
|
||||||
<div className="fancytable--th provider--arrow" />
|
|
||||||
<div className="fancytable--th provider--redirect">
|
|
||||||
Organization
|
|
||||||
</div>
|
|
||||||
<div className="fancytable--th provider--delete" />
|
|
||||||
</div>
|
</div>
|
||||||
{mappings.map((mapping, i) =>
|
<div className="fancytable--th provider--arrow" />
|
||||||
<ProvidersTableRow
|
<div className="fancytable--th provider--redirect">
|
||||||
key={uuid.v4()}
|
Organization
|
||||||
mapping={mapping}
|
</div>
|
||||||
organizations={organizations}
|
<div className="fancytable--th provider--delete" />
|
||||||
schemes={SCHEMES}
|
|
||||||
onDelete={onDeleteMap}
|
|
||||||
onUpdate={onUpdateMap}
|
|
||||||
rowIndex={i + 1}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{isCreatingMap
|
|
||||||
? <ProvidersTableRowNew
|
|
||||||
organizations={organizations}
|
|
||||||
schemes={SCHEMES}
|
|
||||||
onCreate={this.handleCreateMap}
|
|
||||||
onCancel={this.handleCancelCreateMap}
|
|
||||||
rowIndex={mappings.length + 1}
|
|
||||||
/>
|
|
||||||
: null}
|
|
||||||
</div>
|
</div>
|
||||||
: <div className="panel-body">
|
{mappings.map((mapping, i) => (
|
||||||
<div className="generic-empty-state">
|
<ProvidersTableRow
|
||||||
<h4 style={{margin: '50px 0'}}>
|
key={uuid.v4()}
|
||||||
Looks like you have no mappings<br />
|
mapping={mapping}
|
||||||
New users will not be able to sign up automatically
|
organizations={organizations}
|
||||||
</h4>
|
schemes={SCHEMES}
|
||||||
<button
|
onDelete={onDeleteMap}
|
||||||
className="btn btn-sm btn-primary"
|
onUpdate={onUpdateMap}
|
||||||
onClick={this.handleClickCreateMap}
|
rowIndex={i + 1}
|
||||||
disabled={isCreatingMap}
|
/>
|
||||||
>
|
))}
|
||||||
<span className="icon plus" /> Create Mapping
|
{isCreatingMap ? (
|
||||||
</button>
|
<ProvidersTableRowNew
|
||||||
</div>
|
organizations={organizations}
|
||||||
</div>}
|
schemes={SCHEMES}
|
||||||
|
onCreate={this.handleCreateMap}
|
||||||
|
onCancel={this.handleCancelCreateMap}
|
||||||
|
rowIndex={mappings.length + 1}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="panel-body">
|
||||||
|
<div className="generic-empty-state">
|
||||||
|
<h4 style={{margin: '50px 0'}}>
|
||||||
|
Looks like you have no mappings<br />
|
||||||
|
New users will not be able to sign up automatically
|
||||||
|
</h4>
|
||||||
|
<button
|
||||||
|
className="btn btn-sm btn-primary"
|
||||||
|
onClick={this.handleClickCreateMap}
|
||||||
|
disabled={isCreatingMap}
|
||||||
|
>
|
||||||
|
<span className="icon plus" /> Create Mapping
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -106,20 +106,22 @@ class ProvidersTableRow extends Component {
|
||||||
disabled={isDefaultMapping}
|
disabled={isDefaultMapping}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{isDeleting
|
{isDeleting ? (
|
||||||
? <ConfirmButtons
|
<ConfirmButtons
|
||||||
item={mapping}
|
item={mapping}
|
||||||
onCancel={this.handleDismissDeleteConfirmation}
|
onCancel={this.handleDismissDeleteConfirmation}
|
||||||
onConfirm={this.handleDeleteMap}
|
onConfirm={this.handleDeleteMap}
|
||||||
onClickOutside={this.handleDismissDeleteConfirmation}
|
onClickOutside={this.handleDismissDeleteConfirmation}
|
||||||
confirmTitle="Delete"
|
confirmTitle="Delete"
|
||||||
/>
|
/>
|
||||||
: <button
|
) : (
|
||||||
className="btn btn-sm btn-default btn-square"
|
<button
|
||||||
onClick={this.handleDeleteClick}
|
className="btn btn-sm btn-default btn-square"
|
||||||
>
|
onClick={this.handleDeleteClick}
|
||||||
<span className="icon trash" />
|
>
|
||||||
</button>}
|
<span className="icon trash" />
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,29 +71,31 @@ class UsersTable extends Component {
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{isCreatingUser
|
{isCreatingUser ? (
|
||||||
? <UsersTableRowNew
|
<UsersTableRowNew
|
||||||
|
organization={organization}
|
||||||
|
onBlur={this.handleBlurCreateUserRow}
|
||||||
|
onCreateUser={onCreateUser}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
{users.length ? (
|
||||||
|
users.map(user => (
|
||||||
|
<UsersTableRow
|
||||||
|
user={user}
|
||||||
|
key={uuid.v4()}
|
||||||
organization={organization}
|
organization={organization}
|
||||||
onBlur={this.handleBlurCreateUserRow}
|
onChangeUserRole={this.handleChangeUserRole}
|
||||||
onCreateUser={onCreateUser}
|
onDelete={this.handleDeleteUser}
|
||||||
|
meID={meID}
|
||||||
/>
|
/>
|
||||||
: null}
|
))
|
||||||
{users.length
|
) : (
|
||||||
? users.map(user =>
|
<tr className="table-empty-state">
|
||||||
<UsersTableRow
|
<th colSpan="5">
|
||||||
user={user}
|
<p>No Users to display</p>
|
||||||
key={uuid.v4()}
|
</th>
|
||||||
organization={organization}
|
</tr>
|
||||||
onChangeUserRole={this.handleChangeUserRole}
|
)}
|
||||||
onDelete={this.handleDeleteUser}
|
|
||||||
meID={meID}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
: <tr className="table-empty-state">
|
|
||||||
<th colSpan="5">
|
|
||||||
<p>No Users to display</p>
|
|
||||||
</th>
|
|
||||||
</tr>}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -29,14 +29,14 @@ const UsersTableRow = ({
|
||||||
return (
|
return (
|
||||||
<tr className={'chronograf-admin-table--user'}>
|
<tr className={'chronograf-admin-table--user'}>
|
||||||
<td>
|
<td>
|
||||||
{userIsMe
|
{userIsMe ? (
|
||||||
? <strong className="chronograf-user--me">
|
<strong className="chronograf-user--me">
|
||||||
<span className="icon user" />
|
<span className="icon user" />
|
||||||
{user.name}
|
{user.name}
|
||||||
</strong>
|
</strong>
|
||||||
: <strong>
|
) : (
|
||||||
{user.name}
|
<strong>{user.name}</strong>
|
||||||
</strong>}
|
)}
|
||||||
</td>
|
</td>
|
||||||
<td style={{width: colRole}}>
|
<td style={{width: colRole}}>
|
||||||
<span className="chronograf-user--role">
|
<span className="chronograf-user--role">
|
||||||
|
@ -50,12 +50,8 @@ const UsersTableRow = ({
|
||||||
/>
|
/>
|
||||||
</span>
|
</span>
|
||||||
</td>
|
</td>
|
||||||
<td style={{width: colProvider}}>
|
<td style={{width: colProvider}}>{user.provider}</td>
|
||||||
{user.provider}
|
<td style={{width: colScheme}}>{user.scheme}</td>
|
||||||
</td>
|
|
||||||
<td style={{width: colScheme}}>
|
|
||||||
{user.scheme}
|
|
||||||
</td>
|
|
||||||
<DeleteConfirmTableCell
|
<DeleteConfirmTableCell
|
||||||
text="Remove"
|
text="Remove"
|
||||||
onDelete={onDelete}
|
onDelete={onDelete}
|
||||||
|
|
|
@ -165,37 +165,39 @@ class AdminInfluxDBPage extends Component {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<FancyScrollbar className="page-contents">
|
<FancyScrollbar className="page-contents">
|
||||||
{users
|
{users ? (
|
||||||
? <div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<AdminTabs
|
<AdminTabs
|
||||||
users={users}
|
users={users}
|
||||||
roles={roles}
|
roles={roles}
|
||||||
source={source}
|
source={source}
|
||||||
hasRoles={hasRoles}
|
hasRoles={hasRoles}
|
||||||
permissions={allowed}
|
permissions={allowed}
|
||||||
onFilterUsers={filterUsers}
|
onFilterUsers={filterUsers}
|
||||||
onFilterRoles={filterRoles}
|
onFilterRoles={filterRoles}
|
||||||
onEditUser={this.handleEditUser}
|
onEditUser={this.handleEditUser}
|
||||||
onEditRole={this.handleEditRole}
|
onEditRole={this.handleEditRole}
|
||||||
onSaveUser={this.handleSaveUser}
|
onSaveUser={this.handleSaveUser}
|
||||||
onSaveRole={this.handleSaveRole}
|
onSaveRole={this.handleSaveRole}
|
||||||
onDeleteUser={this.handleDeleteUser}
|
onDeleteUser={this.handleDeleteUser}
|
||||||
onDeleteRole={this.handleDeleteRole}
|
onDeleteRole={this.handleDeleteRole}
|
||||||
onClickCreate={this.handleClickCreate}
|
onClickCreate={this.handleClickCreate}
|
||||||
onCancelEditUser={this.handleCancelEditUser}
|
onCancelEditUser={this.handleCancelEditUser}
|
||||||
onCancelEditRole={this.handleCancelEditRole}
|
onCancelEditRole={this.handleCancelEditRole}
|
||||||
isEditingUsers={users.some(u => u.isEditing)}
|
isEditingUsers={users.some(u => u.isEditing)}
|
||||||
isEditingRoles={roles.some(r => r.isEditing)}
|
isEditingRoles={roles.some(r => r.isEditing)}
|
||||||
onUpdateRoleUsers={this.handleUpdateRoleUsers}
|
onUpdateRoleUsers={this.handleUpdateRoleUsers}
|
||||||
onUpdateUserRoles={this.handleUpdateUserRoles}
|
onUpdateUserRoles={this.handleUpdateUserRoles}
|
||||||
onUpdateUserPassword={this.handleUpdateUserPassword}
|
onUpdateUserPassword={this.handleUpdateUserPassword}
|
||||||
onUpdateRolePermissions={this.handleUpdateRolePermissions}
|
onUpdateRolePermissions={this.handleUpdateRolePermissions}
|
||||||
onUpdateUserPermissions={this.handleUpdateUserPermissions}
|
onUpdateUserPermissions={this.handleUpdateUserPermissions}
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
: <div className="page-spinner" />}
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="page-spinner" />
|
||||||
|
)}
|
||||||
</FancyScrollbar>
|
</FancyScrollbar>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@ import {connect} from 'react-redux'
|
||||||
import AdminTabs from 'src/admin/components/chronograf/AdminTabs'
|
import AdminTabs from 'src/admin/components/chronograf/AdminTabs'
|
||||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||||
|
|
||||||
const AdminChronografPage = ({me}) =>
|
const AdminChronografPage = ({me}) => (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="page-header__container">
|
<div className="page-header__container">
|
||||||
|
@ -22,6 +22,7 @@ const AdminChronografPage = ({me}) =>
|
||||||
</div>
|
</div>
|
||||||
</FancyScrollbar>
|
</FancyScrollbar>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,10 @@ import {proxy} from 'utils/queryUrlGenerator'
|
||||||
export const getAlerts = (source, timeRange, limit) =>
|
export const getAlerts = (source, timeRange, limit) =>
|
||||||
proxy({
|
proxy({
|
||||||
source,
|
source,
|
||||||
query: `SELECT host, value, level, alertName FROM alerts WHERE time >= '${timeRange.lower}' AND time <= '${timeRange.upper}' ORDER BY time desc ${limit
|
query: `SELECT host, value, level, alertName FROM alerts WHERE time >= '${
|
||||||
? `LIMIT ${limit}`
|
timeRange.lower
|
||||||
: ''}`,
|
}' AND time <= '${timeRange.upper}' ORDER BY time desc ${
|
||||||
|
limit ? `LIMIT ${limit}` : ''
|
||||||
|
}`,
|
||||||
db: 'chronograf',
|
db: 'chronograf',
|
||||||
})
|
})
|
||||||
|
|
|
@ -79,121 +79,125 @@ class AlertsTable extends Component {
|
||||||
this.state.sortDirection
|
this.state.sortDirection
|
||||||
)
|
)
|
||||||
const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
|
const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
|
||||||
return this.props.alerts.length
|
return this.props.alerts.length ? (
|
||||||
? <div className="alert-history-table">
|
<div className="alert-history-table">
|
||||||
<div className="alert-history-table--thead">
|
<div className="alert-history-table--thead">
|
||||||
<div
|
<div
|
||||||
onClick={this.changeSort('name')}
|
onClick={this.changeSort('name')}
|
||||||
className={this.sortableClasses('name')}
|
className={this.sortableClasses('name')}
|
||||||
style={{width: colName}}
|
style={{width: colName}}
|
||||||
>
|
>
|
||||||
Name
|
Name
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={this.changeSort('level')}
|
onClick={this.changeSort('level')}
|
||||||
className={this.sortableClasses('level')}
|
className={this.sortableClasses('level')}
|
||||||
style={{width: colLevel}}
|
style={{width: colLevel}}
|
||||||
>
|
>
|
||||||
Level
|
Level
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={this.changeSort('time')}
|
onClick={this.changeSort('time')}
|
||||||
className={this.sortableClasses('time')}
|
className={this.sortableClasses('time')}
|
||||||
style={{width: colTime}}
|
style={{width: colTime}}
|
||||||
>
|
>
|
||||||
Time
|
Time
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={this.changeSort('host')}
|
onClick={this.changeSort('host')}
|
||||||
className={this.sortableClasses('host')}
|
className={this.sortableClasses('host')}
|
||||||
style={{width: colHost}}
|
style={{width: colHost}}
|
||||||
>
|
>
|
||||||
Host
|
Host
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
onClick={this.changeSort('value')}
|
onClick={this.changeSort('value')}
|
||||||
className={this.sortableClasses('value')}
|
className={this.sortableClasses('value')}
|
||||||
style={{width: colValue}}
|
style={{width: colValue}}
|
||||||
>
|
>
|
||||||
Value
|
Value
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<InfiniteScroll
|
|
||||||
className="alert-history-table--tbody"
|
|
||||||
itemHeight={25}
|
|
||||||
items={alerts.map(({name, level, time, host, value}) => {
|
|
||||||
return (
|
|
||||||
<div className="alert-history-table--tr" key={uuid.v4()}>
|
|
||||||
<div
|
|
||||||
className="alert-history-table--td"
|
|
||||||
style={{width: colName}}
|
|
||||||
>
|
|
||||||
{name}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
|
|
||||||
style={{width: colLevel}}
|
|
||||||
>
|
|
||||||
<span
|
|
||||||
className={classnames(
|
|
||||||
'table-dot',
|
|
||||||
{'dot-critical': level === 'CRITICAL'},
|
|
||||||
{'dot-success': level === 'OK'}
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="alert-history-table--td"
|
|
||||||
style={{width: colTime}}
|
|
||||||
>
|
|
||||||
{new Date(Number(time)).toISOString()}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="alert-history-table--td alert-history-table--host"
|
|
||||||
style={{width: colHost}}
|
|
||||||
>
|
|
||||||
<Link to={`/sources/${id}/hosts/${host}`} title={host}>
|
|
||||||
{host}
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
className="alert-history-table--td"
|
|
||||||
style={{width: colValue}}
|
|
||||||
>
|
|
||||||
{value}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})}
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
: this.renderTableEmpty()
|
<InfiniteScroll
|
||||||
|
className="alert-history-table--tbody"
|
||||||
|
itemHeight={25}
|
||||||
|
items={alerts.map(({name, level, time, host, value}) => {
|
||||||
|
return (
|
||||||
|
<div className="alert-history-table--tr" key={uuid.v4()}>
|
||||||
|
<div
|
||||||
|
className="alert-history-table--td"
|
||||||
|
style={{width: colName}}
|
||||||
|
>
|
||||||
|
{name}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
|
||||||
|
style={{width: colLevel}}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
className={classnames(
|
||||||
|
'table-dot',
|
||||||
|
{'dot-critical': level === 'CRITICAL'},
|
||||||
|
{'dot-success': level === 'OK'}
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="alert-history-table--td"
|
||||||
|
style={{width: colTime}}
|
||||||
|
>
|
||||||
|
{new Date(Number(time)).toISOString()}
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="alert-history-table--td alert-history-table--host"
|
||||||
|
style={{width: colHost}}
|
||||||
|
>
|
||||||
|
<Link to={`/sources/${id}/hosts/${host}`} title={host}>
|
||||||
|
{host}
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
className="alert-history-table--td"
|
||||||
|
style={{width: colValue}}
|
||||||
|
>
|
||||||
|
{value}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
this.renderTableEmpty()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
renderTableEmpty() {
|
renderTableEmpty() {
|
||||||
const {source: {id}, shouldNotBeFilterable} = this.props
|
const {source: {id}, shouldNotBeFilterable} = this.props
|
||||||
|
|
||||||
return shouldNotBeFilterable
|
return shouldNotBeFilterable ? (
|
||||||
? <div className="graph-empty">
|
<div className="graph-empty">
|
||||||
<p>
|
<p>
|
||||||
Learn how to configure your first <strong>Rule</strong> in<br />
|
Learn how to configure your first <strong>Rule</strong> in<br />
|
||||||
the <em>Getting Started</em> guide
|
the <em>Getting Started</em> guide
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
: <div className="generic-empty-state">
|
) : (
|
||||||
<h4 className="no-user-select">There are no Alerts to display</h4>
|
<div className="generic-empty-state">
|
||||||
<br />
|
<h4 className="no-user-select">There are no Alerts to display</h4>
|
||||||
<h6 className="no-user-select">
|
<br />
|
||||||
Try changing the Time Range or
|
<h6 className="no-user-select">
|
||||||
<Link
|
Try changing the Time Range or
|
||||||
style={{marginLeft: '10px'}}
|
<Link
|
||||||
to={`/sources/${id}/alert-rules/new`}
|
style={{marginLeft: '10px'}}
|
||||||
className="btn btn-primary btn-sm"
|
to={`/sources/${id}/alert-rules/new`}
|
||||||
>
|
className="btn btn-primary btn-sm"
|
||||||
Create an Alert Rule
|
>
|
||||||
</Link>
|
Create an Alert Rule
|
||||||
</h6>
|
</Link>
|
||||||
</div>
|
</h6>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
|
@ -205,35 +209,33 @@ class AlertsTable extends Component {
|
||||||
alertsCount,
|
alertsCount,
|
||||||
} = this.props
|
} = this.props
|
||||||
|
|
||||||
return shouldNotBeFilterable
|
return shouldNotBeFilterable ? (
|
||||||
? <div className="alerts-widget">
|
<div className="alerts-widget">
|
||||||
{this.renderTable()}
|
{this.renderTable()}
|
||||||
{limit && alertsCount
|
{limit && alertsCount ? (
|
||||||
? <button
|
<button
|
||||||
className="btn btn-sm btn-default btn-block"
|
className="btn btn-sm btn-default btn-block"
|
||||||
onClick={onGetMoreAlerts}
|
onClick={onGetMoreAlerts}
|
||||||
disabled={isAlertsMaxedOut}
|
disabled={isAlertsMaxedOut}
|
||||||
style={{marginBottom: '20px'}}
|
style={{marginBottom: '20px'}}
|
||||||
>
|
>
|
||||||
{isAlertsMaxedOut
|
{isAlertsMaxedOut
|
||||||
? `All ${alertsCount} Alerts displayed`
|
? `All ${alertsCount} Alerts displayed`
|
||||||
: 'Load next 30 Alerts'}
|
: 'Load next 30 Alerts'}
|
||||||
</button>
|
</button>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
: <div className="panel">
|
) : (
|
||||||
<div className="panel-heading">
|
<div className="panel">
|
||||||
<h2 className="panel-title">
|
<div className="panel-heading">
|
||||||
{this.props.alerts.length} Alerts
|
<h2 className="panel-title">{this.props.alerts.length} Alerts</h2>
|
||||||
</h2>
|
{this.props.alerts.length ? (
|
||||||
{this.props.alerts.length
|
<SearchBar onSearch={this.filterAlerts} />
|
||||||
? <SearchBar onSearch={this.filterAlerts} />
|
) : null}
|
||||||
: null}
|
|
||||||
</div>
|
|
||||||
<div className="panel-body">
|
|
||||||
{this.renderTable()}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div className="panel-body">{this.renderTable()}</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,9 @@ class AlertsApp extends Component {
|
||||||
alerts: [],
|
alerts: [],
|
||||||
timeRange: {
|
timeRange: {
|
||||||
upper: moment().format(),
|
upper: moment().format(),
|
||||||
lower: moment().subtract(lowerInSec || oneDayInSec, 'seconds').format(),
|
lower: moment()
|
||||||
|
.subtract(lowerInSec || oneDayInSec, 'seconds')
|
||||||
|
.format(),
|
||||||
},
|
},
|
||||||
limit: props.limit || 0, // only used if AlertsApp receives a limit prop
|
limit: props.limit || 0, // only used if AlertsApp receives a limit prop
|
||||||
limitMultiplier: 1, // only used if AlertsApp receives a limit prop
|
limitMultiplier: 1, // only used if AlertsApp receives a limit prop
|
||||||
|
@ -118,17 +120,19 @@ class AlertsApp extends Component {
|
||||||
const {source, isWidget, limit} = this.props
|
const {source, isWidget, limit} = this.props
|
||||||
const {isAlertsMaxedOut, alerts} = this.state
|
const {isAlertsMaxedOut, alerts} = this.state
|
||||||
|
|
||||||
return this.state.hasKapacitor
|
return this.state.hasKapacitor ? (
|
||||||
? <AlertsTable
|
<AlertsTable
|
||||||
source={source}
|
source={source}
|
||||||
alerts={this.state.alerts}
|
alerts={this.state.alerts}
|
||||||
shouldNotBeFilterable={isWidget}
|
shouldNotBeFilterable={isWidget}
|
||||||
limit={limit}
|
limit={limit}
|
||||||
onGetMoreAlerts={this.handleGetMoreAlerts}
|
onGetMoreAlerts={this.handleGetMoreAlerts}
|
||||||
isAlertsMaxedOut={isAlertsMaxedOut}
|
isAlertsMaxedOut={isAlertsMaxedOut}
|
||||||
alertsCount={alerts.length}
|
alertsCount={alerts.length}
|
||||||
/>
|
/>
|
||||||
: <NoKapacitorError source={source} />
|
) : (
|
||||||
|
<NoKapacitorError source={source} />
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
handleApplyTime = timeRange => {
|
handleApplyTime = timeRange => {
|
||||||
|
@ -143,33 +147,33 @@ class AlertsApp extends Component {
|
||||||
return <div className="page-spinner" />
|
return <div className="page-spinner" />
|
||||||
}
|
}
|
||||||
|
|
||||||
return isWidget
|
return isWidget ? (
|
||||||
? this.renderSubComponents()
|
this.renderSubComponents()
|
||||||
: <div className="page alert-history-page">
|
) : (
|
||||||
<div className="page-header">
|
<div className="page alert-history-page">
|
||||||
<div className="page-header__container">
|
<div className="page-header">
|
||||||
<div className="page-header__left">
|
<div className="page-header__container">
|
||||||
<h1 className="page-header__title">Alert History</h1>
|
<div className="page-header__left">
|
||||||
</div>
|
<h1 className="page-header__title">Alert History</h1>
|
||||||
<div className="page-header__right">
|
|
||||||
<SourceIndicator />
|
|
||||||
<CustomTimeRangeDropdown
|
|
||||||
onApplyTimeRange={this.handleApplyTime}
|
|
||||||
timeRange={timeRange}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div className="page-header__right">
|
||||||
<div className="page-contents">
|
<SourceIndicator />
|
||||||
<div className="container-fluid">
|
<CustomTimeRangeDropdown
|
||||||
<div className="row">
|
onApplyTimeRange={this.handleApplyTime}
|
||||||
<div className="col-md-12">
|
timeRange={timeRange}
|
||||||
{this.renderSubComponents()}
|
/>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="page-contents">
|
||||||
|
<div className="container-fluid">
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-md-12">{this.renderSubComponents()}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,12 +20,12 @@ const Login = ({authData: {auth}}) => {
|
||||||
<strong>{VERSION}</strong> / Time-Series Data Visualization
|
<strong>{VERSION}</strong> / Time-Series Data Visualization
|
||||||
</p>
|
</p>
|
||||||
{auth.links &&
|
{auth.links &&
|
||||||
auth.links.map(({name, login, label}) =>
|
auth.links.map(({name, login, label}) => (
|
||||||
<a key={name} className="btn btn-primary" href={login}>
|
<a key={name} className="btn btn-primary" href={login}>
|
||||||
<span className={`icon ${name}`} />
|
<span className={`icon ${name}`} />
|
||||||
Log in with {label}
|
Log in with {label}
|
||||||
</a>
|
</a>
|
||||||
)}
|
))}
|
||||||
</SplashPage>
|
</SplashPage>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -65,31 +65,31 @@ class Purgatory extends Component {
|
||||||
<Notifications />
|
<Notifications />
|
||||||
<SplashPage>
|
<SplashPage>
|
||||||
<div className="auth--purgatory">
|
<div className="auth--purgatory">
|
||||||
<h3>
|
<h3>{name}</h3>
|
||||||
{name}
|
|
||||||
</h3>
|
|
||||||
<h6>
|
<h6>
|
||||||
{subHeading}{' '}
|
{subHeading}{' '}
|
||||||
<code>
|
<code>
|
||||||
{scheme}/{provider}
|
{scheme}/{provider}
|
||||||
</code>
|
</code>
|
||||||
</h6>
|
</h6>
|
||||||
{rolesAndOrgs.length
|
{rolesAndOrgs.length ? (
|
||||||
? <div className="auth--list">
|
<div className="auth--list">
|
||||||
{rolesAndOrgs.map((rag, i) =>
|
{rolesAndOrgs.map((rag, i) => (
|
||||||
<PurgatoryAuthItem
|
<PurgatoryAuthItem
|
||||||
key={i}
|
key={i}
|
||||||
roleAndOrg={rag}
|
roleAndOrg={rag}
|
||||||
superAdmin={superAdmin}
|
superAdmin={superAdmin}
|
||||||
onClickLogin={handleClickLogin({
|
onClickLogin={handleClickLogin({
|
||||||
router,
|
router,
|
||||||
links,
|
links,
|
||||||
meChangeOrganization,
|
meChangeOrganization,
|
||||||
})}
|
})}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
: <p>You are a Lost Soul</p>}
|
) : (
|
||||||
|
<p>You are a Lost Soul</p>
|
||||||
|
)}
|
||||||
<a href={logoutLink} className="btn btn-sm btn-link auth--logout">
|
<a href={logoutLink} className="btn btn-sm btn-link auth--logout">
|
||||||
Log out
|
Log out
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
|
||||||
|
|
||||||
import {isUserAuthorized, VIEWER_ROLE} from 'src/auth/Authorized'
|
import {isUserAuthorized, VIEWER_ROLE} from 'src/auth/Authorized'
|
||||||
|
|
||||||
const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) =>
|
const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) => (
|
||||||
<div
|
<div
|
||||||
className={
|
className={
|
||||||
roleAndOrg.currentOrganization
|
roleAndOrg.currentOrganization
|
||||||
|
@ -12,24 +12,23 @@ const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) =>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
<div className="auth--list-info">
|
<div className="auth--list-info">
|
||||||
<div className="auth--list-org">
|
<div className="auth--list-org">{roleAndOrg.organization.name}</div>
|
||||||
{roleAndOrg.organization.name}
|
<div className="auth--list-role">{roleAndOrg.role}</div>
|
||||||
</div>
|
|
||||||
<div className="auth--list-role">
|
|
||||||
{roleAndOrg.role}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{superAdmin || isUserAuthorized(roleAndOrg.role, VIEWER_ROLE)
|
{superAdmin || isUserAuthorized(roleAndOrg.role, VIEWER_ROLE) ? (
|
||||||
? <button
|
<button
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
onClick={onClickLogin(roleAndOrg.organization)}
|
onClick={onClickLogin(roleAndOrg.organization)}
|
||||||
>
|
>
|
||||||
Log in
|
Log in
|
||||||
</button>
|
</button>
|
||||||
: <span className="auth--list-blocked">
|
) : (
|
||||||
Contact your Admin<br />for access
|
<span className="auth--list-blocked">
|
||||||
</span>}
|
Contact your Admin<br />for access
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {bool, func, shape, string} = PropTypes
|
const {bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -91,9 +91,7 @@ class AxesOptions extends Component {
|
||||||
autoHide={false}
|
autoHide={false}
|
||||||
>
|
>
|
||||||
<div className="display-options--cell-wrapper">
|
<div className="display-options--cell-wrapper">
|
||||||
<h5 className="display-options--header">
|
<h5 className="display-options--header">{menuOption} Controls</h5>
|
||||||
{menuOption} Controls
|
|
||||||
</h5>
|
|
||||||
<form autoComplete="off" className="form-group-wrapper">
|
<form autoComplete="off" className="form-group-wrapper">
|
||||||
<div className="form-group col-sm-12">
|
<div className="form-group col-sm-12">
|
||||||
<label htmlFor="prefix">Title</label>
|
<label htmlFor="prefix">Title</label>
|
||||||
|
|
|
@ -318,27 +318,29 @@ class CellEditorOverlay extends Component {
|
||||||
isDisplayOptionsTabActive={isDisplayOptionsTabActive}
|
isDisplayOptionsTabActive={isDisplayOptionsTabActive}
|
||||||
onClickDisplayOptions={this.handleClickDisplayOptionsTab}
|
onClickDisplayOptions={this.handleClickDisplayOptionsTab}
|
||||||
/>
|
/>
|
||||||
{isDisplayOptionsTabActive
|
{isDisplayOptionsTabActive ? (
|
||||||
? <DisplayOptions
|
<DisplayOptions
|
||||||
queryConfigs={queriesWorkingDraft}
|
queryConfigs={queriesWorkingDraft}
|
||||||
onToggleStaticLegend={this.handleToggleStaticLegend}
|
onToggleStaticLegend={this.handleToggleStaticLegend}
|
||||||
staticLegend={staticLegend}
|
staticLegend={staticLegend}
|
||||||
onResetFocus={this.handleResetFocus}
|
onResetFocus={this.handleResetFocus}
|
||||||
/>
|
/>
|
||||||
: <QueryMaker
|
) : (
|
||||||
source={this.getSource()}
|
<QueryMaker
|
||||||
templates={templates}
|
source={this.getSource()}
|
||||||
queries={queriesWorkingDraft}
|
templates={templates}
|
||||||
actions={queryActions}
|
queries={queriesWorkingDraft}
|
||||||
autoRefresh={autoRefresh}
|
actions={queryActions}
|
||||||
timeRange={timeRange}
|
autoRefresh={autoRefresh}
|
||||||
onDeleteQuery={this.handleDeleteQuery}
|
timeRange={timeRange}
|
||||||
onAddQuery={this.handleAddQuery}
|
onDeleteQuery={this.handleDeleteQuery}
|
||||||
activeQueryIndex={activeQueryIndex}
|
onAddQuery={this.handleAddQuery}
|
||||||
activeQuery={this.getActiveQuery()}
|
activeQueryIndex={activeQueryIndex}
|
||||||
setActiveQueryIndex={this.handleSetActiveQueryIndex}
|
activeQuery={this.getActiveQuery()}
|
||||||
initialGroupByTime={AUTO_GROUP_BY}
|
setActiveQueryIndex={this.handleSetActiveQueryIndex}
|
||||||
/>}
|
initialGroupByTime={AUTO_GROUP_BY}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</CEOBottom>
|
</CEOBottom>
|
||||||
</ResizeContainer>
|
</ResizeContainer>
|
||||||
</div>
|
</div>
|
||||||
|
@ -346,10 +348,9 @@ class CellEditorOverlay extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const CEOBottom = ({children}) =>
|
const CEOBottom = ({children}) => (
|
||||||
<div className="overlay-technology--editor">
|
<div className="overlay-technology--editor">{children}</div>
|
||||||
{children}
|
)
|
||||||
</div>
|
|
||||||
|
|
||||||
const {arrayOf, func, node, number, shape, string} = PropTypes
|
const {arrayOf, func, node, number, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -49,37 +49,39 @@ const Dashboard = ({
|
||||||
setScrollTop={setScrollTop}
|
setScrollTop={setScrollTop}
|
||||||
>
|
>
|
||||||
<div className="dashboard container-fluid full-width">
|
<div className="dashboard container-fluid full-width">
|
||||||
{inPresentationMode
|
{inPresentationMode ? null : (
|
||||||
? null
|
<TemplateControlBar
|
||||||
: <TemplateControlBar
|
templates={dashboard.templates}
|
||||||
templates={dashboard.templates}
|
onSelectTemplate={onSelectTemplate}
|
||||||
onSelectTemplate={onSelectTemplate}
|
onOpenTemplateManager={onOpenTemplateManager}
|
||||||
onOpenTemplateManager={onOpenTemplateManager}
|
isOpen={showTemplateControlBar}
|
||||||
isOpen={showTemplateControlBar}
|
/>
|
||||||
/>}
|
)}
|
||||||
{cells.length
|
{cells.length ? (
|
||||||
? <LayoutRenderer
|
<LayoutRenderer
|
||||||
cells={cells}
|
cells={cells}
|
||||||
onZoom={onZoom}
|
onZoom={onZoom}
|
||||||
source={source}
|
source={source}
|
||||||
sources={sources}
|
sources={sources}
|
||||||
isEditable={true}
|
isEditable={true}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
manualRefresh={manualRefresh}
|
manualRefresh={manualRefresh}
|
||||||
hoverTime={hoverTime}
|
hoverTime={hoverTime}
|
||||||
onSetHoverTime={onSetHoverTime}
|
onSetHoverTime={onSetHoverTime}
|
||||||
onDeleteCell={onDeleteCell}
|
onDeleteCell={onDeleteCell}
|
||||||
onPositionChange={onPositionChange}
|
onPositionChange={onPositionChange}
|
||||||
templates={templatesIncludingDashTime}
|
templates={templatesIncludingDashTime}
|
||||||
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
onSummonOverlayTechnologies={onSummonOverlayTechnologies}
|
||||||
/>
|
/>
|
||||||
: <div className="dashboard__empty">
|
) : (
|
||||||
<p>This Dashboard has no Cells</p>
|
<div className="dashboard__empty">
|
||||||
<button className="btn btn-primary btn-m" onClick={onAddCell}>
|
<p>This Dashboard has no Cells</p>
|
||||||
<span className="icon plus" />Add a Cell
|
<button className="btn btn-primary btn-m" onClick={onAddCell}>
|
||||||
</button>
|
<span className="icon plus" />Add a Cell
|
||||||
</div>}
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</FancyScrollbar>
|
</FancyScrollbar>
|
||||||
)
|
)
|
||||||
|
|
|
@ -31,90 +31,85 @@ const DashboardHeader = ({
|
||||||
handleClickPresentationButton,
|
handleClickPresentationButton,
|
||||||
zoomedTimeRange: {zoomedLower, zoomedUpper},
|
zoomedTimeRange: {zoomedLower, zoomedUpper},
|
||||||
}) =>
|
}) =>
|
||||||
isHidden
|
isHidden ? null : (
|
||||||
? null
|
<div className="page-header full-width">
|
||||||
: <div className="page-header full-width">
|
<div className="page-header__container">
|
||||||
<div className="page-header__container">
|
<div
|
||||||
<div
|
className={
|
||||||
className={
|
dashboard
|
||||||
dashboard
|
? 'page-header__left page-header__dash-editable'
|
||||||
? 'page-header__left page-header__dash-editable'
|
: 'page-header__left'
|
||||||
: 'page-header__left'
|
}
|
||||||
}
|
>
|
||||||
>
|
{names && names.length > 1 ? (
|
||||||
{names && names.length > 1
|
<DashboardSwitcher
|
||||||
? <DashboardSwitcher
|
names={names}
|
||||||
names={names}
|
activeDashboard={activeDashboard}
|
||||||
activeDashboard={activeDashboard}
|
|
||||||
/>
|
|
||||||
: null}
|
|
||||||
{dashboard
|
|
||||||
? <Authorized
|
|
||||||
requiredRole={EDITOR_ROLE}
|
|
||||||
replaceWithIfNotAuthorized={
|
|
||||||
<h1 className="page-header__title">
|
|
||||||
{activeDashboard}
|
|
||||||
</h1>
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<DashboardHeaderEdit
|
|
||||||
onSave={onSave}
|
|
||||||
onCancel={onCancel}
|
|
||||||
activeDashboard={activeDashboard}
|
|
||||||
onEditDashboard={onEditDashboard}
|
|
||||||
isEditMode={isEditMode}
|
|
||||||
/>
|
|
||||||
</Authorized>
|
|
||||||
: <h1 className="page-header__title">
|
|
||||||
{activeDashboard}
|
|
||||||
</h1>}
|
|
||||||
</div>
|
|
||||||
<div className="page-header__right">
|
|
||||||
<GraphTips />
|
|
||||||
<SourceIndicator />
|
|
||||||
{dashboard
|
|
||||||
? <Authorized requiredRole={EDITOR_ROLE}>
|
|
||||||
<button
|
|
||||||
className="btn btn-primary btn-sm"
|
|
||||||
onClick={onAddCell}
|
|
||||||
>
|
|
||||||
<span className="icon plus" />
|
|
||||||
Add Cell
|
|
||||||
</button>
|
|
||||||
</Authorized>
|
|
||||||
: null}
|
|
||||||
{dashboard
|
|
||||||
? <div
|
|
||||||
className={classnames('btn btn-default btn-sm', {
|
|
||||||
active: showTemplateControlBar,
|
|
||||||
})}
|
|
||||||
onClick={onToggleTempVarControls}
|
|
||||||
>
|
|
||||||
<span className="icon cube" />Template Variables
|
|
||||||
</div>
|
|
||||||
: null}
|
|
||||||
<AutoRefreshDropdown
|
|
||||||
onChoose={handleChooseAutoRefresh}
|
|
||||||
onManualRefresh={onManualRefresh}
|
|
||||||
selected={autoRefresh}
|
|
||||||
iconName="refresh"
|
|
||||||
/>
|
/>
|
||||||
<TimeRangeDropdown
|
) : null}
|
||||||
onChooseTimeRange={handleChooseTimeRange}
|
{dashboard ? (
|
||||||
selected={{
|
<Authorized
|
||||||
upper: zoomedUpper || upper,
|
requiredRole={EDITOR_ROLE}
|
||||||
lower: zoomedLower || lower,
|
replaceWithIfNotAuthorized={
|
||||||
}}
|
<h1 className="page-header__title">{activeDashboard}</h1>
|
||||||
/>
|
}
|
||||||
<div
|
|
||||||
className="btn btn-default btn-sm btn-square"
|
|
||||||
onClick={handleClickPresentationButton}
|
|
||||||
>
|
>
|
||||||
<span className="icon expand-a" />
|
<DashboardHeaderEdit
|
||||||
|
onSave={onSave}
|
||||||
|
onCancel={onCancel}
|
||||||
|
activeDashboard={activeDashboard}
|
||||||
|
onEditDashboard={onEditDashboard}
|
||||||
|
isEditMode={isEditMode}
|
||||||
|
/>
|
||||||
|
</Authorized>
|
||||||
|
) : (
|
||||||
|
<h1 className="page-header__title">{activeDashboard}</h1>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div className="page-header__right">
|
||||||
|
<GraphTips />
|
||||||
|
<SourceIndicator />
|
||||||
|
{dashboard ? (
|
||||||
|
<Authorized requiredRole={EDITOR_ROLE}>
|
||||||
|
<button className="btn btn-primary btn-sm" onClick={onAddCell}>
|
||||||
|
<span className="icon plus" />
|
||||||
|
Add Cell
|
||||||
|
</button>
|
||||||
|
</Authorized>
|
||||||
|
) : null}
|
||||||
|
{dashboard ? (
|
||||||
|
<div
|
||||||
|
className={classnames('btn btn-default btn-sm', {
|
||||||
|
active: showTemplateControlBar,
|
||||||
|
})}
|
||||||
|
onClick={onToggleTempVarControls}
|
||||||
|
>
|
||||||
|
<span className="icon cube" />Template Variables
|
||||||
</div>
|
</div>
|
||||||
|
) : null}
|
||||||
|
<AutoRefreshDropdown
|
||||||
|
onChoose={handleChooseAutoRefresh}
|
||||||
|
onManualRefresh={onManualRefresh}
|
||||||
|
selected={autoRefresh}
|
||||||
|
iconName="refresh"
|
||||||
|
/>
|
||||||
|
<TimeRangeDropdown
|
||||||
|
onChooseTimeRange={handleChooseTimeRange}
|
||||||
|
selected={{
|
||||||
|
upper: zoomedUpper || upper,
|
||||||
|
lower: zoomedLower || lower,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
className="btn btn-default btn-sm btn-square"
|
||||||
|
onClick={handleClickPresentationButton}
|
||||||
|
>
|
||||||
|
<span className="icon expand-a" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, number, shape, string} = PropTypes
|
const {arrayOf, bool, func, number, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -46,24 +46,24 @@ class DashboardEditHeader extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="dashboard-title">
|
<div className="dashboard-title">
|
||||||
{isEditMode
|
{isEditMode ? (
|
||||||
? <input
|
<input
|
||||||
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
maxLength={DASHBOARD_NAME_MAX_LENGTH}
|
||||||
type="text"
|
type="text"
|
||||||
className="dashboard-title--input form-control input-sm"
|
className="dashboard-title--input form-control input-sm"
|
||||||
defaultValue={activeDashboard}
|
defaultValue={activeDashboard}
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
onBlur={this.handleInputBlur}
|
onBlur={this.handleInputBlur}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
placeholder="Name this Dashboard"
|
placeholder="Name this Dashboard"
|
||||||
ref={r => (this.inputRef = r)}
|
ref={r => (this.inputRef = r)}
|
||||||
/>
|
/>
|
||||||
: <h1 onClick={onEditDashboard}>
|
) : (
|
||||||
{activeDashboard}
|
<h1 onClick={onEditDashboard}>{activeDashboard}</h1>
|
||||||
</h1>}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class DashboardSwitcher extends Component {
|
||||||
<span className="icon dash-f" />
|
<span className="icon dash-f" />
|
||||||
</button>
|
</button>
|
||||||
<ul className="dropdown-menu">
|
<ul className="dropdown-menu">
|
||||||
{sorted.map(({name, link}) =>
|
{sorted.map(({name, link}) => (
|
||||||
<NameLink
|
<NameLink
|
||||||
key={link}
|
key={link}
|
||||||
name={name}
|
name={name}
|
||||||
|
@ -50,14 +50,14 @@ class DashboardSwitcher extends Component {
|
||||||
activeName={activeDashboard}
|
activeName={activeDashboard}
|
||||||
onClose={this.handleCloseMenu}
|
onClose={this.handleCloseMenu}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const NameLink = ({name, link, activeName, onClose}) =>
|
const NameLink = ({name, link, activeName, onClose}) => (
|
||||||
<li
|
<li
|
||||||
className={classnames('dropdown-item', {
|
className={classnames('dropdown-item', {
|
||||||
active: name === activeName,
|
active: name === activeName,
|
||||||
|
@ -67,6 +67,7 @@ const NameLink = ({name, link, activeName, onClose}) =>
|
||||||
{name}
|
{name}
|
||||||
</Link>
|
</Link>
|
||||||
</li>
|
</li>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, func, shape, string} = PropTypes
|
const {arrayOf, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ import React from 'react'
|
||||||
|
|
||||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||||
|
|
||||||
const DashboardsHeader = () =>
|
const DashboardsHeader = () => (
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="page-header__container">
|
<div className="page-header__container">
|
||||||
<div className="page-header__left">
|
<div className="page-header__left">
|
||||||
|
@ -13,5 +13,6 @@ const DashboardsHeader = () =>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
export default DashboardsHeader
|
export default DashboardsHeader
|
||||||
|
|
|
@ -48,9 +48,7 @@ class DashboardsPageContents extends Component {
|
||||||
<div className="col-md-12">
|
<div className="col-md-12">
|
||||||
<div className="panel">
|
<div className="panel">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<h2 className="panel-title">
|
<h2 className="panel-title">{tableHeader}</h2>
|
||||||
{tableHeader}
|
|
||||||
</h2>
|
|
||||||
<div className="dashboards-page--actions">
|
<div className="dashboards-page--actions">
|
||||||
<SearchBar
|
<SearchBar
|
||||||
placeholder="Filter by Name..."
|
placeholder="Filter by Name..."
|
||||||
|
|
|
@ -7,7 +7,7 @@ import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
|
||||||
|
|
||||||
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
|
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
|
||||||
|
|
||||||
const AuthorizedEmptyState = ({onCreateDashboard}) =>
|
const AuthorizedEmptyState = ({onCreateDashboard}) => (
|
||||||
<div className="generic-empty-state">
|
<div className="generic-empty-state">
|
||||||
<h4 style={{marginTop: '90px'}}>
|
<h4 style={{marginTop: '90px'}}>
|
||||||
Looks like you don’t have any dashboards
|
Looks like you don’t have any dashboards
|
||||||
|
@ -21,6 +21,7 @@ const AuthorizedEmptyState = ({onCreateDashboard}) =>
|
||||||
<span className="icon plus" /> Create Dashboard
|
<span className="icon plus" /> Create Dashboard
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const unauthorizedEmptyState = (
|
const unauthorizedEmptyState = (
|
||||||
<div className="generic-empty-state">
|
<div className="generic-empty-state">
|
||||||
|
@ -34,52 +35,56 @@ const DashboardsTable = ({
|
||||||
onCreateDashboard,
|
onCreateDashboard,
|
||||||
dashboardLink,
|
dashboardLink,
|
||||||
}) => {
|
}) => {
|
||||||
return dashboards && dashboards.length
|
return dashboards && dashboards.length ? (
|
||||||
? <table className="table v-center admin-table table-highlight">
|
<table className="table v-center admin-table table-highlight">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Template Variables</th>
|
<th>Template Variables</th>
|
||||||
<th />
|
<th />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => (
|
||||||
|
<tr key={dashboard.id}>
|
||||||
|
<td>
|
||||||
|
<Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
|
||||||
|
{dashboard.name}
|
||||||
|
</Link>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{dashboard.templates.length ? (
|
||||||
|
dashboard.templates.map(tv => (
|
||||||
|
<code className="table--temp-var" key={tv.id}>
|
||||||
|
{tv.tempVar}
|
||||||
|
</code>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<span className="empty-string">None</span>
|
||||||
|
)}
|
||||||
|
</td>
|
||||||
|
<Authorized
|
||||||
|
requiredRole={EDITOR_ROLE}
|
||||||
|
replaceWithIfNotAuthorized={<td />}
|
||||||
|
>
|
||||||
|
<DeleteConfirmTableCell
|
||||||
|
onDelete={onDeleteDashboard}
|
||||||
|
item={dashboard}
|
||||||
|
buttonSize="btn-xs"
|
||||||
|
/>
|
||||||
|
</Authorized>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
))}
|
||||||
<tbody>
|
</tbody>
|
||||||
{_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard =>
|
</table>
|
||||||
<tr key={dashboard.id}>
|
) : (
|
||||||
<td>
|
<Authorized
|
||||||
<Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
|
requiredRole={EDITOR_ROLE}
|
||||||
{dashboard.name}
|
replaceWithIfNotAuthorized={unauthorizedEmptyState}
|
||||||
</Link>
|
>
|
||||||
</td>
|
<AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
|
||||||
<td>
|
</Authorized>
|
||||||
{dashboard.templates.length
|
)
|
||||||
? dashboard.templates.map(tv =>
|
|
||||||
<code className="table--temp-var" key={tv.id}>
|
|
||||||
{tv.tempVar}
|
|
||||||
</code>
|
|
||||||
)
|
|
||||||
: <span className="empty-string">None</span>}
|
|
||||||
</td>
|
|
||||||
<Authorized
|
|
||||||
requiredRole={EDITOR_ROLE}
|
|
||||||
replaceWithIfNotAuthorized={<td />}
|
|
||||||
>
|
|
||||||
<DeleteConfirmTableCell
|
|
||||||
onDelete={onDeleteDashboard}
|
|
||||||
item={dashboard}
|
|
||||||
buttonSize="btn-xs"
|
|
||||||
/>
|
|
||||||
</Authorized>
|
|
||||||
</tr>
|
|
||||||
)}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
: <Authorized
|
|
||||||
requiredRole={EDITOR_ROLE}
|
|
||||||
replaceWithIfNotAuthorized={unauthorizedEmptyState}
|
|
||||||
>
|
|
||||||
<AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
|
|
||||||
</Authorized>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const {arrayOf, func, shape, string} = PropTypes
|
const {arrayOf, func, shape, string} = PropTypes
|
||||||
|
|
|
@ -9,11 +9,9 @@ const DisplayOptionsInput = ({
|
||||||
labelText,
|
labelText,
|
||||||
colWidth,
|
colWidth,
|
||||||
placeholder,
|
placeholder,
|
||||||
}) =>
|
}) => (
|
||||||
<div className={`form-group ${colWidth}`}>
|
<div className={`form-group ${colWidth}`}>
|
||||||
<label htmlFor={name}>
|
<label htmlFor={name}>{labelText}</label>
|
||||||
{labelText}
|
|
||||||
</label>
|
|
||||||
<input
|
<input
|
||||||
className="form-control input-sm"
|
className="form-control input-sm"
|
||||||
type="text"
|
type="text"
|
||||||
|
@ -24,6 +22,7 @@ const DisplayOptionsInput = ({
|
||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, string} = PropTypes
|
const {func, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -173,7 +173,7 @@ class GaugeOptions extends Component {
|
||||||
>
|
>
|
||||||
<span className="icon plus" /> Add Threshold
|
<span className="icon plus" /> Add Threshold
|
||||||
</button>
|
</button>
|
||||||
{gaugeColors.map(color =>
|
{gaugeColors.map(color => (
|
||||||
<Threshold
|
<Threshold
|
||||||
isMin={color.value === gaugeColors[0].value}
|
isMin={color.value === gaugeColors[0].value}
|
||||||
isMax={
|
isMax={
|
||||||
|
@ -189,7 +189,7 @@ class GaugeOptions extends Component {
|
||||||
onDeleteThreshold={this.handleDeleteThreshold}
|
onDeleteThreshold={this.handleDeleteThreshold}
|
||||||
onSortColors={this.handleSortColors}
|
onSortColors={this.handleSortColors}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
<div className="graph-options-group form-group-wrapper">
|
<div className="graph-options-group form-group-wrapper">
|
||||||
<div className="form-group col-xs-6">
|
<div className="form-group col-xs-6">
|
||||||
|
|
|
@ -16,25 +16,25 @@ const GraphOptionsTextWrapping = ({
|
||||||
<label>Text Wrapping</label>
|
<label>Text Wrapping</label>
|
||||||
<ul className="nav nav-tablist nav-tablist-sm">
|
<ul className="nav nav-tablist nav-tablist-sm">
|
||||||
<li
|
<li
|
||||||
className={`${thresholdsListType === THRESHOLD_TYPE_BG
|
className={`${
|
||||||
? 'active'
|
thresholdsListType === THRESHOLD_TYPE_BG ? 'active' : ''
|
||||||
: ''}`}
|
}`}
|
||||||
onClick={onToggleTextWrapping}
|
onClick={onToggleTextWrapping}
|
||||||
>
|
>
|
||||||
Truncate
|
Truncate
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className={`${thresholdsListType === THRESHOLD_TYPE_TEXT
|
className={`${
|
||||||
? 'active'
|
thresholdsListType === THRESHOLD_TYPE_TEXT ? 'active' : ''
|
||||||
: ''}`}
|
}`}
|
||||||
onClick={onToggleTextWrapping}
|
onClick={onToggleTextWrapping}
|
||||||
>
|
>
|
||||||
Wrap
|
Wrap
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
className={`${thresholdsListType === THRESHOLD_TYPE_BG
|
className={`${
|
||||||
? 'active'
|
thresholdsListType === THRESHOLD_TYPE_BG ? 'active' : ''
|
||||||
: ''}`}
|
}`}
|
||||||
onClick={onToggleTextWrapping}
|
onClick={onToggleTextWrapping}
|
||||||
>
|
>
|
||||||
Single Line
|
Single Line
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) =>
|
const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) => (
|
||||||
<div className="form-group col-xs-12 col-sm-6">
|
<div className="form-group col-xs-12 col-sm-6">
|
||||||
<label>Time Axis</label>
|
<label>Time Axis</label>
|
||||||
<ul className="nav nav-tablist nav-tablist-sm">
|
<ul className="nav nav-tablist nav-tablist-sm">
|
||||||
|
@ -19,6 +19,7 @@ const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) =>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {bool, func} = PropTypes
|
const {bool, func} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ const GraphTypeSelector = ({type, handleChangeCellType}) => {
|
||||||
<div className="display-options--cell-wrapper">
|
<div className="display-options--cell-wrapper">
|
||||||
<h5 className="display-options--header">Visualization Type</h5>
|
<h5 className="display-options--header">Visualization Type</h5>
|
||||||
<div className="viz-type-selector">
|
<div className="viz-type-selector">
|
||||||
{GRAPH_TYPES.map(graphType =>
|
{GRAPH_TYPES.map(graphType => (
|
||||||
<div
|
<div
|
||||||
key={graphType.type}
|
key={graphType.type}
|
||||||
className={classnames('viz-type-selector--option', {
|
className={classnames('viz-type-selector--option', {
|
||||||
|
@ -32,12 +32,10 @@ const GraphTypeSelector = ({type, handleChangeCellType}) => {
|
||||||
>
|
>
|
||||||
<div onClick={onChangeCellType(graphType.type)}>
|
<div onClick={onChangeCellType(graphType.type)}>
|
||||||
{graphType.graphic}
|
{graphType.graphic}
|
||||||
<p>
|
<p>{graphType.menuOption}</p>
|
||||||
{graphType.menuOption}
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FancyScrollbar>
|
</FancyScrollbar>
|
||||||
|
|
|
@ -15,7 +15,7 @@ const OverlayControls = ({
|
||||||
onSetQuerySource,
|
onSetQuerySource,
|
||||||
isDisplayOptionsTabActive,
|
isDisplayOptionsTabActive,
|
||||||
onClickDisplayOptions,
|
onClickDisplayOptions,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="overlay-controls">
|
<div className="overlay-controls">
|
||||||
<SourceSelector
|
<SourceSelector
|
||||||
sources={sources}
|
sources={sources}
|
||||||
|
@ -51,6 +51,7 @@ const OverlayControls = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -26,7 +26,7 @@ const QueryMaker = ({
|
||||||
activeQueryIndex,
|
activeQueryIndex,
|
||||||
initialGroupByTime,
|
initialGroupByTime,
|
||||||
setActiveQueryIndex,
|
setActiveQueryIndex,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="query-maker query-maker--panel">
|
<div className="query-maker query-maker--panel">
|
||||||
<QueryTabList
|
<QueryTabList
|
||||||
queries={queries}
|
queries={queries}
|
||||||
|
@ -36,28 +36,31 @@ const QueryMaker = ({
|
||||||
activeQueryIndex={activeQueryIndex}
|
activeQueryIndex={activeQueryIndex}
|
||||||
setActiveQueryIndex={setActiveQueryIndex}
|
setActiveQueryIndex={setActiveQueryIndex}
|
||||||
/>
|
/>
|
||||||
{activeQuery && activeQuery.id
|
{activeQuery && activeQuery.id ? (
|
||||||
? <div className="query-maker--tab-contents">
|
<div className="query-maker--tab-contents">
|
||||||
<QueryTextArea
|
<QueryTextArea
|
||||||
query={buildText(activeQuery)}
|
query={buildText(activeQuery)}
|
||||||
config={activeQuery}
|
config={activeQuery}
|
||||||
onUpdate={rawTextBinder(
|
onUpdate={rawTextBinder(
|
||||||
source.links,
|
source.links,
|
||||||
activeQuery.id,
|
activeQuery.id,
|
||||||
actions.editRawTextAsync
|
actions.editRawTextAsync
|
||||||
)}
|
)}
|
||||||
templates={templates}
|
templates={templates}
|
||||||
/>
|
/>
|
||||||
<SchemaExplorer
|
<SchemaExplorer
|
||||||
source={source}
|
source={source}
|
||||||
actions={actions}
|
actions={actions}
|
||||||
query={activeQuery}
|
query={activeQuery}
|
||||||
onAddQuery={onAddQuery}
|
onAddQuery={onAddQuery}
|
||||||
initialGroupByTime={initialGroupByTime}
|
initialGroupByTime={initialGroupByTime}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: <EmptyQuery onAddQuery={onAddQuery} />}
|
) : (
|
||||||
|
<EmptyQuery onAddQuery={onAddQuery} />
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, func, number, shape, string} = PropTypes
|
const {arrayOf, func, number, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -215,15 +215,15 @@ class QueryTextArea extends Component {
|
||||||
<QueryStatus status={status} />
|
<QueryStatus status={status} />
|
||||||
</div>
|
</div>
|
||||||
<div className="varmoji-back">
|
<div className="varmoji-back">
|
||||||
{isTemplating
|
{isTemplating ? (
|
||||||
? <TemplateDrawer
|
<TemplateDrawer
|
||||||
onClickTempVar={this.handleClickTempVar}
|
onClickTempVar={this.handleClickTempVar}
|
||||||
templates={filteredTemplates}
|
templates={filteredTemplates}
|
||||||
selected={selectedTemplate}
|
selected={selectedTemplate}
|
||||||
onMouseOverTempVar={this.handleMouseOverTempVar}
|
onMouseOverTempVar={this.handleMouseOverTempVar}
|
||||||
handleClickOutside={this.handleCloseDrawer}
|
handleClickOutside={this.handleCloseDrawer}
|
||||||
/>
|
/>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -3,20 +3,22 @@ import PropTypes from 'prop-types'
|
||||||
import Dropdown from 'shared/components/Dropdown'
|
import Dropdown from 'shared/components/Dropdown'
|
||||||
|
|
||||||
const SourceSelector = ({sources = [], selected, onSetQuerySource, queries}) =>
|
const SourceSelector = ({sources = [], selected, onSetQuerySource, queries}) =>
|
||||||
sources.length > 1 && queries.length
|
sources.length > 1 && queries.length ? (
|
||||||
? <div className="source-selector">
|
<div className="source-selector">
|
||||||
<h3>Source:</h3>
|
<h3>Source:</h3>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
items={sources}
|
items={sources}
|
||||||
buttonSize="btn-sm"
|
buttonSize="btn-sm"
|
||||||
menuClass="dropdown-astronaut"
|
menuClass="dropdown-astronaut"
|
||||||
useAutoComplete={true}
|
useAutoComplete={true}
|
||||||
selected={selected}
|
selected={selected}
|
||||||
onChoose={onSetQuerySource}
|
onChoose={onSetQuerySource}
|
||||||
className="dropdown-240"
|
className="dropdown-240"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: <div className="source-selector" />
|
) : (
|
||||||
|
<div className="source-selector" />
|
||||||
|
)
|
||||||
|
|
||||||
const {array, arrayOf, func, shape, string} = PropTypes
|
const {array, arrayOf, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -2,23 +2,23 @@ import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
|
||||||
|
|
||||||
export const Tabber = ({labelText, children, tipID, tipContent}) =>
|
export const Tabber = ({labelText, children, tipID, tipContent}) => (
|
||||||
<div className="form-group col-md-6">
|
<div className="form-group col-md-6">
|
||||||
<label>
|
<label>
|
||||||
{labelText}
|
{labelText}
|
||||||
{tipID
|
{tipID ? (
|
||||||
? <QuestionMarkTooltip tipID={tipID} tipContent={tipContent} />
|
<QuestionMarkTooltip tipID={tipID} tipContent={tipContent} />
|
||||||
: null}
|
) : null}
|
||||||
</label>
|
</label>
|
||||||
<ul className="nav nav-tablist nav-tablist-sm">
|
<ul className="nav nav-tablist nav-tablist-sm">{children}</ul>
|
||||||
{children}
|
|
||||||
</ul>
|
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
export const Tab = ({isActive, onClickTab, text}) =>
|
export const Tab = ({isActive, onClickTab, text}) => (
|
||||||
<li className={isActive ? 'active' : ''} onClick={onClickTab}>
|
<li className={isActive ? 'active' : ''} onClick={onClickTab}>
|
||||||
{text}
|
{text}
|
||||||
</li>
|
</li>
|
||||||
|
)
|
||||||
|
|
||||||
const {bool, func, node, string} = PropTypes
|
const {bool, func, node, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -16,67 +16,67 @@ const TemplateControlBar = ({
|
||||||
templates,
|
templates,
|
||||||
onSelectTemplate,
|
onSelectTemplate,
|
||||||
onOpenTemplateManager,
|
onOpenTemplateManager,
|
||||||
}) =>
|
}) => (
|
||||||
<div className={classnames('template-control-bar', {show: isOpen})}>
|
<div className={classnames('template-control-bar', {show: isOpen})}>
|
||||||
<div className="template-control--container">
|
<div className="template-control--container">
|
||||||
<div className="template-control--controls">
|
<div className="template-control--controls">
|
||||||
{templates.length
|
{templates.length ? (
|
||||||
? templates.map(({id, values, tempVar}) => {
|
templates.map(({id, values, tempVar}) => {
|
||||||
const items = values.map(value => ({...value, text: value.value}))
|
const items = values.map(value => ({...value, text: value.value}))
|
||||||
const itemValues = values.map(value => value.value)
|
const itemValues = values.map(value => value.value)
|
||||||
const selectedItem = items.find(item => item.selected) || items[0]
|
const selectedItem = items.find(item => item.selected) || items[0]
|
||||||
const selectedText = selectedItem && selectedItem.text
|
const selectedText = selectedItem && selectedItem.text
|
||||||
let customDropdownWidth = 0
|
let customDropdownWidth = 0
|
||||||
if (itemValues.length > 1) {
|
if (itemValues.length > 1) {
|
||||||
const longest = itemValues.reduce(
|
const longest = itemValues.reduce(
|
||||||
(a, b) => (a.length > b.length ? a : b)
|
(a, b) => (a.length > b.length ? a : b)
|
||||||
)
|
|
||||||
const longestLengthPixels =
|
|
||||||
calculateSize(longest, {
|
|
||||||
font: 'Monospace',
|
|
||||||
fontSize: '12px',
|
|
||||||
}).width + tempVarDropdownPadding
|
|
||||||
|
|
||||||
if (
|
|
||||||
longestLengthPixels > minTempVarDropdownWidth &&
|
|
||||||
longestLengthPixels < maxTempVarDropdownWidth
|
|
||||||
) {
|
|
||||||
customDropdownWidth = longestLengthPixels
|
|
||||||
} else if (longestLengthPixels > maxTempVarDropdownWidth) {
|
|
||||||
customDropdownWidth = maxTempVarDropdownWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: change Dropdown to a MultiSelectDropdown, `selected` to
|
|
||||||
// the full array, and [item] to all `selected` values when we update
|
|
||||||
// this component to support multiple values
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
key={id}
|
|
||||||
className="template-control--dropdown"
|
|
||||||
style={
|
|
||||||
customDropdownWidth > 0
|
|
||||||
? {minWidth: customDropdownWidth}
|
|
||||||
: null
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<Dropdown
|
|
||||||
items={items}
|
|
||||||
buttonSize="btn-xs"
|
|
||||||
menuClass="dropdown-astronaut"
|
|
||||||
useAutoComplete={true}
|
|
||||||
selected={selectedText || '(No values)'}
|
|
||||||
onChoose={onSelectTemplate(id)}
|
|
||||||
/>
|
|
||||||
<label className="template-control--label">
|
|
||||||
{tempVar}
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
)
|
)
|
||||||
})
|
const longestLengthPixels =
|
||||||
: <div className="template-control--empty">
|
calculateSize(longest, {
|
||||||
This dashboard does not have any Template Variables
|
font: 'Monospace',
|
||||||
</div>}
|
fontSize: '12px',
|
||||||
|
}).width + tempVarDropdownPadding
|
||||||
|
|
||||||
|
if (
|
||||||
|
longestLengthPixels > minTempVarDropdownWidth &&
|
||||||
|
longestLengthPixels < maxTempVarDropdownWidth
|
||||||
|
) {
|
||||||
|
customDropdownWidth = longestLengthPixels
|
||||||
|
} else if (longestLengthPixels > maxTempVarDropdownWidth) {
|
||||||
|
customDropdownWidth = maxTempVarDropdownWidth
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: change Dropdown to a MultiSelectDropdown, `selected` to
|
||||||
|
// the full array, and [item] to all `selected` values when we update
|
||||||
|
// this component to support multiple values
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
key={id}
|
||||||
|
className="template-control--dropdown"
|
||||||
|
style={
|
||||||
|
customDropdownWidth > 0
|
||||||
|
? {minWidth: customDropdownWidth}
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<Dropdown
|
||||||
|
items={items}
|
||||||
|
buttonSize="btn-xs"
|
||||||
|
menuClass="dropdown-astronaut"
|
||||||
|
useAutoComplete={true}
|
||||||
|
selected={selectedText || '(No values)'}
|
||||||
|
onChoose={onSelectTemplate(id)}
|
||||||
|
/>
|
||||||
|
<label className="template-control--label">{tempVar}</label>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
) : (
|
||||||
|
<div className="template-control--empty">
|
||||||
|
This dashboard does not have any Template Variables
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Authorized requiredRole={EDITOR_ROLE}>
|
<Authorized requiredRole={EDITOR_ROLE}>
|
||||||
<button
|
<button
|
||||||
|
@ -89,6 +89,7 @@ const TemplateControlBar = ({
|
||||||
</Authorized>
|
</Authorized>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -78,17 +78,15 @@ class Threshold extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="threshold-item">
|
<div className="threshold-item">
|
||||||
<div className={labelClass}>
|
<div className={labelClass}>{label}</div>
|
||||||
{label}
|
{canBeDeleted ? (
|
||||||
</div>
|
<button
|
||||||
{canBeDeleted
|
className="btn btn-default btn-sm btn-square"
|
||||||
? <button
|
onClick={onDeleteThreshold(threshold)}
|
||||||
className="btn btn-default btn-sm btn-square"
|
>
|
||||||
onClick={onDeleteThreshold(threshold)}
|
<span className="icon remove" />
|
||||||
>
|
</button>
|
||||||
<span className="icon remove" />
|
) : null}
|
||||||
</button>
|
|
||||||
: null}
|
|
||||||
<input
|
<input
|
||||||
value={workingValue}
|
value={workingValue}
|
||||||
className={inputClass}
|
className={inputClass}
|
||||||
|
|
|
@ -55,21 +55,23 @@ class VisualizationName extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="graph-heading">
|
<div className="graph-heading">
|
||||||
{isEditing
|
{isEditing ? (
|
||||||
? <input
|
<input
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control input-sm"
|
className="form-control input-sm"
|
||||||
defaultValue={name}
|
defaultValue={name}
|
||||||
onBlur={this.handleInputBlur}
|
onBlur={this.handleInputBlur}
|
||||||
onKeyDown={this.handleKeyDown}
|
onKeyDown={this.handleKeyDown}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
onFocus={this.handleFocus}
|
onFocus={this.handleFocus}
|
||||||
placeholder="Name this Cell..."
|
placeholder="Name this Cell..."
|
||||||
spellCheck={false}
|
spellCheck={false}
|
||||||
/>
|
/>
|
||||||
: <div className={graphNameClass} onClick={this.handleInputClick}>
|
) : (
|
||||||
{name}
|
<div className={graphNameClass} onClick={this.handleInputClick}>
|
||||||
</div>}
|
{name}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ const TemplateVariableManager = ({
|
||||||
tempVarAlreadyExists,
|
tempVarAlreadyExists,
|
||||||
onSaveTemplatesSuccess,
|
onSaveTemplatesSuccess,
|
||||||
onEditTemplateVariables,
|
onEditTemplateVariables,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="template-variable-manager">
|
<div className="template-variable-manager">
|
||||||
<div className="template-variable-manager--header">
|
<div className="template-variable-manager--header">
|
||||||
<div className="page-header__left">
|
<div className="page-header__left">
|
||||||
|
@ -56,6 +56,7 @@ const TemplateVariableManager = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
class TemplateVariableManagerWrapper extends Component {
|
class TemplateVariableManagerWrapper extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|
|
@ -45,7 +45,7 @@ const TemplateVariableRow = ({
|
||||||
onSubmit,
|
onSubmit,
|
||||||
onErrorThrown,
|
onErrorThrown,
|
||||||
onDeleteTempVar,
|
onDeleteTempVar,
|
||||||
}) =>
|
}) => (
|
||||||
<form
|
<form
|
||||||
className={classnames('template-variable-manager--table-row', {
|
className={classnames('template-variable-manager--table-row', {
|
||||||
editing: isEditing,
|
editing: isEditing,
|
||||||
|
@ -106,6 +106,7 @@ const TemplateVariableRow = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
)
|
||||||
|
|
||||||
class RowWrapper extends Component {
|
class RowWrapper extends Component {
|
||||||
constructor(props) {
|
constructor(props) {
|
||||||
|
|
|
@ -10,36 +10,39 @@ const TemplateVariableTable = ({
|
||||||
onRunQueryFailure,
|
onRunQueryFailure,
|
||||||
onDelete,
|
onDelete,
|
||||||
tempVarAlreadyExists,
|
tempVarAlreadyExists,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="template-variable-manager--table">
|
<div className="template-variable-manager--table">
|
||||||
{templates.length
|
{templates.length ? (
|
||||||
? <div className="template-variable-manager--table-container">
|
<div className="template-variable-manager--table-container">
|
||||||
<div className="template-variable-manager--table-heading">
|
<div className="template-variable-manager--table-heading">
|
||||||
<div className="tvm--col-1">Variable</div>
|
<div className="tvm--col-1">Variable</div>
|
||||||
<div className="tvm--col-2">Type</div>
|
<div className="tvm--col-2">Type</div>
|
||||||
<div className="tvm--col-3">Definition / Values</div>
|
<div className="tvm--col-3">Definition / Values</div>
|
||||||
<div className="tvm--col-4" />
|
<div className="tvm--col-4" />
|
||||||
</div>
|
|
||||||
<div className="template-variable-manager--table-rows">
|
|
||||||
{templates.map(t =>
|
|
||||||
<TemplateVariableRow
|
|
||||||
key={t.id}
|
|
||||||
source={source}
|
|
||||||
template={t}
|
|
||||||
onRunQuerySuccess={onRunQuerySuccess}
|
|
||||||
onRunQueryFailure={onRunQueryFailure}
|
|
||||||
onDelete={onDelete}
|
|
||||||
tempVarAlreadyExists={tempVarAlreadyExists}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
: <div className="generic-empty-state">
|
<div className="template-variable-manager--table-rows">
|
||||||
<h4 style={{margin: '60px 0'}} className="no-user-select">
|
{templates.map(t => (
|
||||||
You have no Template Variables, why not create one?
|
<TemplateVariableRow
|
||||||
</h4>
|
key={t.id}
|
||||||
</div>}
|
source={source}
|
||||||
|
template={t}
|
||||||
|
onRunQuerySuccess={onRunQuerySuccess}
|
||||||
|
onRunQueryFailure={onRunQueryFailure}
|
||||||
|
onDelete={onDelete}
|
||||||
|
tempVarAlreadyExists={tempVarAlreadyExists}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="generic-empty-state">
|
||||||
|
<h4 style={{margin: '60px 0'}} className="no-user-select">
|
||||||
|
You have no Template Variables, why not create one?
|
||||||
|
</h4>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, shape, string} = PropTypes
|
const {arrayOf, bool, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -8,26 +8,26 @@ const TableInput = ({
|
||||||
onStartEdit,
|
onStartEdit,
|
||||||
autoFocusTarget,
|
autoFocusTarget,
|
||||||
}) => {
|
}) => {
|
||||||
return isEditing
|
return isEditing ? (
|
||||||
? <div name={name} style={{width: '100%'}}>
|
<div name={name} style={{width: '100%'}}>
|
||||||
<input
|
<input
|
||||||
required={true}
|
required={true}
|
||||||
name={name}
|
name={name}
|
||||||
autoFocus={name === autoFocusTarget}
|
autoFocus={name === autoFocusTarget}
|
||||||
className="form-control input-sm tvm-input-edit"
|
className="form-control input-sm tvm-input-edit"
|
||||||
type="text"
|
type="text"
|
||||||
defaultValue={
|
defaultValue={
|
||||||
name === 'tempVar'
|
name === 'tempVar'
|
||||||
? defaultValue.replace(/\u003a/g, '') // remove ':'s
|
? defaultValue.replace(/\u003a/g, '') // remove ':'s
|
||||||
: defaultValue
|
: defaultValue
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
: <div style={{width: '100%'}} onClick={onStartEdit(name)}>
|
) : (
|
||||||
<div className="tvm-input">
|
<div style={{width: '100%'}} onClick={onStartEdit(name)}>
|
||||||
{defaultValue}
|
<div className="tvm-input">{defaultValue}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const {bool, func, string} = PropTypes
|
const {bool, func, string} = PropTypes
|
||||||
|
|
|
@ -46,15 +46,17 @@ const TemplateQueryBuilder = ({
|
||||||
onErrorThrown={onErrorThrown}
|
onErrorThrown={onErrorThrown}
|
||||||
/>
|
/>
|
||||||
<span className="tvm-query-builder--text">FROM</span>
|
<span className="tvm-query-builder--text">FROM</span>
|
||||||
{selectedDatabase
|
{selectedDatabase ? (
|
||||||
? <MeasurementDropdown
|
<MeasurementDropdown
|
||||||
database={selectedDatabase}
|
database={selectedDatabase}
|
||||||
measurement={selectedMeasurement}
|
measurement={selectedMeasurement}
|
||||||
onSelectMeasurement={onSelectMeasurement}
|
onSelectMeasurement={onSelectMeasurement}
|
||||||
onStartEdit={onStartEdit}
|
onStartEdit={onStartEdit}
|
||||||
onErrorThrown={onErrorThrown}
|
onErrorThrown={onErrorThrown}
|
||||||
/>
|
/>
|
||||||
: <div>No database selected</div>}
|
) : (
|
||||||
|
<div>No database selected</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
case 'tagValues':
|
case 'tagValues':
|
||||||
|
@ -68,26 +70,30 @@ const TemplateQueryBuilder = ({
|
||||||
onErrorThrown={onErrorThrown}
|
onErrorThrown={onErrorThrown}
|
||||||
/>
|
/>
|
||||||
<span className="tvm-query-builder--text">FROM</span>
|
<span className="tvm-query-builder--text">FROM</span>
|
||||||
{selectedDatabase
|
{selectedDatabase ? (
|
||||||
? <MeasurementDropdown
|
<MeasurementDropdown
|
||||||
database={selectedDatabase}
|
database={selectedDatabase}
|
||||||
measurement={selectedMeasurement}
|
measurement={selectedMeasurement}
|
||||||
onSelectMeasurement={onSelectMeasurement}
|
onSelectMeasurement={onSelectMeasurement}
|
||||||
onStartEdit={onStartEdit}
|
onStartEdit={onStartEdit}
|
||||||
onErrorThrown={onErrorThrown}
|
onErrorThrown={onErrorThrown}
|
||||||
/>
|
/>
|
||||||
: 'Pick a DB'}
|
) : (
|
||||||
|
'Pick a DB'
|
||||||
|
)}
|
||||||
<span className="tvm-query-builder--text">WITH KEY =</span>
|
<span className="tvm-query-builder--text">WITH KEY =</span>
|
||||||
{selectedMeasurement
|
{selectedMeasurement ? (
|
||||||
? <TagKeyDropdown
|
<TagKeyDropdown
|
||||||
database={selectedDatabase}
|
database={selectedDatabase}
|
||||||
measurement={selectedMeasurement}
|
measurement={selectedMeasurement}
|
||||||
tagKey={selectedTagKey}
|
tagKey={selectedTagKey}
|
||||||
onSelectTagKey={onSelectTagKey}
|
onSelectTagKey={onSelectTagKey}
|
||||||
onStartEdit={onStartEdit}
|
onStartEdit={onStartEdit}
|
||||||
onErrorThrown={onErrorThrown}
|
onErrorThrown={onErrorThrown}
|
||||||
/>
|
/>
|
||||||
: 'Pick a Tag Key'}
|
) : (
|
||||||
|
'Pick a Tag Key'
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -356,35 +356,35 @@ class DashboardPage extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
{isTemplating
|
{isTemplating ? (
|
||||||
? <OverlayTechnologies>
|
<OverlayTechnologies>
|
||||||
<TemplateVariableManager
|
<TemplateVariableManager
|
||||||
source={source}
|
|
||||||
templates={dashboard.templates}
|
|
||||||
onClose={this.handleCloseTemplateManager}
|
|
||||||
onRunQueryFailure={this.handleRunQueryFailure}
|
|
||||||
onEditTemplateVariables={this.handleEditTemplateVariables}
|
|
||||||
/>
|
|
||||||
</OverlayTechnologies>
|
|
||||||
: null}
|
|
||||||
{selectedCell
|
|
||||||
? <CellEditorOverlay
|
|
||||||
source={source}
|
source={source}
|
||||||
sources={sources}
|
templates={dashboard.templates}
|
||||||
cell={selectedCell}
|
onClose={this.handleCloseTemplateManager}
|
||||||
timeRange={timeRange}
|
onRunQueryFailure={this.handleRunQueryFailure}
|
||||||
autoRefresh={autoRefresh}
|
onEditTemplateVariables={this.handleEditTemplateVariables}
|
||||||
dashboardID={dashboardID}
|
|
||||||
queryStatus={cellQueryStatus}
|
|
||||||
onSave={this.handleSaveEditedCell}
|
|
||||||
onCancel={handleHideCellEditorOverlay}
|
|
||||||
templates={templatesIncludingDashTime}
|
|
||||||
editQueryStatus={dashboardActions.editCellQueryStatus}
|
|
||||||
thresholdsListType={thresholdsListType}
|
|
||||||
thresholdsListColors={thresholdsListColors}
|
|
||||||
gaugeColors={gaugeColors}
|
|
||||||
/>
|
/>
|
||||||
: null}
|
</OverlayTechnologies>
|
||||||
|
) : null}
|
||||||
|
{selectedCell ? (
|
||||||
|
<CellEditorOverlay
|
||||||
|
source={source}
|
||||||
|
sources={sources}
|
||||||
|
cell={selectedCell}
|
||||||
|
timeRange={timeRange}
|
||||||
|
autoRefresh={autoRefresh}
|
||||||
|
dashboardID={dashboardID}
|
||||||
|
queryStatus={cellQueryStatus}
|
||||||
|
onSave={this.handleSaveEditedCell}
|
||||||
|
onCancel={handleHideCellEditorOverlay}
|
||||||
|
templates={templatesIncludingDashTime}
|
||||||
|
editQueryStatus={dashboardActions.editCellQueryStatus}
|
||||||
|
thresholdsListType={thresholdsListType}
|
||||||
|
thresholdsListColors={thresholdsListColors}
|
||||||
|
gaugeColors={gaugeColors}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
<DashboardHeader
|
<DashboardHeader
|
||||||
names={names}
|
names={names}
|
||||||
sourceID={sourceID}
|
sourceID={sourceID}
|
||||||
|
@ -407,30 +407,30 @@ class DashboardPage extends Component {
|
||||||
onToggleTempVarControls={this.handleToggleTempVarControls}
|
onToggleTempVarControls={this.handleToggleTempVarControls}
|
||||||
handleClickPresentationButton={handleClickPresentationButton}
|
handleClickPresentationButton={handleClickPresentationButton}
|
||||||
/>
|
/>
|
||||||
{dashboard
|
{dashboard ? (
|
||||||
? <Dashboard
|
<Dashboard
|
||||||
source={source}
|
source={source}
|
||||||
sources={sources}
|
sources={sources}
|
||||||
setScrollTop={this.setScrollTop}
|
setScrollTop={this.setScrollTop}
|
||||||
inView={this.inView}
|
inView={this.inView}
|
||||||
dashboard={dashboard}
|
dashboard={dashboard}
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
manualRefresh={manualRefresh}
|
manualRefresh={manualRefresh}
|
||||||
onZoom={this.handleZoomedTimeRange}
|
onZoom={this.handleZoomedTimeRange}
|
||||||
onAddCell={this.handleAddCell}
|
onAddCell={this.handleAddCell}
|
||||||
hoverTime={hoverTime}
|
hoverTime={hoverTime}
|
||||||
onSetHoverTime={this.handleSetHoverTime}
|
onSetHoverTime={this.handleSetHoverTime}
|
||||||
inPresentationMode={inPresentationMode}
|
inPresentationMode={inPresentationMode}
|
||||||
onPositionChange={this.handleUpdatePosition}
|
onPositionChange={this.handleUpdatePosition}
|
||||||
onSelectTemplate={this.handleSelectTemplate}
|
onSelectTemplate={this.handleSelectTemplate}
|
||||||
onDeleteCell={this.handleDeleteDashboardCell}
|
onDeleteCell={this.handleDeleteDashboardCell}
|
||||||
showTemplateControlBar={showTemplateControlBar}
|
showTemplateControlBar={showTemplateControlBar}
|
||||||
onOpenTemplateManager={this.handleOpenTemplateManager}
|
onOpenTemplateManager={this.handleOpenTemplateManager}
|
||||||
templatesIncludingDashTime={templatesIncludingDashTime}
|
templatesIncludingDashTime={templatesIncludingDashTime}
|
||||||
onSummonOverlayTechnologies={handleShowCellEditorOverlay}
|
onSummonOverlayTechnologies={handleShowCellEditorOverlay}
|
||||||
/>
|
/>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,27 +90,27 @@ class FieldListItem extends Component {
|
||||||
<div className="query-builder--checkbox" />
|
<div className="query-builder--checkbox" />
|
||||||
{fieldName}
|
{fieldName}
|
||||||
</span>
|
</span>
|
||||||
{isSelected
|
{isSelected ? (
|
||||||
? <div
|
<div
|
||||||
className={classnames('btn btn-xs', {
|
className={classnames('btn btn-xs', {
|
||||||
active: isOpen,
|
active: isOpen,
|
||||||
'btn-default': !num,
|
'btn-default': !num,
|
||||||
'btn-primary': num,
|
'btn-primary': num,
|
||||||
})}
|
})}
|
||||||
onClick={this.toggleFunctionsMenu}
|
onClick={this.toggleFunctionsMenu}
|
||||||
data-test={`query-builder-list-item-function-${fieldName}`}
|
data-test={`query-builder-list-item-function-${fieldName}`}
|
||||||
>
|
>
|
||||||
{fieldFuncsLabel}
|
{fieldFuncsLabel}
|
||||||
</div>
|
</div>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
{isSelected && isOpen
|
{isSelected && isOpen ? (
|
||||||
? <FunctionSelector
|
<FunctionSelector
|
||||||
onApply={this.handleApplyFunctions}
|
onApply={this.handleApplyFunctions}
|
||||||
selectedItems={funcs}
|
selectedItems={funcs}
|
||||||
singleSelect={isKapacitorRule}
|
singleSelect={isKapacitorRule}
|
||||||
/>
|
/>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ const GroupByTimeDropdown = ({
|
||||||
selected,
|
selected,
|
||||||
onChooseGroupByTime,
|
onChooseGroupByTime,
|
||||||
location: {pathname},
|
location: {pathname},
|
||||||
}) =>
|
}) => (
|
||||||
<div className="group-by-time">
|
<div className="group-by-time">
|
||||||
<label className="group-by-time--label">Group by:</label>
|
<label className="group-by-time--label">Group by:</label>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
@ -34,6 +34,7 @@ const GroupByTimeDropdown = ({
|
||||||
selected={selected || 'Time'}
|
selected={selected || 'Time'}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, string, shape} = PropTypes
|
const {func, string, shape} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,8 @@ const NoDataNodeError = React.createClass({
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<ClusterError>
|
<ClusterError>
|
||||||
<PanelHeading>
|
<PanelHeading>{errorCopy.noData.head}</PanelHeading>
|
||||||
{errorCopy.noData.head}
|
<PanelBody>{errorCopy.noData.body}</PanelBody>
|
||||||
</PanelHeading>
|
|
||||||
<PanelBody>
|
|
||||||
{errorCopy.noData.body}
|
|
||||||
</PanelBody>
|
|
||||||
</ClusterError>
|
</ClusterError>
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,7 +14,7 @@ const QueryMaker = ({
|
||||||
timeRange,
|
timeRange,
|
||||||
activeQuery,
|
activeQuery,
|
||||||
initialGroupByTime,
|
initialGroupByTime,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="query-maker query-maker--panel">
|
<div className="query-maker query-maker--panel">
|
||||||
<div className="query-maker--tab-contents">
|
<div className="query-maker--tab-contents">
|
||||||
<QueryEditor
|
<QueryEditor
|
||||||
|
@ -33,6 +33,7 @@ const QueryMaker = ({
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, shape, string} = PropTypes
|
const {func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -31,9 +31,7 @@ const QueryMakerTab = React.createClass({
|
||||||
})}
|
})}
|
||||||
onClick={this.handleSelect}
|
onClick={this.handleSelect}
|
||||||
>
|
>
|
||||||
<label>
|
<label>{this.props.queryTabText}</label>
|
||||||
{this.props.queryTabText}
|
|
||||||
</label>
|
|
||||||
<span
|
<span
|
||||||
className="query-maker--delete"
|
className="query-maker--delete"
|
||||||
onClick={this.handleDelete}
|
onClick={this.handleDelete}
|
||||||
|
|
|
@ -134,60 +134,60 @@ class ChronoTable extends Component {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{width: '100%', height: '100%', position: 'relative'}}>
|
<div style={{width: '100%', height: '100%', position: 'relative'}}>
|
||||||
{series.length < maximumTabsCount
|
{series.length < maximumTabsCount ? (
|
||||||
? <div className="table--tabs">
|
<div className="table--tabs">
|
||||||
{series.map((s, i) =>
|
{series.map((s, i) => (
|
||||||
<TabItem
|
<TabItem
|
||||||
isActive={i === activeSeriesIndex}
|
isActive={i === activeSeriesIndex}
|
||||||
key={i}
|
key={i}
|
||||||
name={this.makeTabName(s)}
|
name={this.makeTabName(s)}
|
||||||
index={i}
|
index={i}
|
||||||
onClickTab={this.handleClickTab}
|
onClickTab={this.handleClickTab}
|
||||||
/>
|
/>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
: <Dropdown
|
) : (
|
||||||
className="dropdown-160 table--tabs-dropdown"
|
<Dropdown
|
||||||
items={series.map((s, index) => ({
|
className="dropdown-160 table--tabs-dropdown"
|
||||||
...s,
|
items={series.map((s, index) => ({
|
||||||
text: this.makeTabName(s),
|
...s,
|
||||||
index,
|
text: this.makeTabName(s),
|
||||||
}))}
|
index,
|
||||||
onChoose={this.handleClickDropdown}
|
}))}
|
||||||
selected={this.makeTabName(series[activeSeriesIndex])}
|
onChoose={this.handleClickDropdown}
|
||||||
buttonSize="btn-xs"
|
selected={this.makeTabName(series[activeSeriesIndex])}
|
||||||
/>}
|
buttonSize="btn-xs"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<div className="table--tabs-content">
|
<div className="table--tabs-content">
|
||||||
{(columns && !columns.length) || (values && !values.length)
|
{(columns && !columns.length) || (values && !values.length) ? (
|
||||||
? <div className="generic-empty-state">This series is empty</div>
|
<div className="generic-empty-state">This series is empty</div>
|
||||||
: <Table
|
) : (
|
||||||
onColumnResizeEndCallback={this.handleColumnResize}
|
<Table
|
||||||
isColumnResizing={false}
|
onColumnResizeEndCallback={this.handleColumnResize}
|
||||||
rowHeight={rowHeight}
|
isColumnResizing={false}
|
||||||
rowsCount={values.length}
|
rowHeight={rowHeight}
|
||||||
width={containerWidth}
|
rowsCount={values.length}
|
||||||
ownerHeight={styleAdjustedHeight}
|
width={containerWidth}
|
||||||
height={styleAdjustedHeight}
|
ownerHeight={styleAdjustedHeight}
|
||||||
headerHeight={headerHeight}
|
height={styleAdjustedHeight}
|
||||||
>
|
headerHeight={headerHeight}
|
||||||
{columns.map((columnName, colIndex) => {
|
>
|
||||||
return (
|
{columns.map((columnName, colIndex) => {
|
||||||
<Column
|
return (
|
||||||
isResizable={true}
|
<Column
|
||||||
key={columnName}
|
isResizable={true}
|
||||||
columnKey={columnName}
|
key={columnName}
|
||||||
header={
|
columnKey={columnName}
|
||||||
<Cell>
|
header={<Cell>{columnName}</Cell>}
|
||||||
{columnName}
|
cell={this.handleCustomCell(columnName, values, colIndex)}
|
||||||
</Cell>
|
width={columnWidths[columnName] || width}
|
||||||
}
|
minWidth={minWidth}
|
||||||
cell={this.handleCustomCell(columnName, values, colIndex)}
|
/>
|
||||||
width={columnWidths[columnName] || width}
|
)
|
||||||
minWidth={minWidth}
|
})}
|
||||||
/>
|
</Table>
|
||||||
)
|
)}
|
||||||
})}
|
|
||||||
</Table>}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,13 +2,14 @@ import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
|
|
||||||
const TableTabItem = ({name, index, onClickTab, isActive}) =>
|
const TableTabItem = ({name, index, onClickTab, isActive}) => (
|
||||||
<div
|
<div
|
||||||
className={classnames('table--tab', {active: isActive})}
|
className={classnames('table--tab', {active: isActive})}
|
||||||
onClick={onClickTab(index)}
|
onClick={onClickTab(index)}
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {bool, func, number, string} = PropTypes
|
const {bool, func, number, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -27,32 +27,33 @@ const getCSV = (query, errorThrown) => async () => {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VisHeader = ({views, view, onToggleView, query, errorThrown}) =>
|
const VisHeader = ({views, view, onToggleView, query, errorThrown}) => (
|
||||||
<div className="graph-heading">
|
<div className="graph-heading">
|
||||||
{views.length
|
{views.length ? (
|
||||||
? <ul className="nav nav-tablist nav-tablist-sm">
|
<ul className="nav nav-tablist nav-tablist-sm">
|
||||||
{views.map(v =>
|
{views.map(v => (
|
||||||
<li
|
<li
|
||||||
key={v}
|
key={v}
|
||||||
onClick={onToggleView(v)}
|
onClick={onToggleView(v)}
|
||||||
className={classnames({active: view === v})}
|
className={classnames({active: view === v})}
|
||||||
data-test={`data-${v}`}
|
data-test={`data-${v}`}
|
||||||
>
|
>
|
||||||
{_.upperFirst(v)}
|
{_.upperFirst(v)}
|
||||||
</li>
|
</li>
|
||||||
)}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
: null}
|
) : null}
|
||||||
{query
|
{query ? (
|
||||||
? <div
|
<div
|
||||||
className="btn btn-sm btn-default dlcsv"
|
className="btn btn-sm btn-default dlcsv"
|
||||||
onClick={getCSV(query, errorThrown)}
|
onClick={getCSV(query, errorThrown)}
|
||||||
>
|
>
|
||||||
<span className="icon download dlcsv" />
|
<span className="icon download dlcsv" />
|
||||||
.csv
|
.csv
|
||||||
</div>
|
</div>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, func, shape, string} = PropTypes
|
const {arrayOf, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -15,70 +15,75 @@ const WriteDataBody = ({
|
||||||
fileInput,
|
fileInput,
|
||||||
handleFileOpen,
|
handleFileOpen,
|
||||||
isUploading,
|
isUploading,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="write-data-form--body">
|
<div className="write-data-form--body">
|
||||||
{isManual
|
{isManual ? (
|
||||||
? <textarea
|
<textarea
|
||||||
className="form-control write-data-form--input"
|
className="form-control write-data-form--input"
|
||||||
autoComplete="off"
|
autoComplete="off"
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
|
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
|
||||||
onKeyUp={handleKeyUp}
|
onKeyUp={handleKeyUp}
|
||||||
onChange={handleEdit}
|
onChange={handleEdit}
|
||||||
autoFocus={true}
|
autoFocus={true}
|
||||||
data-test="manual-entry-field"
|
data-test="manual-entry-field"
|
||||||
/>
|
/>
|
||||||
: <div
|
) : (
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
uploadContent
|
||||||
|
? 'write-data-form--file'
|
||||||
|
: 'write-data-form--file write-data-form--file_active'
|
||||||
|
}
|
||||||
|
onClick={handleFileOpen}
|
||||||
|
>
|
||||||
|
{uploadContent ? (
|
||||||
|
<h3 className="write-data-form--filepath_selected">{fileName}</h3>
|
||||||
|
) : (
|
||||||
|
<h3 className="write-data-form--filepath_empty">
|
||||||
|
Drop a file here or click to upload
|
||||||
|
</h3>
|
||||||
|
)}
|
||||||
|
<div
|
||||||
className={
|
className={
|
||||||
uploadContent
|
uploadContent
|
||||||
? 'write-data-form--file'
|
? 'write-data-form--graphic write-data-form--graphic_success'
|
||||||
: 'write-data-form--file write-data-form--file_active'
|
: 'write-data-form--graphic'
|
||||||
}
|
}
|
||||||
onClick={handleFileOpen}
|
/>
|
||||||
>
|
<input
|
||||||
{uploadContent
|
type="file"
|
||||||
? <h3 className="write-data-form--filepath_selected">
|
onChange={handleFile(false)}
|
||||||
{fileName}
|
className="write-data-form--upload"
|
||||||
</h3>
|
ref={fileInput}
|
||||||
: <h3 className="write-data-form--filepath_empty">
|
accept="text/*, application/gzip"
|
||||||
Drop a file here or click to upload
|
/>
|
||||||
</h3>}
|
{uploadContent && (
|
||||||
<div
|
<span className="write-data-form--file-submit">
|
||||||
className={
|
<button className="btn btn-md btn-success" onClick={handleSubmit}>
|
||||||
uploadContent
|
Write this File
|
||||||
? 'write-data-form--graphic write-data-form--graphic_success'
|
</button>
|
||||||
: 'write-data-form--graphic'
|
<button
|
||||||
}
|
className="btn btn-md btn-default"
|
||||||
/>
|
onClick={handleCancelFile}
|
||||||
<input
|
>
|
||||||
type="file"
|
Cancel
|
||||||
onChange={handleFile(false)}
|
</button>
|
||||||
className="write-data-form--upload"
|
</span>
|
||||||
ref={fileInput}
|
)}
|
||||||
accept="text/*, application/gzip"
|
</div>
|
||||||
/>
|
)}
|
||||||
{uploadContent &&
|
{isManual && (
|
||||||
<span className="write-data-form--file-submit">
|
|
||||||
<button className="btn btn-md btn-success" onClick={handleSubmit}>
|
|
||||||
Write this File
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
className="btn btn-md btn-default"
|
|
||||||
onClick={handleCancelFile}
|
|
||||||
>
|
|
||||||
Cancel
|
|
||||||
</button>
|
|
||||||
</span>}
|
|
||||||
</div>}
|
|
||||||
{isManual &&
|
|
||||||
<WriteDataFooter
|
<WriteDataFooter
|
||||||
isUploading={isUploading}
|
isUploading={isUploading}
|
||||||
isManual={isManual}
|
isManual={isManual}
|
||||||
inputContent={inputContent}
|
inputContent={inputContent}
|
||||||
handleSubmit={handleSubmit}
|
handleSubmit={handleSubmit}
|
||||||
uploadContent={uploadContent}
|
uploadContent={uploadContent}
|
||||||
/>}
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, string, bool} = PropTypes
|
const {func, string, bool} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -10,26 +10,28 @@ const WriteDataFooter = ({
|
||||||
uploadContent,
|
uploadContent,
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
isUploading,
|
isUploading,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="write-data-form--footer">
|
<div className="write-data-form--footer">
|
||||||
{isManual
|
{isManual ? (
|
||||||
? <span className="write-data-form--helper">
|
<span className="write-data-form--helper">
|
||||||
Need help writing InfluxDB Line Protocol? -
|
Need help writing InfluxDB Line Protocol? -
|
||||||
<a
|
<a
|
||||||
href="https://docs.influxdata.com/influxdb/latest/write_protocols/line_protocol_tutorial/"
|
href="https://docs.influxdata.com/influxdb/latest/write_protocols/line_protocol_tutorial/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
>
|
>
|
||||||
See Documentation
|
See Documentation
|
||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
: <span className="write-data-form--helper">
|
) : (
|
||||||
<a
|
<span className="write-data-form--helper">
|
||||||
href="https://docs.influxdata.com/influxdb/v1.2//tools/shell/#import-data-from-a-file-with-import"
|
<a
|
||||||
target="_blank"
|
href="https://docs.influxdata.com/influxdb/v1.2//tools/shell/#import-data-from-a-file-with-import"
|
||||||
>
|
target="_blank"
|
||||||
File Upload Documentation
|
>
|
||||||
</a>
|
File Upload Documentation
|
||||||
</span>}
|
</a>
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
<button
|
<button
|
||||||
className={isUploading ? `${submitButton} ${spinner}` : submitButton}
|
className={isUploading ? `${submitButton} ${spinner}` : submitButton}
|
||||||
onClick={handleSubmit}
|
onClick={handleSubmit}
|
||||||
|
@ -43,6 +45,7 @@ const WriteDataFooter = ({
|
||||||
Write
|
Write
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {bool, func, string} = PropTypes
|
const {bool, func, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ const WriteDataHeader = ({
|
||||||
toggleWriteView,
|
toggleWriteView,
|
||||||
isManual,
|
isManual,
|
||||||
onClose,
|
onClose,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="write-data-form--header">
|
<div className="write-data-form--header">
|
||||||
<div className="page-header__left">
|
<div className="page-header__left">
|
||||||
<h1 className="page-header__title">Write Data To</h1>
|
<h1 className="page-header__title">Write Data To</h1>
|
||||||
|
@ -38,6 +38,7 @@ const WriteDataHeader = ({
|
||||||
<span className="page-header__dismiss" onClick={onClose} />
|
<span className="page-header__dismiss" onClick={onClose} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, string, bool} = PropTypes
|
const {func, string, bool} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -95,17 +95,17 @@ class DataExplorer extends Component {
|
||||||
const selectedDatabase = _.get(queryConfigs, ['0', 'database'], null)
|
const selectedDatabase = _.get(queryConfigs, ['0', 'database'], null)
|
||||||
return (
|
return (
|
||||||
<div className="data-explorer">
|
<div className="data-explorer">
|
||||||
{showWriteForm
|
{showWriteForm ? (
|
||||||
? <OverlayTechnologies>
|
<OverlayTechnologies>
|
||||||
<WriteDataForm
|
<WriteDataForm
|
||||||
source={source}
|
source={source}
|
||||||
errorThrown={errorThrownAction}
|
errorThrown={errorThrownAction}
|
||||||
selectedDatabase={selectedDatabase}
|
selectedDatabase={selectedDatabase}
|
||||||
onClose={this.handleCloseWriteData}
|
onClose={this.handleCloseWriteData}
|
||||||
writeLineProtocol={writeLineProtocol}
|
writeLineProtocol={writeLineProtocol}
|
||||||
/>
|
/>
|
||||||
</OverlayTechnologies>
|
</OverlayTechnologies>
|
||||||
: null}
|
) : null}
|
||||||
<Header
|
<Header
|
||||||
timeRange={timeRange}
|
timeRange={timeRange}
|
||||||
autoRefresh={autoRefresh}
|
autoRefresh={autoRefresh}
|
||||||
|
|
|
@ -16,7 +16,7 @@ const Header = ({
|
||||||
onManualRefresh,
|
onManualRefresh,
|
||||||
onChooseTimeRange,
|
onChooseTimeRange,
|
||||||
onChooseAutoRefresh,
|
onChooseAutoRefresh,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="page-header full-width">
|
<div className="page-header full-width">
|
||||||
<div className="page-header__container">
|
<div className="page-header__container">
|
||||||
<div className="page-header__left">
|
<div className="page-header__left">
|
||||||
|
@ -47,6 +47,7 @@ const Header = ({
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
Header.propTypes = {
|
Header.propTypes = {
|
||||||
onChooseAutoRefresh: func.isRequired,
|
onChooseAutoRefresh: func.isRequired,
|
||||||
|
|
|
@ -37,7 +37,10 @@ const download = (data, strFileName, strMimeType) => {
|
||||||
|
|
||||||
if (url && url.length < 2048) {
|
if (url && url.length < 2048) {
|
||||||
// if no filename and no mime, assume a url was passed as the only argument
|
// if no filename and no mime, assume a url was passed as the only argument
|
||||||
fileName = url.split('/').pop().split('?')[0]
|
fileName = url
|
||||||
|
.split('/')
|
||||||
|
.pop()
|
||||||
|
.split('?')[0]
|
||||||
anchor.href = url // assign href prop to temp anchor
|
anchor.href = url // assign href prop to temp anchor
|
||||||
if (anchor.href.indexOf(url) !== -1) {
|
if (anchor.href.indexOf(url) !== -1) {
|
||||||
// if the browser determines that it's a potentially valid url path:
|
// if the browser determines that it's a potentially valid url path:
|
||||||
|
|
|
@ -23,9 +23,7 @@ class HostRow extends Component {
|
||||||
return (
|
return (
|
||||||
<div className="hosts-table--tr">
|
<div className="hosts-table--tr">
|
||||||
<div className="hosts-table--td" style={{width: colName}}>
|
<div className="hosts-table--td" style={{width: colName}}>
|
||||||
<Link to={`/sources/${source.id}/hosts/${name}`}>
|
<Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>
|
||||||
{name}
|
|
||||||
</Link>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="hosts-table--td" style={{width: colStatus}}>
|
<div className="hosts-table--td" style={{width: colStatus}}>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -102,61 +102,61 @@ class HostsTable extends Component {
|
||||||
return (
|
return (
|
||||||
<div className="panel">
|
<div className="panel">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<h2 className="panel-title">
|
<h2 className="panel-title">{hostsTitle}</h2>
|
||||||
{hostsTitle}
|
|
||||||
</h2>
|
|
||||||
<SearchBar
|
<SearchBar
|
||||||
placeholder="Filter by Host..."
|
placeholder="Filter by Host..."
|
||||||
onSearch={this.updateSearchTerm}
|
onSearch={this.updateSearchTerm}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="panel-body">
|
<div className="panel-body">
|
||||||
{hostCount > 0 && !hostsError.length
|
{hostCount > 0 && !hostsError.length ? (
|
||||||
? <div className="hosts-table">
|
<div className="hosts-table">
|
||||||
<div className="hosts-table--thead">
|
<div className="hosts-table--thead">
|
||||||
<div className="hosts-table--tr">
|
<div className="hosts-table--tr">
|
||||||
<div
|
<div
|
||||||
onClick={this.updateSort('name')}
|
onClick={this.updateSort('name')}
|
||||||
className={this.sortableClasses('name')}
|
className={this.sortableClasses('name')}
|
||||||
style={{width: colName}}
|
style={{width: colName}}
|
||||||
>
|
>
|
||||||
Host
|
Host
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={this.updateSort('deltaUptime')}
|
|
||||||
className={this.sortableClasses('deltaUptime')}
|
|
||||||
style={{width: colStatus}}
|
|
||||||
>
|
|
||||||
Status
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={this.updateSort('cpu')}
|
|
||||||
className={this.sortableClasses('cpu')}
|
|
||||||
style={{width: colCPU}}
|
|
||||||
>
|
|
||||||
CPU
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
onClick={this.updateSort('load')}
|
|
||||||
className={this.sortableClasses('load')}
|
|
||||||
style={{width: colLoad}}
|
|
||||||
>
|
|
||||||
Load
|
|
||||||
</div>
|
|
||||||
<div className="hosts-table--th">Apps</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={this.updateSort('deltaUptime')}
|
||||||
|
className={this.sortableClasses('deltaUptime')}
|
||||||
|
style={{width: colStatus}}
|
||||||
|
>
|
||||||
|
Status
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={this.updateSort('cpu')}
|
||||||
|
className={this.sortableClasses('cpu')}
|
||||||
|
style={{width: colCPU}}
|
||||||
|
>
|
||||||
|
CPU
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
onClick={this.updateSort('load')}
|
||||||
|
className={this.sortableClasses('load')}
|
||||||
|
style={{width: colLoad}}
|
||||||
|
>
|
||||||
|
Load
|
||||||
|
</div>
|
||||||
|
<div className="hosts-table--th">Apps</div>
|
||||||
</div>
|
</div>
|
||||||
<InfiniteScroll
|
|
||||||
items={sortedHosts.map(h =>
|
|
||||||
<HostRow key={h.name} host={h} source={source} />
|
|
||||||
)}
|
|
||||||
itemHeight={26}
|
|
||||||
className="hosts-table--tbody"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
: <div className="generic-empty-state">
|
<InfiniteScroll
|
||||||
<h4 style={{margin: '90px 0'}}>No Hosts found</h4>
|
items={sortedHosts.map(h => (
|
||||||
</div>}
|
<HostRow key={h.name} host={h} source={source} />
|
||||||
|
))}
|
||||||
|
itemHeight={26}
|
||||||
|
className="hosts-table--tbody"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className="generic-empty-state">
|
||||||
|
<h4 style={{margin: '90px 0'}}>No Hosts found</h4>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -96,7 +96,7 @@ class HostPage extends Component {
|
||||||
const autoflowCells = autoflowLayouts.reduce((allCells, layout) => {
|
const autoflowCells = autoflowLayouts.reduce((allCells, layout) => {
|
||||||
return allCells.concat(
|
return allCells.concat(
|
||||||
layout.cells.map(cell => {
|
layout.cells.map(cell => {
|
||||||
const x = cellCount * cellWidth % pageWidth
|
const x = (cellCount * cellWidth) % pageWidth
|
||||||
const y = Math.floor(cellCount * cellWidth / pageWidth) * cellHeight
|
const y = Math.floor(cellCount * cellWidth / pageWidth) * cellHeight
|
||||||
cellCount += 1
|
cellCount += 1
|
||||||
return Object.assign(cell, {
|
return Object.assign(cell, {
|
||||||
|
|
102
ui/src/index.js
102
ui/src/index.js
|
@ -122,66 +122,50 @@ const Root = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return !this.state.ready // eslint-disable-line no-negated-condition
|
return !this.state.ready ? ( // eslint-disable-line no-negated-condition
|
||||||
? <div className="page-spinner" />
|
<div className="page-spinner" />
|
||||||
: <Provider store={store}>
|
) : (
|
||||||
<Router history={history}>
|
<Provider store={store}>
|
||||||
<Route path="/" component={UserIsAuthenticated(CheckSources)} />
|
<Router history={history}>
|
||||||
<Route path="/login" component={UserIsNotAuthenticated(Login)} />
|
<Route path="/" component={UserIsAuthenticated(CheckSources)} />
|
||||||
<Route
|
<Route path="/login" component={UserIsNotAuthenticated(Login)} />
|
||||||
path="/purgatory"
|
<Route path="/purgatory" component={UserIsAuthenticated(Purgatory)} />
|
||||||
component={UserIsAuthenticated(Purgatory)}
|
<Route
|
||||||
/>
|
path="/sources/new"
|
||||||
<Route
|
component={UserIsAuthenticated(SourcePage)}
|
||||||
path="/sources/new"
|
/>
|
||||||
component={UserIsAuthenticated(SourcePage)}
|
<Route path="/sources/:sourceID" component={UserIsAuthenticated(App)}>
|
||||||
/>
|
<Route component={CheckSources}>
|
||||||
<Route
|
<Route path="status" component={StatusPage} />
|
||||||
path="/sources/:sourceID"
|
<Route path="hosts" component={HostsPage} />
|
||||||
component={UserIsAuthenticated(App)}
|
<Route path="hosts/:hostID" component={HostPage} />
|
||||||
>
|
<Route path="chronograf/data-explorer" component={DataExplorer} />
|
||||||
<Route component={CheckSources}>
|
<Route path="dashboards" component={DashboardsPage} />
|
||||||
<Route path="status" component={StatusPage} />
|
<Route path="dashboards/:dashboardID" component={DashboardPage} />
|
||||||
<Route path="hosts" component={HostsPage} />
|
<Route path="alerts" component={AlertsApp} />
|
||||||
<Route path="hosts/:hostID" component={HostPage} />
|
<Route path="alert-rules" component={KapacitorRulesPage} />
|
||||||
<Route
|
<Route path="alert-rules/:ruleID" component={KapacitorRulePage} />
|
||||||
path="chronograf/data-explorer"
|
<Route path="alert-rules/new" component={KapacitorRulePage} />
|
||||||
component={DataExplorer}
|
<Route path="tickscript/new" component={TickscriptPage} />
|
||||||
/>
|
<Route path="tickscript/:ruleID" component={TickscriptPage} />
|
||||||
<Route path="dashboards" component={DashboardsPage} />
|
<Route path="kapacitors/new" component={KapacitorPage} />
|
||||||
<Route
|
<Route path="kapacitors/:id/edit" component={KapacitorPage} />
|
||||||
path="dashboards/:dashboardID"
|
<Route
|
||||||
component={DashboardPage}
|
path="kapacitors/:id/edit:hash"
|
||||||
/>
|
component={KapacitorPage}
|
||||||
<Route path="alerts" component={AlertsApp} />
|
/>
|
||||||
<Route path="alert-rules" component={KapacitorRulesPage} />
|
<Route path="kapacitor-tasks" component={KapacitorTasksPage} />
|
||||||
<Route
|
<Route path="admin-chronograf" component={AdminChronografPage} />
|
||||||
path="alert-rules/:ruleID"
|
<Route path="admin-influxdb" component={AdminInfluxDBPage} />
|
||||||
component={KapacitorRulePage}
|
<Route path="manage-sources" component={ManageSources} />
|
||||||
/>
|
<Route path="manage-sources/new" component={SourcePage} />
|
||||||
<Route path="alert-rules/new" component={KapacitorRulePage} />
|
<Route path="manage-sources/:id/edit" component={SourcePage} />
|
||||||
<Route path="tickscript/new" component={TickscriptPage} />
|
|
||||||
<Route path="tickscript/:ruleID" component={TickscriptPage} />
|
|
||||||
<Route path="kapacitors/new" component={KapacitorPage} />
|
|
||||||
<Route path="kapacitors/:id/edit" component={KapacitorPage} />
|
|
||||||
<Route
|
|
||||||
path="kapacitors/:id/edit:hash"
|
|
||||||
component={KapacitorPage}
|
|
||||||
/>
|
|
||||||
<Route path="kapacitor-tasks" component={KapacitorTasksPage} />
|
|
||||||
<Route
|
|
||||||
path="admin-chronograf"
|
|
||||||
component={AdminChronografPage}
|
|
||||||
/>
|
|
||||||
<Route path="admin-influxdb" component={AdminInfluxDBPage} />
|
|
||||||
<Route path="manage-sources" component={ManageSources} />
|
|
||||||
<Route path="manage-sources/new" component={SourcePage} />
|
|
||||||
<Route path="manage-sources/:id/edit" component={SourcePage} />
|
|
||||||
</Route>
|
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="*" component={NotFound} />
|
</Route>
|
||||||
</Router>
|
<Route path="*" component={NotFound} />
|
||||||
</Provider>
|
</Router>
|
||||||
|
</Provider>
|
||||||
|
)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -142,123 +142,134 @@ class AlertTabs extends Component {
|
||||||
alerta: {
|
alerta: {
|
||||||
type: 'Alerta',
|
type: 'Alerta',
|
||||||
enabled: this.getEnabled(configSections, 'alerta'),
|
enabled: this.getEnabled(configSections, 'alerta'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<AlertaConfig
|
<AlertaConfig
|
||||||
onSave={this.handleSaveConfig('alerta')}
|
onSave={this.handleSaveConfig('alerta')}
|
||||||
config={this.getSection(configSections, 'alerta')}
|
config={this.getSection(configSections, 'alerta')}
|
||||||
onTest={this.handleTestConfig('alerta')}
|
onTest={this.handleTestConfig('alerta')}
|
||||||
enabled={this.getEnabled(configSections, 'alerta')}
|
enabled={this.getEnabled(configSections, 'alerta')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
hipchat: {
|
hipchat: {
|
||||||
type: 'HipChat',
|
type: 'HipChat',
|
||||||
enabled: this.getEnabled(configSections, 'hipchat'),
|
enabled: this.getEnabled(configSections, 'hipchat'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<HipChatConfig
|
<HipChatConfig
|
||||||
onSave={this.handleSaveConfig('hipchat')}
|
onSave={this.handleSaveConfig('hipchat')}
|
||||||
config={this.getSection(configSections, 'hipchat')}
|
config={this.getSection(configSections, 'hipchat')}
|
||||||
onTest={this.handleTestConfig('hipchat')}
|
onTest={this.handleTestConfig('hipchat')}
|
||||||
enabled={this.getEnabled(configSections, 'hipchat')}
|
enabled={this.getEnabled(configSections, 'hipchat')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
opsgenie: {
|
opsgenie: {
|
||||||
type: 'OpsGenie',
|
type: 'OpsGenie',
|
||||||
enabled: this.getEnabled(configSections, 'opsgenie'),
|
enabled: this.getEnabled(configSections, 'opsgenie'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<OpsGenieConfig
|
<OpsGenieConfig
|
||||||
onSave={this.handleSaveConfig('opsgenie')}
|
onSave={this.handleSaveConfig('opsgenie')}
|
||||||
config={this.getSection(configSections, 'opsgenie')}
|
config={this.getSection(configSections, 'opsgenie')}
|
||||||
onTest={this.handleTestConfig('opsgenie')}
|
onTest={this.handleTestConfig('opsgenie')}
|
||||||
enabled={this.getEnabled(configSections, 'opsgenie')}
|
enabled={this.getEnabled(configSections, 'opsgenie')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
pagerduty: {
|
pagerduty: {
|
||||||
type: 'PagerDuty',
|
type: 'PagerDuty',
|
||||||
enabled: this.getEnabled(configSections, 'pagerduty'),
|
enabled: this.getEnabled(configSections, 'pagerduty'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<PagerDutyConfig
|
<PagerDutyConfig
|
||||||
onSave={this.handleSaveConfig('pagerduty')}
|
onSave={this.handleSaveConfig('pagerduty')}
|
||||||
config={this.getSection(configSections, 'pagerduty')}
|
config={this.getSection(configSections, 'pagerduty')}
|
||||||
onTest={this.handleTestConfig('pagerduty')}
|
onTest={this.handleTestConfig('pagerduty')}
|
||||||
enabled={this.getEnabled(configSections, 'pagerduty')}
|
enabled={this.getEnabled(configSections, 'pagerduty')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
pushover: {
|
pushover: {
|
||||||
type: 'Pushover',
|
type: 'Pushover',
|
||||||
enabled: this.getEnabled(configSections, 'pushover'),
|
enabled: this.getEnabled(configSections, 'pushover'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<PushoverConfig
|
<PushoverConfig
|
||||||
onSave={this.handleSaveConfig('pushover')}
|
onSave={this.handleSaveConfig('pushover')}
|
||||||
config={this.getSection(configSections, 'pushover')}
|
config={this.getSection(configSections, 'pushover')}
|
||||||
onTest={this.handleTestConfig('pushover')}
|
onTest={this.handleTestConfig('pushover')}
|
||||||
enabled={this.getEnabled(configSections, 'pushover')}
|
enabled={this.getEnabled(configSections, 'pushover')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
sensu: {
|
sensu: {
|
||||||
type: 'Sensu',
|
type: 'Sensu',
|
||||||
enabled: this.getEnabled(configSections, 'sensu'),
|
enabled: this.getEnabled(configSections, 'sensu'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<SensuConfig
|
<SensuConfig
|
||||||
onSave={this.handleSaveConfig('sensu')}
|
onSave={this.handleSaveConfig('sensu')}
|
||||||
config={this.getSection(configSections, 'sensu')}
|
config={this.getSection(configSections, 'sensu')}
|
||||||
onTest={this.handleTestConfig('sensu')}
|
onTest={this.handleTestConfig('sensu')}
|
||||||
enabled={this.getEnabled(configSections, 'sensu')}
|
enabled={this.getEnabled(configSections, 'sensu')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
slack: {
|
slack: {
|
||||||
type: 'Slack',
|
type: 'Slack',
|
||||||
enabled: this.getEnabled(configSections, 'slack'),
|
enabled: this.getEnabled(configSections, 'slack'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<SlackConfig
|
<SlackConfig
|
||||||
onSave={this.handleSaveConfig('slack')}
|
onSave={this.handleSaveConfig('slack')}
|
||||||
config={this.getSection(configSections, 'slack')}
|
config={this.getSection(configSections, 'slack')}
|
||||||
onTest={this.handleTestConfig('slack')}
|
onTest={this.handleTestConfig('slack')}
|
||||||
enabled={this.getEnabled(configSections, 'slack')}
|
enabled={this.getEnabled(configSections, 'slack')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
smtp: {
|
smtp: {
|
||||||
type: 'SMTP',
|
type: 'SMTP',
|
||||||
enabled: this.getEnabled(configSections, 'smtp'),
|
enabled: this.getEnabled(configSections, 'smtp'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<SMTPConfig
|
<SMTPConfig
|
||||||
onSave={this.handleSaveConfig('smtp')}
|
onSave={this.handleSaveConfig('smtp')}
|
||||||
config={this.getSection(configSections, 'smtp')}
|
config={this.getSection(configSections, 'smtp')}
|
||||||
onTest={this.handleTestConfig('smtp')}
|
onTest={this.handleTestConfig('smtp')}
|
||||||
enabled={this.getEnabled(configSections, 'smtp')}
|
enabled={this.getEnabled(configSections, 'smtp')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
talk: {
|
talk: {
|
||||||
type: 'Talk',
|
type: 'Talk',
|
||||||
enabled: this.getEnabled(configSections, 'talk'),
|
enabled: this.getEnabled(configSections, 'talk'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<TalkConfig
|
<TalkConfig
|
||||||
onSave={this.handleSaveConfig('talk')}
|
onSave={this.handleSaveConfig('talk')}
|
||||||
config={this.getSection(configSections, 'talk')}
|
config={this.getSection(configSections, 'talk')}
|
||||||
onTest={this.handleTestConfig('talk')}
|
onTest={this.handleTestConfig('talk')}
|
||||||
enabled={this.getEnabled(configSections, 'talk')}
|
enabled={this.getEnabled(configSections, 'talk')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
telegram: {
|
telegram: {
|
||||||
type: 'Telegram',
|
type: 'Telegram',
|
||||||
enabled: this.getEnabled(configSections, 'telegram'),
|
enabled: this.getEnabled(configSections, 'telegram'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<TelegramConfig
|
<TelegramConfig
|
||||||
onSave={this.handleSaveConfig('telegram')}
|
onSave={this.handleSaveConfig('telegram')}
|
||||||
config={this.getSection(configSections, 'telegram')}
|
config={this.getSection(configSections, 'telegram')}
|
||||||
onTest={this.handleTestConfig('telegram')}
|
onTest={this.handleTestConfig('telegram')}
|
||||||
enabled={this.getEnabled(configSections, 'telegram')}
|
enabled={this.getEnabled(configSections, 'telegram')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
victorops: {
|
victorops: {
|
||||||
type: 'VictorOps',
|
type: 'VictorOps',
|
||||||
enabled: this.getEnabled(configSections, 'victorops'),
|
enabled: this.getEnabled(configSections, 'victorops'),
|
||||||
renderComponent: () =>
|
renderComponent: () => (
|
||||||
<VictorOpsConfig
|
<VictorOpsConfig
|
||||||
onSave={this.handleSaveConfig('victorops')}
|
onSave={this.handleSaveConfig('victorops')}
|
||||||
config={this.getSection(configSections, 'victorops')}
|
config={this.getSection(configSections, 'victorops')}
|
||||||
onTest={this.handleTestConfig('victorops')}
|
onTest={this.handleTestConfig('victorops')}
|
||||||
enabled={this.getEnabled(configSections, 'victorops')}
|
enabled={this.getEnabled(configSections, 'victorops')}
|
||||||
/>,
|
/>
|
||||||
|
),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const CodeData = ({onClickTemplate, template}) =>
|
const CodeData = ({onClickTemplate, template}) => (
|
||||||
<code
|
<code
|
||||||
className="rule-builder--message-template"
|
className="rule-builder--message-template"
|
||||||
data-tip={template.text}
|
data-tip={template.text}
|
||||||
|
@ -9,6 +9,7 @@ const CodeData = ({onClickTemplate, template}) =>
|
||||||
>
|
>
|
||||||
{template.label}
|
{template.label}
|
||||||
</code>
|
</code>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, shape, string} = PropTypes
|
const {func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -76,16 +76,16 @@ const DataSection = ({
|
||||||
onGroupByTag={handleGroupByTag}
|
onGroupByTag={handleGroupByTag}
|
||||||
onToggleTagAcceptance={handleToggleTagAcceptance}
|
onToggleTagAcceptance={handleToggleTagAcceptance}
|
||||||
/>
|
/>
|
||||||
{isDeadman
|
{isDeadman ? null : (
|
||||||
? null
|
<FieldList
|
||||||
: <FieldList
|
query={query}
|
||||||
query={query}
|
onToggleField={handleToggleField}
|
||||||
onToggleField={handleToggleField}
|
isKapacitorRule={isKapacitorRule}
|
||||||
isKapacitorRule={isKapacitorRule}
|
onGroupByTime={handleGroupByTime}
|
||||||
onGroupByTime={handleGroupByTime}
|
removeFuncs={handleRemoveFuncs}
|
||||||
removeFuncs={handleRemoveFuncs}
|
applyFuncsToField={handleApplyFuncsToField(onAddEvery)}
|
||||||
applyFuncsToField={handleApplyFuncsToField(onAddEvery)}
|
/>
|
||||||
/>}
|
)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,7 +7,7 @@ const periods = PERIODS.map(text => {
|
||||||
return {text}
|
return {text}
|
||||||
})
|
})
|
||||||
|
|
||||||
const Deadman = ({rule, onChange}) =>
|
const Deadman = ({rule, onChange}) => (
|
||||||
<div className="rule-section--row rule-section--row-first rule-section--row-last">
|
<div className="rule-section--row rule-section--row-first rule-section--row-last">
|
||||||
<p>Send Alert if Data is missing for</p>
|
<p>Send Alert if Data is missing for</p>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
@ -18,6 +18,7 @@ const Deadman = ({rule, onChange}) =>
|
||||||
onChoose={onChange}
|
onChoose={onChange}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string, func} = PropTypes
|
const {shape, string, func} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ const HandlerCheckbox = ({
|
||||||
fieldDisplay,
|
fieldDisplay,
|
||||||
selectedHandler,
|
selectedHandler,
|
||||||
handleModifyHandler,
|
handleModifyHandler,
|
||||||
}) =>
|
}) => (
|
||||||
<div className="form-group ">
|
<div className="form-group ">
|
||||||
<div className="form-control-static handler-checkbox">
|
<div className="form-control-static handler-checkbox">
|
||||||
<input
|
<input
|
||||||
|
@ -16,11 +16,10 @@ const HandlerCheckbox = ({
|
||||||
defaultChecked={selectedHandler[fieldName]}
|
defaultChecked={selectedHandler[fieldName]}
|
||||||
onClick={handleModifyHandler(selectedHandler, fieldName)}
|
onClick={handleModifyHandler(selectedHandler, fieldName)}
|
||||||
/>
|
/>
|
||||||
<label htmlFor={fieldName}>
|
<label htmlFor={fieldName}>{fieldDisplay}</label>
|
||||||
{fieldDisplay}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {func, shape, string, bool} = PropTypes
|
const {func, shape, string, bool} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const HandlerEmpty = ({onGoToConfig, validationError}) =>
|
const HandlerEmpty = ({onGoToConfig, validationError}) => (
|
||||||
<div className="endpoint-tab-contents">
|
<div className="endpoint-tab-contents">
|
||||||
<div className="endpoint-tab--parameters">
|
<div className="endpoint-tab--parameters">
|
||||||
<div className="endpoint-tab--parameters--empty">
|
<div className="endpoint-tab--parameters--empty">
|
||||||
|
@ -20,6 +20,7 @@ const HandlerEmpty = ({onGoToConfig, validationError}) =>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {string, func} = PropTypes
|
const {string, func} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -17,9 +17,7 @@ const HandlerInput = ({
|
||||||
const formGroupClass = `form-group ${fieldColumns}`
|
const formGroupClass = `form-group ${fieldColumns}`
|
||||||
return (
|
return (
|
||||||
<div className={formGroupClass}>
|
<div className={formGroupClass}>
|
||||||
<label htmlFor={fieldName}>
|
<label htmlFor={fieldName}>{fieldDisplay}</label>
|
||||||
{fieldDisplay}
|
|
||||||
</label>
|
|
||||||
<div className={redacted ? 'form-control-static redacted-handler' : null}>
|
<div className={redacted ? 'form-control-static redacted-handler' : null}>
|
||||||
<input
|
<input
|
||||||
name={fieldName}
|
name={fieldName}
|
||||||
|
@ -42,11 +40,11 @@ const HandlerInput = ({
|
||||||
spellCheck="false"
|
spellCheck="false"
|
||||||
disabled={disabled}
|
disabled={disabled}
|
||||||
/>
|
/>
|
||||||
{redacted
|
{redacted ? (
|
||||||
? <span className="alert-value-set">
|
<span className="alert-value-set">
|
||||||
<span className="icon checkmark" /> Value set in Config
|
<span className="icon checkmark" /> Value set in Config
|
||||||
</span>
|
</span>
|
||||||
: null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,25 +9,25 @@ const HandlerTabs = ({
|
||||||
handleChooseHandler,
|
handleChooseHandler,
|
||||||
handleRemoveHandler,
|
handleRemoveHandler,
|
||||||
}) =>
|
}) =>
|
||||||
handlersOnThisAlert.length
|
handlersOnThisAlert.length ? (
|
||||||
? <ul className="endpoint-tabs">
|
<ul className="endpoint-tabs">
|
||||||
{handlersOnThisAlert.map(ep =>
|
{handlersOnThisAlert.map(ep => (
|
||||||
<li
|
<li
|
||||||
key={uuid.v4()}
|
key={uuid.v4()}
|
||||||
className={classnames('endpoint-tab', {
|
className={classnames('endpoint-tab', {
|
||||||
active: ep.alias === (selectedHandler && selectedHandler.alias),
|
active: ep.alias === (selectedHandler && selectedHandler.alias),
|
||||||
})}
|
})}
|
||||||
onClick={handleChooseHandler(ep)}
|
onClick={handleChooseHandler(ep)}
|
||||||
>
|
>
|
||||||
{ep.type}
|
{ep.type}
|
||||||
<button
|
<button
|
||||||
className="endpoint-tab--delete"
|
className="endpoint-tab--delete"
|
||||||
onClick={handleRemoveHandler(ep)}
|
onClick={handleRemoveHandler(ep)}
|
||||||
/>
|
/>
|
||||||
</li>
|
</li>
|
||||||
)}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
: null
|
) : null
|
||||||
|
|
||||||
const {shape, func, array} = PropTypes
|
const {shape, func, array} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -45,21 +45,18 @@ const KapacitorRules = ({
|
||||||
|
|
||||||
const builderRules = rules.filter(r => r.query)
|
const builderRules = rules.filter(r => r.query)
|
||||||
|
|
||||||
const builderHeader = `${builderRules.length} Alert Rule${builderRules.length ===
|
const builderHeader = `${builderRules.length} Alert Rule${
|
||||||
1
|
builderRules.length === 1 ? '' : 's'
|
||||||
? ''
|
}`
|
||||||
: 's'}`
|
const scriptsHeader = `${rules.length} TICKscript${
|
||||||
const scriptsHeader = `${rules.length} TICKscript${rules.length === 1
|
rules.length === 1 ? '' : 's'
|
||||||
? ''
|
}`
|
||||||
: 's'}`
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageContents source={source}>
|
<PageContents source={source}>
|
||||||
<div className="panel">
|
<div className="panel">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<h2 className="panel-title">
|
<h2 className="panel-title">{builderHeader}</h2>
|
||||||
{builderHeader}
|
|
||||||
</h2>
|
|
||||||
<Link
|
<Link
|
||||||
to={`/sources/${source.id}/alert-rules/new`}
|
to={`/sources/${source.id}/alert-rules/new`}
|
||||||
className="btn btn-sm btn-primary"
|
className="btn btn-sm btn-primary"
|
||||||
|
@ -79,9 +76,7 @@ const KapacitorRules = ({
|
||||||
</div>
|
</div>
|
||||||
<div className="panel">
|
<div className="panel">
|
||||||
<div className="panel-heading">
|
<div className="panel-heading">
|
||||||
<h2 className="panel-title">
|
<h2 className="panel-title">{scriptsHeader}</h2>
|
||||||
{scriptsHeader}
|
|
||||||
</h2>
|
|
||||||
<Link
|
<Link
|
||||||
to={`/sources/${source.id}/tickscript/new`}
|
to={`/sources/${source.id}/tickscript/new`}
|
||||||
className="btn btn-sm btn-success"
|
className="btn btn-sm btn-success"
|
||||||
|
@ -103,7 +98,7 @@ const KapacitorRules = ({
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const PageContents = ({children}) =>
|
const PageContents = ({children}) => (
|
||||||
<div className="page">
|
<div className="page">
|
||||||
<div className="page-header">
|
<div className="page-header">
|
||||||
<div className="page-header__container">
|
<div className="page-header__container">
|
||||||
|
@ -122,13 +117,12 @@ const PageContents = ({children}) =>
|
||||||
<FancyScrollbar className="page-contents fancy-scroll--kapacitor">
|
<FancyScrollbar className="page-contents fancy-scroll--kapacitor">
|
||||||
<div className="container-fluid">
|
<div className="container-fluid">
|
||||||
<div className="row">
|
<div className="row">
|
||||||
<div className="col-md-12">
|
<div className="col-md-12">{children}</div>
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</FancyScrollbar>
|
</FancyScrollbar>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, bool, func, node, shape} = PropTypes
|
const {arrayOf, bool, func, node, shape} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ const {
|
||||||
colActions,
|
colActions,
|
||||||
} = TASKS_TABLE
|
} = TASKS_TABLE
|
||||||
|
|
||||||
const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) =>
|
const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) => (
|
||||||
<table className="table v-center table-highlight">
|
<table className="table v-center table-highlight">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
|
@ -43,10 +43,11 @@ const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) =>
|
||||||
})}
|
})}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
)
|
||||||
|
|
||||||
const handleDelete = (rule, onDelete) => onDelete(rule)
|
const handleDelete = (rule, onDelete) => onDelete(rule)
|
||||||
|
|
||||||
const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) =>
|
const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) => (
|
||||||
<tr key={rule.id}>
|
<tr key={rule.id}>
|
||||||
<td style={{minWidth: colName}}>
|
<td style={{minWidth: colName}}>
|
||||||
<Link to={`/sources/${source.id}/alert-rules/${rule.id}`}>
|
<Link to={`/sources/${source.id}/alert-rules/${rule.id}`}>
|
||||||
|
@ -56,12 +57,8 @@ const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) =>
|
||||||
<td style={{width: colTrigger, textTransform: 'capitalize'}}>
|
<td style={{width: colTrigger, textTransform: 'capitalize'}}>
|
||||||
{rule.trigger}
|
{rule.trigger}
|
||||||
</td>
|
</td>
|
||||||
<td style={{width: colMessage}}>
|
<td style={{width: colMessage}}>{rule.message}</td>
|
||||||
{rule.message}
|
<td style={{width: colAlerts}}>{parseAlertNodeList(rule)}</td>
|
||||||
</td>
|
|
||||||
<td style={{width: colAlerts}}>
|
|
||||||
{parseAlertNodeList(rule)}
|
|
||||||
</td>
|
|
||||||
<td style={{width: colEnabled}} className="text-center">
|
<td style={{width: colEnabled}} className="text-center">
|
||||||
<div className="dark-checkbox">
|
<div className="dark-checkbox">
|
||||||
<input
|
<input
|
||||||
|
@ -84,6 +81,7 @@ const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) =>
|
||||||
/>
|
/>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, func, shape, string} = PropTypes
|
const {arrayOf, func, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogItemHTTP = ({logItem}) =>
|
const LogItemHTTP = ({logItem}) => (
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service">HTTP Request</div>
|
<div className="logs-table--service">HTTP Request</div>
|
||||||
|
@ -16,6 +14,7 @@ const LogItemHTTP = ({logItem}) =>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogItemHTTPError = ({logItem}) =>
|
const LogItemHTTPError = ({logItem}) => (
|
||||||
<div className="logs-table--row" key={logItem.key}>
|
<div className="logs-table--row" key={logItem.key}>
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service error">HTTP Server</div>
|
<div className="logs-table--service error">HTTP Server</div>
|
||||||
<div className="logs-table--columns">
|
<div className="logs-table--columns">
|
||||||
<div className="logs-table--key-values error">
|
<div className="logs-table--key-values error">ERROR: {logItem.msg}</div>
|
||||||
ERROR: {logItem.msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,11 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogItemInfluxDBDebug = ({logItem}) =>
|
const LogItemInfluxDBDebug = ({logItem}) => (
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service debug">InfluxDB</div>
|
<div className="logs-table--service debug">InfluxDB</div>
|
||||||
|
@ -20,6 +18,7 @@ const LogItemInfluxDBDebug = ({logItem}) =>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogItemKapacitorDebug = ({logItem}) =>
|
const LogItemKapacitorDebug = ({logItem}) => (
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service debug">Kapacitor</div>
|
<div className="logs-table--service debug">Kapacitor</div>
|
||||||
<div className="logs-table--columns">
|
<div className="logs-table--columns">
|
||||||
<div className="logs-table--key-values debug">
|
<div className="logs-table--key-values debug">DEBUG: {logItem.msg}</div>
|
||||||
DEBUG: {logItem.msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,20 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogItemKapacitorError = ({logItem}) =>
|
const LogItemKapacitorError = ({logItem}) => (
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service error">Kapacitor</div>
|
<div className="logs-table--service error">Kapacitor</div>
|
||||||
<div className="logs-table--columns">
|
<div className="logs-table--columns">
|
||||||
<div className="logs-table--key-values error">
|
<div className="logs-table--key-values error">ERROR: {logItem.msg}</div>
|
||||||
ERROR: {logItem.msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -10,26 +10,22 @@ const renderKeysAndValues = (object, name) => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="logs-table--column">
|
<div className="logs-table--column">
|
||||||
<h1>
|
<h1>{`${sortedObjKeys.length} ${name}`}</h1>
|
||||||
{`${sortedObjKeys.length} ${name}`}
|
|
||||||
</h1>
|
|
||||||
<div className="logs-table--scrollbox">
|
<div className="logs-table--scrollbox">
|
||||||
{sortedObjKeys.map(objKey =>
|
{sortedObjKeys.map(objKey => (
|
||||||
<div key={objKey} className="logs-table--key-value">
|
<div key={objKey} className="logs-table--key-value">
|
||||||
{objKey}: <span>{object[objKey]}</span>
|
{objKey}: <span>{object[objKey]}</span>
|
||||||
</div>
|
</div>
|
||||||
)}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
const LogItemKapacitorPoint = ({logItem}) =>
|
const LogItemKapacitorPoint = ({logItem}) => (
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service">Kapacitor Point</div>
|
<div className="logs-table--service">Kapacitor Point</div>
|
||||||
|
@ -39,6 +35,7 @@ const LogItemKapacitorPoint = ({logItem}) =>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -1,20 +1,17 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogItemSession = ({logItem}) =>
|
const LogItemSession = ({logItem}) => (
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--session">
|
<div className="logs-table--session">{logItem.msg}</div>
|
||||||
{logItem.msg}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string} = PropTypes
|
const {shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar'
|
||||||
|
|
||||||
const numLogsToRender = 200
|
const numLogsToRender = 200
|
||||||
|
|
||||||
const LogsTable = ({logs}) =>
|
const LogsTable = ({logs}) => (
|
||||||
<div className="logs-table">
|
<div className="logs-table">
|
||||||
<div className="logs-table--header">
|
<div className="logs-table--header">
|
||||||
{`${numLogsToRender} Most Recent Logs`}
|
{`${numLogsToRender} Most Recent Logs`}
|
||||||
|
@ -20,6 +20,7 @@ const LogsTable = ({logs}) =>
|
||||||
.map(log => <LogsTableRow key={log.key} logItem={log} />)}
|
.map(log => <LogsTableRow key={log.key} logItem={log} />)}
|
||||||
</FancyScrollbar>
|
</FancyScrollbar>
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {arrayOf, shape, string} = PropTypes
|
const {arrayOf, shape, string} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -36,18 +36,12 @@ const LogsTableRow = ({logItem}) => {
|
||||||
<div className="logs-table--row">
|
<div className="logs-table--row">
|
||||||
<div className="logs-table--divider">
|
<div className="logs-table--divider">
|
||||||
<div className={`logs-table--level ${logItem.lvl}`} />
|
<div className={`logs-table--level ${logItem.lvl}`} />
|
||||||
<div className="logs-table--timestamp">
|
<div className="logs-table--timestamp">{logItem.ts}</div>
|
||||||
{logItem.ts}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div className="logs-table--details">
|
<div className="logs-table--details">
|
||||||
<div className="logs-table--service">
|
<div className="logs-table--service">{logItem.service || '--'}</div>
|
||||||
{logItem.service || '--'}
|
|
||||||
</div>
|
|
||||||
<div className="logs-table--columns">
|
<div className="logs-table--columns">
|
||||||
<div className="logs-table--key-values">
|
<div className="logs-table--key-values">{logItem.msg || '--'}</div>
|
||||||
{logItem.msg || '--'}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
|
|
||||||
const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) =>
|
const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) => (
|
||||||
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite logs-toggle">
|
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite logs-toggle">
|
||||||
<li
|
<li
|
||||||
className={areLogsVisible ? null : 'active'}
|
className={areLogsVisible ? null : 'active'}
|
||||||
|
@ -16,6 +16,7 @@ const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) =>
|
||||||
Editor + Logs
|
Editor + Logs
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
)
|
||||||
|
|
||||||
const {bool, func} = PropTypes
|
const {bool, func} = PropTypes
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ const Relative = ({
|
||||||
onRuleTypeInputChange,
|
onRuleTypeInputChange,
|
||||||
onDropdownChange,
|
onDropdownChange,
|
||||||
rule: {values: {change, shift, operator, value}},
|
rule: {values: {change, shift, operator, value}},
|
||||||
}) =>
|
}) => (
|
||||||
<div className="rule-section--row rule-section--row-first rule-section--border-bottom">
|
<div className="rule-section--row rule-section--row-first rule-section--border-bottom">
|
||||||
<p>Send Alert when</p>
|
<p>Send Alert when</p>
|
||||||
<Dropdown
|
<Dropdown
|
||||||
|
@ -52,6 +52,7 @@ const Relative = ({
|
||||||
</form>
|
</form>
|
||||||
{change === CHANGES[1] ? <p>%</p> : null}
|
{change === CHANGES[1] ? <p>%</p> : null}
|
||||||
</div>
|
</div>
|
||||||
|
)
|
||||||
|
|
||||||
const {shape, string, func} = PropTypes
|
const {shape, string, func} = PropTypes
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue