diff options
author | Jeremy Davis <jeremy.davis@sonarsource.com> | 2022-05-04 17:22:54 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2022-05-05 20:02:57 +0000 |
commit | 5c53289c4b21a17b5e97eea39312fcdca050c03f (patch) | |
tree | a1a226e22e6e6956c176851ab79cd80abc374754 /server/sonar-web/src/main/js/app/components | |
parent | 9ac71a6077ea468ab40086968cab2d1ae22ef766 (diff) | |
download | sonarqube-5c53289c4b21a17b5e97eea39312fcdca050c03f.tar.gz sonarqube-5c53289c4b21a17b5e97eea39312fcdca050c03f.zip |
SONAR-16206 Improve code sharing for security reports
Diffstat (limited to 'server/sonar-web/src/main/js/app/components')
23 files changed, 8 insertions, 995 deletions
diff --git a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx index b02e8c98ebc..6bc280ca84f 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalContainer.tsx @@ -18,11 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import A11yProvider from '../../components/a11y/A11yProvider'; +import A11ySkipLinks from '../../components/a11y/A11ySkipLinks'; +import SuggestionsProvider from '../../components/embed-docs-modal/SuggestionsProvider'; import Workspace from '../../components/workspace/Workspace'; -import A11yProvider from './a11y/A11yProvider'; -import A11ySkipLinks from './a11y/A11ySkipLinks'; import BranchStatusContextProvider from './branch-status/BranchStatusContextProvider'; -import SuggestionsProvider from './embed-docs-modal/SuggestionsProvider'; import GlobalFooter from './GlobalFooter'; import IndexationContextProvider from './indexation/IndexationContextProvider'; import IndexationNotification from './indexation/IndexationNotification'; diff --git a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.tsx b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.tsx index 6f150e21f8c..b806154db88 100644 --- a/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/ProjectAdminContainer.tsx @@ -18,10 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import A11ySkipTarget from '../../components/a11y/A11ySkipTarget'; import { BranchLike } from '../../types/branch-like'; import { Component } from '../../types/types'; import handleRequiredAuthorization from '../utils/handleRequiredAuthorization'; -import A11ySkipTarget from './a11y/A11ySkipTarget'; interface Props { children: JSX.Element; diff --git a/server/sonar-web/src/main/js/app/components/__tests__/GlobalContainer-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/GlobalContainer-test.tsx index 6643512ad52..e094b6512df 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/GlobalContainer-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/GlobalContainer-test.tsx @@ -22,7 +22,7 @@ import * as React from 'react'; import { mockLocation } from '../../../helpers/testMocks'; import GlobalContainer, { Props } from '../GlobalContainer'; -jest.mock('../embed-docs-modal/SuggestionsProvider', () => { +jest.mock('../../../components/embed-docs-modal/SuggestionsProvider', () => { class SuggestionsProvider extends React.Component { render() { return this.props.children; diff --git a/server/sonar-web/src/main/js/app/components/a11y/A11yContext.tsx b/server/sonar-web/src/main/js/app/components/a11y/A11yContext.tsx deleted file mode 100644 index 345b9caeb3c..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/A11yContext.tsx +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { createContext } from 'react'; -import { A11ySkipLink } from '../../../types/types'; - -export interface A11yContextShape { - addA11ySkipLink: (link: A11ySkipLink) => void; - removeA11ySkipLink: (link: A11ySkipLink) => void; - links: A11ySkipLink[]; -} - -export const A11yContext = createContext<A11yContextShape>({ - addA11ySkipLink: () => {}, - removeA11ySkipLink: () => {}, - links: [] -}); diff --git a/server/sonar-web/src/main/js/app/components/a11y/A11yProvider.tsx b/server/sonar-web/src/main/js/app/components/a11y/A11yProvider.tsx deleted file mode 100644 index 59906929985..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/A11yProvider.tsx +++ /dev/null @@ -1,61 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { sortBy } from 'lodash'; -import * as React from 'react'; -import { A11ySkipLink } from '../../../types/types'; -import { A11yContext } from './A11yContext'; - -interface State { - links: A11ySkipLink[]; -} - -export default class A11yProvider extends React.Component<{}, State> { - keys: string[] = []; - state: State = { links: [] }; - - addA11ySkipLink = (link: A11ySkipLink) => { - this.setState(prevState => { - const links = [...prevState.links]; - links.push({ ...link, weight: link.weight || 0 }); - return { links }; - }); - }; - - removeA11ySkipLink = (link: A11ySkipLink) => { - this.setState(prevState => { - const links = prevState.links.filter(l => l.key !== link.key); - return { links }; - }); - }; - - render() { - const links = sortBy(this.state.links, 'weight'); - return ( - <A11yContext.Provider - value={{ - addA11ySkipLink: this.addA11ySkipLink, - links, - removeA11ySkipLink: this.removeA11ySkipLink - }}> - {this.props.children} - </A11yContext.Provider> - ); - } -} diff --git a/server/sonar-web/src/main/js/app/components/a11y/A11ySkipLinks.css b/server/sonar-web/src/main/js/app/components/a11y/A11ySkipLinks.css deleted file mode 100644 index e1eabb6f279..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/A11ySkipLinks.css +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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. - */ -.a11y-skip-link { - width: 0; - height: 0; - padding: var(--gridSize); - position: absolute; - left: -9999px; - top: -9999px; - border: 0; - font-size: 1rem; - text-align: center; - z-index: 999; -} - -.a11y-skip-link:focus { - width: auto; - height: auto; - left: 6px; - top: 6px; - color: white; - background-color: var(--globalNavBarBg); - text-decoration: underline; -} diff --git a/server/sonar-web/src/main/js/app/components/a11y/A11ySkipLinks.tsx b/server/sonar-web/src/main/js/app/components/a11y/A11ySkipLinks.tsx deleted file mode 100644 index 8af879bbec2..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/A11ySkipLinks.tsx +++ /dev/null @@ -1,36 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { A11yContext } from './A11yContext'; -import './A11ySkipLinks.css'; - -export default function A11ySkipLinks() { - return ( - <A11yContext.Consumer> - {({ links }) => - links.map(link => ( - <a className="a11y-skip-link" href={`#a11y_target__${link.key}`} key={link.key}> - {link.label} - </a> - )) - } - </A11yContext.Consumer> - ); -} diff --git a/server/sonar-web/src/main/js/app/components/a11y/A11ySkipTarget.tsx b/server/sonar-web/src/main/js/app/components/a11y/A11ySkipTarget.tsx deleted file mode 100644 index 3cd3b14949b..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/A11ySkipTarget.tsx +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { translate } from '../../../helpers/l10n'; -import { A11ySkipLink } from '../../../types/types'; -import { A11yContext } from './A11yContext'; - -interface Props { - anchor: string; - label?: string; - weight?: number; -} - -export default function A11ySkipTarget(props: Props) { - return ( - <A11yContext.Consumer> - {({ addA11ySkipLink, removeA11ySkipLink }) => ( - <A11ySkipTargetInner - addA11ySkipLink={addA11ySkipLink} - removeA11ySkipLink={removeA11ySkipLink} - {...props} - /> - )} - </A11yContext.Consumer> - ); -} - -interface InnerProps { - addA11ySkipLink: (link: A11ySkipLink) => void; - removeA11ySkipLink: (link: A11ySkipLink) => void; -} - -export class A11ySkipTargetInner extends React.PureComponent<Props & InnerProps> { - componentDidMount() { - this.props.addA11ySkipLink(this.getLink()); - } - - componentWillUnmount() { - this.props.removeA11ySkipLink(this.getLink()); - } - - getLink = (): A11ySkipLink => { - const { anchor: key, label = translate('skip_to_content'), weight } = this.props; - return { key, label, weight }; - }; - - render() { - const { anchor } = this.props; - return <span id={`a11y_target__${anchor}`} />; - } -} diff --git a/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11yProvider-test.tsx b/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11yProvider-test.tsx deleted file mode 100644 index 70a6dc437f6..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11yProvider-test.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { waitAndUpdate } from '../../../../helpers/testUtils'; -import { A11yContextShape } from '../A11yContext'; -import A11yProvider from '../A11yProvider'; - -const link1 = { key: 'link1', label: 'Link 1', weight: 0 }; -const link2 = { key: 'link2', label: 'Link 2', weight: -10 }; -const link3 = { key: 'link3', label: 'Link 3', weight: 0 }; - -it('should allow to register new skip links', () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - expect(wrapper.state('links')).toEqual([]); - - // Check that an absence of weight is treated as "0". - instance.addA11ySkipLink({ ...link1, weight: undefined }); - expect(wrapper.state('links')).toEqual([link1]); - - instance.addA11ySkipLink(link2); - expect(wrapper.state('links')).toEqual([link1, link2]); -}); - -it('should pass the ordered links to the consumers', () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - instance.setState({ links: [link1, link2, link3] }); - waitAndUpdate(wrapper); - expect((wrapper.prop('value') as A11yContextShape).links).toEqual([link2, link1, link3]); -}); - -it('should allow to unregister skip links', () => { - const wrapper = shallowRender(); - const instance = wrapper.instance(); - instance.setState({ links: [link1, link2, link3] }); - - instance.removeA11ySkipLink(link1); - expect(wrapper.state('links')).toEqual([link2, link3]); - - instance.removeA11ySkipLink(link2); - expect(wrapper.state('links')).toEqual([link3]); -}); - -function shallowRender() { - return shallow<A11yProvider>( - <A11yProvider> - <div /> - </A11yProvider> - ); -} diff --git a/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11ySkipLinks-test.tsx b/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11ySkipLinks-test.tsx deleted file mode 100644 index f19805d53af..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11ySkipLinks-test.tsx +++ /dev/null @@ -1,39 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import A11ySkipLinks from '../A11ySkipLinks'; - -jest.mock('../A11yContext', () => ({ - A11yContext: { - Consumer: ({ children }: any) => { - return children({ - links: [ - { key: 'link1', label: 'Label 1' }, - { key: 'link2', label: 'Label 2' } - ] - }); - } - } -})); - -it('should render correctly', () => { - expect(shallow(<A11ySkipLinks />).dive()).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11ySkipTarget-test.tsx b/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11ySkipTarget-test.tsx deleted file mode 100644 index 55083e63a02..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/__tests__/A11ySkipTarget-test.tsx +++ /dev/null @@ -1,41 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { mount } from 'enzyme'; -import * as React from 'react'; -import { A11ySkipTargetInner } from '../A11ySkipTarget'; - -it('should render correctly, and (un)register the link when (un)mounted', () => { - const link = { key: 'main', label: 'Skip to content' }; - const addA11ySkipLink = jest.fn(); - const removeA11ySkipLink = jest.fn(); - const wrapper = mount( - <A11ySkipTargetInner - addA11ySkipLink={addA11ySkipLink} - anchor={link.key} - label={link.label} - removeA11ySkipLink={removeA11ySkipLink} - /> - ); - - expect(wrapper).toMatchSnapshot(); - expect(addA11ySkipLink).toBeCalledWith(link); - wrapper.unmount(); - expect(removeA11ySkipLink).toBeCalledWith(link); -}); diff --git a/server/sonar-web/src/main/js/app/components/a11y/__tests__/__snapshots__/A11ySkipLinks-test.tsx.snap b/server/sonar-web/src/main/js/app/components/a11y/__tests__/__snapshots__/A11ySkipLinks-test.tsx.snap deleted file mode 100644 index a8a148a13c6..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/__tests__/__snapshots__/A11ySkipLinks-test.tsx.snap +++ /dev/null @@ -1,20 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly 1`] = ` -Array [ - <a - className="a11y-skip-link" - href="#a11y_target__link1" - key="link1" - > - Label 1 - </a>, - <a - className="a11y-skip-link" - href="#a11y_target__link2" - key="link2" - > - Label 2 - </a>, -] -`; diff --git a/server/sonar-web/src/main/js/app/components/a11y/__tests__/__snapshots__/A11ySkipTarget-test.tsx.snap b/server/sonar-web/src/main/js/app/components/a11y/__tests__/__snapshots__/A11ySkipTarget-test.tsx.snap deleted file mode 100644 index 8fa473020e6..00000000000 --- a/server/sonar-web/src/main/js/app/components/a11y/__tests__/__snapshots__/A11ySkipTarget-test.tsx.snap +++ /dev/null @@ -1,32 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render correctly, and (un)register the link when (un)mounted 1`] = ` -<A11ySkipTargetInner - addA11ySkipLink={ - [MockFunction] { - "calls": Array [ - Array [ - Object { - "key": "main", - "label": "Skip to content", - "weight": undefined, - }, - ], - ], - "results": Array [ - Object { - "type": "return", - "value": undefined, - }, - ], - } - } - anchor="main" - label="Skip to content" - removeA11ySkipLink={[MockFunction]} -> - <span - id="a11y_target__main" - /> -</A11ySkipTargetInner> -`; diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx deleted file mode 100644 index 1a2b64ac260..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopup.tsx +++ /dev/null @@ -1,112 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { Link } from 'react-router'; -import { DropdownOverlay } from '../../../components/controls/Dropdown'; -import { translate } from '../../../helpers/l10n'; -import { getBaseUrl } from '../../../helpers/system'; -import { SuggestionLink } from '../../../types/types'; -import { SuggestionsContext } from './SuggestionsContext'; - -interface Props { - onClose: () => void; -} - -export default class EmbedDocsPopup extends React.PureComponent<Props> { - renderTitle(text: string) { - return <li className="menu-header">{text}</li>; - } - - renderSuggestions = ({ suggestions }: { suggestions: SuggestionLink[] }) => { - if (suggestions.length === 0) { - return null; - } - return ( - <> - {this.renderTitle(translate('embed_docs.suggestion'))} - {suggestions.map((suggestion, index) => ( - <li key={index}> - <Link onClick={this.props.onClose} target="_blank" to={suggestion.link}> - {suggestion.text} - </Link> - </li> - ))} - <li className="divider" /> - </> - ); - }; - - renderIconLink(link: string, icon: string, text: string) { - return ( - <a href={link} rel="noopener noreferrer" target="_blank"> - <img - alt={text} - className="spacer-right" - height="18" - src={`${getBaseUrl()}/images/${icon}`} - width="18" - /> - {text} - </a> - ); - } - - render() { - return ( - <DropdownOverlay> - <ul className="menu abs-width-240"> - <SuggestionsContext.Consumer>{this.renderSuggestions}</SuggestionsContext.Consumer> - <li> - <Link onClick={this.props.onClose} target="_blank" to="/documentation"> - {translate('embed_docs.documentation')} - </Link> - </li> - <li> - <Link onClick={this.props.onClose} to="/web_api"> - {translate('api_documentation.page')} - </Link> - </li> - <li className="divider" /> - <li> - <a href="https://community.sonarsource.com/" rel="noopener noreferrer" target="_blank"> - {translate('embed_docs.get_help')} - </a> - </li> - <li className="divider" /> - {this.renderTitle(translate('embed_docs.stay_connected'))} - <li> - {this.renderIconLink( - 'https://www.sonarqube.org/whats-new/?referrer=sonarqube', - 'embed-doc/sq-icon.svg', - translate('embed_docs.news') - )} - </li> - <li> - {this.renderIconLink( - 'https://twitter.com/SonarQube', - 'embed-doc/twitter-icon.svg', - 'Twitter' - )} - </li> - </ul> - </DropdownOverlay> - ); - } -} diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopupHelper.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopupHelper.tsx deleted file mode 100644 index e0249a6e9f1..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/EmbedDocsPopupHelper.tsx +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { ButtonLink } from '../../../components/controls/buttons'; -import Toggler from '../../../components/controls/Toggler'; -import HelpIcon from '../../../components/icons/HelpIcon'; -import { lazyLoadComponent } from '../../../components/lazyLoadComponent'; -import { translate } from '../../../helpers/l10n'; - -const EmbedDocsPopup = lazyLoadComponent(() => import('./EmbedDocsPopup')); - -interface State { - helpOpen: boolean; -} - -export default class EmbedDocsPopupHelper extends React.PureComponent<{}, State> { - mounted = false; - state: State = { helpOpen: false }; - - setHelpDisplay = (helpOpen: boolean) => { - this.setState({ helpOpen }); - }; - - handleClick = () => { - this.toggleHelp(); - }; - - toggleHelp = () => { - this.setState(state => { - return { helpOpen: !state.helpOpen }; - }); - }; - - closeHelp = () => { - this.setState({ helpOpen: false }); - }; - - render() { - return ( - <li className="dropdown"> - <Toggler - onRequestClose={this.closeHelp} - open={this.state.helpOpen} - overlay={<EmbedDocsPopup onClose={this.closeHelp} />}> - <ButtonLink - aria-expanded={this.state.helpOpen} - aria-haspopup={true} - className="navbar-help navbar-icon" - onClick={this.handleClick} - title={translate('help')}> - <HelpIcon /> - </ButtonLink> - </Toggler> - </li> - ); - } -} diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/Suggestions.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/Suggestions.tsx deleted file mode 100644 index 9cf36bac567..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/Suggestions.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { SuggestionsContext } from './SuggestionsContext'; - -interface Props { - suggestions: string; -} - -export default function Suggestions({ suggestions }: Props) { - return ( - <SuggestionsContext.Consumer> - {({ addSuggestions, removeSuggestions }) => ( - <SuggestionsInner - addSuggestions={addSuggestions} - removeSuggestions={removeSuggestions} - suggestions={suggestions} - /> - )} - </SuggestionsContext.Consumer> - ); -} - -interface SuggestionsInnerProps { - addSuggestions: (key: string) => void; - removeSuggestions: (key: string) => void; - suggestions: string; -} - -class SuggestionsInner extends React.PureComponent<SuggestionsInnerProps> { - componentDidMount() { - this.props.addSuggestions(this.props.suggestions); - } - - componentDidUpdate(prevProps: Props) { - if (prevProps.suggestions !== this.props.suggestions) { - this.props.removeSuggestions(this.props.suggestions); - this.props.addSuggestions(prevProps.suggestions); - } - } - - componentWillUnmount() { - this.props.removeSuggestions(this.props.suggestions); - } - - render() { - return null; - } -} diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/SuggestionsContext.ts b/server/sonar-web/src/main/js/app/components/embed-docs-modal/SuggestionsContext.ts deleted file mode 100644 index fcb5c85561b..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/SuggestionsContext.ts +++ /dev/null @@ -1,33 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { createContext } from 'react'; -import { SuggestionLink } from '../../../types/types'; - -interface SuggestionsContextShape { - addSuggestions: (key: string) => void; - removeSuggestions: (key: string) => void; - suggestions: SuggestionLink[]; -} - -export const SuggestionsContext = createContext<SuggestionsContextShape>({ - addSuggestions: () => {}, - removeSuggestions: () => {}, - suggestions: [] -}); diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/SuggestionsProvider.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/SuggestionsProvider.tsx deleted file mode 100644 index ffc6788ab0c..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/SuggestionsProvider.tsx +++ /dev/null @@ -1,72 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 suggestionsJson from 'Docs/EmbedDocsSuggestions.json'; -import * as React from 'react'; -import { isSonarCloud } from '../../../helpers/system'; -import { Dict, SuggestionLink } from '../../../types/types'; -import { SuggestionsContext } from './SuggestionsContext'; - -type SuggestionsJson = Dict<SuggestionLink[]>; - -interface State { - suggestions: SuggestionLink[]; -} - -export default class SuggestionsProvider extends React.Component<{}, State> { - keys: string[] = []; - state: State = { suggestions: [] }; - - fetchSuggestions = () => { - const jsonList = suggestionsJson as SuggestionsJson; - let suggestions: SuggestionLink[] = []; - this.keys.forEach(key => { - if (jsonList[key]) { - suggestions = [...jsonList[key], ...suggestions]; - } - }); - if (!isSonarCloud()) { - suggestions = suggestions.filter(suggestion => suggestion.scope !== 'sonarcloud'); - } - this.setState({ suggestions }); - }; - - addSuggestions = (newKey: string) => { - this.keys = [...this.keys, newKey]; - this.fetchSuggestions(); - }; - - removeSuggestions = (oldKey: string) => { - this.keys = this.keys.filter(key => key !== oldKey); - this.fetchSuggestions(); - }; - - render() { - return ( - <SuggestionsContext.Provider - value={{ - addSuggestions: this.addSuggestions, - removeSuggestions: this.removeSuggestions, - suggestions: this.state.suggestions - }}> - {this.props.children} - </SuggestionsContext.Provider> - ); - } -} diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/EmbedDocsPopup-test.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/EmbedDocsPopup-test.tsx deleted file mode 100644 index f12348ed514..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/EmbedDocsPopup-test.tsx +++ /dev/null @@ -1,27 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import EmbedDocsPopup from '../EmbedDocsPopup'; - -it('should render', () => { - const wrapper = shallow(<EmbedDocsPopup onClose={jest.fn()} />); - expect(wrapper).toMatchSnapshot(); -}); diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/SuggestionsProvider-test.tsx b/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/SuggestionsProvider-test.tsx deleted file mode 100644 index 194ee3d19d9..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/SuggestionsProvider-test.tsx +++ /dev/null @@ -1,77 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2022 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 { shallow } from 'enzyme'; -import * as React from 'react'; -import { isSonarCloud } from '../../../../helpers/system'; -import SuggestionsProvider from '../SuggestionsProvider'; - -jest.mock( - 'Docs/EmbedDocsSuggestions.json', - () => ({ - pageA: [ - { link: '/foo', text: 'Foo' }, - { link: '/bar', text: 'Bar', scope: 'sonarcloud' } - ], - pageB: [{ link: '/qux', text: 'Qux' }] - }), - { virtual: true } -); - -jest.mock('../../../../helpers/system', () => ({ isSonarCloud: jest.fn() })); - -it('should add & remove suggestions', () => { - (isSonarCloud as jest.Mock).mockReturnValue(false); - const wrapper = shallow<SuggestionsProvider>( - <SuggestionsProvider> - <div /> - </SuggestionsProvider> - ); - const instance = wrapper.instance(); - expect(wrapper.state('suggestions')).toEqual([]); - - instance.addSuggestions('pageA'); - expect(wrapper.state('suggestions')).toEqual([{ link: '/foo', text: 'Foo' }]); - - instance.addSuggestions('pageB'); - expect(wrapper.state('suggestions')).toEqual([ - { link: '/qux', text: 'Qux' }, - { link: '/foo', text: 'Foo' } - ]); - - instance.removeSuggestions('pageA'); - expect(wrapper.state('suggestions')).toEqual([{ link: '/qux', text: 'Qux' }]); -}); - -it('should show sonarcloud pages', () => { - (isSonarCloud as jest.Mock).mockReturnValue(true); - const wrapper = shallow<SuggestionsProvider>( - <SuggestionsProvider> - <div /> - </SuggestionsProvider> - ); - const instance = wrapper.instance(); - expect(wrapper.state('suggestions')).toEqual([]); - - instance.addSuggestions('pageA'); - expect(wrapper.state('suggestions')).toEqual([ - { link: '/foo', text: 'Foo' }, - { link: '/bar', text: 'Bar', scope: 'sonarcloud' } - ]); -}); diff --git a/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/__snapshots__/EmbedDocsPopup-test.tsx.snap b/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/__snapshots__/EmbedDocsPopup-test.tsx.snap deleted file mode 100644 index 29a379acaca..00000000000 --- a/server/sonar-web/src/main/js/app/components/embed-docs-modal/__tests__/__snapshots__/EmbedDocsPopup-test.tsx.snap +++ /dev/null @@ -1,86 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`should render 1`] = ` -<DropdownOverlay> - <ul - className="menu abs-width-240" - > - <ContextConsumer> - <Component /> - </ContextConsumer> - <li> - <Link - onClick={[MockFunction]} - onlyActiveOnIndex={false} - style={Object {}} - target="_blank" - to="/documentation" - > - embed_docs.documentation - </Link> - </li> - <li> - <Link - onClick={[MockFunction]} - onlyActiveOnIndex={false} - style={Object {}} - to="/web_api" - > - api_documentation.page - </Link> - </li> - <li - className="divider" - /> - <li> - <a - href="https://community.sonarsource.com/" - rel="noopener noreferrer" - target="_blank" - > - embed_docs.get_help - </a> - </li> - <li - className="divider" - /> - <li - className="menu-header" - > - embed_docs.stay_connected - </li> - <li> - <a - href="https://www.sonarqube.org/whats-new/?referrer=sonarqube" - rel="noopener noreferrer" - target="_blank" - > - <img - alt="embed_docs.news" - className="spacer-right" - height="18" - src="/images/embed-doc/sq-icon.svg" - width="18" - /> - embed_docs.news - </a> - </li> - <li> - <a - href="https://twitter.com/SonarQube" - rel="noopener noreferrer" - target="_blank" - > - <img - alt="Twitter" - className="spacer-right" - height="18" - src="/images/embed-doc/twitter-icon.svg" - width="18" - /> - Twitter - </a> - </li> - </ul> -</DropdownOverlay> -`; diff --git a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts index b534527ce4f..98ee13683b4 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts +++ b/server/sonar-web/src/main/js/app/components/extensions/exposeLibraries.ts @@ -19,6 +19,7 @@ */ import { FormattedMessage } from 'react-intl'; import NotFound from '../../../app/components/NotFound'; +import A11ySkipTarget from '../../../components/a11y/A11ySkipTarget'; import DonutChart from '../../../components/charts/DonutChart'; import ActionsDropdown, { ActionsDropdownItem } from '../../../components/controls/ActionsDropdown'; import BoxedTabs from '../../../components/controls/BoxedTabs'; @@ -45,6 +46,7 @@ import Select, { SearchSelect } from '../../../components/controls/Select'; import SelectList, { SelectListFilter } from '../../../components/controls/SelectList'; import SimpleModal from '../../../components/controls/SimpleModal'; import Tooltip from '../../../components/controls/Tooltip'; +import Suggestions from '../../../components/embed-docs-modal/Suggestions'; import AlertErrorIcon from '../../../components/icons/AlertErrorIcon'; import AlertSuccessIcon from '../../../components/icons/AlertSuccessIcon'; import AlertWarnIcon from '../../../components/icons/AlertWarnIcon'; @@ -118,8 +120,6 @@ import { getMeasureHistoryUrl, getRulesUrl } from '../../../helpers/urls'; -import A11ySkipTarget from '../a11y/A11ySkipTarget'; -import Suggestions from '../embed-docs-modal/Suggestions'; const exposeLibraries = () => { const global = window as any; diff --git a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx index 0c7b6d964cc..6dd85f5fde4 100644 --- a/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx +++ b/server/sonar-web/src/main/js/app/components/nav/global/GlobalNav.tsx @@ -18,11 +18,11 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import EmbedDocsPopupHelper from '../../../../components/embed-docs-modal/EmbedDocsPopupHelper'; import NavBar from '../../../../components/ui/NavBar'; import { CurrentUser } from '../../../../types/users'; import { rawSizes } from '../../../theme'; import withCurrentUserContext from '../../current-user/withCurrentUserContext'; -import EmbedDocsPopupHelper from '../../embed-docs-modal/EmbedDocsPopupHelper'; import Search from '../../search/Search'; import './GlobalNav.css'; import GlobalNavBranding from './GlobalNavBranding'; |