Merge branch 'stable' into develop
This commit is contained in:
commit
3f3148af2c
19 changed files with 144 additions and 66 deletions
|
|
@ -49,6 +49,7 @@ Ruby 2.0 is no longer officially supported.
|
|||
* Added link to diasporafoundation.org to invitation email [#5893](https://github.com/diaspora/diaspora/pull/5893)
|
||||
* Gracefully handle missing `og:url`s [#5926](https://github.com/diaspora/diaspora/pull/5926)
|
||||
* Remove private post content from "also commented" mails [#5931](https://github.com/diaspora/diaspora/pull/5931)
|
||||
* Add a button to follow/unfollow tags to the mobile interface [#5941](https://github.com/diaspora/diaspora/pull/5941)
|
||||
|
||||
# 0.5.0.1
|
||||
|
||||
|
|
|
|||
|
|
@ -12,13 +12,13 @@ Handlebars.registerHelper('imageUrl', function(path){
|
|||
return ImagePaths.get(path);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('urlTo', function(path_helper, id, data){
|
||||
Handlebars.registerHelper("urlTo", function(pathHelper, id, data){
|
||||
if( !data ) {
|
||||
// only one argument given to helper, mangle parameters
|
||||
data = id;
|
||||
return Routes[path_helper+'_path'](data.hash);
|
||||
return Routes[pathHelper](data.hash);
|
||||
}
|
||||
return Routes[path_helper+'_path'](id, data.hash);
|
||||
return Routes[pathHelper](id, data.hash);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('linkToAuthor', function(context, block) {
|
||||
|
|
@ -89,32 +89,32 @@ Handlebars.registerHelper('localTime', function(timestamp) {
|
|||
return new Date(timestamp).toLocaleString();
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('fmtTags', function(tags) {
|
||||
Handlebars.registerHelper("fmtTags", function(tags) {
|
||||
var links = _.map(tags, function(tag) {
|
||||
return '<a class="tag" href="' + Routes.tag_path(tag) + '">' +
|
||||
' #' + tag +
|
||||
'</a>';
|
||||
}).join(' ');
|
||||
return "<a class=\"tag\" href=\"" + Routes.tag(tag) + "\">" +
|
||||
" #" + tag +
|
||||
"</a>";
|
||||
}).join(" ");
|
||||
return new Handlebars.SafeString(links);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('fmtText', function(text) {
|
||||
Handlebars.registerHelper("fmtText", function(text) {
|
||||
return new Handlebars.SafeString(app.helpers.textFormatter(text));
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('isCurrentPage', function(path_helper, id, options){
|
||||
Handlebars.registerHelper("isCurrentPage", function(pathHelper, id, options){
|
||||
var currentPage = "/"+Backbone.history.fragment;
|
||||
if (currentPage === Handlebars.helpers.urlTo(path_helper, id, options.data)) {
|
||||
if (currentPage === Handlebars.helpers.urlTo(pathHelper, id, options.data)) {
|
||||
return options.fn(this);
|
||||
} else {
|
||||
return options.inverse(this);
|
||||
}
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('isCurrentProfilePage', function(id, diaspora_handle, options){
|
||||
var username = diaspora_handle.split("@")[0];
|
||||
return Handlebars.helpers.isCurrentPage('person', id, options) ||
|
||||
Handlebars.helpers.isCurrentPage('user_profile', username, options);
|
||||
Handlebars.registerHelper("isCurrentProfilePage", function(id, diasporaHandle, options){
|
||||
var username = diasporaHandle.split("@")[0];
|
||||
return Handlebars.helpers.isCurrentPage("person", id, options) ||
|
||||
Handlebars.helpers.isCurrentPage("userProfile", username, options);
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('aspectMembershipIndicator', function(contact,in_aspect) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
app.models.Person = Backbone.Model.extend({
|
||||
url: function() {
|
||||
return Routes.person_path(this.get('guid'));
|
||||
return Routes.person(this.get("guid"));
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ app.pages.Contacts = Backbone.View.extend({
|
|||
update: function() {
|
||||
$("#aspect_nav .ui-sortable").removeClass("synced");
|
||||
var data = JSON.stringify({ ordered_aspect_ids: $(this).sortable("toArray", { attribute: "data-aspect-id" }) });
|
||||
$.ajax(Routes.order_aspects_path(),
|
||||
$.ajax(Routes.orderAspects(),
|
||||
{ type: "put", dataType: "text", contentType: "application/json", data: data })
|
||||
.done(function() { $("#aspect_nav .ui-sortable").addClass("synced"); });
|
||||
},
|
||||
|
|
|
|||
|
|
@ -76,11 +76,11 @@ app.pages.Profile = app.views.Base.extend({
|
|||
}
|
||||
|
||||
// a collection is set, this means we want to view photos
|
||||
var route = this.streamCollection ? 'person_photos_path' : 'person_stream_path';
|
||||
var route = this.streamCollection ? "personPhotos" : "personStream";
|
||||
var view = this.streamViewClass ? this.streamViewClass : app.views.Stream;
|
||||
|
||||
app.stream = new app.models.Stream(null, {
|
||||
basePath: Routes[route](app.page.model.get('guid')),
|
||||
basePath: Routes[route](app.page.model.get("guid")),
|
||||
collection: this.streamCollection
|
||||
});
|
||||
app.stream.fetch();
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ app.views.Help = app.views.StaticContentView.extend({
|
|||
this.CHAT_SUBS = {
|
||||
add_contact_roster_a: {
|
||||
toggle_privilege: this.getChatIcons(),
|
||||
contacts_page: this.linkHtml(Routes.contacts_path(), Diaspora.I18n.t('chat.contacts_page'))
|
||||
contacts_page: this.linkHtml(Routes.contacts(), Diaspora.I18n.t("chat.contacts_page"))
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ app.views.NotificationDropdown = app.views.Base.extend({
|
|||
|
||||
getNotifications: function(){
|
||||
var self = this;
|
||||
$.getJSON(Routes.notifications_path(this.getParams()), function(notifications){
|
||||
$.getJSON(Routes.notifications(this.getParams()), function(notifications){
|
||||
$.each(notifications, function(){ self.notifications.push(this); });
|
||||
self.hasMoreNotifs = notifications.length >= self.perPage;
|
||||
if(self.nextPage){ self.nextPage++; }
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ app.views.SinglePostModeration = app.views.Feedback.extend({
|
|||
createParticipation: function (evt) {
|
||||
if(evt) { evt.preventDefault(); }
|
||||
var self = this;
|
||||
$.post(Routes.post_participation_path(this.model.get("id")), {}, function () {
|
||||
$.post(Routes.postParticipation(this.model.get("id")), {}, function () {
|
||||
self.model.set({participation: true});
|
||||
self.render();
|
||||
});
|
||||
|
|
@ -58,7 +58,7 @@ app.views.SinglePostModeration = app.views.Feedback.extend({
|
|||
destroyParticipation: function (evt) {
|
||||
if(evt) { evt.preventDefault(); }
|
||||
var self = this;
|
||||
$.post(Routes.post_participation_path(this.model.get("id")), { _method: "delete" }, function () {
|
||||
$.post(Routes.postParticipation(this.model.get("id")), { _method: "delete" }, function () {
|
||||
self.model.set({participation: false});
|
||||
self.render();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ app.views.StreamPost = app.views.Post.extend({
|
|||
createParticipation: function (evt) {
|
||||
if(evt) { evt.preventDefault(); }
|
||||
that = this;
|
||||
$.post(Routes.post_participation_path(this.model.get("id")), {}, function () {
|
||||
$.post(Routes.postParticipation(this.model.get("id")), {}, function () {
|
||||
that.model.set({participation: true});
|
||||
that.render();
|
||||
});
|
||||
|
|
@ -128,7 +128,7 @@ app.views.StreamPost = app.views.Post.extend({
|
|||
destroyParticipation: function (evt) {
|
||||
if(evt) { evt.preventDefault(); }
|
||||
that = this;
|
||||
$.post(Routes.post_participation_path(this.model.get("id")), { _method: "delete" }, function () {
|
||||
$.post(Routes.postParticipation(this.model.get("id")), { _method: "delete" }, function () {
|
||||
that.model.set({participation: false});
|
||||
that.render();
|
||||
});
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
//= require widgets/timeago
|
||||
//= require mobile/mobile_file_uploader
|
||||
//= require mobile/profile_aspects
|
||||
//= require mobile/tag_following
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
|
|
|
|||
|
|
@ -27,14 +27,14 @@ $(document).ready(function(){
|
|||
|
||||
if(selected.hasClass('selected')) {
|
||||
// remove from aspect
|
||||
var membership_id = selected.data('membership_id');
|
||||
var membershipId = selected.data("membership_id");
|
||||
|
||||
$.ajax({
|
||||
url: Routes.aspect_membership_path(membership_id),
|
||||
type: 'DELETE',
|
||||
dataType: 'json',
|
||||
url: Routes.aspectMembership(membershipId),
|
||||
type: "DELETE",
|
||||
dataType: "json",
|
||||
headers: {
|
||||
'Accept': "application/json, text/javascript, */*; q=0.01"
|
||||
"Accept": "application/json, text/javascript, */*; q=0.01"
|
||||
}
|
||||
}).done(function() {
|
||||
selected.text("– " + Diaspora.I18n.t('aspect_dropdown.mobile_row_unchecked', {name: selected.data('name')}));
|
||||
|
|
@ -50,7 +50,7 @@ $(document).ready(function(){
|
|||
var person_id = $el.data('person-id');
|
||||
|
||||
$.ajax({
|
||||
url: Routes.aspect_memberships_path(),
|
||||
url: Routes.aspectMemberships(),
|
||||
data: JSON.stringify({
|
||||
"person_id": person_id,
|
||||
"aspect_id": parseInt(selected.val(), 10)
|
||||
|
|
|
|||
43
app/assets/javascripts/mobile/tag_following.js
Normal file
43
app/assets/javascripts/mobile/tag_following.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
$(document).ready(function(){
|
||||
$(".tag_following_action").bind("tap click", function(evt){
|
||||
evt.preventDefault();
|
||||
var button = $(this),
|
||||
tagName = button.data("name");
|
||||
|
||||
if(button.hasClass("btn-success")){
|
||||
$.ajax({
|
||||
url: Routes.tagFollowings(),
|
||||
data: JSON.stringify({"name": tagName}),
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
headers: {
|
||||
"Accept": "application/json, text/javascript, */*; q=0.01"
|
||||
},
|
||||
contentType: "application/json; charset=UTF-8"
|
||||
}).done(function(data) {
|
||||
gon.preloads.tagFollowings.push(data);
|
||||
button.removeClass("btn-success").addClass("btn-danger");
|
||||
button.text(Diaspora.I18n.t("stream.tags.stop_following", {tag: tagName}));
|
||||
}).fail(function() {
|
||||
alert(Diaspora.I18n.t("stream.tags.follow_error", {name: "#" + tagName}));
|
||||
});
|
||||
}
|
||||
else if(button.hasClass("btn-danger")){
|
||||
var tagFollowing = _.findWhere(gon.preloads.tagFollowings,{name: tagName});
|
||||
if(!tagFollowing) { return; }
|
||||
$.ajax({
|
||||
url: Routes.tagFollowing(tagFollowing.id),
|
||||
dataType: "json",
|
||||
type: "DELETE",
|
||||
headers: {
|
||||
"Accept": "application/json, text/javascript, */*; q=0.01"
|
||||
}
|
||||
}).done(function() {
|
||||
button.removeClass("btn-danger").addClass("btn-success");
|
||||
button.text(Diaspora.I18n.t("stream.tags.follow", {tag: tagName}));
|
||||
}).fail(function() {
|
||||
alert(Diaspora.I18n.t("stream.tags.stop_following_error", {name: "#" + tagName}));
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
@ -1210,3 +1210,5 @@ select#aspect_ids_ {
|
|||
#app #main h1 {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.tag_following_action { margin: 5px 0 10px 0; }
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
<div class="pull-right">
|
||||
{{#if is_own_profile}}
|
||||
{{!-- can't block myself, so don't check it here --}}
|
||||
<a href="{{urlTo 'edit_profile'}}" id="edit_profile" class="btn btn-primary creation">{{t 'people.edit_my_profile'}}</a>
|
||||
<a href="{{urlTo 'editProfile'}}" id="edit_profile" class="btn btn-primary creation">{{t 'people.edit_my_profile'}}</a>
|
||||
{{else}} {{#if is_blocked}}
|
||||
<a href="#" id="unblock_user_button" class="btn btn-danger">{{t 'people.stop_ignoring'}}</a>
|
||||
{{else}}
|
||||
|
|
@ -31,7 +31,7 @@
|
|||
<div class="description">
|
||||
<i>{{t 'profile.you_have_no_tags'}}</i>
|
||||
<span class="add_tags">
|
||||
<a href="{{urlTo 'edit_profile'}}">{{t 'profile.add_some'}}</a>
|
||||
<a href="{{urlTo 'editProfile'}}">{{t 'profile.add_some'}}</a>
|
||||
</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
@ -74,8 +74,8 @@
|
|||
</a>
|
||||
</li>
|
||||
{{#if show_photos}}
|
||||
<li {{#isCurrentPage 'person_photos' guid}} class="active" {{/isCurrentPage}}>
|
||||
<a href="{{urlTo 'person_photos' guid}}" id="photos_link">
|
||||
<li {{#isCurrentPage 'personPhotos' guid}} class="active" {{/isCurrentPage}}>
|
||||
<a href="{{urlTo 'personPhotos' guid}}" id="photos_link">
|
||||
<i class="entypo picture"></i>
|
||||
{{t 'profile.photos'}}
|
||||
<div class="badge badge-default">{{photos.count}}</div>
|
||||
|
|
@ -83,7 +83,7 @@
|
|||
</li>
|
||||
{{/if}}
|
||||
{{#if show_contacts}}
|
||||
<li {{#isCurrentPage 'person_contacts' guid}} class="active" {{/isCurrentPage}}>
|
||||
<li {{#isCurrentPage 'personContacts' guid}} class="active" {{/isCurrentPage}}>
|
||||
{{#if is_own_profile}}
|
||||
<a href="{{urlTo 'contacts'}}" id="contacts_link">
|
||||
<i class="entypo users"></i>
|
||||
|
|
@ -91,7 +91,7 @@
|
|||
<div class="badge badge-default">{{contacts.count}}</div>
|
||||
</a>
|
||||
{{else}}
|
||||
<a href="{{urlTo 'person_contacts' guid}}" id="contacts_link">
|
||||
<a href="{{urlTo 'personContacts' guid}}" id="contacts_link">
|
||||
<i class="entypo users"></i>
|
||||
{{t 'profile.contacts'}}
|
||||
<div class="badge badge-default">{{contacts.count}}</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,13 @@
|
|||
|
||||
%h1
|
||||
= @stream.display_tag_name
|
||||
- if user_signed_in?
|
||||
- unless tag_followed?
|
||||
.btn.btn-success.tag_following_action{data: {name: @stream.tag_name}}
|
||||
= t(".follow", tag: @stream.tag_name)
|
||||
- else
|
||||
.btn.btn-danger.tag_following_action{data: {name: @stream.tag_name}}
|
||||
= t(".stop_following", tag: @stream.tag_name)
|
||||
|
||||
#main_stream.stream
|
||||
= render 'shared/stream', :posts => @stream.stream_posts
|
||||
|
|
|
|||
4
config/initializers/jsroutes.rb
Normal file
4
config/initializers/jsroutes.rb
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
JsRoutes.setup do |config|
|
||||
config.camel_case = true
|
||||
config.compact = true
|
||||
end
|
||||
|
|
@ -206,6 +206,8 @@ en:
|
|||
follow: "Follow #<%= tag %>"
|
||||
following: "Following #<%= tag %>"
|
||||
stop_following: "Stop following #<%= tag %>"
|
||||
follow_error: "Couldn’t follow <%= name %> :("
|
||||
stop_following_error: "Couldn’t stop following <%= name %> :("
|
||||
|
||||
header:
|
||||
home: "Home"
|
||||
|
|
|
|||
|
|
@ -2,13 +2,31 @@
|
|||
Feature: Interacting with tags
|
||||
|
||||
Background:
|
||||
Given a user with username "alice"
|
||||
And "alice@alice.alice" has a public post with text "Hello! i am #newhere"
|
||||
When I sign in as "alice@alice.alice"
|
||||
Given following users exist:
|
||||
| username |
|
||||
| bob |
|
||||
| alice |
|
||||
And "alice@alice.alice" has a public post with text "Hello! I am #newhere"
|
||||
When I sign in as "bob@bob.bob"
|
||||
And I visit the mobile search page
|
||||
And I fill in the following:
|
||||
| q | #newhere |
|
||||
And I press "Search"
|
||||
Then I should see "Follow #newhere" within ".tag_following_action"
|
||||
|
||||
Scenario: Start and stop following a tag
|
||||
When I click on selector ".tag_following_action"
|
||||
Then I should see "Stop following #newhere" within ".tag_following_action"
|
||||
When I am on the home page
|
||||
Then I should see "Hello! I am #newhere"
|
||||
|
||||
Scenario: Searching for a tag
|
||||
When I visit the mobile search page
|
||||
And I fill in the following:
|
||||
| q | #newhere |
|
||||
And I press "Search"
|
||||
Then I should see "#newhere" within ".ltr"
|
||||
Then I should see "Stop following #newhere" within ".tag_following_action"
|
||||
|
||||
When I click on selector ".tag_following_action"
|
||||
Then I should see "Follow #newhere" within ".tag_following_action"
|
||||
When I am on the home page
|
||||
Then I should not see "Hello! I am #newhere"
|
||||
|
|
|
|||
|
|
@ -1,69 +1,69 @@
|
|||
|
||||
describe("app.models.Person", function() {
|
||||
beforeEach(function() {
|
||||
this.mutual_contact = factory.person({relationship: 'mutual'});
|
||||
this.sharing_contact = factory.person({relationship :'sharing'});
|
||||
this.receiving_contact = factory.person({relationship: 'receiving'});
|
||||
this.blocked_contact = factory.person({relationship: 'blocked', block: {id: 1}});
|
||||
this.mutualContact = factory.person({relationship: "mutual"});
|
||||
this.sharingContact = factory.person({relationship: "sharing"});
|
||||
this.receivingContact = factory.person({relationship: "receiving"});
|
||||
this.blockedContact = factory.person({relationship: "blocked", block: {id: 1}});
|
||||
});
|
||||
|
||||
context("#isSharing", function() {
|
||||
it("indicates if the person is sharing", function() {
|
||||
expect(this.mutual_contact.isSharing()).toBeTruthy();
|
||||
expect(this.sharing_contact.isSharing()).toBeTruthy();
|
||||
expect(this.mutualContact.isSharing()).toBeTruthy();
|
||||
expect(this.sharingContact.isSharing()).toBeTruthy();
|
||||
|
||||
expect(this.receiving_contact.isSharing()).toBeFalsy();
|
||||
expect(this.blocked_contact.isSharing()).toBeFalsy();
|
||||
expect(this.receivingContact.isSharing()).toBeFalsy();
|
||||
expect(this.blockedContact.isSharing()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
context("#isReceiving", function() {
|
||||
it("indicates if the person is receiving", function() {
|
||||
expect(this.mutual_contact.isReceiving()).toBeTruthy();
|
||||
expect(this.receiving_contact.isReceiving()).toBeTruthy();
|
||||
expect(this.mutualContact.isReceiving()).toBeTruthy();
|
||||
expect(this.receivingContact.isReceiving()).toBeTruthy();
|
||||
|
||||
expect(this.sharing_contact.isReceiving()).toBeFalsy();
|
||||
expect(this.blocked_contact.isReceiving()).toBeFalsy();
|
||||
expect(this.sharingContact.isReceiving()).toBeFalsy();
|
||||
expect(this.blockedContact.isReceiving()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
context("#isMutual", function() {
|
||||
it("indicates if we share mutually with the person", function() {
|
||||
expect(this.mutual_contact.isMutual()).toBeTruthy();
|
||||
expect(this.mutualContact.isMutual()).toBeTruthy();
|
||||
|
||||
expect(this.receiving_contact.isMutual()).toBeFalsy();
|
||||
expect(this.sharing_contact.isMutual()).toBeFalsy();
|
||||
expect(this.blocked_contact.isMutual()).toBeFalsy();
|
||||
expect(this.receivingContact.isMutual()).toBeFalsy();
|
||||
expect(this.sharingContact.isMutual()).toBeFalsy();
|
||||
expect(this.blockedContact.isMutual()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
context("#isBlocked", function() {
|
||||
it("indicates whether we blocked the person", function() {
|
||||
expect(this.blocked_contact.isBlocked()).toBeTruthy();
|
||||
expect(this.blockedContact.isBlocked()).toBeTruthy();
|
||||
|
||||
expect(this.mutual_contact.isBlocked()).toBeFalsy();
|
||||
expect(this.receiving_contact.isBlocked()).toBeFalsy();
|
||||
expect(this.sharing_contact.isBlocked()).toBeFalsy();
|
||||
expect(this.mutualContact.isBlocked()).toBeFalsy();
|
||||
expect(this.receivingContact.isBlocked()).toBeFalsy();
|
||||
expect(this.sharingContact.isBlocked()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
context("#block", function() {
|
||||
it("POSTs a block to the server", function() {
|
||||
this.sharing_contact.block();
|
||||
this.sharingContact.block();
|
||||
var request = jasmine.Ajax.requests.mostRecent();
|
||||
|
||||
expect(request.method).toEqual("POST");
|
||||
expect($.parseJSON(request.params).block.person_id).toEqual(this.sharing_contact.id);
|
||||
expect($.parseJSON(request.params).block.person_id).toEqual(this.sharingContact.id);
|
||||
});
|
||||
});
|
||||
|
||||
context("#unblock", function() {
|
||||
it("DELETEs a block from the server", function(){
|
||||
this.blocked_contact.unblock();
|
||||
this.blockedContact.unblock();
|
||||
var request = jasmine.Ajax.requests.mostRecent();
|
||||
|
||||
expect(request.method).toEqual("DELETE");
|
||||
expect(request.url).toEqual(Routes.block_path(this.blocked_contact.get('block').id));
|
||||
expect(request.url).toEqual(Routes.block(this.blockedContact.get("block").id));
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue