mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-26 04:13:30 +03:00
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:
parent
85c6655959
commit
ceb16b5e9f
@ -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}}
|
@ -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;
|
||||
}
|
||||
|
@ -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}}
|
||||
|
@ -8,13 +8,15 @@
|
||||
</button>
|
||||
</div>
|
||||
<div class="settings-menu-content">
|
||||
<GhImageUploaderWithPreview
|
||||
@image={{this.post.featureImage}}
|
||||
@text={{concat "Upload " this.post.displayName " image"}}
|
||||
@allowUnsplash={{true}}
|
||||
@update={{action "setCoverImage"}}
|
||||
@remove={{action "clearCoverImage"}}
|
||||
/>
|
||||
{{#unless (feature "featureImageMeta")}}
|
||||
<GhImageUploaderWithPreview
|
||||
@image={{this.post.featureImage}}
|
||||
@text={{concat "Upload " this.post.displayName " image"}}
|
||||
@allowUnsplash={{true}}
|
||||
@update={{action "setCoverImage"}}
|
||||
@remove={{action "clearCoverImage"}}
|
||||
/>
|
||||
{{/unless}}
|
||||
<form>
|
||||
<div class="form-group">
|
||||
<label for="url">{{capitalize this.post.displayName}} URL</label>
|
||||
|
@ -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);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -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}),
|
||||
|
@ -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,
|
||||
|
||||
|
@ -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%;
|
||||
|
@ -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"}}">
|
||||
|
@ -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}}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user