aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>2018-02-09 17:20:04 +0100
committerGuillaume Jambet <guillaume.jambet@gmail.com>2018-03-01 15:21:05 +0100
commita7cdf1a94281ea4f49db4635682d29e990e8801c (patch)
tree68c49435de14a0c0205b68eac248218fb361b291
parent277349697f2e672ae8c5f438f734cfb9b6223d46 (diff)
downloadsonarqube-a7cdf1a94281ea4f49db4635682d29e990e8801c.tar.gz
sonarqube-a7cdf1a94281ea4f49db4635682d29e990e8801c.zip
SONAR-10346 Display webhook latest delivery status
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/App.tsx8
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/PageActions.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/WebhookActions.tsx15
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx23
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx1
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/App-test.tsx5
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/PageActions-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookActions-test.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookItem-test.tsx27
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookActions-test.tsx.snap25
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookItem-test.tsx.snap52
-rw-r--r--server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhooksList-test.tsx.snap3
-rw-r--r--sonar-core/src/main/resources/org/sonar/l10n/core.properties2
15 files changed, 166 insertions, 20 deletions
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx
index 68a8f9d42bd..9d33f1486e9 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/App.tsx
@@ -37,7 +37,7 @@ interface State {
}
export default class App extends React.PureComponent<Props, State> {
- mounted: boolean = false;
+ mounted = false;
state: State = { loading: true, webhooks: [] };
componentDidMount() {
@@ -65,7 +65,11 @@ export default class App extends React.PureComponent<Props, State> {
};
getScopeParams = ({ organization, component } = this.props) => {
- return { organization: organization && organization.key, project: component && component.key };
+ const organizationKey = organization && organization.key;
+ return {
+ organization: component ? component.organization : organizationKey,
+ project: component && component.key
+ };
};
handleCreate = (data: { name: string; url: string }) => {
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx
index 33c0439d38e..ce12280de2f 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveriesForm.tsx
@@ -40,7 +40,7 @@ interface State {
const PAGE_SIZE = 10;
export default class DeliveriesForm extends React.PureComponent<Props, State> {
- mounted: boolean = false;
+ mounted = false;
state: State = { deliveries: [], loading: true };
componentDidMount() {
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx
index 6eb15b3bc8b..cd75390ec0f 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/DeliveryItem.tsx
@@ -40,7 +40,7 @@ interface State {
}
export default class DeliveryItem extends React.PureComponent<Props, State> {
- mounted: boolean = false;
+ mounted = false;
state: State = { loading: false, open: false };
componentDidMount() {
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/PageActions.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/PageActions.tsx
index 3968f8bdfbe..78e045ea959 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/PageActions.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/PageActions.tsx
@@ -35,7 +35,7 @@ interface State {
const WEBHOOKS_LIMIT = 10;
export default class PageActions extends React.PureComponent<Props, State> {
- mounted: boolean = false;
+ mounted = false;
state: State = { openCreate: false };
componentDidMount() {
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/WebhookActions.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/WebhookActions.tsx
index 42351e01a1f..0027720ad60 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/WebhookActions.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/WebhookActions.tsx
@@ -40,7 +40,7 @@ interface State {
}
export default class WebhookActions extends React.PureComponent<Props, State> {
- mounted: boolean = false;
+ mounted = false;
state: State = { deliveries: false, updating: false };
componentDidMount() {
@@ -77,18 +77,19 @@ export default class WebhookActions extends React.PureComponent<Props, State> {
render() {
const { webhook } = this.props;
- // TODO Disable "Show deliveries" if there is no lastDelivery
return (
<>
<ActionsDropdown className="big-spacer-left">
<ActionsDropdownItem className="js-webhook-update" onClick={this.handleUpdateClick}>
{translate('update_verb')}
</ActionsDropdownItem>
- <ActionsDropdownItem
- className="js-webhook-deliveries"
- onClick={this.handleDeliveriesClick}>
- {translate('webhooks.deliveries.show')}
- </ActionsDropdownItem>
+ {webhook.latestDelivery && (
+ <ActionsDropdownItem
+ className="js-webhook-deliveries"
+ onClick={this.handleDeliveriesClick}>
+ {translate('webhooks.deliveries.show')}
+ </ActionsDropdownItem>
+ )}
<ActionsDropdownDivider />
<ConfirmButton
confirmButtonText={translate('delete')}
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx
index b51ceb085af..5016508e13c 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/WebhookItem.tsx
@@ -19,7 +19,11 @@
*/
import * as React from 'react';
import WebhookActions from './WebhookActions';
-import { Webhook } from '../../../app/types';
+import AlertErrorIcon from '../../../components/icons-components/AlertErrorIcon';
+import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessIcon';
+import DateTimeFormatter from '../../../components/intl/DateTimeFormatter';
+import { Webhook, WebhookDelivery } from '../../../app/types';
+import { translate } from '../../../helpers/l10n';
interface Props {
onDelete: (webhook: string) => Promise<void>;
@@ -32,9 +36,26 @@ export default function WebhookItem({ onDelete, onUpdate, webhook }: Props) {
<tr>
<td>{webhook.name}</td>
<td>{webhook.url}</td>
+ <td>
+ <LatestDelivery latestDelivery={webhook.latestDelivery} />
+ </td>
<td className="thin nowrap text-right">
<WebhookActions onDelete={onDelete} onUpdate={onUpdate} webhook={webhook} />
</td>
</tr>
);
}
+
+export function LatestDelivery({ latestDelivery }: { latestDelivery?: WebhookDelivery }) {
+ if (!latestDelivery) {
+ return <span>{translate('webhooks.last_execution.none')}</span>;
+ }
+ return (
+ <>
+ {latestDelivery.success ? <AlertSuccessIcon /> : <AlertErrorIcon />}
+ <span className="spacer-left">
+ <DateTimeFormatter date={latestDelivery.at} />
+ </span>
+ </>
+ );
+}
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx
index 57f33ffe151..92e8f191c29 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/WebhooksList.tsx
@@ -35,6 +35,7 @@ export default class WebhooksList extends React.PureComponent<Props> {
<tr>
<th>{translate('name')}</th>
<th>{translate('webhooks.url')}</th>
+ <th>{translate('webhooks.last_execution')}</th>
<th />
</tr>
</thead>
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/App-test.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/App-test.tsx
index 62d45726d81..756f3830852 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/App-test.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/App-test.tsx
@@ -81,7 +81,10 @@ describe('should correctly fetch webhooks when', () => {
shallow(<App component={component} organization={undefined} />);
await new Promise(setImmediate);
- expect(searchWebhooks).toHaveBeenCalledWith({ project: component.key });
+ expect(searchWebhooks).toHaveBeenCalledWith({
+ project: component.key,
+ organization: component.organization
+ });
});
it('on organization scope', async () => {
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/PageActions-test.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/PageActions-test.tsx
index f50a9b062a4..e5a6e374120 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/PageActions-test.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/PageActions-test.tsx
@@ -47,5 +47,5 @@ it('should display the create form', () => {
});
function getWrapper(props = {}) {
- return shallow(<PageActions onCreate={jest.fn()} loading={false} webhooksCount={5} {...props} />);
+ return shallow(<PageActions loading={false} onCreate={jest.fn()} webhooksCount={5} {...props} />);
}
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookActions-test.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookActions-test.tsx
index b4331ce8ce8..70fe2bc5c77 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookActions-test.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookActions-test.tsx
@@ -22,7 +22,19 @@ import { shallow } from 'enzyme';
import WebhookActions from '../WebhookActions';
import { click } from '../../../../helpers/testUtils';
-const webhook = { key: '1', name: 'foo', url: 'http://foo.bar' };
+const webhook = {
+ key: '1',
+ name: 'foo',
+ url: 'http://foo.bar'
+};
+
+const delivery = {
+ at: '12.02.2018',
+ durationMs: 20,
+ httpStatus: 200,
+ id: '2',
+ success: true
+};
it('should render correctly', () => {
expect(getWrapper()).toMatchSnapshot();
@@ -55,7 +67,8 @@ it('should display the delete webhook form', () => {
});
it('should display the deliveries form', () => {
- const wrapper = getWrapper();
+ const wrapper = getWrapper({ webhook: { ...webhook, latestDelivery: delivery } });
+ expect(wrapper).toMatchSnapshot();
click(wrapper.find('.js-webhook-deliveries'));
expect(wrapper.find('DeliveriesForm').exists()).toBeTruthy();
});
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookItem-test.tsx b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookItem-test.tsx
index 9322cf58e0a..6861daae1d2 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookItem-test.tsx
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/WebhookItem-test.tsx
@@ -19,9 +19,22 @@
*/
import * as React from 'react';
import { shallow } from 'enzyme';
-import WebhookItem from '../WebhookItem';
+import WebhookItem, { LatestDelivery } from '../WebhookItem';
-const webhook = { key: '1', name: 'my webhook', url: 'http://webhook.target' };
+const latestDelivery = {
+ at: '12.02.2018',
+ durationMs: 20,
+ httpStatus: 200,
+ id: '2',
+ success: true
+};
+
+const webhook = {
+ key: '1',
+ name: 'my webhook',
+ url: 'http://webhook.target',
+ latestDelivery
+};
it('should render correctly', () => {
expect(
@@ -34,3 +47,13 @@ it('should render correctly', () => {
)
).toMatchSnapshot();
});
+
+it('should render correctly the latest delivery', () => {
+ expect(shallow(<LatestDelivery latestDelivery={undefined} />)).toMatchSnapshot();
+ expect(shallow(<LatestDelivery latestDelivery={latestDelivery} />)).toMatchSnapshot();
+ expect(
+ shallow(
+ <LatestDelivery latestDelivery={{ ...latestDelivery, httpStatus: 500, success: false }} />
+ )
+ ).toMatchSnapshot();
+});
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookActions-test.tsx.snap b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookActions-test.tsx.snap
index e3d35952ba5..7079ff776af 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookActions-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookActions-test.tsx.snap
@@ -1,6 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
-exports[`should render correctly 1`] = `
+exports[`should display the deliveries form 1`] = `
<React.Fragment>
<ActionsDropdown
className="big-spacer-left"
@@ -28,3 +28,26 @@ exports[`should render correctly 1`] = `
</ActionsDropdown>
</React.Fragment>
`;
+
+exports[`should render correctly 1`] = `
+<React.Fragment>
+ <ActionsDropdown
+ className="big-spacer-left"
+ >
+ <ActionsDropdownItem
+ className="js-webhook-update"
+ onClick={[Function]}
+ >
+ update_verb
+ </ActionsDropdownItem>
+ <ActionsDropdownDivider />
+ <ConfirmButton
+ confirmButtonText="delete"
+ isDestructive={true}
+ modalBody="webhooks.delete.confirm.foo"
+ modalHeader="webhooks.delete"
+ onConfirm={[Function]}
+ />
+ </ActionsDropdown>
+</React.Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookItem-test.tsx.snap b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookItem-test.tsx.snap
index 7f45d646e0a..99338c1907f 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookItem-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhookItem-test.tsx.snap
@@ -8,6 +8,19 @@ exports[`should render correctly 1`] = `
<td>
http://webhook.target
</td>
+ <td>
+ <LatestDelivery
+ latestDelivery={
+ Object {
+ "at": "12.02.2018",
+ "durationMs": 20,
+ "httpStatus": 200,
+ "id": "2",
+ "success": true,
+ }
+ }
+ />
+ </td>
<td
className="thin nowrap text-right"
>
@@ -17,6 +30,13 @@ exports[`should render correctly 1`] = `
webhook={
Object {
"key": "1",
+ "latestDelivery": Object {
+ "at": "12.02.2018",
+ "durationMs": 20,
+ "httpStatus": 200,
+ "id": "2",
+ "success": true,
+ },
"name": "my webhook",
"url": "http://webhook.target",
}
@@ -25,3 +45,35 @@ exports[`should render correctly 1`] = `
</td>
</tr>
`;
+
+exports[`should render correctly the latest delivery 1`] = `
+<span>
+ webhooks.last_execution.none
+</span>
+`;
+
+exports[`should render correctly the latest delivery 2`] = `
+<React.Fragment>
+ <AlertSuccessIcon />
+ <span
+ className="spacer-left"
+ >
+ <DateTimeFormatter
+ date="12.02.2018"
+ />
+ </span>
+</React.Fragment>
+`;
+
+exports[`should render correctly the latest delivery 3`] = `
+<React.Fragment>
+ <AlertErrorIcon />
+ <span
+ className="spacer-left"
+ >
+ <DateTimeFormatter
+ date="12.02.2018"
+ />
+ </span>
+</React.Fragment>
+`;
diff --git a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhooksList-test.tsx.snap b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhooksList-test.tsx.snap
index ff8401ea461..1f4b340e35e 100644
--- a/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhooksList-test.tsx.snap
+++ b/server/sonar-web/src/main/js/apps/webhooks/components/__tests__/__snapshots__/WebhooksList-test.tsx.snap
@@ -18,6 +18,9 @@ exports[`should correctly render the webhooks 1`] = `
<th>
webhooks.url
</th>
+ <th>
+ webhooks.last_execution
+ </th>
<th />
</tr>
</thead>
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 daf129eab20..f8b475cabd6 100644
--- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties
+++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties
@@ -2824,6 +2824,8 @@ webhooks.delivery.duration_x=Duration: {0}
webhooks.delivery.payload=Payload:
webhooks.delivery.response_x=Response: {0}
webhooks.documentation_link=Webhooks documentation
+webhooks.last_execution=Last execution
+webhooks.last_execution.none=Never
webhooks.maximum_reached=You reached your maximum number of {0} webhooks. You can still update or delete an existing one.
webhooks.name=Name
webhooks.name.required=Name is required.