diff --git a/CHANGELOG.md b/CHANGELOG.md index 93a5f74737..8c34f797ee 100644 --- a/CHANGELOG.md +++ b/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 diff --git a/ui/src/alerts/components/AlertsTable.js b/ui/src/alerts/components/AlertsTable.js index cc9e573df6..22625449e0 100644 --- a/ui/src/alerts/components/AlertsTable.js +++ b/ui/src/alerts/components/AlertsTable.js @@ -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 - ? - - - - - - - - - - + ?
+
+
this.changeSort('name')} + className={this.sortableClasses('name')} + style={{width: colName}} + > + Name +
+
this.changeSort('level')} + className={this.sortableClasses('level')} + style={{width: colLevel}} + > + Level +
+
this.changeSort('time')} + className={this.sortableClasses('time')} + style={{width: colTime}} + > + Time +
+
this.changeSort('host')} + className={this.sortableClasses('host')} + style={{width: colHost}} + > + Host +
+
this.changeSort('value')} + className={this.sortableClasses('value')} + style={{width: colValue}} + > + Value +
+
+ {alerts.map(({name, level, time, host, value}) => { return ( -
- - - - - - + +
+ {value} +
+ ) })} - -
this.changeSort('name')} - className={this.sortableClasses('name')} - > - Name - this.changeSort('level')} - className={this.sortableClasses('level')} - > - Level - this.changeSort('time')} - className={this.sortableClasses('time')} - > - Time - this.changeSort('host')} - className={this.sortableClasses('host')} - > - Host - this.changeSort('value')} - className={this.sortableClasses('value')} - > - Value -
{name} +
+
+ {name} +
+
{level} -
+ +
{new Date(Number(time)).toISOString()} -
+ +
{host} -
{value}
+ + : this.renderTableEmpty() } @@ -239,7 +272,7 @@ class SearchBar extends Component { diff --git a/ui/src/alerts/constants/tableSizing.js b/ui/src/alerts/constants/tableSizing.js new file mode 100644 index 0000000000..ab2879ff7b --- /dev/null +++ b/ui/src/alerts/constants/tableSizing.js @@ -0,0 +1,7 @@ +export const ALERTS_TABLE = { + colName: '15%', + colLevel: '10%', + colTime: '25%', + colHost: '25%', + colValue: '25%', +} diff --git a/ui/src/alerts/containers/AlertsApp.js b/ui/src/alerts/containers/AlertsApp.js index 56faabadb0..ba980ac22d 100644 --- a/ui/src/alerts/containers/AlertsApp.js +++ b/ui/src/alerts/containers/AlertsApp.js @@ -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 - ? - {this.renderSubComponents()} - - :
+ ? this.renderSubComponents() + :
@@ -183,7 +180,7 @@ class AlertsApp extends Component {
- +
@@ -191,7 +188,7 @@ class AlertsApp extends Component {
- +
} } diff --git a/ui/src/dashboards/components/DashboardsHeader.js b/ui/src/dashboards/components/DashboardsHeader.js new file mode 100644 index 0000000000..3774f7293a --- /dev/null +++ b/ui/src/dashboards/components/DashboardsHeader.js @@ -0,0 +1,28 @@ +import React, {PropTypes} from 'react' + +import SourceIndicator from 'shared/components/SourceIndicator' + +const DashboardsHeader = ({sourceName}) => { + return ( +
+
+
+

+ Dashboards +

+
+
+ +
+
+
+ ) +} + +const {string} = PropTypes + +DashboardsHeader.propTypes = { + sourceName: string.isRequired, +} + +export default DashboardsHeader diff --git a/ui/src/dashboards/components/DashboardsPageContents.js b/ui/src/dashboards/components/DashboardsPageContents.js new file mode 100644 index 0000000000..be859ec9ef --- /dev/null +++ b/ui/src/dashboards/components/DashboardsPageContents.js @@ -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 ( + +
+
+
+
+
+

{tableHeader}

+ +
+
+ +
+
+
+
+
+
+ ) +} + +const {arrayOf, func, shape, string} = PropTypes + +DashboardsPageContents.propTypes = { + dashboards: arrayOf(shape()), + onDeleteDashboard: func.isRequired, + onCreateDashboard: func.isRequired, + dashboardLink: string.isRequired, +} + +export default DashboardsPageContents diff --git a/ui/src/dashboards/components/DashboardsTable.js b/ui/src/dashboards/components/DashboardsTable.js new file mode 100644 index 0000000000..3db85bf53d --- /dev/null +++ b/ui/src/dashboards/components/DashboardsTable.js @@ -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 + ? + + + + + + + + {_.sortBy(dashboards, d => d.name.toLowerCase()).map(dashboard => + + + + + + )} + +
NameTemplate Variables +
+ + {dashboard.name} + + + {dashboard.templates.length + ? dashboard.templates.map(tv => + + {tv.tempVar} + + ) + : + None + } +
+ :
+

