Skip to content

Commit

Permalink
Refactor modals
Browse files Browse the repository at this point in the history
refs #5798, closes #5018
- adds new `gh-fullscreen-modal` component - modals are now specified in-context so that they can have deeper interaction with their surrounding components/controller/route, i.e. a modal component can be a thin confirm/deny wrapper over the underlying controller action keeping all context-sensitive logic in one place
- adds spin-buttons to all modals with async behaviour
- adds/improves behaviour of inline-validation in modals
- improves re-authenticate modal to properly handle validation and authentication errors
  • Loading branch information
kevinansfield committed Jan 12, 2016
1 parent d710bde commit 1c6b208
Show file tree
Hide file tree
Showing 88 changed files with 1,262 additions and 1,075 deletions.
6 changes: 6 additions & 0 deletions core/client/app/components/gh-ed-editor.js
Expand Up @@ -57,5 +57,11 @@ export default TextArea.extend(EditorAPI, EditorShortcuts, EditorScroll, {
enable() {
let textarea = this.get('element');
textarea.removeAttribute('readonly');
},

actions: {
toggleCopyHTMLModal(generatedHTML) {
this.attrs.toggleCopyHTMLModal(generatedHTML);
}
}
});
8 changes: 8 additions & 0 deletions core/client/app/components/gh-editor.js
Expand Up @@ -7,6 +7,9 @@ export default Component.extend({
tagName: 'section',
classNames: ['gh-view'],

showCopyHTMLModal: false,
copyHTMLModalContent: null,

// updated when gh-ed-editor component scrolls
editorScrollInfo: null,
// updated when markdown is rendered
Expand Down Expand Up @@ -58,6 +61,11 @@ export default Component.extend({
actions: {
selectTab(tab) {
this.set('activeTab', tab);
},

toggleCopyHTMLModal(generatedHTML) {
this.set('copyHTMLModalContent', generatedHTML);
this.toggleProperty('showCopyHTMLModal');
}
}
});
76 changes: 76 additions & 0 deletions core/client/app/components/gh-fullscreen-modal.js
@@ -0,0 +1,76 @@
import Ember from 'ember';
import LiquidTether from 'liquid-tether/components/liquid-tether';

const {RSVP, isBlank, on, run} = Ember;
const emberA = Ember.A;

const FullScreenModalComponent = LiquidTether.extend({
to: 'fullscreen-modal',
target: 'document.body',
targetModifier: 'visible',
targetAttachment: 'top center',
attachment: 'top center',
tetherClass: 'fullscreen-modal',
overlayClass: 'fullscreen-modal-background',
modalPath: 'unknown',

dropdown: Ember.inject.service(),

init() {
this._super(...arguments);
this.modalPath = `modals/${this.get('modal')}`;
},

setTetherClass: on('init', function () {
let tetherClass = this.get('tetherClass');
let modifiers = (this.get('modifier') || '').split(' ');
let tetherClasses = emberA([tetherClass]);

modifiers.forEach((modifier) => {
if (!isBlank(modifier)) {
let className = `${tetherClass}-${modifier}`;
tetherClasses.push(className);
}
});

this.set('tetherClass', tetherClasses.join(' '));
}),

closeDropdowns: on('didInsertElement', function () {
run.schedule('afterRender', this, function () {
this.get('dropdown').closeDropdowns();
});
}),

actions: {
close() {
if (this.attrs.close) {
return this.attrs.close();
}

return new RSVP.Promise((resolve) => {
resolve();
});
},

confirm() {
if (this.attrs.confirm) {
return this.attrs.confirm();
}

return new RSVP.Promise((resolve) => {
resolve();
});
},

clickOverlay() {
this.send('close');
}
}
});

FullScreenModalComponent.reopenClass({
positionalParams: ['modal']
});

export default FullScreenModalComponent;
67 changes: 0 additions & 67 deletions core/client/app/components/gh-modal-dialog.js

This file was deleted.

4 changes: 2 additions & 2 deletions core/client/app/components/gh-nav-menu.js
Expand Up @@ -21,8 +21,8 @@ export default Component.extend({
this.sendAction('toggleMaximise');
},

openModal(modal) {
this.sendAction('openModal', modal);
showMarkdownHelp() {
this.sendAction('showMarkdownHelp');
},

closeMobileMenu() {
Expand Down
2 changes: 1 addition & 1 deletion core/client/app/components/gh-tag-settings-form.js
Expand Up @@ -125,7 +125,7 @@ export default Component.extend({
},

deleteTag() {
this.sendAction('openModal', 'delete-tag', this.get('tag'));
this.attrs.showDeleteTagModal();
}
}

Expand Down
82 changes: 0 additions & 82 deletions core/client/app/components/gh-upload-modal.js

This file was deleted.

6 changes: 2 additions & 4 deletions core/client/app/components/gh-user-invited.js
Expand Up @@ -31,8 +31,7 @@ export default Component.extend({
notifications.showAlert('Invitation email was not sent. Please try resending.', {type: 'error', key: 'invite.resend.not-sent'});
} else {
user.set('status', result.users[0].status);
notifications.showNotification(notificationText);
notifications.closeAlerts('invite.resend');
notifications.showNotification(notificationText, {key: 'invite.resend.success'});
}
}).catch((error) => {
notifications.showAPIError(error, {key: 'invite.resend'});
Expand All @@ -51,8 +50,7 @@ export default Component.extend({
if (user.get('invited')) {
user.destroyRecord().then(() => {
let notificationText = `Invitation revoked. (${email})`;
notifications.showNotification(notificationText);
notifications.closeAlerts('invite.revoke');
notifications.showNotification(notificationText, {key: 'invite.revoke.success'});
}).catch((error) => {
notifications.showAPIError(error, {key: 'invite.revoke'});
});
Expand Down
45 changes: 45 additions & 0 deletions core/client/app/components/modals/base.js
@@ -0,0 +1,45 @@
/* global key */
import Ember from 'ember';

const {Component, on, run} = Ember;

export default Component.extend({
tagName: 'section',
classNames: 'modal-content',

_previousKeymasterScope: null,

setupShortcuts: on('didInsertElement', function () {
run(function () {
document.activeElement.blur();
});
this._previousKeymasterScope = key.getScope();

key('enter', 'modal', () => {
this.send('confirm');
});

key('escape', 'modal', () => {
this.send('closeModal');
});

key.setScope('modal');
}),

removeShortcuts: on('willDestroyElement', function () {
key.unbind('enter', 'modal');
key.unbind('escape', 'modal');

key.setScope(this._previousKeymasterScope);
}),

actions: {
confirm() {
throw new Error('You must override the "confirm" action in your modal component');
},

closeModal() {
this.attrs.closeModal();
}
}
});
9 changes: 9 additions & 0 deletions core/client/app/components/modals/copy-html.js
@@ -0,0 +1,9 @@
import Ember from 'ember';
import ModalComponent from 'ghost/components/modals/base';

const {computed} = Ember;
const {alias} = computed;

export default ModalComponent.extend({
generatedHtml: alias('model')
});

0 comments on commit 1c6b208

Please sign in to comment.