diff --git a/Changelog.md b/Changelog.md index b3b9fd1c6..cec94dd94 100644 --- a/Changelog.md +++ b/Changelog.md @@ -95,6 +95,7 @@ This maintenance is not enabled by default. Podmins can enable it by for example * Infinite scrolling in the notifications dropdown [#5237](https://github.com/diaspora/diaspora/pull/5237) * Maintenance feature to automatically expire inactive accounts [#5288](https://github.com/diaspora/diaspora/pull/5288) * Add LibreJS markers to JavaScript [5320](https://github.com/diaspora/diaspora/pull/5320) +* Ask for confirmation when leaving a submittable publisher [#5309](https://github.com/diaspora/diaspora/pull/5309) # 0.4.1.2 diff --git a/app/assets/javascripts/app/views/publisher_view.js b/app/assets/javascripts/app/views/publisher_view.js index 8fcca9316..a79db2cfc 100644 --- a/app/assets/javascripts/app/views/publisher_view.js +++ b/app/assets/javascripts/app/views/publisher_view.js @@ -48,6 +48,10 @@ app.views.Publisher = Backbone.View.extend({ // init autoresize plugin this.el_input.autoResize({ 'extraSpace' : 10, 'maxHeight' : Infinity }); + // if there is data in the publisher we ask for a confirmation + // before the user is able to leave the page + $(window).on('beforeunload', _.bind(this._beforeUnload, this)); + // sync textarea content if( this.el_hiddenInput.val() == "" ) { this.el_hiddenInput.val( this.el_input.val() ); @@ -77,14 +81,14 @@ app.views.Publisher = Backbone.View.extend({ this.close(); this.showSpinner(true); }); - + // open publisher on post error this.on('publisher:error', function() { this.open(); this.showSpinner(false); }); - // resetting the poll view + // resetting the poll view this.on('publisher:sync', function() { this.view_poll_creator.render(); }); @@ -159,7 +163,7 @@ app.views.Publisher = Backbone.View.extend({ if(evt){ evt.preventDefault(); } // Auto-adding a poll answer always leaves an empty box when the user starts - // typing in the last box. We'll delete the last one to avoid submitting an + // typing in the last box. We'll delete the last one to avoid submitting an // empty poll answer and failing validation. this.view_poll_creator.removeLastAnswer(); @@ -378,7 +382,7 @@ app.views.Publisher = Backbone.View.extend({ // enable input this.setInputEnabled(true); - + // enable buttons this.setButtonsEnabled(true); @@ -428,7 +432,7 @@ app.views.Publisher = Backbone.View.extend({ else this.$('#publisher_spinner').addClass('hidden'); }, - + checkSubmitAvailability: function() { if( this._submittable() ) { this.setButtonsEnabled(true); @@ -472,8 +476,15 @@ app.views.Publisher = Backbone.View.extend({ this.el_input.mentionsInput("val", function(value){ self.el_hiddenInput.val(value); }); - } + }, + _beforeUnload: function(e) { + if(this._submittable()){ + var confirmationMessage = Diaspora.I18n.t("confirm_unload"); + (e || window.event).returnValue = confirmationMessage; //Gecko + IE + return confirmationMessage; //Webkit, Safari, Chrome, etc. + } + } }); // jQuery helper for serializing a
into JSON diff --git a/app/views/status_messages/new.html.haml b/app/views/status_messages/new.html.haml index 1e6008944..20ae77532 100644 --- a/app/views/status_messages/new.html.haml +++ b/app/views/status_messages/new.html.haml @@ -14,6 +14,7 @@ app.publisher.open(); $("#publisher").bind('ajax:success', function(){ $("#mentionModal").modal('hide'); + app.publisher.clear(); location.reload(); }); }); diff --git a/config/locales/javascript/javascript.en.yml b/config/locales/javascript/javascript.en.yml index 57b5da00b..78fdc4533 100644 --- a/config/locales/javascript/javascript.en.yml +++ b/config/locales/javascript/javascript.en.yml @@ -6,6 +6,7 @@ en: javascripts: confirm_dialog: "Are you sure?" + confirm_unload: "Please confirm that you want to leave this page - data you have entered won't be saved." delete: "Delete" ignore: "Ignore" report: diff --git a/features/desktop/connects_users.feature b/features/desktop/connects_users.feature index e90c5cbda..8a5902efc 100644 --- a/features/desktop/connects_users.feature +++ b/features/desktop/connects_users.feature @@ -16,7 +16,8 @@ Feature: following and being followed And I fill in the following: | status_message_fake_text | I am following you | And I press "Share" - Then I sign out + Then I should see "I am following you" within "#main_stream" + And I sign out Scenario: seeing a follower's posts on their profile page, but not in your stream When I sign in as "alice@alice.alice" @@ -35,6 +36,7 @@ Feature: following and being followed And I press the first ".toggle" within "#publisher" And I press the first ".public" within "#publisher" And I press "Share" + Then I should see "I am ALICE" within "#main_stream" And I sign out When I sign in as "bob@bob.bob" diff --git a/features/desktop/keyboard_navigation.feature b/features/desktop/keyboard_navigation.feature index e92047fd2..384d7959b 100644 --- a/features/desktop/keyboard_navigation.feature +++ b/features/desktop/keyboard_navigation.feature @@ -21,6 +21,7 @@ Feature: Keyboard navigation Given I expand the publisher When I press the "J" key in the publisher Then post 2 should be highlighted + And I close the publisher Scenario: navigate upwards When I am on the home page diff --git a/features/desktop/mentions.feature b/features/desktop/mentions.feature index 5ed5ce6a6..8e9433c45 100644 --- a/features/desktop/mentions.feature +++ b/features/desktop/mentions.feature @@ -29,7 +29,6 @@ Feature: Mentions | status_message_fake_text | @Bo | And I click on the first user in the mentions dropdown list And I press "Share" - And I follow "Bob Jones" + Then I should see "Bob Jones" within ".stream_element" + When I follow "Bob Jones" Then I should see "Bob Jones" - - diff --git a/features/desktop/mentions_from_profile_page.feature b/features/desktop/mentions_from_profile_page.feature index 962e8c5e7..9a0f1822e 100644 --- a/features/desktop/mentions_from_profile_page.feature +++ b/features/desktop/mentions_from_profile_page.feature @@ -26,6 +26,7 @@ Feature: mentioning a contact from their profile page And I want to mention her from the profile And I append "I am eating a yogurt" to the publisher And I press "Share" in the mention modal + Then I should see a flash message indicating success When I am on the aspects page And I follow "PostingTo" within "#aspects_list" Then I should see "I am eating a yogurt" @@ -42,6 +43,7 @@ Feature: mentioning a contact from their profile page And I press the aspect dropdown in the mention modal And I append "I am eating a yogurt" to the publisher And I press "Share" in the mention modal + Then I should see a flash message indicating success When I am on the aspects page And I select only "PostingTo" aspect diff --git a/features/desktop/post_preview.feature b/features/desktop/post_preview.feature index b6b4bf15c..7513d6203 100644 --- a/features/desktop/post_preview.feature +++ b/features/desktop/post_preview.feature @@ -48,12 +48,14 @@ Feature: preview posts in the stream 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" + And I close the publisher 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" + And I confirm the alert Then I should see "Alice Smith" Scenario: preview a post on tag page @@ -67,6 +69,7 @@ Feature: preview posts in the stream And I press "Preview" Then "This preview rocks" should be post 1 And the first post should be a preview + And I close the publisher Scenario: preview a post with the poll Given I expand the publisher @@ -82,3 +85,4 @@ Feature: preview posts in the stream And I press "Preview" Then I should see a ".poll_form" within ".stream_element" And I should see a "form" within ".stream_element" + And I close the publisher diff --git a/features/desktop/posts_from_main_page.feature b/features/desktop/posts_from_main_page.feature index fd829e4eb..c42cc9453 100644 --- a/features/desktop/posts_from_main_page.feature +++ b/features/desktop/posts_from_main_page.feature @@ -86,7 +86,8 @@ Feature: posting from the main page And I attach "spec/fixtures/button.png" to the publisher Then I should see an uploaded image within the photo drop zone When I press "Share" - And I go to the aspects page + Then I should see a "img" within ".stream_element div.photo_attachments" + When I go to the aspects page Then I should see a "img" within ".stream_element div.photo_attachments" When I log out And I sign in as "alice@alice.alice" @@ -108,6 +109,7 @@ Feature: posting from the main page And I click to delete the first uploaded photo Then I should not see an uploaded image within the photo drop zone And the publisher should be expanded + And I close the publisher Scenario: back out of uploading a picture when another has been attached Given I expand the publisher @@ -118,6 +120,7 @@ Feature: posting from the main page And I click to delete the first uploaded photo Then I should see an uploaded image within the photo drop zone And the publisher should be expanded + And I close the publisher @wip Scenario: hide a contact's post diff --git a/features/desktop/posts_from_profile_page.feature b/features/desktop/posts_from_profile_page.feature index 96ee0404a..ed85d3eb9 100644 --- a/features/desktop/posts_from_profile_page.feature +++ b/features/desktop/posts_from_profile_page.feature @@ -48,3 +48,4 @@ Feature: posting from own profile page And I attach "spec/fixtures/button.png" to the publisher And I click to delete the first uploaded photo Then I should not see an uploaded image within the photo drop zone + And I close the publisher diff --git a/features/desktop/profile_photos.feature b/features/desktop/profile_photos.feature index 275e31b32..324e1efe5 100644 --- a/features/desktop/profile_photos.feature +++ b/features/desktop/profile_photos.feature @@ -13,6 +13,7 @@ Feature: show photos And I have turned off jQuery effects And I attach the file "spec/fixtures/button.png" to hidden "file" within "#file-upload" And I press "Share" + Then I should see a "img" within ".stream_element div.photo_attachments" Scenario: see my own photos When I am on "robert@grimm.grimm"'s page diff --git a/features/step_definitions/custom_web_steps.rb b/features/step_definitions/custom_web_steps.rb index a25267daa..bc1ed8e7c 100644 --- a/features/step_definitions/custom_web_steps.rb +++ b/features/step_definitions/custom_web_steps.rb @@ -64,6 +64,10 @@ And /^I expand the publisher$/ do click_publisher end +And /^I close the publisher$/ do + find("#publisher #hide_publisher").click +end + Then /^the publisher should be expanded$/ do find("#publisher")["class"].should_not include("closed") end diff --git a/features/step_definitions/modal_steps.rb b/features/step_definitions/modal_steps.rb new file mode 100644 index 000000000..f672d9f03 --- /dev/null +++ b/features/step_definitions/modal_steps.rb @@ -0,0 +1,3 @@ +Then /I should see the mention modal/ do + step %{I should see a "#mentionModal.in"} +end diff --git a/spec/javascripts/app/views/publisher_view_spec.js b/spec/javascripts/app/views/publisher_view_spec.js index 87eda3116..a77a4c525 100644 --- a/spec/javascripts/app/views/publisher_view_spec.js +++ b/spec/javascripts/app/views/publisher_view_spec.js @@ -176,6 +176,32 @@ describe("app.views.Publisher", function() { expect(submitCallback).toHaveBeenCalled(); expect($(this.view.el)).not.toHaveClass("closed"); }) + }); + + describe("_beforeUnload", function(){ + beforeEach(function(){ + Diaspora.I18n.load({ confirm_unload: "Please confirm that you want to leave this page - data you have entered won't be saved."}); + }); + + it("calls _submittable", function(){ + spyOn(this.view, "_submittable"); + $(window).trigger('beforeunload'); + expect(this.view._submittable).toHaveBeenCalled(); + }); + + it("returns a confirmation if the publisher is submittable", function(){ + spyOn(this.view, "_submittable").and.returnValue(true); + var e = $.Event(); + expect(this.view._beforeUnload(e)).toBe(Diaspora.I18n.t('confirm_unload')); + expect(e.returnValue).toBe(Diaspora.I18n.t('confirm_unload')); + }); + + it("doesn't ask for a confirmation if the publisher isn't submittable", function(){ + spyOn(this.view, "_submittable").and.returnValue(false); + var e = $.Event(); + expect(this.view._beforeUnload(e)).toBe(undefined); + expect(e.returnValue).toBe(undefined); + }); }) }); @@ -280,7 +306,7 @@ describe("app.views.Publisher", function() { // visibility icon is set to the lock icon expect(this.visibility_icon.hasClass('globe')).toBeFalsy(); expect(this.visibility_icon.hasClass('lock')).toBeTruthy(); - + // click on public this.radio_els.first().trigger('click'); // public is selected, "all aspects" is deselected @@ -293,10 +319,10 @@ describe("app.views.Publisher", function() { // visibility icon is set to the globe icon expect(this.visibility_icon.hasClass('globe')).toBeTruthy(); expect(this.visibility_icon.hasClass('lock')).toBeFalsy(); - + // click on "all aspects" this.radio_els.last().trigger('click'); - // public is deselected, "all aspects" is selected + // public is deselected, "all aspects" is selected expect(this.radio_els.first().hasClass('selected')).toBeFalsy(); expect(this.radio_els.last().hasClass('selected')).toBeTruthy(); // the aspects are deselected @@ -305,7 +331,7 @@ describe("app.views.Publisher", function() { }); // visibility icon is set to the lock icon expect(this.visibility_icon.hasClass('globe')).toBeFalsy(); - expect(this.visibility_icon.hasClass('lock')).toBeTruthy(); + expect(this.visibility_icon.hasClass('lock')).toBeTruthy(); }); describe("hidden form elements", function(){