Merge remote-tracking branch 'origin/master' into feature/custom_user_links-1550
commit
f064342440
15
CHANGELOG.md
15
CHANGELOG.md
|
@ -1,11 +1,26 @@
|
|||
## v1.3.4.0 [unreleased]
|
||||
### Bug Fixes
|
||||
1. [#1612](https://github.com/influxdata/chronograf/pull/1612): Prevent users from being able to write to internal system databases
|
||||
1. [#1655](https://github.com/influxdata/chronograf/pull/1655): Add more than one color to Line+Stat graphs
|
||||
|
||||
### Features
|
||||
1. [#1645](https://github.com/influxdata/chronograf/pull/1645): Add Auth0 as a supported OAuth2 provider
|
||||
1. [#1660](https://github.com/influxdata/chronograf/pull/1660): Add ability to add custom links to User menu via server CLI or ENV vars
|
||||
|
||||
### UI Improvements
|
||||
1. [#1644](https://github.com/influxdata/chronograf/pull/1644): Redesign Alerts History table to have sticky headers
|
||||
1. [#1581](https://github.com/influxdata/chronograf/pull/1581): Refresh template variable values on dashboard page load
|
||||
1. [#1612](https://github.com/influxdata/chronograf/pull/1612): Prevent users from being able to write to internal system databases
|
||||
1. [#1655](https://github.com/influxdata/chronograf/pull/1655): Add version number item to the navbar
|
||||
1. [#1655](https://github.com/influxdata/chronograf/pull/1655): Redesign dashboards table and sort alphabetically by name
|
||||
1. [#1655](https://github.com/influxdata/chronograf/pull/1655): Redesign navbar to be consistent with navbar in Branding Documentation
|
||||
|
||||
## v1.3.3.3 [2017-06-21]
|
||||
### Bug Fixes
|
||||
1. [1651](https://github.com/influxdata/chronograf/pull/1651): Add back in x and y axes and revert some style changes on Line + Single Stat graphs
|
||||
|
||||
## v1.3.3.2 [2017-06-21]
|
||||
### Bug Fixes
|
||||
|
||||
## v1.3.3.3 [2017-06-21]
|
||||
### Bug Fixes
|
||||
|
|
|
@ -2,6 +2,10 @@ import React, {Component, PropTypes} from 'react'
|
|||
import _ from 'lodash'
|
||||
import {Link} from 'react-router'
|
||||
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
import {ALERTS_TABLE} from 'src/alerts/constants/tableSizing'
|
||||
|
||||
class AlertsTable extends Component {
|
||||
constructor(props) {
|
||||
super(props)
|
||||
|
@ -55,11 +59,11 @@ class AlertsTable extends Component {
|
|||
sortableClasses(key) {
|
||||
if (this.state.sortKey === key) {
|
||||
if (this.state.sortDirection === 'asc') {
|
||||
return 'sortable-header sorting-ascending'
|
||||
return 'alert-history-table--th sortable-header sorting-ascending'
|
||||
}
|
||||
return 'sortable-header sorting-descending'
|
||||
return 'alert-history-table--th sortable-header sorting-descending'
|
||||
}
|
||||
return 'sortable-header'
|
||||
return 'alert-history-table--th sortable-header'
|
||||
}
|
||||
|
||||
sort(alerts, key, direction) {
|
||||
|
@ -80,64 +84,93 @@ class AlertsTable extends Component {
|
|||
this.state.sortKey,
|
||||
this.state.sortDirection
|
||||
)
|
||||
const {colName, colLevel, colTime, colHost, colValue} = ALERTS_TABLE
|
||||
return this.props.alerts.length
|
||||
? <table className="table v-center table-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th
|
||||
? <div className="alert-history-table">
|
||||
<div className="alert-history-table--thead">
|
||||
<div
|
||||
onClick={() => this.changeSort('name')}
|
||||
className={this.sortableClasses('name')}
|
||||
style={{width: colName}}
|
||||
>
|
||||
Name
|
||||
</th>
|
||||
<th
|
||||
</div>
|
||||
<div
|
||||
onClick={() => this.changeSort('level')}
|
||||
className={this.sortableClasses('level')}
|
||||
style={{width: colLevel}}
|
||||
>
|
||||
Level
|
||||
</th>
|
||||
<th
|
||||
</div>
|
||||
<div
|
||||
onClick={() => this.changeSort('time')}
|
||||
className={this.sortableClasses('time')}
|
||||
style={{width: colTime}}
|
||||
>
|
||||
Time
|
||||
</th>
|
||||
<th
|
||||
</div>
|
||||
<div
|
||||
onClick={() => this.changeSort('host')}
|
||||
className={this.sortableClasses('host')}
|
||||
style={{width: colHost}}
|
||||
>
|
||||
Host
|
||||
</th>
|
||||
<th
|
||||
</div>
|
||||
<div
|
||||
onClick={() => this.changeSort('value')}
|
||||
className={this.sortableClasses('value')}
|
||||
style={{width: colValue}}
|
||||
>
|
||||
Value
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
</div>
|
||||
</div>
|
||||
<FancyScrollbar
|
||||
className="alert-history-table--tbody"
|
||||
autoHide={false}
|
||||
>
|
||||
{alerts.map(({name, level, time, host, value}) => {
|
||||
return (
|
||||
<tr key={`${name}-${level}-${time}-${host}-${value}`}>
|
||||
<td className="monotype">{name}</td>
|
||||
<td className={`monotype alert-level-${level.toLowerCase()}`}>
|
||||
<div
|
||||
className="alert-history-table--tr"
|
||||
key={`${name}-${level}-${time}-${host}-${value}`}
|
||||
>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colName}}
|
||||
>
|
||||
{name}
|
||||
</div>
|
||||
<div
|
||||
className={`alert-history-table--td alert-level-${level.toLowerCase()}`}
|
||||
style={{width: colLevel}}
|
||||
>
|
||||
{level}
|
||||
</td>
|
||||
<td className="monotype">
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colTime}}
|
||||
>
|
||||
{new Date(Number(time)).toISOString()}
|
||||
</td>
|
||||
<td className="monotype">
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colHost}}
|
||||
>
|
||||
<Link to={`/sources/${id}/hosts/${host}`}>
|
||||
{host}
|
||||
</Link>
|
||||
</td>
|
||||
<td className="monotype">{value}</td>
|
||||
</tr>
|
||||
</div>
|
||||
<div
|
||||
className="alert-history-table--td"
|
||||
style={{width: colValue}}
|
||||
>
|
||||
{value}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</tbody>
|
||||
</table>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
: this.renderTableEmpty()
|
||||
}
|
||||
|
||||
|
@ -239,7 +272,7 @@ class SearchBar extends Component {
|
|||
<input
|
||||
type="text"
|
||||
className="form-control"
|
||||
placeholder="Filter Alerts by Name..."
|
||||
placeholder="Filter Alerts..."
|
||||
onChange={this.handleChange}
|
||||
value={this.state.searchTerm}
|
||||
/>
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
export const ALERTS_TABLE = {
|
||||
colName: '15%',
|
||||
colLevel: '10%',
|
||||
colTime: '25%',
|
||||
colHost: '25%',
|
||||
colValue: '25%',
|
||||
}
|
|
@ -4,7 +4,6 @@ import SourceIndicator from 'shared/components/SourceIndicator'
|
|||
import AlertsTable from 'src/alerts/components/AlertsTable'
|
||||
import NoKapacitorError from 'shared/components/NoKapacitorError'
|
||||
import CustomTimeRangeDropdown from 'shared/components/CustomTimeRangeDropdown'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
import {getAlerts} from 'src/alerts/apis'
|
||||
import AJAX from 'utils/ajax'
|
||||
|
@ -160,10 +159,8 @@ class AlertsApp extends Component {
|
|||
}
|
||||
|
||||
return isWidget
|
||||
? <FancyScrollbar autoHide={false}>
|
||||
{this.renderSubComponents()}
|
||||
</FancyScrollbar>
|
||||
: <div className="page">
|
||||
? this.renderSubComponents()
|
||||
: <div className="page alert-history-page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
|
@ -183,7 +180,7 @@ class AlertsApp extends Component {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<FancyScrollbar className="page-contents">
|
||||
<div className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
|
@ -191,7 +188,7 @@ class AlertsApp extends Component {
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||
|
||||
const DashboardsHeader = ({sourceName}) => {
|
||||
return (
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">
|
||||
Dashboards
|
||||
</h1>
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<SourceIndicator sourceName={sourceName} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const {string} = PropTypes
|
||||
|
||||
DashboardsHeader.propTypes = {
|
||||
sourceName: string.isRequired,
|
||||
}
|
||||
|
||||
export default DashboardsHeader
|
|
@ -0,0 +1,61 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
|
||||
import DashboardsTable from 'src/dashboards/components/DashboardsTable'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
|
||||
const DashboardsPageContents = ({
|
||||
dashboards,
|
||||
onDeleteDashboard,
|
||||
onCreateDashboard,
|
||||
dashboardLink,
|
||||
}) => {
|
||||
let tableHeader
|
||||
if (dashboards === null) {
|
||||
tableHeader = 'Loading Dashboards...'
|
||||
} else if (dashboards.length === 1) {
|
||||
tableHeader = '1 Dashboard'
|
||||
} else {
|
||||
tableHeader = `${dashboards.length} Dashboards`
|
||||
}
|
||||
|
||||
return (
|
||||
<FancyScrollbar className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="panel panel-minimal">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<h2 className="panel-title">{tableHeader}</h2>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={onCreateDashboard}
|
||||
>
|
||||
Create Dashboard
|
||||
</button>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
<DashboardsTable
|
||||
dashboards={dashboards}
|
||||
onDeleteDashboard={onDeleteDashboard}
|
||||
onCreateDashboard={onCreateDashboard}
|
||||
dashboardLink={dashboardLink}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
)
|
||||
}
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
DashboardsPageContents.propTypes = {
|
||||
dashboards: arrayOf(shape()),
|
||||
onDeleteDashboard: func.isRequired,
|
||||
onCreateDashboard: func.isRequired,
|
||||
dashboardLink: string.isRequired,
|
||||
}
|
||||
|
||||
export default DashboardsPageContents
|
|
@ -0,0 +1,73 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {Link} from 'react-router'
|
||||
import _ from 'lodash'
|
||||
|
||||
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
|
||||
|
||||
const DashboardsTable = ({
|
||||
dashboards,
|
||||
onDeleteDashboard,
|
||||
onCreateDashboard,
|
||||
dashboardLink,
|
||||
}) => {
|
||||
return dashboards && dashboards.length
|
||||
? <table className="table v-center admin-table table-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Template Variables</th>
|
||||
<th />
|
||||
</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>
|
||||
<DeleteConfirmTableCell
|
||||
onDelete={onDeleteDashboard}
|
||||
item={dashboard}
|
||||
buttonSize="btn-xs"
|
||||
/>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
: <div className="generic-empty-state">
|
||||
<h4 style={{marginTop: '90px'}}>
|
||||
Looks like you dont have any dashboards
|
||||
</h4>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={onCreateDashboard}
|
||||
style={{marginBottom: '90px'}}
|
||||
>
|
||||
Create Dashboard
|
||||
</button>
|
||||
</div>
|
||||
}
|
||||
|
||||
const {arrayOf, func, shape, string} = PropTypes
|
||||
|
||||
DashboardsTable.propTypes = {
|
||||
dashboards: arrayOf(shape()),
|
||||
onDeleteDashboard: func.isRequired,
|
||||
onCreateDashboard: func.isRequired,
|
||||
dashboardLink: string.isRequired,
|
||||
}
|
||||
|
||||
export default DashboardsTable
|
|
@ -1,11 +1,10 @@
|
|||
import React, {PropTypes} from 'react'
|
||||
import {Link, withRouter} from 'react-router'
|
||||
import {withRouter} from 'react-router'
|
||||
import {connect} from 'react-redux'
|
||||
import {bindActionCreators} from 'redux'
|
||||
|
||||
import SourceIndicator from 'shared/components/SourceIndicator'
|
||||
import DeleteConfirmTableCell from 'shared/components/DeleteConfirmTableCell'
|
||||
import FancyScrollbar from 'shared/components/FancyScrollbar'
|
||||
import DashboardsHeader from 'src/dashboards/components/DashboardsHeader'
|
||||
import DashboardsContents from 'src/dashboards/components/DashboardsPageContents'
|
||||
|
||||
import {createDashboard} from 'src/dashboards/apis'
|
||||
import {getDashboardsAsync, deleteDashboardAsync} from 'src/dashboards/actions'
|
||||
|
@ -50,89 +49,16 @@ const DashboardsPage = React.createClass({
|
|||
render() {
|
||||
const {dashboards} = this.props
|
||||
const dashboardLink = `/sources/${this.props.source.id}`
|
||||
let tableHeader
|
||||
if (dashboards === null) {
|
||||
tableHeader = 'Loading Dashboards...'
|
||||
} else if (dashboards.length === 1) {
|
||||
tableHeader = '1 Dashboard'
|
||||
} else {
|
||||
tableHeader = `${dashboards.length} Dashboards`
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="page">
|
||||
<div className="page-header">
|
||||
<div className="page-header__container">
|
||||
<div className="page-header__left">
|
||||
<h1 className="page-header__title">
|
||||
Dashboards
|
||||
</h1>
|
||||
</div>
|
||||
<div className="page-header__right">
|
||||
<SourceIndicator sourceName={this.props.source.name} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<FancyScrollbar className="page-contents">
|
||||
<div className="container-fluid">
|
||||
<div className="row">
|
||||
<div className="col-md-12">
|
||||
<div className="panel panel-minimal">
|
||||
<div className="panel-heading u-flex u-ai-center u-jc-space-between">
|
||||
<h2 className="panel-title">{tableHeader}</h2>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={this.handleCreateDashbord}
|
||||
>
|
||||
Create Dashboard
|
||||
</button>
|
||||
</div>
|
||||
<div className="panel-body">
|
||||
{dashboards && dashboards.length
|
||||
? <table className="table v-center admin-table table-highlight">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th />
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{dashboards.map(dashboard =>
|
||||
<tr key={dashboard.id} className="">
|
||||
<td>
|
||||
<Link
|
||||
to={`${dashboardLink}/dashboards/${dashboard.id}`}
|
||||
>
|
||||
{dashboard.name}
|
||||
</Link>
|
||||
</td>
|
||||
<DeleteConfirmTableCell
|
||||
onDelete={this.handleDeleteDashboard}
|
||||
item={dashboard}
|
||||
buttonSize="btn-xs"
|
||||
<DashboardsHeader sourceName={this.props.source.name} />
|
||||
<DashboardsContents
|
||||
dashboardLink={dashboardLink}
|
||||
dashboards={dashboards}
|
||||
onDeleteDashboard={this.handleDeleteDashboard}
|
||||
onCreateDashboard={this.handleCreateDashbord}
|
||||
/>
|
||||
</tr>
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
: <div className="generic-empty-state">
|
||||
<h4 style={{marginTop: '90px'}}>
|
||||
Looks like you dont have any dashboards
|
||||
</h4>
|
||||
<button
|
||||
className="btn btn-sm btn-primary"
|
||||
onClick={this.handleCreateDashbord}
|
||||
style={{marginBottom: '90px'}}
|
||||
>
|
||||
Create Dashboard
|
||||
</button>
|
||||
</div>}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</FancyScrollbar>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
|
|
@ -43,12 +43,17 @@ class DatabaseDropdown extends Component {
|
|||
const proxy = source.links.proxy
|
||||
try {
|
||||
const {data} = await showDatabases(proxy)
|
||||
const {databases} = showDatabasesParser(data)
|
||||
const {databases, errors} = showDatabasesParser(data)
|
||||
if (errors.length > 0) {
|
||||
throw errors[0] // only one error can come back from this, but it's returned as an array
|
||||
}
|
||||
|
||||
this.setState({databases})
|
||||
const selectedDatabaseText = databases.includes(database)
|
||||
const nonSystemDatabases = databases.filter(name => name !== '_internal')
|
||||
|
||||
this.setState({databases: nonSystemDatabases})
|
||||
const selectedDatabaseText = nonSystemDatabases.includes(database)
|
||||
? database
|
||||
: databases[0] || 'No databases'
|
||||
: nonSystemDatabases[0] || 'No databases'
|
||||
onSelectDatabase({text: selectedDatabaseText})
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
|
|
@ -33,6 +33,7 @@ class FancyScrollbar extends Component {
|
|||
<div {...props} className="fancy-scroll--thumb-h" />}
|
||||
renderThumbVertical={props =>
|
||||
<div {...props} className="fancy-scroll--thumb-v" />}
|
||||
renderView={props => <div {...props} className="fancy-scroll--view" />}
|
||||
>
|
||||
{children}
|
||||
</Scrollbars>
|
||||
|
|
|
@ -131,7 +131,17 @@ export default React.createClass({
|
|||
strokeWidth: 1.5,
|
||||
},
|
||||
}
|
||||
const singleStatLineColor = ['#7A65F2']
|
||||
const singleStatLineColors = [
|
||||
'#7A65F2',
|
||||
'#FFD255',
|
||||
'#7CE490',
|
||||
'#F95F53',
|
||||
'#4591ED',
|
||||
'#B1B6FF',
|
||||
'#FFF6B8',
|
||||
'#C6FFD0',
|
||||
'#6BDFFF',
|
||||
]
|
||||
|
||||
let roundedValue
|
||||
if (showSingleStat) {
|
||||
|
@ -152,7 +162,7 @@ export default React.createClass({
|
|||
<Dygraph
|
||||
containerStyle={{width: '100%', height: '100%'}}
|
||||
overrideLineColors={
|
||||
showSingleStat ? singleStatLineColor : overrideLineColors
|
||||
showSingleStat ? singleStatLineColors : overrideLineColors
|
||||
}
|
||||
isGraphFilled={showSingleStat ? false : isGraphFilled}
|
||||
isBarGraph={isBarGraph}
|
||||
|
|
|
@ -19,14 +19,14 @@ const NavListItem = React.createClass({
|
|||
|
||||
return useAnchor
|
||||
? <a
|
||||
className={classnames('sidebar__menu-item', {active: isActive})}
|
||||
className={classnames('sidebar-menu--item', {active: isActive})}
|
||||
href={link}
|
||||
target={isExternal ? '_blank' : '_self'}
|
||||
>
|
||||
{children}
|
||||
</a>
|
||||
: <Link
|
||||
className={classnames('sidebar__menu-item', {active: isActive})}
|
||||
className={classnames('sidebar-menu--item', {active: isActive})}
|
||||
to={link}
|
||||
>
|
||||
{children}
|
||||
|
@ -46,11 +46,11 @@ const NavHeader = React.createClass({
|
|||
// Some nav items, such as Logout, need to hit an external link rather
|
||||
// than simply route to an internal page. Anchor tags serve that purpose.
|
||||
return useAnchor
|
||||
? <a className="sidebar__menu-route" href={link}>
|
||||
<h3 className="sidebar__menu-heading">{title}</h3>
|
||||
? <a className="sidebar-menu--heading" href={link}>
|
||||
{title}
|
||||
</a>
|
||||
: <Link className="sidebar__menu-route" to={link}>
|
||||
<h3 className="sidebar__menu-heading">{title}</h3>
|
||||
: <Link className="sidebar-menu--heading" to={link}>
|
||||
{title}
|
||||
</Link>
|
||||
},
|
||||
})
|
||||
|
@ -62,11 +62,10 @@ const NavBlock = React.createClass({
|
|||
icon: string.isRequired,
|
||||
location: string,
|
||||
className: string,
|
||||
wrapperClassName: string,
|
||||
},
|
||||
|
||||
render() {
|
||||
const {location, className, wrapperClassName} = this.props
|
||||
const {location, className} = this.props
|
||||
|
||||
const isActive = React.Children.toArray(this.props.children).find(child => {
|
||||
return location.startsWith(child.props.link)
|
||||
|
@ -82,34 +81,30 @@ const NavBlock = React.createClass({
|
|||
|
||||
return (
|
||||
<div
|
||||
className={classnames('sidebar__square', className, {active: isActive})}
|
||||
className={classnames('sidebar--item', className, {active: isActive})}
|
||||
>
|
||||
{this.renderLink()}
|
||||
<div className={wrapperClassName || 'sidebar__menu-wrapper'}>
|
||||
<div className="sidebar__menu">
|
||||
{this.renderSquare()}
|
||||
<div className="sidebar-menu">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
|
||||
renderLink() {
|
||||
renderSquare() {
|
||||
const {link, icon} = this.props
|
||||
|
||||
if (!link) {
|
||||
return (
|
||||
<div className="sidebar__icon">
|
||||
<span className={`icon ${icon}`} />
|
||||
<div className="sidebar--square">
|
||||
<div className={`sidebar--icon icon ${icon}`} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Link className="sidebar__menu-route" to={link}>
|
||||
<div className="sidebar__icon">
|
||||
<span className={`icon ${icon}`} />
|
||||
</div>
|
||||
<Link className="sidebar--square" to={link}>
|
||||
<div className={`sidebar--icon icon ${icon}`} />
|
||||
</Link>
|
||||
)
|
||||
},
|
||||
|
@ -131,7 +126,7 @@ const NavBar = React.createClass({
|
|||
|
||||
return child
|
||||
})
|
||||
return <aside className="sidebar">{children}</aside>
|
||||
return <nav className="sidebar">{children}</nav>
|
||||
},
|
||||
})
|
||||
|
||||
|
|
|
@ -13,6 +13,8 @@ import {DEFAULT_HOME_PAGE} from 'shared/constants'
|
|||
|
||||
const {arrayOf, bool, shape, string} = PropTypes
|
||||
|
||||
const V_NUMBER = VERSION // eslint-disable-line no-undef
|
||||
|
||||
const SideNav = React.createClass({
|
||||
propTypes: {
|
||||
params: shape({
|
||||
|
@ -45,7 +47,11 @@ const SideNav = React.createClass({
|
|||
</NavListItem>
|
||||
)
|
||||
.concat(
|
||||
<NavListItem useAnchor={true} link={logoutLink}>
|
||||
<NavListItem
|
||||
key={customLinks.length + 1}
|
||||
useAnchor={true}
|
||||
link={logoutLink}
|
||||
>
|
||||
Logout
|
||||
</NavListItem>
|
||||
)
|
||||
|
@ -68,12 +74,14 @@ const SideNav = React.createClass({
|
|||
return isHidden
|
||||
? null
|
||||
: <NavBar location={location}>
|
||||
<div className="sidebar--item">
|
||||
<Link
|
||||
to={`${sourcePrefix}/${DEFAULT_HOME_PAGE}`}
|
||||
className="sidebar__logo"
|
||||
className="sidebar--square sidebar--logo"
|
||||
>
|
||||
<span className="icon cubo-uniform" />
|
||||
<span className="sidebar--icon icon cubo-uniform" />
|
||||
</Link>
|
||||
</div>
|
||||
<NavBlock icon="cubo-node" link={`${sourcePrefix}/hosts`}>
|
||||
<NavHeader link={`${sourcePrefix}/hosts`} title="Host List" />
|
||||
</NavBlock>
|
||||
|
@ -108,8 +116,20 @@ const SideNav = React.createClass({
|
|||
title="Configuration"
|
||||
/>
|
||||
</NavBlock>
|
||||
<div className="sidebar--bottom">
|
||||
<div className="sidebar--item">
|
||||
<div className="sidebar--square">
|
||||
<span className="sidebar--icon icon zap" />
|
||||
</div>
|
||||
<div className="sidebar-menu">
|
||||
<div className="sidebar-menu--heading">
|
||||
Version: {V_NUMBER}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{isUsingAuth
|
||||
? <NavBlock icon="user" className="sidebar__square-last">
|
||||
? <NavBlock icon="user" className="sidebar--item-last">
|
||||
{customLinks
|
||||
? this.renderUserMenuBlockWithCustomLinks(
|
||||
customLinks,
|
||||
|
|
|
@ -55,7 +55,11 @@ ul.dropdown-menu {
|
|||
.fancy-scroll--thumb-v { @include gradient-v($c-neutrino,$c-laser); }
|
||||
}
|
||||
|
||||
/* Hacky Fix to make this work in Safari */
|
||||
/* Hacky fix to hide strange white lines in chrome */
|
||||
.fancy-scroll--view {
|
||||
margin-right: -16px !important
|
||||
}
|
||||
/* Hacky Fix to make fancy scrollbars work in Safari */
|
||||
.query-builder--list {
|
||||
position: relative;
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
}
|
||||
.chronograf-root > .page-spinner {
|
||||
// Center the spinner based on the main content window, not the entire screen
|
||||
left: calc(50% + #{$sidebar-width});
|
||||
left: calc(50% + #{$sidebar--width});
|
||||
}
|
||||
|
||||
@keyframes pageSpinner {
|
||||
|
|
|
@ -36,7 +36,6 @@ $breakpoint-c: 2100px;
|
|||
.query-builder--heading {
|
||||
font-size: 17px;
|
||||
font-weight: 400;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.query-maker .multi-select-dropdown .dropdown-toggle {
|
||||
width: 140px;
|
||||
|
|
|
@ -50,7 +50,8 @@
|
|||
Sortable Tables
|
||||
----------------------------------------------
|
||||
*/
|
||||
table.table thead th.sortable-header {
|
||||
table.table thead th.sortable-header,
|
||||
.alert-history-table--th.sortable-header {
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease;
|
||||
|
@ -172,15 +173,84 @@ $table-tab-scrollbar-height: 6px;
|
|||
.table.table-highlight > tbody > tr.highlight {
|
||||
background-color: $g4-onyx;
|
||||
}
|
||||
|
||||
/*
|
||||
Responsive Tables
|
||||
Alert History "Page"
|
||||
----------------------------------------------
|
||||
*/
|
||||
.alert-history-page {
|
||||
.page-contents > .container-fluid,
|
||||
.page-contents > .container-fluid > .row,
|
||||
.page-contents > .container-fluid > .row > .col-md-12,
|
||||
.page-contents > .container-fluid > .row > .col-md-12 > .panel {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.col-md-12 > .panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
> .panel-body {flex: 1 0 0;}
|
||||
.generic-empty-state {height: 100%;}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Misc
|
||||
----------------------------------------------
|
||||
*/
|
||||
.table .empty-string {
|
||||
font-weight: 500;
|
||||
color: $g8-storm;
|
||||
font-style: italic;
|
||||
}
|
||||
.table .table--temp-var {
|
||||
color: $c-comet;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/*
|
||||
Alert History "Table"
|
||||
----------------------------------------------
|
||||
*/
|
||||
|
||||
@media screen and (max-width: 767px) {
|
||||
.table-responsive {
|
||||
border-radius: 3px;
|
||||
border-color: $g5-pepper;
|
||||
@include custom-scrollbar($g5-pepper, $c-pool);
|
||||
.alert-history-table {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
}
|
||||
.alert-history-table--thead {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
border-bottom: 2px solid $g5-pepper;
|
||||
}
|
||||
.alert-history-table--th {
|
||||
@include no-user-select();
|
||||
padding: 8px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
color: $g17-whisper;
|
||||
}
|
||||
.alert-history-table--tbody {
|
||||
flex: 1 0 0;
|
||||
width: 100%;
|
||||
}
|
||||
.alert-history-table--tr {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
&:hover {
|
||||
background-color: $g4-onyx;
|
||||
}
|
||||
}
|
||||
.alert-history-table--td {
|
||||
font-size: 12px;
|
||||
font-family: $code-font;
|
||||
font-weight: 500;
|
||||
padding: 4px 8px;
|
||||
line-height: 1.42857143em;
|
||||
color: $g13-mist;
|
||||
white-space: pre-wrap;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
|
|
@ -19,5 +19,5 @@
|
|||
|
||||
// Make Overlay Technology full screen
|
||||
.overlay-technology {
|
||||
left: -($sidebar-width) !important;
|
||||
left: -($sidebar--width) !important;
|
||||
}
|
|
@ -3,293 +3,177 @@
|
|||
----------------------------------------------
|
||||
*/
|
||||
|
||||
$sidebar-width: 60px;
|
||||
$sidebar-menu-gutter: 30px;
|
||||
$sidebar-menu-indent: 13px;
|
||||
$sidebar--width: 60px;
|
||||
|
||||
$sidebar-hover: $g8-storm;
|
||||
$sidebar-item-hover: $g7-graphite;
|
||||
$sidebar-lighter: $g8-storm;
|
||||
$sidebar-light: $g7-graphite;
|
||||
$sidebar-dark: $g4-onyx;
|
||||
$sidebar-icon: $g11-sidewalk;
|
||||
$sidebar-text: $g13-mist;
|
||||
$sidebar-icon-hover: $g20-white;
|
||||
$sidebar-icon-active: $g20-white;
|
||||
$sidebar-active-bg: $c-pool;
|
||||
$sidebar-active-accent: $c-laser;
|
||||
$sidebar-logo-bg: $g17-whisper;
|
||||
$sidebar-logo-color: $g8-storm;
|
||||
$sidebar--gradient-start: $g7-graphite;
|
||||
$sidebar--gradient-end: $g4-onyx;
|
||||
|
||||
$sidebar--logo-bg: $g19-ghost;
|
||||
$sidebar--logo-color: $c-pool;
|
||||
$sidebar--logo-bg-hover: $g20-white;
|
||||
$sidebar--logo-color-hover: $c-laser;
|
||||
|
||||
$sidebar--item-bg: transparent;
|
||||
$sidebar--item-bg-hover: $c-pool;
|
||||
$sidebar--item-bg-active: $g4-onyx;
|
||||
$sidebar--icon: $g11-sidewalk;
|
||||
$sidebar--icon-hover: $g20-white;
|
||||
$sidebar--icon-active: $g20-white;
|
||||
|
||||
$sidebar-menu--bg: $c-pool;
|
||||
$sidebar-menu--bg-accent: $c-comet;
|
||||
$sidebar-menu--item-bg: $c-ocean;
|
||||
$sidebar-menu--item-bg-accent: $c-star;
|
||||
$sidebar-menu--item-bg-hover: $c-laser;
|
||||
$sidebar-menu--item-bg-hover-accent: $c-potassium;
|
||||
$sidebar-menu--item-text: $c-neutrino;
|
||||
$sidebar-menu--item-text-hover: $g20-white;
|
||||
$sidebar-menu--item-text-active: $g20-white;
|
||||
$sidebar-menu--gutter: 18px;
|
||||
|
||||
// Sidebar styles
|
||||
.sidebar {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: $sidebar-width;
|
||||
@include gradient-v($sidebar-light,$sidebar-dark);
|
||||
|
||||
&__logo {
|
||||
width: $sidebar-width;
|
||||
height: $sidebar-width;
|
||||
background-color: $sidebar-logo-bg;
|
||||
position: relative;
|
||||
color: $sidebar-logo-color;
|
||||
|
||||
span.icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
font-size: $sidebar-width * 0.4222;
|
||||
}
|
||||
}
|
||||
|
||||
&__icon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transition:
|
||||
background-color 0.25s ease,
|
||||
color 0.25s ease;
|
||||
color: $sidebar-icon;
|
||||
|
||||
span.icon {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
font-size: $sidebar-width * 0.4222;
|
||||
}
|
||||
}
|
||||
|
||||
&__square {
|
||||
z-index: 999;
|
||||
width: $sidebar-width;
|
||||
height: $sidebar-width;
|
||||
background-color: transparent;
|
||||
position: relative;
|
||||
color: $sidebar-icon;
|
||||
|
||||
/* Here for specificity issues */
|
||||
.sidebar__icon {
|
||||
&:link,
|
||||
&:active,
|
||||
&:visited {
|
||||
transition:
|
||||
background-color 0.25s ease,
|
||||
color 0.25s ease;
|
||||
color: $sidebar-icon;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.sidebar__icon {
|
||||
color: $sidebar-icon-hover;
|
||||
background-color: $sidebar-hover;
|
||||
}
|
||||
|
||||
/* Show menu on hover */
|
||||
.sidebar__menu-wrapper,
|
||||
.sidebar__menu-wrapper-bottom {
|
||||
visibility: visible;
|
||||
}
|
||||
.sidebar__menu {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Active Indicator */
|
||||
&:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
width: 4px;
|
||||
height: 100%;
|
||||
transform: translateY(-50%) scale(1,0);
|
||||
background-color: $c-pool;
|
||||
z-index: 999;
|
||||
backface-visibility: hidden;
|
||||
transition:
|
||||
transform 0.4s ease;
|
||||
}
|
||||
|
||||
/* Active State Styles */
|
||||
&.active {
|
||||
&:after {
|
||||
transform: translateY(-50%) scale(1,1);
|
||||
transition:
|
||||
transform 0.31s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
}
|
||||
|
||||
.sidebar__icon {
|
||||
color: $sidebar-icon-active;
|
||||
|
||||
&:link,
|
||||
&:active,
|
||||
&:visited,
|
||||
&:hover {
|
||||
color: $sidebar-icon-active;
|
||||
}
|
||||
}
|
||||
}
|
||||
&-last {
|
||||
width: $sidebar--width;
|
||||
@include gradient-v($sidebar--gradient-start,$sidebar--gradient-end);
|
||||
}
|
||||
.sidebar--bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
|
||||
.sidebar__menu-wrapper {
|
||||
bottom: 0;
|
||||
top: initial;
|
||||
}
|
||||
.sidebar__menu-route {
|
||||
order: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__menu {
|
||||
border-radius: 0 $radius $radius 0;
|
||||
background: $sidebar-hover;
|
||||
opacity: 0;
|
||||
transition: opacity 0.25s ease;
|
||||
left: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
list-style: none;
|
||||
justify-content: flex-end;
|
||||
width: $sidebar--width;
|
||||
}
|
||||
|
||||
&-wrapper {
|
||||
/*
|
||||
Sidebar Items
|
||||
----------------------------------------------
|
||||
*/
|
||||
.sidebar--item {
|
||||
width: $sidebar--width;
|
||||
height: $sidebar--width;
|
||||
position: relative;
|
||||
}
|
||||
.sidebar--square {
|
||||
display: block;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-color: $sidebar--item-bg;
|
||||
transition: none;
|
||||
}
|
||||
.sidebar--icon {
|
||||
position: absolute;
|
||||
color: $sidebar--icon;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%,-50%);
|
||||
font-size: $sidebar--width * 0.4222;
|
||||
transition:
|
||||
text-shadow 0.4s ease;
|
||||
}
|
||||
/*
|
||||
Sidebar Item Active State
|
||||
*/
|
||||
.sidebar--item.active {
|
||||
.sidebar--square {background-color: $sidebar--item-bg-active;}
|
||||
.sidebar--icon {
|
||||
color: $sidebar--icon-active;
|
||||
text-shadow:
|
||||
0 0 9px $c-laser,
|
||||
0 0 15px $c-ocean,
|
||||
0 0 20px $c-amethyst;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Sidebar Item Hover State
|
||||
*/
|
||||
.sidebar--item:hover {
|
||||
cursor: pointer;
|
||||
|
||||
.sidebar--square {background-color: $sidebar--item-bg-hover;}
|
||||
.sidebar--icon {color: $sidebar--icon-hover;}
|
||||
.sidebar-menu {display: flex;}
|
||||
}
|
||||
.sidebar--item.active:hover .sidebar--icon {
|
||||
text-shadow:
|
||||
0 0 9px $c-yeti,
|
||||
0 0 15px $c-hydrogen,
|
||||
0 0 20px $c-laser;
|
||||
}
|
||||
/*
|
||||
Sidebar Logo Square
|
||||
*/
|
||||
.sidebar--square.sidebar--logo {
|
||||
background-color: $sidebar--logo-bg;
|
||||
.sidebar--icon {color: $sidebar--logo-color;}
|
||||
}
|
||||
.sidebar--item:hover .sidebar--square.sidebar--logo {
|
||||
background-color: $sidebar--logo-bg-hover;
|
||||
.sidebar--icon {color: $sidebar--logo-color-hover;}
|
||||
}
|
||||
|
||||
/*
|
||||
Sidebar Sub Menus
|
||||
----------------------------------------------
|
||||
*/
|
||||
.sidebar-menu {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 100%;
|
||||
z-index: 999;
|
||||
visibility: hidden;
|
||||
display: flex;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
&-wrapper-bottom {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 100%;
|
||||
z-index: 999;
|
||||
visibility: hidden;
|
||||
display: flex;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
}
|
||||
|
||||
&__menu-heading,
|
||||
&__menu-item {
|
||||
border-radius: 0 $radius $radius 0;
|
||||
@include gradient-h($sidebar-menu--bg,$sidebar-menu--bg-accent);
|
||||
transition: opacity 0.25s ease;
|
||||
display: none;
|
||||
flex-direction: column;
|
||||
}
|
||||
.sidebar-menu--heading,
|
||||
.sidebar-menu--item {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
margin: 0;
|
||||
display: block;
|
||||
@include no-user-select();
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
&__menu-item {
|
||||
color: $sidebar-text;
|
||||
}
|
||||
.sidebar-menu--item:link,
|
||||
.sidebar-menu--item:active,
|
||||
.sidebar-menu--item:visited {
|
||||
color: $sidebar-menu--item-text;
|
||||
font-size: 15px;
|
||||
line-height: 22px;
|
||||
font-weight: 500;
|
||||
position: relative;
|
||||
padding: 4px $sidebar-menu-gutter;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease;
|
||||
|
||||
// Overriding link styles
|
||||
&:link,
|
||||
&:active,
|
||||
&:visited {
|
||||
color: $sidebar-text;
|
||||
font-weight: 500;
|
||||
transition:
|
||||
color 0.25s ease,
|
||||
background-color 0.25s ease;
|
||||
}
|
||||
|
||||
// Rounding top outside corner to match container
|
||||
&:first-child {
|
||||
border-top-right-radius: $radius;
|
||||
}
|
||||
padding: 4px $sidebar-menu--gutter;
|
||||
transition: none;
|
||||
|
||||
// Rounding bottom outside corner of match container
|
||||
&:last-child {
|
||||
border-bottom-right-radius: $radius;
|
||||
}
|
||||
|
||||
// Used for sub-navigation
|
||||
small {
|
||||
font-size: 13px;
|
||||
border-left: 2px solid $sidebar-icon;
|
||||
padding-left: $sidebar-menu-indent;
|
||||
display: inline-block;
|
||||
transition: border-color 0.25s ease;
|
||||
}
|
||||
// Invisible until item is active, indicates active item
|
||||
&:after {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: $sidebar-menu-gutter /2;
|
||||
content: '';
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
background-color: transparent;
|
||||
transform: translate(-50%,-50%);
|
||||
}
|
||||
&:hover {
|
||||
background-color: $sidebar-item-hover;
|
||||
color: $sidebar-icon-hover;
|
||||
|
||||
small {
|
||||
border-color: $sidebar-icon-hover;
|
||||
}
|
||||
// Emphasize rename icon on hover
|
||||
.js-open-rename-cluster-modal {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
&.active {
|
||||
@include gradient-h($sidebar-active-bg,$sidebar-active-accent);
|
||||
color: $sidebar-icon-hover;
|
||||
|
||||
&:link,
|
||||
&:active,
|
||||
&:visited {
|
||||
color: $sidebar-icon-hover;
|
||||
}
|
||||
|
||||
// Show indicator
|
||||
&:after {
|
||||
background-color: $sidebar-icon-active;
|
||||
}
|
||||
|
||||
// Show rename icon when active
|
||||
.js-open-rename-cluster-modal {
|
||||
background-color: $c-laser;
|
||||
opacity: 1;
|
||||
|
||||
&:hover {
|
||||
background-color: $c-hydrogen;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__menu-heading {
|
||||
color: $g20-white;
|
||||
height: $sidebar-width;
|
||||
line-height: $sidebar-width;
|
||||
font-size: 17px;
|
||||
text-transform: uppercase;
|
||||
font-weight: 400;
|
||||
padding: 0px $sidebar-menu-gutter;
|
||||
}
|
||||
&:last-child {border-bottom-right-radius: $radius;}
|
||||
}
|
||||
.sidebar-menu--item.active:link,
|
||||
.sidebar-menu--item.active:active,
|
||||
.sidebar-menu--item.active:visited {
|
||||
@include gradient-h($sidebar-menu--item-bg,$sidebar-menu--item-bg-accent);
|
||||
color: $sidebar-menu--item-text-active;
|
||||
}
|
||||
.sidebar-menu--item:hover,
|
||||
.sidebar-menu--item.active:hover {
|
||||
@include gradient-h($sidebar-menu--item-bg-hover,$sidebar-menu--item-bg-hover-accent);
|
||||
color: $sidebar-menu--item-text-hover;
|
||||
}
|
||||
.sidebar-menu--heading,
|
||||
.sidebar-menu--heading:link,
|
||||
.sidebar-menu--heading:visited,
|
||||
.sidebar-menu--heading:active,
|
||||
.sidebar-menu--heading:hover, {
|
||||
color: $g20-white;
|
||||
height: $sidebar--width;
|
||||
line-height: $sidebar--width;
|
||||
font-size: 19px;
|
||||
font-weight: 400;
|
||||
padding: 0px $sidebar-menu--gutter;
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
overflow: auto;
|
||||
@include custom-scrollbar($g3-castle, $c-pool);
|
||||
@include gradient-v($g3-castle, $g0-obsidian);
|
||||
padding: $sidebar-width;
|
||||
padding: $sidebar--width;
|
||||
}
|
||||
.auth-image {
|
||||
background-image: url(assets/images/auth-bg.svg);
|
||||
|
@ -47,8 +47,8 @@
|
|||
}
|
||||
|
||||
.btn {
|
||||
margin-top: ($sidebar-width / 2);
|
||||
margin-bottom: $sidebar-width;
|
||||
margin-top: ($sidebar--width / 2);
|
||||
margin-bottom: $sidebar--width;
|
||||
|
||||
> .icon {
|
||||
font-size: 20px;
|
||||
|
@ -67,7 +67,7 @@
|
|||
.auth-credits {
|
||||
z-index: 90;
|
||||
position: absolute;
|
||||
bottom: ($sidebar-width / 4);
|
||||
bottom: ($sidebar--width / 4);
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 12px;
|
||||
|
|
|
@ -192,3 +192,15 @@ br {
|
|||
|
||||
p {font-size: 13px;}
|
||||
}
|
||||
.alerts-widget {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
|
||||
> .btn {margin: 20px 0;}
|
||||
|
||||
.alert-history-table {
|
||||
flex: 1 0 0;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue