diff options
author | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-19 11:04:29 +0200 |
---|---|---|
committer | Grégoire Aubert <gregoire.aubert@sonarsource.com> | 2017-10-23 08:01:13 -0700 |
commit | 6e71b7b4a1d26c0de2a2c8bde2b0274de90c08e0 (patch) | |
tree | 8df83e5dfc2ee8df156ed638d889f03fdc2f4dc2 | |
parent | c7c99dc7add3f3d13a6425b60606fce8cf303ed2 (diff) | |
download | sonarqube-6e71b7b4a1d26c0de2a2c8bde2b0274de90c08e0.tar.gz sonarqube-6e71b7b4a1d26c0de2a2c8bde2b0274de90c08e0.zip |
SONAR-10002 Add dismiss button to install error message on marketplace
5 files changed, 83 insertions, 8 deletions
diff --git a/server/sonar-web/src/main/js/api/marketplace.ts b/server/sonar-web/src/main/js/api/marketplace.ts index 4eae2b77737..0574650e603 100644 --- a/server/sonar-web/src/main/js/api/marketplace.ts +++ b/server/sonar-web/src/main/js/api/marketplace.ts @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -import { checkStatus, corsRequest, getJSON, parseJSON, postJSON } from '../helpers/request'; +import { checkStatus, corsRequest, getJSON, parseJSON, post, postJSON } from '../helpers/request'; import throwGlobalError from '../app/utils/throwGlobalError'; export interface Edition { @@ -75,5 +75,9 @@ export function applyLicense(data: { license: string }): Promise<EditionStatus> } export function uninstallEdition(): Promise<void | Response> { - return postJSON('/api/editions/uninstall').catch(throwGlobalError); + return post('/api/editions/uninstall').catch(throwGlobalError); +} + +export function dismissErrorMessage(): Promise<void | Response> { + return post('/api/editions/clear_error_message').catch(throwGlobalError); } diff --git a/server/sonar-web/src/main/js/apps/marketplace/App.tsx b/server/sonar-web/src/main/js/apps/marketplace/App.tsx index eaf510ac707..37cc3b1d72a 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/App.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/App.tsx @@ -177,7 +177,12 @@ export default class App extends React.PureComponent<Props, State> { <div className="page page-limited" id="marketplace-page"> <Helmet title={translate('marketplace.page')} /> <div className="marketplace-notifs"> - {editionStatus && <EditionsStatusNotif editionStatus={editionStatus} />} + {editionStatus && ( + <EditionsStatusNotif + editionStatus={editionStatus} + updateEditionStatus={this.updateEditionStatus} + /> + )} <PendingActions refreshPending={this.fetchPendingPlugins} pending={pending} /> </div> <Header /> diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/EditionsStatusNotif.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/EditionsStatusNotif.tsx index f1acfff516c..1afc9931bf6 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/EditionsStatusNotif.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/EditionsStatusNotif.tsx @@ -19,11 +19,13 @@ */ import * as React from 'react'; import RestartForm from '../../../components/common/RestartForm'; -import { EditionStatus } from '../../../api/marketplace'; +import CloseIcon from '../../../components/icons-components/CloseIcon'; +import { dismissErrorMessage, EditionStatus } from '../../../api/marketplace'; import { translate } from '../../../helpers/l10n'; interface Props { editionStatus: EditionStatus; + updateEditionStatus: (editionStatus: EditionStatus) => void; } interface State { @@ -36,6 +38,15 @@ export default class EditionsStatusNotif extends React.PureComponent<Props, Stat handleOpenRestart = () => this.setState({ openRestart: true }); hanleCloseRestart = () => this.setState({ openRestart: false }); + handleDismissError = (event: React.SyntheticEvent<HTMLAnchorElement>) => { + event.preventDefault(); + dismissErrorMessage().then( + () => + this.props.updateEditionStatus({ ...this.props.editionStatus, installError: undefined }), + () => {} + ); + }; + renderStatusAlert() { const { installationStatus } = this.props.editionStatus; switch (installationStatus) { @@ -74,7 +85,17 @@ export default class EditionsStatusNotif extends React.PureComponent<Props, Stat const { installError } = this.props.editionStatus; return ( <div> - {installError && <div className="alert alert-danger">{installError}</div>} + {installError && ( + <div className="alert alert-danger"> + {installError} + <a + className="pull-right button-link text-danger" + href="#" + onClick={this.handleDismissError}> + <CloseIcon /> + </a> + </div> + )} {this.renderStatusAlert} </div> ); diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionsStatusNotif-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionsStatusNotif-test.tsx index 378f57b3cbb..0a3ca4c9acd 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionsStatusNotif-test.tsx +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/EditionsStatusNotif-test.tsx @@ -19,25 +19,45 @@ */ import * as React from 'react'; import { shallow } from 'enzyme'; +import { click } from '../../../../helpers/testUtils'; import EditionsStatusNotif from '../EditionsStatusNotif'; +jest.mock('../../../../api/marketplace', () => ({ + dismissErrorMessage: jest.fn(() => Promise.resolve()) +})); + +const dismissMsg = require('../../../../api/marketplace').dismissErrorMessage as jest.Mock<any>; + +beforeEach(() => { + dismissMsg.mockClear(); +}); + it('should display an in progress notif', () => { const wrapper = shallow( - <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_IN_PROGRESS' }} /> + <EditionsStatusNotif + editionStatus={{ installationStatus: 'AUTOMATIC_IN_PROGRESS' }} + updateEditionStatus={jest.fn()} + /> ); expect(wrapper).toMatchSnapshot(); }); it('should display an error notification', () => { const wrapper = shallow( - <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_FAILURE' }} /> + <EditionsStatusNotif + editionStatus={{ installationStatus: 'AUTOMATIC_FAILURE' }} + updateEditionStatus={jest.fn()} + /> ); expect(wrapper).toMatchSnapshot(); }); it('should display a ready notification', () => { const wrapper = shallow( - <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_READY' }} /> + <EditionsStatusNotif + editionStatus={{ installationStatus: 'AUTOMATIC_READY' }} + updateEditionStatus={jest.fn()} + /> ); expect(wrapper).toMatchSnapshot(); }); @@ -46,7 +66,25 @@ it('should display install errors', () => { const wrapper = shallow( <EditionsStatusNotif editionStatus={{ installationStatus: 'AUTOMATIC_IN_PROGRESS', installError: 'Foo error' }} + updateEditionStatus={jest.fn()} /> ); expect(wrapper).toMatchSnapshot(); }); + +it('should allow to dismiss install errors', async () => { + const updateEditionStatus = jest.fn(); + const wrapper = shallow( + <EditionsStatusNotif + editionStatus={{ installationStatus: 'NONE', installError: 'Foo error' }} + updateEditionStatus={updateEditionStatus} + /> + ); + click(wrapper.find('a')); + expect(dismissMsg).toHaveBeenCalled(); + await new Promise(setImmediate); + expect(updateEditionStatus).toHaveBeenCalledWith({ + installationStatus: 'NONE', + installError: undefined + }); +}); diff --git a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap index d136af03406..0f79649b873 100644 --- a/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/marketplace/components/__tests__/__snapshots__/EditionsStatusNotif-test.tsx.snap @@ -12,6 +12,13 @@ exports[`should display install errors 1`] = ` className="alert alert-danger" > Foo error + <a + className="pull-right button-link text-danger" + href="#" + onClick={[Function]} + > + <CloseIcon /> + </a> </div> </div> `; |