* cleanup people_controller#show, add people_controller#stream for json
* introduce new presenters and extend the functionality of the BasePresenter * add a handlebars template for the profile sidebar, render it everytime we need to update * introduce a 'aspect_membership:update' global event
This commit is contained in:
parent
d00d69814e
commit
fba3092c61
19 changed files with 333 additions and 100 deletions
|
|
@ -7,6 +7,7 @@ Handlebars.registerHelper('imageUrl', function(path){
|
|||
});
|
||||
|
||||
Handlebars.registerHelper('linkToPerson', function(context, block) {
|
||||
if( !context ) context = this;
|
||||
var html = "<a href=\"/people/" + context.guid + "\" class=\"author-name ";
|
||||
html += Handlebars.helpers.hovercardable(context);
|
||||
html += "\">";
|
||||
|
|
@ -16,6 +17,22 @@ Handlebars.registerHelper('linkToPerson', function(context, block) {
|
|||
return html
|
||||
});
|
||||
|
||||
// relationship indicator for profile page
|
||||
Handlebars.registerHelper('sharingBadge', function(person) {
|
||||
var i18n_scope = 'people.helper.is_not_sharing';
|
||||
var icon = 'icons-circle';
|
||||
if( person.is_sharing ) {
|
||||
i18n_scope = 'people.helper.is_sharing';
|
||||
icon = 'icons-check_yes_ok';
|
||||
}
|
||||
|
||||
var title = Diaspora.I18n.t(i18n_scope, {name: person.name});
|
||||
var html = '<div class="sharing_message_container" title="'+title+'" data-placement="bottom">'+
|
||||
' <div id="sharing_message" class="'+icon+'"></div>'+
|
||||
'</div>';
|
||||
return html;
|
||||
});
|
||||
|
||||
|
||||
// allow hovercards for users that are not the current user.
|
||||
// returns the html class name used to trigger hovercards.
|
||||
|
|
@ -29,15 +46,17 @@ Handlebars.registerHelper('hovercardable', function(person) {
|
|||
Handlebars.registerHelper('personImage', function(person, size, imageClass) {
|
||||
/* we return here if person.avatar is blank, because this happens when a
|
||||
* user is unauthenticated. we don't know why this happens... */
|
||||
if( _.isUndefined(person.avatar) ) { return }
|
||||
var avatar = person.avatar || person.profile.avatar;
|
||||
if( !avatar ) return;
|
||||
|
||||
var name = ( person.name ) ? person.name : 'avatar';
|
||||
size = ( !_.isString(size) ) ? "small" : size;
|
||||
imageClass = ( !_.isString(imageClass) ) ? size : imageClass;
|
||||
|
||||
return _.template('<img src="<%= src %>" class="avatar <%= img_class %>" title="<%= title %>" />', {
|
||||
'src': person.avatar[size],
|
||||
return _.template('<img src="<%= src %>" class="avatar <%= img_class %>" title="<%= title %>" alt="<%= title %>" />', {
|
||||
'src': avatar[size],
|
||||
'img_class': imageClass,
|
||||
'title': _.escape(person.name)
|
||||
'title': _.escape(name)
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
|||
39
app/assets/javascripts/app/models/person.js
Normal file
39
app/assets/javascripts/app/models/person.js
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
app.models.Person = Backbone.Model.extend({
|
||||
urlRoot: '/people',
|
||||
|
||||
url: function() {
|
||||
return this.urlRoot + '/' + this.get('guid');
|
||||
},
|
||||
|
||||
initialize: function() {
|
||||
if( this.get('profile') )
|
||||
this.profile = new app.models.Profile(this.get('profile'));
|
||||
},
|
||||
|
||||
isSharing: function() {
|
||||
var rel = this.get('relationship');
|
||||
return (rel == 'mutual' || rel == 'sharing');
|
||||
},
|
||||
|
||||
isReceiving: function() {
|
||||
var rel = this.get('relationship');
|
||||
return (rel == 'mutual' || rel == 'receiving');
|
||||
},
|
||||
|
||||
isMutual: function() {
|
||||
return (this.get('relationship') == 'mutual');
|
||||
},
|
||||
|
||||
isBlocked: function() {
|
||||
return (this.get('relationship') == 'blocked');
|
||||
},
|
||||
|
||||
block: function() {
|
||||
var self = this;
|
||||
var block = new app.models.Block({block: {person_id: this.id}});
|
||||
|
||||
// return the jqXHR with Promise interface
|
||||
return block.save()
|
||||
.done(function() { app.events.trigger('person:block:'+self.id); });
|
||||
}
|
||||
});
|
||||
|
|
@ -1,44 +1,47 @@
|
|||
|
||||
// TODO: this view should be model-driven an re-render when it was updated,
|
||||
// instead of changing classes/attributes on elements.
|
||||
app.pages.Profile = Backbone.View.extend({
|
||||
// TODO: update the aspect_membership dropdown, too, every time we render the view...
|
||||
app.pages.Profile = app.views.Base.extend({
|
||||
events: {
|
||||
'click #block_user_button': 'blockPerson'
|
||||
},
|
||||
|
||||
subviews: {
|
||||
'#profile .badge': 'sidebarView'
|
||||
},
|
||||
|
||||
tooltipSelector: '.profile_button div, .sharing_message_container',
|
||||
|
||||
initialize: function(opts) {
|
||||
// cache element references
|
||||
this.el_profile_btns = this.$('#profile_buttons');
|
||||
this.el_sharing_msg = this.$('#sharing_message');
|
||||
if( app.hasPreload('person') )
|
||||
this.model = new app.models.Person(app.parsePreload('person'));
|
||||
|
||||
// init tooltips
|
||||
this.el_profile_btns.find('.profile_button div, .sharin_message_container')
|
||||
.tooltip({placement: 'bottom'});
|
||||
this.model.on('change', this.render, this);
|
||||
|
||||
// respond to global events
|
||||
var person_id = this.$('#profile .avatar:first').data('person_id');
|
||||
app.events.on('person:block:'+person_id, this._markBlocked, this);
|
||||
// bind to global events
|
||||
var id = this.model.get('id');
|
||||
app.events.on('person:block:'+id, this.reload, this);
|
||||
app.events.on('aspect_membership:update', this.reload, this);
|
||||
},
|
||||
|
||||
sidebarView: function() {
|
||||
return new app.views.ProfileSidebar({model: this.model});
|
||||
},
|
||||
|
||||
blockPerson: function(evt) {
|
||||
if( !confirm(Diaspora.I18n.t('ignore_user')) ) return;
|
||||
|
||||
var person_id = $(evt.target).data('person-id');
|
||||
var block = new app.models.Block({block: {person_id: person_id}});
|
||||
block.save()
|
||||
.done(function() { app.events.trigger('person:block:'+person_id); })
|
||||
.fail(function() { Diaspora.page.flashMessages.render({
|
||||
var block = this.model.block();
|
||||
block.fail(function() {
|
||||
Diaspora.page.flashMessages.render({
|
||||
success: false,
|
||||
notice: Diaspora.I18n.t('ignore_failed')
|
||||
}); });
|
||||
});
|
||||
});
|
||||
|
||||
return false;
|
||||
},
|
||||
|
||||
_markBlocked: function() {
|
||||
this.el_profile_btns.attr('class', 'blocked');
|
||||
this.el_sharing_msg.attr('class', 'icons-circle');
|
||||
|
||||
this.el_profile_btns.find('.profile_button, .white_bar').remove();
|
||||
reload: function() {
|
||||
this.model.fetch();
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -54,10 +54,11 @@ app.Router = Backbone.Router.extend({
|
|||
renderPage : function(pageConstructor){
|
||||
app.page && app.page.unbind && app.page.unbind(); //old page might mutate global events $(document).keypress, so unbind before creating
|
||||
app.page = pageConstructor(); //create new page after the world is clean (like that will ever happen)
|
||||
app.page.render();
|
||||
|
||||
if( !$.contains(document, app.page.el) ) {
|
||||
// view element isn't already attached to the DOM, insert it
|
||||
$("#container").empty().append(app.page.render().el);
|
||||
$("#container").empty().append(app.page.el);
|
||||
}
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ app.views.Base = Backbone.View.extend({
|
|||
this.template = HandlebarsTemplates[this.templateName+"_tpl"]
|
||||
if(!this.template) {
|
||||
console.log(this.templateName ? ("no template for " + this.templateName) : "no templateName specified")
|
||||
return;
|
||||
}
|
||||
|
||||
this.$el
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ app.views.AspectMembershipBlueprint = Backbone.View.extend({
|
|||
// -> addMembership
|
||||
// -> removeMembership
|
||||
_clickHandler: function(evt) {
|
||||
var promise = null;
|
||||
this.list_item = $(evt.target);
|
||||
this.dropdown = this.list_item.parent();
|
||||
|
||||
|
|
@ -30,13 +31,18 @@ app.views.AspectMembershipBlueprint = Backbone.View.extend({
|
|||
|
||||
if( this.list_item.is('.selected') ) {
|
||||
var membership_id = this.list_item.data('membership_id');
|
||||
this.removeMembership(membership_id);
|
||||
promise = this.removeMembership(membership_id);
|
||||
} else {
|
||||
var aspect_id = this.list_item.data('aspect_id');
|
||||
var person_id = this.dropdown.data('person_id');
|
||||
this.addMembership(person_id, aspect_id);
|
||||
promise = this.addMembership(person_id, aspect_id);
|
||||
}
|
||||
|
||||
promise && promise.always(function() {
|
||||
// trigger a global event
|
||||
app.events.trigger('aspect_membership:update');
|
||||
});
|
||||
|
||||
return false; // stop the event
|
||||
},
|
||||
|
||||
|
|
@ -57,7 +63,7 @@ app.views.AspectMembershipBlueprint = Backbone.View.extend({
|
|||
this._displayError('aspect_dropdown.error');
|
||||
}, this);
|
||||
|
||||
aspect_membership.save();
|
||||
return aspect_membership.save();
|
||||
},
|
||||
|
||||
_successSaveCb: function(aspect_membership) {
|
||||
|
|
@ -100,7 +106,7 @@ app.views.AspectMembershipBlueprint = Backbone.View.extend({
|
|||
this._displayError('aspect_dropdown.error_remove');
|
||||
}, this);
|
||||
|
||||
aspect_membership.destroy();
|
||||
return aspect_membership.destroy();
|
||||
},
|
||||
|
||||
_successDestroyCb: function(aspect_membership) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({
|
|||
// -> addMembership
|
||||
// -> removeMembership
|
||||
_clickHandler: function(evt) {
|
||||
var promise = null;
|
||||
this.list_item = $(evt.target).closest('li.aspect_selector');
|
||||
this.dropdown = this.list_item.parent();
|
||||
|
||||
|
|
@ -30,13 +31,18 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({
|
|||
|
||||
if( this.list_item.is('.selected') ) {
|
||||
var membership_id = this.list_item.data('membership_id');
|
||||
this.removeMembership(membership_id);
|
||||
promise = this.removeMembership(membership_id);
|
||||
} else {
|
||||
var aspect_id = this.list_item.data('aspect_id');
|
||||
var person_id = this.dropdown.data('person_id');
|
||||
this.addMembership(person_id, aspect_id);
|
||||
promise = this.addMembership(person_id, aspect_id);
|
||||
}
|
||||
|
||||
promise && promise.always(function() {
|
||||
// trigger a global event
|
||||
app.events.trigger('aspect_membership:update');
|
||||
});
|
||||
|
||||
return false; // stop the event
|
||||
},
|
||||
|
||||
|
|
@ -57,7 +63,7 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({
|
|||
this._displayError('aspect_dropdown.error');
|
||||
}, this);
|
||||
|
||||
aspect_membership.save();
|
||||
return aspect_membership.save();
|
||||
},
|
||||
|
||||
_successSaveCb: function(aspect_membership) {
|
||||
|
|
@ -99,7 +105,7 @@ app.views.AspectMembership = app.views.AspectsDropdown.extend({
|
|||
this._displayError('aspect_dropdown.error_remove');
|
||||
}, this);
|
||||
|
||||
aspect_membership.destroy();
|
||||
return aspect_membership.destroy();
|
||||
},
|
||||
|
||||
_successDestroyCb: function(aspect_membership) {
|
||||
|
|
|
|||
18
app/assets/javascripts/app/views/profile_sidebar_view.js
Normal file
18
app/assets/javascripts/app/views/profile_sidebar_view.js
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
app.views.ProfileSidebar = app.views.Base.extend({
|
||||
templateName: 'profile_sidebar',
|
||||
|
||||
presenter: function() {
|
||||
return _.extend({}, this.defaultPresenter(), {
|
||||
do_profile_btns: this._shouldDoProfileBtns(),
|
||||
is_sharing: this.model.isSharing(),
|
||||
is_receiving: this.model.isReceiving(),
|
||||
is_mutual: this.model.isMutual(),
|
||||
is_not_blocked: !this.model.isBlocked()
|
||||
});
|
||||
},
|
||||
|
||||
_shouldDoProfileBtns: function() {
|
||||
return (app.currentUser.authenticated() && !this.model.get('is_own_profile'));
|
||||
},
|
||||
});
|
||||
|
|
@ -44,7 +44,7 @@
|
|||
width: 50px;
|
||||
}
|
||||
}
|
||||
.only_sharing {
|
||||
.sharing {
|
||||
background-color: rgb(142, 222, 61);
|
||||
.profile_button {
|
||||
width: 150px;
|
||||
|
|
|
|||
36
app/assets/templates/profile_sidebar_tpl.jst.hbs
Normal file
36
app/assets/templates/profile_sidebar_tpl.jst.hbs
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
<div class="profile_photo">
|
||||
{{#linkToPerson this}}
|
||||
{{{personImage this "l"}}}
|
||||
{{/linkToPerson}}
|
||||
</div>
|
||||
|
||||
{{#if do_profile_btns}}
|
||||
<div id="profile_buttons" class="{{relationship}}">
|
||||
{{{sharingBadge this}}}
|
||||
|
||||
{{#if is_receiving}}
|
||||
<div class="profile_button">
|
||||
<a href="" rel="facebox">
|
||||
<div id="mention_button" class="icons-mention" title="{{t 'people.mention'}}" data-placement="bottom"></div>
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if is_mutual}}
|
||||
<div class="profile_button">
|
||||
<a href="" rel="facebox">
|
||||
<div id="message_button" class="icons-message" title="{{t 'people.message'}}" data-placement="bottom"></div>
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if is_not_blocked}}
|
||||
<div class="profile_button">
|
||||
<a href="#" rel="nofollow">
|
||||
<div id="block_user_button" class="icons-ignoreuser block_user" title="{{t 'ignore'}}" data-placement="bottom"></div>
|
||||
</a>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
@ -76,18 +76,20 @@ class PeopleController < ApplicationController
|
|||
def show
|
||||
@person = Person.find_from_guid_or_username(params)
|
||||
|
||||
# view this profile on the home pod, if you don't want to sign in...
|
||||
authenticate_user! if remote_profile_with_no_user_session?
|
||||
raise Diaspora::AccountClosed if @person.closed_account?
|
||||
|
||||
mark_corresponding_notifications_read if user_signed_in?
|
||||
|
||||
@post_type = :all
|
||||
@aspect = :profile
|
||||
@stream = Stream::Person.new(current_user, @person, :max_time => max_time)
|
||||
@aspect = :profile # what does this do?
|
||||
@post_type = :all # for mobile
|
||||
@person_json = PersonPresenter.new(@person, current_user).full_hash_with_profile
|
||||
|
||||
respond_to do |format|
|
||||
format.all do
|
||||
@profile = @person.profile
|
||||
@photos = photos_from(@person)
|
||||
|
||||
unless params[:format] == "json" # hovercard
|
||||
if current_user
|
||||
@block = current_user.blocks.where(:person_id => @person.id).first
|
||||
@contact = current_user.contact_for(@person)
|
||||
|
|
@ -98,14 +100,27 @@ class PeopleController < ApplicationController
|
|||
@contact ||= Contact.new
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.all do
|
||||
gon.preloads[:person] = @person_json
|
||||
respond_with @person, :locals => {:post_type => :all}
|
||||
end
|
||||
|
||||
format.json { render :json => @stream.stream_posts.map { |p| LastThreeCommentsDecorator.new(PostPresenter.new(p, current_user)) }}
|
||||
format.json { render :json => @person_json }
|
||||
end
|
||||
end
|
||||
|
||||
def stream
|
||||
@person = Person.find_from_guid_or_username(params)
|
||||
|
||||
authenticate_user! if remote_profile_with_no_user_session?
|
||||
raise Diaspora::AccountClosed if @person.closed_account?
|
||||
|
||||
respond_to do |format|
|
||||
format.all { redirect_to person_path(@person) }
|
||||
format.json do
|
||||
@stream = Stream::Person.new(current_user, @person, max_time: max_time)
|
||||
render json: @stream.stream_posts.map { |p| LastThreeCommentsDecorator.new(PostPresenter.new(p, current_user)) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ module PeopleHelper
|
|||
elsif contact.mutual?
|
||||
'mutual'
|
||||
elsif contact.sharing?
|
||||
'only_sharing'
|
||||
'sharing'
|
||||
elsif contact.receiving?
|
||||
'receiving'
|
||||
else
|
||||
|
|
|
|||
12
app/presenters/avatar_presenter.rb
Normal file
12
app/presenters/avatar_presenter.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
class AvatarPresenter < BasePresenter
|
||||
|
||||
DEFAULT_IMAGE = ActionController::Base.helpers.image_path('user/default.png')
|
||||
|
||||
def base_hash
|
||||
{ s: image_url_small || DEFAULT_IMAGE,
|
||||
m: image_url_medium || DEFAULT_IMAGE,
|
||||
l: image_url || DEFAULT_IMAGE
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -1,5 +1,29 @@
|
|||
class BasePresenter
|
||||
def self.as_collection(collection)
|
||||
collection.map{|object| self.new(object).as_json}
|
||||
attr_reader :current_user
|
||||
|
||||
class << self
|
||||
def new(*args)
|
||||
return NilPresenter.new if args[0].nil?
|
||||
super *args
|
||||
end
|
||||
|
||||
def as_collection(collection, method=:as_json, *args)
|
||||
collection.map{|object| self.new(object, *args).send(method) }
|
||||
end
|
||||
end
|
||||
|
||||
def initialize(presentable, curr_user=nil)
|
||||
@presentable = presentable
|
||||
@current_user = curr_user
|
||||
end
|
||||
|
||||
def method_missing(method, *args)
|
||||
@presentable.send(method, *args) if @presentable.respond_to?(method)
|
||||
end
|
||||
|
||||
class NilPresenter
|
||||
def method_missing(method, *args)
|
||||
nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,33 +1,64 @@
|
|||
class PersonPresenter
|
||||
def initialize(person, current_user = nil)
|
||||
@person = person
|
||||
@current_user = current_user
|
||||
class PersonPresenter < BasePresenter
|
||||
def base_hash
|
||||
{ id: id,
|
||||
guid: guid,
|
||||
name: name,
|
||||
diaspora_id: diaspora_handle
|
||||
}
|
||||
end
|
||||
|
||||
def full_hash
|
||||
base_hash.merge({
|
||||
relationship: relationship,
|
||||
is_own_profile: own_profile?
|
||||
})
|
||||
end
|
||||
|
||||
def full_hash_with_avatar
|
||||
full_hash.merge({avatar: AvatarPresenter.new(profile).base_hash})
|
||||
end
|
||||
|
||||
def full_hash_with_profile
|
||||
full_hash.merge({profile: ProfilePresenter.new(profile).full_hash})
|
||||
end
|
||||
|
||||
def as_json(options={})
|
||||
attrs = @person.as_api_response(:backbone).merge(
|
||||
{
|
||||
:is_own_profile => is_own_profile
|
||||
})
|
||||
attrs = full_hash_with_avatar
|
||||
|
||||
if is_own_profile || person_is_following_current_user
|
||||
if own_profile? || person_is_following_current_user
|
||||
attrs.merge!({
|
||||
:location => @person.location,
|
||||
:birthday => @person.formatted_birthday,
|
||||
:bio => @person.bio
|
||||
:location => @presentable.location,
|
||||
:birthday => @presentable.formatted_birthday,
|
||||
:bio => @presentable.bio
|
||||
})
|
||||
end
|
||||
|
||||
attrs
|
||||
end
|
||||
|
||||
def is_own_profile
|
||||
@current_user.try(:person) == @person
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def own_profile?
|
||||
current_user.try(:person) == @presentable
|
||||
end
|
||||
|
||||
def relationship
|
||||
contact = current_user.contact_for(@presentable)
|
||||
|
||||
is_blocked = current_user.blocks.where(person_id: id).limit(1).any?
|
||||
is_mutual = contact ? contact.mutual? : false
|
||||
is_sharing = contact ? contact.sharing? : false
|
||||
is_receiving = contact ? contact.receiving? : false
|
||||
|
||||
if is_blocked then :blocked
|
||||
elsif is_mutual then :mutual
|
||||
elsif is_sharing then :sharing
|
||||
elsif is_receiving then :receiving
|
||||
else :not_sharing
|
||||
end
|
||||
end
|
||||
|
||||
def person_is_following_current_user
|
||||
@person.shares_with(@current_user)
|
||||
@presentable.shares_with(@current_user)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
18
app/presenters/profile_presenter.rb
Normal file
18
app/presenters/profile_presenter.rb
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
class ProfilePresenter < BasePresenter
|
||||
def base_hash
|
||||
{ id: id,
|
||||
tags: tag_string,
|
||||
bio: bio,
|
||||
location: location,
|
||||
gender: gender,
|
||||
birthday: formatted_birthday,
|
||||
searchable: searchable
|
||||
}
|
||||
end
|
||||
|
||||
def full_hash
|
||||
base_hash.merge({
|
||||
avatar: AvatarPresenter.new(@presentable).base_hash,
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
-# the COPYRIGHT file.
|
||||
|
||||
#profile
|
||||
.badge
|
||||
.profile_photo
|
||||
= person_image_link(person, :size => :thumb_large, :to => :photos)
|
||||
|
||||
|
|
@ -26,9 +27,6 @@
|
|||
.profile_button
|
||||
= link_to content_tag(:div, nil, :class => 'icons-ignoreuser block_user', :title => t('ignore'), :id => 'block_user_button', :data => { :person_id => @person.id }), '#', :rel => "nofollow" if @block.blank?
|
||||
|
||||
|
||||
%br
|
||||
|
||||
-if contact.sharing? || person == current_user.person
|
||||
%ul#profile_information
|
||||
|
||||
|
|
|
|||
|
|
@ -115,6 +115,11 @@ en:
|
|||
wasnt_that_interesting: "OK, I suppose #<%= tagName %> wasn't all that interesting..."
|
||||
people:
|
||||
not_found: "and no one was found..."
|
||||
mention: "Mention"
|
||||
message: "Message"
|
||||
helper:
|
||||
is_sharing: "<%= name %> is sharing with you"
|
||||
is_not_sharing: "<%= name %> is not sharing with you"
|
||||
|
||||
conversation:
|
||||
participants: "Participants"
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ Diaspora::Application.routes.draw do
|
|||
resources :photos
|
||||
get :contacts
|
||||
get "aspect_membership_button" => :aspect_membership_dropdown, :as => "aspect_membership_button"
|
||||
get :stream
|
||||
get :hovercard
|
||||
|
||||
member do
|
||||
|
|
|
|||
Loading…
Reference in a new issue