+ Looks like you dont have any dashboards +

+ +
+} + +const {arrayOf, func, shape, string} = PropTypes + +DashboardsTable.propTypes = { + dashboards: arrayOf(shape()), + onDeleteDashboard: func.isRequired, + onCreateDashboard: func.isRequired, + dashboardLink: string.isRequired, +} + +export default DashboardsTable diff --git a/ui/src/dashboards/containers/DashboardsPage.js b/ui/src/dashboards/containers/DashboardsPage.js index 5475b8fe2d..0a1d2d634e 100644 --- a/ui/src/dashboards/containers/DashboardsPage.js +++ b/ui/src/dashboards/containers/DashboardsPage.js @@ -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 (
-
-
-
-

- Dashboards -

-
-
- -
-
-
- -
-
-
-
-
-

{tableHeader}

- -
-
- {dashboards && dashboards.length - ? - - - - - - - {dashboards.map(dashboard => - - - - - )} - -
Name -
- - {dashboard.name} - -
- :
-

- Looks like you dont have any dashboards -

- -
} -
-
-
-
-
-
+ +
) }, diff --git a/ui/src/shared/components/DatabaseDropdown.js b/ui/src/shared/components/DatabaseDropdown.js index 7f9fdf135d..0f99a9faac 100644 --- a/ui/src/shared/components/DatabaseDropdown.js +++ b/ui/src/shared/components/DatabaseDropdown.js @@ -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) diff --git a/ui/src/shared/components/FancyScrollbar.js b/ui/src/shared/components/FancyScrollbar.js index 3b1e81dc7b..87f414144b 100644 --- a/ui/src/shared/components/FancyScrollbar.js +++ b/ui/src/shared/components/FancyScrollbar.js @@ -33,6 +33,7 @@ class FancyScrollbar extends Component {
} renderThumbVertical={props =>
} + renderView={props =>
} > {children} diff --git a/ui/src/shared/components/LineGraph.js b/ui/src/shared/components/LineGraph.js index b5fe2d5ca6..0ce517f8b9 100644 --- a/ui/src/shared/components/LineGraph.js +++ b/ui/src/shared/components/LineGraph.js @@ -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({ {children} : {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 - ? -

{title}

+ ?
+ {title} - : -

{title}

+ : + {title} }, }) @@ -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 (
- {this.renderLink()} -
-
- {children} -
+ {this.renderSquare()} +
+ {children}
) }, - renderLink() { + renderSquare() { const {link, icon} = this.props if (!link) { return ( -
- +
+
) } return ( - -
- -
+ +
) }, @@ -131,7 +126,7 @@ const NavBar = React.createClass({ return child }) - return + return }, }) diff --git a/ui/src/side_nav/containers/SideNav.js b/ui/src/side_nav/containers/SideNav.js index bf62f99a98..c1aa22996c 100644 --- a/ui/src/side_nav/containers/SideNav.js +++ b/ui/src/side_nav/containers/SideNav.js @@ -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({ ) .concat( - + Logout ) @@ -68,12 +74,14 @@ const SideNav = React.createClass({ return isHidden ? null : - - - +
+ + + +
@@ -108,8 +116,20 @@ const SideNav = React.createClass({ title="Configuration" /> +
+
+
+ +
+
+
+ Version: {V_NUMBER} +
+
+
+
{isUsingAuth - ? + ? {customLinks ? this.renderUserMenuBlockWithCustomLinks( customLinks, diff --git a/ui/src/style/components/fancy-scrollbars.scss b/ui/src/style/components/fancy-scrollbars.scss index b9239adda6..1e6160822d 100644 --- a/ui/src/style/components/fancy-scrollbars.scss +++ b/ui/src/style/components/fancy-scrollbars.scss @@ -55,11 +55,15 @@ 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; .fancy-scroll--container { position: absolute !important; } -} \ No newline at end of file +} diff --git a/ui/src/style/components/page-spinner.scss b/ui/src/style/components/page-spinner.scss index 5aa932c425..835e11f91c 100644 --- a/ui/src/style/components/page-spinner.scss +++ b/ui/src/style/components/page-spinner.scss @@ -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 { diff --git a/ui/src/style/components/query-maker-responsive.scss b/ui/src/style/components/query-maker-responsive.scss index d4c52be828..5212660964 100644 --- a/ui/src/style/components/query-maker-responsive.scss +++ b/ui/src/style/components/query-maker-responsive.scss @@ -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; @@ -46,4 +45,4 @@ $breakpoint-c: 2100px; line-height: 18px; } } -} \ No newline at end of file +} diff --git a/ui/src/style/components/tables.scss b/ui/src/style/components/tables.scss index ca68164158..4011985541 100644 --- a/ui/src/style/components/tables.scss +++ b/ui/src/style/components/tables.scss @@ -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; +} diff --git a/ui/src/style/layout/overlay.scss b/ui/src/style/layout/overlay.scss index a736026a00..6731b38011 100644 --- a/ui/src/style/layout/overlay.scss +++ b/ui/src/style/layout/overlay.scss @@ -19,5 +19,5 @@ // Make Overlay Technology full screen .overlay-technology { - left: -($sidebar-width) !important; -} \ No newline at end of file + left: -($sidebar--width) !important; +} diff --git a/ui/src/style/layout/sidebar.scss b/ui/src/style/layout/sidebar.scss index b5e35af2d2..598b5ce407 100644 --- a/ui/src/style/layout/sidebar.scss +++ b/ui/src/style/layout/sidebar.scss @@ -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); + width: $sidebar--width; + @include gradient-v($sidebar--gradient-start,$sidebar--gradient-end); +} +.sidebar--bottom { + position: absolute; + bottom: 0; + left: 0; + display: flex; + flex-direction: column; + justify-content: flex-end; + width: $sidebar--width; +} - &__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 { - 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; - display: flex; - flex-direction: column; - list-style: none; - - &-wrapper { - 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 { - width: 100%; - white-space: nowrap; - margin: 0; - display: block; - @include no-user-select(); - &:hover { - cursor: pointer; - } - } - - &__menu-item { - color: $sidebar-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; - } - - // 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; +/* + 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%; + 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; + display: block; + @include no-user-select(); + &:hover { + cursor: pointer; + } +} +.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: none; + + // Rounding bottom outside corner of match container + &: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; +} diff --git a/ui/src/style/pages/auth-page.scss b/ui/src/style/pages/auth-page.scss index b6c78c6680..75df36ae6c 100644 --- a/ui/src/style/pages/auth-page.scss +++ b/ui/src/style/pages/auth-page.scss @@ -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; @@ -80,4 +80,4 @@ top: -1px; margin-right: 1px; } -} \ No newline at end of file +} diff --git a/ui/src/style/unsorted.scss b/ui/src/style/unsorted.scss index d03c5aaa4c..b1d208c559 100644 --- a/ui/src/style/unsorted.scss +++ b/ui/src/style/unsorted.scss @@ -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; + } +}