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