From ffe03ee22dd80798af53103b7109726a91de0e6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hugo=20H=C3=A4ggmark?= Date: Wed, 23 Jan 2019 15:57:24 +0100 Subject: [PATCH] Restructure of component and styling --- .../app/features/explore/ExploreToolbar.tsx | 178 ++++-- public/app/features/explore/TimePicker.tsx | 21 +- public/sass/pages/_explore.scss | 583 +++++++++++++----- 3 files changed, 549 insertions(+), 233 deletions(-) diff --git a/public/app/features/explore/ExploreToolbar.tsx b/public/app/features/explore/ExploreToolbar.tsx index 6b25b367039..0c2d734ecc0 100644 --- a/public/app/features/explore/ExploreToolbar.tsx +++ b/public/app/features/explore/ExploreToolbar.tsx @@ -1,8 +1,8 @@ import React, { PureComponent } from 'react'; import { ExploreId } from 'app/types/explore'; -import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker'; import { DataSourceSelectItem, RawTimeRange, TimeRange } from '@grafana/ui'; import TimePicker from './TimePicker'; +import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker'; interface Props { datasourceMissing: boolean; @@ -29,70 +29,136 @@ export class ExploreToolbar extends PureComponent { constructor(props) { super(props); this.timepickerRef = React.createRef(); + this.createResponsiveButton = this.createResponsiveButton.bind(this); + this.createDatasourcePicker = this.createDatasourcePicker.bind(this); + this.createSplittedClassName = this.createSplittedClassName.bind(this); + } + + createDatasourcePicker() { + const { exploreDatasources, selectedDatasource } = this.props; + + return ( + + ); + } + + createResponsiveButton(options: { + title: string; + onClick: () => void; + buttonClassName?: string; + iconClassName?: string; + }) { + const { splitted } = this.props; + const { title, onClick, buttonClassName, iconClassName } = options; + + return ( + <> + + + + ); + } + + createSplittedClassName(className: string) { + const { splitted } = this.props; + + return splitted ? `${className}-splitted` : className; } render() { - const { - datasourceMissing, - exploreDatasources, - exploreId, - loading, - range, - selectedDatasource, - splitted, - } = this.props; + const { datasourceMissing, exploreId, loading, range, splitted } = this.props; + const toolbar = this.createSplittedClassName('toolbar'); + const toolbarItem = this.createSplittedClassName('toolbar-item'); + const toolbarHeader = this.createSplittedClassName('toolbar-header'); + const timepickerLarge = this.createSplittedClassName('toolbar-content-item timepicker-large-screens'); + const timepickerSmall = this.createSplittedClassName('toolbar-content-item timepicker-small-screens'); return ( -
- {exploreId === 'left' ? ( -
- - - Explore - +
+
+
+
+ {exploreId === 'left' && ( + + + Explore + + )} +
+
+
+ {!datasourceMissing && !splitted ? this.createDatasourcePicker() : null} +
+
+
+ {exploreId === 'right' && ( + + + + )} +
- ) : ( - <> -
-
-
+
+ {!datasourceMissing && splitted ? ( +
{this.createDatasourcePicker()}
+ ) : null} +
+
+
+ {!datasourceMissing && !splitted ? ( +
+
{this.createDatasourcePicker()}
+
+ ) : null} + {exploreId === 'left' && !splitted ? ( +
+ {this.createResponsiveButton({ + title: 'Split', + onClick: this.props.onSplit, + iconClassName: 'fa fa-fw fa-columns', + })} +
+ ) : null} +
+ +
+
+ +
+
+
- - )} - {!datasourceMissing ? ( -
- +
+ {this.createResponsiveButton({ + title: 'Run Query', + onClick: this.props.onRunQuery, + buttonClassName: 'navbar-button--primary', + iconClassName: loading ? 'fa fa-spinner fa-fw fa-spin run-icon' : 'fa fa-level-down fa-fw run-icon', + })} +
- ) : null} -
- {exploreId === 'left' && !splitted ? ( -
- -
- ) : null} - -
- -
-
-
); diff --git a/public/app/features/explore/TimePicker.tsx b/public/app/features/explore/TimePicker.tsx index 8476c6b2b27..47b8f0de13a 100644 --- a/public/app/features/explore/TimePicker.tsx +++ b/public/app/features/explore/TimePicker.tsx @@ -39,6 +39,7 @@ interface TimePickerProps { isUtc?: boolean; range?: RawTimeRange; onChangeTime?: (range: RawTimeRange, scanning?: boolean) => void; + iconOnly?: boolean; } interface TimePickerState { @@ -292,19 +293,27 @@ export default class TimePicker extends PureComponent
- + {iconOnly ? ( + + ) : ( + + )} diff --git a/public/sass/pages/_explore.scss b/public/sass/pages/_explore.scss index abd13a10368..d64121f761d 100644 --- a/public/sass/pages/_explore.scss +++ b/public/sass/pages/_explore.scss @@ -1,182 +1,248 @@ +.timepicker-small-screens, +.timepicker-small-screens-splitted, +.small-screens { + display: none; +} + +.datasource-picker { + min-width: 200px; + max-width: 200px; +} + +.toolbar-splitted, +.toolbar { + display: flex; + background: inherit; + justify-content: space-between; + height: auto; + padding: 2px $dashboard-padding; +} + +.toolbar { + flex-flow: row nowrap; +} + +.toolbar-splitted { + flex-flow: row wrap; +} + +.toolbar-item-splitted, +.toolbar-item { + align-self: center; +} + +.toolbar-item-splitted:first-child { + flex: 1 1 100%; +} + +.toolbar-header-splitted, +.toolbar-header { + display: flex; + flex: 1 1 0; + flex-flow: row nowrap; + font-size: 18px; + min-height: 55px; + line-height: 55px; + justify-content: space-between; +} + +.toolbar-header { + align-items: center; +} + +.toolbar-header-datasource { + padding-left: $dashboard-padding; + flex: 2 1 auto; +} + +.toolbar-header-close { + color: #d6d6d6; + padding-right: 8px; +} + +.toolbar-content-splitted, +.toolbar-content { + display: flex; + flex: 2 1 0; + flex-flow: row wrap; + justify-content: flex-end; + align-items: center; +} + +.toolbar-content-item { + padding: 10px 2px; +} + +@media only screen and (max-width: 1545px) { + .timepicker-large-screens-splitted { + display: none; + } + + .timepicker-small-screens-splitted { + display: inline-block; + } +} + +@media only screen and (max-width: 1070px) { + .timepicker-large-screens { + display: none; + } + + .timepicker-small-screens { + display: inline-block; + } +} + +@media only screen and (max-width: 768px) { + .large-screens { + display: none; + } + + .small-screens { + display: inline-block; + } + + .toolbar { + flex-flow: row wrap; + } + + .toolbar-content { + align-self: flex-start; + justify-content: flex-start; + } + + .toolbar-content-item { + padding: 5px 2px; + } + + .datasource-picker > div > .ds-picker { + min-width: 160px; + max-width: 160px; + } +} + .explore { flex: 1 1 auto; - - &-container { - padding: $dashboard-padding; - } - - &-wrapper { - display: flex; - - > .explore-split { - width: 50%; - } - } - - // Push split button a bit - .explore-first-button { - margin-left: 15px; - } - - .explore-panel { - margin-top: $panel-margin; - } - - .explore-panel__body { - padding: $panel-padding; - } - - .explore-panel__header { - padding: $panel-padding; - padding-top: 5px; - padding-bottom: 0; - display: flex; - cursor: pointer; - margin-bottom: 5px; - transition: all 0.1s linear; - } - - .explore-panel__header-label { - font-weight: 500; - margin-right: $panel-margin; - font-size: $font-size-h6; - box-shadow: $text-shadow-faint; - } - - .explore-panel__header-buttons { - margin-right: $panel-margin; - font-size: $font-size-lg; - line-height: $font-size-h6; - } - - // Make sure wrap buttons around on small screens - .navbar { - flex-wrap: wrap; - height: auto; - } - - .navbar-page-btn { - margin-right: 1rem; - - // Explore icon in header - .fa { - font-size: 100%; - opacity: 0.75; - margin-right: 0.5em; - } - } - - // Toggle mode - .navbar-button.active { - color: $btn-active-text-color; - background-color: $btn-active-bg; - } - - .navbar-button--no-icon { - line-height: 18px; - } - - .result-options { - margin: 2 * $panel-margin 0; - } - - .time-series-disclaimer { - width: 300px; - margin: $panel-margin auto; - padding: 10px 0; - border-radius: $border-radius; - text-align: center; - background-color: $panel-bg; - - .disclaimer-icon { - color: $yellow; - margin-right: $panel-margin/2; - } - - .show-all-time-series { - cursor: pointer; - color: $external-link-color; - } - } - - .navbar .elapsed-time { - position: absolute; - left: 0; - right: 0; - top: 3.5rem; - text-align: center; - font-size: 0.8rem; - } - - .graph-legend { - flex-wrap: wrap; - } - - .explore-panel__loader { - height: 2px; - position: relative; - overflow: hidden; - background: none; - margin: $panel-margin / 2; - transition: background-color 1s ease; - } - - .explore-panel__loader--active { - background: $text-color-faint; - } - - .explore-panel__loader--active:after { - content: ' '; - display: block; - width: 25%; - top: 0; - top: -50%; - height: 250%; - position: absolute; - animation: loader 2s cubic-bezier(0.17, 0.67, 0.83, 0.67); - animation-iteration-count: 100; - background: $blue; - } - - @keyframes loader { - from { - left: -25%; - } - to { - left: 100%; - } - } - - .datasource-picker { - min-width: 200px; - } - - .timepicker { - display: flex; - - &-rangestring { - margin-left: 0.5em; - } - } - - .run-icon { - margin-left: 0.25em; - transform: rotate(90deg); - } - - .relative { - position: relative; - } - - .link { - text-decoration: underline; - } } .explore + .explore { border-left: 1px dotted $table-border; } +.explore-container { + padding: $dashboard-padding; +} + +.explore-wrapper { + display: flex; + + > .explore-split { + width: 50%; + } +} + +.explore-panel { + margin-top: $panel-margin; +} + +.explore-panel__body { + padding: $panel-padding; +} + +.explore-panel__header { + padding: $panel-padding; + padding-top: 5px; + padding-bottom: 0; + display: flex; + cursor: pointer; + margin-bottom: 5px; + transition: all 0.1s linear; +} + +.explore-panel__header-label { + font-weight: 500; + margin-right: $panel-margin; + font-size: $font-size-h6; + box-shadow: $text-shadow-faint; +} + +.explore-panel__header-buttons { + margin-right: $panel-margin; + font-size: $font-size-lg; + line-height: $font-size-h6; +} + +.result-options { + margin: 2 * $panel-margin 0; +} + +.time-series-disclaimer { + width: 300px; + margin: $panel-margin auto; + padding: 10px 0; + border-radius: $border-radius; + text-align: center; + background-color: $panel-bg; + + .disclaimer-icon { + color: $yellow; + margin-right: $panel-margin/2; + } + + .show-all-time-series { + cursor: pointer; + color: $external-link-color; + } +} + +.navbar .elapsed-time { + position: absolute; + left: 0; + right: 0; + top: 3.5rem; + text-align: center; + font-size: 0.8rem; +} + +.graph-legend { + flex-wrap: wrap; +} + +.explore-panel__loader { + height: 2px; + position: relative; + overflow: hidden; + background: none; + margin: $panel-margin / 2; + transition: background-color 1s ease; +} + +.explore-panel__loader--active { + background: $text-color-faint; +} + +.explore-panel__loader--active:after { + content: ' '; + display: block; + width: 25%; + top: 0; + top: -50%; + height: 250%; + position: absolute; + animation: loader 2s cubic-bezier(0.17, 0.67, 0.83, 0.67); + animation-iteration-count: 100; + background: $blue; +} + +@keyframes loader { + from { + left: -25%; + } + to { + left: 100%; + } +} + .query-row { display: flex; position: relative; @@ -352,3 +418,178 @@ margin: $panel-margin/2 0; cursor: pointer; } + +// .explore { +// flex: 1 1 auto; + +// &-container { +// padding: $dashboard-padding; +// } + +// &-wrapper { +// display: flex; + +// > .explore-split { +// width: 50%; +// } +// } + +// // Push split button a bit +// .explore-first-button { +// margin-left: 15px; +// } + +// .explore-panel { +// margin-top: $panel-margin; +// } + +// .explore-panel__body { +// padding: $panel-padding; +// } + +// .explore-panel__header { +// padding: $panel-padding; +// padding-top: 5px; +// padding-bottom: 0; +// display: flex; +// cursor: pointer; +// margin-bottom: 5px; +// transition: all 0.1s linear; +// } + +// .explore-panel__header-label { +// font-weight: 500; +// margin-right: $panel-margin; +// font-size: $font-size-h6; +// box-shadow: $text-shadow-faint; +// } + +// .explore-panel__header-buttons { +// margin-right: $panel-margin; +// font-size: $font-size-lg; +// line-height: $font-size-h6; +// } + +// // Make sure wrap buttons around on small screens +// .navbar { +// flex-wrap: wrap; +// height: auto; +// } + +// .navbar-page-btn { +// margin-right: 1rem; + +// // Explore icon in header +// .fa { +// font-size: 100%; +// opacity: 0.75; +// margin-right: 0.5em; +// } +// } + +// // Toggle mode +// .navbar-button.active { +// color: $btn-active-text-color; +// background-color: $btn-active-bg; +// } + +// .navbar-button--no-icon { +// line-height: 18px; +// } + +// .result-options { +// margin: 2 * $panel-margin 0; +// } + +// .time-series-disclaimer { +// width: 300px; +// margin: $panel-margin auto; +// padding: 10px 0; +// border-radius: $border-radius; +// text-align: center; +// background-color: $panel-bg; + +// .disclaimer-icon { +// color: $yellow; +// margin-right: $panel-margin/2; +// } + +// .show-all-time-series { +// cursor: pointer; +// color: $external-link-color; +// } +// } + +// .navbar .elapsed-time { +// position: absolute; +// left: 0; +// right: 0; +// top: 3.5rem; +// text-align: center; +// font-size: 0.8rem; +// } + +// .graph-legend { +// flex-wrap: wrap; +// } + +// .explore-panel__loader { +// height: 2px; +// position: relative; +// overflow: hidden; +// background: none; +// margin: $panel-margin / 2; +// transition: background-color 1s ease; +// } + +// .explore-panel__loader--active { +// background: $text-color-faint; +// } + +// .explore-panel__loader--active:after { +// content: ' '; +// display: block; +// width: 25%; +// top: 0; +// top: -50%; +// height: 250%; +// position: absolute; +// animation: loader 2s cubic-bezier(0.17, 0.67, 0.83, 0.67); +// animation-iteration-count: 100; +// background: $blue; +// } + +// @keyframes loader { +// from { +// left: -25%; +// } +// to { +// left: 100%; +// } +// } + +// .datasource-picker { +// min-width: 200px; +// } + +// .timepicker { +// display: flex; + +// &-rangestring { +// margin-left: 0.5em; +// } +// } + +// .run-icon { +// margin-left: 0.25em; +// transform: rotate(90deg); +// } + +// .relative { +// position: relative; +// } + +// .link { +// text-decoration: underline; +// } +// }