From 7ab0db9be73ed2ef0ac6d200a71da93e841095ef Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Thu, 8 Jul 2021 22:44:52 +0100 Subject: [PATCH] Fixed ember-test-selectors bound attributes deprecations no issue - converted publish menu and `gh-tags-list-item` components to glimmer syntax so data attributes can be passed in via `...attributes` - added explicit `data-test-button` bound attribute to `gh-task-button` component - moved `modal-theme-warnings` auto-bound data attribute from JS file to explicit html attribute in template --- .../app/components/gh-publishmenu-draft.hbs | 97 ++++++------- .../app/components/gh-publishmenu-draft.js | 134 +++++++++--------- .../components/gh-publishmenu-published.hbs | 32 +++-- .../components/gh-publishmenu-published.js | 12 -- .../components/gh-publishmenu-scheduled.hbs | 98 ++++++------- .../components/gh-publishmenu-scheduled.js | 104 +++++++------- ghost/admin/app/components/gh-publishmenu.hbs | 12 +- .../app/components/gh-tags-list-item.hbs | 56 ++++---- .../admin/app/components/gh-tags-list-item.js | 38 ----- ghost/admin/app/components/gh-task-button.js | 2 +- .../app/components/modal-theme-warnings.hbs | 2 +- .../app/components/modal-theme-warnings.js | 2 - ghost/admin/app/templates/members.hbs | 2 +- ghost/admin/app/templates/tags.hbs | 2 +- 14 files changed, 273 insertions(+), 320 deletions(-) delete mode 100644 ghost/admin/app/components/gh-publishmenu-published.js delete mode 100644 ghost/admin/app/components/gh-tags-list-item.js diff --git a/ghost/admin/app/components/gh-publishmenu-draft.hbs b/ghost/admin/app/components/gh-publishmenu-draft.hbs index 32c59bfe0f..c2c8b5c8ae 100644 --- a/ghost/admin/app/components/gh-publishmenu-draft.hbs +++ b/ghost/admin/app/components/gh-publishmenu-draft.hbs @@ -1,54 +1,55 @@ -
Ready to publish your {{this.post.displayName}}?
-
-
-
-
-
-
Set it live now
-
Publish this {{this.post.displayName}} immediately
+
+
Ready to publish your {{@post.displayName}}?
+
+
+
+
+
+
Set it live now
+
Publish this {{@post.displayName}} immediately
+
+
+
+
+
+
Schedule it for later
+ +
Set automatic future publish date
+
-
-
-
-
Schedule it for later
- -
Set automatic future publish date
-
-
-
- {{#if this.canSendEmail}} -
-
- {{#if this.isSendingEmailLimited}} -

{{html-safe this.sendingEmailLimitError}}

- {{else}} -
- + {{#if @canSendEmail}} +
+
+ {{#if @isSendingEmailLimited}} +

{{html-safe @sendingEmailLimitError}}

+ {{else}} +
+ -
- +
+ +
-
- {{/if}} + {{/if}} +
-
- {{/if}} -
- + {{/if}} + + \ No newline at end of file diff --git a/ghost/admin/app/components/gh-publishmenu-draft.js b/ghost/admin/app/components/gh-publishmenu-draft.js index ac8ecef455..5451a3bfb4 100644 --- a/ghost/admin/app/components/gh-publishmenu-draft.js +++ b/ghost/admin/app/components/gh-publishmenu-draft.js @@ -1,96 +1,96 @@ -import Component from '@ember/component'; +import Component from '@glimmer/component'; import moment from 'moment'; -import {computed} from '@ember/object'; +import {action} from '@ember/object'; import {isEmpty} from '@ember/utils'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task} from 'ember-concurrency-decorators'; +import {tracked} from '@glimmer/tracking'; -export default Component.extend({ - config: service(), - feature: service(), - session: service(), - settings: service(), - store: service(), +export default class GhPublishMenuDraftComponent extends Component { + @service config; + @service feature; + @service session; + @service settings; + @service store; - post: null, - saveType: null, + @tracked totalMemberCount = 0; // used to set minDate in datepicker - _minDate: null, - _publishedAtBlogTZ: null, + _minDate = null; + _publishedAtBlogTZ = null; - 'data-test-publishmenu-draft': true, + get disableEmailOption() { + // TODO: remove owner or admin check when editors can count members + return this.session.user.isOwnerOrAdmin && (this.totalMemberCount === 0 || this.countTotalMembersTask.isRunning); + } - // TODO: remove owner or admin check when editors can count members - disableEmailOption: computed('totalMemberCount', 'countTotalMembersTask.isRunning', function () { - return this.get('session.user.isOwnerOrAdmin') && (this.totalMemberCount === 0 || this.countTotalMembersTask.isRunning); - }), + constructor() { + super(...arguments); + this.args.post.set('publishedAtBlogTZ', this.args.post.publishedAtUTC); + } - didInsertElement() { - this.post.set('publishedAtBlogTZ', this.get('post.publishedAtUTC')); - this.send('setSaveType', 'publish'); - }, + @action + setSaveType(type) { + if (this.args.saveType !== type) { + let hasDateError = !isEmpty(this.args.post.errors.errorsFor('publishedAtBlogDate')); + let hasTimeError = !isEmpty(this.args.post.errors.errorsFor('publishedAtBlogTime')); + let minDate = this._getMinDate(); - actions: { - setSaveType(type) { - if (this.saveType !== type) { - let hasDateError = !isEmpty(this.get('post.errors').errorsFor('publishedAtBlogDate')); - let hasTimeError = !isEmpty(this.get('post.errors').errorsFor('publishedAtBlogTime')); - let minDate = this._getMinDate(); + this._minDate = minDate; + this.args.setSaveType(type); - this.set('_minDate', minDate); - this.setSaveType(type); - - // when publish: switch to now to avoid validation errors - // when schedule: switch to last valid or new minimum scheduled date - if (type === 'publish') { - if (!hasDateError && !hasTimeError) { - this._publishedAtBlogTZ = this.get('post.publishedAtBlogTZ'); - } else { - this._publishedAtBlogTZ = this.get('post.publishedAtUTC'); - } - - this.post.set('publishedAtBlogTZ', this.get('post.publishedAtUTC')); + // when publish: switch to now to avoid validation errors + // when schedule: switch to last valid or new minimum scheduled date + if (type === 'publish') { + if (!hasDateError && !hasTimeError) { + this._publishedAtBlogTZ = this.args.post.publishedAtBlogTZ; } else { - if (!this._publishedAtBlogTZ || moment(this._publishedAtBlogTZ).isBefore(minDate)) { - this.post.set('publishedAtBlogTZ', minDate); - } else { - this.post.set('publishedAtBlogTZ', this._publishedAtBlogTZ); - } + this._publishedAtBlogTZ = this.args.post.publishedAtUTC; } - this.post.validate(); + this.args.post.set('publishedAtBlogTZ', this.args.post.publishedAtUTC); + } else { + if (!this._publishedAtBlogTZ || moment(this._publishedAtBlogTZ).isBefore(minDate)) { + this.args.post.set('publishedAtBlogTZ', minDate); + } else { + this.args.post.set('publishedAtBlogTZ', this._publishedAtBlogTZ); + } } - }, - setDate(date) { - let post = this.post; - let dateString = moment(date).format('YYYY-MM-DD'); - - post.set('publishedAtBlogDate', dateString); - return post.validate(); - }, - - setTime(time) { - let post = this.post; - - post.set('publishedAtBlogTime', time); - return post.validate(); + this.args.post.validate(); } - }, + } - countTotalMembersTask: task(function*() { + @action + setDate(date) { + let post = this.args.post; + let dateString = moment(date).format('YYYY-MM-DD'); + + post.set('publishedAtBlogDate', dateString); + return post.validate(); + } + + @action + setTime(time) { + let post = this.args.post; + + post.set('publishedAtBlogTime', time); + return post.validate(); + } + + @task + *countTotalMembersTask() { const user = yield this.session.user; if (user.isOwnerOrAdmin) { const result = yield this.store.query('member', {limit: 1, filter: 'subscribed:true'}); - this.set('totalMemberCount', result.meta.pagination.total); + this.totalMemberCount = result.meta.pagination.total; } - }), + } + // API only accepts dates at least 2 mins in the future, default the // scheduled date 5 mins in the future to avoid immediate validation errors _getMinDate() { return moment.utc().add(5, 'minutes'); } - // API only accepts dates at least 2 mins in the future, default the -}); +} diff --git a/ghost/admin/app/components/gh-publishmenu-published.hbs b/ghost/admin/app/components/gh-publishmenu-published.hbs index e7b3333bb7..79e901c57f 100644 --- a/ghost/admin/app/components/gh-publishmenu-published.hbs +++ b/ghost/admin/app/components/gh-publishmenu-published.hbs @@ -1,17 +1,19 @@ -
Update {{post.displayName}} status
-
-
-
-
-
Unpublished
-
Revert this {{post.displayName}} to a private draft
+
+
Update {{@post.displayName}} status
+
+
+
+
+
Unpublished
+
Revert this {{@post.displayName}} to a private draft
+
-
-
-
-
-
Published
-
Display this {{post.displayName}} publicly
+
+
+
+
Published
+
Display this {{@post.displayName}} publicly
+
-
-
+ + \ No newline at end of file diff --git a/ghost/admin/app/components/gh-publishmenu-published.js b/ghost/admin/app/components/gh-publishmenu-published.js deleted file mode 100644 index 2a177d719d..0000000000 --- a/ghost/admin/app/components/gh-publishmenu-published.js +++ /dev/null @@ -1,12 +0,0 @@ -import Component from '@ember/component'; -import {inject as service} from '@ember/service'; - -export default Component.extend({ - feature: service(), - - 'data-test-publishmenu-published': true, - - didInsertElement() { - this.setSaveType('publish'); - } -}); diff --git a/ghost/admin/app/components/gh-publishmenu-scheduled.hbs b/ghost/admin/app/components/gh-publishmenu-scheduled.hbs index db3a951da3..4fabc93494 100644 --- a/ghost/admin/app/components/gh-publishmenu-scheduled.hbs +++ b/ghost/admin/app/components/gh-publishmenu-scheduled.hbs @@ -1,51 +1,53 @@ -
Will be published in {{this.timeToPublished}}
-
-
-
-
-
-
Revert to draft
-
Do not publish
-
-
-
-
-
-
Schedule for later
- -
Set automatic future publish date
-
-
-
- {{#if this.canSendEmail}} +
+
Will be published in {{this.timeToPublished}}
+
-
- {{#if this.isSendingEmailLimited}} -

{{html-safe this.sendingEmailLimitError}}

- {{else}} -
- - -
- -
-
- {{/if}} +
+
+
+
Revert to draft
+
Do not publish
+
+
+
+
+
+
Schedule for later
+ +
Set automatic future publish date
+
- {{/if}} -
+ {{#if @canSendEmail}} +
+
+ {{#if @isSendingEmailLimited}} +

{{html-safe @sendingEmailLimitError}}

+ {{else}} +
+ + +
+ +
+
+ {{/if}} +
+
+ {{/if}} +
+
\ No newline at end of file diff --git a/ghost/admin/app/components/gh-publishmenu-scheduled.js b/ghost/admin/app/components/gh-publishmenu-scheduled.js index 4bba770315..a4c54a19d6 100644 --- a/ghost/admin/app/components/gh-publishmenu-scheduled.js +++ b/ghost/admin/app/components/gh-publishmenu-scheduled.js @@ -1,74 +1,70 @@ -import Component from '@ember/component'; +import Component from '@glimmer/component'; import moment from 'moment'; -import {computed} from '@ember/object'; +import {action} from '@ember/object'; import {inject as service} from '@ember/service'; +import {tracked} from '@glimmer/tracking'; -export default Component.extend({ - clock: service(), - session: service(), - feature: service(), - settings: service(), - config: service(), - - post: null, - saveType: null, - isClosing: null, +export default class GhPublishmenuScheduledComponent extends Component { + @service clock; + @service session; + @service feature; + @service settings; + @service config; // used to set minDate in datepicker - _minDate: null, + @tracked minDate = null; - 'data-test-publishmenu-scheduled': true, - - timeToPublished: computed('post.publishedAtUTC', 'clock.second', function () { - let publishedAtUTC = this.get('post.publishedAtUTC'); + get timeToPublished() { + let publishedAtUTC = this.args.post.publishedAtUTC; if (!publishedAtUTC) { return null; } - this.get('clock.second'); + this.clock.get('second'); return publishedAtUTC.toNow(true); - }), + } - didInsertElement() { - this.set('_minDate', new Date()); - this.setSaveType('schedule'); - }, + constructor() { + super(...arguments); + this.minDate = new Date(); + } - actions: { - setSaveType(type) { - if (this.saveType !== type) { - this.set('_minDate', new Date()); - this.setSaveType(type); + @action + setSaveType(type) { + if (this.saveType !== type) { + this.minDate = new Date(); + this.args.setSaveType(type); - // when draft switch to now to avoid validation errors - // when schedule switch back to saved date to avoid unnecessary re-scheduling - if (type === 'draft') { - this.post.set('publishedAtBlogTZ', new Date()); - } else { - this.post.set('publishedAtBlogTZ', this.get('post.publishedAtUTC')); - } - - this.post.validate(); + // when draft switch to now to avoid validation errors + // when schedule switch back to saved date to avoid unnecessary re-scheduling + if (type === 'draft') { + this.args.post.set('publishedAtBlogTZ', new Date()); + } else { + this.args.post.set('publishedAtBlogTZ', this.args.post.publishedAtUTC); } - }, - setDate(date) { - let post = this.post; - let dateString = moment(date).format('YYYY-MM-DD'); - - post.set('publishedAtBlogDate', dateString); - return post.validate(); - }, - - setTime(time) { - let post = this.post; - - if (!this.isClosing) { - post.set('publishedAtBlogTime', time); - return post.validate(); - } + this.args.post.validate(); } } -}); + + @action + setDate(date) { + let post = this.args.post; + let dateString = moment(date).format('YYYY-MM-DD'); + + post.set('publishedAtBlogDate', dateString); + return post.validate(); + } + + @action + setTime(time) { + let post = this.args.post; + + if (!this.args.isClosing) { + post.set('publishedAtBlogTime', time); + return post.validate(); + } + } +} diff --git a/ghost/admin/app/components/gh-publishmenu.hbs b/ghost/admin/app/components/gh-publishmenu.hbs index 139f24b304..3b182f8655 100644 --- a/ghost/admin/app/components/gh-publishmenu.hbs +++ b/ghost/admin/app/components/gh-publishmenu.hbs @@ -8,7 +8,8 @@ + @setSaveType={{action "setSaveType"}} + data-test-publishmenu-published="true" /> {{else if (eq this.displayState "scheduled")}} + @sendingEmailLimitError={{this.sendingEmailLimitError}} + data-test-publishmenu-scheduled="true" /> {{else}} + @sendingEmailLimitError={{this.sendingEmailLimitError}} + data-test-publishmenu-draft="true" /> {{/if}} {{!-- @@ -51,7 +53,7 @@ @successText={{this.successText}} @runningText={{this.runningText}} @class="gh-btn gh-btn-black gh-publishmenu-button gh-btn-icon" - data-test-publishmenu-save=true + data-test-publishmenu-save="true" /> diff --git a/ghost/admin/app/components/gh-tags-list-item.hbs b/ghost/admin/app/components/gh-tags-list-item.hbs index 90348b6ceb..cec63e176e 100644 --- a/ghost/admin/app/components/gh-tags-list-item.hbs +++ b/ghost/admin/app/components/gh-tags-list-item.hbs @@ -1,30 +1,32 @@ - -

- {{this.tag.name}} -

- {{#if this.description}} -

- {{this.description}} -

+
  • + +

    + {{@tag.name}} +

    + {{#if @tag.description}} +

    + {{@tag.description}} +

    + {{/if}} +
    + + + {{@slug}} + + + {{#if @tag.count.posts}} + + {{gh-pluralize @tag.count.posts "post"}} + + {{else}} + + {{gh-pluralize @tag.count.posts "post"}} + {{/if}} - - - {{this.slug}} - - -{{#if this.postsCount}} - - {{this.postsLabel}} + +
    + {{svg-jar "arrow-right" class="w6 h6 fill-midgrey pa1"}} +
    -{{else}} - - {{this.postsLabel}} - -{{/if}} - - -
    - {{svg-jar "arrow-right" class="w6 h6 fill-midgrey pa1"}} -
    -
    \ No newline at end of file +
  • \ No newline at end of file diff --git a/ghost/admin/app/components/gh-tags-list-item.js b/ghost/admin/app/components/gh-tags-list-item.js deleted file mode 100644 index 8320f38925..0000000000 --- a/ghost/admin/app/components/gh-tags-list-item.js +++ /dev/null @@ -1,38 +0,0 @@ -import Component from '@ember/component'; -import {alias} from '@ember/object/computed'; -import {computed} from '@ember/object'; -import {inject as service} from '@ember/service'; - -export default Component.extend({ - ghostPaths: service(), - notifications: service(), - router: service(), - - tagName: 'li', - classNames: ['gh-list-row', 'gh-tags-list-item'], - - active: false, - - id: alias('tag.id'), - slug: alias('tag.slug'), - name: alias('tag.name'), - isInternal: alias('tag.isInternal'), - description: alias('tag.description'), - postsCount: alias('tag.count.posts'), - postsLabel: computed('tag.count.posts', function () { - let noOfPosts = this.postsCount || 0; - return (noOfPosts === 1) ? `${noOfPosts} post` : `${noOfPosts} posts`; - }), - - _deleteTag() { - let tag = this.tag; - - return tag.destroyRecord().then(() => {}, (error) => { - this._deleteTagFailure(error); - }); - }, - - _deleteTagFailure(error) { - this.notifications.showAPIError(error, {key: 'tag.delete'}); - } -}); diff --git a/ghost/admin/app/components/gh-task-button.js b/ghost/admin/app/components/gh-task-button.js index dc6dfc7c01..0dcc3a95ce 100644 --- a/ghost/admin/app/components/gh-task-button.js +++ b/ghost/admin/app/components/gh-task-button.js @@ -25,7 +25,7 @@ const GhTaskButton = Component.extend({ 'isSuccessClass', 'isFailureClass' ], - attributeBindings: ['disabled', 'form', 'type', 'tabindex'], + attributeBindings: ['disabled', 'form', 'type', 'tabindex', 'data-test-button'], task: null, taskArgs: undefined, diff --git a/ghost/admin/app/components/modal-theme-warnings.hbs b/ghost/admin/app/components/modal-theme-warnings.hbs index 2c91b5a809..dad848a20a 100644 --- a/ghost/admin/app/components/modal-theme-warnings.hbs +++ b/ghost/admin/app/components/modal-theme-warnings.hbs @@ -1,4 +1,4 @@ -
    +