Added first version of feature image with caption inside editor (#1999)

refs https://github.com/TryGhost/Team/issues/771

- updated `<GhImageUploaderWithPreview>` to take an `@includeMetadata` argument that shows a basic html supporting caption field underneath (ready for toggle between caption/alt but not fully implemented)
- added feature image alt/caption properties to post model
- updated UI behind "featureImageMeta" labs flag
  - added the feature image uploader to the top of `<GhKoenigEditor>` for display above the editor title
  - removed feature image uploader from post settings menu
- added labs flag checkbox
This commit is contained in:
Kevin Ansfield 2021-06-10 20:42:32 +01:00 committed by GitHub
parent 85c6655959
commit ceb16b5e9f
11 changed files with 116 additions and 53 deletions

View File

@ -1,18 +1,33 @@
{{#if this.image}}
{{#if @image}}
<div class="gh-image-uploader -with-image">
<div><img src={{this.image}}></div>
<a class="image-cancel" title="Delete" {{action "remove"}}>
<div><img src={{@image}}></div>
<a class="image-cancel" title="Delete" {{on "click" @remove}}>
{{svg-jar "trash"}}
<span class="hidden">Delete</span>
</a>
</div>
{{else}}
<GhImageUploader
@text={{this.text}}
@altText={{this.altText}}
@allowUnsplash={{this.allowUnsplash}}
@update={{action "update"}}
@uploadStarted={{action "uploadStarted"}}
@uploadFinished={{action "uploadFinished"}}
@text={{@text}}
@altText={{@altText}}
@allowUnsplash={{@allowUnsplash}}
@update={{@update}}
@uploadStarted={{optional @uploadStarted}}
@uploadFinished={{optional @uploadFinished}}
/>
{{/if}}
{{#if @includeMetadata}}
{{#if this.isEditingAlt}}
{{else}}
<KoenigBasicHtmlInput
@html={{@caption}}
@placeholder={{if this.captionInputFocused "" @captionPlaceholder}}
@class="miw-100 tc bn form-text bg-transparent pr8 pl8"
@name="caption"
@onChange={{@updateCaption}}
@onFocus={{fn (mut this.captionInputFocused) true}}
@onBlur={{fn (mut this.captionInputFocused) false}}
/>
{{/if}}
{{/if}}

View File

@ -1,36 +1,7 @@
import Component from '@ember/component';
import Component from '@glimmer/component';
import {tracked} from '@glimmer/tracking';
export default Component.extend({
allowUnsplash: false,
actions: {
update() {
let action = this.update;
if (action) {
action(...arguments);
}
},
uploadStarted() {
let action = this.uploadStarted;
if (action) {
action(...arguments);
}
},
uploadFinished() {
let action = this.uploadFinished;
if (action) {
action(...arguments);
}
},
remove() {
let action = this.remove;
if (action) {
action();
}
}
}
});
export default class GhImageUploaderWithPreviewComponent extends Component {
@tracked isEditingAlt = false;
@tracked captionInputFocused = false;
}

View File

@ -5,6 +5,24 @@
{{on "mousedown" this.trackMousedown}}
{{on "mouseup" this.focusEditor}}
>
{{#if (feature "featureImageMeta")}}
<div class="gh-editor-feature-image">
<GhImageUploaderWithPreview
@image={{@featureImage}}
@text="Upload feature image"
@allowUnsplash={{true}}
@includeMetadata={{true}}
@update={{@setFeatureImage}}
@remove={{fn @setFeatureImage null}}
@alt={{@featureImageAlt}}
@caption={{@featureImageCaption}}
@updateAlt={{@setFeatureImageAlt}}
@updateCaption={{@setFeatureImageCaption}}
@captionPlaceholder="Add a caption to the feature image"
/>
</div>
{{/if}}
<GhTextarea
@class="gh-editor-title"
@placeholder={{@titlePlaceholder}}

View File

@ -8,6 +8,7 @@
</button>
</div>
<div class="settings-menu-content">
{{#unless (feature "featureImageMeta")}}
<GhImageUploaderWithPreview
@image={{this.post.featureImage}}
@text={{concat "Upload " this.post.displayName " image"}}
@ -15,6 +16,7 @@
@update={{action "setCoverImage"}}
@remove={{action "clearCoverImage"}}
/>
{{/unless}}
<form>
<div class="form-group">
<label for="url">{{capitalize this.post.displayName}} URL</label>

View File

@ -305,6 +305,22 @@ export default Controller.extend({
updateWordCount(counts) {
this.set('wordCount', counts);
},
setFeatureImage(url) {
this.post.set('featureImage', url);
},
clearFeatureImage() {
this.post.set('featureImage', null);
},
setFeatureImageAlt(text) {
this.post.set('featureImageAlt', text);
},
setFeatureImageCaption(html) {
this.post.set('featureImageCaption', html);
}
},

View File

@ -79,7 +79,6 @@ export default Model.extend(Comparable, ValidationEngine, {
excerpt: attr('string'),
customExcerpt: attr('string'),
featured: attr('boolean', {defaultValue: false}),
featureImage: attr('string'),
canonicalUrl: attr('string'),
codeinjectionFoot: attr('string', {defaultValue: ''}),
codeinjectionHead: attr('string', {defaultValue: ''}),
@ -107,6 +106,10 @@ export default Model.extend(Comparable, ValidationEngine, {
uuid: attr('string'),
emailRecipientFilter: attr('members-segment-string', {defaultValue: null}),
featureImage: attr('string'),
featureImageAlt: attr('string'),
featureImageCaption: attr('string'),
authors: hasMany('user', {embedded: 'always', async: false}),
createdBy: belongsTo('user', {async: true}),
email: belongsTo('email', {async: false}),

View File

@ -55,6 +55,7 @@ export default Service.extend({
launchComplete: feature('launchComplete', {user: true}),
matchHelper: feature('matchHelper'),
multipleProducts: feature('multipleProducts', {developer: true}),
featureImageMeta: feature('featureImageMeta', {developer: true}),
_user: null,

View File

@ -380,6 +380,16 @@
margin: 0 auto;
}
.gh-editor-feature-image {
display: block;
width: 100%;
max-width: 740px;
min-height: auto;
margin-left: auto;
margin-right: auto;
margin-bottom: 1.6rem;
}
.gh-editor-title {
display: block;
width: 100%;

View File

@ -84,6 +84,12 @@
@snippets={{this.snippets}}
@saveSnippet={{if this.canManageSnippets this.saveSnippet}}
@deleteSnippet={{if this.canManageSnippets this.toggleDeleteSnippetModal}}
@featureImage={{this.post.featureImage}}
@featureImageAlt={{this.post.featureImageAlt}}
@featureImageCaption={{this.post.featureImageCaption}}
@setFeatureImage={{action "setFeatureImage"}}
@setFeatureImageAlt={{action "setFeatureImageAlt"}}
@setFeatureImageCaption={{action "setFeatureImageCaption"}}
/>
<div class="gh-editor-wordcount-container {{if editor.headerClass "small"}}">

View File

@ -267,6 +267,19 @@
</div>
</div>
</div>
<div class="gh-expandable-block">
<div class="gh-expandable-header">
<div>
<h4 class="gh-expandable-title">Feature image redesign with caption support</h4>
<p class="gh-expandable-description">
Moves feature image uploader to top of editor screen and adds alt/caption input.
</p>
</div>
<div class="for-switch">
<GhFeatureFlag @flag="featureImageMeta" />
</div>
</div>
</div>
</div>
</div>
{{/if}}

View File

@ -19,7 +19,8 @@ export default BaseValidator.create({
'twitterDescription',
'publishedAtBlogTime',
'publishedAtBlogDate',
'emailSubject'
'emailSubject',
'featureImageAlt'
],
title(model) {
@ -187,5 +188,12 @@ export default BaseValidator.create({
this.invalidate();
}
}
},
featureImageAlt(model) {
if (!validator.isLength(model.featureImageAlt || '', 0, 125)) {
model.errors.add('featureImageAlt', 'Feature image alt text cannot be longer than 125 characters.');
this.invalidate();
}
}
});