From adb2430a1b11945401e1e4a422cc1d006adef37f Mon Sep 17 00:00:00 2001 From: David Kaltschmidt Date: Fri, 16 Nov 2018 18:21:13 +0000 Subject: [PATCH] Explore: collapsible result panels - replace the Graph/Table buttons with toggle control in a wrapper panel - moved toggle control to left to be close to the label - removed panel styles from Logs and Graph viewer - moved loader animation to panel --- public/app/features/explore/Explore.tsx | 88 +++++++++---------- public/app/features/explore/Graph.tsx | 8 +- public/app/features/explore/Logs.tsx | 49 +++++------ public/app/features/explore/Panel.tsx | 34 +++++++ .../explore/__snapshots__/Graph.test.tsx.snap | 18 ++-- public/app/types/explore.ts | 1 + public/sass/pages/_explore.scss | 55 +++++++++--- 7 files changed, 152 insertions(+), 101 deletions(-) create mode 100644 public/app/features/explore/Panel.tsx diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index ba367efb497..5d39992c4a2 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -19,6 +19,7 @@ import NoOptionsMessage from 'app/core/components/Picker/NoOptionsMessage'; import TableModel, { mergeTablesIntoModel } from 'app/core/table_model'; import { DatasourceSrv } from 'app/features/plugins/datasource_srv'; +import Panel from './Panel'; import QueryRows from './QueryRows'; import Graph from './Graph'; import Logs from './Logs'; @@ -127,6 +128,7 @@ export class Explore extends React.PureComponent { range: initialRange, showingGraph: true, showingLogs: true, + showingStartPage: false, showingTable: true, supportsGraph: null, supportsLogs: null, @@ -238,6 +240,7 @@ export class Explore extends React.PureComponent { datasourceLoading: false, datasourceName: datasource.name, queries: nextQueries, + showingStartPage: Boolean(StartPage), }, () => { if (datasourceError === null) { @@ -329,10 +332,11 @@ export class Explore extends React.PureComponent { onClickClear = () => { this.queryExpressions = ['']; this.setState( - { + prevState => ({ queries: ensureQueries(), queryTransactions: [], - }, + showingStartPage: Boolean(prevState.StartPage), + }), this.saveState ); }; @@ -563,6 +567,7 @@ export class Explore extends React.PureComponent { return { queryTransactions: nextQueryTransactions, + showingStartPage: false, }; }); @@ -789,16 +794,13 @@ export class Explore extends React.PureComponent { range, showingGraph, showingLogs, + showingStartPage, showingTable, supportsGraph, supportsLogs, supportsTable, } = this.state; - const showingBoth = showingGraph && showingTable; - const graphHeight = showingBoth ? '200px' : '400px'; - const graphButtonActive = showingBoth || showingGraph ? 'active' : ''; - const logsButtonActive = showingLogs ? 'active' : ''; - const tableButtonActive = showingBoth || showingTable ? 'active' : ''; + const graphHeight = showingGraph && showingTable ? '200px' : '400px'; const exploreClass = split ? 'explore explore-split' : 'explore'; const selectedDatasource = datasource ? exploreDatasources.find(d => d.label === datasource.name) : undefined; const graphRangeIntervals = getIntervals(graphRange, datasource, this.el ? this.el.offsetWidth : 0); @@ -823,8 +825,6 @@ export class Explore extends React.PureComponent { ) : undefined; const loading = queryTransactions.some(qt => !qt.done); - const showStartPages = StartPage && queryTransactions.length === 0; - const viewModeCount = [supportsGraph, supportsLogs, supportsTable].filter(m => m).length; return (
@@ -913,55 +913,47 @@ export class Explore extends React.PureComponent { />
- {showStartPages && } - {!showStartPages && ( + {showingStartPage && } + {!showingStartPage && ( <> - {viewModeCount > 1 && ( -
- {supportsGraph ? ( - - ) : null} - {supportsTable ? ( - - ) : null} - {supportsLogs ? ( - - ) : null} -
- )} - - {supportsGraph && - showingGraph && ( + {supportsGraph && ( + - )} - {supportsTable && showingTable ? ( -
+ + )} + {supportsTable && ( + - - ) : null} - {supportsLogs && showingLogs ? ( - - ) : null} + + )} + {supportsLogs && ( + + + + )} )} diff --git a/public/app/features/explore/Graph.tsx b/public/app/features/explore/Graph.tsx index 9e4fea0d3de..61cf5753b19 100644 --- a/public/app/features/explore/Graph.tsx +++ b/public/app/features/explore/Graph.tsx @@ -77,7 +77,6 @@ interface GraphProps { data: any[]; height?: string; // e.g., '200px' id?: string; - loading?: boolean; range: RawTimeRange; split?: boolean; size?: { width: number; height: number }; @@ -188,12 +187,11 @@ export class Graph extends PureComponent { } render() { - const { height = '100px', id = 'graph', loading = false } = this.props; + const { height = '100px', id = 'graph' } = this.props; const data = this.getGraphData(); return ( -
- {loading &&
} + <> {this.props.data && this.props.data.length > MAX_NUMBER_OF_TIME_SERIES && !this.state.showAllTimeSeries && ( @@ -207,7 +205,7 @@ export class Graph extends PureComponent { )}
-
+ ); } } diff --git a/public/app/features/explore/Logs.tsx b/public/app/features/explore/Logs.tsx index edde5acba92..a00aaccb028 100644 --- a/public/app/features/explore/Logs.tsx +++ b/public/app/features/explore/Logs.tsx @@ -97,7 +97,7 @@ export default class Logs extends PureComponent { />
-
+
@@ -116,33 +116,30 @@ export default class Logs extends PureComponent {
-
- {loading &&
} -
- {hasData && - data.rows.map(row => ( - -
- {showUtc &&
{row.timestamp}
} - {showLocalTime &&
{row.timeLocal}
} - {showLabels && ( -
- {row.labels} -
- )} -
- +
+ {hasData && + data.rows.map(row => ( + +
+ {showUtc &&
{row.timestamp}
} + {showLocalTime &&
{row.timeLocal}
} + {showLabels && ( +
+ {row.labels}
- - ))} -
- {!loading && !hasData && 'No data was returned.'} + )} +
+ +
+
+ ))}
+ {!loading && !hasData && 'No data was returned.'}
); } diff --git a/public/app/features/explore/Panel.tsx b/public/app/features/explore/Panel.tsx new file mode 100644 index 00000000000..dc75cb0ecca --- /dev/null +++ b/public/app/features/explore/Panel.tsx @@ -0,0 +1,34 @@ +import React, { PureComponent } from 'react'; + +interface Props { + isOpen: boolean; + label: string; + loading?: boolean; + onToggle: (isOpen: boolean) => void; +} + +export default class Panel extends PureComponent { + onClickToggle = () => this.props.onToggle(!this.props.isOpen); + + render() { + const { isOpen, loading } = this.props; + const iconClass = isOpen ? 'fa fa-caret-up' : 'fa fa-caret-down'; + const loaderClass = loading ? 'explore-panel__loader explore-panel__loader--active' : 'explore-panel__loader'; + return ( +
+
+
+ +
+
{this.props.label}
+
+ {isOpen && ( +
+
+ {this.props.children} +
+ )} +
+ ); + } +} diff --git a/public/app/features/explore/__snapshots__/Graph.test.tsx.snap b/public/app/features/explore/__snapshots__/Graph.test.tsx.snap index fd2010a76d3..6b9553d2e1d 100644 --- a/public/app/features/explore/__snapshots__/Graph.test.tsx.snap +++ b/public/app/features/explore/__snapshots__/Graph.test.tsx.snap @@ -1,9 +1,7 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render component 1`] = ` -
+
-
+
`; exports[`Render should render component with disclaimer 1`] = ` -
+
@@ -952,13 +948,11 @@ exports[`Render should render component with disclaimer 1`] = ` ] } /> -
+
`; exports[`Render should show query return no time series 1`] = ` -
+
-
+
`; diff --git a/public/app/types/explore.ts b/public/app/types/explore.ts index 5a9db7e9b53..662835633db 100644 --- a/public/app/types/explore.ts +++ b/public/app/types/explore.ts @@ -173,6 +173,7 @@ export interface ExploreState { range: RawTimeRange; showingGraph: boolean; showingLogs: boolean; + showingStartPage?: boolean; showingTable: boolean; supportsGraph: boolean | null; supportsLogs: boolean | null; diff --git a/public/sass/pages/_explore.scss b/public/sass/pages/_explore.scss index 58b4ca17840..210920e848d 100644 --- a/public/sass/pages/_explore.scss +++ b/public/sass/pages/_explore.scss @@ -18,10 +18,39 @@ margin-left: 15px; } - // Graph panel needs a bit extra padding at top - .panel-container { + .explore-panel { + margin-top: $panel-margin; + } + + .explore-panel__body { padding: $panel-padding; - padding-top: 10px; + } + + .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:hover { + transform: translateY(-1px); + } + + .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 @@ -91,11 +120,16 @@ height: 2px; position: relative; overflow: hidden; - background: $text-color-faint; + background: none; margin: $panel-margin / 2; + transition: background-color 1s ease; } - .explore-panel__loader:after { + .explore-panel__loader--active { + background: $text-color-faint; + } + + .explore-panel__loader--active:after { content: ' '; display: block; width: 25%; @@ -221,17 +255,18 @@ .logs-controls { display: flex; + background-color: $page-bg; + padding: $panel-padding; + padding-top: 10px; + border-radius: $border-radius; + margin: 2*$panel-margin 0; + border: $panel-border; > * { margin-right: 1em; } } - .logs-options, - .logs-graph { - margin-bottom: $panel-margin; - } - .logs-meta { flex: 1; color: $text-color-weak;