Merge pull request #4099 from svbergerem/feature/post-preview

Preview posts in stream
This commit is contained in:
Florian Staudacher 2013-04-07 11:38:11 -07:00
commit 06d67bf854
11 changed files with 173 additions and 2 deletions

View file

@ -127,6 +127,7 @@ by them self.
* Add multiphoto for mobile post. [#4065](https://github.com/diaspora/diaspora/issues/4065) * Add multiphoto for mobile post. [#4065](https://github.com/diaspora/diaspora/issues/4065)
* Add hotkeys to navigate in stream [#4089](https://github.com/diaspora/diaspora/pull/4089) * Add hotkeys to navigate in stream [#4089](https://github.com/diaspora/diaspora/pull/4089)
* Add a brief explanatory text about external services connections to services index page [#3064](https://github.com/diaspora/diaspora/issues/3064) * Add a brief explanatory text about external services connections to services index page [#3064](https://github.com/diaspora/diaspora/issues/3064)
* Add a preview for posts in the stream [#4099](https://github.com/diaspora/diaspora/issues/4099)
# 0.0.3.4 # 0.0.3.4

View file

@ -18,6 +18,7 @@ app.views.Publisher = Backbone.View.extend(_.extend(
"focus textarea" : "open", "focus textarea" : "open",
"click #hide_publisher" : "clear", "click #hide_publisher" : "clear",
"submit form" : "createStatusMessage", "submit form" : "createStatusMessage",
"click .post_preview_button" : "createPostPreview",
"click .service_icon": "toggleService", "click .service_icon": "toggleService",
"textchange #status_message_fake_text": "handleTextchange", "textchange #status_message_fake_text": "handleTextchange",
"click .dropdown .dropdown_list li": "toggleAspect" "click .dropdown .dropdown_list li": "toggleAspect"
@ -29,6 +30,7 @@ app.views.Publisher = Backbone.View.extend(_.extend(
this.el_hiddenInput = this.$('#status_message_text'); this.el_hiddenInput = this.$('#status_message_text');
this.el_wrapper = this.$('#publisher_textarea_wrapper'); this.el_wrapper = this.$('#publisher_textarea_wrapper');
this.el_submit = this.$('input[type=submit]'); this.el_submit = this.$('input[type=submit]');
this.el_preview = this.$('button.post_preview_button');
this.el_photozone = this.$('#photodropzone'); this.el_photozone = this.$('#photodropzone');
// init mentions plugin // init mentions plugin
@ -42,10 +44,11 @@ app.views.Publisher = Backbone.View.extend(_.extend(
this.el_hiddenInput.val( this.el_input.val() ); this.el_hiddenInput.val( this.el_input.val() );
} }
// hide close button, in case publisher is standalone // hide close and preview buttons, in case publisher is standalone
// (e.g. bookmarklet, mentions popup) // (e.g. bookmarklet, mentions popup)
if( this.options.standalone ) { if( this.options.standalone ) {
this.$('#hide_publisher').hide(); this.$('#hide_publisher').hide();
this.el_preview.hide();
} }
// this has to be here, otherwise for some reason the callback for the // this has to be here, otherwise for some reason the callback for the
@ -85,6 +88,83 @@ app.views.Publisher = Backbone.View.extend(_.extend(
// clear state // clear state
this.clear(); this.clear();
}, },
createPostPreview : function(evt) {
if(evt){ evt.preventDefault(); }
var serializedForm = $(evt.target).closest("form").serializeObject();
var photos = new Array();
$('li.publisher_photo img').each(function(){
var file = $(this).attr('src').substring("/uploads/images/".length);
photos.push(
{
"sizes":{
"small" : "/uploads/images/thumb_small_" + file,
"medium" : "/uploads/images/thumb_medium_" + file,
"large" : "/uploads/images/scaled_full_" + file
}
}
);
});
var mentioned_people = new Array();
var regexp = new RegExp("@{\(\.\*\) ; \(\.\*\)}", "g");
while(user=regexp.exec(serializedForm["status_message[text]"])){
// user[1]: name, user[2]: handle
var mentioned_user = Mentions.contacts.filter(function(item) { return item.handle == user[2];})[0];
if(mentioned_user){
mentioned_people.push({
"id":mentioned_user["id"],
"guid":mentioned_user["guid"],
"name":user[1],
"diaspora_id":user[2],
"avatar":mentioned_user["avatar"]
});
}
}
var date = (new Date()).toISOString();
var previewMessage = {
"id" : 0,
"text" : serializedForm["status_message[text]"],
"public" : serializedForm["aspect_ids[]"]=="public",
"created_at" : date,
"interacted_at" : date,
"post_type" : "StatusMessage",
"author" : app.currentUser ? app.currentUser.attributes : {},
"mentioned_people" : mentioned_people,
"photos" : photos,
"frame_name" : "status",
"title" : serializedForm["status_message[text]"],
"interactions" : {"likes":[],"reshares":[],"comments_count":0,"likes_count":0,"reshares_count":0}
}
if(app.stream) {
this.removePostPreview();
app.stream.items.add(previewMessage);
this.recentPreview=previewMessage;
this.modifyPostPreview($('.stream_element:first'));
}
},
modifyPostPreview : function(post) {
post.addClass('post_preview');
$('a.delete.remove_post',post).hide();
$('a.like, a.focus_comment_textarea',post).removeAttr("href");
$('a.like',post).addClass("like_preview");
$('a.like',post).removeClass("like");
$('a.focus_comment_textarea',post).addClass("focus_comment_textarea_preview");
$('a.focus_comment_textarea',post).removeClass("focus_comment_textarea");
$('a',$('span.details.grey',post)).removeAttr("href");
},
removePostPreview : function() {
if(app.stream && this.recentPreview){
app.stream.items.remove(this.recentPreview);
delete this.recentPreview;
}
},
clear : function() { clear : function() {
// clear text(s) // clear text(s)
@ -104,6 +184,9 @@ app.views.Publisher = Backbone.View.extend(_.extend(
// close publishing area (CSS) // close publishing area (CSS)
this.close(); this.close();
// remove preview
this.removePostPreview();
// disable submitting // disable submitting
this.checkSubmitAvailability(); this.checkSubmitAvailability();
@ -137,8 +220,10 @@ app.views.Publisher = Backbone.View.extend(_.extend(
checkSubmitAvailability: function() { checkSubmitAvailability: function() {
if( this._submittable() ) { if( this._submittable() ) {
this.el_submit.removeAttr('disabled'); this.el_submit.removeAttr('disabled');
this.el_preview.removeAttr('disabled');
} else { } else {
this.el_submit.attr('disabled','disabled'); this.el_submit.attr('disabled','disabled');
this.el_preview.attr('disabled','disabled');
} }
}, },

View file

@ -3112,3 +3112,11 @@ body
:font-size small :font-size small
:text-align right :text-align right
:margin 5px 2px :margin 5px 2px
.post_preview
:padding
:top 5px
:border
:bottom 3px solid #3f8fba !important
:background
:color #e8f7ff

View file

@ -30,6 +30,7 @@
onSubmit: function(id, fileName){ onSubmit: function(id, fileName){
$('#file-upload').addClass("loading"); $('#file-upload').addClass("loading");
$('#publisher').find("input[type='submit']").attr('disabled','disabled'); $('#publisher').find("input[type='submit']").attr('disabled','disabled');
$('#publisher').find("button.post_preview_button").attr('disabled','disabled');
app.publisher.el_wrapper.addClass("with_attachments"); app.publisher.el_wrapper.addClass("with_attachments");
$('#photodropzone').append( $('#photodropzone').append(
@ -61,6 +62,7 @@
textarea = publisher.find('textarea'); textarea = publisher.find('textarea');
publisher.find("input[type='submit']").removeAttr('disabled'); publisher.find("input[type='submit']").removeAttr('disabled');
publisher.find("button.post_preview_button").removeAttr('disabled');
$('.x').bind('click', function(){ $('.x').bind('click', function(){
var photo = $(this).closest('.publisher_photo'); var photo = $(this).closest('.publisher_photo');

View file

@ -73,6 +73,9 @@
- for aspect in all_aspects - for aspect in all_aspects
= aspect_dropdown_list_item(aspect, !all_aspects_selected?(selected_aspects) && selected_aspects.include?(aspect) ) = aspect_dropdown_list_item(aspect, !all_aspects_selected?(selected_aspects) && selected_aspects.include?(aspect) )
%button{ :disabled => ("disabled" if publisher_hidden_text.blank?), :class => 'button post_preview_button'}
= t('.preview')
= status.submit t('.share'), :disabled => publisher_hidden_text.blank?, :class => 'button creation', :tabindex => 2 = status.submit t('.share'), :disabled => publisher_hidden_text.blank?, :class => 'button creation', :tabindex => 2
.facebox_content .facebox_content

View file

@ -789,6 +789,7 @@ en:
publisher: publisher:
posting: "Posting..." posting: "Posting..."
share: "Share" share: "Share"
preview: "Preview"
post_a_message_to: "Post a message to %{aspect}" post_a_message_to: "Post a message to %{aspect}"
make_public: "make public" make_public: "make public"
all: "all" all: "all"

View file

@ -0,0 +1,52 @@
@javascript
Feature: preview posts in the stream
In order to test markdown without posting
As a user
I want to see a preview of my posts in the stream
Background:
Given following users exist:
| username | email |
| Bob Jones | bob@bob.bob |
| Alice Smith | alice@alice.alice |
And a user with email "bob@bob.bob" is connected with "alice@alice.alice"
When I sign in as "bob@bob.bob"
And I am on the home page
Then I should not see any posts in my stream
Scenario: preview and post a text-only message
Given I expand the publisher
When I fill in the following:
| status_message_fake_text | I am eating yogurt |
And I press "Preview"
Then "I am eating yogurt" should be post 1
And the first post should be a preview
When I fill in the following:
| status_message_fake_text | This preview rocks |
And I press "Preview"
Then "This preview rocks" should be post 1
And I should not see "I am eating a yogurt"
When I fill in the following:
| status_message_fake_text | I like rocks |
And I press "Share"
And I wait for the ajax to finish
Then "I like rocks" should be post 1
And I should not see "This preview rocks"
Scenario: preview a photo with text
Given I expand the publisher
When I attach the file "spec/fixtures/button.png" to hidden element "file" within "#file-upload"
When I fill in the following:
| status_message_fake_text | Look at this dog |
And I press "Preview"
Then I should see a "img" within ".stream_element div.photo_attachments"
And I should see "Look at this dog" within ".stream_element"
Scenario: preview a post with mentions
Given I expand the publisher
And I mention Alice in the publisher
And I press "Preview"
And I follow "Alice Smith"
Then I should see "Alice Smith"

View file

@ -3,4 +3,9 @@ And /^Alice has a post mentioning Bob$/ do
bob = User.find_by_email 'bob@bob.bob' bob = User.find_by_email 'bob@bob.bob'
aspect = alice.aspects.where(:name => "Besties").first aspect = alice.aspects.where(:name => "Besties").first
alice.post(:status_message, :text => "@{Bob Jones; #{bob.person.diaspora_handle}}", :to => aspect) alice.post(:status_message, :text => "@{Bob Jones; #{bob.person.diaspora_handle}}", :to => aspect)
end
And /^I mention Alice in the publisher$/ do
alice = User.find_by_email 'alice@alice.alice'
fill_in 'status_message_fake_text', :with => "@{Alice Smith ; #{alice.person.diaspora_handle}}"
end end

View file

@ -0,0 +1,3 @@
Then /^the first post should be a preview$/ do
find(".post_preview .post-content").text.should == first_post_text
end

View file

@ -1,7 +1,7 @@
module PublishingCukeHelpers module PublishingCukeHelpers
def make_post(text) def make_post(text)
fill_in 'status_message_fake_text', :with => text fill_in 'status_message_fake_text', :with => text
click_button :submit find(".creation").click
wait_for_ajax_to_finish wait_for_ajax_to_finish
end end

View file

@ -18,6 +18,10 @@ describe("app.views.Publisher", function() {
it("hides the close button in standalone mode", function() { it("hides the close button in standalone mode", function() {
expect(this.view.$('#hide_publisher').is(':visible')).toBeFalsy(); expect(this.view.$('#hide_publisher').is(':visible')).toBeFalsy();
}); });
it("hides the post preview button in standalone mode", function() {
expect(this.view.$('.post_preview_button').is(':visible')).toBeFalsy();
});
}); });
context("plain publisher", function() { context("plain publisher", function() {
@ -61,6 +65,13 @@ describe("app.views.Publisher", function() {
this.view.clear($.Event()); this.view.clear($.Event());
expect(this.view.close).toHaveBeenCalled(); expect(this.view.close).toHaveBeenCalled();
}) })
it("calls removePostPreview", function(){
spyOn(this.view, "removePostPreview");
this.view.clear($.Event());
expect(this.view.removePostPreview).toHaveBeenCalled();
})
it("clears all textareas", function(){ it("clears all textareas", function(){
_.each(this.view.$("textarea"), function(element){ _.each(this.view.$("textarea"), function(element){