mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-21 09:52:06 +03:00
8fee5f155b
no issue - we had a mix of legacy jQuery triggers and native triggers for file input clicks and jQuery hasn't been required to do this in our target browsers for quite a long time now so it made sense to update all click triggers to avoid old patterns being replicated - cleaned up some conditionals with optional-chaining - removed use of `run.bind(this)` for methods that use `@action` because the binding is already handled for us
211 lines
5.6 KiB
JavaScript
211 lines
5.6 KiB
JavaScript
import Component from '@glimmer/component';
|
|
import {
|
|
IMAGE_EXTENSIONS,
|
|
IMAGE_MIME_TYPES
|
|
} from 'ghost-admin/components/gh-image-uploader';
|
|
import {action} from '@ember/object';
|
|
import {run} from '@ember/runloop';
|
|
import {tracked} from '@glimmer/tracking';
|
|
|
|
export default class KoenigCardBeforeAfterComponent extends Component {
|
|
@tracked imageWidth;
|
|
files = null;
|
|
selectingFile = false;
|
|
imageMimeTypes = IMAGE_MIME_TYPES;
|
|
imageExtensions = IMAGE_EXTENSIONS;
|
|
|
|
get isPopulated() {
|
|
return this.args.payload.beforeImage && this.args.payload.afterImage;
|
|
}
|
|
|
|
get overlayStyle() {
|
|
return `width: ${this.args.payload.startingPosition}%`;
|
|
}
|
|
|
|
get toolbar() {
|
|
let cardWidth = this.args.payload.cardWidth;
|
|
|
|
return {
|
|
items: [{
|
|
title: 'Wide',
|
|
icon: 'koenig/kg-img-wide',
|
|
iconClass: cardWidth === 'wide' ? 'fill-green-l2' : 'fill-white',
|
|
action: run.bind(this, this.setLayoutWide)
|
|
}, {
|
|
title: 'Full',
|
|
icon: 'koenig/kg-img-full',
|
|
iconClass: cardWidth === 'full' ? 'fill-green-l2' : 'fill-white',
|
|
action: run.bind(this, this.setLayoutFull)
|
|
}, {
|
|
divider: true
|
|
}]
|
|
};
|
|
}
|
|
|
|
updateImageDimensions() {
|
|
let beforeImage = this.args.payload.beforeImage;
|
|
let afterImage = this.args.payload.afterImage;
|
|
|
|
let smallestImageWidth = Math.min(
|
|
beforeImage ? beforeImage.width : Infinity,
|
|
afterImage ? afterImage.width : Infinity
|
|
);
|
|
|
|
try {
|
|
this.imageWidth = Math.min(
|
|
smallestImageWidth,
|
|
parseInt(getComputedStyle(this.element).getPropertyValue('width'))
|
|
);
|
|
} catch (err) {
|
|
this.imageWidth = Math.min(
|
|
smallestImageWidth,
|
|
0
|
|
);
|
|
}
|
|
}
|
|
|
|
constructor(owner, args) {
|
|
super(owner, args);
|
|
args.registerComponent(this);
|
|
|
|
let placeholders = ['summer', 'mountains', 'ufo-attack'];
|
|
this.placeholder = placeholders[Math.floor(Math.random() * placeholders.length)];
|
|
if (!args.payload.cardWidth) {
|
|
args.payload.cardWidth = 'wide';
|
|
}
|
|
if (!args.payload.startingPosition) {
|
|
args.payload.startingPosition = 50;
|
|
}
|
|
if (!args.payload.caption) {
|
|
args.payload.caption = null;
|
|
}
|
|
}
|
|
|
|
setupListeners() {
|
|
this.updateImageDimensions();
|
|
const handleResize = () => {
|
|
this.updateImageDimensions();
|
|
};
|
|
window.addEventListener('resize', handleResize);
|
|
this.willDestroy = () => {
|
|
window.removeEventListener('resize', handleResize);
|
|
};
|
|
}
|
|
|
|
@action
|
|
preventDefault(e) {
|
|
e.preventDefault();
|
|
}
|
|
|
|
@action
|
|
stopPropagation(e) {
|
|
e.stopPropagation();
|
|
}
|
|
|
|
@action
|
|
removeFocus(e) {
|
|
e.target.blur();
|
|
}
|
|
|
|
// required for snippet rects to be calculated - editor reaches in to component,
|
|
// expecting a non-Glimmer component with a .element property
|
|
@action
|
|
registerElement(element) {
|
|
this.element = element;
|
|
this.setupListeners();
|
|
}
|
|
|
|
@action
|
|
uploadStart(file) {
|
|
return new Promise((resolve) => {
|
|
let objectURL = URL.createObjectURL(file);
|
|
let image = new Image();
|
|
image.addEventListener('load', () => {
|
|
let id = this.selectingFile;
|
|
this.selectingFile = false;
|
|
let metadata = {
|
|
id: id
|
|
};
|
|
resolve(metadata);
|
|
});
|
|
image.src = objectURL;
|
|
});
|
|
}
|
|
|
|
@action
|
|
uploadSuccess(file, metadata) {
|
|
let image = new Image();
|
|
image.addEventListener('load', () => {
|
|
let imageData = {
|
|
src: file.url,
|
|
width: image.naturalWidth,
|
|
height: image.naturalHeight
|
|
};
|
|
let prop = `${metadata.id}Image`;
|
|
this.args.payload[prop] = imageData;
|
|
this.updateImageDimensions();
|
|
});
|
|
image.src = file.url;
|
|
}
|
|
|
|
@action
|
|
setLayoutWide() {
|
|
this.args.payload.cardWidth = 'wide';
|
|
run.scheduleOnce('afterRender', this, this.updateImageDimensions);
|
|
}
|
|
|
|
@action
|
|
setLayoutFull() {
|
|
this.args.payload.cardWidth = 'full';
|
|
run.scheduleOnce('afterRender', this, this.updateImageDimensions);
|
|
}
|
|
|
|
@action
|
|
setStartingPosition(event) {
|
|
this.args.payload.startingPosition = Math.min(100, Math.max(0, parseInt(event.target.value)));
|
|
}
|
|
|
|
@action
|
|
selectBeforeImage() {
|
|
this.selectingFile = 'before';
|
|
this._triggerFileDialog();
|
|
}
|
|
|
|
@action
|
|
selectAfterImage() {
|
|
this.selectingFile = 'after';
|
|
this._triggerFileDialog();
|
|
}
|
|
|
|
_triggerFileDialog(event) {
|
|
const target = event?.target || this.element;
|
|
|
|
const cardElem = target.closest('.__mobiledoc-card');
|
|
const fileInput = cardElem?.querySelector('input[type="file"]');
|
|
|
|
fileInput?.click();
|
|
}
|
|
|
|
@action
|
|
uploadFailed() {
|
|
}
|
|
|
|
@action
|
|
handleErrors() {
|
|
}
|
|
|
|
@action
|
|
setCaption(caption) {
|
|
this.args.payload.caption = caption;
|
|
}
|
|
|
|
@action
|
|
leaveEditMode() {
|
|
if (this.isEmpty) {
|
|
// afterRender is required to avoid double modification of `isSelected`
|
|
// TODO: see if there's a way to avoid afterRender
|
|
run.scheduleOnce('afterRender', this, this.args.deleteCard);
|
|
}
|
|
}
|
|
}
|