aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorstanislavh <stanislav.honcharov@sonarsource.com>2024-04-09 11:18:48 +0200
committersonartech <sonartech@sonarsource.com>2024-04-10 20:02:53 +0000
commitf5dd75ab4b842eb2a5280411cfaceb0c09eea57d (patch)
tree6b69a9ee971a946b735850eb668c740d07eb7fe1
parentf480ae1f6255e9cf6b58bd37f2841c0cd20ce31c (diff)
downloadsonarqube-f5dd75ab4b842eb2a5280411cfaceb0c09eea57d.tar.gz
sonarqube-f5dd75ab4b842eb2a5280411cfaceb0c09eea57d.zip
SONAR-22018 Introduce active version link in footer and system apge
-rw-r--r--server/sonar-web/src/main/js/app/components/GlobalFooter.tsx19
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/__snapshots__/GlobalFooter-test.tsx.snap40
-rw-r--r--server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx1
-rw-r--r--server/sonar-web/src/main/js/app/components/app-state/__tests__/__snapshots__/AppStateContextProvider-test.tsx.snap1
-rw-r--r--server/sonar-web/src/main/js/app/components/app-state/withAppStateContext.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/components/extensions/__tests__/__snapshots__/Extension-test.tsx.snap2
-rw-r--r--server/sonar-web/src/main/js/app/components/indexation/__tests__/__snapshots__/IndexationContextProvider-test.tsx.snap1
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/PageHeader.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/system/components/__tests__/__snapshots__/PageHeader-test.tsx.snap4
-rw-r--r--server/sonar-web/src/main/js/components/shared/AppVersionStatus.tsx48
-rw-r--r--server/sonar-web/src/main/js/components/shared/__tests__/AppVersionStatus-test.tsx50
-rw-r--r--server/sonar-web/src/main/js/helpers/testMocks.ts1
-rw-r--r--server/sonar-web/src/main/js/types/appstate.ts1
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties4
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