Run eslint to fix issues

pull/10616/head
Brandon Farmer 2018-03-21 14:41:18 -07:00
parent ca7c72c695
commit 4dd1cc7418
203 changed files with 3194 additions and 3152 deletions

View File

@ -4,12 +4,13 @@ import PropTypes from 'prop-types'
import SideNav from 'src/side_nav' import SideNav from 'src/side_nav'
import Notifications from 'shared/components/Notifications' import Notifications from 'shared/components/Notifications'
const App = ({children}) => const App = ({children}) => (
<div className="chronograf-root"> <div className="chronograf-root">
<Notifications /> <Notifications />
<SideNav /> <SideNav />
{children} {children}
</div> </div>
)
const {node} = PropTypes const {node} = PropTypes

View File

@ -168,9 +168,9 @@ export const createMappingAsync = (url, mapping) => async dispatch => {
const {data} = await createMappingAJAX(url, mapping) const {data} = await createMappingAJAX(url, mapping)
dispatch(updateMapping(mappingWithTempId, data)) dispatch(updateMapping(mappingWithTempId, data))
} catch (error) { } catch (error) {
const message = `${_.upperFirst( const message = `${_.upperFirst(_.toLower(error.data.message))}: Scheme: ${
_.toLower(error.data.message) mapping.scheme
)}: Scheme: ${mapping.scheme} Provider: ${mapping.provider}` } Provider: ${mapping.provider}`
dispatch(errorThrown(error, message)) dispatch(errorThrown(error, message))
setTimeout( setTimeout(
() => dispatch(removeMapping(mappingWithTempId)), () => dispatch(removeMapping(mappingWithTempId)),
@ -212,9 +212,9 @@ export const createUserAsync = (url, user) => async dispatch => {
const {data} = await createUserAJAX(url, user) const {data} = await createUserAJAX(url, user)
dispatch(syncUser(userWithTempID, data)) dispatch(syncUser(userWithTempID, data))
} catch (error) { } catch (error) {
const message = `${_.upperFirst( const message = `${_.upperFirst(_.toLower(error.data.message))}: ${
_.toLower(error.data.message) user.scheme
)}: ${user.scheme}::${user.provider}::${user.name}` }::${user.provider}::${user.name}`
dispatch(errorThrown(error, message)) dispatch(errorThrown(error, message))
// undo optimistic update // undo optimistic update
setTimeout(() => dispatch(removeUser(userWithTempID)), REVERT_STATE_DELAY) setTimeout(() => dispatch(removeUser(userWithTempID)), REVERT_STATE_DELAY)
@ -277,9 +277,9 @@ export const createOrganizationAsync = (
const {data} = await createOrganizationAJAX(url, organization) const {data} = await createOrganizationAJAX(url, organization)
dispatch(syncOrganization(organization, data)) dispatch(syncOrganization(organization, data))
} catch (error) { } catch (error) {
const message = `${_.upperFirst( const message = `${_.upperFirst(_.toLower(error.data.message))}: ${
_.toLower(error.data.message) organization.name
)}: ${organization.name}` }`
dispatch(errorThrown(error, message)) dispatch(errorThrown(error, message))
// undo optimistic update // undo optimistic update
setTimeout( setTimeout(

View File

@ -89,18 +89,12 @@ const AdminTabs = ({
return ( return (
<Tabs className="row"> <Tabs className="row">
<TabList customClass="col-md-2 admin-tabs"> <TabList customClass="col-md-2 admin-tabs">
{tabs.map((t, i) => {tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
<Tab key={tabs[i].type}>
{tabs[i].type}
</Tab>
)}
</TabList> </TabList>
<TabPanels customClass="col-md-10 admin-tabs--content"> <TabPanels customClass="col-md-10 admin-tabs--content">
{tabs.map((t, i) => {tabs.map((t, i) => (
<TabPanel key={tabs[i].type}> <TabPanel key={tabs[i].type}>{t.component}</TabPanel>
{t.component} ))}
</TabPanel>
)}
</TabPanels> </TabPanels>
</Tabs> </Tabs>
) )

View File

@ -41,7 +41,7 @@ const DatabaseManager = ({
</button> </button>
</div> </div>
<div className="panel-body"> <div className="panel-body">
{databases.map(db => {databases.map(db => (
<DatabaseTable <DatabaseTable
key={db.links.self} key={db.links.self}
database={db} database={db}
@ -62,7 +62,7 @@ const DatabaseManager = ({
onRemoveRetentionPolicy={onRemoveRetentionPolicy} onRemoveRetentionPolicy={onRemoveRetentionPolicy}
onDeleteRetentionPolicy={onDeleteRetentionPolicy} onDeleteRetentionPolicy={onDeleteRetentionPolicy}
/> />
)} ))}
</div> </div>
</div> </div>
) )

View File

@ -148,19 +148,21 @@ class DatabaseRow extends Component {
return ( return (
<tr> <tr>
<td style={{width: `${DATABASE_TABLE.colRetentionPolicy}px`}}> <td style={{width: `${DATABASE_TABLE.colRetentionPolicy}px`}}>
{isNew {isNew ? (
? <input <input
className="form-control input-xs" className="form-control input-xs"
type="text" type="text"
defaultValue={name} defaultValue={name}
placeholder="Name this RP" placeholder="Name this RP"
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
ref={r => (this.name = r)} ref={r => (this.name = r)}
autoFocus={true} autoFocus={true}
spellCheck={false} spellCheck={false}
autoComplete={false} autoComplete={false}
/> />
: name} ) : (
name
)}
</td> </td>
<td style={{width: `${DATABASE_TABLE.colDuration}px`}}> <td style={{width: `${DATABASE_TABLE.colDuration}px`}}>
<input <input
@ -176,22 +178,22 @@ class DatabaseRow extends Component {
autoComplete={false} autoComplete={false}
/> />
</td> </td>
{isRFDisplayed {isRFDisplayed ? (
? <td style={{width: `${DATABASE_TABLE.colReplication}px`}}> <td style={{width: `${DATABASE_TABLE.colReplication}px`}}>
<input <input
className="form-control input-xs" className="form-control input-xs"
name="name" name="name"
type="number" type="number"
min="1" min="1"
defaultValue={replication || 1} defaultValue={replication || 1}
placeholder="# of Nodes" placeholder="# of Nodes"
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
ref={r => (this.replication = r)} ref={r => (this.replication = r)}
spellCheck={false} spellCheck={false}
autoComplete={false} autoComplete={false}
/> />
</td> </td>
: null} ) : null}
<td <td
className="text-right" className="text-right"
style={{width: `${DATABASE_TABLE.colDelete}px`}} style={{width: `${DATABASE_TABLE.colDelete}px`}}
@ -210,9 +212,9 @@ class DatabaseRow extends Component {
<tr> <tr>
<td> <td>
{`${name} `} {`${name} `}
{isDefault {isDefault ? (
? <span className="default-source-label">default</span> <span className="default-source-label">default</span>
: null} ) : null}
</td> </td>
<td <td
onClick={this.handleStartEdit} onClick={this.handleStartEdit}
@ -220,31 +222,33 @@ class DatabaseRow extends Component {
> >
{formattedDuration} {formattedDuration}
</td> </td>
{isRFDisplayed {isRFDisplayed ? (
? <td <td
onClick={this.handleStartEdit} onClick={this.handleStartEdit}
style={{width: `${DATABASE_TABLE.colReplication}px`}} style={{width: `${DATABASE_TABLE.colReplication}px`}}
> >
{replication} {replication}
</td> </td>
: null} ) : null}
<td <td
className="text-right" className="text-right"
style={{width: `${DATABASE_TABLE.colDelete}px`}} style={{width: `${DATABASE_TABLE.colDelete}px`}}
> >
{isDeleting {isDeleting ? (
? <YesNoButtons <YesNoButtons
onConfirm={onDelete(database, retentionPolicy)} onConfirm={onDelete(database, retentionPolicy)}
onCancel={this.handleEndDelete} onCancel={this.handleEndDelete}
buttonSize="btn-xs" buttonSize="btn-xs"
/> />
: <button ) : (
className="btn btn-danger btn-xs table--show-on-row-hover" <button
style={isDeletable ? {} : {visibility: 'hidden'}} className="btn btn-danger btn-xs table--show-on-row-hover"
onClick={this.handleStartDelete} style={isDeletable ? {} : {visibility: 'hidden'}}
> onClick={this.handleStartDelete}
{`Delete ${name}`} >
</button>} {`Delete ${name}`}
</button>
)}
</td> </td>
</tr> </tr>
) )

View File

@ -57,11 +57,11 @@ const DatabaseTable = ({
<th style={{width: `${DATABASE_TABLE.colDuration}px`}}> <th style={{width: `${DATABASE_TABLE.colDuration}px`}}>
Duration Duration
</th> </th>
{isRFDisplayed {isRFDisplayed ? (
? <th style={{width: `${DATABASE_TABLE.colReplication}px`}}> <th style={{width: `${DATABASE_TABLE.colReplication}px`}}>
Replication Factor Replication Factor
</th> </th>
: null} ) : null}
<th style={{width: `${DATABASE_TABLE.colDelete}px`}} /> <th style={{width: `${DATABASE_TABLE.colDelete}px`}} />
</tr> </tr>
</thead> </thead>

View File

@ -68,14 +68,14 @@ const Header = ({
> >
<span className="icon plus" /> Add Retention Policy <span className="icon plus" /> Add Retention Policy
</button> </button>
{database.name === '_internal' {database.name === '_internal' ? null : (
? null <button
: <button className="btn btn-xs btn-danger"
className="btn btn-xs btn-danger" onClick={onStartDelete(database)}
onClick={onStartDelete(database)} >
> Delete
Delete </button>
</button>} )}
</div> </div>
) )
@ -112,15 +112,13 @@ const Header = ({
return ( return (
<div className="db-manager-header"> <div className="db-manager-header">
<h4> <h4>{database.name}</h4>
{database.name}
</h4>
{database.hasOwnProperty('deleteCode') ? deleteConfirmation : buttons} {database.hasOwnProperty('deleteCode') ? deleteConfirmation : buttons}
</div> </div>
) )
} }
const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) => const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) => (
<div className="db-manager-header db-manager-header--edit"> <div className="db-manager-header db-manager-header--edit">
<input <input
className="form-control input-sm" className="form-control input-sm"
@ -136,6 +134,7 @@ const EditHeader = ({database, onEdit, onKeyDown, onConfirm, onCancel}) =>
/> />
<ConfirmButtons item={database} onConfirm={onConfirm} onCancel={onCancel} /> <ConfirmButtons item={database} onConfirm={onConfirm} onCancel={onCancel} />
</div> </div>
)
const {func, shape, bool} = PropTypes const {func, shape, bool} = PropTypes

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const EmptyRow = ({tableName}) => const EmptyRow = ({tableName}) => (
<tr className="table-empty-state"> <tr className="table-empty-state">
<th colSpan="5"> <th colSpan="5">
<p> <p>
@ -9,6 +9,7 @@ const EmptyRow = ({tableName}) =>
</p> </p>
</th> </th>
</tr> </tr>
)
const {string} = PropTypes const {string} = PropTypes

View File

@ -4,7 +4,7 @@ import PropTypes from 'prop-types'
import QueryRow from 'src/admin/components/QueryRow' import QueryRow from 'src/admin/components/QueryRow'
import {QUERIES_TABLE} from 'src/admin/constants/tableSizing' import {QUERIES_TABLE} from 'src/admin/constants/tableSizing'
const QueriesTable = ({queries, onKillQuery}) => const QueriesTable = ({queries, onKillQuery}) => (
<div> <div>
<div className="panel panel-solid"> <div className="panel panel-solid">
<div className="panel-body"> <div className="panel-body">
@ -20,14 +20,15 @@ const QueriesTable = ({queries, onKillQuery}) =>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{queries.map(q => {queries.map(q => (
<QueryRow key={q.id} query={q} onKill={onKillQuery} /> <QueryRow key={q.id} query={q} onKill={onKillQuery} />
)} ))}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
</div> </div>
)
const {arrayOf, func, shape} = PropTypes const {arrayOf, func, shape} = PropTypes

View File

@ -37,9 +37,7 @@ class QueryRow extends Component {
{database} {database}
</td> </td>
<td> <td>
<code> <code>{query}</code>
{query}
</code>
</td> </td>
<td <td
style={{width: `${QUERIES_TABLE.colRunning}px`}} style={{width: `${QUERIES_TABLE.colRunning}px`}}
@ -51,18 +49,20 @@ class QueryRow extends Component {
style={{width: `${QUERIES_TABLE.colKillQuery}px`}} style={{width: `${QUERIES_TABLE.colKillQuery}px`}}
className="text-right" className="text-right"
> >
{this.state.confirmingKill {this.state.confirmingKill ? (
? <ConfirmButtons <ConfirmButtons
onConfirm={this.handleFinishHim} onConfirm={this.handleFinishHim}
onCancel={this.handleShowMercy} onCancel={this.handleShowMercy}
buttonSize="btn-xs" buttonSize="btn-xs"
/> />
: <button ) : (
className="btn btn-xs btn-danger table--show-on-row-hover" <button
onClick={this.handleInitiateKill} className="btn btn-xs btn-danger table--show-on-row-hover"
> onClick={this.handleInitiateKill}
Kill >
</button>} Kill
</button>
)}
</td> </td>
</tr> </tr>
) )

View File

@ -64,41 +64,36 @@ const RoleRow = ({
return ( return (
<tr> <tr>
<td style={{width: `${ROLES_TABLE.colName}px`}}> <td style={{width: `${ROLES_TABLE.colName}px`}}>{roleName}</td>
{roleName} <td>
{allPermissions && allPermissions.length ? (
<MultiSelectDropdown
items={allPermissions.map(name => ({name}))}
selectedItems={perms.map(name => ({name}))}
label={perms.length ? '' : 'Select Permissions'}
onApply={handleUpdatePermissions}
buttonSize="btn-xs"
buttonColor="btn-primary"
customClass={classnames(`dropdown-${ROLES_TABLE.colPermissions}`, {
'admin-table--multi-select-empty': !permissions.length,
})}
/>
) : null}
</td> </td>
<td> <td>
{allPermissions && allPermissions.length {allUsers && allUsers.length ? (
? <MultiSelectDropdown <MultiSelectDropdown
items={allPermissions.map(name => ({name}))} items={allUsers}
selectedItems={perms.map(name => ({name}))} selectedItems={users}
label={perms.length ? '' : 'Select Permissions'} label={users.length ? '' : 'Select Users'}
onApply={handleUpdatePermissions} onApply={handleUpdateUsers}
buttonSize="btn-xs" buttonSize="btn-xs"
buttonColor="btn-primary" buttonColor="btn-primary"
customClass={classnames( customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
`dropdown-${ROLES_TABLE.colPermissions}`, 'admin-table--multi-select-empty': !users.length,
{ })}
'admin-table--multi-select-empty': !permissions.length, />
} ) : null}
)}
/>
: null}
</td>
<td>
{allUsers && allUsers.length
? <MultiSelectDropdown
items={allUsers}
selectedItems={users}
label={users.length ? '' : 'Select Users'}
onApply={handleUpdateUsers}
buttonSize="btn-xs"
buttonColor="btn-primary"
customClass={classnames(`dropdown-${ROLES_TABLE.colUsers}`, {
'admin-table--multi-select-empty': !users.length,
})}
/>
: null}
</td> </td>
<DeleteConfirmTableCell <DeleteConfirmTableCell
onDelete={onDelete} onDelete={onDelete}

View File

@ -17,7 +17,7 @@ const RolesTable = ({
onFilter, onFilter,
onUpdateRoleUsers, onUpdateRoleUsers,
onUpdateRolePermissions, onUpdateRolePermissions,
}) => }) => (
<div className="panel panel-solid"> <div className="panel panel-solid">
<FilterBar <FilterBar
type="roles" type="roles"
@ -36,30 +36,33 @@ const RolesTable = ({
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{roles.length {roles.length ? (
? roles roles
.filter(r => !r.hidden) .filter(r => !r.hidden)
.map(role => .map(role => (
<RoleRow <RoleRow
key={role.links.self} key={role.links.self}
allUsers={allUsers} allUsers={allUsers}
allPermissions={permissions} allPermissions={permissions}
role={role} role={role}
onEdit={onEdit} onEdit={onEdit}
onSave={onSave} onSave={onSave}
onCancel={onCancel} onCancel={onCancel}
onDelete={onDelete} onDelete={onDelete}
onUpdateRoleUsers={onUpdateRoleUsers} onUpdateRoleUsers={onUpdateRoleUsers}
onUpdateRolePermissions={onUpdateRolePermissions} onUpdateRolePermissions={onUpdateRolePermissions}
isEditing={role.isEditing} isEditing={role.isEditing}
isNew={role.isNew} isNew={role.isNew}
/> />
) ))
: <EmptyRow tableName={'Roles'} />} ) : (
<EmptyRow tableName={'Roles'} />
)}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
)
const {arrayOf, bool, func, shape, string} = PropTypes const {arrayOf, bool, func, shape, string} = PropTypes

View File

@ -22,19 +22,21 @@ class UserNewPassword extends Component {
const {user, isNew} = this.props const {user, isNew} = this.props
return ( return (
<td style={{width: `${USERS_TABLE.colPassword}px`}}> <td style={{width: `${USERS_TABLE.colPassword}px`}}>
{isNew {isNew ? (
? <input <input
className="form-control input-xs" className="form-control input-xs"
name="password" name="password"
type="password" type="password"
value={user.password || ''} value={user.password || ''}
placeholder="Password" placeholder="Password"
onChange={this.handleEdit(user)} onChange={this.handleEdit(user)}
onKeyPress={this.handleKeyPress(user)} onKeyPress={this.handleKeyPress(user)}
spellCheck={false} spellCheck={false}
autoComplete={false} autoComplete={false}
/> />
: '--'} ) : (
'--'
)}
</td> </td>
) )
} }

View File

@ -75,9 +75,7 @@ const UserRow = ({
return ( return (
<tr> <tr>
<td style={{width: `${USERS_TABLE.colUsername}px`}}> <td style={{width: `${USERS_TABLE.colUsername}px`}}>{name}</td>
{name}
</td>
<td style={{width: `${USERS_TABLE.colPassword}px`}}> <td style={{width: `${USERS_TABLE.colPassword}px`}}>
<ChangePassRow <ChangePassRow
onEdit={onEdit} onEdit={onEdit}
@ -86,40 +84,37 @@ const UserRow = ({
buttonSize="btn-xs" buttonSize="btn-xs"
/> />
</td> </td>
{hasRoles {hasRoles ? (
? <td> <td>
<MultiSelectDropdown <MultiSelectDropdown
items={allRoles} items={allRoles}
selectedItems={roles.map(r => ({name: r.name}))} selectedItems={roles.map(r => ({name: r.name}))}
label={roles.length ? '' : 'Select Roles'} label={roles.length ? '' : 'Select Roles'}
onApply={handleUpdateRoles} onApply={handleUpdateRoles}
buttonSize="btn-xs" buttonSize="btn-xs"
buttonColor="btn-primary" buttonColor="btn-primary"
customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, { customClass={classnames(`dropdown-${USERS_TABLE.colRoles}`, {
'admin-table--multi-select-empty': !roles.length, 'admin-table--multi-select-empty': !roles.length,
})} })}
/> />
</td> </td>
: null} ) : null}
<td> <td>
{allPermissions && allPermissions.length {allPermissions && allPermissions.length ? (
? <MultiSelectDropdown <MultiSelectDropdown
items={allPermissions.map(p => ({name: p}))} items={allPermissions.map(p => ({name: p}))}
selectedItems={perms.map(p => ({name: p}))} selectedItems={perms.map(p => ({name: p}))}
label={ label={
permissions && permissions.length ? '' : 'Select Permissions' permissions && permissions.length ? '' : 'Select Permissions'
} }
onApply={handleUpdatePermissions} onApply={handleUpdatePermissions}
buttonSize="btn-xs" buttonSize="btn-xs"
buttonColor="btn-primary" buttonColor="btn-primary"
customClass={classnames( customClass={classnames(`dropdown-${USERS_TABLE.colPermissions}`, {
`dropdown-${USERS_TABLE.colPermissions}`, 'admin-table--multi-select-empty': !permissions.length,
{ })}
'admin-table--multi-select-empty': !permissions.length, />
} ) : null}
)}
/>
: null}
</td> </td>
<DeleteConfirmTableCell <DeleteConfirmTableCell
onDelete={onDelete} onDelete={onDelete}

View File

@ -20,7 +20,7 @@ const UsersTable = ({
onUpdatePermissions, onUpdatePermissions,
onUpdateRoles, onUpdateRoles,
onUpdatePassword, onUpdatePassword,
}) => }) => (
<div className="panel panel-solid"> <div className="panel panel-solid">
<FilterBar <FilterBar
type="users" type="users"
@ -40,32 +40,35 @@ const UsersTable = ({
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{users.length {users.length ? (
? users users
.filter(u => !u.hidden) .filter(u => !u.hidden)
.map(user => .map(user => (
<UserRow <UserRow
key={user.links.self} key={user.links.self}
user={user} user={user}
onEdit={onEdit} onEdit={onEdit}
onSave={onSave} onSave={onSave}
onCancel={onCancel} onCancel={onCancel}
onDelete={onDelete} onDelete={onDelete}
isEditing={user.isEditing} isEditing={user.isEditing}
isNew={user.isNew} isNew={user.isNew}
allRoles={allRoles} allRoles={allRoles}
hasRoles={hasRoles} hasRoles={hasRoles}
allPermissions={permissions} allPermissions={permissions}
onUpdatePermissions={onUpdatePermissions} onUpdatePermissions={onUpdatePermissions}
onUpdateRoles={onUpdateRoles} onUpdateRoles={onUpdateRoles}
onUpdatePassword={onUpdatePassword} onUpdatePassword={onUpdatePassword}
/> />
) ))
: <EmptyRow tableName={'Users'} />} ) : (
<EmptyRow tableName={'Users'} />
)}
</tbody> </tbody>
</table> </table>
</div> </div>
</div> </div>
)
const {arrayOf, bool, func, shape, string} = PropTypes const {arrayOf, bool, func, shape, string} = PropTypes

View File

@ -51,18 +51,12 @@ const AdminTabs = ({
return ( return (
<Tabs className="row"> <Tabs className="row">
<TabList customClass="col-md-2 admin-tabs"> <TabList customClass="col-md-2 admin-tabs">
{tabs.map((t, i) => {tabs.map((t, i) => <Tab key={tabs[i].type}>{tabs[i].type}</Tab>)}
<Tab key={tabs[i].type}>
{tabs[i].type}
</Tab>
)}
</TabList> </TabList>
<TabPanels customClass="col-md-10 admin-tabs--content"> <TabPanels customClass="col-md-10 admin-tabs--content">
{tabs.map((t, i) => {tabs.map((t, i) => (
<TabPanel key={tabs[i].type}> <TabPanel key={tabs[i].type}>{t.component}</TabPanel>
{t.component} ))}
</TabPanel>
)}
</TabPanels> </TabPanels>
</Tabs> </Tabs>
) )

View File

@ -133,33 +133,33 @@ class AllUsersTable extends Component {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{users.length {users.length ? (
? users.map(user => users.map(user => (
<AllUsersTableRow <AllUsersTableRow
user={user} user={user}
key={uuid.v4()} key={uuid.v4()}
organizations={organizations}
onAddToOrganization={this.handleAddToOrganization}
onRemoveFromOrganization={
this.handleRemoveFromOrganization
}
onChangeSuperAdmin={this.handleChangeSuperAdmin}
onDelete={onDeleteUser}
meID={meID}
/>
)
: <tr className="table-empty-state">
<th colSpan="6">
<p>No Users to display</p>
</th>
</tr>}
{isCreatingUser
? <AllUsersTableRowNew
organizations={organizations} organizations={organizations}
onBlur={this.handleBlurCreateUserRow} onAddToOrganization={this.handleAddToOrganization}
onCreateUser={onCreateUser} onRemoveFromOrganization={this.handleRemoveFromOrganization}
onChangeSuperAdmin={this.handleChangeSuperAdmin}
onDelete={onDeleteUser}
meID={meID}
/> />
: null} ))
) : (
<tr className="table-empty-state">
<th colSpan="6">
<p>No Users to display</p>
</th>
</tr>
)}
{isCreatingUser ? (
<AllUsersTableRowNew
organizations={organizations}
onBlur={this.handleBlurCreateUserRow}
onCreateUser={onCreateUser}
/>
) : null}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -12,10 +12,9 @@ const AllUsersTableHeader = ({
onChangeAuthConfig, onChangeAuthConfig,
}) => { }) => {
const numUsersString = `${numUsers} User${numUsers === 1 ? '' : 's'}` const numUsersString = `${numUsers} User${numUsers === 1 ? '' : 's'}`
const numOrganizationsString = `${numOrganizations} Org${numOrganizations === const numOrganizationsString = `${numOrganizations} Org${
1 numOrganizations === 1 ? '' : 's'
? '' }`
: 's'}`
return ( return (
<div className="panel-heading"> <div className="panel-heading">

View File

@ -47,14 +47,14 @@ const AllUsersTableRow = ({
return ( return (
<tr className={'chronograf-admin-table--user'}> <tr className={'chronograf-admin-table--user'}>
<td> <td>
{userIsMe {userIsMe ? (
? <strong className="chronograf-user--me"> <strong className="chronograf-user--me">
<span className="icon user" /> <span className="icon user" />
{user.name} {user.name}
</strong> </strong>
: <strong> ) : (
{user.name} <strong>{user.name}</strong>
</strong>} )}
</td> </td>
<td style={{width: colOrganizations}}> <td style={{width: colOrganizations}}>
<Tags <Tags
@ -65,12 +65,8 @@ const AllUsersTableRow = ({
addMenuChoose={onAddToOrganization(user)} addMenuChoose={onAddToOrganization(user)}
/> />
</td> </td>
<td style={{width: colProvider}}> <td style={{width: colProvider}}>{user.provider}</td>
{user.provider} <td style={{width: colScheme}}>{user.scheme}</td>
</td>
<td style={{width: colScheme}}>
{user.scheme}
</td>
<td style={{width: colSuperAdmin}} className="text-center"> <td style={{width: colSuperAdmin}} className="text-center">
<SlideToggle <SlideToggle
active={user.superAdmin} active={user.superAdmin}

View File

@ -39,10 +39,9 @@ class OrganizationsTable extends Component {
} = this.props } = this.props
const {isCreatingOrganization} = this.state const {isCreatingOrganization} = this.state
const tableTitle = `${organizations.length} Organization${organizations.length === const tableTitle = `${organizations.length} Organization${
1 organizations.length === 1 ? '' : 's'
? '' }`
: 's'}`
if (!organizations.length) { if (!organizations.length) {
return ( return (
@ -56,9 +55,7 @@ class OrganizationsTable extends Component {
return ( return (
<div className="panel panel-solid"> <div className="panel panel-solid">
<div className="panel-heading"> <div className="panel-heading">
<h2 className="panel-title"> <h2 className="panel-title">{tableTitle}</h2>
{tableTitle}
</h2>
<button <button
className="btn btn-sm btn-primary" className="btn btn-sm btn-primary"
onClick={this.handleClickCreateOrganization} onClick={this.handleClickCreateOrganization}
@ -76,13 +73,13 @@ class OrganizationsTable extends Component {
</div> </div>
<div className="fancytable--th orgs-table--delete" /> <div className="fancytable--th orgs-table--delete" />
</div> </div>
{isCreatingOrganization {isCreatingOrganization ? (
? <OrganizationsTableRowNew <OrganizationsTableRowNew
onCreateOrganization={this.handleCreateOrganization} onCreateOrganization={this.handleCreateOrganization}
onCancelCreateOrganization={this.handleCancelCreateOrganization} onCancelCreateOrganization={this.handleCancelCreateOrganization}
/> />
: null} ) : null}
{organizations.map(org => {organizations.map(org => (
<OrganizationsTableRow <OrganizationsTableRow
key={uuid.v4()} key={uuid.v4()}
organization={org} organization={org}
@ -91,7 +88,7 @@ class OrganizationsTable extends Component {
onChooseDefaultRole={onChooseDefaultRole} onChooseDefaultRole={onChooseDefaultRole}
currentOrganization={currentOrganization} currentOrganization={currentOrganization}
/> />
)} ))}
</div> </div>
</div> </div>
) )

View File

@ -14,19 +14,21 @@ import {DEFAULT_ORG_ID} from 'src/admin/constants/chronografAdmin'
import {USER_ROLES} from 'src/admin/constants/chronografAdmin' import {USER_ROLES} from 'src/admin/constants/chronografAdmin'
const OrganizationsTableRowDeleteButton = ({organization, onClickDelete}) => const OrganizationsTableRowDeleteButton = ({organization, onClickDelete}) =>
organization.id === DEFAULT_ORG_ID organization.id === DEFAULT_ORG_ID ? (
? <button <button
className="btn btn-sm btn-default btn-square orgs-table--delete" className="btn btn-sm btn-default btn-square orgs-table--delete"
disabled={true} disabled={true}
> >
<span className="icon trash" /> <span className="icon trash" />
</button> </button>
: <button ) : (
className="btn btn-sm btn-default btn-square" <button
onClick={onClickDelete} className="btn btn-sm btn-default btn-square"
> onClick={onClickDelete}
<span className="icon trash" /> >
</button> <span className="icon trash" />
</button>
)
class OrganizationsTableRow extends Component { class OrganizationsTableRow extends Component {
constructor(props) { constructor(props) {
@ -81,16 +83,18 @@ class OrganizationsTableRow extends Component {
return ( return (
<div className="fancytable--row"> <div className="fancytable--row">
<div className="fancytable--td orgs-table--active"> <div className="fancytable--td orgs-table--active">
{organization.id === currentOrganization.id {organization.id === currentOrganization.id ? (
? <button className="btn btn-sm btn-success"> <button className="btn btn-sm btn-success">
<span className="icon checkmark" /> Current <span className="icon checkmark" /> Current
</button> </button>
: <button ) : (
className="btn btn-sm btn-default" <button
onClick={this.handleChangeCurrentOrganization} className="btn btn-sm btn-default"
> onClick={this.handleChangeCurrentOrganization}
<span className="icon shuffle" /> Switch to >
</button>} <span className="icon shuffle" /> Switch to
</button>
)}
</div> </div>
<InputClickToEdit <InputClickToEdit
value={organization.name} value={organization.name}
@ -105,19 +109,21 @@ class OrganizationsTableRow extends Component {
className="dropdown-stretch" className="dropdown-stretch"
/> />
</div> </div>
{isDeleting {isDeleting ? (
? <ConfirmButtons <ConfirmButtons
item={organization} item={organization}
onCancel={this.handleDismissDeleteConfirmation} onCancel={this.handleDismissDeleteConfirmation}
onConfirm={this.handleDeleteOrg} onConfirm={this.handleDeleteOrg}
onClickOutside={this.handleDismissDeleteConfirmation} onClickOutside={this.handleDismissDeleteConfirmation}
confirmLeft={true} confirmLeft={true}
confirmTitle="Delete" confirmTitle="Delete"
/> />
: <OrganizationsTableRowDeleteButton ) : (
organization={organization} <OrganizationsTableRowDeleteButton
onClickDelete={this.handleDeleteClick} organization={organization}
/>} onClickDelete={this.handleDeleteClick}
/>
)}
</div> </div>
) )
} }

View File

@ -55,9 +55,7 @@ class ProvidersTable extends Component {
return ( return (
<div className="panel panel-solid"> <div className="panel panel-solid">
<div className="panel-heading"> <div className="panel-heading">
<h2 className="panel-title"> <h2 className="panel-title">{tableTitle}</h2>
{tableTitle}
</h2>
<button <button
className="btn btn-sm btn-primary" className="btn btn-sm btn-primary"
onClick={this.handleClickCreateMap} onClick={this.handleClickCreateMap}
@ -66,58 +64,58 @@ class ProvidersTable extends Component {
<span className="icon plus" /> Create Mapping <span className="icon plus" /> Create Mapping
</button> </button>
</div> </div>
{mappings.length || isCreatingMap {mappings.length || isCreatingMap ? (
? <div className="panel-body"> <div className="panel-body">
<div className="fancytable--labels"> <div className="fancytable--labels">
<div className="fancytable--th provider--scheme">Scheme</div> <div className="fancytable--th provider--scheme">Scheme</div>
<div className="fancytable--th provider--provider"> <div className="fancytable--th provider--provider">Provider</div>
Provider <div className="fancytable--th provider--providerorg">
</div> Provider Org
<div className="fancytable--th provider--providerorg">
Provider Org
</div>
<div className="fancytable--th provider--arrow" />
<div className="fancytable--th provider--redirect">
Organization
</div>
<div className="fancytable--th provider--delete" />
</div> </div>
{mappings.map((mapping, i) => <div className="fancytable--th provider--arrow" />
<ProvidersTableRow <div className="fancytable--th provider--redirect">
key={uuid.v4()} Organization
mapping={mapping} </div>
organizations={organizations} <div className="fancytable--th provider--delete" />
schemes={SCHEMES}
onDelete={onDeleteMap}
onUpdate={onUpdateMap}
rowIndex={i + 1}
/>
)}
{isCreatingMap
? <ProvidersTableRowNew
organizations={organizations}
schemes={SCHEMES}
onCreate={this.handleCreateMap}
onCancel={this.handleCancelCreateMap}
rowIndex={mappings.length + 1}
/>
: null}
</div> </div>
: <div className="panel-body"> {mappings.map((mapping, i) => (
<div className="generic-empty-state"> <ProvidersTableRow
<h4 style={{margin: '50px 0'}}> key={uuid.v4()}
Looks like you have no mappings<br /> mapping={mapping}
New users will not be able to sign up automatically organizations={organizations}
</h4> schemes={SCHEMES}
<button onDelete={onDeleteMap}
className="btn btn-sm btn-primary" onUpdate={onUpdateMap}
onClick={this.handleClickCreateMap} rowIndex={i + 1}
disabled={isCreatingMap} />
> ))}
<span className="icon plus" /> Create Mapping {isCreatingMap ? (
</button> <ProvidersTableRowNew
</div> organizations={organizations}
</div>} schemes={SCHEMES}
onCreate={this.handleCreateMap}
onCancel={this.handleCancelCreateMap}
rowIndex={mappings.length + 1}
/>
) : null}
</div>
) : (
<div className="panel-body">
<div className="generic-empty-state">
<h4 style={{margin: '50px 0'}}>
Looks like you have no mappings<br />
New users will not be able to sign up automatically
</h4>
<button
className="btn btn-sm btn-primary"
onClick={this.handleClickCreateMap}
disabled={isCreatingMap}
>
<span className="icon plus" /> Create Mapping
</button>
</div>
</div>
)}
</div> </div>
) )
} }

View File

@ -106,20 +106,22 @@ class ProvidersTableRow extends Component {
disabled={isDefaultMapping} disabled={isDefaultMapping}
/> />
</div> </div>
{isDeleting {isDeleting ? (
? <ConfirmButtons <ConfirmButtons
item={mapping} item={mapping}
onCancel={this.handleDismissDeleteConfirmation} onCancel={this.handleDismissDeleteConfirmation}
onConfirm={this.handleDeleteMap} onConfirm={this.handleDeleteMap}
onClickOutside={this.handleDismissDeleteConfirmation} onClickOutside={this.handleDismissDeleteConfirmation}
confirmTitle="Delete" confirmTitle="Delete"
/> />
: <button ) : (
className="btn btn-sm btn-default btn-square" <button
onClick={this.handleDeleteClick} className="btn btn-sm btn-default btn-square"
> onClick={this.handleDeleteClick}
<span className="icon trash" /> >
</button>} <span className="icon trash" />
</button>
)}
</div> </div>
) )
} }

View File

@ -71,29 +71,31 @@ class UsersTable extends Component {
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
{isCreatingUser {isCreatingUser ? (
? <UsersTableRowNew <UsersTableRowNew
organization={organization}
onBlur={this.handleBlurCreateUserRow}
onCreateUser={onCreateUser}
/>
) : null}
{users.length ? (
users.map(user => (
<UsersTableRow
user={user}
key={uuid.v4()}
organization={organization} organization={organization}
onBlur={this.handleBlurCreateUserRow} onChangeUserRole={this.handleChangeUserRole}
onCreateUser={onCreateUser} onDelete={this.handleDeleteUser}
meID={meID}
/> />
: null} ))
{users.length ) : (
? users.map(user => <tr className="table-empty-state">
<UsersTableRow <th colSpan="5">
user={user} <p>No Users to display</p>
key={uuid.v4()} </th>
organization={organization} </tr>
onChangeUserRole={this.handleChangeUserRole} )}
onDelete={this.handleDeleteUser}
meID={meID}
/>
)
: <tr className="table-empty-state">
<th colSpan="5">
<p>No Users to display</p>
</th>
</tr>}
</tbody> </tbody>
</table> </table>
</div> </div>

View File

@ -29,14 +29,14 @@ const UsersTableRow = ({
return ( return (
<tr className={'chronograf-admin-table--user'}> <tr className={'chronograf-admin-table--user'}>
<td> <td>
{userIsMe {userIsMe ? (
? <strong className="chronograf-user--me"> <strong className="chronograf-user--me">
<span className="icon user" /> <span className="icon user" />
{user.name} {user.name}
</strong> </strong>
: <strong> ) : (
{user.name} <strong>{user.name}</strong>
</strong>} )}
</td> </td>
<td style={{width: colRole}}> <td style={{width: colRole}}>
<span className="chronograf-user--role"> <span className="chronograf-user--role">
@ -50,12 +50,8 @@ const UsersTableRow = ({
/> />
</span> </span>
</td> </td>
<td style={{width: colProvider}}> <td style={{width: colProvider}}>{user.provider}</td>
{user.provider} <td style={{width: colScheme}}>{user.scheme}</td>
</td>
<td style={{width: colScheme}}>
{user.scheme}
</td>
<DeleteConfirmTableCell <DeleteConfirmTableCell
text="Remove" text="Remove"
onDelete={onDelete} onDelete={onDelete}

View File

@ -165,37 +165,39 @@ class AdminInfluxDBPage extends Component {
</div> </div>
</div> </div>
<FancyScrollbar className="page-contents"> <FancyScrollbar className="page-contents">
{users {users ? (
? <div className="container-fluid"> <div className="container-fluid">
<div className="row"> <div className="row">
<AdminTabs <AdminTabs
users={users} users={users}
roles={roles} roles={roles}
source={source} source={source}
hasRoles={hasRoles} hasRoles={hasRoles}
permissions={allowed} permissions={allowed}
onFilterUsers={filterUsers} onFilterUsers={filterUsers}
onFilterRoles={filterRoles} onFilterRoles={filterRoles}
onEditUser={this.handleEditUser} onEditUser={this.handleEditUser}
onEditRole={this.handleEditRole} onEditRole={this.handleEditRole}
onSaveUser={this.handleSaveUser} onSaveUser={this.handleSaveUser}
onSaveRole={this.handleSaveRole} onSaveRole={this.handleSaveRole}
onDeleteUser={this.handleDeleteUser} onDeleteUser={this.handleDeleteUser}
onDeleteRole={this.handleDeleteRole} onDeleteRole={this.handleDeleteRole}
onClickCreate={this.handleClickCreate} onClickCreate={this.handleClickCreate}
onCancelEditUser={this.handleCancelEditUser} onCancelEditUser={this.handleCancelEditUser}
onCancelEditRole={this.handleCancelEditRole} onCancelEditRole={this.handleCancelEditRole}
isEditingUsers={users.some(u => u.isEditing)} isEditingUsers={users.some(u => u.isEditing)}
isEditingRoles={roles.some(r => r.isEditing)} isEditingRoles={roles.some(r => r.isEditing)}
onUpdateRoleUsers={this.handleUpdateRoleUsers} onUpdateRoleUsers={this.handleUpdateRoleUsers}
onUpdateUserRoles={this.handleUpdateUserRoles} onUpdateUserRoles={this.handleUpdateUserRoles}
onUpdateUserPassword={this.handleUpdateUserPassword} onUpdateUserPassword={this.handleUpdateUserPassword}
onUpdateRolePermissions={this.handleUpdateRolePermissions} onUpdateRolePermissions={this.handleUpdateRolePermissions}
onUpdateUserPermissions={this.handleUpdateUserPermissions} onUpdateUserPermissions={this.handleUpdateUserPermissions}
/> />
</div>
</div> </div>
: <div className="page-spinner" />} </div>
) : (
<div className="page-spinner" />
)}
</FancyScrollbar> </FancyScrollbar>
</div> </div>
) )

View File

@ -5,7 +5,7 @@ import {connect} from 'react-redux'
import AdminTabs from 'src/admin/components/chronograf/AdminTabs' import AdminTabs from 'src/admin/components/chronograf/AdminTabs'
import FancyScrollbar from 'shared/components/FancyScrollbar' import FancyScrollbar from 'shared/components/FancyScrollbar'
const AdminChronografPage = ({me}) => const AdminChronografPage = ({me}) => (
<div className="page"> <div className="page">
<div className="page-header"> <div className="page-header">
<div className="page-header__container"> <div className="page-header__container">
@ -22,6 +22,7 @@ const AdminChronografPage = ({me}) =>
</div> </div>
</FancyScrollbar> </FancyScrollbar>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -3,8 +3,10 @@ import {proxy} from 'utils/queryUrlGenerator'
export const getAlerts = (source, timeRange, limit) => export const getAlerts = (source, timeRange, limit) =>
proxy({ proxy({
source, source,
query: `SELECT host, value, level, alertName FROM alerts WHERE time >= '${timeRange.lower}' AND time <= '${timeRange.upper}' ORDER BY time desc ${limit query: `SELECT host, value, level, alertName FROM alerts WHERE time >= '${
? `LIMIT ${limit}` timeRange.lower
: ''}`, }' AND time <= '${timeRange.upper}' ORDER BY time desc ${
limit ? `LIMIT ${limit}` : ''
}`,
db: 'chronograf', db: 'chronograf',
}) })

View File

@ -79,121 +79,125 @@ class AlertsTable extends Component {
this.state.sortDirection this.state.sortDirection
) )
const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
return this.props.alerts.length return this.props.alerts.length ? (
? <div className="alert-history-table"> <div className="alert-history-table">
<div className="alert-history-table--thead"> <div className="alert-history-table--thead">
<div <div
onClick={this.changeSort('name')} onClick={this.changeSort('name')}
className={this.sortableClasses('name')} className={this.sortableClasses('name')}
style={{width: colName}} style={{width: colName}}
> >
Name Name
</div> </div>
<div <div
onClick={this.changeSort('level')} onClick={this.changeSort('level')}
className={this.sortableClasses('level')} className={this.sortableClasses('level')}
style={{width: colLevel}} style={{width: colLevel}}
> >
Level Level
</div> </div>
<div <div
onClick={this.changeSort('time')} onClick={this.changeSort('time')}
className={this.sortableClasses('time')} className={this.sortableClasses('time')}
style={{width: colTime}} style={{width: colTime}}
> >
Time Time
</div> </div>
<div <div
onClick={this.changeSort('host')} onClick={this.changeSort('host')}
className={this.sortableClasses('host')} className={this.sortableClasses('host')}
style={{width: colHost}} style={{width: colHost}}
> >
Host Host
</div> </div>
<div <div
onClick={this.changeSort('value')} onClick={this.changeSort('value')}
className={this.sortableClasses('value')} className={this.sortableClasses('value')}
style={{width: colValue}} style={{width: colValue}}
> >
Value Value
</div>
</div> </div>
<InfiniteScroll
className="alert-history-table--tbody"
itemHeight={25}
items={alerts.map(({name, level, time, host, value}) => {
return (
<div className="alert-history-table--tr" key={uuid.v4()}>
<div
className="alert-history-table--td"
style={{width: colName}}
>
{name}
</div>
<div
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
style={{width: colLevel}}
>
<span
className={classnames(
'table-dot',
{'dot-critical': level === 'CRITICAL'},
{'dot-success': level === 'OK'}
)}
/>
</div>
<div
className="alert-history-table--td"
style={{width: colTime}}
>
{new Date(Number(time)).toISOString()}
</div>
<div
className="alert-history-table--td alert-history-table--host"
style={{width: colHost}}
>
<Link to={`/sources/${id}/hosts/${host}`} title={host}>
{host}
</Link>
</div>
<div
className="alert-history-table--td"
style={{width: colValue}}
>
{value}
</div>
</div>
)
})}
/>
</div> </div>
: this.renderTableEmpty() <InfiniteScroll
className="alert-history-table--tbody"
itemHeight={25}
items={alerts.map(({name, level, time, host, value}) => {
return (
<div className="alert-history-table--tr" key={uuid.v4()}>
<div
className="alert-history-table--td"
style={{width: colName}}
>
{name}
</div>
<div
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
style={{width: colLevel}}
>
<span
className={classnames(
'table-dot',
{'dot-critical': level === 'CRITICAL'},
{'dot-success': level === 'OK'}
)}
/>
</div>
<div
className="alert-history-table--td"
style={{width: colTime}}
>
{new Date(Number(time)).toISOString()}
</div>
<div
className="alert-history-table--td alert-history-table--host"
style={{width: colHost}}
>
<Link to={`/sources/${id}/hosts/${host}`} title={host}>
{host}
</Link>
</div>
<div
className="alert-history-table--td"
style={{width: colValue}}
>
{value}
</div>
</div>
)
})}
/>
</div>
) : (
this.renderTableEmpty()
)
} }
renderTableEmpty() { renderTableEmpty() {
const {source: {id}, shouldNotBeFilterable} = this.props const {source: {id}, shouldNotBeFilterable} = this.props
return shouldNotBeFilterable return shouldNotBeFilterable ? (
? <div className="graph-empty"> <div className="graph-empty">
<p> <p>
Learn how to configure your first <strong>Rule</strong> in<br /> Learn how to configure your first <strong>Rule</strong> in<br />
the <em>Getting Started</em> guide the <em>Getting Started</em> guide
</p> </p>
</div> </div>
: <div className="generic-empty-state"> ) : (
<h4 className="no-user-select">There are no Alerts to display</h4> <div className="generic-empty-state">
<br /> <h4 className="no-user-select">There are no Alerts to display</h4>
<h6 className="no-user-select"> <br />
Try changing the Time Range or <h6 className="no-user-select">
<Link Try changing the Time Range or
style={{marginLeft: '10px'}} <Link
to={`/sources/${id}/alert-rules/new`} style={{marginLeft: '10px'}}
className="btn btn-primary btn-sm" to={`/sources/${id}/alert-rules/new`}
> className="btn btn-primary btn-sm"
Create an Alert Rule >
</Link> Create an Alert Rule
</h6> </Link>
</div> </h6>
</div>
)
} }
render() { render() {
@ -205,35 +209,33 @@ class AlertsTable extends Component {
alertsCount, alertsCount,
} = this.props } = this.props
return shouldNotBeFilterable return shouldNotBeFilterable ? (
? <div className="alerts-widget"> <div className="alerts-widget">
{this.renderTable()} {this.renderTable()}
{limit && alertsCount {limit && alertsCount ? (
? <button <button
className="btn btn-sm btn-default btn-block" className="btn btn-sm btn-default btn-block"
onClick={onGetMoreAlerts} onClick={onGetMoreAlerts}
disabled={isAlertsMaxedOut} disabled={isAlertsMaxedOut}
style={{marginBottom: '20px'}} style={{marginBottom: '20px'}}
> >
{isAlertsMaxedOut {isAlertsMaxedOut
? `All ${alertsCount} Alerts displayed` ? `All ${alertsCount} Alerts displayed`
: 'Load next 30 Alerts'} : 'Load next 30 Alerts'}
</button> </button>
: null} ) : null}
</div> </div>
: <div className="panel"> ) : (
<div className="panel-heading"> <div className="panel">
<h2 className="panel-title"> <div className="panel-heading">
{this.props.alerts.length} Alerts <h2 className="panel-title">{this.props.alerts.length} Alerts</h2>
</h2> {this.props.alerts.length ? (
{this.props.alerts.length <SearchBar onSearch={this.filterAlerts} />
? <SearchBar onSearch={this.filterAlerts} /> ) : null}
: null}
</div>
<div className="panel-body">
{this.renderTable()}
</div>
</div> </div>
<div className="panel-body">{this.renderTable()}</div>
</div>
)
} }
} }

View File

@ -30,7 +30,9 @@ class AlertsApp extends Component {
alerts: [], alerts: [],
timeRange: { timeRange: {
upper: moment().format(), upper: moment().format(),
lower: moment().subtract(lowerInSec || oneDayInSec, 'seconds').format(), lower: moment()
.subtract(lowerInSec || oneDayInSec, 'seconds')
.format(),
}, },
limit: props.limit || 0, // only used if AlertsApp receives a limit prop limit: props.limit || 0, // only used if AlertsApp receives a limit prop
limitMultiplier: 1, // only used if AlertsApp receives a limit prop limitMultiplier: 1, // only used if AlertsApp receives a limit prop
@ -118,17 +120,19 @@ class AlertsApp extends Component {
const {source, isWidget, limit} = this.props const {source, isWidget, limit} = this.props
const {isAlertsMaxedOut, alerts} = this.state const {isAlertsMaxedOut, alerts} = this.state
return this.state.hasKapacitor return this.state.hasKapacitor ? (
? <AlertsTable <AlertsTable
source={source} source={source}
alerts={this.state.alerts} alerts={this.state.alerts}
shouldNotBeFilterable={isWidget} shouldNotBeFilterable={isWidget}
limit={limit} limit={limit}
onGetMoreAlerts={this.handleGetMoreAlerts} onGetMoreAlerts={this.handleGetMoreAlerts}
isAlertsMaxedOut={isAlertsMaxedOut} isAlertsMaxedOut={isAlertsMaxedOut}
alertsCount={alerts.length} alertsCount={alerts.length}
/> />
: <NoKapacitorError source={source} /> ) : (
<NoKapacitorError source={source} />
)
} }
handleApplyTime = timeRange => { handleApplyTime = timeRange => {
@ -143,33 +147,33 @@ class AlertsApp extends Component {
return <div className="page-spinner" /> return <div className="page-spinner" />
} }
return isWidget return isWidget ? (
? this.renderSubComponents() this.renderSubComponents()
: <div className="page alert-history-page"> ) : (
<div className="page-header"> <div className="page alert-history-page">
<div className="page-header__container"> <div className="page-header">
<div className="page-header__left"> <div className="page-header__container">
<h1 className="page-header__title">Alert History</h1> <div className="page-header__left">
</div> <h1 className="page-header__title">Alert History</h1>
<div className="page-header__right">
<SourceIndicator />
<CustomTimeRangeDropdown
onApplyTimeRange={this.handleApplyTime}
timeRange={timeRange}
/>
</div>
</div> </div>
</div> <div className="page-header__right">
<div className="page-contents"> <SourceIndicator />
<div className="container-fluid"> <CustomTimeRangeDropdown
<div className="row"> onApplyTimeRange={this.handleApplyTime}
<div className="col-md-12"> timeRange={timeRange}
{this.renderSubComponents()} />
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
<div className="page-contents">
<div className="container-fluid">
<div className="row">
<div className="col-md-12">{this.renderSubComponents()}</div>
</div>
</div>
</div>
</div>
)
} }
} }

View File

@ -20,12 +20,12 @@ const Login = ({authData: {auth}}) => {
<strong>{VERSION}</strong> / Time-Series Data Visualization <strong>{VERSION}</strong> / Time-Series Data Visualization
</p> </p>
{auth.links && {auth.links &&
auth.links.map(({name, login, label}) => auth.links.map(({name, login, label}) => (
<a key={name} className="btn btn-primary" href={login}> <a key={name} className="btn btn-primary" href={login}>
<span className={`icon ${name}`} /> <span className={`icon ${name}`} />
Log in with {label} Log in with {label}
</a> </a>
)} ))}
</SplashPage> </SplashPage>
</div> </div>
) )

View File

@ -65,31 +65,31 @@ class Purgatory extends Component {
<Notifications /> <Notifications />
<SplashPage> <SplashPage>
<div className="auth--purgatory"> <div className="auth--purgatory">
<h3> <h3>{name}</h3>
{name}
</h3>
<h6> <h6>
{subHeading}{' '} {subHeading}{' '}
<code> <code>
{scheme}/{provider} {scheme}/{provider}
</code> </code>
</h6> </h6>
{rolesAndOrgs.length {rolesAndOrgs.length ? (
? <div className="auth--list"> <div className="auth--list">
{rolesAndOrgs.map((rag, i) => {rolesAndOrgs.map((rag, i) => (
<PurgatoryAuthItem <PurgatoryAuthItem
key={i} key={i}
roleAndOrg={rag} roleAndOrg={rag}
superAdmin={superAdmin} superAdmin={superAdmin}
onClickLogin={handleClickLogin({ onClickLogin={handleClickLogin({
router, router,
links, links,
meChangeOrganization, meChangeOrganization,
})} })}
/> />
)} ))}
</div> </div>
: <p>You are a Lost Soul</p>} ) : (
<p>You are a Lost Soul</p>
)}
<a href={logoutLink} className="btn btn-sm btn-link auth--logout"> <a href={logoutLink} className="btn btn-sm btn-link auth--logout">
Log out Log out
</a> </a>

View File

@ -3,7 +3,7 @@ import PropTypes from 'prop-types'
import {isUserAuthorized, VIEWER_ROLE} from 'src/auth/Authorized' import {isUserAuthorized, VIEWER_ROLE} from 'src/auth/Authorized'
const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) => const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) => (
<div <div
className={ className={
roleAndOrg.currentOrganization roleAndOrg.currentOrganization
@ -12,24 +12,23 @@ const PurgatoryAuthItem = ({roleAndOrg, onClickLogin, superAdmin}) =>
} }
> >
<div className="auth--list-info"> <div className="auth--list-info">
<div className="auth--list-org"> <div className="auth--list-org">{roleAndOrg.organization.name}</div>
{roleAndOrg.organization.name} <div className="auth--list-role">{roleAndOrg.role}</div>
</div>
<div className="auth--list-role">
{roleAndOrg.role}
</div>
</div> </div>
{superAdmin || isUserAuthorized(roleAndOrg.role, VIEWER_ROLE) {superAdmin || isUserAuthorized(roleAndOrg.role, VIEWER_ROLE) ? (
? <button <button
className="btn btn-sm btn-primary" className="btn btn-sm btn-primary"
onClick={onClickLogin(roleAndOrg.organization)} onClick={onClickLogin(roleAndOrg.organization)}
> >
Log in Log in
</button> </button>
: <span className="auth--list-blocked"> ) : (
Contact your Admin<br />for access <span className="auth--list-blocked">
</span>} Contact your Admin<br />for access
</span>
)}
</div> </div>
)
const {bool, func, shape, string} = PropTypes const {bool, func, shape, string} = PropTypes

View File

@ -91,9 +91,7 @@ class AxesOptions extends Component {
autoHide={false} autoHide={false}
> >
<div className="display-options--cell-wrapper"> <div className="display-options--cell-wrapper">
<h5 className="display-options--header"> <h5 className="display-options--header">{menuOption} Controls</h5>
{menuOption} Controls
</h5>
<form autoComplete="off" className="form-group-wrapper"> <form autoComplete="off" className="form-group-wrapper">
<div className="form-group col-sm-12"> <div className="form-group col-sm-12">
<label htmlFor="prefix">Title</label> <label htmlFor="prefix">Title</label>

View File

@ -318,27 +318,29 @@ class CellEditorOverlay extends Component {
isDisplayOptionsTabActive={isDisplayOptionsTabActive} isDisplayOptionsTabActive={isDisplayOptionsTabActive}
onClickDisplayOptions={this.handleClickDisplayOptionsTab} onClickDisplayOptions={this.handleClickDisplayOptionsTab}
/> />
{isDisplayOptionsTabActive {isDisplayOptionsTabActive ? (
? <DisplayOptions <DisplayOptions
queryConfigs={queriesWorkingDraft} queryConfigs={queriesWorkingDraft}
onToggleStaticLegend={this.handleToggleStaticLegend} onToggleStaticLegend={this.handleToggleStaticLegend}
staticLegend={staticLegend} staticLegend={staticLegend}
onResetFocus={this.handleResetFocus} onResetFocus={this.handleResetFocus}
/> />
: <QueryMaker ) : (
source={this.getSource()} <QueryMaker
templates={templates} source={this.getSource()}
queries={queriesWorkingDraft} templates={templates}
actions={queryActions} queries={queriesWorkingDraft}
autoRefresh={autoRefresh} actions={queryActions}
timeRange={timeRange} autoRefresh={autoRefresh}
onDeleteQuery={this.handleDeleteQuery} timeRange={timeRange}
onAddQuery={this.handleAddQuery} onDeleteQuery={this.handleDeleteQuery}
activeQueryIndex={activeQueryIndex} onAddQuery={this.handleAddQuery}
activeQuery={this.getActiveQuery()} activeQueryIndex={activeQueryIndex}
setActiveQueryIndex={this.handleSetActiveQueryIndex} activeQuery={this.getActiveQuery()}
initialGroupByTime={AUTO_GROUP_BY} setActiveQueryIndex={this.handleSetActiveQueryIndex}
/>} initialGroupByTime={AUTO_GROUP_BY}
/>
)}
</CEOBottom> </CEOBottom>
</ResizeContainer> </ResizeContainer>
</div> </div>
@ -346,10 +348,9 @@ class CellEditorOverlay extends Component {
} }
} }
const CEOBottom = ({children}) => const CEOBottom = ({children}) => (
<div className="overlay-technology--editor"> <div className="overlay-technology--editor">{children}</div>
{children} )
</div>
const {arrayOf, func, node, number, shape, string} = PropTypes const {arrayOf, func, node, number, shape, string} = PropTypes

View File

@ -49,37 +49,39 @@ const Dashboard = ({
setScrollTop={setScrollTop} setScrollTop={setScrollTop}
> >
<div className="dashboard container-fluid full-width"> <div className="dashboard container-fluid full-width">
{inPresentationMode {inPresentationMode ? null : (
? null <TemplateControlBar
: <TemplateControlBar templates={dashboard.templates}
templates={dashboard.templates} onSelectTemplate={onSelectTemplate}
onSelectTemplate={onSelectTemplate} onOpenTemplateManager={onOpenTemplateManager}
onOpenTemplateManager={onOpenTemplateManager} isOpen={showTemplateControlBar}
isOpen={showTemplateControlBar} />
/>} )}
{cells.length {cells.length ? (
? <LayoutRenderer <LayoutRenderer
cells={cells} cells={cells}
onZoom={onZoom} onZoom={onZoom}
source={source} source={source}
sources={sources} sources={sources}
isEditable={true} isEditable={true}
timeRange={timeRange} timeRange={timeRange}
autoRefresh={autoRefresh} autoRefresh={autoRefresh}
manualRefresh={manualRefresh} manualRefresh={manualRefresh}
hoverTime={hoverTime} hoverTime={hoverTime}
onSetHoverTime={onSetHoverTime} onSetHoverTime={onSetHoverTime}
onDeleteCell={onDeleteCell} onDeleteCell={onDeleteCell}
onPositionChange={onPositionChange} onPositionChange={onPositionChange}
templates={templatesIncludingDashTime} templates={templatesIncludingDashTime}
onSummonOverlayTechnologies={onSummonOverlayTechnologies} onSummonOverlayTechnologies={onSummonOverlayTechnologies}
/> />
: <div className="dashboard__empty"> ) : (
<p>This Dashboard has no Cells</p> <div className="dashboard__empty">
<button className="btn btn-primary btn-m" onClick={onAddCell}> <p>This Dashboard has no Cells</p>
<span className="icon plus" />Add a Cell <button className="btn btn-primary btn-m" onClick={onAddCell}>
</button> <span className="icon plus" />Add a Cell
</div>} </button>
</div>
)}
</div> </div>
</FancyScrollbar> </FancyScrollbar>
) )

View File

@ -31,90 +31,85 @@ const DashboardHeader = ({
handleClickPresentationButton, handleClickPresentationButton,
zoomedTimeRange: {zoomedLower, zoomedUpper}, zoomedTimeRange: {zoomedLower, zoomedUpper},
}) => }) =>
isHidden isHidden ? null : (
? null <div className="page-header full-width">
: <div className="page-header full-width"> <div className="page-header__container">
<div className="page-header__container"> <div
<div className={
className={ dashboard
dashboard ? 'page-header__left page-header__dash-editable'
? 'page-header__left page-header__dash-editable' : 'page-header__left'
: 'page-header__left' }
} >
> {names && names.length > 1 ? (
{names && names.length > 1 <DashboardSwitcher
? <DashboardSwitcher names={names}
names={names} activeDashboard={activeDashboard}
activeDashboard={activeDashboard}
/>
: null}
{dashboard
? <Authorized
requiredRole={EDITOR_ROLE}
replaceWithIfNotAuthorized={
<h1 className="page-header__title">
{activeDashboard}
</h1>
}
>
<DashboardHeaderEdit
onSave={onSave}
onCancel={onCancel}
activeDashboard={activeDashboard}
onEditDashboard={onEditDashboard}
isEditMode={isEditMode}
/>
</Authorized>
: <h1 className="page-header__title">
{activeDashboard}
</h1>}
</div>
<div className="page-header__right">
<GraphTips />
<SourceIndicator />
{dashboard
? <Authorized requiredRole={EDITOR_ROLE}>
<button
className="btn btn-primary btn-sm"
onClick={onAddCell}
>
<span className="icon plus" />
Add Cell
</button>
</Authorized>
: null}
{dashboard
? <div
className={classnames('btn btn-default btn-sm', {
active: showTemplateControlBar,
})}
onClick={onToggleTempVarControls}
>
<span className="icon cube" />Template Variables
</div>
: null}
<AutoRefreshDropdown
onChoose={handleChooseAutoRefresh}
onManualRefresh={onManualRefresh}
selected={autoRefresh}
iconName="refresh"
/> />
<TimeRangeDropdown ) : null}
onChooseTimeRange={handleChooseTimeRange} {dashboard ? (
selected={{ <Authorized
upper: zoomedUpper || upper, requiredRole={EDITOR_ROLE}
lower: zoomedLower || lower, replaceWithIfNotAuthorized={
}} <h1 className="page-header__title">{activeDashboard}</h1>
/> }
<div
className="btn btn-default btn-sm btn-square"
onClick={handleClickPresentationButton}
> >
<span className="icon expand-a" /> <DashboardHeaderEdit
onSave={onSave}
onCancel={onCancel}
activeDashboard={activeDashboard}
onEditDashboard={onEditDashboard}
isEditMode={isEditMode}
/>
</Authorized>
) : (
<h1 className="page-header__title">{activeDashboard}</h1>
)}
</div>
<div className="page-header__right">
<GraphTips />
<SourceIndicator />
{dashboard ? (
<Authorized requiredRole={EDITOR_ROLE}>
<button className="btn btn-primary btn-sm" onClick={onAddCell}>
<span className="icon plus" />
Add Cell
</button>
</Authorized>
) : null}
{dashboard ? (
<div
className={classnames('btn btn-default btn-sm', {
active: showTemplateControlBar,
})}
onClick={onToggleTempVarControls}
>
<span className="icon cube" />Template Variables
</div> </div>
) : null}
<AutoRefreshDropdown
onChoose={handleChooseAutoRefresh}
onManualRefresh={onManualRefresh}
selected={autoRefresh}
iconName="refresh"
/>
<TimeRangeDropdown
onChooseTimeRange={handleChooseTimeRange}
selected={{
upper: zoomedUpper || upper,
lower: zoomedLower || lower,
}}
/>
<div
className="btn btn-default btn-sm btn-square"
onClick={handleClickPresentationButton}
>
<span className="icon expand-a" />
</div> </div>
</div> </div>
</div> </div>
</div>
)
const {arrayOf, bool, func, number, shape, string} = PropTypes const {arrayOf, bool, func, number, shape, string} = PropTypes

View File

@ -46,24 +46,24 @@ class DashboardEditHeader extends Component {
return ( return (
<div className="dashboard-title"> <div className="dashboard-title">
{isEditMode {isEditMode ? (
? <input <input
maxLength={DASHBOARD_NAME_MAX_LENGTH} maxLength={DASHBOARD_NAME_MAX_LENGTH}
type="text" type="text"
className="dashboard-title--input form-control input-sm" className="dashboard-title--input form-control input-sm"
defaultValue={activeDashboard} defaultValue={activeDashboard}
autoComplete="off" autoComplete="off"
autoFocus={true} autoFocus={true}
spellCheck={false} spellCheck={false}
onBlur={this.handleInputBlur} onBlur={this.handleInputBlur}
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
onFocus={this.handleFocus} onFocus={this.handleFocus}
placeholder="Name this Dashboard" placeholder="Name this Dashboard"
ref={r => (this.inputRef = r)} ref={r => (this.inputRef = r)}
/> />
: <h1 onClick={onEditDashboard}> ) : (
{activeDashboard} <h1 onClick={onEditDashboard}>{activeDashboard}</h1>
</h1>} )}
</div> </div>
) )
} }

View File

@ -42,7 +42,7 @@ class DashboardSwitcher extends Component {
<span className="icon dash-f" /> <span className="icon dash-f" />
</button> </button>
<ul className="dropdown-menu"> <ul className="dropdown-menu">
{sorted.map(({name, link}) => {sorted.map(({name, link}) => (
<NameLink <NameLink
key={link} key={link}
name={name} name={name}
@ -50,14 +50,14 @@ class DashboardSwitcher extends Component {
activeName={activeDashboard} activeName={activeDashboard}
onClose={this.handleCloseMenu} onClose={this.handleCloseMenu}
/> />
)} ))}
</ul> </ul>
</div> </div>
) )
} }
} }
const NameLink = ({name, link, activeName, onClose}) => const NameLink = ({name, link, activeName, onClose}) => (
<li <li
className={classnames('dropdown-item', { className={classnames('dropdown-item', {
active: name === activeName, active: name === activeName,
@ -67,6 +67,7 @@ const NameLink = ({name, link, activeName, onClose}) =>
{name} {name}
</Link> </Link>
</li> </li>
)
const {arrayOf, func, shape, string} = PropTypes const {arrayOf, func, shape, string} = PropTypes

View File

@ -2,7 +2,7 @@ import React from 'react'
import SourceIndicator from 'shared/components/SourceIndicator' import SourceIndicator from 'shared/components/SourceIndicator'
const DashboardsHeader = () => const DashboardsHeader = () => (
<div className="page-header"> <div className="page-header">
<div className="page-header__container"> <div className="page-header__container">
<div className="page-header__left"> <div className="page-header__left">
@ -13,5 +13,6 @@ const DashboardsHeader = () =>
</div> </div>
</div> </div>
</div> </div>
)
export default DashboardsHeader export default DashboardsHeader

View File

@ -48,9 +48,7 @@ class DashboardsPageContents extends Component {
<div className="col-md-12"> <div className="col-md-12">
<div className="panel"> <div className="panel">
<div className="panel-heading"> <div className="panel-heading">
<h2 className="panel-title"> <h2 className="panel-title">{tableHeader}</h2>
{tableHeader}
</h2>
<div className="dashboards-page--actions"> <div className="dashboards-page--actions">
<SearchBar <SearchBar
placeholder="Filter by Name..." placeholder="Filter by Name..."

View File

@ -7,7 +7,7 @@ import Authorized, {EDITOR_ROLE} from 'src/auth/Authorized'
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell' import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
const AuthorizedEmptyState = ({onCreateDashboard}) => const AuthorizedEmptyState = ({onCreateDashboard}) => (
<div className="generic-empty-state"> <div className="generic-empty-state">
<h4 style={{marginTop: '90px'}}> <h4 style={{marginTop: '90px'}}>
Looks like you dont have any dashboards Looks like you dont have any dashboards
@ -21,6 +21,7 @@ const AuthorizedEmptyState = ({onCreateDashboard}) =>
<span className="icon plus" /> Create Dashboard <span className="icon plus" /> Create Dashboard
</button> </button>
</div> </div>
)
const unauthorizedEmptyState = ( const unauthorizedEmptyState = (
<div className="generic-empty-state"> <div className="generic-empty-state">
@ -34,52 +35,56 @@ const DashboardsTable = ({
onCreateDashboard, onCreateDashboard,
dashboardLink, dashboardLink,
}) => { }) => {
return dashboards && dashboards.length return dashboards && dashboards.length ? (
? <table className="table v-center admin-table table-highlight"> <table className="table v-center admin-table table-highlight">
<thead> <thead>
<tr> <tr>
<th>Name</th> <th>Name</th>
<th>Template Variables</th> <th>Template Variables</th>
<th /> <th />
</tr>
</thead>
<tbody>
{_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => (
<tr key={dashboard.id}>
<td>
<Link to={`${dashboardLink}/dashboards/${dashboard.id}`}>
{dashboard.name}
</Link>
</td>
<td>
{dashboard.templates.length ? (
dashboard.templates.map(tv => (
<code className="table--temp-var" key={tv.id}>
{tv.tempVar}
</code>
))
) : (
<span className="empty-string">None</span>
)}
</td>
<Authorized
requiredRole={EDITOR_ROLE}
replaceWithIfNotAuthorized={<td />}
>
<DeleteConfirmTableCell
onDelete={onDeleteDashboard}
item={dashboard}
buttonSize="btn-xs"
/>
</Authorized>
</tr> </tr>
</thead> ))}
<tbody> </tbody>
{_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => </table>
<tr key={dashboard.id}> ) : (
<td> <Authorized
<Link to={`${dashboardLink}/dashboards/${dashboard.id}`}> requiredRole={EDITOR_ROLE}
{dashboard.name} replaceWithIfNotAuthorized={unauthorizedEmptyState}
</Link> >
</td> <AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
<td> </Authorized>
{dashboard.templates.length )
? dashboard.templates.map(tv =>
<code className="table--temp-var" key={tv.id}>
{tv.tempVar}
</code>
)
: <span className="empty-string">None</span>}
</td>
<Authorized
requiredRole={EDITOR_ROLE}
replaceWithIfNotAuthorized={<td />}
>
<DeleteConfirmTableCell
onDelete={onDeleteDashboard}
item={dashboard}
buttonSize="btn-xs"
/>
</Authorized>
</tr>
)}
</tbody>
</table>
: <Authorized
requiredRole={EDITOR_ROLE}
replaceWithIfNotAuthorized={unauthorizedEmptyState}
>
<AuthorizedEmptyState onCreateDashboard={onCreateDashboard} />
</Authorized>
} }
const {arrayOf, func, shape, string} = PropTypes const {arrayOf, func, shape, string} = PropTypes

View File

@ -9,11 +9,9 @@ const DisplayOptionsInput = ({
labelText, labelText,
colWidth, colWidth,
placeholder, placeholder,
}) => }) => (
<div className={`form-group ${colWidth}`}> <div className={`form-group ${colWidth}`}>
<label htmlFor={name}> <label htmlFor={name}>{labelText}</label>
{labelText}
</label>
<input <input
className="form-control input-sm" className="form-control input-sm"
type="text" type="text"
@ -24,6 +22,7 @@ const DisplayOptionsInput = ({
placeholder={placeholder} placeholder={placeholder}
/> />
</div> </div>
)
const {func, string} = PropTypes const {func, string} = PropTypes

View File

@ -173,7 +173,7 @@ class GaugeOptions extends Component {
> >
<span className="icon plus" /> Add Threshold <span className="icon plus" /> Add Threshold
</button> </button>
{gaugeColors.map(color => {gaugeColors.map(color => (
<Threshold <Threshold
isMin={color.value === gaugeColors[0].value} isMin={color.value === gaugeColors[0].value}
isMax={ isMax={
@ -189,7 +189,7 @@ class GaugeOptions extends Component {
onDeleteThreshold={this.handleDeleteThreshold} onDeleteThreshold={this.handleDeleteThreshold}
onSortColors={this.handleSortColors} onSortColors={this.handleSortColors}
/> />
)} ))}
</div> </div>
<div className="graph-options-group form-group-wrapper"> <div className="graph-options-group form-group-wrapper">
<div className="form-group col-xs-6"> <div className="form-group col-xs-6">

View File

@ -16,25 +16,25 @@ const GraphOptionsTextWrapping = ({
<label>Text Wrapping</label> <label>Text Wrapping</label>
<ul className="nav nav-tablist nav-tablist-sm"> <ul className="nav nav-tablist nav-tablist-sm">
<li <li
className={`${thresholdsListType === THRESHOLD_TYPE_BG className={`${
? 'active' thresholdsListType === THRESHOLD_TYPE_BG ? 'active' : ''
: ''}`} }`}
onClick={onToggleTextWrapping} onClick={onToggleTextWrapping}
> >
Truncate Truncate
</li> </li>
<li <li
className={`${thresholdsListType === THRESHOLD_TYPE_TEXT className={`${
? 'active' thresholdsListType === THRESHOLD_TYPE_TEXT ? 'active' : ''
: ''}`} }`}
onClick={onToggleTextWrapping} onClick={onToggleTextWrapping}
> >
Wrap Wrap
</li> </li>
<li <li
className={`${thresholdsListType === THRESHOLD_TYPE_BG className={`${
? 'active' thresholdsListType === THRESHOLD_TYPE_BG ? 'active' : ''
: ''}`} }`}
onClick={onToggleTextWrapping} onClick={onToggleTextWrapping}
> >
Single Line Single Line

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) => const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) => (
<div className="form-group col-xs-12 col-sm-6"> <div className="form-group col-xs-12 col-sm-6">
<label>Time Axis</label> <label>Time Axis</label>
<ul className="nav nav-tablist nav-tablist-sm"> <ul className="nav nav-tablist nav-tablist-sm">
@ -19,6 +19,7 @@ const GraphOptionsTimeAxis = ({verticalTimeAxis, onToggleVerticalTimeAxis}) =>
</li> </li>
</ul> </ul>
</div> </div>
)
const {bool, func} = PropTypes const {bool, func} = PropTypes

View File

@ -23,7 +23,7 @@ const GraphTypeSelector = ({type, handleChangeCellType}) => {
<div className="display-options--cell-wrapper"> <div className="display-options--cell-wrapper">
<h5 className="display-options--header">Visualization Type</h5> <h5 className="display-options--header">Visualization Type</h5>
<div className="viz-type-selector"> <div className="viz-type-selector">
{GRAPH_TYPES.map(graphType => {GRAPH_TYPES.map(graphType => (
<div <div
key={graphType.type} key={graphType.type}
className={classnames('viz-type-selector--option', { className={classnames('viz-type-selector--option', {
@ -32,12 +32,10 @@ const GraphTypeSelector = ({type, handleChangeCellType}) => {
> >
<div onClick={onChangeCellType(graphType.type)}> <div onClick={onChangeCellType(graphType.type)}>
{graphType.graphic} {graphType.graphic}
<p> <p>{graphType.menuOption}</p>
{graphType.menuOption}
</p>
</div> </div>
</div> </div>
)} ))}
</div> </div>
</div> </div>
</FancyScrollbar> </FancyScrollbar>

View File

@ -15,7 +15,7 @@ const OverlayControls = ({
onSetQuerySource, onSetQuerySource,
isDisplayOptionsTabActive, isDisplayOptionsTabActive,
onClickDisplayOptions, onClickDisplayOptions,
}) => }) => (
<div className="overlay-controls"> <div className="overlay-controls">
<SourceSelector <SourceSelector
sources={sources} sources={sources}
@ -51,6 +51,7 @@ const OverlayControls = ({
/> />
</div> </div>
</div> </div>
)
const {arrayOf, bool, func, shape, string} = PropTypes const {arrayOf, bool, func, shape, string} = PropTypes

View File

@ -26,7 +26,7 @@ const QueryMaker = ({
activeQueryIndex, activeQueryIndex,
initialGroupByTime, initialGroupByTime,
setActiveQueryIndex, setActiveQueryIndex,
}) => }) => (
<div className="query-maker query-maker--panel"> <div className="query-maker query-maker--panel">
<QueryTabList <QueryTabList
queries={queries} queries={queries}
@ -36,28 +36,31 @@ const QueryMaker = ({
activeQueryIndex={activeQueryIndex} activeQueryIndex={activeQueryIndex}
setActiveQueryIndex={setActiveQueryIndex} setActiveQueryIndex={setActiveQueryIndex}
/> />
{activeQuery && activeQuery.id {activeQuery && activeQuery.id ? (
? <div className="query-maker--tab-contents"> <div className="query-maker--tab-contents">
<QueryTextArea <QueryTextArea
query={buildText(activeQuery)} query={buildText(activeQuery)}
config={activeQuery} config={activeQuery}
onUpdate={rawTextBinder( onUpdate={rawTextBinder(
source.links, source.links,
activeQuery.id, activeQuery.id,
actions.editRawTextAsync actions.editRawTextAsync
)} )}
templates={templates} templates={templates}
/> />
<SchemaExplorer <SchemaExplorer
source={source} source={source}
actions={actions} actions={actions}
query={activeQuery} query={activeQuery}
onAddQuery={onAddQuery} onAddQuery={onAddQuery}
initialGroupByTime={initialGroupByTime} initialGroupByTime={initialGroupByTime}
/> />
</div> </div>
: <EmptyQuery onAddQuery={onAddQuery} />} ) : (
<EmptyQuery onAddQuery={onAddQuery} />
)}
</div> </div>
)
const {arrayOf, func, number, shape, string} = PropTypes const {arrayOf, func, number, shape, string} = PropTypes

View File

@ -215,15 +215,15 @@ class QueryTextArea extends Component {
<QueryStatus status={status} /> <QueryStatus status={status} />
</div> </div>
<div className="varmoji-back"> <div className="varmoji-back">
{isTemplating {isTemplating ? (
? <TemplateDrawer <TemplateDrawer
onClickTempVar={this.handleClickTempVar} onClickTempVar={this.handleClickTempVar}
templates={filteredTemplates} templates={filteredTemplates}
selected={selectedTemplate} selected={selectedTemplate}
onMouseOverTempVar={this.handleMouseOverTempVar} onMouseOverTempVar={this.handleMouseOverTempVar}
handleClickOutside={this.handleCloseDrawer} handleClickOutside={this.handleCloseDrawer}
/> />
: null} ) : null}
</div> </div>
</div> </div>
</div> </div>

View File

@ -3,20 +3,22 @@ import PropTypes from 'prop-types'
import Dropdown from 'shared/components/Dropdown' import Dropdown from 'shared/components/Dropdown'
const SourceSelector = ({sources = [], selected, onSetQuerySource, queries}) => const SourceSelector = ({sources = [], selected, onSetQuerySource, queries}) =>
sources.length > 1 && queries.length sources.length > 1 && queries.length ? (
? <div className="source-selector"> <div className="source-selector">
<h3>Source:</h3> <h3>Source:</h3>
<Dropdown <Dropdown
items={sources} items={sources}
buttonSize="btn-sm" buttonSize="btn-sm"
menuClass="dropdown-astronaut" menuClass="dropdown-astronaut"
useAutoComplete={true} useAutoComplete={true}
selected={selected} selected={selected}
onChoose={onSetQuerySource} onChoose={onSetQuerySource}
className="dropdown-240" className="dropdown-240"
/> />
</div> </div>
: <div className="source-selector" /> ) : (
<div className="source-selector" />
)
const {array, arrayOf, func, shape, string} = PropTypes const {array, arrayOf, func, shape, string} = PropTypes

View File

@ -2,23 +2,23 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip' import QuestionMarkTooltip from 'src/shared/components/QuestionMarkTooltip'
export const Tabber = ({labelText, children, tipID, tipContent}) => export const Tabber = ({labelText, children, tipID, tipContent}) => (
<div className="form-group col-md-6"> <div className="form-group col-md-6">
<label> <label>
{labelText} {labelText}
{tipID {tipID ? (
? <QuestionMarkTooltip tipID={tipID} tipContent={tipContent} /> <QuestionMarkTooltip tipID={tipID} tipContent={tipContent} />
: null} ) : null}
</label> </label>
<ul className="nav nav-tablist nav-tablist-sm"> <ul className="nav nav-tablist nav-tablist-sm">{children}</ul>
{children}
</ul>
</div> </div>
)
export const Tab = ({isActive, onClickTab, text}) => export const Tab = ({isActive, onClickTab, text}) => (
<li className={isActive ? 'active' : ''} onClick={onClickTab}> <li className={isActive ? 'active' : ''} onClick={onClickTab}>
{text} {text}
</li> </li>
)
const {bool, func, node, string} = PropTypes const {bool, func, node, string} = PropTypes

View File

@ -16,67 +16,67 @@ const TemplateControlBar = ({
templates, templates,
onSelectTemplate, onSelectTemplate,
onOpenTemplateManager, onOpenTemplateManager,
}) => }) => (
<div className={classnames('template-control-bar', {show: isOpen})}> <div className={classnames('template-control-bar', {show: isOpen})}>
<div className="template-control--container"> <div className="template-control--container">
<div className="template-control--controls"> <div className="template-control--controls">
{templates.length {templates.length ? (
? templates.map(({id, values, tempVar}) => { templates.map(({id, values, tempVar}) => {
const items = values.map(value => ({...value, text: value.value})) const items = values.map(value => ({...value, text: value.value}))
const itemValues = values.map(value => value.value) const itemValues = values.map(value => value.value)
const selectedItem = items.find(item => item.selected) || items[0] const selectedItem = items.find(item => item.selected) || items[0]
const selectedText = selectedItem && selectedItem.text const selectedText = selectedItem && selectedItem.text
let customDropdownWidth = 0 let customDropdownWidth = 0
if (itemValues.length > 1) { if (itemValues.length > 1) {
const longest = itemValues.reduce( const longest = itemValues.reduce(
(a, b) => (a.length > b.length ? a : b) (a, b) => (a.length > b.length ? a : b)
)
const longestLengthPixels =
calculateSize(longest, {
font: 'Monospace',
fontSize: '12px',
}).width + tempVarDropdownPadding
if (
longestLengthPixels > minTempVarDropdownWidth &&
longestLengthPixels < maxTempVarDropdownWidth
) {
customDropdownWidth = longestLengthPixels
} else if (longestLengthPixels > maxTempVarDropdownWidth) {
customDropdownWidth = maxTempVarDropdownWidth
}
}
// TODO: change Dropdown to a MultiSelectDropdown, `selected` to
// the full array, and [item] to all `selected` values when we update
// this component to support multiple values
return (
<div
key={id}
className="template-control--dropdown"
style={
customDropdownWidth > 0
? {minWidth: customDropdownWidth}
: null
}
>
<Dropdown
items={items}
buttonSize="btn-xs"
menuClass="dropdown-astronaut"
useAutoComplete={true}
selected={selectedText || '(No values)'}
onChoose={onSelectTemplate(id)}
/>
<label className="template-control--label">
{tempVar}
</label>
</div>
) )
}) const longestLengthPixels =
: <div className="template-control--empty"> calculateSize(longest, {
This dashboard does not have any Template Variables font: 'Monospace',
</div>} fontSize: '12px',
}).width + tempVarDropdownPadding
if (
longestLengthPixels > minTempVarDropdownWidth &&
longestLengthPixels < maxTempVarDropdownWidth
) {
customDropdownWidth = longestLengthPixels
} else if (longestLengthPixels > maxTempVarDropdownWidth) {
customDropdownWidth = maxTempVarDropdownWidth
}
}
// TODO: change Dropdown to a MultiSelectDropdown, `selected` to
// the full array, and [item] to all `selected` values when we update
// this component to support multiple values
return (
<div
key={id}
className="template-control--dropdown"
style={
customDropdownWidth > 0
? {minWidth: customDropdownWidth}
: null
}
>
<Dropdown
items={items}
buttonSize="btn-xs"
menuClass="dropdown-astronaut"
useAutoComplete={true}
selected={selectedText || '(No values)'}
onChoose={onSelectTemplate(id)}
/>
<label className="template-control--label">{tempVar}</label>
</div>
)
})
) : (
<div className="template-control--empty">
This dashboard does not have any Template Variables
</div>
)}
</div> </div>
<Authorized requiredRole={EDITOR_ROLE}> <Authorized requiredRole={EDITOR_ROLE}>
<button <button
@ -89,6 +89,7 @@ const TemplateControlBar = ({
</Authorized> </Authorized>
</div> </div>
</div> </div>
)
const {arrayOf, bool, func, shape, string} = PropTypes const {arrayOf, bool, func, shape, string} = PropTypes

View File

@ -78,17 +78,15 @@ class Threshold extends Component {
return ( return (
<div className="threshold-item"> <div className="threshold-item">
<div className={labelClass}> <div className={labelClass}>{label}</div>
{label} {canBeDeleted ? (
</div> <button
{canBeDeleted className="btn btn-default btn-sm btn-square"
? <button onClick={onDeleteThreshold(threshold)}
className="btn btn-default btn-sm btn-square" >
onClick={onDeleteThreshold(threshold)} <span className="icon remove" />
> </button>
<span className="icon remove" /> ) : null}
</button>
: null}
<input <input
value={workingValue} value={workingValue}
className={inputClass} className={inputClass}

View File

@ -55,21 +55,23 @@ class VisualizationName extends Component {
return ( return (
<div className="graph-heading"> <div className="graph-heading">
{isEditing {isEditing ? (
? <input <input
type="text" type="text"
className="form-control input-sm" className="form-control input-sm"
defaultValue={name} defaultValue={name}
onBlur={this.handleInputBlur} onBlur={this.handleInputBlur}
onKeyDown={this.handleKeyDown} onKeyDown={this.handleKeyDown}
autoFocus={true} autoFocus={true}
onFocus={this.handleFocus} onFocus={this.handleFocus}
placeholder="Name this Cell..." placeholder="Name this Cell..."
spellCheck={false} spellCheck={false}
/> />
: <div className={graphNameClass} onClick={this.handleInputClick}> ) : (
{name} <div className={graphNameClass} onClick={this.handleInputClick}>
</div>} {name}
</div>
)}
</div> </div>
) )
} }

View File

@ -19,7 +19,7 @@ const TemplateVariableManager = ({
tempVarAlreadyExists, tempVarAlreadyExists,
onSaveTemplatesSuccess, onSaveTemplatesSuccess,
onEditTemplateVariables, onEditTemplateVariables,
}) => }) => (
<div className="template-variable-manager"> <div className="template-variable-manager">
<div className="template-variable-manager--header"> <div className="template-variable-manager--header">
<div className="page-header__left"> <div className="page-header__left">
@ -56,6 +56,7 @@ const TemplateVariableManager = ({
/> />
</div> </div>
</div> </div>
)
class TemplateVariableManagerWrapper extends Component { class TemplateVariableManagerWrapper extends Component {
constructor(props) { constructor(props) {

View File

@ -45,7 +45,7 @@ const TemplateVariableRow = ({
onSubmit, onSubmit,
onErrorThrown, onErrorThrown,
onDeleteTempVar, onDeleteTempVar,
}) => }) => (
<form <form
className={classnames('template-variable-manager--table-row', { className={classnames('template-variable-manager--table-row', {
editing: isEditing, editing: isEditing,
@ -106,6 +106,7 @@ const TemplateVariableRow = ({
/> />
</div> </div>
</form> </form>
)
class RowWrapper extends Component { class RowWrapper extends Component {
constructor(props) { constructor(props) {

View File

@ -10,36 +10,39 @@ const TemplateVariableTable = ({
onRunQueryFailure, onRunQueryFailure,
onDelete, onDelete,
tempVarAlreadyExists, tempVarAlreadyExists,
}) => }) => (
<div className="template-variable-manager--table"> <div className="template-variable-manager--table">
{templates.length {templates.length ? (
? <div className="template-variable-manager--table-container"> <div className="template-variable-manager--table-container">
<div className="template-variable-manager--table-heading"> <div className="template-variable-manager--table-heading">
<div className="tvm--col-1">Variable</div> <div className="tvm--col-1">Variable</div>
<div className="tvm--col-2">Type</div> <div className="tvm--col-2">Type</div>
<div className="tvm--col-3">Definition / Values</div> <div className="tvm--col-3">Definition / Values</div>
<div className="tvm--col-4" /> <div className="tvm--col-4" />
</div>
<div className="template-variable-manager--table-rows">
{templates.map(t =>
<TemplateVariableRow
key={t.id}
source={source}
template={t}
onRunQuerySuccess={onRunQuerySuccess}
onRunQueryFailure={onRunQueryFailure}
onDelete={onDelete}
tempVarAlreadyExists={tempVarAlreadyExists}
/>
)}
</div>
</div> </div>
: <div className="generic-empty-state"> <div className="template-variable-manager--table-rows">
<h4 style={{margin: '60px 0'}} className="no-user-select"> {templates.map(t => (
You have no Template Variables, why not create one? <TemplateVariableRow
</h4> key={t.id}
</div>} source={source}
template={t}
onRunQuerySuccess={onRunQuerySuccess}
onRunQueryFailure={onRunQueryFailure}
onDelete={onDelete}
tempVarAlreadyExists={tempVarAlreadyExists}
/>
))}
</div>
</div>
) : (
<div className="generic-empty-state">
<h4 style={{margin: '60px 0'}} className="no-user-select">
You have no Template Variables, why not create one?
</h4>
</div>
)}
</div> </div>
)
const {arrayOf, bool, func, shape, string} = PropTypes const {arrayOf, bool, func, shape, string} = PropTypes

View File

@ -8,26 +8,26 @@ const TableInput = ({
onStartEdit, onStartEdit,
autoFocusTarget, autoFocusTarget,
}) => { }) => {
return isEditing return isEditing ? (
? <div name={name} style={{width: '100%'}}> <div name={name} style={{width: '100%'}}>
<input <input
required={true} required={true}
name={name} name={name}
autoFocus={name === autoFocusTarget} autoFocus={name === autoFocusTarget}
className="form-control input-sm tvm-input-edit" className="form-control input-sm tvm-input-edit"
type="text" type="text"
defaultValue={ defaultValue={
name === 'tempVar' name === 'tempVar'
? defaultValue.replace(/\u003a/g, '') // remove ':'s ? defaultValue.replace(/\u003a/g, '') // remove ':'s
: defaultValue : defaultValue
} }
/> />
</div> </div>
: <div style={{width: '100%'}} onClick={onStartEdit(name)}> ) : (
<div className="tvm-input"> <div style={{width: '100%'}} onClick={onStartEdit(name)}>
{defaultValue} <div className="tvm-input">{defaultValue}</div>
</div> </div>
</div> )
} }
const {bool, func, string} = PropTypes const {bool, func, string} = PropTypes

View File

@ -46,15 +46,17 @@ const TemplateQueryBuilder = ({
onErrorThrown={onErrorThrown} onErrorThrown={onErrorThrown}
/> />
<span className="tvm-query-builder--text">FROM</span> <span className="tvm-query-builder--text">FROM</span>
{selectedDatabase {selectedDatabase ? (
? <MeasurementDropdown <MeasurementDropdown
database={selectedDatabase} database={selectedDatabase}
measurement={selectedMeasurement} measurement={selectedMeasurement}
onSelectMeasurement={onSelectMeasurement} onSelectMeasurement={onSelectMeasurement}
onStartEdit={onStartEdit} onStartEdit={onStartEdit}
onErrorThrown={onErrorThrown} onErrorThrown={onErrorThrown}
/> />
: <div>No database selected</div>} ) : (
<div>No database selected</div>
)}
</div> </div>
) )
case 'tagValues': case 'tagValues':
@ -68,26 +70,30 @@ const TemplateQueryBuilder = ({
onErrorThrown={onErrorThrown} onErrorThrown={onErrorThrown}
/> />
<span className="tvm-query-builder--text">FROM</span> <span className="tvm-query-builder--text">FROM</span>
{selectedDatabase {selectedDatabase ? (
? <MeasurementDropdown <MeasurementDropdown
database={selectedDatabase} database={selectedDatabase}
measurement={selectedMeasurement} measurement={selectedMeasurement}
onSelectMeasurement={onSelectMeasurement} onSelectMeasurement={onSelectMeasurement}
onStartEdit={onStartEdit} onStartEdit={onStartEdit}
onErrorThrown={onErrorThrown} onErrorThrown={onErrorThrown}
/> />
: 'Pick a DB'} ) : (
'Pick a DB'
)}
<span className="tvm-query-builder--text">WITH KEY =</span> <span className="tvm-query-builder--text">WITH KEY =</span>
{selectedMeasurement {selectedMeasurement ? (
? <TagKeyDropdown <TagKeyDropdown
database={selectedDatabase} database={selectedDatabase}
measurement={selectedMeasurement} measurement={selectedMeasurement}
tagKey={selectedTagKey} tagKey={selectedTagKey}
onSelectTagKey={onSelectTagKey} onSelectTagKey={onSelectTagKey}
onStartEdit={onStartEdit} onStartEdit={onStartEdit}
onErrorThrown={onErrorThrown} onErrorThrown={onErrorThrown}
/> />
: 'Pick a Tag Key'} ) : (
'Pick a Tag Key'
)}
</div> </div>
) )
default: default:

View File

@ -356,35 +356,35 @@ class DashboardPage extends Component {
return ( return (
<div className="page"> <div className="page">
{isTemplating {isTemplating ? (
? <OverlayTechnologies> <OverlayTechnologies>
<TemplateVariableManager <TemplateVariableManager
source={source}
templates={dashboard.templates}
onClose={this.handleCloseTemplateManager}
onRunQueryFailure={this.handleRunQueryFailure}
onEditTemplateVariables={this.handleEditTemplateVariables}
/>
</OverlayTechnologies>
: null}
{selectedCell
? <CellEditorOverlay
source={source} source={source}
sources={sources} templates={dashboard.templates}
cell={selectedCell} onClose={this.handleCloseTemplateManager}
timeRange={timeRange} onRunQueryFailure={this.handleRunQueryFailure}
autoRefresh={autoRefresh} onEditTemplateVariables={this.handleEditTemplateVariables}
dashboardID={dashboardID}
queryStatus={cellQueryStatus}
onSave={this.handleSaveEditedCell}
onCancel={handleHideCellEditorOverlay}
templates={templatesIncludingDashTime}
editQueryStatus={dashboardActions.editCellQueryStatus}
thresholdsListType={thresholdsListType}
thresholdsListColors={thresholdsListColors}
gaugeColors={gaugeColors}
/> />
: null} </OverlayTechnologies>
) : null}
{selectedCell ? (
<CellEditorOverlay
source={source}
sources={sources}
cell={selectedCell}
timeRange={timeRange}
autoRefresh={autoRefresh}
dashboardID={dashboardID}
queryStatus={cellQueryStatus}
onSave={this.handleSaveEditedCell}
onCancel={handleHideCellEditorOverlay}
templates={templatesIncludingDashTime}
editQueryStatus={dashboardActions.editCellQueryStatus}
thresholdsListType={thresholdsListType}
thresholdsListColors={thresholdsListColors}
gaugeColors={gaugeColors}
/>
) : null}
<DashboardHeader <DashboardHeader
names={names} names={names}
sourceID={sourceID} sourceID={sourceID}
@ -407,30 +407,30 @@ class DashboardPage extends Component {
onToggleTempVarControls={this.handleToggleTempVarControls} onToggleTempVarControls={this.handleToggleTempVarControls}
handleClickPresentationButton={handleClickPresentationButton} handleClickPresentationButton={handleClickPresentationButton}
/> />
{dashboard {dashboard ? (
? <Dashboard <Dashboard
source={source} source={source}
sources={sources} sources={sources}
setScrollTop={this.setScrollTop} setScrollTop={this.setScrollTop}
inView={this.inView} inView={this.inView}
dashboard={dashboard} dashboard={dashboard}
timeRange={timeRange} timeRange={timeRange}
autoRefresh={autoRefresh} autoRefresh={autoRefresh}
manualRefresh={manualRefresh} manualRefresh={manualRefresh}
onZoom={this.handleZoomedTimeRange} onZoom={this.handleZoomedTimeRange}
onAddCell={this.handleAddCell} onAddCell={this.handleAddCell}
hoverTime={hoverTime} hoverTime={hoverTime}
onSetHoverTime={this.handleSetHoverTime} onSetHoverTime={this.handleSetHoverTime}
inPresentationMode={inPresentationMode} inPresentationMode={inPresentationMode}
onPositionChange={this.handleUpdatePosition} onPositionChange={this.handleUpdatePosition}
onSelectTemplate={this.handleSelectTemplate} onSelectTemplate={this.handleSelectTemplate}
onDeleteCell={this.handleDeleteDashboardCell} onDeleteCell={this.handleDeleteDashboardCell}
showTemplateControlBar={showTemplateControlBar} showTemplateControlBar={showTemplateControlBar}
onOpenTemplateManager={this.handleOpenTemplateManager} onOpenTemplateManager={this.handleOpenTemplateManager}
templatesIncludingDashTime={templatesIncludingDashTime} templatesIncludingDashTime={templatesIncludingDashTime}
onSummonOverlayTechnologies={handleShowCellEditorOverlay} onSummonOverlayTechnologies={handleShowCellEditorOverlay}
/> />
: null} ) : null}
</div> </div>
) )
} }

View File

@ -90,27 +90,27 @@ class FieldListItem extends Component {
<div className="query-builder--checkbox" /> <div className="query-builder--checkbox" />
{fieldName} {fieldName}
</span> </span>
{isSelected {isSelected ? (
? <div <div
className={classnames('btn btn-xs', { className={classnames('btn btn-xs', {
active: isOpen, active: isOpen,
'btn-default': !num, 'btn-default': !num,
'btn-primary': num, 'btn-primary': num,
})} })}
onClick={this.toggleFunctionsMenu} onClick={this.toggleFunctionsMenu}
data-test={`query-builder-list-item-function-${fieldName}`} data-test={`query-builder-list-item-function-${fieldName}`}
> >
{fieldFuncsLabel} {fieldFuncsLabel}
</div> </div>
: null} ) : null}
</div> </div>
{isSelected && isOpen {isSelected && isOpen ? (
? <FunctionSelector <FunctionSelector
onApply={this.handleApplyFunctions} onApply={this.handleApplyFunctions}
selectedItems={funcs} selectedItems={funcs}
singleSelect={isKapacitorRule} singleSelect={isKapacitorRule}
/> />
: null} ) : null}
</div> </div>
) )
} }

View File

@ -19,7 +19,7 @@ const GroupByTimeDropdown = ({
selected, selected,
onChooseGroupByTime, onChooseGroupByTime,
location: {pathname}, location: {pathname},
}) => }) => (
<div className="group-by-time"> <div className="group-by-time">
<label className="group-by-time--label">Group by:</label> <label className="group-by-time--label">Group by:</label>
<Dropdown <Dropdown
@ -34,6 +34,7 @@ const GroupByTimeDropdown = ({
selected={selected || 'Time'} selected={selected || 'Time'}
/> />
</div> </div>
)
const {func, string, shape} = PropTypes const {func, string, shape} = PropTypes

View File

@ -8,12 +8,8 @@ const NoDataNodeError = React.createClass({
render() { render() {
return ( return (
<ClusterError> <ClusterError>
<PanelHeading> <PanelHeading>{errorCopy.noData.head}</PanelHeading>
{errorCopy.noData.head} <PanelBody>{errorCopy.noData.body}</PanelBody>
</PanelHeading>
<PanelBody>
{errorCopy.noData.body}
</PanelBody>
</ClusterError> </ClusterError>
) )
}, },

View File

@ -14,7 +14,7 @@ const QueryMaker = ({
timeRange, timeRange,
activeQuery, activeQuery,
initialGroupByTime, initialGroupByTime,
}) => }) => (
<div className="query-maker query-maker--panel"> <div className="query-maker query-maker--panel">
<div className="query-maker--tab-contents"> <div className="query-maker--tab-contents">
<QueryEditor <QueryEditor
@ -33,6 +33,7 @@ const QueryMaker = ({
/> />
</div> </div>
</div> </div>
)
const {func, shape, string} = PropTypes const {func, shape, string} = PropTypes

View File

@ -31,9 +31,7 @@ const QueryMakerTab = React.createClass({
})} })}
onClick={this.handleSelect} onClick={this.handleSelect}
> >
<label> <label>{this.props.queryTabText}</label>
{this.props.queryTabText}
</label>
<span <span
className="query-maker--delete" className="query-maker--delete"
onClick={this.handleDelete} onClick={this.handleDelete}

View File

@ -134,60 +134,60 @@ class ChronoTable extends Component {
return ( return (
<div style={{width: '100%', height: '100%', position: 'relative'}}> <div style={{width: '100%', height: '100%', position: 'relative'}}>
{series.length < maximumTabsCount {series.length < maximumTabsCount ? (
? <div className="table--tabs"> <div className="table--tabs">
{series.map((s, i) => {series.map((s, i) => (
<TabItem <TabItem
isActive={i === activeSeriesIndex} isActive={i === activeSeriesIndex}
key={i} key={i}
name={this.makeTabName(s)} name={this.makeTabName(s)}
index={i} index={i}
onClickTab={this.handleClickTab} onClickTab={this.handleClickTab}
/> />
)} ))}
</div> </div>
: <Dropdown ) : (
className="dropdown-160 table--tabs-dropdown" <Dropdown
items={series.map((s, index) => ({ className="dropdown-160 table--tabs-dropdown"
...s, items={series.map((s, index) => ({
text: this.makeTabName(s), ...s,
index, text: this.makeTabName(s),
}))} index,
onChoose={this.handleClickDropdown} }))}
selected={this.makeTabName(series[activeSeriesIndex])} onChoose={this.handleClickDropdown}
buttonSize="btn-xs" selected={this.makeTabName(series[activeSeriesIndex])}
/>} buttonSize="btn-xs"
/>
)}
<div className="table--tabs-content"> <div className="table--tabs-content">
{(columns && !columns.length) || (values && !values.length) {(columns && !columns.length) || (values && !values.length) ? (
? <div className="generic-empty-state">This series is empty</div> <div className="generic-empty-state">This series is empty</div>
: <Table ) : (
onColumnResizeEndCallback={this.handleColumnResize} <Table
isColumnResizing={false} onColumnResizeEndCallback={this.handleColumnResize}
rowHeight={rowHeight} isColumnResizing={false}
rowsCount={values.length} rowHeight={rowHeight}
width={containerWidth} rowsCount={values.length}
ownerHeight={styleAdjustedHeight} width={containerWidth}
height={styleAdjustedHeight} ownerHeight={styleAdjustedHeight}
headerHeight={headerHeight} height={styleAdjustedHeight}
> headerHeight={headerHeight}
{columns.map((columnName, colIndex) => { >
return ( {columns.map((columnName, colIndex) => {
<Column return (
isResizable={true} <Column
key={columnName} isResizable={true}
columnKey={columnName} key={columnName}
header={ columnKey={columnName}
<Cell> header={<Cell>{columnName}</Cell>}
{columnName} cell={this.handleCustomCell(columnName, values, colIndex)}
</Cell> width={columnWidths[columnName] || width}
} minWidth={minWidth}
cell={this.handleCustomCell(columnName, values, colIndex)} />
width={columnWidths[columnName] || width} )
minWidth={minWidth} })}
/> </Table>
) )}
})}
</Table>}
</div> </div>
</div> </div>
) )

View File

@ -2,13 +2,14 @@ import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
import classnames from 'classnames' import classnames from 'classnames'
const TableTabItem = ({name, index, onClickTab, isActive}) => const TableTabItem = ({name, index, onClickTab, isActive}) => (
<div <div
className={classnames('table--tab', {active: isActive})} className={classnames('table--tab', {active: isActive})}
onClick={onClickTab(index)} onClick={onClickTab(index)}
> >
{name} {name}
</div> </div>
)
const {bool, func, number, string} = PropTypes const {bool, func, number, string} = PropTypes

View File

@ -27,32 +27,33 @@ const getCSV = (query, errorThrown) => async () => {
} }
} }
const VisHeader = ({views, view, onToggleView, query, errorThrown}) => const VisHeader = ({views, view, onToggleView, query, errorThrown}) => (
<div className="graph-heading"> <div className="graph-heading">
{views.length {views.length ? (
? <ul className="nav nav-tablist nav-tablist-sm"> <ul className="nav nav-tablist nav-tablist-sm">
{views.map(v => {views.map(v => (
<li <li
key={v} key={v}
onClick={onToggleView(v)} onClick={onToggleView(v)}
className={classnames({active: view === v})} className={classnames({active: view === v})}
data-test={`data-${v}`} data-test={`data-${v}`}
> >
{_.upperFirst(v)} {_.upperFirst(v)}
</li> </li>
)} ))}
</ul> </ul>
: null} ) : null}
{query {query ? (
? <div <div
className="btn btn-sm btn-default dlcsv" className="btn btn-sm btn-default dlcsv"
onClick={getCSV(query, errorThrown)} onClick={getCSV(query, errorThrown)}
> >
<span className="icon download dlcsv" /> <span className="icon download dlcsv" />
.csv .csv
</div> </div>
: null} ) : null}
</div> </div>
)
const {arrayOf, func, shape, string} = PropTypes const {arrayOf, func, shape, string} = PropTypes

View File

@ -15,70 +15,75 @@ const WriteDataBody = ({
fileInput, fileInput,
handleFileOpen, handleFileOpen,
isUploading, isUploading,
}) => }) => (
<div className="write-data-form--body"> <div className="write-data-form--body">
{isManual {isManual ? (
? <textarea <textarea
className="form-control write-data-form--input" className="form-control write-data-form--input"
autoComplete="off" autoComplete="off"
spellCheck="false" spellCheck="false"
placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>" placeholder="<measurement>,<tag_key>=<tag_value> <field_key>=<field_value>"
onKeyUp={handleKeyUp} onKeyUp={handleKeyUp}
onChange={handleEdit} onChange={handleEdit}
autoFocus={true} autoFocus={true}
data-test="manual-entry-field" data-test="manual-entry-field"
/> />
: <div ) : (
<div
className={
uploadContent
? 'write-data-form--file'
: 'write-data-form--file write-data-form--file_active'
}
onClick={handleFileOpen}
>
{uploadContent ? (
<h3 className="write-data-form--filepath_selected">{fileName}</h3>
) : (
<h3 className="write-data-form--filepath_empty">
Drop a file here or click to upload
</h3>
)}
<div
className={ className={
uploadContent uploadContent
? 'write-data-form--file' ? 'write-data-form--graphic write-data-form--graphic_success'
: 'write-data-form--file write-data-form--file_active' : 'write-data-form--graphic'
} }
onClick={handleFileOpen} />
> <input
{uploadContent type="file"
? <h3 className="write-data-form--filepath_selected"> onChange={handleFile(false)}
{fileName} className="write-data-form--upload"
</h3> ref={fileInput}
: <h3 className="write-data-form--filepath_empty"> accept="text/*, application/gzip"
Drop a file here or click to upload />
</h3>} {uploadContent && (
<div <span className="write-data-form--file-submit">
className={ <button className="btn btn-md btn-success" onClick={handleSubmit}>
uploadContent Write this File
? 'write-data-form--graphic write-data-form--graphic_success' </button>
: 'write-data-form--graphic' <button
} className="btn btn-md btn-default"
/> onClick={handleCancelFile}
<input >
type="file" Cancel
onChange={handleFile(false)} </button>
className="write-data-form--upload" </span>
ref={fileInput} )}
accept="text/*, application/gzip" </div>
/> )}
{uploadContent && {isManual && (
<span className="write-data-form--file-submit">
<button className="btn btn-md btn-success" onClick={handleSubmit}>
Write this File
</button>
<button
className="btn btn-md btn-default"
onClick={handleCancelFile}
>
Cancel
</button>
</span>}
</div>}
{isManual &&
<WriteDataFooter <WriteDataFooter
isUploading={isUploading} isUploading={isUploading}
isManual={isManual} isManual={isManual}
inputContent={inputContent} inputContent={inputContent}
handleSubmit={handleSubmit} handleSubmit={handleSubmit}
uploadContent={uploadContent} uploadContent={uploadContent}
/>} />
)}
</div> </div>
)
const {func, string, bool} = PropTypes const {func, string, bool} = PropTypes

View File

@ -10,26 +10,28 @@ const WriteDataFooter = ({
uploadContent, uploadContent,
handleSubmit, handleSubmit,
isUploading, isUploading,
}) => }) => (
<div className="write-data-form--footer"> <div className="write-data-form--footer">
{isManual {isManual ? (
? <span className="write-data-form--helper"> <span className="write-data-form--helper">
Need help writing InfluxDB Line Protocol? -&nbsp; Need help writing InfluxDB Line Protocol? -&nbsp;
<a <a
href="https://docs.influxdata.com/influxdb/latest/write_protocols/line_protocol_tutorial/" href="https://docs.influxdata.com/influxdb/latest/write_protocols/line_protocol_tutorial/"
target="_blank" target="_blank"
> >
See Documentation See Documentation
</a> </a>
</span> </span>
: <span className="write-data-form--helper"> ) : (
<a <span className="write-data-form--helper">
href="https://docs.influxdata.com/influxdb/v1.2//tools/shell/#import-data-from-a-file-with-import" <a
target="_blank" href="https://docs.influxdata.com/influxdb/v1.2//tools/shell/#import-data-from-a-file-with-import"
> target="_blank"
File Upload Documentation >
</a> File Upload Documentation
</span>} </a>
</span>
)}
<button <button
className={isUploading ? `${submitButton} ${spinner}` : submitButton} className={isUploading ? `${submitButton} ${spinner}` : submitButton}
onClick={handleSubmit} onClick={handleSubmit}
@ -43,6 +45,7 @@ const WriteDataFooter = ({
Write Write
</button> </button>
</div> </div>
)
const {bool, func, string} = PropTypes const {bool, func, string} = PropTypes

View File

@ -9,7 +9,7 @@ const WriteDataHeader = ({
toggleWriteView, toggleWriteView,
isManual, isManual,
onClose, onClose,
}) => }) => (
<div className="write-data-form--header"> <div className="write-data-form--header">
<div className="page-header__left"> <div className="page-header__left">
<h1 className="page-header__title">Write Data To</h1> <h1 className="page-header__title">Write Data To</h1>
@ -38,6 +38,7 @@ const WriteDataHeader = ({
<span className="page-header__dismiss" onClick={onClose} /> <span className="page-header__dismiss" onClick={onClose} />
</div> </div>
</div> </div>
)
const {func, string, bool} = PropTypes const {func, string, bool} = PropTypes

View File

@ -95,17 +95,17 @@ class DataExplorer extends Component {
const selectedDatabase = _.get(queryConfigs, ['0', 'database'], null) const selectedDatabase = _.get(queryConfigs, ['0', 'database'], null)
return ( return (
<div className="data-explorer"> <div className="data-explorer">
{showWriteForm {showWriteForm ? (
? <OverlayTechnologies> <OverlayTechnologies>
<WriteDataForm <WriteDataForm
source={source} source={source}
errorThrown={errorThrownAction} errorThrown={errorThrownAction}
selectedDatabase={selectedDatabase} selectedDatabase={selectedDatabase}
onClose={this.handleCloseWriteData} onClose={this.handleCloseWriteData}
writeLineProtocol={writeLineProtocol} writeLineProtocol={writeLineProtocol}
/> />
</OverlayTechnologies> </OverlayTechnologies>
: null} ) : null}
<Header <Header
timeRange={timeRange} timeRange={timeRange}
autoRefresh={autoRefresh} autoRefresh={autoRefresh}

View File

@ -16,7 +16,7 @@ const Header = ({
onManualRefresh, onManualRefresh,
onChooseTimeRange, onChooseTimeRange,
onChooseAutoRefresh, onChooseAutoRefresh,
}) => }) => (
<div className="page-header full-width"> <div className="page-header full-width">
<div className="page-header__container"> <div className="page-header__container">
<div className="page-header__left"> <div className="page-header__left">
@ -47,6 +47,7 @@ const Header = ({
</div> </div>
</div> </div>
</div> </div>
)
Header.propTypes = { Header.propTypes = {
onChooseAutoRefresh: func.isRequired, onChooseAutoRefresh: func.isRequired,

View File

@ -37,7 +37,10 @@ const download = (data, strFileName, strMimeType) => {
if (url && url.length < 2048) { if (url && url.length < 2048) {
// if no filename and no mime, assume a url was passed as the only argument // if no filename and no mime, assume a url was passed as the only argument
fileName = url.split('/').pop().split('?')[0] fileName = url
.split('/')
.pop()
.split('?')[0]
anchor.href = url // assign href prop to temp anchor anchor.href = url // assign href prop to temp anchor
if (anchor.href.indexOf(url) !== -1) { if (anchor.href.indexOf(url) !== -1) {
// if the browser determines that it's a potentially valid url path: // if the browser determines that it's a potentially valid url path:

View File

@ -23,9 +23,7 @@ class HostRow extends Component {
return ( return (
<div className="hosts-table--tr"> <div className="hosts-table--tr">
<div className="hosts-table--td" style={{width: colName}}> <div className="hosts-table--td" style={{width: colName}}>
<Link to={`/sources/${source.id}/hosts/${name}`}> <Link to={`/sources/${source.id}/hosts/${name}`}>{name}</Link>
{name}
</Link>
</div> </div>
<div className="hosts-table--td" style={{width: colStatus}}> <div className="hosts-table--td" style={{width: colStatus}}>
<div <div

View File

@ -102,61 +102,61 @@ class HostsTable extends Component {
return ( return (
<div className="panel"> <div className="panel">
<div className="panel-heading"> <div className="panel-heading">
<h2 className="panel-title"> <h2 className="panel-title">{hostsTitle}</h2>
{hostsTitle}
</h2>
<SearchBar <SearchBar
placeholder="Filter by Host..." placeholder="Filter by Host..."
onSearch={this.updateSearchTerm} onSearch={this.updateSearchTerm}
/> />
</div> </div>
<div className="panel-body"> <div className="panel-body">
{hostCount > 0 && !hostsError.length {hostCount > 0 && !hostsError.length ? (
? <div className="hosts-table"> <div className="hosts-table">
<div className="hosts-table--thead"> <div className="hosts-table--thead">
<div className="hosts-table--tr"> <div className="hosts-table--tr">
<div <div
onClick={this.updateSort('name')} onClick={this.updateSort('name')}
className={this.sortableClasses('name')} className={this.sortableClasses('name')}
style={{width: colName}} style={{width: colName}}
> >
Host Host
</div>
<div
onClick={this.updateSort('deltaUptime')}
className={this.sortableClasses('deltaUptime')}
style={{width: colStatus}}
>
Status
</div>
<div
onClick={this.updateSort('cpu')}
className={this.sortableClasses('cpu')}
style={{width: colCPU}}
>
CPU
</div>
<div
onClick={this.updateSort('load')}
className={this.sortableClasses('load')}
style={{width: colLoad}}
>
Load
</div>
<div className="hosts-table--th">Apps</div>
</div> </div>
<div
onClick={this.updateSort('deltaUptime')}
className={this.sortableClasses('deltaUptime')}
style={{width: colStatus}}
>
Status
</div>
<div
onClick={this.updateSort('cpu')}
className={this.sortableClasses('cpu')}
style={{width: colCPU}}
>
CPU
</div>
<div
onClick={this.updateSort('load')}
className={this.sortableClasses('load')}
style={{width: colLoad}}
>
Load
</div>
<div className="hosts-table--th">Apps</div>
</div> </div>
<InfiniteScroll
items={sortedHosts.map(h =>
<HostRow key={h.name} host={h} source={source} />
)}
itemHeight={26}
className="hosts-table--tbody"
/>
</div> </div>
: <div className="generic-empty-state"> <InfiniteScroll
<h4 style={{margin: '90px 0'}}>No Hosts found</h4> items={sortedHosts.map(h => (
</div>} <HostRow key={h.name} host={h} source={source} />
))}
itemHeight={26}
className="hosts-table--tbody"
/>
</div>
) : (
<div className="generic-empty-state">
<h4 style={{margin: '90px 0'}}>No Hosts found</h4>
</div>
)}
</div> </div>
</div> </div>
) )

View File

@ -96,7 +96,7 @@ class HostPage extends Component {
const autoflowCells = autoflowLayouts.reduce((allCells, layout) => { const autoflowCells = autoflowLayouts.reduce((allCells, layout) => {
return allCells.concat( return allCells.concat(
layout.cells.map(cell => { layout.cells.map(cell => {
const x = cellCount * cellWidth % pageWidth const x = (cellCount * cellWidth) % pageWidth
const y = Math.floor(cellCount * cellWidth / pageWidth) * cellHeight const y = Math.floor(cellCount * cellWidth / pageWidth) * cellHeight
cellCount += 1 cellCount += 1
return Object.assign(cell, { return Object.assign(cell, {

View File

@ -122,66 +122,50 @@ const Root = React.createClass({
}, },
render() { render() {
return !this.state.ready // eslint-disable-line no-negated-condition return !this.state.ready ? ( // eslint-disable-line no-negated-condition
? <div className="page-spinner" /> <div className="page-spinner" />
: <Provider store={store}> ) : (
<Router history={history}> <Provider store={store}>
<Route path="/" component={UserIsAuthenticated(CheckSources)} /> <Router history={history}>
<Route path="/login" component={UserIsNotAuthenticated(Login)} /> <Route path="/" component={UserIsAuthenticated(CheckSources)} />
<Route <Route path="/login" component={UserIsNotAuthenticated(Login)} />
path="/purgatory" <Route path="/purgatory" component={UserIsAuthenticated(Purgatory)} />
component={UserIsAuthenticated(Purgatory)} <Route
/> path="/sources/new"
<Route component={UserIsAuthenticated(SourcePage)}
path="/sources/new" />
component={UserIsAuthenticated(SourcePage)} <Route path="/sources/:sourceID" component={UserIsAuthenticated(App)}>
/> <Route component={CheckSources}>
<Route <Route path="status" component={StatusPage} />
path="/sources/:sourceID" <Route path="hosts" component={HostsPage} />
component={UserIsAuthenticated(App)} <Route path="hosts/:hostID" component={HostPage} />
> <Route path="chronograf/data-explorer" component={DataExplorer} />
<Route component={CheckSources}> <Route path="dashboards" component={DashboardsPage} />
<Route path="status" component={StatusPage} /> <Route path="dashboards/:dashboardID" component={DashboardPage} />
<Route path="hosts" component={HostsPage} /> <Route path="alerts" component={AlertsApp} />
<Route path="hosts/:hostID" component={HostPage} /> <Route path="alert-rules" component={KapacitorRulesPage} />
<Route <Route path="alert-rules/:ruleID" component={KapacitorRulePage} />
path="chronograf/data-explorer" <Route path="alert-rules/new" component={KapacitorRulePage} />
component={DataExplorer} <Route path="tickscript/new" component={TickscriptPage} />
/> <Route path="tickscript/:ruleID" component={TickscriptPage} />
<Route path="dashboards" component={DashboardsPage} /> <Route path="kapacitors/new" component={KapacitorPage} />
<Route <Route path="kapacitors/:id/edit" component={KapacitorPage} />
path="dashboards/:dashboardID" <Route
component={DashboardPage} path="kapacitors/:id/edit:hash"
/> component={KapacitorPage}
<Route path="alerts" component={AlertsApp} /> />
<Route path="alert-rules" component={KapacitorRulesPage} /> <Route path="kapacitor-tasks" component={KapacitorTasksPage} />
<Route <Route path="admin-chronograf" component={AdminChronografPage} />
path="alert-rules/:ruleID" <Route path="admin-influxdb" component={AdminInfluxDBPage} />
component={KapacitorRulePage} <Route path="manage-sources" component={ManageSources} />
/> <Route path="manage-sources/new" component={SourcePage} />
<Route path="alert-rules/new" component={KapacitorRulePage} /> <Route path="manage-sources/:id/edit" component={SourcePage} />
<Route path="tickscript/new" component={TickscriptPage} />
<Route path="tickscript/:ruleID" component={TickscriptPage} />
<Route path="kapacitors/new" component={KapacitorPage} />
<Route path="kapacitors/:id/edit" component={KapacitorPage} />
<Route
path="kapacitors/:id/edit:hash"
component={KapacitorPage}
/>
<Route path="kapacitor-tasks" component={KapacitorTasksPage} />
<Route
path="admin-chronograf"
component={AdminChronografPage}
/>
<Route path="admin-influxdb" component={AdminInfluxDBPage} />
<Route path="manage-sources" component={ManageSources} />
<Route path="manage-sources/new" component={SourcePage} />
<Route path="manage-sources/:id/edit" component={SourcePage} />
</Route>
</Route> </Route>
<Route path="*" component={NotFound} /> </Route>
</Router> <Route path="*" component={NotFound} />
</Provider> </Router>
</Provider>
)
}, },
}) })

View File

@ -142,123 +142,134 @@ class AlertTabs extends Component {
alerta: { alerta: {
type: 'Alerta', type: 'Alerta',
enabled: this.getEnabled(configSections, 'alerta'), enabled: this.getEnabled(configSections, 'alerta'),
renderComponent: () => renderComponent: () => (
<AlertaConfig <AlertaConfig
onSave={this.handleSaveConfig('alerta')} onSave={this.handleSaveConfig('alerta')}
config={this.getSection(configSections, 'alerta')} config={this.getSection(configSections, 'alerta')}
onTest={this.handleTestConfig('alerta')} onTest={this.handleTestConfig('alerta')}
enabled={this.getEnabled(configSections, 'alerta')} enabled={this.getEnabled(configSections, 'alerta')}
/>, />
),
}, },
hipchat: { hipchat: {
type: 'HipChat', type: 'HipChat',
enabled: this.getEnabled(configSections, 'hipchat'), enabled: this.getEnabled(configSections, 'hipchat'),
renderComponent: () => renderComponent: () => (
<HipChatConfig <HipChatConfig
onSave={this.handleSaveConfig('hipchat')} onSave={this.handleSaveConfig('hipchat')}
config={this.getSection(configSections, 'hipchat')} config={this.getSection(configSections, 'hipchat')}
onTest={this.handleTestConfig('hipchat')} onTest={this.handleTestConfig('hipchat')}
enabled={this.getEnabled(configSections, 'hipchat')} enabled={this.getEnabled(configSections, 'hipchat')}
/>, />
),
}, },
opsgenie: { opsgenie: {
type: 'OpsGenie', type: 'OpsGenie',
enabled: this.getEnabled(configSections, 'opsgenie'), enabled: this.getEnabled(configSections, 'opsgenie'),
renderComponent: () => renderComponent: () => (
<OpsGenieConfig <OpsGenieConfig
onSave={this.handleSaveConfig('opsgenie')} onSave={this.handleSaveConfig('opsgenie')}
config={this.getSection(configSections, 'opsgenie')} config={this.getSection(configSections, 'opsgenie')}
onTest={this.handleTestConfig('opsgenie')} onTest={this.handleTestConfig('opsgenie')}
enabled={this.getEnabled(configSections, 'opsgenie')} enabled={this.getEnabled(configSections, 'opsgenie')}
/>, />
),
}, },
pagerduty: { pagerduty: {
type: 'PagerDuty', type: 'PagerDuty',
enabled: this.getEnabled(configSections, 'pagerduty'), enabled: this.getEnabled(configSections, 'pagerduty'),
renderComponent: () => renderComponent: () => (
<PagerDutyConfig <PagerDutyConfig
onSave={this.handleSaveConfig('pagerduty')} onSave={this.handleSaveConfig('pagerduty')}
config={this.getSection(configSections, 'pagerduty')} config={this.getSection(configSections, 'pagerduty')}
onTest={this.handleTestConfig('pagerduty')} onTest={this.handleTestConfig('pagerduty')}
enabled={this.getEnabled(configSections, 'pagerduty')} enabled={this.getEnabled(configSections, 'pagerduty')}
/>, />
),
}, },
pushover: { pushover: {
type: 'Pushover', type: 'Pushover',
enabled: this.getEnabled(configSections, 'pushover'), enabled: this.getEnabled(configSections, 'pushover'),
renderComponent: () => renderComponent: () => (
<PushoverConfig <PushoverConfig
onSave={this.handleSaveConfig('pushover')} onSave={this.handleSaveConfig('pushover')}
config={this.getSection(configSections, 'pushover')} config={this.getSection(configSections, 'pushover')}
onTest={this.handleTestConfig('pushover')} onTest={this.handleTestConfig('pushover')}
enabled={this.getEnabled(configSections, 'pushover')} enabled={this.getEnabled(configSections, 'pushover')}
/>, />
),
}, },
sensu: { sensu: {
type: 'Sensu', type: 'Sensu',
enabled: this.getEnabled(configSections, 'sensu'), enabled: this.getEnabled(configSections, 'sensu'),
renderComponent: () => renderComponent: () => (
<SensuConfig <SensuConfig
onSave={this.handleSaveConfig('sensu')} onSave={this.handleSaveConfig('sensu')}
config={this.getSection(configSections, 'sensu')} config={this.getSection(configSections, 'sensu')}
onTest={this.handleTestConfig('sensu')} onTest={this.handleTestConfig('sensu')}
enabled={this.getEnabled(configSections, 'sensu')} enabled={this.getEnabled(configSections, 'sensu')}
/>, />
),
}, },
slack: { slack: {
type: 'Slack', type: 'Slack',
enabled: this.getEnabled(configSections, 'slack'), enabled: this.getEnabled(configSections, 'slack'),
renderComponent: () => renderComponent: () => (
<SlackConfig <SlackConfig
onSave={this.handleSaveConfig('slack')} onSave={this.handleSaveConfig('slack')}
config={this.getSection(configSections, 'slack')} config={this.getSection(configSections, 'slack')}
onTest={this.handleTestConfig('slack')} onTest={this.handleTestConfig('slack')}
enabled={this.getEnabled(configSections, 'slack')} enabled={this.getEnabled(configSections, 'slack')}
/>, />
),
}, },
smtp: { smtp: {
type: 'SMTP', type: 'SMTP',
enabled: this.getEnabled(configSections, 'smtp'), enabled: this.getEnabled(configSections, 'smtp'),
renderComponent: () => renderComponent: () => (
<SMTPConfig <SMTPConfig
onSave={this.handleSaveConfig('smtp')} onSave={this.handleSaveConfig('smtp')}
config={this.getSection(configSections, 'smtp')} config={this.getSection(configSections, 'smtp')}
onTest={this.handleTestConfig('smtp')} onTest={this.handleTestConfig('smtp')}
enabled={this.getEnabled(configSections, 'smtp')} enabled={this.getEnabled(configSections, 'smtp')}
/>, />
),
}, },
talk: { talk: {
type: 'Talk', type: 'Talk',
enabled: this.getEnabled(configSections, 'talk'), enabled: this.getEnabled(configSections, 'talk'),
renderComponent: () => renderComponent: () => (
<TalkConfig <TalkConfig
onSave={this.handleSaveConfig('talk')} onSave={this.handleSaveConfig('talk')}
config={this.getSection(configSections, 'talk')} config={this.getSection(configSections, 'talk')}
onTest={this.handleTestConfig('talk')} onTest={this.handleTestConfig('talk')}
enabled={this.getEnabled(configSections, 'talk')} enabled={this.getEnabled(configSections, 'talk')}
/>, />
),
}, },
telegram: { telegram: {
type: 'Telegram', type: 'Telegram',
enabled: this.getEnabled(configSections, 'telegram'), enabled: this.getEnabled(configSections, 'telegram'),
renderComponent: () => renderComponent: () => (
<TelegramConfig <TelegramConfig
onSave={this.handleSaveConfig('telegram')} onSave={this.handleSaveConfig('telegram')}
config={this.getSection(configSections, 'telegram')} config={this.getSection(configSections, 'telegram')}
onTest={this.handleTestConfig('telegram')} onTest={this.handleTestConfig('telegram')}
enabled={this.getEnabled(configSections, 'telegram')} enabled={this.getEnabled(configSections, 'telegram')}
/>, />
),
}, },
victorops: { victorops: {
type: 'VictorOps', type: 'VictorOps',
enabled: this.getEnabled(configSections, 'victorops'), enabled: this.getEnabled(configSections, 'victorops'),
renderComponent: () => renderComponent: () => (
<VictorOpsConfig <VictorOpsConfig
onSave={this.handleSaveConfig('victorops')} onSave={this.handleSaveConfig('victorops')}
config={this.getSection(configSections, 'victorops')} config={this.getSection(configSections, 'victorops')}
onTest={this.handleTestConfig('victorops')} onTest={this.handleTestConfig('victorops')}
enabled={this.getEnabled(configSections, 'victorops')} enabled={this.getEnabled(configSections, 'victorops')}
/>, />
),
}, },
} }
return ( return (

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const CodeData = ({onClickTemplate, template}) => const CodeData = ({onClickTemplate, template}) => (
<code <code
className="rule-builder--message-template" className="rule-builder--message-template"
data-tip={template.text} data-tip={template.text}
@ -9,6 +9,7 @@ const CodeData = ({onClickTemplate, template}) =>
> >
{template.label} {template.label}
</code> </code>
)
const {func, shape, string} = PropTypes const {func, shape, string} = PropTypes

View File

@ -76,16 +76,16 @@ const DataSection = ({
onGroupByTag={handleGroupByTag} onGroupByTag={handleGroupByTag}
onToggleTagAcceptance={handleToggleTagAcceptance} onToggleTagAcceptance={handleToggleTagAcceptance}
/> />
{isDeadman {isDeadman ? null : (
? null <FieldList
: <FieldList query={query}
query={query} onToggleField={handleToggleField}
onToggleField={handleToggleField} isKapacitorRule={isKapacitorRule}
isKapacitorRule={isKapacitorRule} onGroupByTime={handleGroupByTime}
onGroupByTime={handleGroupByTime} removeFuncs={handleRemoveFuncs}
removeFuncs={handleRemoveFuncs} applyFuncsToField={handleApplyFuncsToField(onAddEvery)}
applyFuncsToField={handleApplyFuncsToField(onAddEvery)} />
/>} )}
</div> </div>
</div> </div>
) )

View File

@ -7,7 +7,7 @@ const periods = PERIODS.map(text => {
return {text} return {text}
}) })
const Deadman = ({rule, onChange}) => const Deadman = ({rule, onChange}) => (
<div className="rule-section--row rule-section--row-first rule-section--row-last"> <div className="rule-section--row rule-section--row-first rule-section--row-last">
<p>Send Alert if Data is missing for</p> <p>Send Alert if Data is missing for</p>
<Dropdown <Dropdown
@ -18,6 +18,7 @@ const Deadman = ({rule, onChange}) =>
onChoose={onChange} onChoose={onChange}
/> />
</div> </div>
)
const {shape, string, func} = PropTypes const {shape, string, func} = PropTypes

View File

@ -6,7 +6,7 @@ const HandlerCheckbox = ({
fieldDisplay, fieldDisplay,
selectedHandler, selectedHandler,
handleModifyHandler, handleModifyHandler,
}) => }) => (
<div className="form-group "> <div className="form-group ">
<div className="form-control-static handler-checkbox"> <div className="form-control-static handler-checkbox">
<input <input
@ -16,11 +16,10 @@ const HandlerCheckbox = ({
defaultChecked={selectedHandler[fieldName]} defaultChecked={selectedHandler[fieldName]}
onClick={handleModifyHandler(selectedHandler, fieldName)} onClick={handleModifyHandler(selectedHandler, fieldName)}
/> />
<label htmlFor={fieldName}> <label htmlFor={fieldName}>{fieldDisplay}</label>
{fieldDisplay}
</label>
</div> </div>
</div> </div>
)
const {func, shape, string, bool} = PropTypes const {func, shape, string, bool} = PropTypes

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const HandlerEmpty = ({onGoToConfig, validationError}) => const HandlerEmpty = ({onGoToConfig, validationError}) => (
<div className="endpoint-tab-contents"> <div className="endpoint-tab-contents">
<div className="endpoint-tab--parameters"> <div className="endpoint-tab--parameters">
<div className="endpoint-tab--parameters--empty"> <div className="endpoint-tab--parameters--empty">
@ -20,6 +20,7 @@ const HandlerEmpty = ({onGoToConfig, validationError}) =>
</div> </div>
</div> </div>
</div> </div>
)
const {string, func} = PropTypes const {string, func} = PropTypes

View File

@ -17,9 +17,7 @@ const HandlerInput = ({
const formGroupClass = `form-group ${fieldColumns}` const formGroupClass = `form-group ${fieldColumns}`
return ( return (
<div className={formGroupClass}> <div className={formGroupClass}>
<label htmlFor={fieldName}> <label htmlFor={fieldName}>{fieldDisplay}</label>
{fieldDisplay}
</label>
<div className={redacted ? 'form-control-static redacted-handler' : null}> <div className={redacted ? 'form-control-static redacted-handler' : null}>
<input <input
name={fieldName} name={fieldName}
@ -42,11 +40,11 @@ const HandlerInput = ({
spellCheck="false" spellCheck="false"
disabled={disabled} disabled={disabled}
/> />
{redacted {redacted ? (
? <span className="alert-value-set"> <span className="alert-value-set">
<span className="icon checkmark" /> Value set in Config <span className="icon checkmark" /> Value set in Config
</span> </span>
: null} ) : null}
</div> </div>
</div> </div>
) )

View File

@ -9,25 +9,25 @@ const HandlerTabs = ({
handleChooseHandler, handleChooseHandler,
handleRemoveHandler, handleRemoveHandler,
}) => }) =>
handlersOnThisAlert.length handlersOnThisAlert.length ? (
? <ul className="endpoint-tabs"> <ul className="endpoint-tabs">
{handlersOnThisAlert.map(ep => {handlersOnThisAlert.map(ep => (
<li <li
key={uuid.v4()} key={uuid.v4()}
className={classnames('endpoint-tab', { className={classnames('endpoint-tab', {
active: ep.alias === (selectedHandler && selectedHandler.alias), active: ep.alias === (selectedHandler && selectedHandler.alias),
})} })}
onClick={handleChooseHandler(ep)} onClick={handleChooseHandler(ep)}
> >
{ep.type} {ep.type}
<button <button
className="endpoint-tab--delete" className="endpoint-tab--delete"
onClick={handleRemoveHandler(ep)} onClick={handleRemoveHandler(ep)}
/> />
</li> </li>
)} ))}
</ul> </ul>
: null ) : null
const {shape, func, array} = PropTypes const {shape, func, array} = PropTypes

View File

@ -45,21 +45,18 @@ const KapacitorRules = ({
const builderRules = rules.filter(r => r.query) const builderRules = rules.filter(r => r.query)
const builderHeader = `${builderRules.length} Alert Rule${builderRules.length === const builderHeader = `${builderRules.length} Alert Rule${
1 builderRules.length === 1 ? '' : 's'
? '' }`
: 's'}` const scriptsHeader = `${rules.length} TICKscript${
const scriptsHeader = `${rules.length} TICKscript${rules.length === 1 rules.length === 1 ? '' : 's'
? '' }`
: 's'}`
return ( return (
<PageContents source={source}> <PageContents source={source}>
<div className="panel"> <div className="panel">
<div className="panel-heading"> <div className="panel-heading">
<h2 className="panel-title"> <h2 className="panel-title">{builderHeader}</h2>
{builderHeader}
</h2>
<Link <Link
to={`/sources/${source.id}/alert-rules/new`} to={`/sources/${source.id}/alert-rules/new`}
className="btn btn-sm btn-primary" className="btn btn-sm btn-primary"
@ -79,9 +76,7 @@ const KapacitorRules = ({
</div> </div>
<div className="panel"> <div className="panel">
<div className="panel-heading"> <div className="panel-heading">
<h2 className="panel-title"> <h2 className="panel-title">{scriptsHeader}</h2>
{scriptsHeader}
</h2>
<Link <Link
to={`/sources/${source.id}/tickscript/new`} to={`/sources/${source.id}/tickscript/new`}
className="btn btn-sm btn-success" className="btn btn-sm btn-success"
@ -103,7 +98,7 @@ const KapacitorRules = ({
) )
} }
const PageContents = ({children}) => const PageContents = ({children}) => (
<div className="page"> <div className="page">
<div className="page-header"> <div className="page-header">
<div className="page-header__container"> <div className="page-header__container">
@ -122,13 +117,12 @@ const PageContents = ({children}) =>
<FancyScrollbar className="page-contents fancy-scroll--kapacitor"> <FancyScrollbar className="page-contents fancy-scroll--kapacitor">
<div className="container-fluid"> <div className="container-fluid">
<div className="row"> <div className="row">
<div className="col-md-12"> <div className="col-md-12">{children}</div>
{children}
</div>
</div> </div>
</div> </div>
</FancyScrollbar> </FancyScrollbar>
</div> </div>
)
const {arrayOf, bool, func, node, shape} = PropTypes const {arrayOf, bool, func, node, shape} = PropTypes

View File

@ -15,7 +15,7 @@ const {
colActions, colActions,
} = TASKS_TABLE } = TASKS_TABLE
const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) => const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) => (
<table className="table v-center table-highlight"> <table className="table v-center table-highlight">
<thead> <thead>
<tr> <tr>
@ -43,10 +43,11 @@ const KapacitorRulesTable = ({rules, source, onDelete, onChangeRuleStatus}) =>
})} })}
</tbody> </tbody>
</table> </table>
)
const handleDelete = (rule, onDelete) => onDelete(rule) const handleDelete = (rule, onDelete) => onDelete(rule)
const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) => const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) => (
<tr key={rule.id}> <tr key={rule.id}>
<td style={{minWidth: colName}}> <td style={{minWidth: colName}}>
<Link to={`/sources/${source.id}/alert-rules/${rule.id}`}> <Link to={`/sources/${source.id}/alert-rules/${rule.id}`}>
@ -56,12 +57,8 @@ const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) =>
<td style={{width: colTrigger, textTransform: 'capitalize'}}> <td style={{width: colTrigger, textTransform: 'capitalize'}}>
{rule.trigger} {rule.trigger}
</td> </td>
<td style={{width: colMessage}}> <td style={{width: colMessage}}>{rule.message}</td>
{rule.message} <td style={{width: colAlerts}}>{parseAlertNodeList(rule)}</td>
</td>
<td style={{width: colAlerts}}>
{parseAlertNodeList(rule)}
</td>
<td style={{width: colEnabled}} className="text-center"> <td style={{width: colEnabled}} className="text-center">
<div className="dark-checkbox"> <div className="dark-checkbox">
<input <input
@ -84,6 +81,7 @@ const RuleRow = ({rule, source, onDelete, onChangeRuleStatus}) =>
/> />
</td> </td>
</tr> </tr>
)
const {arrayOf, func, shape, string} = PropTypes const {arrayOf, func, shape, string} = PropTypes

View File

@ -1,13 +1,11 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogItemHTTP = ({logItem}) => const LogItemHTTP = ({logItem}) => (
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service">HTTP Request</div> <div className="logs-table--service">HTTP Request</div>
@ -16,6 +14,7 @@ const LogItemHTTP = ({logItem}) =>
</div> </div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -1,23 +1,20 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogItemHTTPError = ({logItem}) => const LogItemHTTPError = ({logItem}) => (
<div className="logs-table--row" key={logItem.key}> <div className="logs-table--row" key={logItem.key}>
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service error">HTTP Server</div> <div className="logs-table--service error">HTTP Server</div>
<div className="logs-table--columns"> <div className="logs-table--columns">
<div className="logs-table--key-values error"> <div className="logs-table--key-values error">ERROR: {logItem.msg}</div>
ERROR: {logItem.msg}
</div>
</div> </div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -1,13 +1,11 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogItemInfluxDBDebug = ({logItem}) => const LogItemInfluxDBDebug = ({logItem}) => (
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service debug">InfluxDB</div> <div className="logs-table--service debug">InfluxDB</div>
@ -20,6 +18,7 @@ const LogItemInfluxDBDebug = ({logItem}) =>
</div> </div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -1,23 +1,20 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogItemKapacitorDebug = ({logItem}) => const LogItemKapacitorDebug = ({logItem}) => (
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service debug">Kapacitor</div> <div className="logs-table--service debug">Kapacitor</div>
<div className="logs-table--columns"> <div className="logs-table--columns">
<div className="logs-table--key-values debug"> <div className="logs-table--key-values debug">DEBUG: {logItem.msg}</div>
DEBUG: {logItem.msg}
</div>
</div> </div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -1,23 +1,20 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogItemKapacitorError = ({logItem}) => const LogItemKapacitorError = ({logItem}) => (
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service error">Kapacitor</div> <div className="logs-table--service error">Kapacitor</div>
<div className="logs-table--columns"> <div className="logs-table--columns">
<div className="logs-table--key-values error"> <div className="logs-table--key-values error">ERROR: {logItem.msg}</div>
ERROR: {logItem.msg}
</div>
</div> </div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -10,26 +10,22 @@ const renderKeysAndValues = (object, name) => {
return ( return (
<div className="logs-table--column"> <div className="logs-table--column">
<h1> <h1>{`${sortedObjKeys.length} ${name}`}</h1>
{`${sortedObjKeys.length} ${name}`}
</h1>
<div className="logs-table--scrollbox"> <div className="logs-table--scrollbox">
{sortedObjKeys.map(objKey => {sortedObjKeys.map(objKey => (
<div key={objKey} className="logs-table--key-value"> <div key={objKey} className="logs-table--key-value">
{objKey}: <span>{object[objKey]}</span> {objKey}: <span>{object[objKey]}</span>
</div> </div>
)} ))}
</div> </div>
</div> </div>
) )
} }
const LogItemKapacitorPoint = ({logItem}) => const LogItemKapacitorPoint = ({logItem}) => (
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service">Kapacitor Point</div> <div className="logs-table--service">Kapacitor Point</div>
@ -39,6 +35,7 @@ const LogItemKapacitorPoint = ({logItem}) =>
</div> </div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -1,20 +1,17 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogItemSession = ({logItem}) => const LogItemSession = ({logItem}) => (
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--session"> <div className="logs-table--session">{logItem.msg}</div>
{logItem.msg}
</div>
</div> </div>
</div> </div>
)
const {shape, string} = PropTypes const {shape, string} = PropTypes

View File

@ -6,7 +6,7 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar'
const numLogsToRender = 200 const numLogsToRender = 200
const LogsTable = ({logs}) => const LogsTable = ({logs}) => (
<div className="logs-table"> <div className="logs-table">
<div className="logs-table--header"> <div className="logs-table--header">
{`${numLogsToRender} Most Recent Logs`} {`${numLogsToRender} Most Recent Logs`}
@ -20,6 +20,7 @@ const LogsTable = ({logs}) =>
.map(log => <LogsTableRow key={log.key} logItem={log} />)} .map(log => <LogsTableRow key={log.key} logItem={log} />)}
</FancyScrollbar> </FancyScrollbar>
</div> </div>
)
const {arrayOf, shape, string} = PropTypes const {arrayOf, shape, string} = PropTypes

View File

@ -36,18 +36,12 @@ const LogsTableRow = ({logItem}) => {
<div className="logs-table--row"> <div className="logs-table--row">
<div className="logs-table--divider"> <div className="logs-table--divider">
<div className={`logs-table--level ${logItem.lvl}`} /> <div className={`logs-table--level ${logItem.lvl}`} />
<div className="logs-table--timestamp"> <div className="logs-table--timestamp">{logItem.ts}</div>
{logItem.ts}
</div>
</div> </div>
<div className="logs-table--details"> <div className="logs-table--details">
<div className="logs-table--service"> <div className="logs-table--service">{logItem.service || '--'}</div>
{logItem.service || '--'}
</div>
<div className="logs-table--columns"> <div className="logs-table--columns">
<div className="logs-table--key-values"> <div className="logs-table--key-values">{logItem.msg || '--'}</div>
{logItem.msg || '--'}
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,7 @@
import React from 'react' import React from 'react'
import PropTypes from 'prop-types' import PropTypes from 'prop-types'
const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) => const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) => (
<ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite logs-toggle"> <ul className="nav nav-tablist nav-tablist-sm nav-tablist-malachite logs-toggle">
<li <li
className={areLogsVisible ? null : 'active'} className={areLogsVisible ? null : 'active'}
@ -16,6 +16,7 @@ const LogsToggle = ({areLogsVisible, onToggleLogsVisibility}) =>
Editor + Logs Editor + Logs
</li> </li>
</ul> </ul>
)
const {bool, func} = PropTypes const {bool, func} = PropTypes

View File

@ -12,7 +12,7 @@ const Relative = ({
onRuleTypeInputChange, onRuleTypeInputChange,
onDropdownChange, onDropdownChange,
rule: {values: {change, shift, operator, value}}, rule: {values: {change, shift, operator, value}},
}) => }) => (
<div className="rule-section--row rule-section--row-first rule-section--border-bottom"> <div className="rule-section--row rule-section--row-first rule-section--border-bottom">
<p>Send Alert when</p> <p>Send Alert when</p>
<Dropdown <Dropdown
@ -52,6 +52,7 @@ const Relative = ({
</form> </form>
{change === CHANGES[1] ? <p>%</p> : null} {change === CHANGES[1] ? <p>%</p> : null}
</div> </div>
)
const {shape, string, func} = PropTypes const {shape, string, func} = PropTypes

Some files were not shown because too many files have changed in this diff Show More