Merge pull request #5473 from svbergerem/contacts-backbonejs
Port contacts page to backbonejs
This commit is contained in:
commit
f20020f06b
35 changed files with 751 additions and 394 deletions
|
|
@ -84,6 +84,7 @@ diaspora.yml file**. The existing settings from 0.4.x and before will not work a
|
||||||
* Make sure conversations without any visibilities left are deleted [#5478](https://github.com/diaspora/diaspora/pull/5478)
|
* Make sure conversations without any visibilities left are deleted [#5478](https://github.com/diaspora/diaspora/pull/5478)
|
||||||
* Change tooltip for delete button in conversations view [#5477](https://github.com/diaspora/diaspora/pull/5477)
|
* Change tooltip for delete button in conversations view [#5477](https://github.com/diaspora/diaspora/pull/5477)
|
||||||
* Replace a modifier-rescue with a specific rescue [#5491](https://github.com/diaspora/diaspora/pull/5491)
|
* Replace a modifier-rescue with a specific rescue [#5491](https://github.com/diaspora/diaspora/pull/5491)
|
||||||
|
* Port contacts page to backbone [#5473](https://github.com/diaspora/diaspora/pull/5473)
|
||||||
|
|
||||||
## Bug fixes
|
## Bug fixes
|
||||||
* orca cannot see 'Add Contact' button [#5158](https://github.com/diaspora/diaspora/pull/5158)
|
* orca cannot see 'Add Contact' button [#5158](https://github.com/diaspora/diaspora/pull/5158)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
|
app.collections.AspectMemberships = Backbone.Collection.extend({
|
||||||
|
model: app.models.AspectMembership
|
||||||
|
})
|
||||||
|
// @license-end
|
||||||
21
app/assets/javascripts/app/collections/contacts.js
Normal file
21
app/assets/javascripts/app/collections/contacts.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
|
app.collections.Contacts = Backbone.Collection.extend({
|
||||||
|
model: app.models.Contact,
|
||||||
|
|
||||||
|
comparator : function(con1, con2) {
|
||||||
|
if( !con1.person || !con2.person ) return 1;
|
||||||
|
|
||||||
|
if(app.aspect) {
|
||||||
|
var inAspect1 = con1.inAspect(app.aspect.get('id'));
|
||||||
|
var inAspect2 = con2.inAspect(app.aspect.get('id'));
|
||||||
|
if( inAspect1 && !inAspect2 ) return -1;
|
||||||
|
if( !inAspect1 && inAspect2 ) return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
var n1 = con1.person.get('name');
|
||||||
|
var n2 = con2.person.get('name');
|
||||||
|
return n1.localeCompare(n2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// @license-end
|
||||||
|
|
@ -21,7 +21,7 @@ Handlebars.registerHelper('urlTo', function(path_helper, id, data){
|
||||||
return Routes[path_helper+'_path'](id, data.hash);
|
return Routes[path_helper+'_path'](id, data.hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
Handlebars.registerHelper('linkToPerson', function(context, block) {
|
Handlebars.registerHelper('linkToAuthor', function(context, block) {
|
||||||
if( !context ) context = this;
|
if( !context ) context = this;
|
||||||
var html = "<a href=\"/people/" + context.guid + "\" class=\"author-name ";
|
var html = "<a href=\"/people/" + context.guid + "\" class=\"author-name ";
|
||||||
html += Handlebars.helpers.hovercardable(context);
|
html += Handlebars.helpers.hovercardable(context);
|
||||||
|
|
@ -32,6 +32,15 @@ Handlebars.registerHelper('linkToPerson', function(context, block) {
|
||||||
return html
|
return html
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Handlebars.registerHelper('linkToPerson', function(context, block) {
|
||||||
|
if( !context ) context = this;
|
||||||
|
var html = "<a href=\"/people/" + context.guid + "\" class=\"name\">";
|
||||||
|
html += block.fn(context);
|
||||||
|
html += "</a>";
|
||||||
|
|
||||||
|
return html
|
||||||
|
});
|
||||||
|
|
||||||
// relationship indicator for profile page
|
// relationship indicator for profile page
|
||||||
Handlebars.registerHelper('sharingMessage', function(person) {
|
Handlebars.registerHelper('sharingMessage', function(person) {
|
||||||
var i18n_scope = 'people.helper.is_not_sharing';
|
var i18n_scope = 'people.helper.is_not_sharing';
|
||||||
|
|
@ -107,5 +116,20 @@ Handlebars.registerHelper('isCurrentProfilePage', function(id, diaspora_handle,
|
||||||
return Handlebars.helpers.isCurrentPage('person', id, options) ||
|
return Handlebars.helpers.isCurrentPage('person', id, options) ||
|
||||||
Handlebars.helpers.isCurrentPage('user_profile', username, options);
|
Handlebars.helpers.isCurrentPage('user_profile', username, options);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Handlebars.registerHelper('aspectMembershipIndicator', function(contact,in_aspect) {
|
||||||
|
if(!app.aspect || !app.aspect.get('id')) return '<div class="aspect_membership_dropdown placeholder"></div>';
|
||||||
|
|
||||||
|
var html = '<i class="entypo ';
|
||||||
|
if( in_aspect == 'in_aspect' ) {
|
||||||
|
html += 'circled-cross contact_remove-from-aspect" ';
|
||||||
|
html += 'title="' + Diaspora.I18n.t('contacts.remove_contact') + '" ';
|
||||||
|
} else {
|
||||||
|
html += 'circled-plus contact_add-to-aspect" ';
|
||||||
|
html += 'title="' + Diaspora.I18n.t('contacts.add_contact') + '" ';
|
||||||
|
}
|
||||||
|
html += '></i>';
|
||||||
|
return html;
|
||||||
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
||||||
|
|
|
||||||
13
app/assets/javascripts/app/models/contact.js
Normal file
13
app/assets/javascripts/app/models/contact.js
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
|
app.models.Contact = Backbone.Model.extend({
|
||||||
|
initialize : function() {
|
||||||
|
this.aspect_memberships = new app.collections.AspectMemberships(this.get('aspect_memberships'));
|
||||||
|
if( this.get('person') ) this.person = new app.models.Person(this.get('person'));
|
||||||
|
},
|
||||||
|
|
||||||
|
inAspect : function(id) {
|
||||||
|
return this.aspect_memberships.any(function(membership){ return membership.get('aspect').id == id; });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// @license-end
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
app.views.Contacts = Backbone.View.extend({
|
app.pages.Contacts = Backbone.View.extend({
|
||||||
|
|
||||||
el: "#contacts_container",
|
el: "#contacts_container",
|
||||||
|
|
||||||
|
|
@ -8,17 +8,15 @@ app.views.Contacts = Backbone.View.extend({
|
||||||
"click #contacts_visibility_toggle" : "toggleContactVisibility",
|
"click #contacts_visibility_toggle" : "toggleContactVisibility",
|
||||||
"click #chat_privilege_toggle" : "toggleChatPrivilege",
|
"click #chat_privilege_toggle" : "toggleChatPrivilege",
|
||||||
"click #change_aspect_name" : "showAspectNameForm",
|
"click #change_aspect_name" : "showAspectNameForm",
|
||||||
"click .contact_remove-from-aspect" : "removeContactFromAspect",
|
|
||||||
"click .contact_add-to-aspect" : "addContactToAspect",
|
|
||||||
"keyup #contact_list_search" : "searchContactList"
|
"keyup #contact_list_search" : "searchContactList"
|
||||||
},
|
},
|
||||||
|
|
||||||
initialize: function() {
|
initialize: function(opts) {
|
||||||
this.visibility_toggle = $("#contacts_visibility_toggle .entypo");
|
this.visibility_toggle = $("#contacts_visibility_toggle .entypo");
|
||||||
this.chat_toggle = $("#chat_privilege_toggle .entypo");
|
this.chat_toggle = $("#chat_privilege_toggle .entypo");
|
||||||
|
this.stream = opts.stream;
|
||||||
|
this.stream.render();
|
||||||
$("#people_stream.contacts .header .entypo").tooltip({ 'placement': 'bottom'});
|
$("#people_stream.contacts .header .entypo").tooltip({ 'placement': 'bottom'});
|
||||||
$(".contact_remove-from-aspect").tooltip();
|
|
||||||
$(".contact_add-to-aspect").tooltip();
|
|
||||||
$(document).on('ajax:success', 'form.edit_aspect', this.updateAspectName);
|
$(document).on('ajax:success', 'form.edit_aspect', this.updateAspectName);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -69,65 +67,8 @@ app.views.Contacts = Backbone.View.extend({
|
||||||
$(".header > h3").show();
|
$(".header > h3").show();
|
||||||
},
|
},
|
||||||
|
|
||||||
addContactToAspect: function(e){
|
|
||||||
var contact = $(e.currentTarget);
|
|
||||||
var aspect_membership = new app.models.AspectMembership({
|
|
||||||
'person_id': contact.attr('data-person_id'),
|
|
||||||
'aspect_id': contact.attr('data-aspect_id')
|
|
||||||
});
|
|
||||||
|
|
||||||
aspect_membership.save({},{
|
|
||||||
success: function(model,response){
|
|
||||||
contact.attr('data-membership_id',model.id)
|
|
||||||
.tooltip('destroy')
|
|
||||||
.removeAttr('data-original-title')
|
|
||||||
.removeClass("contact_add-to-aspect").removeClass("circled-plus")
|
|
||||||
.addClass("contact_remove-from-aspect").addClass("circled-cross")
|
|
||||||
.attr('title', Diaspora.I18n.t('contacts.remove_contact'))
|
|
||||||
.tooltip()
|
|
||||||
.closest('.stream_element').addClass('in_aspect');
|
|
||||||
},
|
|
||||||
error: function(model,response){
|
|
||||||
var msg = Diaspora.I18n.t('contacts.error_add', { 'name':contact.closest('.stream_element').find('.name').text() });
|
|
||||||
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeContactFromAspect: function(e){
|
|
||||||
var contact = $(e.currentTarget);
|
|
||||||
var aspect_membership = new app.models.AspectMembership({
|
|
||||||
'id': contact.attr('data-membership_id')
|
|
||||||
});
|
|
||||||
|
|
||||||
aspect_membership.destroy({
|
|
||||||
success: function(model,response){
|
|
||||||
contact.removeAttr('data-membership_id')
|
|
||||||
.tooltip('destroy')
|
|
||||||
.removeAttr('data-original-title')
|
|
||||||
.removeClass("contact_remove-from-aspect").removeClass("circled-cross")
|
|
||||||
.addClass("contact_add-to-aspect").addClass("circled-plus")
|
|
||||||
.attr('title', Diaspora.I18n.t('contacts.add_contact'))
|
|
||||||
.tooltip()
|
|
||||||
.closest('.stream_element').removeClass('in_aspect');
|
|
||||||
},
|
|
||||||
error: function(model,response){
|
|
||||||
var msg = Diaspora.I18n.t('contacts.error_remove', { 'name':contact.closest('.stream_element').find('.name').text() });
|
|
||||||
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
searchContactList: function(e) {
|
searchContactList: function(e) {
|
||||||
var query = new RegExp($(e.target).val(),'i');
|
this.stream.search($(e.target).val());
|
||||||
|
|
||||||
$("#people_stream.stream.contacts .stream_element").each(function(){
|
|
||||||
if($(this).find(".name").text().match(query)){
|
|
||||||
$(this).show();
|
|
||||||
} else {
|
|
||||||
$(this).hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// @license-end
|
// @license-end
|
||||||
|
|
@ -43,7 +43,15 @@ app.Router = Backbone.Router.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
contacts: function() {
|
contacts: function() {
|
||||||
app.contacts = new app.views.Contacts();
|
app.aspect = new app.models.Aspect(gon.preloads.aspect);
|
||||||
|
app.contacts = new app.collections.Contacts(app.parsePreload('contacts'));
|
||||||
|
|
||||||
|
var stream = new app.views.ContactStream({
|
||||||
|
collection: app.contacts,
|
||||||
|
el: $('.stream.contacts #contact_stream'),
|
||||||
|
});
|
||||||
|
|
||||||
|
app.page = new app.pages.Contacts({stream: stream});
|
||||||
},
|
},
|
||||||
|
|
||||||
conversations: function() {
|
conversations: function() {
|
||||||
|
|
|
||||||
77
app/assets/javascripts/app/views/contact_stream_view.js
Normal file
77
app/assets/javascripts/app/views/contact_stream_view.js
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
|
app.views.ContactStream = Backbone.View.extend({
|
||||||
|
initialize: function() {
|
||||||
|
this.itemCount = 0;
|
||||||
|
this.perPage = 25;
|
||||||
|
this.query = '';
|
||||||
|
this.resultList = this.collection.toArray();
|
||||||
|
var throttledScroll = _.throttle(_.bind(this.infScroll, this), 200);
|
||||||
|
$(window).scroll(throttledScroll);
|
||||||
|
this.on('renderContacts', this.renderContacts, this);
|
||||||
|
},
|
||||||
|
|
||||||
|
render: function() {
|
||||||
|
if( _.isEmpty(this.resultList) ) {
|
||||||
|
var content = document.createDocumentFragment();
|
||||||
|
content = '<div id="no_contacts" class="well">' +
|
||||||
|
' <h4>' +
|
||||||
|
Diaspora.I18n.t('contacts.search_no_results') +
|
||||||
|
' </h4>' +
|
||||||
|
'</div>';
|
||||||
|
this.$el.html(content);
|
||||||
|
} else {
|
||||||
|
this.$el.html('');
|
||||||
|
this.renderContacts();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
renderContacts: function() {
|
||||||
|
this.$el.addClass("loading");
|
||||||
|
var content = document.createDocumentFragment();
|
||||||
|
_.rest(_.first(this.resultList , this.itemCount + this.perPage), this.itemCount).forEach( function(item) {
|
||||||
|
var view = new app.views.Contact({model: item});
|
||||||
|
content.appendChild(view.render().el);
|
||||||
|
});
|
||||||
|
|
||||||
|
var size = _.size(this.resultList);
|
||||||
|
if( this.itemCount + this.perPage >= size ){
|
||||||
|
this.itemCount = size;
|
||||||
|
this.off('renderContacts');
|
||||||
|
} else {
|
||||||
|
this.itemCount += this.perPage;
|
||||||
|
}
|
||||||
|
this.$el.append(content);
|
||||||
|
this.$el.removeClass("loading");
|
||||||
|
},
|
||||||
|
|
||||||
|
search: function(query) {
|
||||||
|
query = query.trim();
|
||||||
|
if( query || this.query ) {
|
||||||
|
this.off('renderContacts');
|
||||||
|
this.on('renderContacts', this.renderContacts, this);
|
||||||
|
this.itemCount = 0;
|
||||||
|
if( query ) {
|
||||||
|
this.query = query;
|
||||||
|
var regex = new RegExp(query,'i');
|
||||||
|
this.resultList = this.collection.filter(function(contact) {
|
||||||
|
return regex.test(contact.get('person').name) ||
|
||||||
|
regex.test(contact.get('person').diaspora_id);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.resultList = this.collection.toArray();
|
||||||
|
this.query = '';
|
||||||
|
}
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
infScroll: function() {
|
||||||
|
if( this.$el.hasClass('loading') ) return;
|
||||||
|
|
||||||
|
var distanceTop = $(window).height() + $(window).scrollTop(),
|
||||||
|
distanceBottom = $(document).height() - distanceTop;
|
||||||
|
if(distanceBottom < 300) this.trigger('renderContacts');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// @license-end
|
||||||
72
app/assets/javascripts/app/views/contact_view.js
Normal file
72
app/assets/javascripts/app/views/contact_view.js
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
// @license magnet:?xt=urn:btih:0b31508aeb0634b347b8270c7bee4d411b5d4109&dn=agpl-3.0.txt AGPL-v3-or-Later
|
||||||
|
|
||||||
|
app.views.Contact = app.views.Base.extend({
|
||||||
|
templateName: 'contact',
|
||||||
|
|
||||||
|
events: {
|
||||||
|
"click .contact_add-to-aspect" : "addContactToAspect",
|
||||||
|
"click .contact_remove-from-aspect" : "removeContactFromAspect"
|
||||||
|
},
|
||||||
|
|
||||||
|
tooltipSelector: '.contact_add-to-aspect, .contact_remove-from-aspect',
|
||||||
|
|
||||||
|
presenter: function() {
|
||||||
|
return _.extend(this.defaultPresenter(), {
|
||||||
|
person_id : this.model.get('person_id'),
|
||||||
|
person : this.model.get('person'),
|
||||||
|
in_aspect: (app.aspect && this.model.inAspect(app.aspect.get('id'))) ? 'in_aspect' : '',
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
postRenderTemplate: function() {
|
||||||
|
var self = this;
|
||||||
|
var dropdownEl = this.$('.aspect_membership_dropdown.placeholder');
|
||||||
|
if( dropdownEl.length == 0 ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO render me client side!!!
|
||||||
|
var href = this.model.person.url() + '/aspect_membership_button?size=small';
|
||||||
|
if( gon.bootstrap ) href += '&bootstrap=true';
|
||||||
|
|
||||||
|
$.get(href, function(resp) {
|
||||||
|
dropdownEl.html(resp);
|
||||||
|
new app.views.AspectMembership({el: $('.aspect_dropdown',dropdownEl)});
|
||||||
|
|
||||||
|
// UGLY (re-)attach the facebox
|
||||||
|
self.$('a[rel*=facebox]').facebox();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
addContactToAspect: function(){
|
||||||
|
var self = this;
|
||||||
|
this.model.aspect_memberships.create({
|
||||||
|
'person_id': this.model.get('person_id'),
|
||||||
|
'aspect_id': app.aspect.get('id')
|
||||||
|
},{
|
||||||
|
success: function(model,response){
|
||||||
|
self.render();
|
||||||
|
},
|
||||||
|
error: function(model,response){
|
||||||
|
var msg = Diaspora.I18n.t('contacts.error_add', { 'name': self.model.get('person').name });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
removeContactFromAspect: function(){
|
||||||
|
var self = this;
|
||||||
|
this.model.aspect_memberships
|
||||||
|
.find(function(membership){ return membership.get('aspect').id == app.aspect.id; })
|
||||||
|
.destroy({
|
||||||
|
success: function(model,response){
|
||||||
|
self.render();
|
||||||
|
},
|
||||||
|
error: function(model,response){
|
||||||
|
var msg = Diaspora.I18n.t('contacts.error_remove', { 'name': self.model.get('person').name });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// @license-end
|
||||||
|
|
@ -66,8 +66,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
#no_contacts {
|
#no_contacts {
|
||||||
|
margin-top: 20px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 10px;
|
|
||||||
background-color: #eee;
|
|
||||||
color: $text-dark-grey;
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
<div id="{{guid}}">
|
<div id="{{guid}}">
|
||||||
<div class="img">
|
<div class="img">
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{{personImage this "small" "small"}}}
|
{{{personImage this "small" "small"}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bd">
|
<div class="bd">
|
||||||
|
|
|
||||||
23
app/assets/templates/contact_tpl.jst.hbs
Normal file
23
app/assets/templates/contact_tpl.jst.hbs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
<div class="stream_element media contact {{in_aspect}}" id={{person_id}}>
|
||||||
|
<div class="pull-right">
|
||||||
|
{{{aspectMembershipIndicator this in_aspect}}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="media-object pull-left">
|
||||||
|
{{{personImage person 'small'}}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="media-body">
|
||||||
|
{{#linkToPerson person}}
|
||||||
|
{{name}}
|
||||||
|
{{/linkToPerson}}
|
||||||
|
|
||||||
|
<div class="info diaspora_handle">
|
||||||
|
{{person.diaspora_id}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info tags">
|
||||||
|
{{{fmtTags person.profile.tags}}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -3,26 +3,26 @@
|
||||||
<div id='post-info' class='span8'>
|
<div id='post-info' class='span8'>
|
||||||
<div class="img pull-left">
|
<div class="img pull-left">
|
||||||
{{#if root}}
|
{{#if root}}
|
||||||
{{#linkToPerson root.author}}
|
{{#linkToAuthor root.author}}
|
||||||
{{{personImage this 'medium'}}}
|
{{{personImage this 'medium'}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{{personImage this 'medium'}}}
|
{{{personImage this 'medium'}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bd">
|
<div class="bd">
|
||||||
<span class='author'>
|
<span class='author'>
|
||||||
{{#if root}}
|
{{#if root}}
|
||||||
{{#linkToPerson root.author}}
|
{{#linkToAuthor root.author}}
|
||||||
{{name}}
|
{{name}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{name}}
|
{{name}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|
@ -69,14 +69,14 @@
|
||||||
<div class='span8' id='reshare-info'>
|
<div class='span8' id='reshare-info'>
|
||||||
<i class='entypo retweet small pull-left'></i>
|
<i class='entypo retweet small pull-left'></i>
|
||||||
<div class="img pull-left">
|
<div class="img pull-left">
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{{personImage this 'small'}}}
|
{{{personImage this 'small'}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
</div>
|
</div>
|
||||||
<span class="author">
|
<span class="author">
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{name}}
|
{{name}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
</span>
|
</span>
|
||||||
<span class="post-time">
|
<span class="post-time">
|
||||||
<a href="/posts/{{id}}">
|
<a href="/posts/{{id}}">
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{{#each reshares}}
|
{{#each reshares}}
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{{personImage this 'small' 'micro'}}}
|
{{{personImage this 'small' 'micro'}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -21,9 +21,9 @@
|
||||||
</span>
|
</span>
|
||||||
<span>
|
<span>
|
||||||
{{#each likes}}
|
{{#each likes}}
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{{personImage this 'small' 'micro'}}}
|
{{{personImage this 'small' 'micro'}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
{{#people}}
|
{{#people}}
|
||||||
{{#linkToPerson this}}
|
{{#linkToAuthor this}}
|
||||||
{{{personImage this "small"}}}
|
{{{personImage this "small"}}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
{{/people}}
|
{{/people}}
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,16 @@
|
||||||
<div class='stream-frame-feedback'></div>
|
<div class='stream-frame-feedback'></div>
|
||||||
|
|
||||||
<div class="media author">
|
<div class="media author">
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
<div class="img">
|
<div class="img">
|
||||||
<div class="profile-image-container smaller" style="background-image : url('{{avatar.large}}')"></div>
|
<div class="profile-image-container smaller" style="background-image : url('{{avatar.large}}')"></div>
|
||||||
</div>
|
</div>
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
|
|
||||||
<div class="bd">
|
<div class="bd">
|
||||||
{{#linkToPerson author}}
|
{{#linkToAuthor author}}
|
||||||
{{name}}
|
{{name}}
|
||||||
{{/linkToPerson}}
|
{{/linkToAuthor}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,10 +34,7 @@ class AspectMembershipsController < ApplicationController
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.json do
|
format.json do
|
||||||
if success
|
if success
|
||||||
render :json => {
|
render :json => AspectMembershipPresenter.new(membership).base_hash
|
||||||
:person_id => contact.person_id,
|
|
||||||
:aspect_ids => contact.aspects.map{|a| a.id}
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
render :text => membership.errors.full_messages, :status => 403
|
render :text => membership.errors.full_messages, :status => 403
|
||||||
end
|
end
|
||||||
|
|
@ -57,7 +54,9 @@ class AspectMembershipsController < ApplicationController
|
||||||
flash.now[:notice] = I18n.t('aspects.add_to_aspect.success')
|
flash.now[:notice] = I18n.t('aspects.add_to_aspect.success')
|
||||||
respond_with do |format|
|
respond_with do |format|
|
||||||
format.json do
|
format.json do
|
||||||
render :json => AspectMembership.where(:contact_id => @contact.id, :aspect_id => @aspect.id).first.to_json
|
render :json => AspectMembershipPresenter.new(
|
||||||
|
AspectMembership.where(:contact_id => @contact.id, :aspect_id => @aspect.id).first)
|
||||||
|
.base_hash
|
||||||
end
|
end
|
||||||
|
|
||||||
format.all { redirect_to :back }
|
format.all { redirect_to :back }
|
||||||
|
|
|
||||||
|
|
@ -40,32 +40,24 @@ class ContactsController < ApplicationController
|
||||||
|
|
||||||
@contacts = contacts_by_type(type)
|
@contacts = contacts_by_type(type)
|
||||||
@contacts_size = @contacts.length
|
@contacts_size = @contacts.length
|
||||||
|
gon.preloads[:contacts] = @contacts.map{ |c| ContactPresenter.new(c, current_user).full_hash_with_person }
|
||||||
end
|
end
|
||||||
|
|
||||||
def contacts_by_type(type)
|
def contacts_by_type(type)
|
||||||
contacts = case type
|
case type
|
||||||
when "all"
|
when "all"
|
||||||
[current_user.contacts]
|
current_user.contacts
|
||||||
when "only_sharing"
|
when "only_sharing"
|
||||||
[current_user.contacts.only_sharing]
|
current_user.contacts.only_sharing
|
||||||
when "receiving"
|
when "receiving"
|
||||||
[current_user.contacts.receiving]
|
current_user.contacts.receiving
|
||||||
when "by_aspect"
|
when "by_aspect"
|
||||||
@aspect = current_user.aspects.find(params[:a_id])
|
@aspect = current_user.aspects.find(params[:a_id])
|
||||||
@contacts_in_aspect = @aspect.contacts
|
gon.preloads[:aspect] = AspectPresenter.new(@aspect).as_json
|
||||||
@contacts_not_in_aspect = current_user.contacts.where.not(contacts: {id: @contacts_in_aspect.pluck(:id) })
|
current_user.contacts
|
||||||
[@contacts_in_aspect, @contacts_not_in_aspect].map {|relation|
|
|
||||||
relation.includes(:aspect_memberships)
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
raise ArgumentError, "unknown type #{type}"
|
raise ArgumentError, "unknown type #{type}"
|
||||||
end
|
end
|
||||||
|
|
||||||
contacts.map {|relation|
|
|
||||||
relation.includes(:person => :profile).to_a.tap {|contacts|
|
|
||||||
contacts.sort_by! {|contact| contact.person.name }
|
|
||||||
}
|
|
||||||
}.inject(:+).paginate(:page => params[:page], :per_page => 25)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_up_contacts_mobile
|
def set_up_contacts_mobile
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,9 @@
|
||||||
module ContactsHelper
|
module ContactsHelper
|
||||||
def contact_aspect_dropdown(contact)
|
def contact_aspect_dropdown(contact)
|
||||||
membership = contact.aspect_memberships.where(:aspect_id => @aspect.id).first unless @aspect.nil?
|
|
||||||
|
|
||||||
if membership
|
|
||||||
content_tag(:i, nil, :class => 'entypo circled-cross contact_remove-from-aspect',
|
|
||||||
:title => t('contacts.index.remove_contact'),
|
|
||||||
'data-aspect_id' => @aspect.id,
|
|
||||||
'data-person_id' => contact.person_id,
|
|
||||||
'data-membership_id' => membership.id )
|
|
||||||
|
|
||||||
elsif @aspect.nil?
|
|
||||||
render :partial => 'people/relationship_action',
|
render :partial => 'people/relationship_action',
|
||||||
:locals => { :person => contact.person,
|
:locals => { :person => contact.person,
|
||||||
:contact => contact,
|
:contact => contact,
|
||||||
:current_user => current_user }
|
:current_user => current_user }
|
||||||
else
|
|
||||||
content_tag(:i, nil, :class => 'entypo circled-plus contact_add-to-aspect',
|
|
||||||
:title => t('contacts.index.add_contact'),
|
|
||||||
'data-aspect_id' => @aspect.id,
|
|
||||||
'data-person_id' => contact.person_id )
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def start_a_conversation_link(aspect, contacts_size)
|
def start_a_conversation_link(aspect, contacts_size)
|
||||||
|
|
|
||||||
11
app/presenters/aspect_membership_presenter.rb
Normal file
11
app/presenters/aspect_membership_presenter.rb
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
class AspectMembershipPresenter < BasePresenter
|
||||||
|
def initialize(membership)
|
||||||
|
@membership = membership
|
||||||
|
end
|
||||||
|
|
||||||
|
def base_hash
|
||||||
|
{ id: @membership.id,
|
||||||
|
aspect: AspectPresenter.new(@membership.aspect).as_json,
|
||||||
|
}
|
||||||
|
end
|
||||||
|
end
|
||||||
17
app/presenters/contact_presenter.rb
Normal file
17
app/presenters/contact_presenter.rb
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
class ContactPresenter < BasePresenter
|
||||||
|
def base_hash
|
||||||
|
{ id: id,
|
||||||
|
person_id: person_id
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_hash
|
||||||
|
base_hash.merge({
|
||||||
|
aspect_memberships: aspect_memberships.map{ |membership| AspectMembershipPresenter.new(membership).base_hash }
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
def full_hash_with_person
|
||||||
|
full_hash.merge({person: PersonPresenter.new(person).full_hash_with_profile})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
- membership = contact.aspect_memberships.where(:aspect_id => @aspect.id).first unless @aspect.nil?
|
|
||||||
.media.stream_element{:id => contact.person_id, :class => ("in_aspect" if membership)}
|
|
||||||
.pull-right
|
|
||||||
= contact_aspect_dropdown(contact)
|
|
||||||
.media-object.pull-left
|
|
||||||
= person_image_link(contact.person, :size => :thumb_small)
|
|
||||||
.media-body
|
|
||||||
= person_link(contact.person, :class => 'name')
|
|
||||||
.info.diaspora_handle
|
|
||||||
= contact.person_diaspora_handle
|
|
||||||
.info.tags
|
|
||||||
= Diaspora::Taggable.format_tags(contact.person.profile.tag_string)
|
|
||||||
|
|
@ -11,8 +11,9 @@
|
||||||
= render 'contacts/header'
|
= render 'contacts/header'
|
||||||
|
|
||||||
- if @contacts_size > 0
|
- if @contacts_size > 0
|
||||||
= render @contacts
|
#contact_stream
|
||||||
= will_paginate @contacts
|
-# JS
|
||||||
|
|
||||||
- else
|
- else
|
||||||
.no_contacts
|
.no_contacts
|
||||||
%h3
|
%h3
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ en:
|
||||||
remove_contact: "Remove contact"
|
remove_contact: "Remove contact"
|
||||||
error_add: "Couldn't add <%= name %> to the aspect :("
|
error_add: "Couldn't add <%= name %> to the aspect :("
|
||||||
error_remove: "Couldn't remove <%= name %> from the aspect :("
|
error_remove: "Couldn't remove <%= name %> from the aspect :("
|
||||||
|
search_no_results: "No contacts found"
|
||||||
|
|
||||||
my_activity: "My Activity"
|
my_activity: "My Activity"
|
||||||
my_stream: "Stream"
|
my_stream: "Stream"
|
||||||
|
|
|
||||||
|
|
@ -72,14 +72,14 @@ describe AspectMembershipsController, :type => :controller do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'json' do
|
context 'json' do
|
||||||
it 'returns a list of aspect ids for the person' do
|
it 'returns the aspect membership' do
|
||||||
post :create,
|
post :create,
|
||||||
:format => :json,
|
:format => :json,
|
||||||
:person_id => @person.id,
|
:person_id => @person.id,
|
||||||
:aspect_id => @aspect0.id
|
:aspect_id => @aspect0.id
|
||||||
|
|
||||||
contact = @controller.current_user.contact_for(@person)
|
contact = @controller.current_user.contact_for(@person)
|
||||||
expect(response.body).to eq(contact.aspect_memberships.first.to_json)
|
expect(response.body).to eq(AspectMembershipPresenter.new(contact.aspect_memberships.first).base_hash.to_json)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,20 @@ describe ContactsController, :type => :controller do
|
||||||
AppConfig.chat.enabled = true
|
AppConfig.chat.enabled = true
|
||||||
@aspect = bob.aspects.create(:name => "another aspect")
|
@aspect = bob.aspects.create(:name => "another aspect")
|
||||||
bob.share_with alice.person, @aspect
|
bob.share_with alice.person, @aspect
|
||||||
|
bob.share_with eve.person, @aspect
|
||||||
sign_in :user, bob
|
sign_in :user, bob
|
||||||
end
|
end
|
||||||
|
|
||||||
it "generates a jasmine fixture", :fixture => true do
|
it "generates the aspects_manage fixture", :fixture => true do
|
||||||
get :index, :a_id => @aspect.id
|
get :index, :a_id => @aspect.id
|
||||||
save_fixture(html_for("body"), "aspects_manage")
|
save_fixture(html_for("body"), "aspects_manage")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it "generates the contacts_json fixture", :fixture => true do
|
||||||
|
json = bob.contacts.map { |c|
|
||||||
|
ContactPresenter.new(c, bob).full_hash_with_person
|
||||||
|
}.to_json
|
||||||
|
save_fixture(json, "contacts_json")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
37
spec/javascripts/app/collections/contacts_collection_spec.js
Normal file
37
spec/javascripts/app/collections/contacts_collection_spec.js
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
describe("app.collections.Contacts", function(){
|
||||||
|
beforeEach(function(){
|
||||||
|
this.collection = new app.collections.Contacts();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("comparator", function() {
|
||||||
|
beforeEach(function(){
|
||||||
|
this.aspect = new app.models.Aspect({id: 42, name: "cats"});
|
||||||
|
this.con1 = new app.models.Contact({
|
||||||
|
person: { name: "aaa" },
|
||||||
|
aspect_memberships: []
|
||||||
|
});
|
||||||
|
this.con2 = new app.models.Contact({
|
||||||
|
person: { name: "aaa" },
|
||||||
|
aspect_memberships: [{id: 23, aspect: this.aspect}]
|
||||||
|
});
|
||||||
|
this.con3 = new app.models.Contact({
|
||||||
|
person: { name: "zzz" },
|
||||||
|
aspect_memberships: [{id: 23, aspect: this.aspect}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should compare the username if app.aspect is not present", function() {
|
||||||
|
expect(this.collection.comparator(this.con1, this.con3)).toBeLessThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should compare the aspect memberships if app.aspect is present", function() {
|
||||||
|
app.aspect = this.aspect;
|
||||||
|
expect(this.collection.comparator(this.con1, this.con3)).toBeGreaterThan(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("should compare the username if the contacts have equal aspect memberships", function() {
|
||||||
|
app.aspect = this.aspect;
|
||||||
|
expect(this.collection.comparator(this.con2, this.con3)).toBeLessThan(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
20
spec/javascripts/app/models/contact_spec.js
Normal file
20
spec/javascripts/app/models/contact_spec.js
Normal file
|
|
@ -0,0 +1,20 @@
|
||||||
|
describe("app.models.Contact", function() {
|
||||||
|
|
||||||
|
beforeEach(function(){
|
||||||
|
this.aspect = factory.aspect();
|
||||||
|
this.contact = new app.models.Contact({
|
||||||
|
person: { name: "aaa" },
|
||||||
|
aspect_memberships: [{id: 42, aspect: this.aspect}]
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("inAspect", function(){
|
||||||
|
it("returns true if the contact has been added to the aspect", function(){
|
||||||
|
expect(this.contact.inAspect(this.aspect.id)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("returns false if the contact hasn't been added to the aspect", function(){
|
||||||
|
expect(this.contact.inAspect(this.aspect.id+1)).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
101
spec/javascripts/app/pages/contacts_spec.js
Normal file
101
spec/javascripts/app/pages/contacts_spec.js
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
describe("app.pages.Contacts", function(){
|
||||||
|
beforeEach(function() {
|
||||||
|
spec.loadFixture("aspects_manage");
|
||||||
|
this.view = new app.pages.Contacts({
|
||||||
|
stream: {
|
||||||
|
render: function(){}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
Diaspora.I18n.load({
|
||||||
|
contacts: {
|
||||||
|
aspect_list_is_visible: "Contacts in this aspect are able to see each other.",
|
||||||
|
aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other.",
|
||||||
|
aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you.",
|
||||||
|
aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you.",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('toggle chat privilege', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.chat_toggle = $("#chat_privilege_toggle");
|
||||||
|
this.chat_icon = $("#chat_privilege_toggle .entypo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates the title for the tooltip', function() {
|
||||||
|
expect(this.chat_icon.attr('data-original-title')).toBe(
|
||||||
|
Diaspora.I18n.t("contacts.aspect_chat_is_not_enabled")
|
||||||
|
);
|
||||||
|
this.chat_toggle.trigger('click');
|
||||||
|
expect(this.chat_icon.attr('data-original-title')).toBe(
|
||||||
|
Diaspora.I18n.t("contacts.aspect_chat_is_enabled")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toggles the chat icon', function() {
|
||||||
|
expect(this.chat_icon.hasClass('enabled')).toBeFalsy();
|
||||||
|
this.chat_toggle.trigger('click');
|
||||||
|
expect(this.chat_icon.hasClass('enabled')).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('toggle contacts visibility', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.visibility_toggle = $("#contacts_visibility_toggle");
|
||||||
|
this.lock_icon = $("#contacts_visibility_toggle .entypo");
|
||||||
|
});
|
||||||
|
|
||||||
|
it('updates the title for the tooltip', function() {
|
||||||
|
expect(this.lock_icon.attr('data-original-title')).toBe(
|
||||||
|
Diaspora.I18n.t("contacts.aspect_list_is_visible")
|
||||||
|
);
|
||||||
|
|
||||||
|
this.visibility_toggle.trigger('click');
|
||||||
|
|
||||||
|
expect(this.lock_icon.attr('data-original-title')).toBe(
|
||||||
|
Diaspora.I18n.t("contacts.aspect_list_is_not_visible")
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('toggles the lock icon', function() {
|
||||||
|
expect(this.lock_icon.hasClass('lock-open')).toBeTruthy();
|
||||||
|
expect(this.lock_icon.hasClass('lock')).toBeFalsy();
|
||||||
|
|
||||||
|
this.visibility_toggle.trigger('click');
|
||||||
|
|
||||||
|
expect(this.lock_icon.hasClass('lock')).toBeTruthy();
|
||||||
|
expect(this.lock_icon.hasClass('lock-open')).toBeFalsy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('show aspect name form', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.button = $('#change_aspect_name');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the form', function() {
|
||||||
|
expect($('#aspect_name_form').css('display')).toBe('none');
|
||||||
|
this.button.trigger('click');
|
||||||
|
expect($('#aspect_name_form').css('display')).not.toBe('none');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('hides the aspect name', function() {
|
||||||
|
expect($('.header > h3').css('display')).not.toBe('none');
|
||||||
|
this.button.trigger('click');
|
||||||
|
expect($('.header > h3').css('display')).toBe('none');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('search contact list', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.searchinput = $('#contact_list_search');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls stream.search', function() {
|
||||||
|
this.view.stream.search = jasmine.createSpy();
|
||||||
|
this.searchinput.val("Username");
|
||||||
|
this.searchinput.trigger('keyup');
|
||||||
|
expect(this.view.stream.search).toHaveBeenCalledWith("Username");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
77
spec/javascripts/app/views/contact_stream_view_spec.js
Normal file
77
spec/javascripts/app/views/contact_stream_view_spec.js
Normal file
|
|
@ -0,0 +1,77 @@
|
||||||
|
describe("app.views.ContactStream", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
loginAs({name: "alice", avatar : {small : "http://avatar.com/photo.jpg"}});
|
||||||
|
spec.loadFixture("aspects_manage");
|
||||||
|
this.contacts = new app.collections.Contacts($.parseJSON(spec.readFixture("contacts_json")));
|
||||||
|
app.aspect = new app.models.Aspect(this.contacts.first().get('aspect_memberships')[0].aspect);
|
||||||
|
this.view = new app.views.ContactStream({
|
||||||
|
collection : this.contacts,
|
||||||
|
el: $('.stream.contacts #contact_stream')
|
||||||
|
});
|
||||||
|
|
||||||
|
this.view.perPage=1;
|
||||||
|
|
||||||
|
//clean the page
|
||||||
|
this.view.$el.html('');
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("initialize", function() {
|
||||||
|
it("binds an infinite scroll listener", function() {
|
||||||
|
spyOn($.fn, "scroll");
|
||||||
|
new app.views.ContactStream({collection : this.contacts});
|
||||||
|
expect($.fn.scroll).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("search", function() {
|
||||||
|
it("filters the contacts", function() {
|
||||||
|
this.view.render();
|
||||||
|
expect(this.view.$el.html()).toContain("alice");
|
||||||
|
this.view.search("eve");
|
||||||
|
expect(this.view.$el.html()).not.toContain("alice");
|
||||||
|
expect(this.view.$el.html()).toContain("eve");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("infScroll", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.view.off("renderContacts");
|
||||||
|
this.fn = jasmine.createSpy();
|
||||||
|
this.view.on("renderContacts", this.fn);
|
||||||
|
spyOn($.fn, "height").and.returnValue(0);
|
||||||
|
spyOn($.fn, "scrollTop").and.returnValue(100);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("triggers renderContacts when the user is at the bottom of the page", function() {
|
||||||
|
this.view.infScroll();
|
||||||
|
expect(this.fn).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("render", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
spyOn(this.view, "renderContacts");
|
||||||
|
});
|
||||||
|
|
||||||
|
it("calls renderContacts", function() {
|
||||||
|
this.view.render();
|
||||||
|
expect(this.view.renderContacts).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("renderContacts", function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.view.off("renderContacts");
|
||||||
|
this.view.renderContacts();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders perPage contacts", function() {
|
||||||
|
expect(this.view.$el.find('.stream_element.contact').length).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("renders more contacts when called a second time", function() {
|
||||||
|
this.view.renderContacts();
|
||||||
|
expect(this.view.$el.find('.stream_element.contact').length).toBe(2);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
136
spec/javascripts/app/views/contact_view_spec.js
Normal file
136
spec/javascripts/app/views/contact_view_spec.js
Normal file
|
|
@ -0,0 +1,136 @@
|
||||||
|
describe("app.views.Contact", function(){
|
||||||
|
beforeEach(function() {
|
||||||
|
this.aspect1 = factory.aspect({id: 1});
|
||||||
|
this.aspect2 = factory.aspect({id: 2});
|
||||||
|
|
||||||
|
this.model = new app.models.Contact({
|
||||||
|
person_id: 42,
|
||||||
|
person: { id: 42, name: 'alice' },
|
||||||
|
aspect_memberships: [{id: 23, aspect: this.aspect1}]
|
||||||
|
});
|
||||||
|
this.view = new app.views.Contact({ model: this.model });
|
||||||
|
Diaspora.I18n.load({
|
||||||
|
contacts: {
|
||||||
|
add_contact: "Add contact",
|
||||||
|
remove_contact: "Remove contact",
|
||||||
|
error_add: "Couldn't add <%= name %> to the aspect :(",
|
||||||
|
error_remove: "Couldn't remove <%= name %> from the aspect :("
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context("#presenter", function() {
|
||||||
|
it("contains necessary elements", function() {
|
||||||
|
app.aspect = this.aspect1;
|
||||||
|
expect(this.view.presenter()).toEqual(jasmine.objectContaining({
|
||||||
|
person_id: 42,
|
||||||
|
person: jasmine.objectContaining({id: 42, name: 'alice'}),
|
||||||
|
in_aspect: 'in_aspect'
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('add contact to aspect', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
app.aspect = this.aspect2;
|
||||||
|
this.view.render();
|
||||||
|
this.button = this.view.$el.find('.contact_add-to-aspect');
|
||||||
|
this.contact = this.view.$el.find('.stream_element.contact');
|
||||||
|
this.aspect_membership = {id: 42, aspect: app.aspect.toJSON()};
|
||||||
|
this.response = JSON.stringify(this.aspect_membership);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends a correct ajax request', function() {
|
||||||
|
this.button.trigger('click');
|
||||||
|
var obj = $.parseJSON(jasmine.Ajax.requests.mostRecent().params);
|
||||||
|
expect(obj.person_id).toBe(this.model.get('person_id'));
|
||||||
|
expect(obj.aspect_id).toBe(app.aspect.get('id'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('adds a aspect_membership to the contact', function() {
|
||||||
|
expect(this.model.aspect_memberships.length).toBe(1);
|
||||||
|
$('.contact_add-to-aspect',this.contact).trigger('click');
|
||||||
|
jasmine.Ajax.requests.mostRecent().response({
|
||||||
|
status: 200, // success
|
||||||
|
responseText: this.response
|
||||||
|
});
|
||||||
|
expect(this.model.aspect_memberships.length).toBe(2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls render', function() {
|
||||||
|
spyOn(this.view, 'render');
|
||||||
|
$('.contact_add-to-aspect',this.contact).trigger('click');
|
||||||
|
jasmine.Ajax.requests.mostRecent().response({
|
||||||
|
status: 200, // success
|
||||||
|
responseText: this.response
|
||||||
|
});
|
||||||
|
expect(this.view.render).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('displays a flash message on errors', function(){
|
||||||
|
$('.contact_add-to-aspect',this.contact).trigger('click');
|
||||||
|
jasmine.Ajax.requests.mostRecent().response({
|
||||||
|
status: 400, // fail
|
||||||
|
});
|
||||||
|
expect($('[id^="flash"]')).toBeErrorFlashMessage(
|
||||||
|
Diaspora.I18n.t(
|
||||||
|
'contacts.error_add',
|
||||||
|
{name: this.model.get('person').name}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('remove contact from aspect', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
app.aspect = this.aspect1;
|
||||||
|
this.view.render();
|
||||||
|
this.button = this.view.$el.find('.contact_remove-from-aspect');
|
||||||
|
this.contact = this.view.$el.find('.stream_element.contact');
|
||||||
|
this.aspect_membership = this.model.aspect_memberships.first().toJSON();
|
||||||
|
this.response = JSON.stringify(this.aspect_membership);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('sends a correct ajax request', function() {
|
||||||
|
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
||||||
|
expect(jasmine.Ajax.requests.mostRecent().url).toBe(
|
||||||
|
"/aspect_memberships/"+this.aspect_membership.id
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes the aspect_membership from the contact', function() {
|
||||||
|
expect(this.model.aspect_memberships.length).toBe(1);
|
||||||
|
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
||||||
|
jasmine.Ajax.requests.mostRecent().response({
|
||||||
|
status: 200, // success
|
||||||
|
responseText: this.response
|
||||||
|
});
|
||||||
|
expect(this.model.aspect_memberships.length).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls render', function() {
|
||||||
|
spyOn(this.view, 'render');
|
||||||
|
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
||||||
|
jasmine.Ajax.requests.mostRecent().response({
|
||||||
|
status: 200, // success
|
||||||
|
responseText: this.response,
|
||||||
|
});
|
||||||
|
expect(this.view.render).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays a flash message on errors', function(){
|
||||||
|
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
||||||
|
jasmine.Ajax.requests.mostRecent().response({
|
||||||
|
status: 400, // fail
|
||||||
|
});
|
||||||
|
expect($('[id^="flash"]')).toBeErrorFlashMessage(
|
||||||
|
Diaspora.I18n.t(
|
||||||
|
'contacts.error_remove',
|
||||||
|
{name: this.model.get('person').name}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -1,240 +0,0 @@
|
||||||
describe("app.views.Contacts", function(){
|
|
||||||
beforeEach(function() {
|
|
||||||
spec.loadFixture("aspects_manage");
|
|
||||||
this.view = new app.views.Contacts();
|
|
||||||
Diaspora.I18n.load({
|
|
||||||
contacts: {
|
|
||||||
add_contact: "Add contact",
|
|
||||||
aspect_list_is_visible: "Contacts in this aspect are able to see each other.",
|
|
||||||
aspect_list_is_not_visible: "Contacts in this aspect are not able to see each other.",
|
|
||||||
aspect_chat_is_enabled: "Contacts in this aspect are able to chat with you.",
|
|
||||||
aspect_chat_is_not_enabled: "Contacts in this aspect are not able to chat with you.",
|
|
||||||
remove_contact: "Remove contact",
|
|
||||||
error_add: "Couldn't add <%= name %> to the aspect :(",
|
|
||||||
error_remove: "Couldn't remove <%= name %> from the aspect :("
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('toggle chat privilege', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.chat_toggle = $("#chat_privilege_toggle");
|
|
||||||
this.chat_icon = $("#chat_privilege_toggle .entypo");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('updates the title for the tooltip', function() {
|
|
||||||
expect(this.chat_icon.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t("contacts.aspect_chat_is_not_enabled")
|
|
||||||
);
|
|
||||||
this.chat_toggle.trigger('click');
|
|
||||||
expect(this.chat_icon.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t("contacts.aspect_chat_is_enabled")
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('toggles the chat icon', function() {
|
|
||||||
expect(this.chat_icon.hasClass('enabled')).toBeFalsy;
|
|
||||||
this.chat_toggle.trigger('click');
|
|
||||||
expect(this.chat_icon.hasClass('enabled')).toBeTruethy;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('toggle contacts visibility', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.visibility_toggle = $("#contacts_visibility_toggle");
|
|
||||||
this.lock_icon = $("#contacts_visibility_toggle .entypo");
|
|
||||||
});
|
|
||||||
|
|
||||||
it('updates the title for the tooltip', function() {
|
|
||||||
expect(this.lock_icon.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t("contacts.aspect_list_is_visible")
|
|
||||||
);
|
|
||||||
|
|
||||||
this.visibility_toggle.trigger('click');
|
|
||||||
|
|
||||||
expect(this.lock_icon.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t("contacts.aspect_list_is_not_visible")
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('toggles the lock icon', function() {
|
|
||||||
expect(this.lock_icon.hasClass('lock-open')).toBeTruethy;
|
|
||||||
expect(this.lock_icon.hasClass('lock')).toBeFalsy;
|
|
||||||
|
|
||||||
this.visibility_toggle.trigger('click');
|
|
||||||
|
|
||||||
expect(this.lock_icon.hasClass('lock')).toBeTruethy;
|
|
||||||
expect(this.lock_icon.hasClass('lock-open')).toBeFalsy;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('show aspect name form', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.button = $('#change_aspect_name');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows the form', function() {
|
|
||||||
expect($('#aspect_name_form').css('display')).toBe('none');
|
|
||||||
this.button.trigger('click');
|
|
||||||
expect($('#aspect_name_form').css('display')).not.toBe('none');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('hides the aspect name', function() {
|
|
||||||
expect($('.header > h3').css('display')).not.toBe('none');
|
|
||||||
this.button.trigger('click');
|
|
||||||
expect($('.header > h3').css('display')).toBe('none');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('add contact to aspect', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.contact = $('#people_stream .stream_element').last();
|
|
||||||
this.button = this.contact.find('.contact_add-to-aspect');
|
|
||||||
this.person_id = this.button.attr('data-person_id');
|
|
||||||
this.aspect_id = this.button.attr('data-aspect_id');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sends a correct ajax request', function() {
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_add-to-aspect',this.contact).trigger('click');
|
|
||||||
var obj = $.parseJSON(jasmine.Ajax.requests.mostRecent().params);
|
|
||||||
expect(obj.person_id).toBe(this.person_id);
|
|
||||||
expect(obj.aspect_id).toBe(this.aspect_id);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('adds a membership id to the contact', function() {
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_add-to-aspect',this.contact).trigger('click');
|
|
||||||
jasmine.Ajax.requests.mostRecent().response({
|
|
||||||
status: 200, // success
|
|
||||||
responseText: '{ "id": 42 }'
|
|
||||||
});
|
|
||||||
expect(this.button.attr('data-membership_id')).toBe('42');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('displays a flash message on errors', function(){
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_add-to-aspect',this.contact).trigger('click');
|
|
||||||
jasmine.Ajax.requests.mostRecent().response({
|
|
||||||
status: 400, // fail
|
|
||||||
});
|
|
||||||
expect($('[id^="flash"]')).toBeErrorFlashMessage(
|
|
||||||
Diaspora.I18n.t(
|
|
||||||
'contacts.error_add',
|
|
||||||
{name: this.contact.find('.name').text()}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('changes the appearance of the contact', function() {
|
|
||||||
expect(this.button.hasClass('contact_add-to-aspect')).toBeTruethy;
|
|
||||||
expect(this.button.hasClass('circled-cross')).toBeTruethy;
|
|
||||||
expect(this.contact.hasClass('in_aspect')).toBeTruethy;
|
|
||||||
expect(this.button.hasClass('contact_remove-from-aspect')).toBeFalsy;
|
|
||||||
expect(this.button.hasClass('circled-plus')).toBeFalsy;
|
|
||||||
expect(this.button.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t('contacts.add_contact')
|
|
||||||
);
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_add-to-aspect',this.contact).trigger('click');
|
|
||||||
jasmine.Ajax.requests.mostRecent().response({
|
|
||||||
status: 200, // success
|
|
||||||
responseText: '{ "id": 42 }'
|
|
||||||
});
|
|
||||||
expect(this.button.hasClass('contact_add-to-aspect')).toBeFalsy;
|
|
||||||
expect(this.button.hasClass('circled-cross')).toBeFalsy;
|
|
||||||
expect(this.contact.hasClass('in_aspect')).toBeFalsy;
|
|
||||||
expect(this.button.hasClass('contact_remove-from-aspect')).toBeTruethy;
|
|
||||||
expect(this.button.hasClass('circled-plus')).toBeTruethy;
|
|
||||||
expect(this.button.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t('contacts.remove_contact')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('remove contact from aspect', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.contact = $('#people_stream .stream_element').first();
|
|
||||||
this.button = this.contact.find('.contact_remove-from-aspect');
|
|
||||||
this.person_id = this.button.attr('data-person_id');
|
|
||||||
this.aspect_id = this.button.attr('data-aspect_id');
|
|
||||||
this.membership_id = this.button.attr('data-membership_id');
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
it('sends a correct ajax request', function() {
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
|
||||||
expect(jasmine.Ajax.requests.mostRecent().url).toBe(
|
|
||||||
"/aspect_memberships/"+this.membership_id
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('removes the membership id from the contact', function() {
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
|
||||||
jasmine.Ajax.requests.mostRecent().response({
|
|
||||||
status: 200, // success
|
|
||||||
responseText: '{}'
|
|
||||||
});
|
|
||||||
expect(this.button.attr('data-membership_id')).toBe(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('displays a flash message on errors', function(){
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
|
||||||
jasmine.Ajax.requests.mostRecent().response({
|
|
||||||
status: 400, // fail
|
|
||||||
});
|
|
||||||
expect($('[id^="flash"]')).toBeErrorFlashMessage(
|
|
||||||
Diaspora.I18n.t(
|
|
||||||
'contacts.error_remove',
|
|
||||||
{name: this.contact.find('.name').text()}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('changes the appearance of the contact', function() {
|
|
||||||
expect(this.button.hasClass('contact_add-to-aspect')).toBeFalsy;
|
|
||||||
expect(this.button.hasClass('circled-cross')).toBeFalsy;
|
|
||||||
expect(this.contact.hasClass('in_aspect')).toBeFalsy;
|
|
||||||
expect(this.button.hasClass('contact_remove-from-aspect')).toBeTruethy;
|
|
||||||
expect(this.button.hasClass('circled-plus')).toBeTruethy;
|
|
||||||
expect(this.button.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t('contacts.remove_contact')
|
|
||||||
);
|
|
||||||
|
|
||||||
jasmine.Ajax.install();
|
|
||||||
$('.contact_remove-from-aspect',this.contact).trigger('click');
|
|
||||||
jasmine.Ajax.requests.mostRecent().response({
|
|
||||||
status: 200, // success
|
|
||||||
responseText: '{}'
|
|
||||||
});
|
|
||||||
|
|
||||||
expect(this.button.hasClass('contact_add-to-aspect')).toBeTruethy;
|
|
||||||
expect(this.button.hasClass('circled-cross')).toBeTruethy;
|
|
||||||
expect(this.contact.hasClass('in_aspect')).toBeTruethy;
|
|
||||||
expect(this.button.hasClass('contact_remove-from-aspect')).toBeFalsy;
|
|
||||||
expect(this.button.hasClass('circled-plus')).toBeFalsy;
|
|
||||||
expect(this.button.attr('data-original-title')).toBe(
|
|
||||||
Diaspora.I18n.t('contacts.add_contact')
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
context('search contact list', function() {
|
|
||||||
beforeEach(function() {
|
|
||||||
this.searchinput = $('#contact_list_search');
|
|
||||||
this.username = $('.stream_element .name').first().text();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('filters the contact list by name', function() {
|
|
||||||
expect($('.stream_element').length).toBeGreaterThan(1);
|
|
||||||
this.searchinput.val(this.username);
|
|
||||||
this.searchinput.trigger('keyup');
|
|
||||||
expect($('.stream_element:visible').length).toBe(1);
|
|
||||||
expect($('.stream_element:visible .name').first().text()).toBe(this.username);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
@ -63,13 +63,13 @@ describe("app.views.Notifications", function(){
|
||||||
|
|
||||||
it('toggles the unread class and changes the title', function() {
|
it('toggles the unread class and changes the title', function() {
|
||||||
this.view.updateView(this.readN.data('guid'), this.readN.data('type'), true);
|
this.view.updateView(this.readN.data('guid'), this.readN.data('type'), true);
|
||||||
expect(this.readN.hasClass('unread')).toBeTruethy;
|
expect(this.readN.hasClass('unread')).toBeTruthy();
|
||||||
expect(this.readN.hasClass('read')).toBeFalsy;
|
expect(this.readN.hasClass('read')).toBeFalsy();
|
||||||
expect(this.readN.find('.unread-toggle .entypo').data('original-title')).toBe(Diaspora.I18n.t('notifications.mark_read'));
|
expect(this.readN.find('.unread-toggle .entypo').data('original-title')).toBe(Diaspora.I18n.t('notifications.mark_read'));
|
||||||
|
|
||||||
this.view.updateView(this.readN.data('guid'), this.readN.data('type'), false);
|
this.view.updateView(this.readN.data('guid'), this.readN.data('type'), false);
|
||||||
expect(this.readN.hasClass('read')).toBeTruethy;
|
expect(this.readN.hasClass('read')).toBeTruthy();
|
||||||
expect(this.readN.hasClass('unread')).toBeFalsy;
|
expect(this.readN.hasClass('unread')).toBeFalsy();
|
||||||
expect(this.readN.find('.unread-toggle .entypo').data('original-title')).toBe(Diaspora.I18n.t('notifications.mark_unread'));
|
expect(this.readN.find('.unread-toggle .entypo').data('original-title')).toBe(Diaspora.I18n.t('notifications.mark_unread'));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
15
spec/presenters/aspect_membership_presenter_spec.rb
Normal file
15
spec/presenters/aspect_membership_presenter_spec.rb
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe AspectMembershipPresenter do
|
||||||
|
before do
|
||||||
|
@am = alice.aspects.where(:name => "generic").first.aspect_memberships.first
|
||||||
|
@presenter = AspectMembershipPresenter.new(@am)
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#base_hash' do
|
||||||
|
it 'works' do
|
||||||
|
expect(@presenter.base_hash).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
26
spec/presenters/contact_presenter_spec.rb
Normal file
26
spec/presenters/contact_presenter_spec.rb
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
|
||||||
|
describe ContactPresenter do
|
||||||
|
before do
|
||||||
|
@presenter = ContactPresenter.new(alice.contact_for(bob.person))
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#base_hash' do
|
||||||
|
it 'works' do
|
||||||
|
expect(@presenter.base_hash).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#full_hash' do
|
||||||
|
it 'works' do
|
||||||
|
expect(@presenter.full_hash).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '#full_hash_with_person' do
|
||||||
|
it 'works' do
|
||||||
|
expect(@presenter.full_hash_with_person).to be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Loading…
Reference in a new issue