import throwGlobalError from '../app/utils/throwGlobalError';
export interface Edition {
+ key: string;
name: string;
desc: string;
more_link: string;
download_link: string;
}
-export interface Editions {
- [key: string]: Edition;
+export interface EditionsPerVersion {
+ [version: string]: Edition[];
}
export interface EditionStatus {
return getJSON('/api/editions/status').catch(throwGlobalError);
}
-export function getEditionsList(): Promise<Editions> {
- // TODO Replace with real url
- const url =
- 'https://gist.githubusercontent.com/gregaubert/e34535494f8a94bec7cbc4d750ae7d06/raw/ba8670a28d4bc6fbac18f92e450ec42029cc5dcb/editions.json';
+export function getEditionsList(url: string): Promise<EditionsPerVersion> {
return corsRequest(url)
.submit()
.then(checkStatus)
export interface Props {
editionStatus?: EditionStatus;
+ editionsUrl: string;
location: { pathname: string; query: RawQuery };
+ sonarqubeVersion: string;
updateCenterActive: boolean;
}
<Header />
<EditionBoxes
editionStatus={this.props.editionStatus}
+ editionsUrl={this.props.editionsUrl}
+ sonarqubeVersion={this.props.sonarqubeVersion}
updateCenterActive={this.props.updateCenterActive}
/>
<PendingActions refreshPending={this.fetchPendingPlugins} pending={pending} />
const mapStateToProps = (state: any) => ({
editionStatus: getAppState(state).editionStatus,
+ editionsUrl: (getGlobalSettingValue(state, 'sonar.editions.jsonUrl') || {}).value,
+ sonarqubeVersion: getAppState(state).version,
updateCenterActive: (getGlobalSettingValue(state, 'sonar.updatecenter.activate') || {}).value
});
import { FormattedMessage } from 'react-intl';
import EditionBox from './components/EditionBox';
import LicenseEditionForm from './components/LicenseEditionForm';
-import { Edition, Editions, EditionStatus, getEditionsList } from '../../api/marketplace';
+import { Edition, EditionStatus, getEditionsList } from '../../api/marketplace';
+import { getEditionsForVersion } from './utils';
import { translate } from '../../helpers/l10n';
export interface Props {
editionStatus?: EditionStatus;
+ editionsUrl: string;
+ sonarqubeVersion: string;
updateCenterActive: boolean;
}
interface State {
- editions: Editions;
+ editions?: Edition[];
editionsError: boolean;
loading: boolean;
installEdition?: Edition;
export default class EditionBoxes extends React.PureComponent<Props, State> {
mounted: boolean;
- state: State = { editions: {}, editionsError: false, loading: true };
+ state: State = { editionsError: false, loading: true };
componentDidMount() {
this.mounted = true;
fetchEditions = () => {
this.setState({ loading: true });
- getEditionsList().then(
- editions => {
+ getEditionsList(this.props.editionsUrl).then(
+ editionsPerVersion => {
if (this.mounted) {
this.setState({
loading: false,
- editions,
+ editions: getEditionsForVersion(editionsPerVersion, this.props.sonarqubeVersion),
editionsError: false
});
}
handleCloseLicenseForm = () => this.setState({ installEdition: undefined });
render() {
- const { editions, loading, installEdition } = this.state;
+ const { editions, editionsError, loading, installEdition } = this.state;
if (loading) {
- return null;
+ return <i className="big-spacer-bottom spinner" />;
}
return (
<div className="spacer-bottom marketplace-editions">
- {this.state.editionsError ? (
+ {!editions || editionsError ? (
<span className="alert alert-info">
<FormattedMessage
defaultMessage={translate('marketplace.editions_unavailable')}
/>
</span>
) : (
- Object.keys(editions).map(key => (
+ editions.map(edition => (
<EditionBox
- edition={editions[key]}
- editionKey={key}
+ edition={edition}
editionStatus={this.props.editionStatus}
- key={key}
+ key={edition.key}
onInstall={this.handleOpenLicenseForm}
/>
))
installationStatus: 'NONE'
};
-const DEFAULT_EDITIONS = {
- foo: {
+const DEFAULT_EDITIONS = [
+ {
+ key: 'foo',
name: 'Foo',
desc: 'Foo desc',
download_link: 'download_url',
more_link: 'more_url',
request_license_link: 'license_url'
},
- bar: {
+ {
+ key: 'bar',
name: 'Bar',
desc: 'Bar desc',
download_link: 'download_url',
more_link: 'more_url',
request_license_link: 'license_url'
}
-};
+];
it('should display the edition boxes', () => {
const wrapper = getWrapper();
editions: DEFAULT_EDITIONS,
loading: false
});
- (wrapper.instance() as EditionBoxes).handleOpenLicenseForm(DEFAULT_EDITIONS.foo);
+ (wrapper.instance() as EditionBoxes).handleOpenLicenseForm(DEFAULT_EDITIONS[0]);
expect(wrapper.find('LicenseEditionForm').exists()).toBeTruthy();
});
function getWrapper(props = {}) {
return shallow(
- <EditionBoxes editionStatus={DEFAULT_STATUS} updateCenterActive={true} {...props} />
+ <EditionBoxes
+ editionStatus={DEFAULT_STATUS}
+ editionsUrl=""
+ sonarqubeVersion="6.7.5"
+ updateCenterActive={true}
+ {...props}
+ />
);
}
</div>
`;
-exports[`should display the edition boxes 1`] = `null`;
+exports[`should display the edition boxes 1`] = `
+<i
+ className="big-spacer-bottom spinner"
+/>
+`;
exports[`should display the edition boxes 2`] = `
<div
Object {
"desc": "Foo desc",
"download_link": "download_url",
+ "key": "foo",
"more_link": "more_url",
"name": "Foo",
"request_license_link": "license_url",
}
}
- editionKey="foo"
editionStatus={
Object {
"currentEditionKey": "foo",
Object {
"desc": "Bar desc",
"download_link": "download_url",
+ "key": "bar",
"more_link": "more_url",
"name": "Bar",
"request_license_link": "license_url",
}
}
- editionKey="bar"
editionStatus={
Object {
"currentEditionKey": "foo",
interface Props {
edition: Edition;
- editionKey: string;
editionStatus?: EditionStatus;
onInstall: (edition: Edition) => void;
}
handleInstall = () => this.props.onInstall(this.props.edition);
render() {
- const { edition, editionKey, editionStatus } = this.props;
- const isInstalled = editionStatus && editionStatus.currentEditionKey === editionKey;
- const isInstalling = editionStatus && editionStatus.nextEditionKey === editionKey;
+ const { edition, editionStatus } = this.props;
+ const isInstalled = editionStatus && editionStatus.currentEditionKey === edition.key;
+ const isInstalling = editionStatus && editionStatus.nextEditionKey === edition.key;
const installInProgress =
editionStatus && editionStatus.installationStatus === 'AUTOMATIC_IN_PROGRESS';
return (
};
const DEFAULT_EDITION: Edition = {
+ key: 'foo',
name: 'Foo',
desc: 'Foo desc',
download_link: 'download_url',
return shallow(
<EditionBox
edition={DEFAULT_EDITION}
- editionKey="foo"
editionStatus={DEFAULT_STATUS}
onInstall={jest.fn()}
{...props}
const getStore = require('../../../../app/utils/getStore').default as jest.Mock<any>;
const DEFAULT_EDITION = {
+ key: 'foo',
name: 'Foo',
desc: 'Foo desc',
download_link: 'download_url',
>;
const DEFAULT_EDITION = {
+ key: 'foo',
name: 'Foo',
desc: 'Foo desc',
download_link: 'download_url',
Object {
"desc": "Foo desc",
"download_link": "download_url",
+ "key": "foo",
"more_link": "more_url",
"name": "Foo",
"request_license_link": "license_url",
*/
import { memoize } from 'lodash';
import { Plugin, PluginAvailable, PluginInstalled, PluginPending } from '../../api/plugins';
+import { Edition, EditionsPerVersion } from '../../api/marketplace';
import { cleanQuery, parseAsString, RawQuery, serializeString } from '../../helpers/query';
export interface Query {
});
}
+export function getEditionsForVersion(
+ editions: EditionsPerVersion,
+ version: string
+): Edition[] | undefined {
+ const matchResult = version.match(/\d+\.\d+/);
+ if (matchResult) {
+ if (editions[matchResult[0]]) {
+ return editions[matchResult[0]];
+ }
+ }
+ return undefined;
+}
+
export const parseQuery = memoize((urlQuery: RawQuery): Query => ({
filter: parseAsString(urlQuery['filter']) || DEFAULT_FILTER,
search: parseAsString(urlQuery['search'])