mirror of
https://github.com/flarum/core.git
synced 2025-08-06 00:17:31 +02:00
Implement "renamed" posts
Record when the discussion was renamed, from what, and by whom. Information is stored in the `content` field as a serialised JSON object because proper polymorphism will be too difficult with Ember Data and especially when extensions try to add new post types.
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
import FadeIn from 'flarum/mixins/fade-in';
|
||||
import HasItemLists from 'flarum/mixins/has-item-lists';
|
||||
|
||||
var precompileTemplate = Ember.Handlebars.compile;
|
||||
|
||||
/**
|
||||
Component for a `renamed`-typed post.
|
||||
*/
|
||||
export default Ember.Component.extend(FadeIn, HasItemLists, {
|
||||
layoutName: 'components/discussion/post-renamed',
|
||||
tagName: 'article',
|
||||
classNames: ['post', 'post-renamed', 'post-activity'],
|
||||
itemLists: ['controls'],
|
||||
|
||||
// The stream-content component instansiates this component and sets the
|
||||
// `content` property to the content of the item in the post-stream object.
|
||||
// This happens to be our post model!
|
||||
post: Ember.computed.alias('content'),
|
||||
|
||||
decodedContent: Ember.computed('post.content', function() {
|
||||
return JSON.parse(this.get('post.content'));
|
||||
}),
|
||||
oldTitle: Ember.computed.alias('decodedContent.0'),
|
||||
newTitle: Ember.computed.alias('decodedContent.1'),
|
||||
|
||||
populateControls: function(items) {
|
||||
this.addActionItem(items, 'delete', 'Delete', 'times', 'post.canDelete');
|
||||
},
|
||||
|
||||
actions: {
|
||||
// In the template, we render the "controls" dropdown with the contents of
|
||||
// the `renderControls` property. This way, when a post is initially
|
||||
// rendered, it doesn't have to go to the trouble of rendering the
|
||||
// controls right away, which speeds things up. When the dropdown button
|
||||
// is clicked, this will fill in the actual controls.
|
||||
renderControls: function() {
|
||||
this.set('renderControls', this.get('controls'));
|
||||
},
|
||||
|
||||
delete: function() {
|
||||
var post = this.get('post');
|
||||
post.destroyRecord();
|
||||
this.sendAction('postRemoved', post);
|
||||
}
|
||||
}
|
||||
});
|
@@ -107,7 +107,16 @@ export default Ember.Controller.extend(Ember.Evented, UseComposerMixin, {
|
||||
rename: function(title) {
|
||||
var discussion = this.get('model');
|
||||
discussion.set('title', title);
|
||||
discussion.save();
|
||||
|
||||
// When we save the title, we should get back an 'added post' in the
|
||||
// response which documents the title change. We'll add this to the post
|
||||
// stream.
|
||||
var controller = this;
|
||||
discussion.save().then(function(discussion) {
|
||||
discussion.get('addedPosts').forEach(function(post) {
|
||||
controller.get('stream').addPostToEnd(post);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
delete: function() {
|
||||
|
@@ -36,6 +36,7 @@ export default DS.Model.extend({
|
||||
}),
|
||||
loadedPosts: DS.hasMany('post'),
|
||||
relevantPosts: DS.hasMany('post'),
|
||||
addedPosts: DS.hasMany('post'),
|
||||
|
||||
readTime: DS.attr('date'),
|
||||
readNumber: DS.attr('number'),
|
||||
|
@@ -7,10 +7,19 @@ export default Ember.Route.extend({
|
||||
start: {replace: true}
|
||||
},
|
||||
|
||||
model: function(params) {
|
||||
return this.store.findQueryOne('discussion', params.id, {
|
||||
discussion: function(id, start) {
|
||||
return this.store.findQueryOne('discussion', id, {
|
||||
include: 'posts',
|
||||
near: params.start
|
||||
near: start
|
||||
});
|
||||
},
|
||||
|
||||
// When we fetch the discussion from the model hook (i.e. on a fresh page
|
||||
// load), we'll wrap it in an object proxy and set a `loaded` flag to true
|
||||
// so that it won't be reloaded later on.
|
||||
model: function(params) {
|
||||
return this.discussion(params.id, params.start).then(function(discussion) {
|
||||
return Ember.ObjectProxy.create({content: discussion, loaded: true});
|
||||
});
|
||||
},
|
||||
|
||||
@@ -36,18 +45,18 @@ export default Ember.Route.extend({
|
||||
});
|
||||
controller.set('stream', stream);
|
||||
|
||||
// Next, we need to make sure we have a list of the discussion's post
|
||||
// IDs. If we don't already have this information, we'll need to
|
||||
// reload the discussion model.
|
||||
var promise = discussion.get('posts') ? Ember.RSVP.resolve(discussion) : this.model({
|
||||
id: discussion.get('id'),
|
||||
start: controller.get('start')
|
||||
});
|
||||
// We need to make sure we have an up-to-date list of the discussion's
|
||||
// post IDs. If we didn't enter this route using the model hook (like if
|
||||
// clicking on a discussion in the index), then we'll reload the model.
|
||||
var promise = discussion.get('loaded') ?
|
||||
Ember.RSVP.resolve(discussion.get('content')) :
|
||||
this.discussion(discussion.get('id'), controller.get('start'));
|
||||
|
||||
// When we know we have the post IDs, we can set up the post stream with
|
||||
// them. Then we will tell the view that we have finished loading so that
|
||||
// it can scroll down to the appropriate post.
|
||||
promise.then(function(discussion) {
|
||||
controller.set('model', discussion);
|
||||
var postIds = discussion.get('postIds');
|
||||
stream.setup(postIds);
|
||||
|
||||
@@ -70,11 +79,6 @@ export default Ember.Route.extend({
|
||||
}));
|
||||
}
|
||||
|
||||
// Clear the list of post IDs for this discussion (without
|
||||
// dirtying the record), so that next time we load the discussion,
|
||||
// the discussion details and post IDs will be refreshed.
|
||||
controller.store.push('discussion', {id: discussion.get('id'), posts: ''});
|
||||
|
||||
// It's possible for this promise to have resolved but the user
|
||||
// has clicked away to a different discussion. So only if we're
|
||||
// still on the original one, we will tell the view that we're
|
||||
|
@@ -152,10 +152,9 @@
|
||||
}
|
||||
.post-icon {
|
||||
float: left;
|
||||
margin-top: -2px;
|
||||
margin-left: -90px;
|
||||
width: 64px;
|
||||
text-align: center;
|
||||
text-align: right;
|
||||
font-size: 22px;
|
||||
}
|
||||
.post.is-hidden {
|
||||
@@ -194,6 +193,25 @@
|
||||
}
|
||||
}
|
||||
|
||||
.post-activity {
|
||||
&, & a {
|
||||
color: @fl-body-muted-color;
|
||||
}
|
||||
& a {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
.post-activity-info {
|
||||
font-size: 15px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.post-renamed {
|
||||
& .old-title, & .new-title {
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------
|
||||
// Scrubber
|
||||
|
||||
|
@@ -1,11 +1,4 @@
|
||||
{{#if controls}}
|
||||
{{ui/dropdown-button
|
||||
items=renderControls
|
||||
class="contextual-controls"
|
||||
buttonClass="btn btn-default btn-icon btn-sm btn-naked"
|
||||
buttonClick="renderControls"
|
||||
menuClass="pull-right"}}
|
||||
{{/if}}
|
||||
{{partial "components/discussion/post-controls"}}
|
||||
|
||||
<header class="post-header">
|
||||
{{ui/item-list items=header}}
|
||||
|
@@ -0,0 +1,8 @@
|
||||
{{#if controls}}
|
||||
{{ui/dropdown-button
|
||||
items=renderControls
|
||||
class="contextual-controls"
|
||||
buttonClass="btn btn-default btn-icon btn-sm btn-naked"
|
||||
buttonClick="renderControls"
|
||||
menuClass="pull-right"}}
|
||||
{{/if}}
|
@@ -0,0 +1,7 @@
|
||||
{{partial "components/discussion/post-controls"}}
|
||||
|
||||
{{fa-icon "pencil" class="post-icon"}}
|
||||
|
||||
<div class="post-activity-info">{{#link-to "user" post.user class="post-user"}}{{post.user.username}}{{/link-to}} changed the title from <strong class="old-title">{{oldTitle}}</strong> to <strong class="new-title">{{newTitle}}</strong>.</div>
|
||||
|
||||
<div class="post-activity-time">{{human-time post.time}}</div>
|
@@ -1,4 +0,0 @@
|
||||
<div class="activity">
|
||||
{{fa-icon "pencil" class="post-icon"}}
|
||||
{{#link-to "user" post.user}}{{post.user.username}}{{/link-to}} changed the title from <strong class="old-title">{{post.oldTitle}}</strong> to <strong class="new-title">{{post.newTitle}}</strong>.
|
||||
</div>
|
@@ -71,8 +71,9 @@ export default Ember.View.extend(HasItemLists, {
|
||||
|
||||
this.addActionItem(items, 'rename', 'Rename', 'pencil', 'discussion.canEdit', function() {
|
||||
var discussion = view.get('controller.model');
|
||||
var title = prompt('Enter a new title for this discussion:', discussion.get('title'));
|
||||
if (title) {
|
||||
var currentTitle = discussion.get('title');
|
||||
var title = prompt('Enter a new title for this discussion:', currentTitle);
|
||||
if (title && title !== currentTitle) {
|
||||
view.get('controller').send('rename', title);
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user