mirror of
https://github.com/flarum/framework.git
synced 2024-12-04 16:23:37 +08:00
Refactor post components and controls
This commit is contained in:
parent
1f53547ee5
commit
3baa817326
|
@ -1,6 +1,7 @@
|
||||||
import App from 'flarum/utils/app';
|
import App from 'flarum/utils/app';
|
||||||
import store from 'flarum/initializers/store';
|
import store from 'flarum/initializers/store';
|
||||||
import discussionControls from 'flarum/initializers/discussion-controls';
|
import discussionControls from 'flarum/initializers/discussion-controls';
|
||||||
|
import postControls from 'flarum/initializers/post-controls';
|
||||||
import preload from 'flarum/initializers/preload';
|
import preload from 'flarum/initializers/preload';
|
||||||
import session from 'flarum/initializers/session';
|
import session from 'flarum/initializers/session';
|
||||||
import routes from 'flarum/initializers/routes';
|
import routes from 'flarum/initializers/routes';
|
||||||
|
@ -12,6 +13,7 @@ var app = new App();
|
||||||
|
|
||||||
app.initializers.add('store', store);
|
app.initializers.add('store', store);
|
||||||
app.initializers.add('discussion-controls', discussionControls);
|
app.initializers.add('discussion-controls', discussionControls);
|
||||||
|
app.initializers.add('post-controls', postControls);
|
||||||
app.initializers.add('session', session);
|
app.initializers.add('session', session);
|
||||||
app.initializers.add('routes', routes);
|
app.initializers.add('routes', routes);
|
||||||
app.initializers.add('components', components);
|
app.initializers.add('components', components);
|
||||||
|
|
|
@ -4,8 +4,8 @@ export default class Notification extends Component {
|
||||||
view() {
|
view() {
|
||||||
var notification = this.props.notification;
|
var notification = this.props.notification;
|
||||||
|
|
||||||
return m('div.notification', {
|
return m('div.notification.notification-'+notification.contentType(), {
|
||||||
classNames: !notification.isRead ? 'unread' : '',
|
classNames: !notification.isRead() ? 'unread' : '',
|
||||||
onclick: this.read.bind(this)
|
onclick: this.read.bind(this)
|
||||||
}, this.content());
|
}, this.content());
|
||||||
}
|
}
|
||||||
|
|
24
framework/core/js/forum/src/components/post-activity.js
Normal file
24
framework/core/js/forum/src/components/post-activity.js
Normal file
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,14 +1,10 @@
|
||||||
import Component from 'flarum/component';
|
import Post from 'flarum/components/post';
|
||||||
import classList from 'flarum/utils/class-list';
|
import classList from 'flarum/utils/class-list';
|
||||||
import ComposerEdit from 'flarum/components/composer-edit';
|
|
||||||
import PostHeaderUser from 'flarum/components/post-header-user';
|
import PostHeaderUser from 'flarum/components/post-header-user';
|
||||||
import PostHeaderMeta from 'flarum/components/post-header-meta';
|
import PostHeaderMeta from 'flarum/components/post-header-meta';
|
||||||
import PostHeaderEdited from 'flarum/components/post-header-edited';
|
import PostHeaderEdited from 'flarum/components/post-header-edited';
|
||||||
import PostHeaderToggle from 'flarum/components/post-header-toggle';
|
import PostHeaderToggle from 'flarum/components/post-header-toggle';
|
||||||
import ItemList from 'flarum/utils/item-list';
|
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';
|
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
|
(controls, header, and footer) surrounding the post's HTML content. Allows
|
||||||
the post to be edited with the composer, hidden, or restored.
|
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) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.postHeaderUser = new PostHeaderUser({post: this.props.post});
|
this.postHeaderUser = new PostHeaderUser({post: this.props.post});
|
||||||
|
this.subtree.add(this.postHeaderUser.showCard);
|
||||||
this.subtree = new SubtreeRetainer(
|
|
||||||
() => this.props.post.freshness,
|
|
||||||
() => this.props.post.user() && this.props.post.user().freshness,
|
|
||||||
this.postHeaderUser.showCard
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
view() {
|
view() {
|
||||||
var post = this.props.post;
|
var post = this.props.post;
|
||||||
|
|
||||||
var classes = {
|
return super.view([
|
||||||
'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'
|
|
||||||
}) : '',
|
|
||||||
m('header.post-header', m('ul', listItems(this.headerItems().toArray()))),
|
m('header.post-header', m('ul', listItems(this.headerItems().toArray()))),
|
||||||
m('div.post-body', m.trust(post.contentHtml())),
|
m('div.post-body', m.trust(post.contentHtml())),
|
||||||
m('aside.post-footer', m('ul', listItems(this.footerItems().toArray()))),
|
m('aside.post-footer', m('ul', listItems(this.footerItems().toArray()))),
|
||||||
m('aside.post-actions', m('ul', listItems(this.actionItems().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() {
|
toggleContent() {
|
||||||
|
@ -78,25 +61,6 @@ export default class PostComment extends Component {
|
||||||
return items;
|
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() {
|
footerItems() {
|
||||||
return new ItemList();
|
return new ItemList();
|
||||||
}
|
}
|
||||||
|
@ -104,30 +68,4 @@ export default class PostComment extends Component {
|
||||||
actionItems() {
|
actionItems() {
|
||||||
return new ItemList();
|
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +1,14 @@
|
||||||
import Component from 'flarum/component';
|
import PostActivity from 'flarum/components/post-activity';
|
||||||
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();
|
|
||||||
|
|
||||||
|
export default class PostDiscussionRenamed extends PostActivity {
|
||||||
|
view() {
|
||||||
var post = this.props.post;
|
var post = this.props.post;
|
||||||
var oldTitle = post.content()[0];
|
var oldTitle = post.content()[0];
|
||||||
var newTitle = post.content()[1];
|
var newTitle = post.content()[1];
|
||||||
|
|
||||||
return m('article.post.post-activity.post-discussion-renamed', this.subtree.retain() || m('div', [
|
return super.view(['changed the title from ', m('strong.old-title', oldTitle), ' to ', m('strong.new-title', newTitle), '.'], {
|
||||||
controls.length ? DropdownButton.component({
|
className: 'post-discussion-renamed',
|
||||||
items: controls,
|
icon: 'pencil'
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
31
framework/core/js/forum/src/components/post.js
Normal file
31
framework/core/js/forum/src/components/post.js
Normal file
|
@ -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
|
||||||
|
]));
|
||||||
|
}
|
||||||
|
}
|
48
framework/core/js/forum/src/initializers/post-controls.js
Normal file
48
framework/core/js/forum/src/initializers/post-controls.js
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user