aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-ui-common/components/ui/update-center
diff options
context:
space:
mode:
authorPhilippe Perrin <philippe.perrin@sonarsource.com>2021-07-15 15:55:30 +0200
committersonartech <sonartech@sonarsource.com>2021-07-21 20:03:01 +0000
commita57b5dd4d8ba48dd55a80111f1c6db54cb36c63d (patch)
treef382d2c7b08747e2b7d1cea7fa87550bac3882df /server/sonar-ui-common/components/ui/update-center
parent1dff5a612667788aed965d14945767b277a2b313 (diff)
downloadsonarqube-a57b5dd4d8ba48dd55a80111f1c6db54cb36c63d.tar.gz
sonarqube-a57b5dd4d8ba48dd55a80111f1c6db54cb36c63d.zip
SONAR-14617 Embed the sonar-ui-common library
Diffstat (limited to 'server/sonar-ui-common/components/ui/update-center')
-rw-r--r--server/sonar-ui-common/components/ui/update-center/MetaData.css102
-rw-r--r--server/sonar-ui-common/components/ui/update-center/MetaData.tsx123
-rw-r--r--server/sonar-ui-common/components/ui/update-center/MetaDataVersion.tsx99
-rw-r--r--server/sonar-ui-common/components/ui/update-center/MetaDataVersions.tsx85
-rw-r--r--server/sonar-ui-common/components/ui/update-center/__tests__/MetaData-test.tsx87
-rw-r--r--server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersion-test.tsx46
-rw-r--r--server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersions-test.tsx52
-rw-r--r--server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaData-test.tsx.snap133
-rw-r--r--server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersion-test.tsx.snap113
-rw-r--r--server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersions-test.tsx.snap28
-rw-r--r--server/sonar-ui-common/components/ui/update-center/mocks/update-center-metadata.ts58
-rw-r--r--server/sonar-ui-common/components/ui/update-center/update-center-metadata.ts49
12 files changed, 975 insertions, 0 deletions
diff --git a/server/sonar-ui-common/components/ui/update-center/MetaData.css b/server/sonar-ui-common/components/ui/update-center/MetaData.css
new file mode 100644
index 00000000000..582d6633757
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/MetaData.css
@@ -0,0 +1,102 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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.
+ */
+
+.update-center-meta-data {
+ margin: 16px 0;
+ padding: 16px 16px 8px 16px;
+ background: #f9f9fb;
+ border: 1px solid #e6e6e6;
+ border-radius: 3px;
+}
+
+.update-center-meta-data a svg {
+ margin-right: 8px;
+}
+
+.update-center-meta-data-header {
+ border-bottom: 1px solid #cfd3d7;
+ padding-bottom: 16px;
+}
+
+.update-center-meta-data-header,
+.update-center-meta-data-version-release-info,
+.update-center-meta-data-version-links {
+ display: flex;
+}
+
+.update-center-meta-data-header > * + *,
+.update-center-meta-data-version-release-info > * + * {
+ margin-left: 16px;
+}
+
+.update-center-meta-data-header > * + * {
+ padding-left: 16px;
+ border-left: 1px solid #cfd3d7;
+}
+
+.update-center-meta-data-versions {
+ margin-top: 16px;
+}
+
+.update-center-meta-data-versions-show-more {
+ font-size: 14px;
+ float: right;
+ color: #51575a;
+ border-color: #7b8184;
+ border-width: 0 0 1px 0;
+ padding-left: 0;
+ padding-right: 0;
+ background: transparent;
+ cursor: pointer;
+}
+
+.update-center-meta-data-versions-show-more:hover {
+ color: #2d3032;
+ border-color: #2d3032;
+}
+
+.update-center-meta-data-version {
+ margin-bottom: 16px;
+}
+
+.update-center-meta-data-version + .update-center-meta-data-version {
+ padding-top: 8px;
+ border-top: 1px dashed #cfd3d7;
+}
+
+.update-center-meta-data-version-version {
+ font-weight: bold;
+ font-size: 18px;
+}
+
+.update-center-meta-data-version-release-info {
+ margin-top: 8px;
+ font-style: italic;
+}
+
+.update-center-meta-data-version-release-description {
+ margin-top: 8px;
+}
+
+.update-center-meta-data-version-download > a,
+.update-center-meta-data-version-release-notes > a {
+ display: inline-block;
+ margin: 8px 16px 0 0;
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/MetaData.tsx b/server/sonar-ui-common/components/ui/update-center/MetaData.tsx
new file mode 100644
index 00000000000..568a7fba454
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/MetaData.tsx
@@ -0,0 +1,123 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 './MetaData.css';
+import MetaDataVersions from './MetaDataVersions';
+import { MetaDataInformation } from './update-center-metadata';
+import { isSuccessStatus } from '../../../helpers/request';
+
+interface Props {
+ updateCenterKey?: string;
+}
+
+interface State {
+ data?: MetaDataInformation;
+}
+
+export default class MetaData extends React.Component<Props, State> {
+ mounted = false;
+ state: State = {};
+
+ componentDidMount() {
+ this.mounted = true;
+ this.fetchData();
+ }
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.updateCenterKey !== this.props.updateCenterKey) {
+ this.fetchData();
+ }
+ }
+
+ componentWillUnmount() {
+ this.mounted = false;
+ }
+
+ fetchData() {
+ const { updateCenterKey } = this.props;
+
+ if (updateCenterKey) {
+ window
+ .fetch(`https://update.sonarsource.org/${updateCenterKey}.json`)
+ .then((response: Response) => {
+ if (isSuccessStatus(response.status)) {
+ return response.json();
+ } else {
+ return Promise.reject(response);
+ }
+ })
+ .then((data) => {
+ if (this.mounted) {
+ this.setState({ data });
+ }
+ })
+ .catch(() => {
+ if (this.mounted) {
+ this.setState({ data: undefined });
+ }
+ });
+ } else {
+ this.setState({ data: undefined });
+ }
+ }
+
+ render() {
+ const { data } = this.state;
+
+ if (!data) {
+ return null;
+ }
+
+ const { isSonarSourceCommercial, issueTrackerURL, license, organization, versions } = data;
+
+ let vendor;
+ if (organization) {
+ vendor = organization.name;
+ if (organization.url) {
+ vendor = (
+ <a href={organization.url} rel="noopener noreferrer" target="_blank">
+ {vendor}
+ </a>
+ );
+ }
+ }
+
+ return (
+ <div className="update-center-meta-data">
+ <div className="update-center-meta-data-header">
+ {vendor && <span className="update-center-meta-data-vendor">By {vendor}</span>}
+ {license && <span className="update-center-meta-data-license">{license}</span>}
+ {issueTrackerURL && (
+ <span className="update-center-meta-data-issue-tracker">
+ <a href={issueTrackerURL} rel="noopener noreferrer" target="_blank">
+ Issue Tracker
+ </a>
+ </span>
+ )}
+ {isSonarSourceCommercial && (
+ <span className="update-center-meta-data-supported">Supported by SonarSource</span>
+ )}
+ </div>
+ {versions && versions.length > 0 && <MetaDataVersions versions={versions} />}
+ </div>
+ );
+ }
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/MetaDataVersion.tsx b/server/sonar-ui-common/components/ui/update-center/MetaDataVersion.tsx
new file mode 100644
index 00000000000..f9f2155179e
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/MetaDataVersion.tsx
@@ -0,0 +1,99 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 classNames from 'classnames';
+import * as React from 'react';
+import { AdvancedDownloadUrl, MetaDataVersionInformation } from './update-center-metadata';
+
+export interface MetaDataVersionProps {
+ versionInformation: MetaDataVersionInformation;
+}
+
+export default function MetaDataVersion(props: MetaDataVersionProps) {
+ const {
+ versionInformation: {
+ archived,
+ changeLogUrl,
+ compatibility,
+ date,
+ description,
+ downloadURL,
+ version,
+ },
+ } = props;
+
+ const fallbackLabel = 'Download';
+
+ const advancedDownloadUrls = isAdvancedDownloadUrlArray(downloadURL)
+ ? downloadURL.map((url) => ({ ...url, label: url.label || fallbackLabel }))
+ : [{ label: fallbackLabel, url: downloadURL }];
+
+ return (
+ <div
+ className={classNames('update-center-meta-data-version', {
+ 'update-center-meta-data-version-archived': archived,
+ })}>
+ <div className="update-center-meta-data-version-version">{version}</div>
+
+ <div className="update-center-meta-data-version-release-info">
+ {date && <time className="update-center-meta-data-version-release-date">{date}</time>}
+
+ {compatibility && (
+ <span className="update-center-meta-data-version-compatibility">{compatibility}</span>
+ )}
+ </div>
+
+ {description && (
+ <div className="update-center-meta-data-version-release-description">{description}</div>
+ )}
+
+ {(advancedDownloadUrls.length > 0 || changeLogUrl) && (
+ <div className="update-center-meta-data-version-release-links">
+ {advancedDownloadUrls.length > 0 &&
+ advancedDownloadUrls.map(
+ (advancedDownloadUrl, i) =>
+ advancedDownloadUrl.url && (
+ // eslint-disable-next-line react/no-array-index-key
+ <span className="update-center-meta-data-version-download" key={i}>
+ <a href={advancedDownloadUrl.url} rel="noopener noreferrer" target="_blank">
+ {advancedDownloadUrl.label}
+ </a>
+ </span>
+ )
+ )}
+
+ {changeLogUrl && (
+ <span className="update-center-meta-data-version-release-notes">
+ <a href={changeLogUrl} rel="noopener noreferrer" target="_blank">
+ Release notes
+ </a>
+ </span>
+ )}
+ </div>
+ )}
+ </div>
+ );
+}
+
+function isAdvancedDownloadUrlArray(
+ downloadUrl: string | AdvancedDownloadUrl[] | undefined
+): downloadUrl is AdvancedDownloadUrl[] {
+ return !!downloadUrl && typeof downloadUrl !== 'string';
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/MetaDataVersions.tsx b/server/sonar-ui-common/components/ui/update-center/MetaDataVersions.tsx
new file mode 100644
index 00000000000..59e3a2cf41b
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/MetaDataVersions.tsx
@@ -0,0 +1,85 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 MetaDataVersion from './MetaDataVersion';
+import { MetaDataVersionInformation } from './update-center-metadata';
+
+interface Props {
+ versions: MetaDataVersionInformation[];
+}
+
+interface State {
+ collapsed: boolean;
+}
+
+export default class MetaDataVersions extends React.Component<Props, State> {
+ state: State = {
+ collapsed: true,
+ };
+
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.versions !== this.props.versions) {
+ this.setState({ collapsed: true });
+ }
+ }
+
+ handleClick = (event: React.SyntheticEvent<HTMLButtonElement>) => {
+ event.preventDefault();
+ event.currentTarget.blur();
+ this.setState(({ collapsed }) => ({ collapsed: !collapsed }));
+ };
+
+ render() {
+ const { versions } = this.props;
+ const { collapsed } = this.state;
+
+ const archivedVersions = versions.filter((version) => version.archived);
+ const currentVersions = versions.filter((version) => !version.archived);
+
+ return (
+ <div className="update-center-meta-data-versions">
+ {archivedVersions.length > 0 && (
+ <button
+ className="update-center-meta-data-versions-show-more"
+ onClick={this.handleClick}
+ type="button">
+ {collapsed ? 'Show more versions' : 'Show fewer versions'}
+ </button>
+ )}
+
+ {currentVersions.map((versionInformation) => (
+ <MetaDataVersion
+ key={versionInformation.version}
+ versionInformation={versionInformation}
+ />
+ ))}
+
+ {!collapsed &&
+ archivedVersions.map((archivedVersionInformation) => (
+ <MetaDataVersion
+ key={archivedVersionInformation.version}
+ versionInformation={archivedVersionInformation}
+ />
+ ))}
+ </div>
+ );
+ }
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/__tests__/MetaData-test.tsx b/server/sonar-ui-common/components/ui/update-center/__tests__/MetaData-test.tsx
new file mode 100644
index 00000000000..574abcb130f
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/__tests__/MetaData-test.tsx
@@ -0,0 +1,87 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 MetaData from '../MetaData';
+import { mockMetaDataInformation } from '../mocks/update-center-metadata';
+import { MetaDataInformation } from '../update-center-metadata';
+import { HttpStatus } from '../../../../helpers/request';
+
+beforeAll(() => {
+ window.fetch = jest.fn();
+});
+
+beforeEach(() => {
+ jest.resetAllMocks();
+});
+
+it('should render correctly', async () => {
+ const metaDataInfo = mockMetaDataInformation();
+ mockFetchReturnValue(metaDataInfo);
+
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should render correctly with organization', async () => {
+ const metaDataInfo = mockMetaDataInformation({
+ organization: { name: 'test-org', url: 'test-org-url' },
+ });
+ mockFetchReturnValue(metaDataInfo);
+
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should not render anything if call for metadata fails', async () => {
+ const metaDataInfo = mockMetaDataInformation();
+ mockFetchReturnValue(metaDataInfo, HttpStatus.NotFound);
+
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+ expect(wrapper.type()).toBeNull();
+});
+
+it('should fetch metadata again if the update center key if modified', async () => {
+ const metaDataInfo = mockMetaDataInformation();
+ mockFetchReturnValue(metaDataInfo);
+
+ const wrapper = shallowRender();
+ await waitAndUpdate(wrapper);
+
+ expect(window.fetch).toHaveBeenCalledTimes(1);
+
+ mockFetchReturnValue(metaDataInfo);
+ wrapper.setProps({ updateCenterKey: 'abap' });
+
+ expect(window.fetch).toHaveBeenCalledTimes(2);
+});
+
+function shallowRender(props?: Partial<MetaData['props']>) {
+ return shallow<MetaData>(<MetaData updateCenterKey="apex" {...props} />);
+}
+
+function mockFetchReturnValue(metaDataInfo: MetaDataInformation, status = HttpStatus.Ok) {
+ (window.fetch as jest.Mock).mockResolvedValueOnce({ status, json: () => metaDataInfo });
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersion-test.tsx b/server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersion-test.tsx
new file mode 100644
index 00000000000..eb21373830c
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersion-test.tsx
@@ -0,0 +1,46 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 MetaDataVersion, { MetaDataVersionProps } from '../MetaDataVersion';
+import { mockMetaDataVersionInformation } from '../mocks/update-center-metadata';
+
+it('should render correctly', () => {
+ expect(shallowRender()).toMatchSnapshot();
+ expect(
+ shallowRender({
+ versionInformation: mockMetaDataVersionInformation({
+ downloadURL: [{ label: 'macos 64 bits', url: '' }],
+ }),
+ })
+ ).toMatchSnapshot('with advanced downloadUrl');
+ expect(
+ shallowRender({
+ versionInformation: { version: '2.0' },
+ })
+ ).toMatchSnapshot('with very few info');
+});
+
+function shallowRender(props?: Partial<MetaDataVersionProps>) {
+ return shallow(
+ <MetaDataVersion versionInformation={mockMetaDataVersionInformation()} {...props} />
+ );
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersions-test.tsx b/server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersions-test.tsx
new file mode 100644
index 00000000000..5a4fc20d4f1
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/__tests__/MetaDataVersions-test.tsx
@@ -0,0 +1,52 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 { click } from '../../../../helpers/testUtils';
+import MetaDataVersion from '../MetaDataVersion';
+import MetaDataVersions from '../MetaDataVersions';
+import { mockMetaDataVersionInformation } from '../mocks/update-center-metadata';
+
+it('should render correctly', () => {
+ const wrapper = shallowRender();
+ expect(wrapper).toMatchSnapshot();
+});
+
+it('should properly handle show more / show less', () => {
+ const wrapper = shallowRender();
+ expect(wrapper.find(MetaDataVersion).length).toBe(1);
+
+ click(wrapper.find('.update-center-meta-data-versions-show-more'));
+ expect(wrapper.find(MetaDataVersion).length).toBe(3);
+});
+
+function shallowRender(props?: Partial<MetaDataVersions['props']>) {
+ return shallow<MetaDataVersions>(
+ <MetaDataVersions
+ versions={[
+ mockMetaDataVersionInformation({ version: '3.0' }),
+ mockMetaDataVersionInformation({ version: '2.0', archived: true }),
+ mockMetaDataVersionInformation({ version: '1.0', archived: true }),
+ ]}
+ {...props}
+ />
+ );
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaData-test.tsx.snap b/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaData-test.tsx.snap
new file mode 100644
index 00000000000..89e8d74a6d1
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaData-test.tsx.snap
@@ -0,0 +1,133 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="update-center-meta-data"
+>
+ <div
+ className="update-center-meta-data-header"
+ >
+ <span
+ className="update-center-meta-data-vendor"
+ >
+ By
+ <a
+ href="http://www.sonarsource.com/"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ SonarSource
+ </a>
+ </span>
+ <span
+ className="update-center-meta-data-license"
+ >
+ SonarSource
+ </span>
+ <span
+ className="update-center-meta-data-issue-tracker"
+ >
+ <a
+ href="https://jira.sonarsource.com/browse/SONARJAVA"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ Issue Tracker
+ </a>
+ </span>
+ <span
+ className="update-center-meta-data-supported"
+ >
+ Supported by SonarSource
+ </span>
+ </div>
+ <MetaDataVersions
+ versions={
+ Array [
+ Object {
+ "archived": false,
+ "changeLogUrl": "https://example.com/sonar-java-plugin/release",
+ "compatibility": "6.7",
+ "date": "2019-05-31",
+ "downloadURL": "https://example.com/sonar-java-plugin-5.13.0.18197.jar",
+ "version": "2.0",
+ },
+ Object {
+ "archived": true,
+ "changeLogUrl": "https://example.com/sonar-java-plugin/release",
+ "compatibility": "6.7",
+ "date": "2019-05-31",
+ "downloadURL": "https://example.com/sonar-java-plugin-5.13.0.18197.jar",
+ "version": "1.0",
+ },
+ ]
+ }
+ />
+</div>
+`;
+
+exports[`should render correctly with organization 1`] = `
+<div
+ className="update-center-meta-data"
+>
+ <div
+ className="update-center-meta-data-header"
+ >
+ <span
+ className="update-center-meta-data-vendor"
+ >
+ By
+ <a
+ href="test-org-url"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ test-org
+ </a>
+ </span>
+ <span
+ className="update-center-meta-data-license"
+ >
+ SonarSource
+ </span>
+ <span
+ className="update-center-meta-data-issue-tracker"
+ >
+ <a
+ href="https://jira.sonarsource.com/browse/SONARJAVA"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ Issue Tracker
+ </a>
+ </span>
+ <span
+ className="update-center-meta-data-supported"
+ >
+ Supported by SonarSource
+ </span>
+ </div>
+ <MetaDataVersions
+ versions={
+ Array [
+ Object {
+ "archived": false,
+ "changeLogUrl": "https://example.com/sonar-java-plugin/release",
+ "compatibility": "6.7",
+ "date": "2019-05-31",
+ "downloadURL": "https://example.com/sonar-java-plugin-5.13.0.18197.jar",
+ "version": "2.0",
+ },
+ Object {
+ "archived": true,
+ "changeLogUrl": "https://example.com/sonar-java-plugin/release",
+ "compatibility": "6.7",
+ "date": "2019-05-31",
+ "downloadURL": "https://example.com/sonar-java-plugin-5.13.0.18197.jar",
+ "version": "1.0",
+ },
+ ]
+ }
+ />
+</div>
+`;
diff --git a/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersion-test.tsx.snap b/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersion-test.tsx.snap
new file mode 100644
index 00000000000..7fd964fe2ab
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersion-test.tsx.snap
@@ -0,0 +1,113 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="update-center-meta-data-version"
+>
+ <div
+ className="update-center-meta-data-version-version"
+ >
+ 5.13
+ </div>
+ <div
+ className="update-center-meta-data-version-release-info"
+ >
+ <time
+ className="update-center-meta-data-version-release-date"
+ >
+ 2019-05-31
+ </time>
+ <span
+ className="update-center-meta-data-version-compatibility"
+ >
+ 6.7
+ </span>
+ </div>
+ <div
+ className="update-center-meta-data-version-release-links"
+ >
+ <span
+ className="update-center-meta-data-version-download"
+ key="0"
+ >
+ <a
+ href="https://example.com/sonar-java-plugin-5.13.0.18197.jar"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ Download
+ </a>
+ </span>
+ <span
+ className="update-center-meta-data-version-release-notes"
+ >
+ <a
+ href="https://example.com/sonar-java-plugin/release"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ Release notes
+ </a>
+ </span>
+ </div>
+</div>
+`;
+
+exports[`should render correctly: with advanced downloadUrl 1`] = `
+<div
+ className="update-center-meta-data-version"
+>
+ <div
+ className="update-center-meta-data-version-version"
+ >
+ 5.13
+ </div>
+ <div
+ className="update-center-meta-data-version-release-info"
+ >
+ <time
+ className="update-center-meta-data-version-release-date"
+ >
+ 2019-05-31
+ </time>
+ <span
+ className="update-center-meta-data-version-compatibility"
+ >
+ 6.7
+ </span>
+ </div>
+ <div
+ className="update-center-meta-data-version-release-links"
+ >
+ <span
+ className="update-center-meta-data-version-release-notes"
+ >
+ <a
+ href="https://example.com/sonar-java-plugin/release"
+ rel="noopener noreferrer"
+ target="_blank"
+ >
+ Release notes
+ </a>
+ </span>
+ </div>
+</div>
+`;
+
+exports[`should render correctly: with very few info 1`] = `
+<div
+ className="update-center-meta-data-version"
+>
+ <div
+ className="update-center-meta-data-version-version"
+ >
+ 2.0
+ </div>
+ <div
+ className="update-center-meta-data-version-release-info"
+ />
+ <div
+ className="update-center-meta-data-version-release-links"
+ />
+</div>
+`;
diff --git a/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersions-test.tsx.snap b/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersions-test.tsx.snap
new file mode 100644
index 00000000000..109fe964473
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/__tests__/__snapshots__/MetaDataVersions-test.tsx.snap
@@ -0,0 +1,28 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`should render correctly 1`] = `
+<div
+ className="update-center-meta-data-versions"
+>
+ <button
+ className="update-center-meta-data-versions-show-more"
+ onClick={[Function]}
+ type="button"
+ >
+ Show more versions
+ </button>
+ <MetaDataVersion
+ key="3.0"
+ versionInformation={
+ Object {
+ "archived": false,
+ "changeLogUrl": "https://example.com/sonar-java-plugin/release",
+ "compatibility": "6.7",
+ "date": "2019-05-31",
+ "downloadURL": "https://example.com/sonar-java-plugin-5.13.0.18197.jar",
+ "version": "3.0",
+ }
+ }
+ />
+</div>
+`;
diff --git a/server/sonar-ui-common/components/ui/update-center/mocks/update-center-metadata.ts b/server/sonar-ui-common/components/ui/update-center/mocks/update-center-metadata.ts
new file mode 100644
index 00000000000..0da8569994f
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/mocks/update-center-metadata.ts
@@ -0,0 +1,58 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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 { MetaDataInformation, MetaDataVersionInformation } from '../update-center-metadata';
+
+export function mockMetaDataVersionInformation(
+ overrides?: Partial<MetaDataVersionInformation>
+): MetaDataVersionInformation {
+ return {
+ version: '5.13',
+ date: '2019-05-31',
+ compatibility: '6.7',
+ archived: false,
+ downloadURL: 'https://example.com/sonar-java-plugin-5.13.0.18197.jar',
+ changeLogUrl: 'https://example.com/sonar-java-plugin/release',
+ ...overrides,
+ };
+}
+
+export function mockMetaDataInformation(
+ overrides?: Partial<MetaDataInformation>
+): MetaDataInformation {
+ return {
+ name: 'SonarJava',
+ key: 'java',
+ isSonarSourceCommercial: true,
+ organization: {
+ name: 'SonarSource',
+ url: 'http://www.sonarsource.com/',
+ },
+ category: 'Languages',
+ license: 'SonarSource',
+ issueTrackerURL: 'https://jira.sonarsource.com/browse/SONARJAVA',
+ sourcesURL: 'https://github.com/SonarSource/sonar-java',
+ versions: [
+ mockMetaDataVersionInformation({ version: '2.0' }),
+ mockMetaDataVersionInformation({ version: '1.0', archived: true }),
+ ],
+ ...overrides,
+ };
+}
diff --git a/server/sonar-ui-common/components/ui/update-center/update-center-metadata.ts b/server/sonar-ui-common/components/ui/update-center/update-center-metadata.ts
new file mode 100644
index 00000000000..00e1d969b40
--- /dev/null
+++ b/server/sonar-ui-common/components/ui/update-center/update-center-metadata.ts
@@ -0,0 +1,49 @@
+/*
+ * Sonar UI Common
+ * Copyright (C) 2019-2020 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.
+ */
+
+export interface MetaDataInformation {
+ category?: string;
+ isSonarSourceCommercial?: boolean;
+ issueTrackerURL?: string;
+ key?: string;
+ license?: string;
+ name: string;
+ organization?: {
+ name: string;
+ url?: string;
+ };
+ sourcesURL?: string;
+ versions?: MetaDataVersionInformation[];
+}
+
+export interface MetaDataVersionInformation {
+ archived?: boolean;
+ changeLogUrl?: string;
+ compatibility?: string;
+ date?: string;
+ description?: string;
+ downloadURL?: string | AdvancedDownloadUrl[];
+ version: string;
+}
+
+export interface AdvancedDownloadUrl {
+ label?: string;
+ url: string;
+}