Skip to content

Commit

Permalink
merge 3.3.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ololoken committed Jan 13, 2020
2 parents 446a6ed + dd66c0f commit af37156
Show file tree
Hide file tree
Showing 43 changed files with 1,569 additions and 1,270 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
dist: xenial
language: node_js
node_js:
- '10'
- '12'
cache: yarn
env:
global:
Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2013-2019 Ghost Foundation
Copyright (c) 2013-2020 Ghost Foundation

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ Bugs and issues (even if they only affect the admin client) should be opened on

# Copyright & License

Copyright (c) 2013-2019 Ghost Foundation - Released under the [MIT license](LICENSE). Ghost and the Ghost Logo are trademarks of Ghost Foundation Ltd. Please see our [trademark policy](https://ghost.org/trademark/) for info on acceptable usage.
Copyright (c) 2013-2020 Ghost Foundation - Released under the [MIT license](LICENSE). Ghost and the Ghost Logo are trademarks of Ghost Foundation Ltd. Please see our [trademark policy](https://ghost.org/trademark/) for info on acceptable usage.
4 changes: 0 additions & 4 deletions app/adapters/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,6 @@ export default RESTAdapter.extend(DataAdapterMixin, AjaxServiceSupport, {
return false;
},

authorize(/*xhr*/) {
// noop - we're using server-side session cookies
},

query(store, type, query) {
let id;

Expand Down
2 changes: 1 addition & 1 deletion app/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import 'ghost-admin/utils/link-component';
import 'ghost-admin/utils/route';
import Application from '@ember/application';
import Resolver from './resolver';
import Resolver from 'ember-resolver';
import config from './config/environment';
import loadInitializers from 'ember-load-initializers';
import {registerWarnHandler} from '@ember/debug';
Expand Down
2 changes: 1 addition & 1 deletion app/components/gh-activating-list-item.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,6 @@ export default Component.extend({
},

click() {
this.$('a').blur();
this.element.querySelector('a').blur();
}
});
145 changes: 138 additions & 7 deletions app/components/gh-date-time-picker.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,56 @@
import Component from '@ember/component';
import moment from 'moment';
import {computed} from '@ember/object';
import {action, computed} from '@ember/object';
import {isBlank, isEmpty} from '@ember/utils';
import {or, reads} from '@ember/object/computed';
import {inject as service} from '@ember/service';

const DATE_FORMAT = 'YYYY-MM-DD';

export default Component.extend({
settings: service(),

tagName: '',

date: '',
dateFormat: DATE_FORMAT,
time: '',
errors: null,
dateErrorProperty: null,
timeErrorProperty: null,
isActive: true,

_time: '',
_previousTime: '',
_minDate: null,
_maxDate: null,
_scratchDate: null,
_scratchDateError: null,

// actions
setTypedDateError() {},

blogTimezone: reads('settings.activeTimezone'),
hasError: or('dateError', 'timeError'),

dateValue: computed('_date', '_scratchDate', function () {
if (this._scratchDate !== null) {
return this._scratchDate;
} else {
return moment(this._date).format(DATE_FORMAT);
}
}),

timezone: computed('blogTimezone', function () {
let blogTimezone = this.blogTimezone;
return moment.utc().tz(blogTimezone).format('z');
}),

dateError: computed('errors.[]', 'dateErrorProperty', function () {
dateError: computed('errors.[]', 'dateErrorProperty', '_scratchDateError', function () {
if (this._scratchDateError) {
return this._scratchDateError;
}

let errors = this.errors;
let property = this.dateErrorProperty;

Expand Down Expand Up @@ -64,31 +85,48 @@ export default Component.extend({
this.set('_date', moment().tz(blogTimezone));
}

// reset scratch date if the component becomes inactive
// (eg, PSM is closed, or save type is changed away from scheduled)
if (!this.isActive && this._lastIsActive) {
this._resetScratchDate();
}
this._lastIsActive = this.isActive;

// reset scratch date if date is changed externally
if ((date && date.valueOf()) !== (this._lastDate && this._lastDate.valueOf())) {
this._resetScratchDate();
}
this._lastDate = this.date;

if (isBlank(time)) {
this.set('_time', this._date.format('HH:mm'));
this.set('_time', moment(this._date).format('HH:mm'));
} else {
this.set('_time', this.time);
}
this.set('_previousTime', this._time);

// unless min/max date is at midnight moment will diable that day
if (minDate === 'now') {
this.set('_minDate', moment(moment().format('YYYY-MM-DD')));
this.set('_minDate', moment(moment().format(DATE_FORMAT)));
} else if (!isBlank(minDate)) {
this.set('_minDate', moment(moment(minDate).format('YYYY-MM-DD')));
this.set('_minDate', moment(moment(minDate).format(DATE_FORMAT)));
} else {
this.set('_minDate', null);
}

if (maxDate === 'now') {
this.set('_maxDate', moment(moment().format('YYYY-MM-DD')));
this.set('_maxDate', moment(moment().format(DATE_FORMAT)));
} else if (!isBlank(maxDate)) {
this.set('_maxDate', moment(moment(maxDate).format('YYYY-MM-DD')));
this.set('_maxDate', moment(moment(maxDate).format(DATE_FORMAT)));
} else {
this.set('_maxDate', null);
}
},

willDestroyElement() {
this.setTypedDateError(null);
},

actions: {
// if date or time is set and the other property is blank set that too
// so that we don't get "can't be blank" errors
Expand Down Expand Up @@ -116,5 +154,98 @@ export default Component.extend({
}
}
}
},

registerTimeInput: action(function (elem) {
this._timeInputElem = elem;
}),

onDateInput: action(function (datepicker, event) {
datepicker.actions.close();
this.set('_scratchDate', event.target.value);
}),

onDateBlur: action(function (event) {
// make sure we're not doing anything just because the calendar dropdown
// is opened and clicked
if (event.target.value === moment(this._date).format('YYYY-MM-DD')) {
this._resetScratchDate();
return;
}

if (!event.target.value) {
this._resetScratchDate();
} else {
this._setDate(event.target.value);
}
}),

onDateKeydown: action(function (datepicker, event) {
if (event.key === 'Escape') {
this._resetScratchDate();
}

if (event.key === 'Enter') {
this._setDate(event.target.value);
event.preventDefault();
event.stopImmediatePropagation();
datepicker.actions.close();
}

// close the dropdown and manually focus the time input if necessary
// so that keyboard focus behaves as expected
if (event.key === 'Tab' && datepicker.isOpen) {
datepicker.actions.close();

// manual focus is required because the dropdown is rendered in place
// and the default browser behaviour will move focus to the dropdown
// which is then removed from the DOM making it look like focus has
// disappeared. Shift+Tab is fine because the DOM is not changing in
// that direction
if (!event.shiftKey && this._timeInputElem) {
event.preventDefault();
this._timeInputElem.focus();
this._timeInputElem.select();
}
}

// capture a Ctrl/Cmd+S combo to make sure that the model value is updated
// before the save occurs or we abort the save if the value is invalid
if (event.key === 's' && (event.ctrlKey || event.metaKey)) {
let wasValid = this._setDate(event.target.value);
if (!wasValid) {
event.stopImmediatePropagation();
event.preventDefault();
}
}
}),

// internal methods

_resetScratchDate() {
this.set('_scratchDate', null);
this._setScratchDateError(null);
},

_setDate(dateStr) {
if (!dateStr.match(/^\d\d\d\d-\d\d-\d\d$/)) {
this._setScratchDateError('Invalid date format, must be YYYY-MM-DD');
return false;
}

let date = moment(dateStr, DATE_FORMAT);
if (!date.isValid()) {
this._setScratchDateError('Invalid date');
return false;
}

this.send('setDate', date.toDate());
this._resetScratchDate();
return true;
},

_setScratchDateError(error) {
this.set('_scratchDateError', error);
this.setTypedDateError(error);
}
});
28 changes: 13 additions & 15 deletions app/components/gh-dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,21 +25,30 @@ export default Component.extend(DropdownMixin, {
}),

didInsertElement() {
let dropdownService = this.dropdown;

this._super(...arguments);

let dropdownService = this.dropdown;
dropdownService.on('close', this, this.close);
dropdownService.on('toggle', this, this.toggle);

this._animationEndHandler = run.bind(this, function (event) {
if (event.animationName === 'fade-out' && this.closing) {
this.set('isOpen', false);
this.set('closing', false);
}
});

this.element.addEventListener('animationend', this._animationEndHandler);
},

willDestroyElement() {
let dropdownService = this.dropdown;

this._super(...arguments);

let dropdownService = this.dropdown;
dropdownService.off('close', this, this.close);
dropdownService.off('toggle', this, this.toggle);

this.element.removeEventListener('animationend', this._animationEndHandler);
},

open() {
Expand All @@ -54,17 +63,6 @@ export default Component.extend(DropdownMixin, {
if (this.button) {
this.set('button.isOpen', false);
}

this.$().on('animationend webkitAnimationEnd oanimationend MSAnimationEnd', (event) => {
if (event.originalEvent.animationName === 'fade-out') {
run(this, function () {
if (this.closing) {
this.set('isOpen', false);
this.set('closing', false);
}
});
}
});
},

// Called by the dropdown service when any dropdown button is clicked.
Expand Down
2 changes: 1 addition & 1 deletion app/components/gh-file-upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default Component.extend({

// Reset form
if (this.shouldResetForm) {
this.$().closest('form')[0].reset();
this.element.closest('form').reset();
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion app/components/gh-markdown-editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ export default Component.extend(ShortcutsMixin, {

// trigger the dialog via gh-file-input, when a file is selected it will
// trigger the onImageFilesSelected closure action
this.$('input[type="file"]').click();
this.element.querySelector('input[type="file"]').click();
},

// wrap SimpleMDE's built-in preview toggle so that we can trigger a closure
Expand Down
7 changes: 5 additions & 2 deletions app/components/gh-notification.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Component from '@ember/component';
import {computed} from '@ember/object';
import {run} from '@ember/runloop';
import {inject as service} from '@ember/service';

export default Component.extend({
Expand Down Expand Up @@ -32,16 +33,18 @@ export default Component.extend({
didInsertElement() {
this._super(...arguments);

this.$().on('animationend webkitAnimationEnd oanimationend MSAnimationEnd', (event) => {
this._animationEndHandler = run.bind(this, function () {
if (event.originalEvent.animationName === 'fade-out') {
this.notifications.closeNotification(this.message);
}
});

this.element.addEventListener('animationend', this._animationEndHandler);
},

willDestroyElement() {
this._super(...arguments);
this.$().off('animationend webkitAnimationEnd oanimationend MSAnimationEnd');
this.element.removeEventListener('animationend', this._animationEndHandler);
},

actions: {
Expand Down
18 changes: 15 additions & 3 deletions app/components/gh-publishmenu.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ export default Component.extend({
clock: service(),
intl: service(),

backgroundTask: null,
classNames: 'gh-publishmenu',
displayState: 'draft',
post: null,
postStatus: 'draft',
saveTask: null,
runningText: null,
backgroundTask: null,
saveTask: null,
sendEmailWhenPublished: false,
typedDateError: null,

_publishedAtBlogTZ: null,
_previousStatus: null,
Expand Down Expand Up @@ -258,7 +259,18 @@ export default Component.extend({
}),

save: task(function* ({dropdown} = {}) {
let {post, sendEmailWhenPublished, sendEmailConfirmed, saveType} = this;
let {
post,
sendEmailWhenPublished,
sendEmailConfirmed,
saveType,
typedDateError
} = this;

// don't allow save if an invalid schedule date is present
if (typedDateError) {
return false;
}

if (
post.status === 'draft' &&
Expand Down
Loading

0 comments on commit af37156

Please sign in to comment.