diff --git a/ghost/admin/app/components/modal-delete-webhook.js b/ghost/admin/app/components/modal-delete-webhook.js
new file mode 100644
index 0000000000..b39eeb90e3
--- /dev/null
+++ b/ghost/admin/app/components/modal-delete-webhook.js
@@ -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()
+});
diff --git a/ghost/admin/app/components/modal-webhook-form.js b/ghost/admin/app/components/modal-webhook-form.js
index dd538410e2..4926ca0fab 100644
--- a/ghost/admin/app/components/modal-webhook-form.js
+++ b/ghost/admin/app/components/modal-webhook-form.js
@@ -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);
}
});
diff --git a/ghost/admin/app/controllers/settings/integration.js b/ghost/admin/app/controllers/settings/integration.js
index 9355297047..d680220bab 100644
--- a/ghost/admin/app/controllers/settings/integration.js
+++ b/ghost/admin/app/controllers/settings/integration.js
@@ -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();
}
},
diff --git a/ghost/admin/app/controllers/settings/integration/webhooks/edit.js b/ghost/admin/app/controllers/settings/integration/webhooks/edit.js
new file mode 100644
index 0000000000..6cc9234613
--- /dev/null
+++ b/ghost/admin/app/controllers/settings/integration/webhooks/edit.js
@@ -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);
+ });
+ }
+ }
+});
diff --git a/ghost/admin/app/helpers/event-name.js b/ghost/admin/app/helpers/event-name.js
new file mode 100644
index 0000000000..d54a6a0ebe
--- /dev/null
+++ b/ghost/admin/app/helpers/event-name.js
@@ -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);
diff --git a/ghost/admin/app/router.js b/ghost/admin/app/router.js
index abf18f2c57..db79192318 100644
--- a/ghost/admin/app/router.js
+++ b/ghost/admin/app/router.js
@@ -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'});
diff --git a/ghost/admin/app/routes/settings/integration/webhooks/edit.js b/ghost/admin/app/routes/settings/integration/webhooks/edit.js
new file mode 100644
index 0000000000..8308394cbb
--- /dev/null
+++ b/ghost/admin/app/routes/settings/integration/webhooks/edit.js
@@ -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();
+ }
+});
diff --git a/ghost/admin/app/templates/components/modal-delete-webhook.hbs b/ghost/admin/app/templates/components/modal-delete-webhook.hbs
new file mode 100644
index 0000000000..ac927a91ba
--- /dev/null
+++ b/ghost/admin/app/templates/components/modal-delete-webhook.hbs
@@ -0,0 +1,15 @@
+Are you sure?
+
+ Deleting this webhook may prevent the integration from functioning. +
+{{error}}
+ {{/if}}