浏览代码

SONAR-9936 Switch to upgrade/downgrade buttons in the editions

tags/6.7-RC1
Grégoire Aubert 6 年前
父节点
当前提交
35a5d851ce

+ 45
- 23
server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx 查看文件

@@ -24,6 +24,7 @@ import LicenseEditionForm from './components/LicenseEditionForm';
import UninstallEditionForm from './components/UninstallEditionForm';
import { Edition, EditionStatus } from '../../api/marketplace';
import { translate } from '../../helpers/l10n';
import { sortEditions } from './utils';

export interface Props {
canInstall: boolean;
@@ -49,9 +50,45 @@ export default class EditionBoxes extends React.PureComponent<Props, State> {
handleOpenUninstallForm = () => this.setState({ openUninstallForm: true });
handleCloseUninstallForm = () => this.setState({ openUninstallForm: false });

renderForms(sortedEditions: Edition[], installedIdx?: number) {
const { canInstall, canUninstall, editionStatus } = this.props;
const { installEdition, openUninstallForm } = this.state;
const installEditionIdx =
installEdition && sortedEditions.findIndex(edition => edition.key === installEdition.key);

if (canInstall && installEdition) {
return (
<LicenseEditionForm
edition={installEdition}
editions={sortedEditions}
isDowngrade={
installedIdx !== undefined &&
installEditionIdx !== undefined &&
installEditionIdx < installedIdx
}
onClose={this.handleCloseLicenseForm}
updateEditionStatus={this.props.updateEditionStatus}
/>
);
}

if (canUninstall && openUninstallForm && editionStatus && editionStatus.currentEditionKey) {
return (
<UninstallEditionForm
edition={sortedEditions.find(edition => edition.key === editionStatus.currentEditionKey)}
editionStatus={editionStatus}
onClose={this.handleCloseUninstallForm}
updateEditionStatus={this.props.updateEditionStatus}
/>
);
}

return null;
}

render() {
const { canInstall, canUninstall, editions, editionStatus, loading } = this.props;
const { installEdition, openUninstallForm } = this.state;
if (loading) {
return <i className="big-spacer-bottom spinner" />;
}
@@ -76,41 +113,26 @@ export default class EditionBoxes extends React.PureComponent<Props, State> {
);
}

const sortedEditions = sortEditions(editions);
const installedIdx =
editionStatus &&
sortedEditions.findIndex(edition => edition.key === editionStatus.currentEditionKey);
return (
<div className="spacer-bottom marketplace-editions">
{editions.map(edition => (
{sortedEditions.map((edition, idx) => (
<EditionBox
canInstall={canInstall}
canUninstall={canUninstall}
edition={edition}
editionStatus={editionStatus}
isDowngrade={installedIdx !== undefined && idx < installedIdx}
key={edition.key}
onInstall={this.handleOpenLicenseForm}
onUninstall={this.handleOpenUninstallForm}
/>
))}

{canInstall &&
installEdition && (
<LicenseEditionForm
edition={installEdition}
editions={editions}
onClose={this.handleCloseLicenseForm}
updateEditionStatus={this.props.updateEditionStatus}
/>
)}

{canUninstall &&
openUninstallForm &&
editionStatus &&
editionStatus.currentEditionKey && (
<UninstallEditionForm
edition={editions.find(edition => edition.key === editionStatus.currentEditionKey)}
editionStatus={editionStatus}
onClose={this.handleCloseUninstallForm}
updateEditionStatus={this.props.updateEditionStatus}
/>
)}
{this.renderForms(sortedEditions, installedIdx)}
</div>
);
}

+ 8
- 8
server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx 查看文件

@@ -23,31 +23,31 @@ import EditionBoxes from '../EditionBoxes';
import { EditionStatus } from '../../../api/marketplace';

const DEFAULT_STATUS: EditionStatus = {
currentEditionKey: 'foo',
currentEditionKey: 'developer',
nextEditionKey: '',
installationStatus: 'NONE'
};

const DEFAULT_EDITIONS = [
{
key: 'foo',
name: 'Foo',
textDescription: 'Foo desc',
key: 'developer',
name: 'Developer Edition',
textDescription: 'foo',
downloadUrl: 'download_url',
homeUrl: 'more_url',
requestUrl: 'license_url'
},
{
key: 'bar',
name: 'Bar',
textDescription: 'Bar desc',
key: 'comunity',
name: 'Comunity Edition',
textDescription: 'bar',
downloadUrl: 'download_url',
homeUrl: 'more_url',
requestUrl: 'license_url'
}
];

it('should display the edition boxes', () => {
it('should display the edition boxes correctly', () => {
const wrapper = getWrapper({ editions: DEFAULT_EDITIONS, loading: true });
expect(wrapper).toMatchSnapshot();
wrapper.setProps({ loading: false });

+ 12
- 10
server/sonar-web/src/main/js/apps/marketplace/__tests__/__snapshots__/EditionBoxes-test.tsx.snap 查看文件

@@ -25,13 +25,13 @@ exports[`should display an error message 1`] = `
</div>
`;

exports[`should display the edition boxes 1`] = `
exports[`should display the edition boxes correctly 1`] = `
<i
className="big-spacer-bottom spinner"
/>
`;

exports[`should display the edition boxes 2`] = `
exports[`should display the edition boxes correctly 2`] = `
<div
className="spacer-bottom marketplace-editions"
>
@@ -42,19 +42,20 @@ exports[`should display the edition boxes 2`] = `
Object {
"downloadUrl": "download_url",
"homeUrl": "more_url",
"key": "foo",
"name": "Foo",
"key": "comunity",
"name": "Comunity Edition",
"requestUrl": "license_url",
"textDescription": "Foo desc",
"textDescription": "bar",
}
}
editionStatus={
Object {
"currentEditionKey": "foo",
"currentEditionKey": "developer",
"installationStatus": "NONE",
"nextEditionKey": "",
}
}
isDowngrade={true}
onInstall={[Function]}
onUninstall={[Function]}
/>
@@ -65,19 +66,20 @@ exports[`should display the edition boxes 2`] = `
Object {
"downloadUrl": "download_url",
"homeUrl": "more_url",
"key": "bar",
"name": "Bar",
"key": "developer",
"name": "Developer Edition",
"requestUrl": "license_url",
"textDescription": "Bar desc",
"textDescription": "foo",
}
}
editionStatus={
Object {
"currentEditionKey": "foo",
"currentEditionKey": "developer",
"installationStatus": "NONE",
"nextEditionKey": "",
}
}
isDowngrade={false}
onInstall={[Function]}
onUninstall={[Function]}
/>

+ 26
- 36
server/sonar-web/src/main/js/apps/marketplace/components/EditionBox.tsx 查看文件

@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
import CheckIcon from '../../../components/icons-components/CheckIcon';
import EditionBoxBadge from './EditionBoxBadge';
import { Edition, EditionStatus } from '../../../api/marketplace';
import { translate } from '../../../helpers/l10n';

@@ -27,6 +27,7 @@ interface Props {
canUninstall: boolean;
edition: Edition;
editionStatus?: EditionStatus;
isDowngrade?: boolean;
onInstall: (edition: Edition) => void;
onUninstall: () => void;
}
@@ -34,40 +35,45 @@ interface Props {
export default class EditionBox extends React.PureComponent<Props> {
handleInstall = () => this.props.onInstall(this.props.edition);

renderBadge(isInstalled?: boolean, installInProgress?: boolean) {
const { edition, editionStatus } = this.props;
const installReady = editionStatus && editionStatus.installationStatus === 'AUTOMATIC_READY';
const isInstalling =
installInProgress && editionStatus && editionStatus.nextEditionKey === edition.key;
if (isInstalling) {
renderActions(isInstalled?: boolean, installInProgress?: boolean) {
const { canInstall, canUninstall, editionStatus } = this.props;
const uninstallInProgress =
editionStatus && editionStatus.installationStatus === 'UNINSTALL_IN_PROGRESS';
if (canInstall && !isInstalled) {
return (
<span className="marketplace-edition-badge badge badge-normal-size">
{installReady ? translate('marketplace.pending') : translate('marketplace.installing')}
</span>
<button disabled={installInProgress || uninstallInProgress} onClick={this.handleInstall}>
{this.props.isDowngrade ? (
translate('marketplace.downgrade')
) : (
translate('marketplace.upgrade')
)}
</button>
);
}
if (isInstalled) {
if (canUninstall && isInstalled) {
return (
<span className="marketplace-edition-badge badge badge-normal-size">
<CheckIcon size={14} className="little-spacer-right text-bottom" />
{translate('marketplace.installed')}
</span>
<button
className="button-red"
disabled={installInProgress || uninstallInProgress}
onClick={this.props.onUninstall}>
{translate('marketplace.uninstall')}
</button>
);
}

return null;
}

render() {
const { canInstall, canUninstall, edition, editionStatus } = this.props;
const { edition, editionStatus } = this.props;
const isInstalled = editionStatus && editionStatus.currentEditionKey === edition.key;
const uninstallInProgress =
editionStatus && editionStatus.installationStatus === 'UNINSTALL_IN_PROGRESS';
const installInProgress =
editionStatus &&
['AUTOMATIC_IN_PROGRESS', 'AUTOMATIC_READY'].includes(editionStatus.installationStatus);
return (
<div className="boxed-group boxed-group-inner marketplace-edition">
{this.renderBadge(isInstalled, installInProgress)}
{editionStatus && <EditionBoxBadge editionKey={edition.key} status={editionStatus} />}
<div>
<h3 className="spacer-bottom">{edition.name}</h3>
<p>{edition.textDescription}</p>
@@ -76,23 +82,7 @@ export default class EditionBox extends React.PureComponent<Props> {
<a href={edition.homeUrl} target="_blank">
{translate('marketplace.learn_more')}
</a>
{canUninstall &&
isInstalled && (
<button
className="button-red"
disabled={installInProgress || uninstallInProgress}
onClick={this.props.onUninstall}>
{translate('marketplace.uninstall')}
</button>
)}
{canInstall &&
!isInstalled && (
<button
disabled={installInProgress || uninstallInProgress}
onClick={this.handleInstall}>
{translate('marketplace.install')}
</button>
)}
{this.renderActions(isInstalled, installInProgress)}
</div>
</div>
);

+ 56
- 0
server/sonar-web/src/main/js/apps/marketplace/components/EditionBoxBadge.tsx 查看文件

@@ -0,0 +1,56 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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 CheckIcon from '../../../components/icons-components/CheckIcon';
import { EditionStatus } from '../../../api/marketplace';
import { translate } from '../../../helpers/l10n';

interface Props {
editionKey: string;
status: EditionStatus;
}

export default function EditionBoxBadge({ editionKey, status }: Props) {
const inProgress = ['AUTOMATIC_IN_PROGRESS', 'AUTOMATIC_READY'].includes(
status.installationStatus
);
const isInstalling = inProgress && status.nextEditionKey === editionKey;

if (isInstalling) {
const installReady = status.installationStatus === 'AUTOMATIC_READY';
return (
<span className="marketplace-edition-badge badge badge-normal-size">
{installReady ? translate('marketplace.pending') : translate('marketplace.installing')}
</span>
);
}

const isInstalled = status.currentEditionKey === editionKey;
if (isInstalled) {
return (
<span className="marketplace-edition-badge badge badge-normal-size">
<CheckIcon size={14} className="little-spacer-right text-bottom" />
{translate('marketplace.installed')}
</span>
);
}

return null;
}

+ 6
- 2
server/sonar-web/src/main/js/apps/marketplace/components/LicenseEditionForm.tsx 查看文件

@@ -26,6 +26,7 @@ import { translate, translateWithParameters } from '../../../helpers/l10n';
export interface Props {
edition: Edition;
editions: Edition[];
isDowngrade: boolean;
onClose: () => void;
updateEditionStatus: (editionStatus: EditionStatus) => void;
}
@@ -79,9 +80,12 @@ export default class LicenseEditionForm extends React.PureComponent<Props, State
};

render() {
const { edition } = this.props;
const { edition, isDowngrade } = this.props;
const { submitting, status } = this.state;
const header = translateWithParameters('marketplace.install_x', edition.name);

const header = isDowngrade
? translateWithParameters('marketplace.downgrade_to_x', edition.name)
: translateWithParameters('marketplace.upgrade_to_x', edition.name);
return (
<Modal
isOpen={true}

+ 13
- 31
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBox-test.tsx 查看文件

@@ -41,31 +41,16 @@ it('should display the edition', () => {
expect(getWrapper()).toMatchSnapshot();
});

it('should display installed badge', () => {
it('should disable upgrade button', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: 'foo',
nextEditionKey: '',
installationStatus: 'NONE'
}
})
).toMatchSnapshot();
});

it('should display installing badge', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: 'foo',
currentEditionKey: '',
nextEditionKey: 'foo',
installationStatus: 'AUTOMATIC_IN_PROGRESS'
}
})
).toMatchSnapshot();
});

it('should display pending badge', () => {
expect(
getWrapper({
editionStatus: {
@@ -77,39 +62,36 @@ it('should display pending badge', () => {
).toMatchSnapshot();
});

it('should disable install button', () => {
it('should disable uninstall button', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: '',
currentEditionKey: 'foo',
nextEditionKey: 'foo',
installationStatus: 'AUTOMATIC_IN_PROGRESS'
}
})
).toMatchSnapshot();
expect(
getWrapper({
editionStatus: {
currentEditionKey: '',
nextEditionKey: 'foo',
installationStatus: 'AUTOMATIC_READY'
}
})
).toMatchSnapshot();
});

it('should disable uninstall button', () => {
it('should correctly hide upgrade/uninstall buttons', () => {
expect(getWrapper({ canInstall: false })).toMatchSnapshot();
expect(
getWrapper({
canUninstall: false,
editionStatus: {
currentEditionKey: 'foo',
nextEditionKey: 'foo',
installationStatus: 'AUTOMATIC_IN_PROGRESS'
nextEditionKey: '',
installationStatus: 'NONE'
}
})
).toMatchSnapshot();
});

it('should display a downgrade button', () => {
expect(getWrapper({ isDowngrade: true })).toMatchSnapshot();
});

function getWrapper(props = {}) {
return shallow(
<EditionBox

+ 81
- 0
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionBoxBadge-test.tsx 查看文件

@@ -0,0 +1,81 @@
/*
* SonarQube
* Copyright (C) 2009-2017 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 { shallow } from 'enzyme';
import { EditionStatus } from '../../../../api/marketplace';
import EditionBoxBadge from '../EditionBoxBadge';

const DEFAULT_STATUS: EditionStatus = {
currentEditionKey: '',
nextEditionKey: '',
installationStatus: 'NONE'
};

it('should display installed badge', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: 'foo',
nextEditionKey: '',
installationStatus: 'NONE'
}
})
).toMatchSnapshot();
});

it('should display installing badge', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: 'foo',
nextEditionKey: 'foo',
installationStatus: 'AUTOMATIC_IN_PROGRESS'
}
})
).toMatchSnapshot();
});

it('should display pending badge', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: '',
nextEditionKey: 'foo',
installationStatus: 'AUTOMATIC_READY'
}
})
).toMatchSnapshot();
});

it('should not display a badge', () => {
expect(
getWrapper({
editionStatus: {
currentEditionKey: '',
nextEditionKey: 'bar',
installationStatus: 'AUTOMATIC_READY'
}
})
).toMatchSnapshot();
});

function getWrapper(props = {}) {
return shallow(<EditionBoxBadge editionKey="foo" status={DEFAULT_STATUS} {...props} />);
}

+ 1
- 0
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/LicenseEditionForm-test.tsx 查看文件

@@ -78,6 +78,7 @@ function getWrapper(props = {}) {
<LicenseEditionForm
edition={DEFAULT_EDITION}
editions={[DEFAULT_EDITION]}
isDowngrade={false}
onClose={jest.fn()}
updateEditionStatus={jest.fn()}
{...props}

+ 81
- 59
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBox-test.tsx.snap 查看文件

@@ -1,14 +1,19 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should disable install button 1`] = `
exports[`should correctly hide upgrade/uninstall buttons 1`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<span
className="marketplace-edition-badge badge badge-normal-size"
>
marketplace.installing
</span>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "",
"installationStatus": "NONE",
"nextEditionKey": "",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -28,25 +33,24 @@ exports[`should disable install button 1`] = `
>
marketplace.learn_more
</a>
<button
disabled={true}
onClick={[Function]}
>
marketplace.install
</button>
</div>
</div>
`;

exports[`should disable install button 2`] = `
exports[`should correctly hide upgrade/uninstall buttons 2`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<span
className="marketplace-edition-badge badge badge-normal-size"
>
marketplace.pending
</span>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "foo",
"installationStatus": "NONE",
"nextEditionKey": "",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -66,12 +70,6 @@ exports[`should disable install button 2`] = `
>
marketplace.learn_more
</a>
<button
disabled={true}
onClick={[Function]}
>
marketplace.install
</button>
</div>
</div>
`;
@@ -80,11 +78,16 @@ exports[`should disable uninstall button 1`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<span
className="marketplace-edition-badge badge badge-normal-size"
>
marketplace.installing
</span>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "foo",
"installationStatus": "AUTOMATIC_IN_PROGRESS",
"nextEditionKey": "foo",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -115,19 +118,20 @@ exports[`should disable uninstall button 1`] = `
</div>
`;

exports[`should display installed badge 1`] = `
exports[`should disable upgrade button 1`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<span
className="marketplace-edition-badge badge badge-normal-size"
>
<CheckIcon
className="little-spacer-right text-bottom"
size={14}
/>
marketplace.installed
</span>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "",
"installationStatus": "AUTOMATIC_IN_PROGRESS",
"nextEditionKey": "foo",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -148,25 +152,29 @@ exports[`should display installed badge 1`] = `
marketplace.learn_more
</a>
<button
className="button-red"
disabled={false}
disabled={true}
onClick={[Function]}
>
marketplace.uninstall
marketplace.upgrade
</button>
</div>
</div>
`;

exports[`should display installing badge 1`] = `
exports[`should disable upgrade button 2`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<span
className="marketplace-edition-badge badge badge-normal-size"
>
marketplace.installing
</span>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "",
"installationStatus": "AUTOMATIC_READY",
"nextEditionKey": "foo",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -187,25 +195,29 @@ exports[`should display installing badge 1`] = `
marketplace.learn_more
</a>
<button
className="button-red"
disabled={true}
onClick={[Function]}
>
marketplace.uninstall
marketplace.upgrade
</button>
</div>
</div>
`;

exports[`should display pending badge 1`] = `
exports[`should display a downgrade button 1`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<span
className="marketplace-edition-badge badge badge-normal-size"
>
marketplace.pending
</span>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "",
"installationStatus": "NONE",
"nextEditionKey": "",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -226,10 +238,10 @@ exports[`should display pending badge 1`] = `
marketplace.learn_more
</a>
<button
disabled={true}
disabled={false}
onClick={[Function]}
>
marketplace.install
marketplace.downgrade
</button>
</div>
</div>
@@ -239,6 +251,16 @@ exports[`should display the edition 1`] = `
<div
className="boxed-group boxed-group-inner marketplace-edition"
>
<EditionBoxBadge
editionKey="foo"
status={
Object {
"currentEditionKey": "",
"installationStatus": "NONE",
"nextEditionKey": "",
}
}
/>
<div>
<h3
className="spacer-bottom"
@@ -262,7 +284,7 @@ exports[`should display the edition 1`] = `
disabled={false}
onClick={[Function]}
>
marketplace.install
marketplace.upgrade
</button>
</div>
</div>

+ 9
- 0
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionBoxBadge-test.tsx.snap 查看文件

@@ -0,0 +1,9 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`should display installed badge 1`] = `null`;

exports[`should display installing badge 1`] = `null`;

exports[`should display pending badge 1`] = `null`;

exports[`should not display a badge 1`] = `null`;

+ 2
- 2
server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/LicenseEditionForm-test.tsx.snap 查看文件

@@ -36,7 +36,7 @@ exports[`should display correctly 1`] = `
bodyOpenClassName="ReactModal__Body--open"
className="modal"
closeTimeoutMS={0}
contentLabel="marketplace.install_x.Foo"
contentLabel="marketplace.upgrade_to_x.Foo"
isOpen={true}
onRequestClose={[Function]}
overlayClassName="modal-overlay"
@@ -48,7 +48,7 @@ exports[`should display correctly 1`] = `
className="modal-head"
>
<h2>
marketplace.install_x.Foo
marketplace.upgrade_to_x.Foo
</h2>
</header>
<LicenseEditionSet

+ 8
- 3
server/sonar-web/src/main/js/apps/marketplace/utils.ts 查看文件

@@ -17,17 +17,16 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { memoize } from 'lodash';
import { memoize, sortBy } from 'lodash';
import { Plugin, PluginAvailable, PluginInstalled, PluginPending } from '../../api/plugins';
import { cleanQuery, parseAsString, RawQuery, serializeString } from '../../helpers/query';
import { Edition } from '../../api/marketplace';

export interface Query {
filter: string;
search?: string;
}

export const DEFAULT_FILTER = 'all';

export function isPluginAvailable(plugin: Plugin): plugin is PluginAvailable {
return (plugin as any).release !== undefined;
}
@@ -51,6 +50,12 @@ export function filterPlugins(plugins: Plugin[], search: string): Plugin[] {
});
}

const EDITIONS_ORDER = ['community', 'developer', 'enterprise', 'datacenter'];
export function sortEditions(editions: Edition[]): Edition[] {
return sortBy(editions, edition => EDITIONS_ORDER.indexOf(edition.key));
}

export const DEFAULT_FILTER = 'all';
export const parseQuery = memoize((urlQuery: RawQuery): Query => ({
filter: parseAsString(urlQuery['filter']) || DEFAULT_FILTER,
search: parseAsString(urlQuery['search'])

+ 4
- 1
sonar-core/src/main/resources/org/sonar/l10n/core.properties 查看文件

@@ -2068,9 +2068,12 @@ marketplace.updates_only=Updates Only
marketplace.restart=Restart
marketplace.revert=Revert
marketplace.install=Install
marketplace.install_x=Install {0}
marketplace.upgrade_to_x=Upgrade to {0}
marketplace.downgrade_to_x=Downgrade to {0}
marketplace.installed=Installed
marketplace.installing=Installing...
marketplace.upgrade=Upgrade
marketplace.downgrade=Downgrade
marketplace.uninstall_x=Uninstall {0}
marketplace.uninstall_x_confirmation=Are you sure you want to uninstall {0} and get back to the Community Edition?
marketplace.pending=Pending...

正在加载...
取消
保存