From 059cf8688eafd9f151a1fad84997ce77e5af511e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Fri, 29 Sep 2017 15:03:12 +0200 Subject: [PATCH] SONAR-9792 Fix sidebar position with a notification --- .../apps/component-measures/components/App.js | 25 ++++--- .../__tests__/__snapshots__/App-test.js.snap | 27 +------- .../src/main/js/apps/issues/components/App.js | 17 ++--- .../components/QualityGatesApp.js | 21 +++--- .../js/apps/web-api/components/WebApiApp.tsx | 55 ++++++++------- .../common/ScreenPositionHelper.tsx | 67 +++++++++++++++++++ 6 files changed, 132 insertions(+), 80 deletions(-) create mode 100644 server/sonar-web/src/main/js/components/common/ScreenPositionHelper.tsx diff --git a/server/sonar-web/src/main/js/apps/component-measures/components/App.js b/server/sonar-web/src/main/js/apps/component-measures/components/App.js index a9fc88958ad..a33340530ea 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/components/App.js +++ b/server/sonar-web/src/main/js/apps/component-measures/components/App.js @@ -24,6 +24,7 @@ import key from 'keymaster'; import MeasureContentContainer from './MeasureContentContainer'; import MeasureOverviewContainer from './MeasureOverviewContainer'; import Sidebar from '../sidebar/Sidebar'; +import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; import { hasBubbleChart, parseQuery, serializeQuery } from '../utils'; import { getBranchName } from '../../../helpers/branches'; import { translate } from '../../../helpers/l10n'; @@ -148,19 +149,21 @@ export default class App extends React.PureComponent {
-
-
-
-
- + + {({ top }) => ( +
+
+
+ +
-
-
+ )} + {metric != null && ( -
-
-
-
- -
-
-
-
+ /> -
-
- {openIssue == null ? this.renderFacets() : this.renderConciseIssuesList()} + + {({ top }) => ( +
+
+ {openIssue == null ? this.renderFacets() : this.renderConciseIssuesList()} +
-
-
+ )} + ); } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js index 1499f139787..b756fee0c39 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js @@ -22,6 +22,7 @@ import PropTypes from 'prop-types'; import Helmet from 'react-helmet'; import ListHeader from './ListHeader'; import List from './List'; +import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; import { fetchQualityGatesAppDetails, fetchQualityGates as fetchQualityGatesAPI @@ -67,22 +68,22 @@ export default class QualityGatesApp extends Component { render() { const { children, qualityGates, edit, organization } = this.props; const defaultTitle = translate('quality_gates.page'); - const top = organization ? 95 : 30; return (
-
-
-
-
- - {qualityGates && } + + {({ top }) => ( +
+
+
+ + {qualityGates && } +
-
-
- + )} + {qualityGates != null && React.Children.map(children, child => React.cloneElement(child, { organization }))}
diff --git a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx index 3a69c4bc4c6..ebc579d5ca5 100644 --- a/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx +++ b/server/sonar-web/src/main/js/apps/web-api/components/WebApiApp.tsx @@ -25,6 +25,7 @@ import { Domain as DomainType, fetchWebApi } from '../../../api/web-api'; import Menu from './Menu'; import Search from './Search'; import Domain from './Domain'; +import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper'; import { getActionKey, isDomainPathActive } from '../utils'; import { scrollToElement } from '../../../helpers/scrolling'; import { translate } from '../../../helpers/l10n'; @@ -141,35 +142,37 @@ export default class WebApiApp extends React.PureComponent { return (
-
-
-
-
-
- -

{translate('api_documentation.page')}

- + + {({ top }) => ( +
+
+
+
+ +

{translate('api_documentation.page')}

+ +
+ + + +
- - - -
-
-
+ )} +
diff --git a/server/sonar-web/src/main/js/components/common/ScreenPositionHelper.tsx b/server/sonar-web/src/main/js/components/common/ScreenPositionHelper.tsx new file mode 100644 index 00000000000..00f8f375766 --- /dev/null +++ b/server/sonar-web/src/main/js/components/common/ScreenPositionHelper.tsx @@ -0,0 +1,67 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +import * as React from 'react'; +import { throttle } from 'lodash'; + +interface Props { + className?: string; + children: (position: { top: number; left: number }) => React.ReactElement; +} + +interface State { + position: { top: number; left: number }; +} + +export default class ScreenPositionHelper extends React.PureComponent { + container: HTMLDivElement; + throttledUpdatePosition: () => void; + + constructor(props: Props) { + super(props); + this.state = { position: { top: 0, left: 0 } }; + this.throttledUpdatePosition = throttle(this.updatePosition, 100); + } + + componentDidMount() { + this.updatePosition(); + window.addEventListener('resize', this.throttledUpdatePosition); + } + + componentWillUnmount() { + window.removeEventListener('resize', this.throttledUpdatePosition); + } + + updatePosition = () => { + const containerPos = this.container.getBoundingClientRect(); + this.setState({ + position: { top: window.scrollY + containerPos.top, left: window.scrollX + containerPos.left } + }); + }; + + render() { + return ( +
(this.container = container as HTMLDivElement)}> + {this.props.children(this.state.position)} +
+ ); + } +} -- 2.39.5