From: stanislavh Date: Thu, 4 May 2023 08:26:09 +0000 (+0200) Subject: SONAR-18503 Read documentation base URL from backend to generate documentation link X-Git-Tag: 10.1.0.73491~342 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=8ba0e9b1c53d3621054abf26d60524d4fa45fc87;p=sonarqube.git SONAR-18503 Read documentation base URL from backend to generate documentation link --- diff --git a/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx b/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx index 88a0eaa06c7..dd9a2cc148e 100644 --- a/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx +++ b/server/sonar-web/src/main/js/app/components/DocumentationRedirect.tsx @@ -21,14 +21,13 @@ import * as React from 'react'; import { Helmet } from 'react-helmet-async'; import { useLocation } from 'react-router-dom'; import Link from '../../components/common/Link'; -import { getUrlForDoc } from '../../helpers/docs'; -import withAppStateContext, { WithAppStateContextProps } from './app-state/withAppStateContext'; +import { useDocUrl } from '../../helpers/docs'; const PAUSE_REDIRECT = 1; -function DocumentationRedirect({ appState }: WithAppStateContextProps) { +export default function DocumentationRedirect() { const location = useLocation(); - const url = getUrlForDoc(appState.version, location.pathname.replace(/^\/documentation/, '')); + const url = useDocUrl(location.pathname.replace(/^\/documentation/, '')); return ( <> @@ -47,5 +46,3 @@ function DocumentationRedirect({ appState }: WithAppStateContextProps) { ); } - -export default withAppStateContext(DocumentationRedirect); diff --git a/server/sonar-web/src/main/js/app/components/__tests__/DocumentationRedirect-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/DocumentationRedirect-test.tsx index 49e54de4d34..a8db8911181 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/DocumentationRedirect-test.tsx +++ b/server/sonar-web/src/main/js/app/components/__tests__/DocumentationRedirect-test.tsx @@ -25,16 +25,16 @@ import { renderAppRoutes } from '../../../helpers/testReactTestingUtils'; import DocumentationRedirect from '../DocumentationRedirect'; it('should redirect to static doc for specific version', async () => { - renderDocumentationRedirect('land', '9.7.1234'); + renderDocumentationRedirect('land', '10.0'); expect(await screen.findByRole('link')).toHaveAttribute( 'href', - 'https://docs.sonarqube.org/9.7/land' + 'https://docs.sonarqube.org/10.0/land' ); }); it('should redirect to static doc for latest version', async () => { - renderDocumentationRedirect('land', '9.7-SNAPSHOT'); + renderDocumentationRedirect('land', '10.0-SNAPSHOT'); expect(await screen.findByRole('link')).toHaveAttribute( 'href', @@ -42,9 +42,9 @@ it('should redirect to static doc for latest version', async () => { ); }); -function renderDocumentationRedirect(navigatge: string, version?: string) { +function renderDocumentationRedirect(navigate: string, version?: string) { renderAppRoutes( - `documentation/${navigatge}`, + `documentation/${navigate}`, () => } />, { appState: mockAppState({ version }) } ); diff --git a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap index 492e71658d2..6769c24e32a 100644 --- a/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap @@ -44,20 +44,20 @@ exports[`should display the sq version 1`] = `
  • - footer.documentation - +
  • - footer.plugins - +
  • - footer.documentation - +
  • - footer.plugins - +
  • @@ -169,20 +169,20 @@ exports[`should render the only logged in information 1`] = `
  • - footer.documentation - +
  • - footer.plugins - +
  • (DEFAULT_APP_STATE); diff --git a/server/sonar-web/src/main/js/app/components/app-state/__tests__/__snapshots__/AppStateContextProvider-test.tsx.snap b/server/sonar-web/src/main/js/app/components/app-state/__tests__/__snapshots__/AppStateContextProvider-test.tsx.snap index dbdc02fa1c4..9881aed06e7 100644 --- a/server/sonar-web/src/main/js/app/components/app-state/__tests__/__snapshots__/AppStateContextProvider-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/app-state/__tests__/__snapshots__/AppStateContextProvider-test.tsx.snap @@ -4,6 +4,7 @@ exports[`should set value correctly 1`] = ` { id="maintenance.sonarqube_is_under_maintenance.2" values={{ link: ( - here, as it relies on AppState. However, the maintenance - // app is a special app that can run in a "downgraded" environment, where the AppState - // may not yet be fully loaded. Hence, we link to this documentation page directly. - to="https://docs.sonarqube.org/latest/setup-and-upgrade/upgrade-the-server/upgrade-guide/" - target="_blank" - > + {translate('maintenance.sonarqube_is_under_maintenance_link.2')} - + ), }} /> diff --git a/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap index 423ae4b0dd4..dddad9f865d 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/App-test.tsx.snap @@ -43,11 +43,11 @@ exports[`should render correctly: loaded 1`] = ` id="marketplace.page.plugins.description2" values={ { - "link": marketplace.page.plugins.description2.link - , + , } } /> @@ -140,11 +140,11 @@ exports[`should render correctly: loading 1`] = ` id="marketplace.page.plugins.description2" values={ { - "link": marketplace.page.plugins.description2.link - , + , } } /> diff --git a/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx b/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx index e8f6fc3c1bc..0cbadd8fc01 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/ApplicationNonCaycProjectWarning.tsx @@ -19,11 +19,8 @@ */ import { Card, FlagMessage, Link } from 'design-system'; import * as React from 'react'; -import withAppStateContext, { - WithAppStateContextProps, -} from '../../../app/components/app-state/withAppStateContext'; import { getBranchLikeQuery } from '../../../helpers/branch-like'; -import { getUrlForDoc } from '../../../helpers/docs'; +import { useDocUrl } from '../../../helpers/docs'; import { translate, translateWithParameters } from '../../../helpers/l10n'; import { getProjectQueryUrl } from '../../../helpers/urls'; import { QualityGateStatus } from '../../../types/quality-gates'; @@ -34,16 +31,9 @@ interface Props { caycStatus: CaycStatus; } -function ApplicationNonCaycProjectWarning({ - projects, - caycStatus, - appState, -}: Props & WithAppStateContextProps) { - const caycUrl = getUrlForDoc(appState.version, '/user-guide/clean-as-you-code/'); - const caycDrawbacksUrl = getUrlForDoc( - appState.version, - '/user-guide/clean-as-you-code/#potential-drawbacks' - ); +export default function ApplicationNonCaycProjectWarning({ projects, caycStatus }: Props) { + const caycUrl = useDocUrl('/user-guide/clean-as-you-code/'); + const caycDrawbacksUrl = useDocUrl('/user-guide/clean-as-you-code/#potential-drawbacks'); return ( @@ -89,5 +79,3 @@ function ApplicationNonCaycProjectWarning({ ); } - -export default withAppStateContext(ApplicationNonCaycProjectWarning); diff --git a/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx b/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx index 746f5fa5a7f..d54f177c953 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarning.tsx @@ -20,10 +20,7 @@ import { DiscreetLink, FlagMessage, Link } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; -import withAppStateContext, { - WithAppStateContextProps, -} from '../../../app/components/app-state/withAppStateContext'; -import { getUrlForDoc } from '../../../helpers/docs'; +import { useDocUrl } from '../../../helpers/docs'; import { translate } from '../../../helpers/l10n'; import { getQualityGateUrl } from '../../../helpers/urls'; import { Component } from '../../../types/types'; @@ -32,8 +29,8 @@ interface Props { component: Pick; } -function CleanAsYouCodeWarning({ component, appState }: Props & WithAppStateContextProps) { - const caycUrl = getUrlForDoc(appState.version, '/user-guide/clean-as-you-code/'); +export default function CleanAsYouCodeWarning({ component }: Props) { + const caycUrl = useDocUrl('/user-guide/clean-as-you-code/'); return ( <> @@ -65,5 +62,3 @@ function CleanAsYouCodeWarning({ component, appState }: Props & WithAppStateCont ); } - -export default withAppStateContext(CleanAsYouCodeWarning); diff --git a/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarningOverCompliant.tsx b/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarningOverCompliant.tsx index c2a5e08982e..38a2b966f99 100644 --- a/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarningOverCompliant.tsx +++ b/server/sonar-web/src/main/js/apps/overview/branches/CleanAsYouCodeWarningOverCompliant.tsx @@ -20,10 +20,7 @@ import { DiscreetLink, Link } from 'design-system'; import * as React from 'react'; import { FormattedMessage } from 'react-intl'; -import withAppStateContext, { - WithAppStateContextProps, -} from '../../../app/components/app-state/withAppStateContext'; -import { getUrlForDoc } from '../../../helpers/docs'; +import { useDocUrl } from '../../../helpers/docs'; import { translate } from '../../../helpers/l10n'; import { getQualityGateUrl } from '../../../helpers/urls'; import { Component } from '../../../types/types'; @@ -32,14 +29,8 @@ interface Props { component: Pick; } -function CleanAsYouCodeWarningOverCompliant({ - component, - appState, -}: Props & WithAppStateContextProps) { - const caycDrawbackUrl = getUrlForDoc( - appState.version, - '/user-guide/clean-as-you-code/#potential-drawbacks' - ); +export default function CleanAsYouCodeWarningOverCompliant({ component }: Props) { + const caycDrawbackUrl = useDocUrl('/user-guide/clean-as-you-code/#potential-drawbacks'); return ( <> @@ -71,5 +62,3 @@ function CleanAsYouCodeWarningOverCompliant({ ); } - -export default withAppStateContext(CleanAsYouCodeWarningOverCompliant); diff --git a/server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/PageHeader-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/PageHeader-test.tsx.snap index b5ea540762f..f0c9b17a863 100644 --- a/server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/PageHeader-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/quality-profiles/home/__tests__/__snapshots__/PageHeader-test.tsx.snap @@ -15,12 +15,12 @@ exports[`should render correctly 1`] = ` quality_profiles.intro1
    quality_profiles.intro2 - learn_more - + `; @@ -58,12 +58,12 @@ exports[`should render correctly 2`] = ` quality_profiles.intro1
    quality_profiles.intro2 - learn_more - + `; @@ -107,12 +107,12 @@ exports[`should render correctly 3`] = ` quality_profiles.intro1
    quality_profiles.intro2 - learn_more - + `; @@ -150,12 +150,12 @@ exports[`should show a create form 1`] = ` quality_profiles.intro1
    quality_profiles.intro2 - learn_more - + quality_profiles.intro2 - learn_more - + { }); function renderDeactivateForm(user: UserActive) { - return render( - - - + return renderComponent( + ); } diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/PageHeader-test.tsx.snap b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/PageHeader-test.tsx.snap index 14d8687ab1e..ac418761feb 100644 --- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/PageHeader-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/PageHeader-test.tsx.snap @@ -21,11 +21,11 @@ exports[`should render correctly 1`] = ` id="webhooks.description" values={ { - "url": webhooks.documentation_link - , + , } } /> diff --git a/server/sonar-web/src/main/js/components/common/DocLink.tsx b/server/sonar-web/src/main/js/components/common/DocLink.tsx index 08c01031675..6039b2d1b30 100644 --- a/server/sonar-web/src/main/js/components/common/DocLink.tsx +++ b/server/sonar-web/src/main/js/components/common/DocLink.tsx @@ -18,18 +18,12 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import withAppStateContext, { - WithAppStateContextProps, -} from '../../app/components/app-state/withAppStateContext'; -import { getUrlForDoc } from '../../helpers/docs'; +import { useDocUrl } from '../../helpers/docs'; import Link, { LinkProps } from './Link'; -type Props = WithAppStateContextProps & - Omit & { to: string; innerRef?: React.Ref }; +type Props = Omit & { to: string; innerRef?: React.Ref }; -export function DocLink({ appState, to, innerRef, ...props }: Props) { - const toStatic = getUrlForDoc(appState.version, to); +export default function DocLink({ to, innerRef, ...props }: Props) { + const toStatic = useDocUrl(to); return ; } - -export default withAppStateContext(DocLink); diff --git a/server/sonar-web/src/main/js/components/embed-docs-modal/DocItemLink.tsx b/server/sonar-web/src/main/js/components/embed-docs-modal/DocItemLink.tsx index dd5939ff1d9..083c5856d29 100644 --- a/server/sonar-web/src/main/js/components/embed-docs-modal/DocItemLink.tsx +++ b/server/sonar-web/src/main/js/components/embed-docs-modal/DocItemLink.tsx @@ -20,9 +20,7 @@ import { ItemLink, OpenNewTabIcon } from 'design-system'; import * as React from 'react'; -import { AppStateContext } from '../../app/components/app-state/AppStateContext'; - -import { getUrlForDoc } from '../../helpers/docs'; +import { useDocUrl } from '../../helpers/docs'; interface Props { to: string; @@ -31,9 +29,7 @@ interface Props { } export function DocItemLink({ to, innerRef, children }: Props) { - const { version } = React.useContext(AppStateContext); - - const toStatic = getUrlForDoc(version, to); + const toStatic = useDocUrl(to); return ( diff --git a/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap index 2ab2d84ff4d..b9494c41c54 100644 --- a/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap +++ b/server/sonar-web/src/main/js/components/upgrade/__tests__/__snapshots__/SystemUpgradeItem-test.tsx.snap @@ -89,12 +89,12 @@ exports[`should display correctly 1`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; @@ -188,12 +188,12 @@ exports[`should display correctly 2`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; @@ -280,12 +280,12 @@ exports[`should display correctly 3`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; @@ -379,12 +379,12 @@ exports[`should display correctly 4`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; @@ -478,12 +478,12 @@ exports[`should display correctly 5`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; @@ -577,12 +577,12 @@ exports[`should display correctly 6`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; @@ -657,12 +657,12 @@ exports[`should display correctly 7`] = ` > system.download_x.5.6.7 - system.how_to_upgrade - + `; diff --git a/server/sonar-web/src/main/js/helpers/docs.ts b/server/sonar-web/src/main/js/helpers/docs.ts index 5bcb593339f..1e106d55f24 100644 --- a/server/sonar-web/src/main/js/helpers/docs.ts +++ b/server/sonar-web/src/main/js/helpers/docs.ts @@ -17,13 +17,20 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -const VERSION_PARSER = /^(\d+\.\d+).*$/; +import React from 'react'; +import { AppStateContext } from '../app/components/app-state/AppStateContext'; -export function getUrlForDoc(version: string, to: string) { - const versionPrefix = VERSION_PARSER.exec(version); +export function getUrlForDoc(url: string, version: string, to: string) { const isSnapshot = version.indexOf('SNAPSHOT') !== -1; - const docPrefix = - versionPrefix && versionPrefix.length === 2 && !isSnapshot ? versionPrefix[1] : 'latest'; + const path = to.replace(/^\//, ''); - return `https://docs.sonarqube.org/${docPrefix}${to}`; + return isSnapshot + ? `${url.replace(url.slice(url.lastIndexOf('/')), '/latest')}/${path}` + : `${url}/${path}`; +} + +export function useDocUrl(to: string) { + const { version, documentationUrl } = React.useContext(AppStateContext); + + return getUrlForDoc(documentationUrl, version, to); } diff --git a/server/sonar-web/src/main/js/helpers/testMocks.ts b/server/sonar-web/src/main/js/helpers/testMocks.ts index c5646eff516..fe4dd38fa58 100644 --- a/server/sonar-web/src/main/js/helpers/testMocks.ts +++ b/server/sonar-web/src/main/js/helpers/testMocks.ts @@ -74,6 +74,7 @@ export function mockAppState(overrides: Partial = {}): AppState { qualifiers: ['TRK'], settings: {}, version: '1.0', + documentationUrl: 'https://docs.sonarqube.org/10.0', ...overrides, }; } diff --git a/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx b/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx index 55e58f6a28c..53c99fe652a 100644 --- a/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx +++ b/server/sonar-web/src/main/js/helpers/testReactTestingUtils.tsx @@ -90,16 +90,22 @@ export function renderAppWithAdminContext( ); } -export function renderComponent(component: React.ReactElement, pathname = '/') { +export function renderComponent( + component: React.ReactElement, + pathname = '/', + { appState = mockAppState() }: RenderContext = {} +) { function Wrapper({ children }: { children: React.ReactElement }) { return ( - - - - - + + + + + + + ); diff --git a/server/sonar-web/src/main/js/types/appstate.ts b/server/sonar-web/src/main/js/types/appstate.ts index 7e45a4e8e2a..8b5e53b562e 100644 --- a/server/sonar-web/src/main/js/types/appstate.ts +++ b/server/sonar-web/src/main/js/types/appstate.ts @@ -35,4 +35,5 @@ export interface AppState { standalone?: boolean; version: string; webAnalyticsJsPath?: string; + documentationUrl: string; }