From 6e724fc1d4d34efe680f56c26474bc11a2cad773 Mon Sep 17 00:00:00 2001 From: Steffen van Bergerem Date: Thu, 4 Apr 2013 02:14:49 +0200 Subject: [PATCH] preview posts in stream --- Changelog.md | 1 + .../javascripts/app/views/publisher_view.js | 87 ++++++++++++++++++- app/assets/stylesheets/application.css.sass | 8 ++ app/views/photos/_new_photo.haml | 2 + app/views/shared/_publisher.html.haml | 3 + config/locales/diaspora/en.yml | 1 + features/post_preview.feature | 52 +++++++++++ features/step_definitions/mention_steps.rb | 5 ++ .../step_definitions/post_preview_steps.rb | 3 + features/support/publishing_cuke_helpers.rb | 2 +- .../app/views/publisher_view_spec.js | 11 +++ 11 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 features/post_preview.feature create mode 100644 features/step_definitions/post_preview_steps.rb diff --git a/Changelog.md b/Changelog.md index 5f87019e8..fff3fc383 100644 --- a/Changelog.md +++ b/Changelog.md @@ -127,6 +127,7 @@ by them self. * 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 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 diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index 0da15b333..0c00fc2d7 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -18,6 +18,7 @@ app.views.Publisher = Backbone.View.extend(_.extend( "focus textarea" : "open", "click #hide_publisher" : "clear", "submit form" : "createStatusMessage", + "click .post_preview_button" : "createPostPreview", "click .service_icon": "toggleService", "textchange #status_message_fake_text": "handleTextchange", "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_wrapper = this.$('#publisher_textarea_wrapper'); this.el_submit = this.$('input[type=submit]'); + this.el_preview = this.$('button.post_preview_button'); this.el_photozone = this.$('#photodropzone'); // init mentions plugin @@ -42,10 +44,11 @@ app.views.Publisher = Backbone.View.extend(_.extend( 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) if( this.options.standalone ) { this.$('#hide_publisher').hide(); + this.el_preview.hide(); } // 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 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 text(s) @@ -104,6 +184,9 @@ app.views.Publisher = Backbone.View.extend(_.extend( // close publishing area (CSS) this.close(); + + // remove preview + this.removePostPreview(); // disable submitting this.checkSubmitAvailability(); @@ -137,8 +220,10 @@ app.views.Publisher = Backbone.View.extend(_.extend( checkSubmitAvailability: function() { if( this._submittable() ) { this.el_submit.removeAttr('disabled'); + this.el_preview.removeAttr('disabled'); } else { this.el_submit.attr('disabled','disabled'); + this.el_preview.attr('disabled','disabled'); } }, diff --git a/app/assets/stylesheets/application.css.sass b/app/assets/stylesheets/application.css.sass index d232ee327..c0f9c516a 100644 --- a/app/assets/stylesheets/application.css.sass +++ b/app/assets/stylesheets/application.css.sass @@ -3112,3 +3112,11 @@ body :font-size small :text-align right :margin 5px 2px + +.post_preview + :padding + :top 5px + :border + :bottom 3px solid #3f8fba !important + :background + :color #e8f7ff diff --git a/app/views/photos/_new_photo.haml b/app/views/photos/_new_photo.haml index 868b0a337..8aa2996ed 100644 --- a/app/views/photos/_new_photo.haml +++ b/app/views/photos/_new_photo.haml @@ -30,6 +30,7 @@ onSubmit: function(id, fileName){ $('#file-upload').addClass("loading"); $('#publisher').find("input[type='submit']").attr('disabled','disabled'); + $('#publisher').find("button.post_preview_button").attr('disabled','disabled'); app.publisher.el_wrapper.addClass("with_attachments"); $('#photodropzone').append( @@ -61,6 +62,7 @@ textarea = publisher.find('textarea'); publisher.find("input[type='submit']").removeAttr('disabled'); + publisher.find("button.post_preview_button").removeAttr('disabled'); $('.x').bind('click', function(){ var photo = $(this).closest('.publisher_photo'); diff --git a/app/views/shared/_publisher.html.haml b/app/views/shared/_publisher.html.haml index 90c35a5c0..e99acbfbe 100644 --- a/app/views/shared/_publisher.html.haml +++ b/app/views/shared/_publisher.html.haml @@ -73,6 +73,9 @@ - for aspect in all_aspects = 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 .facebox_content diff --git a/config/locales/diaspora/en.yml b/config/locales/diaspora/en.yml index abc4b2e1d..92984d995 100644 --- a/config/locales/diaspora/en.yml +++ b/config/locales/diaspora/en.yml @@ -789,6 +789,7 @@ en: publisher: posting: "Posting..." share: "Share" + preview: "Preview" post_a_message_to: "Post a message to %{aspect}" make_public: "make public" all: "all" diff --git a/features/post_preview.feature b/features/post_preview.feature new file mode 100644 index 000000000..1f11cadab --- /dev/null +++ b/features/post_preview.feature @@ -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" diff --git a/features/step_definitions/mention_steps.rb b/features/step_definitions/mention_steps.rb index d1f72fbd6..c57af4929 100644 --- a/features/step_definitions/mention_steps.rb +++ b/features/step_definitions/mention_steps.rb @@ -3,4 +3,9 @@ And /^Alice has a post mentioning Bob$/ do bob = User.find_by_email 'bob@bob.bob' aspect = alice.aspects.where(:name => "Besties").first 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 \ No newline at end of file diff --git a/features/step_definitions/post_preview_steps.rb b/features/step_definitions/post_preview_steps.rb new file mode 100644 index 000000000..e7129d73c --- /dev/null +++ b/features/step_definitions/post_preview_steps.rb @@ -0,0 +1,3 @@ +Then /^the first post should be a preview$/ do + find(".post_preview .post-content").text.should == first_post_text +end diff --git a/features/support/publishing_cuke_helpers.rb b/features/support/publishing_cuke_helpers.rb index de447cc7a..2ef2a9243 100644 --- a/features/support/publishing_cuke_helpers.rb +++ b/features/support/publishing_cuke_helpers.rb @@ -1,7 +1,7 @@ module PublishingCukeHelpers def make_post(text) fill_in 'status_message_fake_text', :with => text - click_button :submit + find(".creation").click wait_for_ajax_to_finish end diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index 0e301847c..fd2e51783 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -18,6 +18,10 @@ describe("app.views.Publisher", function() { it("hides the close button in standalone mode", function() { 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() { @@ -61,6 +65,13 @@ describe("app.views.Publisher", function() { this.view.clear($.Event()); 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(){ _.each(this.view.$("textarea"), function(element){