From 030370cf6255d1185ecb3deeaab7de1fe76e058b Mon Sep 17 00:00:00 2001 From: Stas Vilchik Date: Mon, 28 Aug 2017 11:41:51 +0200 Subject: add branches help popups (#2420) --- .../src/main/js/components/common/BubblePopup.js | 46 --------- .../src/main/js/components/common/BubblePopup.tsx | 39 +++++++ .../main/js/components/common/BubblePopupHelper.js | 113 --------------------- .../js/components/common/BubblePopupHelper.tsx | 105 +++++++++++++++++++ .../__snapshots__/BubblePopupHelper-test.js.snap | 4 - .../js/components/icons-components/HelpIcon.js | 6 +- 6 files changed, 147 insertions(+), 166 deletions(-) delete mode 100644 server/sonar-web/src/main/js/components/common/BubblePopup.js create mode 100644 server/sonar-web/src/main/js/components/common/BubblePopup.tsx delete mode 100644 server/sonar-web/src/main/js/components/common/BubblePopupHelper.js create mode 100644 server/sonar-web/src/main/js/components/common/BubblePopupHelper.tsx (limited to 'server/sonar-web/src/main/js/components') diff --git a/server/sonar-web/src/main/js/components/common/BubblePopup.js b/server/sonar-web/src/main/js/components/common/BubblePopup.js deleted file mode 100644 index c77167ee53b..00000000000 --- a/server/sonar-web/src/main/js/components/common/BubblePopup.js +++ /dev/null @@ -1,46 +0,0 @@ -/* - * 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 React from 'react'; -import PropTypes from 'prop-types'; -import classNames from 'classnames'; - -export default class BubblePopup extends React.PureComponent { - static propsType = { - children: PropTypes.object.isRequired, - position: PropTypes.object.isRequired, - customClass: PropTypes.string - }; - - static defaultProps = { - customClass: '' - }; - - render() { - const popupClass = classNames('bubble-popup', this.props.customClass); - const popupStyle = { ...this.props.position }; - - return ( -
- {this.props.children} -
-
- ); - } -} diff --git a/server/sonar-web/src/main/js/components/common/BubblePopup.tsx b/server/sonar-web/src/main/js/components/common/BubblePopup.tsx new file mode 100644 index 00000000000..ff2c3b12ee4 --- /dev/null +++ b/server/sonar-web/src/main/js/components/common/BubblePopup.tsx @@ -0,0 +1,39 @@ +/* + * 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 * as classNames from 'classnames'; + +interface Props { + customClass?: string; + children: React.ReactNode; + position: { top: number; right: number }; +} + +export default function BubblePopup(props: Props) { + const popupClass = classNames('bubble-popup', props.customClass); + const popupStyle = { ...props.position }; + + return ( +
+ {props.children} +
+
+ ); +} diff --git a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js deleted file mode 100644 index 48fa517be01..00000000000 --- a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * 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 React from 'react'; -import classNames from 'classnames'; - -/*:: -type Props = { - className?: string, - children?: React.Element<*>, - isOpen: boolean, - offset?: { - vertical: number, - horizontal: number - }, - popup: Object, - position: 'bottomleft' | 'bottomright', - togglePopup: (?boolean) => void -}; -*/ - -/*:: -type State = { - position: { top: number, right: number } -}; -*/ - -export default class BubblePopupHelper extends React.PureComponent { - /*:: props: Props; */ - state /*: State */ = { - position: { - top: 0, - right: 0 - } - }; - - componentDidMount() { - this.setState({ position: this.getPosition(this.props) }); - } - - componentWillReceiveProps(nextProps /*: Props */) { - if (!this.props.isOpen && nextProps.isOpen) { - window.addEventListener('keydown', this.handleKey, false); - window.addEventListener('click', this.handleOutsideClick, false); - } else if (this.props.isOpen && !nextProps.isOpen) { - window.removeEventListener('keydown', this.handleKey); - window.removeEventListener('click', this.handleOutsideClick); - } - } - - handleKey = (evt /*: KeyboardEvent */) => { - // Escape key - if (evt.keyCode === 27) { - this.props.togglePopup(false); - } - }; - - handleOutsideClick = (evt /*: SyntheticInputEvent */) => { - if (!this.popupContainer || !this.popupContainer.contains(evt.target)) { - this.props.togglePopup(false); - } - }; - - handleClick(evt /*: SyntheticInputEvent */) { - evt.stopPropagation(); - } - - getPosition(props /*: Props */) { - const containerPos = this.container.getBoundingClientRect(); - const { position } = props; - const offset = props.offset || { vertical: 0, horizontal: 0 }; - if (position === 'bottomleft') { - return { top: containerPos.height + offset.vertical, left: offset.horizontal }; - } else if (position === 'bottomright') { - return { top: containerPos.height + offset.vertical, right: offset.horizontal }; - } - } - - render() { - return ( -
(this.container = container)} - onClick={this.handleClick} - tabIndex={0} - role="tooltip"> - {this.props.children} - {this.props.isOpen && -
(this.popupContainer = popupContainer)}> - {React.cloneElement(this.props.popup, { - popupPosition: this.state.position - })} -
} -
- ); - } -} diff --git a/server/sonar-web/src/main/js/components/common/BubblePopupHelper.tsx b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.tsx new file mode 100644 index 00000000000..f24365adf57 --- /dev/null +++ b/server/sonar-web/src/main/js/components/common/BubblePopupHelper.tsx @@ -0,0 +1,105 @@ +/* + * 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 * as classNames from 'classnames'; + +interface Props { + className?: string; + children?: React.ReactNode; + isOpen: boolean; + offset?: { vertical: number; horizontal: number }; + popup: React.ReactElement; + position: 'bottomleft' | 'bottomright'; + togglePopup: (show: boolean) => void; +} + +interface State { + position: { top: number; left?: number; right?: number }; +} + +export default class BubblePopupHelper extends React.PureComponent { + container: HTMLElement; + popupContainer: HTMLElement | null; + state: State = { + position: { top: 0, right: 0 } + }; + + componentDidMount() { + this.setState({ position: this.getPosition(this.props) }); + } + + componentWillReceiveProps(nextProps: Props) { + if (!this.props.isOpen && nextProps.isOpen) { + window.addEventListener('keydown', this.handleKey, false); + window.addEventListener('click', this.handleOutsideClick, false); + } else if (this.props.isOpen && !nextProps.isOpen) { + window.removeEventListener('keydown', this.handleKey); + window.removeEventListener('click', this.handleOutsideClick); + } + } + + handleKey = (event: KeyboardEvent) => { + // Escape key + if (event.keyCode === 27) { + this.props.togglePopup(false); + } + }; + + handleOutsideClick = (event: MouseEvent) => { + if (!this.popupContainer || !this.popupContainer.contains(event.target as Node)) { + this.props.togglePopup(false); + } + }; + + handleClick(event: React.SyntheticEvent) { + event.stopPropagation(); + } + + getPosition(props: Props) { + const containerPos = this.container.getBoundingClientRect(); + const { position } = props; + const offset = props.offset || { vertical: 0, horizontal: 0 }; + if (position === 'bottomleft') { + return { top: containerPos.height + offset.vertical, left: offset.horizontal }; + } else { + // if (position === 'bottomright') + return { top: containerPos.height + offset.vertical, right: offset.horizontal }; + } + } + + render() { + return ( +
(this.container = container as HTMLElement)} + onClick={this.handleClick} + tabIndex={0} + role="tooltip"> + {this.props.children} + {this.props.isOpen && +
(this.popupContainer = popupContainer)}> + {React.cloneElement(this.props.popup, { + popupPosition: this.state.position + })} +
} +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/BubblePopupHelper-test.js.snap b/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/BubblePopupHelper-test.js.snap index 3c3b06134cb..9234d2e1550 100644 --- a/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/BubblePopupHelper-test.js.snap +++ b/server/sonar-web/src/main/js/components/common/__tests__/__snapshots__/BubblePopupHelper-test.js.snap @@ -29,7 +29,6 @@ exports[`should correctly handle clicks on the button 2`] = `
-- cgit v1.2.3