From 7f4a479451370f3d80e2aaa2876a2c205afb9edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Tue, 8 Jan 2019 08:38:43 +0100 Subject: [PATCH 01/17] POC of page layout component --- public/app/core/components/Page/Page.tsx | 26 ++++++++++ .../app/core/components/Page/PageContents.tsx | 29 +++++++++++ .../core/components/PageLoader/PageLoader.tsx | 2 +- .../datasources/DataSourcesListPage.tsx | 50 +++++++++---------- 4 files changed, 81 insertions(+), 26 deletions(-) create mode 100644 public/app/core/components/Page/Page.tsx create mode 100644 public/app/core/components/Page/PageContents.tsx diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx new file mode 100644 index 00000000000..087ac0e111b --- /dev/null +++ b/public/app/core/components/Page/Page.tsx @@ -0,0 +1,26 @@ +// Libraries +import React, { Component } from 'react'; + +// Components +import PageHeader from '../PageHeader/PageHeader'; +import PageContents from './PageContents'; + +interface Props { + title: string; + children: JSX.Element[] | JSX.Element; +} + +class Page extends Component { + static Header = PageHeader; + static Contents = PageContents; + + render() { + return ( +
+ {this.props.children} +
+ ); + } +} + +export default Page; diff --git a/public/app/core/components/Page/PageContents.tsx b/public/app/core/components/Page/PageContents.tsx new file mode 100644 index 00000000000..bf5e3ba7385 --- /dev/null +++ b/public/app/core/components/Page/PageContents.tsx @@ -0,0 +1,29 @@ +// Libraries +import React, { Component } from 'react'; + +// Components +import CustomScrollbar from '../CustomScrollbar/CustomScrollbar'; +import PageLoader from '../PageLoader/PageLoader'; + +interface Props { + isLoading?: boolean; + children: JSX.Element[] | JSX.Element; +} + +class PageContents extends Component { + + render() { + const { isLoading } = this.props; + + return ( +
+ + {isLoading && } + {this.props.children} + +
+ ); + } +} + +export default PageContents; diff --git a/public/app/core/components/PageLoader/PageLoader.tsx b/public/app/core/components/PageLoader/PageLoader.tsx index dcb67dde220..5fff00b2f6f 100644 --- a/public/app/core/components/PageLoader/PageLoader.tsx +++ b/public/app/core/components/PageLoader/PageLoader.tsx @@ -1,7 +1,7 @@ import React, { SFC } from 'react'; interface Props { - pageName: string; + pageName?: string; } const PageLoader: SFC = ({ pageName }) => { diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index 6a292d63e53..de9dba34d73 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -1,15 +1,14 @@ import React, { PureComponent } from 'react'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; -import PageHeader from '../../core/components/PageHeader/PageHeader'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; -import OrgActionBar from '../../core/components/OrgActionBar/OrgActionBar'; -import EmptyListCTA from '../../core/components/EmptyListCTA/EmptyListCTA'; +import Page from 'app/core/components/Page/Page'; +import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar'; +import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import DataSourcesList from './DataSourcesList'; import { DataSource, NavModel } from 'app/types'; -import { LayoutMode } from '../../core/components/LayoutSelector/LayoutSelector'; +import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; import { loadDataSources, setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions'; -import { getNavModel } from '../../core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; import { getDataSources, getDataSourcesCount, @@ -67,25 +66,26 @@ export class DataSourcesListPage extends PureComponent { }; return ( -
- -
- {!hasFetched && } - {hasFetched && dataSourcesCount === 0 && } - {hasFetched && - dataSourcesCount > 0 && [ - setDataSourcesLayoutMode(mode)} - setSearchQuery={query => setDataSourcesSearchQuery(query)} - linkButton={linkButton} - key="action-bar" - />, - , - ]} -
-
+ + + + <> + {hasFetched && dataSourcesCount === 0 && } + {hasFetched && + dataSourcesCount > 0 && [ + setDataSourcesLayoutMode(mode)} + setSearchQuery={query => setDataSourcesSearchQuery(query)} + linkButton={linkButton} + key="action-bar" + />, + , + ]} + + + ); } } From 1d8e036bcbf779faaf4e70c30cefbe0805a7b7eb Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 9 Jan 2019 16:31:28 +0100 Subject: [PATCH 02/17] fix: Fix import path after Scrollbar move to @grafana/ui --- public/app/core/components/Page/PageContents.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/app/core/components/Page/PageContents.tsx b/public/app/core/components/Page/PageContents.tsx index bf5e3ba7385..4c740584e69 100644 --- a/public/app/core/components/Page/PageContents.tsx +++ b/public/app/core/components/Page/PageContents.tsx @@ -2,7 +2,7 @@ import React, { Component } from 'react'; // Components -import CustomScrollbar from '../CustomScrollbar/CustomScrollbar'; +import { CustomScrollbar } from '@grafana/ui'; import PageLoader from '../PageLoader/PageLoader'; interface Props { From 9e0e91a90a84b072ecd0ed363990bcdb8b2467ac Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 10 Jan 2019 08:33:39 +0100 Subject: [PATCH 03/17] test: Snapshot update --- .../DataSourcesListPage.test.tsx.snap | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap index c26ac50fed8..e523816c021 100644 --- a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap +++ b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap @@ -1,12 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render action bar and datasources 1`] = ` -
+ -
-
-
+ + `; exports[`Render should render component 1`] = ` -
+ -
- -
-
+ + `; From 47d86ee81898753d2567d03f5e529be6172ba15d Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 10 Jan 2019 08:36:38 +0100 Subject: [PATCH 04/17] fix: Proper types for linter --- public/app/core/components/PageHeader/PageHeader.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/public/app/core/components/PageHeader/PageHeader.tsx b/public/app/core/components/PageHeader/PageHeader.tsx index c176095afa4..83066054f88 100644 --- a/public/app/core/components/PageHeader/PageHeader.tsx +++ b/public/app/core/components/PageHeader/PageHeader.tsx @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { FormEvent } from 'react'; import { NavModel, NavModelItem } from 'app/types'; import classNames from 'classnames'; import appEvents from 'app/core/app_events'; @@ -12,8 +12,8 @@ const SelectNav = ({ main, customCss }: { main: NavModelItem; customCss: string return navItem.active === true; }); - const gotoUrl = evt => { - const element = evt.target; + const gotoUrl = (evt: FormEvent) => { + const element = evt.target as HTMLSelectElement; const url = element.options[element.selectedIndex].value; appEvents.emit('location-change', { href: url }); }; From 8237c22e24a83224c61a7a0fe06a931e4622272c Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 14 Jan 2019 16:05:49 +0100 Subject: [PATCH 05/17] fix: Add CustomScroller on DataSources page --- .../CustomScrollbar/CustomScrollbar.tsx | 3 +- public/app/core/components/Page/Page.tsx | 28 +++++++++++++++++-- .../app/core/components/Page/PageContents.tsx | 7 ++--- .../datasources/DataSourcesListPage.tsx | 4 +-- public/sass/components/_footer.scss | 8 ++++++ public/sass/layout/_page.scss | 17 ++++++++++- 6 files changed, 56 insertions(+), 11 deletions(-) diff --git a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx index 519e755b474..7f43936481f 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx +++ b/packages/grafana-ui/src/components/CustomScrollbar/CustomScrollbar.tsx @@ -8,6 +8,7 @@ interface Props { autoHideDuration?: number; autoMaxHeight?: string; hideTracksWhenNotNeeded?: boolean; + autoHeightMin?: number | string; } /** @@ -21,6 +22,7 @@ export class CustomScrollbar extends PureComponent { autoHideDuration: 200, autoMaxHeight: '100%', hideTracksWhenNotNeeded: false, + autoHeightMin: '0' }; render() { @@ -32,7 +34,6 @@ export class CustomScrollbar extends PureComponent { autoHeight={true} // These autoHeightMin & autoHeightMax options affect firefox and chrome differently. // Before these where set to inhert but that caused problems with cut of legends in firefox - autoHeightMin={'0'} autoHeightMax={autoMaxHeight} renderTrackHorizontal={props =>
} renderTrackVertical={props =>
} diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index 087ac0e111b..f225d4d3170 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -4,6 +4,7 @@ import React, { Component } from 'react'; // Components import PageHeader from '../PageHeader/PageHeader'; import PageContents from './PageContents'; +import { CustomScrollbar } from '@grafana/ui'; interface Props { title: string; @@ -11,13 +12,36 @@ interface Props { } class Page extends Component { + private bodyClass = 'is-react'; + private body = document.getElementsByTagName('body')[0]; + private footer = document.getElementsByClassName('footer')[0].cloneNode(true); + private scrollbarElementRef = React.createRef(); static Header = PageHeader; static Contents = PageContents; + + componentDidMount() { + this.body.classList.add(this.bodyClass); + this.copyFooter(); + } + + componentWillUnmount() { + this.body.classList.remove(this.bodyClass); + } + + copyFooter = () => { + const c = this.scrollbarElementRef.current; + c.append(this.footer); + } + render() { return ( -
- {this.props.children} +
+ +
+ {this.props.children} +
+
); } diff --git a/public/app/core/components/Page/PageContents.tsx b/public/app/core/components/Page/PageContents.tsx index 4c740584e69..6970857d383 100644 --- a/public/app/core/components/Page/PageContents.tsx +++ b/public/app/core/components/Page/PageContents.tsx @@ -2,7 +2,6 @@ import React, { Component } from 'react'; // Components -import { CustomScrollbar } from '@grafana/ui'; import PageLoader from '../PageLoader/PageLoader'; interface Props { @@ -17,10 +16,8 @@ class PageContents extends Component { return (
- - {isLoading && } - {this.props.children} - + {isLoading && } + {this.props.children}
); } diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index de9dba34d73..d81caae663c 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -5,7 +5,7 @@ import Page from 'app/core/components/Page/Page'; import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import DataSourcesList from './DataSourcesList'; -import { DataSource, NavModel } from 'app/types'; +import { DataSource, NavModel, StoreState } from 'app/types'; import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; import { loadDataSources, setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions'; import { getNavModel } from 'app/core/selectors/navModel'; @@ -90,7 +90,7 @@ export class DataSourcesListPage extends PureComponent { } } -function mapStateToProps(state) { +function mapStateToProps(state: StoreState) { return { navModel: getNavModel(state.navIndex, 'datasources'), dataSources: getDataSources(state.dataSources), diff --git a/public/sass/components/_footer.scss b/public/sass/components/_footer.scss index 893eea02914..b5617f4e387 100644 --- a/public/sass/components/_footer.scss +++ b/public/sass/components/_footer.scss @@ -38,6 +38,14 @@ } } +.is-react .footer { + display: none; +} + +.is-react .custom-scrollbars .footer { + display: block; +} + // Keeping footer inside the graphic on Login screen .login-page { .footer { diff --git a/public/sass/layout/_page.scss b/public/sass/layout/_page.scss index 818dc6c3e60..425cbc903c0 100644 --- a/public/sass/layout/_page.scss +++ b/public/sass/layout/_page.scss @@ -20,7 +20,23 @@ } } +.page-scrollbar-wrapper { + position: absolute; + top: 0; + bottom: 0; + width: 100%; +} + +.page-scrollbar-content { + display: flex; + min-height: 100%; + flex-direction: column; + width: 100%; +} + .page-container { + flex-grow: 1; + width: 100%; margin-left: auto; margin-right: auto; padding-left: $spacer*2; @@ -78,7 +94,6 @@ .page-body { padding-top: $spacer*2; - min-height: 500px; } .page-heading { From 06d8243ab590e81ffb3721f788672d995a6c0a3a Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 14 Jan 2019 16:51:43 +0100 Subject: [PATCH 06/17] feat: Possibility to change document title on pages using the Page component --- public/app/core/components/Page/Page.tsx | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index f225d4d3170..eeba4b3037b 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -7,7 +7,7 @@ import PageContents from './PageContents'; import { CustomScrollbar } from '@grafana/ui'; interface Props { - title: string; + title?: string; children: JSX.Element[] | JSX.Element; } @@ -23,12 +23,24 @@ class Page extends Component { componentDidMount() { this.body.classList.add(this.bodyClass); this.copyFooter(); + this.updateTitle(); + } + + componentDidUpdate(prevProps: Props) { + if (prevProps.title !== this.props.title) { + this.updateTitle(); + } } componentWillUnmount() { this.body.classList.remove(this.bodyClass); } + updateTitle = () => { + const { title } = this.props; + document.title = title ? title + ' - Grafana' : 'Grafana'; + } + copyFooter = () => { const c = this.scrollbarElementRef.current; c.append(this.footer); @@ -37,11 +49,11 @@ class Page extends Component { render() { return (
- -
- {this.props.children} -
-
+ +
+ {this.props.children} +
+
); } From b2961a4b4a9f3336331a5fa59063a8f331c5d9ce Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 14 Jan 2019 16:53:26 +0100 Subject: [PATCH 07/17] fix: Configuration: Users should also use the Page component --- .../datasources/DataSourcesListPage.tsx | 2 +- public/app/features/users/UsersListPage.tsx | 17 +++++++++-------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index d81caae663c..12eb49cb856 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -66,7 +66,7 @@ export class DataSourcesListPage extends PureComponent { }; return ( - + <> diff --git a/public/app/features/users/UsersListPage.tsx b/public/app/features/users/UsersListPage.tsx index ff0ac8f1239..ece431158fd 100644 --- a/public/app/features/users/UsersListPage.tsx +++ b/public/app/features/users/UsersListPage.tsx @@ -2,8 +2,7 @@ import React, { PureComponent } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; import Remarkable from 'remarkable'; -import PageHeader from 'app/core/components/PageHeader/PageHeader'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; +import Page from 'app/core/components/Page/Page'; import UsersActionBar from './UsersActionBar'; import UsersTable from './UsersTable'; import InviteesTable from './InviteesTable'; @@ -105,16 +104,18 @@ export class UsersListPage extends PureComponent { const externalUserMngInfoHtml = this.externalUserMngInfoHtml; return ( -
- -
+ + + + <> {externalUserMngInfoHtml && (
)} - {hasFetched ? this.renderTable() : } -
-
+ {hasFetched && this.renderTable()} + + + ); } } From d426981d1d20d9a302accd49cfda7fa908d48ca0 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 14 Jan 2019 17:03:49 +0100 Subject: [PATCH 08/17] fix: Add Pages component to Plugins and TeamList --- .../app/features/plugins/PluginListPage.tsx | 37 +++++++++---------- public/app/features/teams/TeamList.tsx | 13 ++++--- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/public/app/features/plugins/PluginListPage.tsx b/public/app/features/plugins/PluginListPage.tsx index a2fcb90ce54..ba61f637609 100644 --- a/public/app/features/plugins/PluginListPage.tsx +++ b/public/app/features/plugins/PluginListPage.tsx @@ -1,9 +1,8 @@ import React, { PureComponent } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; -import PageHeader from 'app/core/components/PageHeader/PageHeader'; +import Page from 'app/core/components/Page/Page'; import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; import PluginList from './PluginList'; import { NavModel, Plugin } from 'app/types'; import { loadPlugins, setPluginsLayoutMode, setPluginsSearchQuery } from './state/actions'; @@ -48,23 +47,23 @@ export class PluginListPage extends PureComponent { }; return ( -
- -
- setPluginsLayoutMode(mode)} - setSearchQuery={query => setPluginsSearchQuery(query)} - linkButton={linkButton} - /> - {hasFetched ? ( - plugins && - ) : ( - - )} -
-
+ + + + <> + setPluginsLayoutMode(mode)} + setSearchQuery={query => setPluginsSearchQuery(query)} + linkButton={linkButton} + /> + {hasFetched && plugins && ( + plugins && + )} + + + ); } } diff --git a/public/app/features/teams/TeamList.tsx b/public/app/features/teams/TeamList.tsx index d1551d6baa6..8eac05be3bf 100644 --- a/public/app/features/teams/TeamList.tsx +++ b/public/app/features/teams/TeamList.tsx @@ -1,10 +1,9 @@ import React, { PureComponent } from 'react'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; -import PageHeader from 'app/core/components/PageHeader/PageHeader'; +import Page from 'app/core/components/Page/Page'; import { DeleteButton } from '@grafana/ui'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; import { NavModel, Team } from '../../types'; import { loadTeams, deleteTeam, setSearchQuery } from './state/actions'; import { getSearchQuery, getTeams, getTeamsCount } from './state/selectors'; @@ -141,10 +140,12 @@ export class TeamList extends PureComponent { const { hasFetched, navModel } = this.props; return ( -
- - {hasFetched ? this.renderList() : } -
+ + + + {hasFetched && this.renderList()} + + ); } } From 1e80bac2d226e8d62c53aa45c1209067a13711fb Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 14 Jan 2019 22:15:21 +0100 Subject: [PATCH 09/17] chore: Reactify footer --- public/app/core/components/Footer/Footer.tsx | 50 ++++++++++++++++++++ public/app/core/components/Page/Page.tsx | 21 ++++---- public/app/core/config.ts | 2 + 3 files changed, 63 insertions(+), 10 deletions(-) create mode 100644 public/app/core/components/Footer/Footer.tsx diff --git a/public/app/core/components/Footer/Footer.tsx b/public/app/core/components/Footer/Footer.tsx new file mode 100644 index 00000000000..01da74036b6 --- /dev/null +++ b/public/app/core/components/Footer/Footer.tsx @@ -0,0 +1,50 @@ +import React, { SFC } from 'react'; +import { Tooltip } from '@grafana/ui'; + +interface Props { + appName: string; + buildVersion: string; + buildCommit: string; + newGrafanaVersionExists: boolean; + newGrafanaVersion: string; +} + +export const Footer: SFC = ({appName, buildVersion, buildCommit, newGrafanaVersionExists, newGrafanaVersion}) => { + return ( + + ); +}; + +export default Footer; diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index eeba4b3037b..95345f250ed 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -1,11 +1,14 @@ // Libraries import React, { Component } from 'react'; +import config from 'app/core/config'; // Components import PageHeader from '../PageHeader/PageHeader'; +import Footer from '../Footer/Footer'; import PageContents from './PageContents'; import { CustomScrollbar } from '@grafana/ui'; + interface Props { title?: string; children: JSX.Element[] | JSX.Element; @@ -14,15 +17,11 @@ interface Props { class Page extends Component { private bodyClass = 'is-react'; private body = document.getElementsByTagName('body')[0]; - private footer = document.getElementsByClassName('footer')[0].cloneNode(true); - private scrollbarElementRef = React.createRef(); static Header = PageHeader; static Contents = PageContents; - componentDidMount() { this.body.classList.add(this.bodyClass); - this.copyFooter(); this.updateTitle(); } @@ -41,17 +40,19 @@ class Page extends Component { document.title = title ? title + ' - Grafana' : 'Grafana'; } - copyFooter = () => { - const c = this.scrollbarElementRef.current; - c.append(this.footer); - } - render() { + const { buildInfo } = config; return (
-
+
{this.props.children} +
diff --git a/public/app/core/config.ts b/public/app/core/config.ts index 13d84772ecf..0aa159af84d 100644 --- a/public/app/core/config.ts +++ b/public/app/core/config.ts @@ -6,6 +6,8 @@ export interface BuildInfo { commit: string; isEnterprise: boolean; env: string; + latestVersion: string; + hasUpdate: boolean; } export class Settings { From 6bd87098cf0d46953d7ab6cba805202775387a93 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Mon, 14 Jan 2019 22:19:24 +0100 Subject: [PATCH 10/17] chore: Better way of getting the body node --- public/app/core/components/Page/Page.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index 95345f250ed..0197076d150 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -8,7 +8,6 @@ import Footer from '../Footer/Footer'; import PageContents from './PageContents'; import { CustomScrollbar } from '@grafana/ui'; - interface Props { title?: string; children: JSX.Element[] | JSX.Element; @@ -16,7 +15,7 @@ interface Props { class Page extends Component { private bodyClass = 'is-react'; - private body = document.getElementsByTagName('body')[0]; + private body = document.body; static Header = PageHeader; static Contents = PageContents; From 25304629bdbc75b35865f15283f97dd9e7b3d4f2 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Tue, 15 Jan 2019 08:27:07 +0100 Subject: [PATCH 11/17] test: Updated snapshots --- .../DataSourcesListPage.test.tsx.snap | 4 +- .../PluginListPage.test.tsx.snap | 27 +- .../__snapshots__/TeamList.test.tsx.snap | 578 +++++++++--------- .../__snapshots__/UsersListPage.test.tsx.snap | 27 +- 4 files changed, 323 insertions(+), 313 deletions(-) diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap index e523816c021..145623bbad0 100644 --- a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap +++ b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap @@ -2,7 +2,7 @@ exports[`Render should render action bar and datasources 1`] = ` + -
- -
-
+ + `; exports[`Render should render list 1`] = ` -
+ -
-
-
+ + `; diff --git a/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap b/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap index ae94691df0e..d10a2fd2052 100644 --- a/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap +++ b/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap @@ -1,336 +1,344 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render component 1`] = ` -
+ - -
+ `; exports[`Render should render teams table 1`] = ` -
+ -
- + +
+ -
- - - - - - - + + + + + - - - - - - - - - - - + - - + + + + + + + - + - - test-2 - - - + - + - - - - + + - + - - test-3 - - - + - + - - - - + + - + - - test-4 - - - + - + - - - - + + - + - - test-5 - - - + - + - - - -
- - Name - - Email - - Members - +
+ + Name + + Email + + Members + -
- - - - - - test-1 - - - - test-1@test.com - - - - 1 - - - -
+ +
+ + test-1 + + + + test-1@test.com + + + + 1 + + + - - +
- + + + - test-2@test.com - - - + test-2 + + - 2 - - - -
- + test-2@test.com + + - + 2 + + + - - +
- + + + - test-3@test.com - - - + test-3 + + - 3 - - - -
- + test-3@test.com + + - + 3 + + + - - +
- + + + - test-4@test.com - - - + test-4 + + - 4 - - - -
- + test-4@test.com + + - + 4 + + + - - +
- + + + - test-5@test.com - - - + test-5 + + - 5 - - - -
+ + test-5@test.com + + + + + 5 + + + + + + + + +
-
-
+ + `; diff --git a/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap b/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap index 429322eac98..a6c71f63d53 100644 --- a/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap +++ b/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap @@ -1,12 +1,14 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render List page 1`] = ` -
+ -
-
-
+ + `; exports[`Render should render component 1`] = ` -
+ -
- -
-
+ + `; From feeb3ea56dae1cb3384466797dfda88de985925c Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 16 Jan 2019 15:59:05 +0100 Subject: [PATCH 12/17] feat: Generate page titles from navModel --- public/app/core/selectors/navModel.ts | 4 ++++ public/app/features/datasources/DataSourcesListPage.tsx | 5 +++-- public/app/features/plugins/PluginListPage.tsx | 6 +++--- public/app/features/teams/TeamList.tsx | 6 +++--- public/app/features/users/UsersListPage.tsx | 4 ++-- 5 files changed, 15 insertions(+), 10 deletions(-) diff --git a/public/app/core/selectors/navModel.ts b/public/app/core/selectors/navModel.ts index aa508616962..7d745b58002 100644 --- a/public/app/core/selectors/navModel.ts +++ b/public/app/core/selectors/navModel.ts @@ -41,3 +41,7 @@ export function getNavModel(navIndex: NavIndex, id: string, fallback?: NavModel) return getNotFoundModel(); } + +export const getTitleFromNavModel = (navModel: NavModel) => { + return `${navModel.main.text}${navModel.node.text ? ': ' + navModel.node.text : '' }`; +}; diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index 12eb49cb856..f1c1c45ded8 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -8,7 +8,8 @@ import DataSourcesList from './DataSourcesList'; import { DataSource, NavModel, StoreState } from 'app/types'; import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; import { loadDataSources, setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions'; -import { getNavModel } from 'app/core/selectors/navModel'; +import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; + import { getDataSources, getDataSourcesCount, @@ -66,7 +67,7 @@ export class DataSourcesListPage extends PureComponent { }; return ( - + <> diff --git a/public/app/features/plugins/PluginListPage.tsx b/public/app/features/plugins/PluginListPage.tsx index ba61f637609..14bd05f0537 100644 --- a/public/app/features/plugins/PluginListPage.tsx +++ b/public/app/features/plugins/PluginListPage.tsx @@ -6,9 +6,9 @@ import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar'; import PluginList from './PluginList'; import { NavModel, Plugin } from 'app/types'; import { loadPlugins, setPluginsLayoutMode, setPluginsSearchQuery } from './state/actions'; -import { getNavModel } from '../../core/selectors/navModel'; +import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; import { getLayoutMode, getPlugins, getPluginsSearchQuery } from './state/selectors'; -import { LayoutMode } from '../../core/components/LayoutSelector/LayoutSelector'; +import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; export interface Props { navModel: NavModel; @@ -47,7 +47,7 @@ export class PluginListPage extends PureComponent { }; return ( - + <> diff --git a/public/app/features/teams/TeamList.tsx b/public/app/features/teams/TeamList.tsx index 8eac05be3bf..5dd83ca385c 100644 --- a/public/app/features/teams/TeamList.tsx +++ b/public/app/features/teams/TeamList.tsx @@ -4,10 +4,10 @@ import { hot } from 'react-hot-loader'; import Page from 'app/core/components/Page/Page'; import { DeleteButton } from '@grafana/ui'; import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; -import { NavModel, Team } from '../../types'; +import { NavModel, Team } from 'app/types'; import { loadTeams, deleteTeam, setSearchQuery } from './state/actions'; import { getSearchQuery, getTeams, getTeamsCount } from './state/selectors'; -import { getNavModel } from 'app/core/selectors/navModel'; +import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; export interface Props { navModel: NavModel; @@ -140,7 +140,7 @@ export class TeamList extends PureComponent { const { hasFetched, navModel } = this.props; return ( - + {hasFetched && this.renderList()} diff --git a/public/app/features/users/UsersListPage.tsx b/public/app/features/users/UsersListPage.tsx index ece431158fd..43fcc67e470 100644 --- a/public/app/features/users/UsersListPage.tsx +++ b/public/app/features/users/UsersListPage.tsx @@ -9,7 +9,7 @@ import InviteesTable from './InviteesTable'; import { Invitee, NavModel, OrgUser } from 'app/types'; import appEvents from 'app/core/app_events'; import { loadUsers, loadInvitees, setUsersSearchQuery, updateUser, removeUser } from './state/actions'; -import { getNavModel } from '../../core/selectors/navModel'; +import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; import { getInvitees, getUsers, getUsersSearchQuery } from './state/selectors'; export interface Props { @@ -104,7 +104,7 @@ export class UsersListPage extends PureComponent { const externalUserMngInfoHtml = this.externalUserMngInfoHtml; return ( - + <> From 3ca7523a0207ad514692d4ae132fc543ac060a86 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 16 Jan 2019 16:16:19 +0100 Subject: [PATCH 13/17] fix: Use Page component on "Api Keys" and "Preferences" under Configuration --- public/app/features/api-keys/ApiKeysPage.tsx | 29 ++++++++-------- public/app/features/org/OrgDetailsPage.tsx | 36 ++++++++++---------- 2 files changed, 32 insertions(+), 33 deletions(-) diff --git a/public/app/features/api-keys/ApiKeysPage.tsx b/public/app/features/api-keys/ApiKeysPage.tsx index e14873fa9f6..4cbd8ce4170 100644 --- a/public/app/features/api-keys/ApiKeysPage.tsx +++ b/public/app/features/api-keys/ApiKeysPage.tsx @@ -3,11 +3,10 @@ import ReactDOMServer from 'react-dom/server'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; import { NavModel, ApiKey, NewApiKey, OrgRole } from 'app/types'; -import { getNavModel } from 'app/core/selectors/navModel'; +import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; import { getApiKeys, getApiKeysCount } from './state/selectors'; import { loadApiKeys, deleteApiKey, setSearchQuery, addApiKey } from './state/actions'; -import PageHeader from 'app/core/components/PageHeader/PageHeader'; -import PageLoader from 'app/core/components/PageLoader/PageLoader'; +import Page from 'app/core/components/Page/Page'; import SlideDown from 'app/core/components/Animations/SlideDown'; import ApiKeysAddedModal from './ApiKeysAddedModal'; import config from 'app/core/config'; @@ -240,18 +239,18 @@ export class ApiKeysPage extends PureComponent { const { hasFetched, navModel, apiKeysCount } = this.props; return ( -
- - {hasFetched ? ( - apiKeysCount > 0 ? ( - this.renderApiKeyList() - ) : ( - this.renderEmptyList() - ) - ) : ( - - )} -
+ + + + {hasFetched && ( + apiKeysCount > 0 ? ( + this.renderApiKeyList() + ) : ( + this.renderEmptyList() + ) + )} + + ); } } diff --git a/public/app/features/org/OrgDetailsPage.tsx b/public/app/features/org/OrgDetailsPage.tsx index b011901aa71..ce84bdefafd 100644 --- a/public/app/features/org/OrgDetailsPage.tsx +++ b/public/app/features/org/OrgDetailsPage.tsx @@ -1,13 +1,12 @@ import React, { PureComponent } from 'react'; import { hot } from 'react-hot-loader'; import { connect } from 'react-redux'; -import PageHeader from '../../core/components/PageHeader/PageHeader'; -import PageLoader from '../../core/components/PageLoader/PageLoader'; +import Page from 'app/core/components/Page/Page'; import OrgProfile from './OrgProfile'; import SharedPreferences from 'app/core/components/SharedPreferences/SharedPreferences'; import { loadOrganization, setOrganizationName, updateOrganization } from './state/actions'; import { NavModel, Organization, StoreState } from 'app/types'; -import { getNavModel } from '../../core/selectors/navModel'; +import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; export interface Props { navModel: NavModel; @@ -35,22 +34,23 @@ export class OrgDetailsPage extends PureComponent { const isLoading = Object.keys(organization).length === 0; return ( -
- -
- {isLoading && } - {!isLoading && ( -
- this.onOrgNameChange(name)} - onSubmit={this.onUpdateOrganization} - orgName={organization.name} - /> - + + + +
+ {!isLoading && ( +
+ this.onOrgNameChange(name)} + onSubmit={this.onUpdateOrganization} + orgName={organization.name} + /> + +
+ )}
- )} -
-
+ + ); } } From 234713466e655c1f4167fbede9ee4509f8c8456f Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Wed, 16 Jan 2019 16:29:07 +0100 Subject: [PATCH 14/17] test: Update snapshots and mocks --- .../CustomScrollbar.test.tsx.snap | 4 +- .../features/api-keys/ApiKeysPage.test.tsx | 9 +- .../__snapshots__/ApiKeysPage.test.tsx.snap | 242 ++++++++++-------- .../datasources/DataSourcesListPage.test.tsx | 9 +- .../DataSourcesListPage.test.tsx.snap | 22 +- .../app/features/org/OrgDetailsPage.test.tsx | 9 +- .../OrgDetailsPage.test.tsx.snap | 72 ++++-- .../features/plugins/PluginListPage.test.tsx | 9 +- .../PluginListPage.test.tsx.snap | 22 +- public/app/features/teams/TeamList.test.tsx | 9 +- .../__snapshots__/TeamList.test.tsx.snap | 26 +- .../app/features/users/UsersListPage.test.tsx | 9 +- .../__snapshots__/UsersListPage.test.tsx.snap | 22 +- 13 files changed, 315 insertions(+), 149 deletions(-) diff --git a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap index 60b4a2e0aa5..aabe3dd98c5 100644 --- a/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap +++ b/packages/grafana-ui/src/components/CustomScrollbar/__snapshots__/CustomScrollbar.test.tsx.snap @@ -7,7 +7,7 @@ exports[`CustomScrollbar renders correctly 1`] = ` Object { "height": "auto", "maxHeight": "100%", - "minHeight": "0", + "minHeight": 0, "overflow": "hidden", "position": "relative", "width": "100%", @@ -24,7 +24,7 @@ exports[`CustomScrollbar renders correctly 1`] = ` "marginBottom": 0, "marginRight": 0, "maxHeight": "calc(100% + 0px)", - "minHeight": "calc(0 + 0px)", + "minHeight": 0, "overflow": "scroll", "position": "relative", "right": undefined, diff --git a/public/app/features/api-keys/ApiKeysPage.test.tsx b/public/app/features/api-keys/ApiKeysPage.test.tsx index 54200234ddc..cd640b5a357 100644 --- a/public/app/features/api-keys/ApiKeysPage.test.tsx +++ b/public/app/features/api-keys/ApiKeysPage.test.tsx @@ -6,7 +6,14 @@ import { getMultipleMockKeys, getMockKey } from './__mocks__/apiKeysMock'; const setup = (propOverrides?: object) => { const props: Props = { - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Api Keys' + } + } as NavModel, apiKeys: [] as ApiKey[], searchQuery: '', hasFetched: false, diff --git a/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap b/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap index 7ede9618250..fd05b79da81 100644 --- a/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap +++ b/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap @@ -1,132 +1,158 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render API keys table if there are any keys 1`] = ` -
+ - -
+ `; exports[`Render should render CTA if there are no API keys 1`] = ` -
+ -
- - + +
-
+ - -
- Add API Key -
-
-
+ + +
+ Add API Key +
+
- - Key name - - -
-
- - Role - - - +
+
+ + Role + + + - -
-
-
+
- Add - + +
-
- -
-
-
-
+ +
+ +
+ +
`; diff --git a/public/app/features/datasources/DataSourcesListPage.test.tsx b/public/app/features/datasources/DataSourcesListPage.test.tsx index 0ea716d62c9..33f5790978d 100644 --- a/public/app/features/datasources/DataSourcesListPage.test.tsx +++ b/public/app/features/datasources/DataSourcesListPage.test.tsx @@ -10,7 +10,14 @@ const setup = (propOverrides?: object) => { dataSources: [] as DataSource[], layoutMode: LayoutModes.Grid, loadDataSources: jest.fn(), - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Data Sources' + } + } as NavModel, dataSourcesCount: 0, searchQuery: '', setDataSourcesSearchQuery: jest.fn(), diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap index 145623bbad0..8c351d1dc2d 100644 --- a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap +++ b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap @@ -5,7 +5,16 @@ exports[`Render should render action bar and datasources 1`] = ` title="Configuration: Data Sources" > { const props: Props = { organization: {} as Organization, - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Org details' + } + } as NavModel, loadOrganization: jest.fn(), setOrganizationName: jest.fn(), updateOrganization: jest.fn(), diff --git a/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap b/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap index 582d626d315..84c4f17fba8 100644 --- a/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap +++ b/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap @@ -1,38 +1,64 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Render should render component 1`] = ` -
+ -
- -
-
+
+
`; exports[`Render should render organization and preferences 1`] = ` -
+ -
-
- - +
+
+ + +
-
-
+ +
`; diff --git a/public/app/features/plugins/PluginListPage.test.tsx b/public/app/features/plugins/PluginListPage.test.tsx index 31b2f128436..31956f41cc1 100644 --- a/public/app/features/plugins/PluginListPage.test.tsx +++ b/public/app/features/plugins/PluginListPage.test.tsx @@ -6,7 +6,14 @@ import { LayoutModes } from '../../core/components/LayoutSelector/LayoutSelector const setup = (propOverrides?: object) => { const props: Props = { - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Plugins' + } + } as NavModel, plugins: [] as Plugin[], searchQuery: '', setPluginsSearchQuery: jest.fn(), diff --git a/public/app/features/plugins/__snapshots__/PluginListPage.test.tsx.snap b/public/app/features/plugins/__snapshots__/PluginListPage.test.tsx.snap index 6444c0c82cc..48f7d638637 100644 --- a/public/app/features/plugins/__snapshots__/PluginListPage.test.tsx.snap +++ b/public/app/features/plugins/__snapshots__/PluginListPage.test.tsx.snap @@ -5,7 +5,16 @@ exports[`Render should render component 1`] = ` title="Configuration: Plugins" > { const props: Props = { - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Team List' + } + } as NavModel, teams: [] as Team[], loadTeams: jest.fn(), deleteTeam: jest.fn(), diff --git a/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap b/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap index d10a2fd2052..cfa9533e1b6 100644 --- a/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap +++ b/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap @@ -2,10 +2,19 @@ exports[`Render should render component 1`] = ` ({ const setup = (propOverrides?: object) => { const props: Props = { - navModel: {} as NavModel, + navModel: { + main: { + text: 'Configuration' + }, + node: { + text: 'Users' + } + } as NavModel, users: [] as OrgUser[], invitees: [] as Invitee[], searchQuery: '', diff --git a/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap b/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap index a6c71f63d53..c6c02562115 100644 --- a/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap +++ b/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap @@ -5,7 +5,16 @@ exports[`Render should render List page 1`] = ` title="Configuration: Users" > Date: Thu, 17 Jan 2019 09:01:17 +0100 Subject: [PATCH 15/17] chore: Reduce code duplication by letting the page component adding the header and taking care of the page title --- public/app/core/components/Page/Page.tsx | 41 +++++++++++------ public/app/features/api-keys/ApiKeysPage.tsx | 5 +- .../__snapshots__/ApiKeysPage.test.tsx.snap | 46 ++++++++----------- .../datasources/DataSourcesListPage.tsx | 5 +- .../DataSourcesListPage.test.tsx.snap | 46 ++++++++----------- public/app/features/org/OrgDetailsPage.tsx | 5 +- .../OrgDetailsPage.test.tsx.snap | 46 ++++++++----------- .../app/features/plugins/PluginListPage.tsx | 5 +- .../PluginListPage.test.tsx.snap | 46 ++++++++----------- public/app/features/teams/TeamList.tsx | 5 +- .../__snapshots__/TeamList.test.tsx.snap | 46 ++++++++----------- public/app/features/users/UsersListPage.tsx | 5 +- .../__snapshots__/UsersListPage.test.tsx.snap | 46 ++++++++----------- 13 files changed, 159 insertions(+), 188 deletions(-) diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index 0197076d150..8c9a5595cb7 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -1,6 +1,8 @@ // Libraries import React, { Component } from 'react'; import config from 'app/core/config'; +import { NavModel } from 'app/types'; +import { getTitleFromNavModel } from 'app/core/selectors/navModel'; // Components import PageHeader from '../PageHeader/PageHeader'; @@ -11,6 +13,7 @@ import { CustomScrollbar } from '@grafana/ui'; interface Props { title?: string; children: JSX.Element[] | JSX.Element; + navModel: NavModel; } class Page extends Component { @@ -35,26 +38,36 @@ class Page extends Component { } updateTitle = () => { - const { title } = this.props; + const title = this.getPageTitle; document.title = title ? title + ' - Grafana' : 'Grafana'; } + get getPageTitle () { + const { navModel } = this.props; + if (navModel) { + return getTitleFromNavModel(navModel) || undefined; + } + return undefined; + } + render() { + const { navModel } = this.props; const { buildInfo } = config; return ( -
- -
- {this.props.children} -
-
-
-
+
+ +
+ + {this.props.children} +
+
+
+
); } } diff --git a/public/app/features/api-keys/ApiKeysPage.tsx b/public/app/features/api-keys/ApiKeysPage.tsx index 4cbd8ce4170..41b9b0c8a55 100644 --- a/public/app/features/api-keys/ApiKeysPage.tsx +++ b/public/app/features/api-keys/ApiKeysPage.tsx @@ -3,7 +3,7 @@ import ReactDOMServer from 'react-dom/server'; import { connect } from 'react-redux'; import { hot } from 'react-hot-loader'; import { NavModel, ApiKey, NewApiKey, OrgRole } from 'app/types'; -import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; import { getApiKeys, getApiKeysCount } from './state/selectors'; import { loadApiKeys, deleteApiKey, setSearchQuery, addApiKey } from './state/actions'; import Page from 'app/core/components/Page/Page'; @@ -239,8 +239,7 @@ export class ApiKeysPage extends PureComponent { const { hasFetched, navModel, apiKeysCount } = this.props; return ( - - + {hasFetched && ( apiKeysCount > 0 ? ( diff --git a/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap b/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap index fd05b79da81..f40894426ae 100644 --- a/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap +++ b/public/app/features/api-keys/__snapshots__/ApiKeysPage.test.tsx.snap @@ -2,20 +2,17 @@ exports[`Render should render API keys table if there are any keys 1`] = ` - + } +> @@ -24,20 +21,17 @@ exports[`Render should render API keys table if there are any keys 1`] = ` exports[`Render should render CTA if there are no API keys 1`] = ` - + } +> diff --git a/public/app/features/datasources/DataSourcesListPage.tsx b/public/app/features/datasources/DataSourcesListPage.tsx index f1c1c45ded8..884df929319 100644 --- a/public/app/features/datasources/DataSourcesListPage.tsx +++ b/public/app/features/datasources/DataSourcesListPage.tsx @@ -8,7 +8,7 @@ import DataSourcesList from './DataSourcesList'; import { DataSource, NavModel, StoreState } from 'app/types'; import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; import { loadDataSources, setDataSourcesLayoutMode, setDataSourcesSearchQuery } from './state/actions'; -import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; import { getDataSources, @@ -67,8 +67,7 @@ export class DataSourcesListPage extends PureComponent { }; return ( - - + <> {hasFetched && dataSourcesCount === 0 && } diff --git a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap index 8c351d1dc2d..63998d43870 100644 --- a/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap +++ b/public/app/features/datasources/__snapshots__/DataSourcesListPage.test.tsx.snap @@ -2,20 +2,17 @@ exports[`Render should render action bar and datasources 1`] = ` - + } +> @@ -160,20 +157,17 @@ exports[`Render should render action bar and datasources 1`] = ` exports[`Render should render component 1`] = ` - + } +> diff --git a/public/app/features/org/OrgDetailsPage.tsx b/public/app/features/org/OrgDetailsPage.tsx index ce84bdefafd..ee644f0006f 100644 --- a/public/app/features/org/OrgDetailsPage.tsx +++ b/public/app/features/org/OrgDetailsPage.tsx @@ -6,7 +6,7 @@ import OrgProfile from './OrgProfile'; import SharedPreferences from 'app/core/components/SharedPreferences/SharedPreferences'; import { loadOrganization, setOrganizationName, updateOrganization } from './state/actions'; import { NavModel, Organization, StoreState } from 'app/types'; -import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; export interface Props { navModel: NavModel; @@ -34,8 +34,7 @@ export class OrgDetailsPage extends PureComponent { const isLoading = Object.keys(organization).length === 0; return ( - - +
{!isLoading && ( diff --git a/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap b/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap index 84c4f17fba8..9e13a73901e 100644 --- a/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap +++ b/public/app/features/org/__snapshots__/OrgDetailsPage.test.tsx.snap @@ -2,20 +2,17 @@ exports[`Render should render component 1`] = ` - + } +> @@ -28,20 +25,17 @@ exports[`Render should render component 1`] = ` exports[`Render should render organization and preferences 1`] = ` - + } +> diff --git a/public/app/features/plugins/PluginListPage.tsx b/public/app/features/plugins/PluginListPage.tsx index 14bd05f0537..3bc0ee545b4 100644 --- a/public/app/features/plugins/PluginListPage.tsx +++ b/public/app/features/plugins/PluginListPage.tsx @@ -6,7 +6,7 @@ import OrgActionBar from 'app/core/components/OrgActionBar/OrgActionBar'; import PluginList from './PluginList'; import { NavModel, Plugin } from 'app/types'; import { loadPlugins, setPluginsLayoutMode, setPluginsSearchQuery } from './state/actions'; -import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; import { getLayoutMode, getPlugins, getPluginsSearchQuery } from './state/selectors'; import { LayoutMode } from 'app/core/components/LayoutSelector/LayoutSelector'; @@ -47,8 +47,7 @@ export class PluginListPage extends PureComponent { }; return ( - - + <> - + } +> @@ -37,20 +34,17 @@ exports[`Render should render component 1`] = ` exports[`Render should render list 1`] = ` - + } +> diff --git a/public/app/features/teams/TeamList.tsx b/public/app/features/teams/TeamList.tsx index 5dd83ca385c..efd279184d4 100644 --- a/public/app/features/teams/TeamList.tsx +++ b/public/app/features/teams/TeamList.tsx @@ -7,7 +7,7 @@ import EmptyListCTA from 'app/core/components/EmptyListCTA/EmptyListCTA'; import { NavModel, Team } from 'app/types'; import { loadTeams, deleteTeam, setSearchQuery } from './state/actions'; import { getSearchQuery, getTeams, getTeamsCount } from './state/selectors'; -import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; export interface Props { navModel: NavModel; @@ -140,8 +140,7 @@ export class TeamList extends PureComponent { const { hasFetched, navModel } = this.props; return ( - - + {hasFetched && this.renderList()} diff --git a/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap b/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap index cfa9533e1b6..812fe05c424 100644 --- a/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap +++ b/public/app/features/teams/__snapshots__/TeamList.test.tsx.snap @@ -2,20 +2,17 @@ exports[`Render should render component 1`] = ` - + } +> @@ -24,20 +21,17 @@ exports[`Render should render component 1`] = ` exports[`Render should render teams table 1`] = ` - + } +> diff --git a/public/app/features/users/UsersListPage.tsx b/public/app/features/users/UsersListPage.tsx index 43fcc67e470..5396603bbde 100644 --- a/public/app/features/users/UsersListPage.tsx +++ b/public/app/features/users/UsersListPage.tsx @@ -9,7 +9,7 @@ import InviteesTable from './InviteesTable'; import { Invitee, NavModel, OrgUser } from 'app/types'; import appEvents from 'app/core/app_events'; import { loadUsers, loadInvitees, setUsersSearchQuery, updateUser, removeUser } from './state/actions'; -import { getNavModel, getTitleFromNavModel } from 'app/core/selectors/navModel'; +import { getNavModel } from 'app/core/selectors/navModel'; import { getInvitees, getUsers, getUsersSearchQuery } from './state/selectors'; export interface Props { @@ -104,8 +104,7 @@ export class UsersListPage extends PureComponent { const externalUserMngInfoHtml = this.externalUserMngInfoHtml; return ( - - + <> diff --git a/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap b/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap index c6c02562115..c8836666c59 100644 --- a/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap +++ b/public/app/features/users/__snapshots__/UsersListPage.test.tsx.snap @@ -2,20 +2,17 @@ exports[`Render should render List page 1`] = ` - + } +> @@ -34,20 +31,17 @@ exports[`Render should render List page 1`] = ` exports[`Render should render component 1`] = ` - + } +> From 71121e1dbea17a931de6a57589353fc1b0ca3074 Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 17 Jan 2019 09:15:47 +0100 Subject: [PATCH 16/17] chore: Wrap footer with React's memo hoc --- public/app/core/components/Footer/Footer.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/app/core/components/Footer/Footer.tsx b/public/app/core/components/Footer/Footer.tsx index 01da74036b6..59ec913c34a 100644 --- a/public/app/core/components/Footer/Footer.tsx +++ b/public/app/core/components/Footer/Footer.tsx @@ -9,7 +9,7 @@ interface Props { newGrafanaVersion: string; } -export const Footer: SFC = ({appName, buildVersion, buildCommit, newGrafanaVersionExists, newGrafanaVersion}) => { +export const Footer: SFC = React.memo(({appName, buildVersion, buildCommit, newGrafanaVersionExists, newGrafanaVersion}) => { return (
@@ -45,6 +45,6 @@ export const Footer: SFC = ({appName, buildVersion, buildCommit, newGrafa
); -}; +}); export default Footer; From 1dfabf498a2eea9e7076a7d56d939cd5236c9f4a Mon Sep 17 00:00:00 2001 From: Johannes Schill Date: Thu, 17 Jan 2019 09:27:43 +0100 Subject: [PATCH 17/17] chore: Replace the deprecated SFC with FC --- public/app/core/components/Animations/FadeIn.tsx | 4 ++-- public/app/core/components/Footer/Footer.tsx | 4 ++-- public/app/core/components/LayoutSelector/LayoutSelector.tsx | 4 ++-- public/app/core/components/PageLoader/PageLoader.tsx | 4 ++-- .../core/components/ToggleButtonGroup/ToggleButtonGroup.tsx | 4 ++-- public/app/core/components/sidemenu/DropDownChild.tsx | 4 ++-- public/app/core/components/sidemenu/SideMenuDropDown.tsx | 4 ++-- public/app/core/components/sidemenu/SignIn.tsx | 4 ++-- public/app/core/components/sidemenu/TopSection.tsx | 4 ++-- public/app/core/components/sidemenu/TopSectionItem.tsx | 4 ++-- .../dashboard/dashgrid/PanelHeader/PanelHeaderMenuItem.tsx | 4 ++-- .../app/features/dashboard/panel_editor/DataSourceOption.tsx | 4 ++-- public/app/features/datasources/DashboardsTable.tsx | 4 ++-- public/app/features/datasources/settings/BasicSettings.tsx | 4 ++-- public/app/features/datasources/settings/ButtonRow.tsx | 4 ++-- public/app/features/explore/Error.tsx | 4 ++-- public/app/features/org/OrgProfile.tsx | 4 ++-- public/app/features/plugins/PluginList.tsx | 4 ++-- public/app/features/plugins/PluginListItem.tsx | 4 ++-- public/app/features/users/UsersTable.tsx | 4 ++-- .../datasource/stackdriver/components/AlignmentPeriods.tsx | 4 ++-- .../plugins/datasource/stackdriver/components/Alignments.tsx | 4 ++-- .../datasource/stackdriver/components/AnnotationsHelp.tsx | 4 ++-- .../datasource/stackdriver/components/SimpleSelect.tsx | 4 ++-- 24 files changed, 48 insertions(+), 48 deletions(-) diff --git a/public/app/core/components/Animations/FadeIn.tsx b/public/app/core/components/Animations/FadeIn.tsx index e12f22486f1..ea9a92d5f0f 100644 --- a/public/app/core/components/Animations/FadeIn.tsx +++ b/public/app/core/components/Animations/FadeIn.tsx @@ -1,4 +1,4 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import Transition from 'react-transition-group/Transition'; interface Props { @@ -8,7 +8,7 @@ interface Props { unmountOnExit?: boolean; } -export const FadeIn: SFC = props => { +export const FadeIn: FC = props => { const defaultStyle = { transition: `opacity ${props.duration}ms linear`, opacity: 0, diff --git a/public/app/core/components/Footer/Footer.tsx b/public/app/core/components/Footer/Footer.tsx index 59ec913c34a..101168beb66 100644 --- a/public/app/core/components/Footer/Footer.tsx +++ b/public/app/core/components/Footer/Footer.tsx @@ -1,4 +1,4 @@ -import React, { SFC } from 'react'; +import React, { FC } from 'react'; import { Tooltip } from '@grafana/ui'; interface Props { @@ -9,7 +9,7 @@ interface Props { newGrafanaVersion: string; } -export const Footer: SFC = React.memo(({appName, buildVersion, buildCommit, newGrafanaVersionExists, newGrafanaVersion}) => { +export const Footer: FC = React.memo(({appName, buildVersion, buildCommit, newGrafanaVersionExists, newGrafanaVersion}) => { return (