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';
<div className="layout-page" id="component-measures">
<Helmet title={translate('layout.measures')} />
- <div className="layout-page-side-outer">
- <div className="layout-page-side" style={{ top: 95 }}>
- <div className="layout-page-side-inner">
- <div className="layout-page-filters">
- <Sidebar
- measures={this.state.measures}
- selectedMetric={query.metric}
- updateQuery={this.updateQuery}
- />
+ <ScreenPositionHelper className="layout-page-side-outer">
+ {({ top }) => (
+ <div className="layout-page-side" style={{ top }}>
+ <div className="layout-page-side-inner">
+ <div className="layout-page-filters">
+ <Sidebar
+ measures={this.state.measures}
+ selectedMetric={query.metric}
+ updateQuery={this.updateQuery}
+ />
+ </div>
</div>
</div>
- </div>
- </div>
+ )}
+ </ScreenPositionHelper>
{metric != null && (
<MeasureContentContainer
encodeSpecialCharacters={true}
title="layout.measures"
/>
- <div
+ <ScreenPositionHelper
className="layout-page-side-outer"
- >
- <div
- className="layout-page-side"
- style={
- Object {
- "top": 95,
- }
- }
- >
- <div
- className="layout-page-side-inner"
- >
- <div
- className="layout-page-filters"
- >
- <Sidebar
- measures={Array []}
- selectedMetric="coverage"
- updateQuery={[Function]}
- />
- </div>
- </div>
- </div>
- </div>
+ />
<MeasureContentContainer
className="layout-page-main"
fetchMeasures={[Function]}
} from '../utils'; */
import ListFooter from '../../../components/controls/ListFooter';
import EmptySearch from '../../../components/common/EmptySearch';
+import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper';
import { getBranchName } from '../../../helpers/branches';
import { translate, translateWithParameters } from '../../../helpers/l10n';
import { scrollToElement } from '../../../helpers/scrolling';
}
renderSide(openIssue /*: ?Issue */) {
- const top = this.props.component || this.props.organization ? 95 : 30;
-
return (
- <div className="layout-page-side-outer">
- <div className="layout-page-side" style={{ top }}>
- <div className="layout-page-side-inner">
- {openIssue == null ? this.renderFacets() : this.renderConciseIssuesList()}
+ <ScreenPositionHelper className="layout-page-side-outer">
+ {({ top }) => (
+ <div className="layout-page-side" style={{ top }}>
+ <div className="layout-page-side-inner">
+ {openIssue == null ? this.renderFacets() : this.renderConciseIssuesList()}
+ </div>
</div>
- </div>
- </div>
+ )}
+ </ScreenPositionHelper>
);
}
import Helmet from 'react-helmet';
import ListHeader from './ListHeader';
import List from './List';
+import ScreenPositionHelper from '../../../components/common/ScreenPositionHelper';
import {
fetchQualityGatesAppDetails,
fetchQualityGates as fetchQualityGatesAPI
render() {
const { children, qualityGates, edit, organization } = this.props;
const defaultTitle = translate('quality_gates.page');
- const top = organization ? 95 : 30;
return (
<div id="quality-gates-page" className="layout-page">
<Helmet defaultTitle={defaultTitle} titleTemplate={'%s - ' + defaultTitle} />
- <div className="layout-page-side-outer">
- <div className="layout-page-side" style={{ top }}>
- <div className="layout-page-side-inner">
- <div className="layout-page-filters">
- <ListHeader canEdit={edit} onAdd={this.handleAdd.bind(this)} />
- {qualityGates && <List organization={organization} qualityGates={qualityGates} />}
+ <ScreenPositionHelper className="layout-page-side-outer">
+ {({ top }) => (
+ <div className="layout-page-side" style={{ top }}>
+ <div className="layout-page-side-inner">
+ <div className="layout-page-filters">
+ <ListHeader canEdit={edit} onAdd={this.handleAdd.bind(this)} />
+ {qualityGates && <List organization={organization} qualityGates={qualityGates} />}
+ </div>
</div>
</div>
- </div>
- </div>
-
+ )}
+ </ScreenPositionHelper>
{qualityGates != null &&
React.Children.map(children, child => React.cloneElement(child, { organization }))}
</div>
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';
return (
<div className="layout-page">
<Helmet title={translate('api_documentation.page')} />
- <div className="layout-page-side-outer">
- <div className="layout-page-side" style={{ top: 30 }}>
- <div className="layout-page-side-inner">
- <div className="layout-page-filters">
- <div className="web-api-page-header">
- <Link to="/web_api/">
- <h1>{translate('api_documentation.page')}</h1>
- </Link>
+ <ScreenPositionHelper className="layout-page-side-outer">
+ {({ top }) => (
+ <div className="layout-page-side" style={{ top }}>
+ <div className="layout-page-side-inner">
+ <div className="layout-page-filters">
+ <div className="web-api-page-header">
+ <Link to="/web_api/">
+ <h1>{translate('api_documentation.page')}</h1>
+ </Link>
+ </div>
+
+ <Search
+ showDeprecated={showDeprecated}
+ showInternal={showInternal}
+ onSearch={this.handleSearch}
+ onToggleInternal={this.handleToggleInternal}
+ onToggleDeprecated={this.handleToggleDeprecated}
+ />
+
+ <Menu
+ domains={this.state.domains}
+ showDeprecated={showDeprecated}
+ showInternal={showInternal}
+ searchQuery={searchQuery}
+ splat={splat}
+ />
</div>
-
- <Search
- showDeprecated={showDeprecated}
- showInternal={showInternal}
- onSearch={this.handleSearch}
- onToggleInternal={this.handleToggleInternal}
- onToggleDeprecated={this.handleToggleDeprecated}
- />
-
- <Menu
- domains={this.state.domains}
- showDeprecated={showDeprecated}
- showInternal={showInternal}
- searchQuery={searchQuery}
- splat={splat}
- />
</div>
</div>
- </div>
- </div>
+ )}
+ </ScreenPositionHelper>
<div className="layout-page-main">
<div className="layout-page-main-inner">
--- /dev/null
+/*
+ * 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<any>;
+}
+
+interface State {
+ position: { top: number; left: number };
+}
+
+export default class ScreenPositionHelper extends React.PureComponent<Props, State> {
+ 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 (
+ <div
+ className={this.props.className}
+ ref={container => (this.container = container as HTMLDivElement)}>
+ {this.props.children(this.state.position)}
+ </div>
+ );
+ }
+}