0
Fork 0
mirror of https://github.com/TryGhost/Ghost.git synced 2025-02-24 23:48:13 -05:00

Added edit webhook modal (#1056)

requires https://github.com/TryGhost/Ghost/pull/10033
- added `settings.integration.webhooks.edit` route
  - `/integrations/:integration_id/webhooks/:webhook_id`
- added error handling to the webhook form modal that copes with the actual errors we get back from the server
- added `event-name` helper to display humanised event names in the webhooks list
- added delete button to the webhooks list and associated confirmation modal
This commit is contained in:
Kevin Ansfield 2018-10-19 17:34:53 +01:00 committed by GitHub
parent 832968d4a5
commit 296e35493d
11 changed files with 139 additions and 9 deletions

View file

@ -0,0 +1,26 @@
import ModalComponent from 'ghost-admin/components/modal-base';
import {alias} from '@ember/object/computed';
import {inject as service} from '@ember/service';
import {task} from 'ember-concurrency';
export default ModalComponent.extend({
notifications: service(),
webhook: alias('model'),
actions: {
confirm() {
this.deleteWebhook.perform();
}
},
deleteWebhook: task(function* () {
try {
yield this.confirm();
} catch (error) {
this.notifications.showAPIError(error, {key: 'webhook.delete.failed'});
} finally {
this.send('closeModal');
}
}).drop()
});

View file

@ -1,5 +1,6 @@
import ModalComponent from 'ghost-admin/components/modal-base';
import Webhook from 'ghost-admin/models/webhook';
import {AVAILABLE_EVENTS} from 'ghost-admin/helpers/event-name';
import {alias} from '@ember/object/computed';
import {camelize} from '@ember/string';
import {isInvalidError} from 'ember-ajax/errors';
@ -10,6 +11,7 @@ export default ModalComponent.extend({
router: service(),
availableEvents: null,
error: null,
buttonText: 'Save',
successText: 'Saved',
@ -19,11 +21,7 @@ export default ModalComponent.extend({
init() {
this._super(...arguments);
this.availableEvents = [
{event: 'site.changed', name: 'Site Changed (rebuild)'},
{event: 'subscriber.added', name: 'Subscriber Added'},
{event: 'subscriber.deleted', name: 'Subscriber Deleted'}
];
this.availableEvents = AVAILABLE_EVENTS;
},
didReceiveAttrs() {
@ -45,6 +43,8 @@ export default ModalComponent.extend({
},
saveWebhook: task(function* () {
this.set('error', null);
try {
let webhook = yield this.confirm();
let integration = yield webhook.get('integration');
@ -62,6 +62,8 @@ export default ModalComponent.extend({
if (property && attrs.includes(property)) {
this.webhook.errors.add(property, message);
this.webhook.hasValidated.pushObject(property);
} else {
this.set('error', message);
}
});

View file

@ -61,6 +61,18 @@ export default Controller.extend({
this.integration.rollbackAttributes();
return transition.retry();
},
confirmWebhookDeletion(webhook) {
this.set('webhookToDelete', webhook);
},
cancelWebhookDeletion() {
this.set('webhookToDelete', null);
},
deleteWebhook() {
return this.webhookToDelete.destroyRecord();
}
},

View file

@ -0,0 +1,19 @@
import Controller from '@ember/controller';
import {alias} from '@ember/object/computed';
export default Controller.extend({
webhook: alias('model'),
actions: {
save() {
return this.webhook.save();
},
cancel() {
// 'new' route's dectivate hook takes care of rollback
return this.webhook.get('integration').then((integration) => {
this.transitionToRoute('settings.integration', integration);
});
}
}
});

View file

@ -0,0 +1,15 @@
import {helper} from '@ember/component/helper';
export const AVAILABLE_EVENTS = [
{event: 'site.changed', name: 'Site Changed (rebuild)'},
{event: 'subscriber.added', name: 'Subscriber Added'},
{event: 'subscriber.deleted', name: 'Subscriber Deleted'}
];
export function eventName([event]/*, hash*/) {
let match = AVAILABLE_EVENTS.findBy('event', event);
return match ? match.name : event;
}
export default helper(eventName);

View file

@ -57,6 +57,7 @@ Router.map(function () {
});
this.route('settings.integration', {path: '/settings/integrations/:integration_id'}, function () {
this.route('webhooks.new', {path: 'webhooks/new'});
this.route('webhooks.edit', {path: 'webhooks/:webhook_id'});
});
this.route('settings.integrations.slack', {path: '/settings/integrations/slack'});
this.route('settings.integrations.amp', {path: '/settings/integrations/amp'});

View file

@ -0,0 +1,14 @@
import Route from '@ember/routing/route';
export default Route.extend({
model(params) {
let integration = this.modelFor('settings.integration');
let webhook = integration.webhooks.findBy('id', params.webhook_id);
return webhook;
},
deactivate() {
this._super(...arguments);
this.controller.webhook.rollbackAttributes();
}
});

View file

@ -0,0 +1,15 @@
<header class="modal-header">
<h1>Are you sure?</h1>
</header>
<a class="close" href="" title="Close" {{action "closeModal"}}>{{svg-jar "close"}}<span class="hidden">Close</span></a>
<div class="modal-body">
<p>
Deleting this webhook may prevent the integration from functioning.
</p>
</div>
<div class="modal-footer">
<button {{action "closeModal"}} class="gh-btn"><span>Cancel</span></button>
{{gh-task-button "Delete Webhook" successText="Deleted" task=deleteWebhook class="gh-btn gh-btn-red gh-btn-icon"}}
</div>

View file

@ -78,6 +78,9 @@
{{gh-error-message errors=webhook.errors property="secret" data-test-error="new-webhook-secret"}}
{{/gh-form-group}}
</fieldset>
{{#if error}}
<p class="red">{{error}}</p>
{{/if}}
</div>
<div class="modal-footer">

View file

@ -127,16 +127,27 @@
<th class="pa3 br3 br--bottom br--right bg-lightgrey-l1">Name</th>
<th class="pa3 bg-lightgrey-l1">Event</th>
<th class="pa3 bg-lightgrey-l1">URL</th>
<th class="pa3 br3 br--top br--left bg-lightgrey-l1">Last triggered</th>
<th class="pa3 bg-lightgrey-l1">Last triggered</th>
<th class="pa3 br3 br--top br--left bg-lightgrey-l1"></th>
</tr>
</thead>
<tbody>
{{#each filteredWebhooks as |webhook|}}
<tr>
<tr class="hide-child">
<td class="pa3">{{webhook.name}}</td>
<td class="pa3">{{webhook.event}}</td>
<td class="pa3">{{event-name webhook.event}}</td>
<td class="pa3">{{webhook.targetUrl}}</td>
<td class="pa3">{{webhook.lastTriggeredAtUTC}}</td>
<td class="pa3">{{or webhook.lastTriggeredAtUTC "Not triggered"}}</td>
<td class="w1 pa3 nowrap">
<div class="child">
{{#link-to "settings.integration.webhooks.edit" integration webhook}}
{{svg-jar "koenig/kg-thin-edit" class="w4 fill-black-80"}}
{{/link-to}}
<button {{action "confirmWebhookDeletion" webhook}}>
{{svg-jar "trash" class="w4 fill-red"}}
</button>
</div>
</td>
</tr>
{{else}}
<tr>
@ -164,4 +175,11 @@
modifier="action wide"}}
{{/if}}
{{#if webhookToDelete}}
{{gh-fullscreen-modal "delete-webhook"
confirm=(action "deleteWebhook")
close=(action "cancelWebhookDeletion")
modifier="action wide"}}
{{/if}}
{{outlet}}

View file

@ -0,0 +1,5 @@
{{gh-fullscreen-modal "webhook-form"
model=webhook
confirm=(action "save")
close=(action "cancel")
modifier="action wide"}}