mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-11-28 22:43:30 +03:00
bd27295ede
refs https://github.com/TryGhost/Ghost/issues/9623 - do not process drop in `{{koenig-editor}}` if the drop happened on a card and the card's `handlesDragDrop` property is true - allow `dragover` events on cards to bubble up to Ember's event handler in `{{koenig-editor}}` - handle drag/drop in `{{koenig-card-image}}` - show different overlays when dragging files over the card to indicate an upload or replace action - start upload when a file is dropped on the card
212 lines
5.8 KiB
JavaScript
212 lines
5.8 KiB
JavaScript
import $ from 'jquery';
|
|
import Component from '@ember/component';
|
|
import layout from '../templates/components/koenig-card-image';
|
|
import {
|
|
IMAGE_EXTENSIONS,
|
|
IMAGE_MIME_TYPES
|
|
} from 'ghost-admin/components/gh-image-uploader';
|
|
import {computed, set} from '@ember/object';
|
|
import {htmlSafe} from '@ember/string';
|
|
import {isEmpty} from '@ember/utils';
|
|
import {run} from '@ember/runloop';
|
|
import {inject as service} from '@ember/service';
|
|
|
|
export default Component.extend({
|
|
ui: service(),
|
|
layout,
|
|
|
|
// attrs
|
|
files: null,
|
|
payload: null,
|
|
isSelected: false,
|
|
isEditing: false,
|
|
imageExtensions: IMAGE_EXTENSIONS,
|
|
imageMimeTypes: IMAGE_MIME_TYPES,
|
|
|
|
// properties
|
|
handlesDragDrop: true,
|
|
|
|
// closure actions
|
|
selectCard() {},
|
|
deselectCard() {},
|
|
editCard() {},
|
|
saveCard() {},
|
|
moveCursorToNextSection() {},
|
|
moveCursorToPrevSection() {},
|
|
addParagraphAfterCard() {},
|
|
|
|
kgImgStyle: computed('payload.imageStyle', function () {
|
|
let imageStyle = this.payload.imageStyle;
|
|
|
|
if (imageStyle === 'wide') {
|
|
return 'image-wide';
|
|
}
|
|
|
|
if (imageStyle === 'full') {
|
|
return 'image-full';
|
|
}
|
|
|
|
return 'image-normal';
|
|
}),
|
|
|
|
toolbar: computed('payload.{imageStyle,src}', function () {
|
|
let imageStyle = this.payload.imageStyle;
|
|
let items = [];
|
|
|
|
if (this.payload.src) {
|
|
items.push({
|
|
title: 'Regular',
|
|
icon: 'koenig/kg-img-regular',
|
|
iconClass: `${!imageStyle ? 'stroke-blue-l2' : 'stroke-white'}`,
|
|
action: run.bind(this, this._changeImageStyle, '')
|
|
});
|
|
|
|
items.push({
|
|
title: 'Wide',
|
|
icon: 'koenig/kg-img-wide',
|
|
iconClass: `${imageStyle === 'wide' ? 'stroke-blue-l2' : 'stroke-white'}`,
|
|
action: run.bind(this, this._changeImageStyle, 'wide')
|
|
});
|
|
|
|
items.push({
|
|
title: 'Full',
|
|
icon: 'koenig/kg-img-full',
|
|
iconClass: `${imageStyle === 'full' ? 'stroke-blue-l2' : 'stroke-white'}`,
|
|
action: run.bind(this, this._changeImageStyle, 'full')
|
|
});
|
|
|
|
items.push({divider: true});
|
|
|
|
items.push({
|
|
title: 'Replace image',
|
|
icon: 'koenig/kg-replace',
|
|
iconClass: '',
|
|
action: run.bind(this, this._triggerFileDialog)
|
|
});
|
|
}
|
|
|
|
if (items.length > 0) {
|
|
return {items};
|
|
}
|
|
}),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
if (!this.payload) {
|
|
this.set('payload', {});
|
|
}
|
|
},
|
|
|
|
didReceiveAttrs() {
|
|
this._super(...arguments);
|
|
|
|
// `payload.files` can be set if we have an externaly set image that
|
|
// should be uploaded. Typical example would be from a paste or drag/drop
|
|
if (!isEmpty(this.payload.files)) {
|
|
run.schedule('afterRender', this, function () {
|
|
this.set('files', this.payload.files);
|
|
|
|
// we don't want to persist any file data in the document
|
|
delete this.payload.files;
|
|
});
|
|
}
|
|
},
|
|
|
|
actions: {
|
|
updateSrc(images) {
|
|
let [image] = images;
|
|
this._updatePayloadAttr('src', image.url);
|
|
},
|
|
|
|
updateCaption(caption) {
|
|
this._updatePayloadAttr('caption', caption);
|
|
},
|
|
|
|
/**
|
|
* Opens a file selection dialog - Triggered by "Upload Image" buttons,
|
|
* searches for the hidden file input within the .gh-setting element
|
|
* containing the clicked button then simulates a click
|
|
* @param {MouseEvent} event - MouseEvent fired by the button click
|
|
*/
|
|
triggerFileDialog(event) {
|
|
this._triggerFileDialog(event);
|
|
},
|
|
|
|
setPreviewSrc(files) {
|
|
let file = files[0];
|
|
if (file) {
|
|
let reader = new FileReader();
|
|
|
|
reader.onload = (e) => {
|
|
this.set('previewSrc', htmlSafe(e.target.result));
|
|
};
|
|
|
|
reader.readAsDataURL(file);
|
|
}
|
|
},
|
|
|
|
resetSrcs() {
|
|
this.set('previewSrc', null);
|
|
this._updatePayloadAttr('src', null);
|
|
}
|
|
},
|
|
|
|
dragOver(event) {
|
|
if (!event.dataTransfer) {
|
|
return;
|
|
}
|
|
|
|
// this is needed to work around inconsistencies with dropping files
|
|
// from Chrome's downloads bar
|
|
if (navigator.userAgent.indexOf('Chrome') > -1) {
|
|
let eA = event.dataTransfer.effectAllowed;
|
|
event.dataTransfer.dropEffect = (eA === 'move' || eA === 'linkMove') ? 'move' : 'copy';
|
|
}
|
|
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
|
|
this.set('isDraggedOver', true);
|
|
},
|
|
|
|
dragLeave(event) {
|
|
event.preventDefault();
|
|
this.set('isDraggedOver', false);
|
|
},
|
|
|
|
drop(event) {
|
|
event.preventDefault();
|
|
this.set('isDraggedOver', false);
|
|
|
|
if (event.dataTransfer.files) {
|
|
this.set('files', [event.dataTransfer.files[0]]);
|
|
}
|
|
},
|
|
|
|
_changeImageStyle(imageStyle) {
|
|
this._updatePayloadAttr('imageStyle', imageStyle);
|
|
},
|
|
|
|
_updatePayloadAttr(attr, value) {
|
|
let payload = this.payload;
|
|
let save = this.saveCard;
|
|
|
|
set(payload, attr, value);
|
|
|
|
// update the mobiledoc and stay in edit mode
|
|
save(payload, false);
|
|
},
|
|
|
|
_triggerFileDialog(event) {
|
|
let target = event && event.target || this.element;
|
|
|
|
// simulate click to open file dialog
|
|
// using jQuery because IE11 doesn't support MouseEvent
|
|
$(target)
|
|
.closest('.__mobiledoc-card')
|
|
.find('input[type="file"]')
|
|
.click();
|
|
}
|
|
});
|