diff options
author | stanislavh <stanislav.honcharov@sonarsource.com> | 2024-04-09 11:18:48 +0200 |
---|---|---|
committer | sonartech <sonartech@sonarsource.com> | 2024-04-10 20:02:53 +0000 |
commit | f5dd75ab4b842eb2a5280411cfaceb0c09eea57d (patch) | |
tree | 6b69a9ee971a946b735850eb668c740d07eb7fe1 | |
parent | f480ae1f6255e9cf6b58bd37f2841c0cd20ce31c (diff) | |
download | sonarqube-f5dd75ab4b842eb2a5280411cfaceb0c09eea57d.tar.gz sonarqube-f5dd75ab4b842eb2a5280411cfaceb0c09eea57d.zip |
SONAR-22018 Introduce active version link in footer and system apge
14 files changed, 148 insertions, 33 deletions
diff --git a/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx b/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx index 20c452b06ba..e11b18e6292 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalFooter.tsx @@ -21,12 +21,13 @@ import * as React from 'react'; import DocLink from '../../components/common/DocLink'; import InstanceMessage from '../../components/common/InstanceMessage'; import Link from '../../components/common/Link'; +import AppVersionStatus from '../../components/shared/AppVersionStatus'; import { Alert } from '../../components/ui/Alert'; import { getEdition } from '../../helpers/editions'; -import { translate, translateWithParameters } from '../../helpers/l10n'; +import { translate } from '../../helpers/l10n'; import { AppState } from '../../types/appstate'; -import withAppStateContext from './app-state/withAppStateContext'; import GlobalFooterBranding from './GlobalFooterBranding'; +import withAppStateContext from './app-state/withAppStateContext'; export interface GlobalFooterProps { hideLoggedInInfo?: boolean; @@ -55,26 +56,26 @@ export function GlobalFooter({ hideLoggedInInfo, appState }: GlobalFooterProps) )} {!hideLoggedInInfo && appState?.version && ( <li className="page-footer-menu-item"> - {translateWithParameters('footer.version_x', appState.version)} + <AppVersionStatus /> </li> )} <li className="page-footer-menu-item"> - <a - href="https://www.gnu.org/licenses/lgpl-3.0.txt" + <Link + to="https://www.gnu.org/licenses/lgpl-3.0.txt" rel="noopener noreferrer" target="_blank" > {translate('footer.license')} - </a> + </Link> </li> <li className="page-footer-menu-item"> - <a - href="https://community.sonarsource.com/c/help/sq" + <Link + to="https://community.sonarsource.com/c/help/sq" rel="noopener noreferrer" target="_blank" > {translate('footer.community')} - </a> + </Link> </li> <li className="page-footer-menu-item"> <DocLink to="/">{translate('footer.documentation')}</DocLink> 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..05208a8b2a1 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 @@ -17,29 +17,29 @@ exports[`should display the sq version 1`] = ` <li className="page-footer-menu-item" > - footer.version_x.6.4-SNAPSHOT + <AppVersionStatus /> </li> <li className="page-footer-menu-item" > - <a - href="https://www.gnu.org/licenses/lgpl-3.0.txt" + <ForwardRef(Link) rel="noopener noreferrer" target="_blank" + to="https://www.gnu.org/licenses/lgpl-3.0.txt" > footer.license - </a> + </ForwardRef(Link)> </li> <li className="page-footer-menu-item" > - <a - href="https://community.sonarsource.com/c/help/sq" + <ForwardRef(Link) rel="noopener noreferrer" target="_blank" + to="https://community.sonarsource.com/c/help/sq" > footer.community - </a> + </ForwardRef(Link)> </li> <li className="page-footer-menu-item" @@ -84,24 +84,24 @@ exports[`should not render the only logged in information 1`] = ` <li className="page-footer-menu-item" > - <a - href="https://www.gnu.org/licenses/lgpl-3.0.txt" + <ForwardRef(Link) rel="noopener noreferrer" target="_blank" + to="https://www.gnu.org/licenses/lgpl-3.0.txt" > footer.license - </a> + </ForwardRef(Link)> </li> <li className="page-footer-menu-item" > - <a - href="https://community.sonarsource.com/c/help/sq" + <ForwardRef(Link) rel="noopener noreferrer" target="_blank" + to="https://community.sonarsource.com/c/help/sq" > footer.community - </a> + </ForwardRef(Link)> </li> <li className="page-footer-menu-item" @@ -142,29 +142,29 @@ exports[`should render the only logged in information 1`] = ` <li className="page-footer-menu-item" > - footer.version_x.1.0 + <AppVersionStatus /> </li> <li className="page-footer-menu-item" > - <a - href="https://www.gnu.org/licenses/lgpl-3.0.txt" + <ForwardRef(Link) rel="noopener noreferrer" target="_blank" + to="https://www.gnu.org/licenses/lgpl-3.0.txt" > footer.license - </a> + </ForwardRef(Link)> </li> <li className="page-footer-menu-item" > - <a - href="https://community.sonarsource.com/c/help/sq" + <ForwardRef(Link) rel="noopener noreferrer" target="_blank" + to="https://community.sonarsource.com/c/help/sq" > footer.community - </a> + </ForwardRef(Link)> </li> <li className="page-footer-menu-item" diff --git a/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx b/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx index eeedf321faf..c9ae626f0e7 100644 --- a/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx +++ b/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx @@ -28,5 +28,6 @@ export const DEFAULT_APP_STATE = { qualifiers: [], settings: {}, version: '', + versionEOL: '', }; export const AppStateContext = React.createContext<AppState>(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..59a0d40fa40 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 @@ -13,6 +13,7 @@ exports[`should set value correctly 1`] = ` "sonar.lf.logoUrl": "whatevs/", }, "version": "1.0", + "versionEOL": "2022-01-01", } } /> diff --git a/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx b/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx index 8b42de90487..5a7be0e1a21 100644 --- a/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx +++ b/server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx @@ -43,3 +43,7 @@ export default function withAppStateContext<P>( } }; } + +export function useAppState() { + return React.useContext(AppStateContext); +} diff --git a/server/sonar-web/src/main/js/app/components/extensions/__tests__/__snapshots__/Extension-test.tsx.snap b/server/sonar-web/src/main/js/app/components/extensions/__tests__/__snapshots__/Extension-test.tsx.snap index 2aece96de23..32b49f0abe2 100644 --- a/server/sonar-web/src/main/js/app/components/extensions/__tests__/__snapshots__/Extension-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/extensions/__tests__/__snapshots__/Extension-test.tsx.snap @@ -11,6 +11,7 @@ exports[`should render React extensions correctly 1`] = ` ], "settings": {}, "version": "1.0", + "versionEOL": "2022-01-01", } } currentUser={ @@ -73,6 +74,7 @@ exports[`should render React extensions correctly 2`] = ` ], "settings": {}, "version": "1.0", + "versionEOL": "2022-01-01", } } currentUser={ diff --git a/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationContextProvider-test.tsx.snap b/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationContextProvider-test.tsx.snap index b2fda45425a..641e0b9a63e 100644 --- a/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationContextProvider-test.tsx.snap +++ b/server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationContextProvider-test.tsx.snap @@ -12,6 +12,7 @@ exports[`should render correctly and start polling if issue sync is needed 1`] = ], "settings": {}, "version": "1.0", + "versionEOL": "2022-01-01", } } > diff --git a/server/sonar-web/src/main/js/apps/system/components/PageHeader.tsx b/server/sonar-web/src/main/js/apps/system/components/PageHeader.tsx index e6b768af8e7..4ebabc0abb1 100644 --- a/server/sonar-web/src/main/js/apps/system/components/PageHeader.tsx +++ b/server/sonar-web/src/main/js/apps/system/components/PageHeader.tsx @@ -20,6 +20,7 @@ import * as React from 'react'; import withAppStateContext from '../../../app/components/app-state/withAppStateContext'; import { ClipboardButton } from '../../../components/controls/clipboard'; +import AppVersionStatus from '../../../components/shared/AppVersionStatus'; import { Alert } from '../../../components/ui/Alert'; import { toShortNotSoISOString } from '../../../helpers/dates'; import { translate } from '../../../helpers/l10n'; @@ -79,7 +80,9 @@ export function PageHeader(props: Props) { <th> <strong>{translate('system.version')}</strong> </th> - <td>{version}</td> + <td> + <AppVersionStatus /> + </td> </tr> </tbody> </table> diff --git a/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/PageHeader-test.tsx.snap b/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/PageHeader-test.tsx.snap index c8ef70f9e61..cad0c680de6 100644 --- a/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/PageHeader-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/PageHeader-test.tsx.snap @@ -85,7 +85,7 @@ exports[`should render correctly 3`] = ` </strong> </th> <td> - 7.7.0.1234 + <AppVersionStatus /> </td> </tr> </tbody> @@ -160,7 +160,7 @@ exports[`should render correctly: on embedded database 1`] = ` </strong> </th> <td> - 7.7.0.1234 + <AppVersionStatus /> </td> </tr> </tbody> diff --git a/server/sonar-web/src/main/js/components/shared/AppVersionStatus.tsx b/server/sonar-web/src/main/js/components/shared/AppVersionStatus.tsx new file mode 100644 index 00000000000..91e961695e7 --- /dev/null +++ b/server/sonar-web/src/main/js/components/shared/AppVersionStatus.tsx @@ -0,0 +1,48 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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 { FormattedMessage } from 'react-intl'; +import { useAppState } from '../../app/components/app-state/withAppStateContext'; +import { now, parseDate } from '../../helpers/dates'; +import { translate } from '../../helpers/l10n'; +import DocLink from '../common/DocLink'; + +export default function AppVersionStatus() { + const { version, versionEOL } = useAppState(); + const isActive = parseDate(versionEOL) > now(); + + return ( + <FormattedMessage + id="footer.version" + defaultMessage={translate('footer.version')} + values={{ + version, + status: ( + <DocLink + to="/setup-and-upgrade/upgrade-the-server/active-versions/" + className="little-spacer-left" + > + {translate(`footer.version.status.${isActive ? 'active' : 'inactive'}`)} + </DocLink> + ), + }} + /> + ); +} diff --git a/server/sonar-web/src/main/js/components/shared/__tests__/AppVersionStatus-test.tsx b/server/sonar-web/src/main/js/components/shared/__tests__/AppVersionStatus-test.tsx new file mode 100644 index 00000000000..f60dba440bb --- /dev/null +++ b/server/sonar-web/src/main/js/components/shared/__tests__/AppVersionStatus-test.tsx @@ -0,0 +1,50 @@ +/* + * SonarQube + * Copyright (C) 2009-2024 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 { screen } from '@testing-library/react'; +import React from 'react'; +import AppStateContextProvider from '../../../app/components/app-state/AppStateContextProvider'; +import AppVersionStatus from '../../../components/shared/AppVersionStatus'; +import { mockAppState } from '../../../helpers/testMocks'; +import { renderComponent } from '../../../helpers/testReactTestingUtils'; + +jest.mock('../../../helpers/dates', () => ({ + ...jest.requireActual('../../../helpers/dates'), + now: () => new Date('2022-01-01'), +})); + +it('should render active version if it has not reached EOL', () => { + renderAppVersionStatus(mockAppState({ versionEOL: '2022-01-02' })); + + expect(screen.getByRole('link', { name: /footer.version.status.active/ })).toBeInTheDocument(); +}); + +it('should render inactive version if it has reached EOL', () => { + renderAppVersionStatus(mockAppState({ versionEOL: '2021-12-30' })); + + expect(screen.getByRole('link', { name: /footer.version.status.inactive/ })).toBeInTheDocument(); +}); + +const renderAppVersionStatus = (appState = mockAppState()) => { + return renderComponent( + <AppStateContextProvider appState={appState}> + <AppVersionStatus /> + </AppStateContextProvider> + ); +}; diff --git a/server/sonar-web/src/main/js/helpers/testMocks.ts b/server/sonar-web/src/main/js/helpers/testMocks.ts index efa1c1602a7..f08cc766963 100644 --- a/server/sonar-web/src/main/js/helpers/testMocks.ts +++ b/server/sonar-web/src/main/js/helpers/testMocks.ts @@ -76,6 +76,7 @@ export function mockAppState(overrides: Partial<AppState> = {}): AppState { qualifiers: ['TRK'], settings: {}, version: '1.0', + versionEOL: '2022-01-01', ...overrides, }; } diff --git a/server/sonar-web/src/main/js/types/appstate.ts b/server/sonar-web/src/main/js/types/appstate.ts index 6d31f5b09e0..3701a3901a1 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; + versionEOL: string; } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index fabcfb1630c..30ceba145ea 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -3531,7 +3531,9 @@ footer.security=Security footer.status=Status footer.terms=Terms footer.twitter=Twitter -footer.version_x=Version {0} +footer.version=v{version}{status} +footer.version.status.active=ACTIVE +footer.version.status.inactive=NO LONGER ACTIVE footer.web_api=Web API |