diff --git a/ghost/admin/.lint-todo b/ghost/admin/.lint-todo index 7c276cc23e..13ef8548d1 100644 --- a/ghost/admin/.lint-todo +++ b/ghost/admin/.lint-todo @@ -1839,3 +1839,26 @@ add|ember-template-lint|no-nested-landmark|131|24|131|24|9eb7d301f1f50334e793aaf remove|ember-template-lint|table-groups|5|8|5|8|9b53737f259340d2970119c70be1af3a83081cab|1643760000000|1646352000000|1648940400000|app/components/gh-portal-links.hbs remove|ember-template-lint|no-action|11|72|11|72|a8b13fedc345ad6ca2c1514b209e84a19d82915d|1643760000000|1646352000000|1648940400000|app/components/gh-portal-links.hbs remove|ember-template-lint|no-invalid-interactive|11|64|11|64|5b5bb32075e5f0470fbe12d099229964f1dc7dfe|1643760000000|1646352000000|1648940400000|app/components/gh-portal-links.hbs +remove|ember-template-lint|no-action|32|48|32|48|993079a3ad8b556330d2aa5a0cb01dcb63a4bdb0|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|43|44|43|44|166ab6daac6556b497c8693a94715fca7c8158f9|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|71|43|71|43|8234e3f75b9c72cbd8e726b3d26f03d0a2a26dfb|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|72|47|72|47|829a527ba5a2ff30234ea240400d9935421c5556|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|90|43|90|43|ffe817ddea62969f8b2d45127828416d6adfc773|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|91|47|91|47|bb670279bd6dc2dfca1b714200cc42b1b4b38d69|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|107|74|107|74|159455060ac247ee60be18b8ebb8f7907f652132|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|110|74|110|74|38bfdf3e4ec8c79d195e80a48c2f343757845cab|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|132|74|132|74|2e441eb8956fdd6684b75ae1139f097237ebc1fa|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|135|74|135|74|2d51bed033fe50baea3002bf5acc234ac3738b58|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|157|74|157|74|bfcab210b651dbe74a1b9e5eb565756ab863f3bb|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-passed-in-event-handlers|71|36|71|36|094eea0b41531dd31234f4a47d22faa0ad3cbaa7|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-passed-in-event-handlers|90|36|90|36|ecfb8bbcc595aaaf0c1a929efa948e75787a5e18|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|202|92|202|92|bb9a5097405a3fcaad689d0d592294e1741edd7b|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|246|72|246|72|541a413eb944fa0091ea28f7256a20e2a724a3a9|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|255|17|255|17|9fa650a0ca3325ef8182634ad5d34c5db548287a|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|256|15|256|15|2fe6989da74d54cbdbaef0ae0a7cc68f22825a1d|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|266|17|266|17|1907c9b1ae81cfb450b7a2ae7e0f874c26595144|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|267|15|267|15|20eb710122c95e74c9293fe14e11f105a86f172a|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|273|17|273|17|17ede810216f1750e8f5a0447f0d8ca9dd51eefd|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|274|15|274|15|97a8488c705fd167d8803635395470e929e57425|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|280|17|280|17|989fbbea271b49165ed76435745c43151cfc7ef7|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs +remove|ember-template-lint|no-action|281|15|281|15|6466c92ea49ac23d994c08c504e6d4ffefcadbff|1643760000000|1646352000000|1648940400000|app/templates/settings/integration.hbs diff --git a/ghost/admin/app/controllers/settings/integration.js b/ghost/admin/app/controllers/settings/integration.js index 8c24cc0b29..be288b0ca5 100644 --- a/ghost/admin/app/controllers/settings/integration.js +++ b/ghost/admin/app/controllers/settings/integration.js @@ -1,39 +1,41 @@ import Controller from '@ember/controller'; -import classic from 'ember-classic-decorator'; import config from 'ghost-admin/config/environment'; import copyTextToClipboard from 'ghost-admin/utils/copy-text-to-clipboard'; import { IMAGE_EXTENSIONS, IMAGE_MIME_TYPES } from 'ghost-admin/components/gh-image-uploader'; -import {action, computed} from '@ember/object'; -import {alias} from '@ember/object/computed'; +import {action} from '@ember/object'; import {htmlSafe} from '@ember/template'; import {inject as service} from '@ember/service'; import {task, timeout} from 'ember-concurrency'; +import {tracked} from '@glimmer/tracking'; -@classic export default class IntegrationController extends Controller { @service config; @service ghostPaths; imageExtensions = IMAGE_EXTENSIONS; imageMimeTypes = IMAGE_MIME_TYPES; - showRegenerateKeyModal = false; - selectedApiKey = null; - isApiKeyRegenerated = false; - init() { - super.init(...arguments); + @tracked showDeleteIntegrationModal = false; + @tracked showRegenerateKeyModal = false; + @tracked showUnsavedChangesModal = false; + @tracked selectedApiKey = null; + @tracked isApiKeyRegenerated = false; + @tracked webhookToDelete; + + constructor() { + super(...arguments); if (this.isTesting === undefined) { this.isTesting = config.environment === 'test'; } } - @alias('model') - integration; + get integration() { + return this.model; + } - @computed get apiUrl() { let origin = window.location.origin; let subdir = this.ghostPaths.subdir; @@ -42,20 +44,17 @@ export default class IntegrationController extends Controller { return url.replace(/\/$/, ''); } - @computed('isApiKeyRegenerated', 'selectedApiKey') get regeneratedKeyType() { if (this.isApiKeyRegenerated) { - return this.get('selectedApiKey.type'); + return this.selectedApiKey.type; } return null; } - @computed get allWebhooks() { return this.store.peekAll('webhook'); } - @computed('integration.id', 'allWebhooks.@each.{isNew,isDeleted}') get filteredWebhooks() { return this.allWebhooks.filter((webhook) => { let matchesIntegration = webhook.belongsTo('integration').id() === this.integration.id; @@ -66,7 +65,6 @@ export default class IntegrationController extends Controller { }); } - @computed('integration.iconImage') get iconImageStyle() { let url = this.integration.iconImage; if (url) { @@ -83,11 +81,22 @@ export default class IntegrationController extends Controller { } @action - triggerIconFileDialog() { + triggerIconFileDialog(event) { + event.preventDefault(); let input = document.querySelector('input[type="file"][name="iconImage"]'); input.click(); } + @action + updateProperty(property, event) { + this.integration.set(property, event.target.value); + } + + @action + validateProperty(property) { + this.integration.validate({property}); + } + @action setIconImage([image]) { this.integration.set('iconImage', image.url); @@ -103,13 +112,13 @@ export default class IntegrationController extends Controller { let leaveTransition = this.leaveScreenTransition; if (!transition && this.showUnsavedChangesModal) { - this.set('leaveScreenTransition', null); - this.set('showUnsavedChangesModal', false); + this.leaveScreenTransition = null; + this.showUnsavedChangesModal = false; return; } if (!leaveTransition || transition.targetName === leaveTransition.targetName) { - this.set('leaveScreenTransition', transition); + this.leaveScreenTransition = transition; // if a save is running, wait for it to finish then transition if (this.saveTask.isRunning) { @@ -119,12 +128,13 @@ export default class IntegrationController extends Controller { } // we genuinely have unsaved data, show the modal - this.set('showUnsavedChangesModal', true); + this.showUnsavedChangesModal = true; } } @action - leaveScreen() { + leaveScreen(event) { + event?.preventDefault(); let transition = this.leaveScreenTransition; if (!transition) { @@ -139,53 +149,63 @@ export default class IntegrationController extends Controller { } @action - deleteIntegration() { + deleteIntegration(event) { + event?.preventDefault(); this.integration.destroyRecord(); } @action - confirmIntegrationDeletion() { - this.set('showDeleteIntegrationModal', true); + confirmIntegrationDeletion(event) { + event?.preventDefault(); + this.showDeleteIntegrationModal = true; } @action - cancelIntegrationDeletion() { - this.set('showDeleteIntegrationModal', false); + cancelIntegrationDeletion(event) { + event?.preventDefault(); + this.showDeleteIntegrationModal = false; } @action - confirmRegenerateKeyModal(apiKey) { - this.set('showRegenerateKeyModal', true); - this.set('isApiKeyRegenerated', false); - this.set('selectedApiKey', apiKey); + confirmRegenerateKeyModal(apiKey, event) { + event?.preventDefault(); + this.showRegenerateKeyModal = true; + this.isApiKeyRegenerated = false; + this.selectedApiKey = apiKey; } @action - cancelRegenerateKeyModal() { - this.set('showRegenerateKeyModal', false); + cancelRegenerateKeyModal(event) { + event?.preventDefault(); + this.showRegenerateKeyModal = false; } @action - regenerateKey() { - this.set('isApiKeyRegenerated', true); + regenerateKey(event) { + event?.preventDefault(); + this.isApiKeyRegenerated = true; } @action - confirmWebhookDeletion(webhook) { - this.set('webhookToDelete', webhook); + confirmWebhookDeletion(webhook, event) { + event?.preventDefault(); + this.webhookToDelete = webhook; } @action - cancelWebhookDeletion() { - this.set('webhookToDelete', null); + cancelWebhookDeletion(event) { + event?.preventDefault(); + this.webhookToDelete = null; } @action - deleteWebhook() { + deleteWebhook(event) { + event?.preventDefault(); return this.webhookToDelete.destroyRecord(); } - @task(function* () { + @task + *saveTask() { try { return yield this.integration.save(); } catch (e) { @@ -196,24 +216,23 @@ export default class IntegrationController extends Controller { throw e; } - }) - saveTask; + } - @task(function* () { + @task + *copyContentKey() { copyTextToClipboard(this.integration.contentKey.secret); yield timeout(this.isTesting ? 50 : 3000); - }) - copyContentKey; + } - @task(function* () { + @task + *copyAdminKey() { copyTextToClipboard(this.integration.adminKey.secret); yield timeout(this.isTesting ? 50 : 3000); - }) - copyAdminKey; + } - @task(function* () { + @task + *copyApiUrl() { copyTextToClipboard(this.apiUrl); yield timeout(this.isTesting ? 50 : 3000); - }) - copyApiUrl; + } } diff --git a/ghost/admin/app/mixins/text-input.js b/ghost/admin/app/mixins/text-input.js index 0b380c6641..26146517d1 100644 --- a/ghost/admin/app/mixins/text-input.js +++ b/ghost/admin/app/mixins/text-input.js @@ -35,6 +35,10 @@ export default Mixin.create({ } }, + input(event) { + this['on-input']?.(event); + }, + keyDown(event) { // stop event propagation when pressing "enter" // most useful in the case when undesired (global) keyboard shortcuts diff --git a/ghost/admin/app/templates/settings/integration.hbs b/ghost/admin/app/templates/settings/integration.hbs index d719a7b29d..417656fa69 100644 --- a/ghost/admin/app/templates/settings/integration.hbs +++ b/ghost/admin/app/templates/settings/integration.hbs @@ -29,7 +29,7 @@ {{#if uploader.isUploading}} @@ -40,7 +40,7 @@ @@ -68,8 +68,8 @@ @class="gh-input mt1 mb1" @type="text" @value={{readonly this.integration.name}} - @input={{action (mut this.integration.name) value="target.value"}} - @focus-out={{action "validate" "name" target=this.integration}} + @on-input={{fn this.updateProperty "name"}} + @focus-out={{fn this.validateProperty "name"}} data-test-input="name" /> @@ -87,8 +87,8 @@ @class="gh-input mt1" @type="text" @value={{readonly this.integration.description}} - @input={{action (mut this.integration.description) value="target.value"}} - @focus-out={{action "validate" "description" target=this.integration}} + @on-input={{fn this.updateProperty "description"}} + @focus-out={{fn this.validateProperty "description"}} data-test-input="description" /> @@ -104,10 +104,10 @@ {{this.integration.contentKey.secret}}
- - -
@@ -243,7 +243,7 @@
-
@@ -252,8 +252,8 @@ {{#if this.showUnsavedChangesModal}} {{/if}} @@ -263,22 +263,22 @@ apiKey=this.selectedApiKey integration=this.integration }} - @confirm={{action "regenerateKey"}} - @close={{action "cancelRegenerateKeyModal"}} + @confirm={{this.regenerateKey}} + @close={{this.cancelRegenerateKeyModal}} @modifier="action wide" /> {{/if}} {{#if this.showDeleteIntegrationModal}} {{/if}} {{#if this.webhookToDelete}} {{/if}}