Ghost/ghost/admin/app/components/gh-editor.js
Kevin Ansfield 352c4af1d7 Refactored usage of .get('property') with es5 getters
no issue
- ran [es5-getter-ember-codemod](https://github.com/rondale-sc/es5-getter-ember-codemod)
- [es5 getters RFC](https://github.com/emberjs/rfcs/blob/master/text/0281-es5-getters.md)
- updates the majority of `object.get('property')` with `object.property` with exceptions:
  - `.get('nested.property')` - it's not possible to determine if this is relying on "safe" path chaining for when `nested` doesn't exist
  - `.get('config.x')` and `.get('settings.x')` - both our `config` and `settings` services are proxy objects which do not support es5 getters
- this PR is not exhaustive, there are still a number of places where `.get('service.foo')` and similar could be replaced but it gets us a long way there in a quick and automated fashion
2019-03-06 13:54:14 +00:00

180 lines
5.0 KiB
JavaScript

import Component from '@ember/component';
import {
IMAGE_EXTENSIONS,
IMAGE_MIME_TYPES
} from 'ghost-admin/components/gh-image-uploader';
import {debounce, run} from '@ember/runloop';
import {inject as service} from '@ember/service';
export default Component.extend({
ui: service(),
classNameBindings: [
'isDraggedOver:-drag-over',
'isFullScreen:gh-editor-fullscreen',
'isPreview:gh-editor-preview'
],
// Internal attributes
droppedFiles: null,
headerClass: '',
headerHeight: 0,
imageExtensions: IMAGE_EXTENSIONS,
imageMimeTypes: IMAGE_MIME_TYPES,
isDraggedOver: false,
isFullScreen: false,
isSplitScreen: false,
uploadedImageUrls: null,
// Private
_dragCounter: 0,
_onResizeHandler: null,
_viewActionsWidth: 190,
init() {
this._super(...arguments);
this._onResizeHandler = (evt) => {
debounce(this, this._setHeaderClass, evt, 100);
};
},
didInsertElement() {
this._super(...arguments);
window.addEventListener('resize', this._onResizeHandler);
this._setHeaderClass();
},
willDestroyElement() {
this._super(...arguments);
window.removeEventListener('resize', this._onResizeHandler);
},
actions: {
toggleFullScreen(isFullScreen) {
this.set('isFullScreen', isFullScreen);
this.ui.set('isFullScreen', isFullScreen);
run.scheduleOnce('afterRender', this, this._setHeaderClass);
},
togglePreview(isPreview) {
this.set('isPreview', isPreview);
},
toggleSplitScreen(isSplitScreen) {
this.set('isSplitScreen', isSplitScreen);
run.scheduleOnce('afterRender', this, this._setHeaderClass);
},
uploadImages(fileList, resetInput) {
// convert FileList to an array so that resetting the input doesn't
// clear the file references before upload actions can be triggered
let files = Array.from(fileList);
this.set('droppedFiles', files);
resetInput();
},
uploadComplete(uploads) {
this.set('uploadedImageUrls', uploads.mapBy('url'));
this.set('droppedFiles', null);
},
uploadCancelled() {
this.set('droppedFiles', null);
}
},
_setHeaderClass() {
let editorTitle = this.element.querySelector('.gh-editor-title, .kg-title-input');
let smallHeaderClass = 'gh-editor-header-small';
let newHeaderClass = '';
this._editorTitleElement = editorTitle;
if (this.isSplitScreen) {
this.set('headerClass', smallHeaderClass);
return;
}
if (editorTitle) {
let boundingRect = editorTitle.getBoundingClientRect();
let maxRight = window.innerWidth - this._viewActionsWidth;
if (boundingRect.right >= maxRight) {
newHeaderClass = smallHeaderClass;
}
}
if (newHeaderClass !== this.headerClass) {
// grab height of header so that we can pass it as an offset to other
// editor components
run.scheduleOnce('afterRender', this, this._setHeaderHeight);
}
this.set('headerClass', newHeaderClass);
},
_setHeaderHeight() {
if (this.headerClass && this._editorTitleElement) {
let height = this._editorTitleElement.offsetHeight;
return this.set('headerHeight', height);
}
this.set('headerHeight', 0);
},
// dragOver is needed so that drop works
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.preventDefault();
event.stopPropagation();
},
// dragEnter is needed so that the drag class is correctly removed
dragEnter(event) {
if (!event.dataTransfer) {
return;
}
event.preventDefault();
event.stopPropagation();
// the counter technique prevents flickering of the drag class when
// dragging across child elements
this._dragCounter += 1;
this.set('isDraggedOver', true);
},
dragLeave(event) {
event.preventDefault();
event.stopPropagation();
this._dragCounter -= 1;
if (this._dragCounter === 0) {
this.set('isDraggedOver', false);
}
},
drop(event) {
event.preventDefault();
event.stopPropagation();
this._dragCounter = 0;
this.set('isDraggedOver', false);
if (event.dataTransfer.files) {
this.set('droppedFiles', event.dataTransfer.files);
}
}
});