🎨 Moved default focus in editor from body to title for new posts
refs https://github.com/TryGhost/Team/issues/707 Placing focus in the title aligns better with typical editorial process. - switched `autofocus` attribute from body to title for new posts - added a default value to the `mobiledoc` attr on the Post model, without it the autosave when moving from title to editor creates a forced re-render and clears the focus whilst you're typing
This commit is contained in:
parent
bb825dfa13
commit
65ed9cc69c
|
@ -26,6 +26,7 @@
|
|||
<GhTextarea
|
||||
@class="gh-editor-title"
|
||||
@placeholder={{@titlePlaceholder}}
|
||||
@shouldFocus={{or @titleAutofocus false}}
|
||||
@tabindex="1"
|
||||
@autoExpand=".gh-koenig-editor"
|
||||
@value={{readonly this.title}}
|
||||
|
@ -39,7 +40,6 @@
|
|||
<KoenigEditor
|
||||
@mobiledoc={{@body}}
|
||||
@placeholder={{@bodyPlaceholder}}
|
||||
@autofocus={{or @bodyAutofocus false}}
|
||||
@spellcheck={{true}}
|
||||
@onChange={{@onBodyChange}}
|
||||
@didCreateEditor={{this.onEditorCreated}}
|
||||
|
|
|
@ -97,7 +97,7 @@ export default Controller.extend({
|
|||
/* public properties -----------------------------------------------------*/
|
||||
|
||||
leaveEditorTransition: null,
|
||||
shouldFocusEditor: false,
|
||||
shouldFocusTitle: false,
|
||||
showDeletePostModal: false,
|
||||
showLeaveEditorModal: false,
|
||||
showReAuthenticateModal: false,
|
||||
|
@ -436,7 +436,7 @@ export default Controller.extend({
|
|||
this.set('post.emailSubject', this.get('post.emailSubjectScratch'));
|
||||
|
||||
if (!this.get('post.slug')) {
|
||||
this.saveTitle.cancelAll();
|
||||
this.saveTitleTask.cancelAll();
|
||||
|
||||
yield this.generateSlug.perform();
|
||||
}
|
||||
|
@ -595,12 +595,12 @@ export default Controller.extend({
|
|||
return post;
|
||||
}),
|
||||
|
||||
saveTitle: task(function* () {
|
||||
saveTitleTask: task(function* () {
|
||||
let post = this.post;
|
||||
let currentTitle = post.get('title');
|
||||
let newTitle = post.get('titleScratch').trim();
|
||||
|
||||
if (currentTitle && newTitle && newTitle === currentTitle) {
|
||||
if ((currentTitle && newTitle && newTitle === currentTitle) || (!currentTitle && !newTitle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -662,8 +662,7 @@ export default Controller.extend({
|
|||
setPost(post) {
|
||||
// don't do anything else if we're setting the same post
|
||||
if (post === this.post) {
|
||||
// set autofocus as change signal to the persistent editor on new->edit
|
||||
this.set('shouldFocusEditor', post.get('isNew'));
|
||||
this.set('shouldFocusTitle', post.get('isNew'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -673,8 +672,8 @@ export default Controller.extend({
|
|||
this.set('post', post);
|
||||
this.backgroundLoader.perform();
|
||||
|
||||
// autofocus the editor if we have a new post
|
||||
this.set('shouldFocusEditor', post.get('isNew'));
|
||||
// autofocus the title if we have a new post
|
||||
this.set('shouldFocusTitle', post.get('isNew'));
|
||||
|
||||
// need to set scratch values because they won't be present on first
|
||||
// edit of the post
|
||||
|
@ -770,7 +769,7 @@ export default Controller.extend({
|
|||
|
||||
this.set('post', null);
|
||||
this.set('hasDirtyAttributes', false);
|
||||
this.set('shouldFocusEditor', false);
|
||||
this.set('shouldFocusTitle', false);
|
||||
this.set('leaveEditorTransition', null);
|
||||
this.set('showLeaveEditorModal', false);
|
||||
this.set('showPostPreviewModal', false);
|
||||
|
|
|
@ -5,6 +5,7 @@ import boundOneWay from 'ghost-admin/utils/bound-one-way';
|
|||
import moment from 'moment';
|
||||
import {compare} from '@ember/utils';
|
||||
// eslint-disable-next-line ghost/ember/no-observers
|
||||
import {BLANK_DOC} from 'koenig-editor/components/koenig-editor';
|
||||
import {computed, observer} from '@ember/object';
|
||||
import {equal, filterBy, reads} from '@ember/object/computed';
|
||||
import {isBlank} from '@ember/utils';
|
||||
|
@ -94,7 +95,7 @@ export default Model.extend(Comparable, ValidationEngine, {
|
|||
visibility: attr('string'),
|
||||
metaDescription: attr('string'),
|
||||
metaTitle: attr('string'),
|
||||
mobiledoc: attr('json-string'),
|
||||
mobiledoc: attr('json-string', {defaultValue: () => JSON.parse(JSON.stringify(BLANK_DOC))}),
|
||||
plaintext: attr('string'),
|
||||
publishedAtUTC: attr('moment-utc'),
|
||||
slug: attr('string'),
|
||||
|
|
|
@ -68,12 +68,12 @@
|
|||
--}}
|
||||
<GhKoenigEditor
|
||||
@title={{readonly this.post.titleScratch}}
|
||||
@titleAutofocus={{this.shouldFocusTitle}}
|
||||
@titlePlaceholder={{concat (capitalize this.post.displayName) " Title"}}
|
||||
@onTitleChange={{action "updateTitleScratch"}}
|
||||
@onTitleBlur={{action (perform this.saveTitle)}}
|
||||
@onTitleBlur={{action (perform this.saveTitleTask)}}
|
||||
@body={{readonly this.post.scratch}}
|
||||
@bodyPlaceholder={{concat "Begin writing your " this.post.displayName "..."}}
|
||||
@bodyAutofocus={{this.shouldFocusEditor}}
|
||||
@onBodyChange={{action "updateScratch"}}
|
||||
@headerOffset={{editor.headerHeight}}
|
||||
@scrollContainerSelector=".gh-koenig-editor"
|
||||
|
|
|
@ -574,35 +574,6 @@ describe('Acceptance: Editor', function () {
|
|||
expect(savedAuthors[1].name).to.equal('Waldo');
|
||||
});
|
||||
|
||||
it('autosaves when title loses focus', async function () {
|
||||
let role = this.server.create('role', {name: 'Administrator'});
|
||||
this.server.create('user', {name: 'Admin', roles: [role]});
|
||||
|
||||
await visit('/editor');
|
||||
|
||||
// NOTE: there were checks here for the title element having focus
|
||||
// but they were very temperamental whilst running tests in the
|
||||
// browser so they've been left out for now
|
||||
|
||||
expect(
|
||||
currentURL(),
|
||||
'url on initial visit'
|
||||
).to.equal('/editor/post');
|
||||
|
||||
await click('[data-test-editor-title-input]');
|
||||
await blur('[data-test-editor-title-input]');
|
||||
|
||||
expect(
|
||||
find('[data-test-editor-title-input]').value,
|
||||
'title value after autosave'
|
||||
).to.equal('');
|
||||
|
||||
expect(
|
||||
currentURL(),
|
||||
'url after autosave'
|
||||
).to.equal('/editor/post/1');
|
||||
});
|
||||
|
||||
it('saves post settings fields', async function () {
|
||||
let post = this.server.create('post', {authors: [author]});
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ describe('Unit: Controller: editor', function () {
|
|||
});
|
||||
});
|
||||
|
||||
describe('saveTitle', function () {
|
||||
describe('saveTitleTask', function () {
|
||||
beforeEach(function () {
|
||||
this.controller = this.owner.lookup('controller:editor');
|
||||
this.controller.set('target', {send() {}});
|
||||
|
@ -70,7 +70,7 @@ describe('Unit: Controller: editor', function () {
|
|||
expect(controller.get('post.titleScratch')).to.not.be.ok;
|
||||
|
||||
controller.set('post.titleScratch', 'test');
|
||||
await controller.get('saveTitle').perform();
|
||||
await controller.get('saveTitleTask').perform();
|
||||
|
||||
expect(controller.get('post.titleScratch')).to.equal('test');
|
||||
expect(controller.get('post.slug')).to.equal('test-slug');
|
||||
|
@ -91,7 +91,7 @@ describe('Unit: Controller: editor', function () {
|
|||
|
||||
controller.set('post.titleScratch', 'New Title');
|
||||
|
||||
await controller.get('saveTitle').perform();
|
||||
await controller.get('saveTitleTask').perform();
|
||||
|
||||
expect(controller.get('post.titleScratch')).to.equal('New Title');
|
||||
expect(controller.get('post.slug')).to.equal('test-slug');
|
||||
|
@ -115,7 +115,7 @@ describe('Unit: Controller: editor', function () {
|
|||
expect(controller.get('post.titleScratch')).to.not.be.ok;
|
||||
|
||||
controller.set('post.titleScratch', 'test');
|
||||
await controller.get('saveTitle').perform();
|
||||
await controller.get('saveTitleTask').perform();
|
||||
|
||||
expect(controller.get('post.titleScratch')).to.equal('test');
|
||||
expect(controller.get('post.slug')).to.not.be.ok;
|
||||
|
@ -135,7 +135,7 @@ describe('Unit: Controller: editor', function () {
|
|||
expect(controller.get('post.title')).to.not.be.ok;
|
||||
|
||||
controller.set('post.titleScratch', 'title');
|
||||
await controller.get('saveTitle').perform();
|
||||
await controller.get('saveTitleTask').perform();
|
||||
|
||||
expect(controller.get('post.titleScratch')).to.equal('title');
|
||||
expect(controller.get('post.slug')).to.not.be.ok;
|
||||
|
|
Loading…
Reference in New Issue