From 3baa81732696b53e1cdb1c69ca56b778c79d0214 Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Tue, 5 May 2015 17:07:12 +0930 Subject: [PATCH] Refactor post components and controls --- framework/core/js/forum/src/app.js | 2 + .../js/forum/src/components/notification.js | 4 +- .../js/forum/src/components/post-activity.js | 24 ++++++ .../js/forum/src/components/post-comment.js | 86 +++---------------- .../src/components/post-discussion-renamed.js | 59 ++----------- .../core/js/forum/src/components/post.js | 31 +++++++ .../forum/src/initializers/post-controls.js | 48 +++++++++++ 7 files changed, 126 insertions(+), 128 deletions(-) create mode 100644 framework/core/js/forum/src/components/post-activity.js create mode 100644 framework/core/js/forum/src/components/post.js create mode 100644 framework/core/js/forum/src/initializers/post-controls.js diff --git a/framework/core/js/forum/src/app.js b/framework/core/js/forum/src/app.js index 5495946cb..9aa36238f 100644 --- a/framework/core/js/forum/src/app.js +++ b/framework/core/js/forum/src/app.js @@ -1,6 +1,7 @@ import App from 'flarum/utils/app'; import store from 'flarum/initializers/store'; import discussionControls from 'flarum/initializers/discussion-controls'; +import postControls from 'flarum/initializers/post-controls'; import preload from 'flarum/initializers/preload'; import session from 'flarum/initializers/session'; import routes from 'flarum/initializers/routes'; @@ -12,6 +13,7 @@ var app = new App(); app.initializers.add('store', store); app.initializers.add('discussion-controls', discussionControls); +app.initializers.add('post-controls', postControls); app.initializers.add('session', session); app.initializers.add('routes', routes); app.initializers.add('components', components); diff --git a/framework/core/js/forum/src/components/notification.js b/framework/core/js/forum/src/components/notification.js index 3d5082ae0..a9b83fbda 100644 --- a/framework/core/js/forum/src/components/notification.js +++ b/framework/core/js/forum/src/components/notification.js @@ -4,8 +4,8 @@ export default class Notification extends Component { view() { var notification = this.props.notification; - return m('div.notification', { - classNames: !notification.isRead ? 'unread' : '', + return m('div.notification.notification-'+notification.contentType(), { + classNames: !notification.isRead() ? 'unread' : '', onclick: this.read.bind(this) }, this.content()); } diff --git a/framework/core/js/forum/src/components/post-activity.js b/framework/core/js/forum/src/components/post-activity.js new file mode 100644 index 000000000..dd52e46a2 --- /dev/null +++ b/framework/core/js/forum/src/components/post-activity.js @@ -0,0 +1,24 @@ +import Post from 'flarum/components/post'; +import username from 'flarum/helpers/username'; +import icon from 'flarum/helpers/icon'; +import humanTime from 'flarum/utils/human-time'; + +export default class PostActivity extends Post { + view(content, attrs) { + attrs.className = 'post-activity '+(attrs.className || ''); + + var iconName = attrs.icon; + delete attrs.icon; + + var post = this.props.post; + + return super.view([ + icon(iconName+' post-icon'), + m('div.post-activity-info', [ + m('a.post-user', {href: app.route('user', { username: post.user().username() }), config: m.route}, username(post.user())), ' ', + content + ]), + m('div.post-activity-time', humanTime(post.time())) + ], attrs); + } +} diff --git a/framework/core/js/forum/src/components/post-comment.js b/framework/core/js/forum/src/components/post-comment.js index 5fc69c665..8910b7a12 100644 --- a/framework/core/js/forum/src/components/post-comment.js +++ b/framework/core/js/forum/src/components/post-comment.js @@ -1,14 +1,10 @@ -import Component from 'flarum/component'; +import Post from 'flarum/components/post'; import classList from 'flarum/utils/class-list'; -import ComposerEdit from 'flarum/components/composer-edit'; import PostHeaderUser from 'flarum/components/post-header-user'; import PostHeaderMeta from 'flarum/components/post-header-meta'; import PostHeaderEdited from 'flarum/components/post-header-edited'; import PostHeaderToggle from 'flarum/components/post-header-toggle'; import ItemList from 'flarum/utils/item-list'; -import ActionButton from 'flarum/components/action-button'; -import DropdownButton from 'flarum/components/dropdown-button'; -import SubtreeRetainer from 'flarum/utils/subtree-retainer'; import listItems from 'flarum/helpers/list-items'; /** @@ -16,43 +12,30 @@ import listItems from 'flarum/helpers/list-items'; (controls, header, and footer) surrounding the post's HTML content. Allows the post to be edited with the composer, hidden, or restored. */ -export default class PostComment extends Component { +export default class PostComment extends Post { constructor(props) { super(props); this.postHeaderUser = new PostHeaderUser({post: this.props.post}); - - this.subtree = new SubtreeRetainer( - () => this.props.post.freshness, - () => this.props.post.user() && this.props.post.user().freshness, - this.postHeaderUser.showCard - ); + this.subtree.add(this.postHeaderUser.showCard); } view() { var post = this.props.post; - var classes = { - 'is-hidden': post.isHidden(), - 'is-edited': post.isEdited(), - 'reveal-content': this.revealContent - }; - - var controls = this.controlItems().toArray(); - - // @todo Having to wrap children in a div isn't nice - return m('article.post.post-comment', {className: classList(classes)}, this.subtree.retain() || m('div', [ - controls.length ? DropdownButton.component({ - items: controls, - className: 'contextual-controls', - buttonClass: 'btn btn-default btn-icon btn-sm btn-naked', - menuClass: 'pull-right' - }) : '', + return super.view([ m('header.post-header', m('ul', listItems(this.headerItems().toArray()))), m('div.post-body', m.trust(post.contentHtml())), m('aside.post-footer', m('ul', listItems(this.footerItems().toArray()))), m('aside.post-actions', m('ul', listItems(this.actionItems().toArray()))) - ])); + ], { + className: classList({ + 'post-comment': true, + 'is-hidden': post.isHidden(), + 'is-edited': post.isEdited(), + 'reveal-content': this.revealContent + }) + }); } toggleContent() { @@ -78,25 +61,6 @@ export default class PostComment extends Component { return items; } - controlItems() { - var items = new ItemList(); - var post = this.props.post; - - if (post.isHidden()) { - if (post.canEdit()) { - items.add('restore', ActionButton.component({ icon: 'reply', label: 'Restore', onclick: this.restore.bind(this) })); - } - if (post.canDelete()) { - items.add('delete', ActionButton.component({ icon: 'times', label: 'Delete Forever', onclick: this.delete.bind(this) })); - } - } else if (post.canEdit()) { - items.add('edit', ActionButton.component({ icon: 'pencil', label: 'Edit', onclick: this.edit.bind(this) })); - items.add('hide', ActionButton.component({ icon: 'times', label: 'Delete', onclick: this.hide.bind(this) })); - } - - return items; - } - footerItems() { return new ItemList(); } @@ -104,30 +68,4 @@ export default class PostComment extends Component { actionItems() { return new ItemList(); } - - edit() { - if (!this.composer || app.composer.component !== this.composer) { - this.composer = new ComposerEdit({ post: this.props.post }); - app.composer.load(this.composer); - } - app.composer.show(); - } - - hide() { - var post = this.props.post; - post.save({ isHidden: true }); - post.pushData({ hideTime: new Date(), hideUser: app.session.user() }); - } - - restore() { - var post = this.props.post; - post.save({ isHidden: false }); - post.pushData({ hideTime: null, hideUser: null }); - } - - delete() { - var post = this.props.post; - post.delete(); - this.props.ondelete && this.props.ondelete(post); - } } diff --git a/framework/core/js/forum/src/components/post-discussion-renamed.js b/framework/core/js/forum/src/components/post-discussion-renamed.js index 8d372f1b1..ac65bf0c0 100644 --- a/framework/core/js/forum/src/components/post-discussion-renamed.js +++ b/framework/core/js/forum/src/components/post-discussion-renamed.js @@ -1,59 +1,14 @@ -import Component from 'flarum/component'; -import icon from 'flarum/helpers/icon'; -import username from 'flarum/helpers/username'; -import humanTime from 'flarum/utils/human-time'; -import SubtreeRetainer from 'flarum/utils/subtree-retainer'; -import ItemList from 'flarum/utils/item-list'; -import ActionButton from 'flarum/components/action-button'; -import DropdownButton from 'flarum/components/dropdown-button'; - -export default class PostDiscussionRenamed extends Component { - constructor(props) { - super(props); - - this.subtree = new SubtreeRetainer( - () => this.props.post.freshness, - () => this.props.post.user().freshness - ); - } - - view(ctrl) { - var controls = this.controlItems().toArray(); +import PostActivity from 'flarum/components/post-activity'; +export default class PostDiscussionRenamed extends PostActivity { + view() { var post = this.props.post; var oldTitle = post.content()[0]; var newTitle = post.content()[1]; - return m('article.post.post-activity.post-discussion-renamed', this.subtree.retain() || m('div', [ - controls.length ? DropdownButton.component({ - items: controls, - className: 'contextual-controls', - buttonClass: 'btn btn-default btn-icon btn-sm btn-naked', - menuClass: 'pull-right' - }) : '', - icon('pencil post-icon'), - m('div.post-activity-info', [ - m('a.post-user', {href: app.route('user', { username: post.user().username() }), config: m.route}, username(post.user())), - ' changed the title from ', m('strong.old-title', oldTitle), ' to ', m('strong.new-title', newTitle), '.' - ]), - m('div.post-activity-time', humanTime(post.time())) - ])); - } - - controlItems() { - var items = new ItemList(); - var post = this.props.post; - - if (post.canDelete()) { - items.add('delete', ActionButton.component({ icon: 'times', label: 'Delete', onclick: this.delete.bind(this) })); - } - - return items; - } - - delete() { - var post = this.props.post; - post.delete(); - this.props.ondelete && this.props.ondelete(post); + return super.view(['changed the title from ', m('strong.old-title', oldTitle), ' to ', m('strong.new-title', newTitle), '.'], { + className: 'post-discussion-renamed', + icon: 'pencil' + }); } } diff --git a/framework/core/js/forum/src/components/post.js b/framework/core/js/forum/src/components/post.js new file mode 100644 index 000000000..f3b8abce7 --- /dev/null +++ b/framework/core/js/forum/src/components/post.js @@ -0,0 +1,31 @@ +import Component from 'flarum/component'; +import SubtreeRetainer from 'flarum/utils/subtree-retainer'; +import DropdownButton from 'flarum/components/dropdown-button'; + +export default class Post extends Component { + constructor(props) { + super(props); + + this.subtree = new SubtreeRetainer( + () => this.props.post.freshness, + () => { + var user = this.props.post.user(); + return user && user.freshness; + } + ); + } + + view(content, attrs) { + var controls = this.props.post.controls(this).toArray(); + + return m('article.post', attrs, this.subtree.retain() || m('div', [ + controls.length ? DropdownButton.component({ + items: controls, + className: 'contextual-controls', + buttonClass: 'btn btn-default btn-icon btn-sm btn-naked', + menuClass: 'pull-right' + }) : '', + content + ])); + } +} diff --git a/framework/core/js/forum/src/initializers/post-controls.js b/framework/core/js/forum/src/initializers/post-controls.js new file mode 100644 index 000000000..192843997 --- /dev/null +++ b/framework/core/js/forum/src/initializers/post-controls.js @@ -0,0 +1,48 @@ +import Post from 'flarum/models/post'; +import ComposerEdit from 'flarum/components/composer-edit'; +import ActionButton from 'flarum/components/action-button'; +import Separator from 'flarum/components/separator'; +import ItemList from 'flarum/utils/item-list'; + +export default function(app) { + function editAction() { + app.composer.load(new ComposerEdit({ post: this })); + app.composer.show(); + } + + function hideAction() { + this.save({ isHidden: true }); + this.pushData({ hideTime: new Date(), hideUser: app.session.user() }); + } + + function restoreAction() { + this.save({ isHidden: false }); + this.pushData({ hideTime: null, hideUser: null }); + } + + function deleteAction() { + this.delete(); + if (app.current instanceof DiscussionPage) { + app.current.stream().removePost(this.id()); + } + } + + Post.prototype.controls = function(context) { + var items = new ItemList(); + + if (this.contentType() === 'comment' && this.canEdit()) { + if (this.isHidden()) { + items.add('restore', ActionButton.component({ icon: 'reply', label: 'Restore', onclick: restoreAction.bind(this) })); + } else { + items.add('edit', ActionButton.component({ icon: 'pencil', label: 'Edit', onclick: editAction.bind(this) })); + items.add('hide', ActionButton.component({ icon: 'times', label: 'Delete', onclick: hideAction.bind(this) })); + } + } + + if ((this.contentType() !== 'comment' || this.isHidden()) && this.canDelete()) { + items.add('delete', ActionButton.component({ icon: 'times', label: 'Delete', onclick: deleteAction.bind(this) })); + } + + return items; + } +};