Merge pull request #3864 from Raven24/aspect_memberships
[WIP] aspect membership dropdown Backbone.js rework
This commit is contained in:
commit
f3093ca8ae
21 changed files with 594 additions and 182 deletions
|
|
@ -55,6 +55,7 @@ var app = {
|
||||||
});
|
});
|
||||||
|
|
||||||
app.hovercard = new app.views.Hovercard();
|
app.hovercard = new app.views.Hovercard();
|
||||||
|
app.aspectMemberships = new app.views.AspectMembership();
|
||||||
},
|
},
|
||||||
|
|
||||||
hasPreload : function(prop) {
|
hasPreload : function(prop) {
|
||||||
|
|
|
||||||
7
app/assets/javascripts/app/models/aspect_membership.js
Normal file
7
app/assets/javascripts/app/models/aspect_membership.js
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
/**
|
||||||
|
* this model represents the assignment of an aspect to a person.
|
||||||
|
* (only valid for the context of the current user)
|
||||||
|
*/
|
||||||
|
app.models.AspectMembership = Backbone.Model.extend({
|
||||||
|
urlRoot: "/aspect_memberships"
|
||||||
|
});
|
||||||
161
app/assets/javascripts/app/views/aspect_membership_view.js
Normal file
161
app/assets/javascripts/app/views/aspect_membership_view.js
Normal file
|
|
@ -0,0 +1,161 @@
|
||||||
|
/**
|
||||||
|
* this view lets the user (de-)select aspect memberships in the context
|
||||||
|
* of another users profile or the contact page.
|
||||||
|
*
|
||||||
|
* updates to the list of aspects are immediately propagated to the server, and
|
||||||
|
* the results are dislpayed as flash messages.
|
||||||
|
*/
|
||||||
|
app.views.AspectMembership = Backbone.View.extend({
|
||||||
|
|
||||||
|
initialize: function() {
|
||||||
|
// attach event handler, removing any previous instances
|
||||||
|
var selector = '.dropdown.aspect_membership .dropdown_list > li';
|
||||||
|
$('body')
|
||||||
|
.off('click', selector)
|
||||||
|
.on('click', selector, _.bind(this._clickHandler, this));
|
||||||
|
|
||||||
|
this.list_item = null;
|
||||||
|
this.dropdown = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
// decide what to do when clicked
|
||||||
|
// -> addMembership
|
||||||
|
// -> removeMembership
|
||||||
|
_clickHandler: function(evt) {
|
||||||
|
this.list_item = $(evt.target);
|
||||||
|
this.dropdown = this.list_item.parent();
|
||||||
|
|
||||||
|
this.list_item.addClass('loading');
|
||||||
|
|
||||||
|
if( this.list_item.is('.selected') ) {
|
||||||
|
var membership_id = this.list_item.data('membership_id');
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false; // stop the event
|
||||||
|
},
|
||||||
|
|
||||||
|
// return the (short) name of the person associated with the current dropdown
|
||||||
|
_name: function() {
|
||||||
|
return this.dropdown.data('person-short-name');
|
||||||
|
},
|
||||||
|
|
||||||
|
// create a membership for the given person in the given aspect
|
||||||
|
addMembership: function(person_id, aspect_id) {
|
||||||
|
var aspect_membership = new app.models.AspectMembership({
|
||||||
|
'person_id': person_id,
|
||||||
|
'aspect_id': aspect_id
|
||||||
|
});
|
||||||
|
|
||||||
|
aspect_membership.on('sync', this._successSaveCb, this);
|
||||||
|
aspect_membership.on('error', function() {
|
||||||
|
this._displayError('aspect_dropdown.error');
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
aspect_membership.save();
|
||||||
|
},
|
||||||
|
|
||||||
|
_successSaveCb: function(aspect_membership) {
|
||||||
|
var aspect_id = aspect_membership.get('aspect_id');
|
||||||
|
var membership_id = aspect_membership.get('id');
|
||||||
|
var li = this.dropdown.find('li[data-aspect_id="'+aspect_id+'"]');
|
||||||
|
|
||||||
|
// the user didn't have this person in any aspects before, congratulate them
|
||||||
|
// on their newly found friendship ;)
|
||||||
|
if( this.dropdown.find('li.selected').length == 0 ) {
|
||||||
|
var msg = Diaspora.I18n.t('aspect_dropdown.started_sharing_with', { 'name': this._name() });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':true, 'notice':msg });
|
||||||
|
}
|
||||||
|
|
||||||
|
li.attr('data-membership_id', membership_id) // just to be sure...
|
||||||
|
.data('membership_id', membership_id)
|
||||||
|
.addClass('selected');
|
||||||
|
|
||||||
|
this.updateSummary();
|
||||||
|
this._done();
|
||||||
|
},
|
||||||
|
|
||||||
|
// show an error flash msg
|
||||||
|
_displayError: function(msg_id) {
|
||||||
|
this._done();
|
||||||
|
this.dropdown.removeClass('active'); // close the dropdown
|
||||||
|
|
||||||
|
var msg = Diaspora.I18n.t(msg_id, { 'name': this._name() });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
||||||
|
},
|
||||||
|
|
||||||
|
// remove the membership with the given id
|
||||||
|
removeMembership: function(membership_id) {
|
||||||
|
var aspect_membership = new app.models.AspectMembership({
|
||||||
|
'id': membership_id
|
||||||
|
});
|
||||||
|
|
||||||
|
aspect_membership.on('sync', this._successDestroyCb, this);
|
||||||
|
aspect_membership.on('error', function() {
|
||||||
|
this._displayError('aspect_dropdown.error_remove');
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
aspect_membership.destroy();
|
||||||
|
},
|
||||||
|
|
||||||
|
_successDestroyCb: function(aspect_membership) {
|
||||||
|
var membership_id = aspect_membership.get('id');
|
||||||
|
var li = this.dropdown.find('li[data-membership_id="'+membership_id+'"]');
|
||||||
|
|
||||||
|
li.removeAttr('data-membership_id')
|
||||||
|
.removeData('membership_id')
|
||||||
|
.removeClass('selected');
|
||||||
|
|
||||||
|
// we just removed the last aspect, inform the user with a flash message
|
||||||
|
// that he is no longer sharing with that person
|
||||||
|
if( this.dropdown.find('li.selected').length == 0 ) {
|
||||||
|
var msg = Diaspora.I18n.t('aspect_dropdown.stopped_sharing_with', { 'name': this._name() });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':true, 'notice':msg });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.updateSummary();
|
||||||
|
this._done();
|
||||||
|
},
|
||||||
|
|
||||||
|
// cleanup tasks after aspect selection
|
||||||
|
_done: function() {
|
||||||
|
if( this.list_item ) {
|
||||||
|
this.list_item.removeClass('loading');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// refresh the button text to reflect the current aspect selection status
|
||||||
|
updateSummary: function() {
|
||||||
|
var btn = this.dropdown.parents('div.aspect_membership').find('.button.toggle');
|
||||||
|
var aspects_cnt = this.dropdown.find('li.selected').length;
|
||||||
|
var txt;
|
||||||
|
|
||||||
|
if( aspects_cnt == 0 ) {
|
||||||
|
btn.removeClass('in_aspects');
|
||||||
|
txt = Diaspora.I18n.t('aspect_dropdown.toggle.zero');
|
||||||
|
} else {
|
||||||
|
btn.addClass('in_aspects');
|
||||||
|
txt = this._pluralSummaryTxt(aspects_cnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.text(txt + ' ▼');
|
||||||
|
},
|
||||||
|
|
||||||
|
_pluralSummaryTxt: function(cnt) {
|
||||||
|
var all_aspects_cnt = this.dropdown.find('li').length;
|
||||||
|
|
||||||
|
if( cnt == 1 ) {
|
||||||
|
return this.dropdown.find('li.selected').first().text();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( cnt == all_aspects_cnt ) {
|
||||||
|
return Diaspora.I18n.t('aspect_dropdown.all_aspects');
|
||||||
|
}
|
||||||
|
|
||||||
|
return Diaspora.I18n.t('aspect_dropdown.toggle', { 'count':cnt.toString() });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
/**
|
||||||
|
* the aspects dropdown specifies the scope of a posted status message.
|
||||||
|
*
|
||||||
|
* this view is part of the publisher where users are presented the options
|
||||||
|
* 'public', 'all aspects' and a list of their personal aspects, for limiting
|
||||||
|
* 'the audience of created contents.
|
||||||
|
*/
|
||||||
app.views.AspectsDropdown = app.views.Base.extend({
|
app.views.AspectsDropdown = app.views.Base.extend({
|
||||||
templateName : "aspects-dropdown",
|
templateName : "aspects-dropdown",
|
||||||
events : {
|
events : {
|
||||||
|
|
|
||||||
|
|
@ -27,3 +27,88 @@ $(document).ready(function() {
|
||||||
toggleAspectTitle();
|
toggleAspectTitle();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMPORARY SOLUTION
|
||||||
|
* TODO remove me, when the contacts section is done with Backbone.js ...
|
||||||
|
* (this is about as much covered by tests as the old code ... not at all)
|
||||||
|
*
|
||||||
|
* see also 'contact-edit.js'
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.tmp || (app.tmp = {});
|
||||||
|
|
||||||
|
// on the contacts page, viewing the facebox for single aspect
|
||||||
|
app.tmp.ContactAspectsBox = function() {
|
||||||
|
$('body').on('click', '#aspect_edit_pane a.add.button', _.bind(this.addToAspect, this));
|
||||||
|
$('body').on('click', '#aspect_edit_pane a.added.button', _.bind(this.removeFromAspect, this));
|
||||||
|
};
|
||||||
|
_.extend(app.tmp.ContactAspectsBox.prototype, {
|
||||||
|
addToAspect: function(evt) {
|
||||||
|
var el = $(evt.currentTarget);
|
||||||
|
var aspect_membership = new app.models.AspectMembership({
|
||||||
|
'person_id': el.data('person_id'),
|
||||||
|
'aspect_id': el.data('aspect_id')
|
||||||
|
});
|
||||||
|
|
||||||
|
aspect_membership.on('sync', this._successSaveCb, this);
|
||||||
|
aspect_membership.on('error', function() {
|
||||||
|
this._displayError('aspect_dropdown.error', el);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
aspect_membership.save();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_successSaveCb: function(aspect_membership) {
|
||||||
|
var membership_id = aspect_membership.get('id');
|
||||||
|
var person_id = aspect_membership.get('person_id');
|
||||||
|
var el = $('li.contact').find('a.add[data-person_id="'+person_id+'"]');
|
||||||
|
|
||||||
|
el.removeClass('add')
|
||||||
|
.addClass('added')
|
||||||
|
.attr('data-membership_id', membership_id) // just to be sure...
|
||||||
|
.data('membership_id', membership_id);
|
||||||
|
},
|
||||||
|
|
||||||
|
removeFromAspect: function(evt) {
|
||||||
|
var el = $(evt.currentTarget);
|
||||||
|
|
||||||
|
var aspect_membership = new app.models.AspectMembership({
|
||||||
|
'id': el.data('membership_id')
|
||||||
|
});
|
||||||
|
aspect_membership.on('sync', this._successDestroyCb, this);
|
||||||
|
aspect_membership.on('error', function(aspect_membership) {
|
||||||
|
this._displayError('aspect_dropdown.error_remove', el);
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
aspect_membership.destroy();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_successDestroyCb: function(aspect_membership) {
|
||||||
|
var membership_id = aspect_membership.get('id');
|
||||||
|
var el = $('li.contact').find('a.added[data-membership_id="'+membership_id+'"]');
|
||||||
|
|
||||||
|
el.removeClass('added')
|
||||||
|
.addClass('add')
|
||||||
|
.removeAttr('data-membership_id')
|
||||||
|
.removeData('membership_id');
|
||||||
|
},
|
||||||
|
|
||||||
|
_displayError: function(msg_id, contact_el) {
|
||||||
|
var name = $('li.contact')
|
||||||
|
.has(contact_el)
|
||||||
|
.find('h4.name')
|
||||||
|
.text();
|
||||||
|
var msg = Diaspora.I18n.t(msg_id, { 'name': name });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
var contact_aspects_box = new app.tmp.ContactAspectsBox();
|
||||||
|
});
|
||||||
|
|
|
||||||
|
|
@ -3,34 +3,6 @@
|
||||||
// the COPYRIGHT file.
|
// the COPYRIGHT file.
|
||||||
|
|
||||||
var ContactEdit = {
|
var ContactEdit = {
|
||||||
init: function(){
|
|
||||||
$.extend(ContactEdit, AspectsDropdown);
|
|
||||||
$('.dropdown.aspect_membership .dropdown_list > li, .dropdown.inviter .dropdown_list > li').live('click', function(evt){
|
|
||||||
ContactEdit.processClick($(this), evt);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
updateNumber: function(dropdown, personId, number){
|
|
||||||
var button = dropdown.parents(".dropdown").children('.button.toggle'),
|
|
||||||
replacement;
|
|
||||||
|
|
||||||
if (number == 0) {
|
|
||||||
button.removeClass("in_aspects");
|
|
||||||
replacement = Diaspora.I18n.t("aspect_dropdown.toggle.zero");
|
|
||||||
}else if (number == 1) {
|
|
||||||
button.addClass("in_aspects");
|
|
||||||
replacement = dropdown.find(".selected").first().text();
|
|
||||||
}else if (number < 3) {
|
|
||||||
replacement = Diaspora.I18n.t('aspect_dropdown.toggle.few', { count: number.toString()})
|
|
||||||
}else if (number > 3) {
|
|
||||||
replacement = Diaspora.I18n.t('aspect_dropdown.toggle.many', { count: number.toString()})
|
|
||||||
}else {
|
|
||||||
//the above one are a tautology, but I want to have them here once for once we figure out a neat way i18n them
|
|
||||||
replacement = Diaspora.I18n.t('aspect_dropdown.toggle.other', { count: number.toString()})
|
|
||||||
ContactEdit.toggleAspectMembership(li, evt);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
inviteFriend: function(li, evt) {
|
inviteFriend: function(li, evt) {
|
||||||
$.post('/services/inviter/facebook.json', {
|
$.post('/services/inviter/facebook.json', {
|
||||||
"aspect_id" : li.data("aspect_id"),
|
"aspect_id" : li.data("aspect_id"),
|
||||||
|
|
@ -38,61 +10,66 @@ var ContactEdit = {
|
||||||
}, function(data){
|
}, function(data){
|
||||||
ContactEdit.processSuccess(li, evt, data);
|
ContactEdit.processSuccess(li, evt, data);
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
processSuccess: function(element, evt, data) {
|
|
||||||
element.removeClass('loading')
|
|
||||||
if (data.url != undefined) {
|
|
||||||
window.location = data.url;
|
|
||||||
} else {
|
|
||||||
element.toggleClass("selected");
|
|
||||||
Diaspora.widgets.flashes.render({'success':true, 'notice':data.message});
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
processClick: function(li, evt){
|
|
||||||
var dropdown = li.closest('.dropdown');
|
|
||||||
li.addClass('loading');
|
|
||||||
if (dropdown.hasClass('inviter')) {
|
|
||||||
ContactEdit.inviteFriend(li, evt);
|
|
||||||
dropdown.html('sending, please wait...');
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ContactEdit.toggleAspectMembership(li, evt);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
toggleAspectMembership: function(li, evt) {
|
|
||||||
var button = li.find('.button'),
|
|
||||||
dropdown = li.closest('.dropdown'),
|
|
||||||
dropdownList = li.parent('.dropdown_list');
|
|
||||||
|
|
||||||
if(button.hasClass('disabled') || li.hasClass('newItem')){ return; }
|
|
||||||
|
|
||||||
var selected = li.hasClass("selected"),
|
|
||||||
routedId = selected ? "/42" : "";
|
|
||||||
|
|
||||||
$.post("/aspect_memberships" + routedId + ".json", {
|
|
||||||
"aspect_id": li.data("aspect_id"),
|
|
||||||
"person_id": li.parent().data("person_id"),
|
|
||||||
"_method": (selected) ? "DELETE" : "POST"
|
|
||||||
}, function(aspectMembership) {
|
|
||||||
ContactEdit.toggleCheckbox(li);
|
|
||||||
ContactEdit.updateNumber(li.closest(".dropdown_list"), li.parent().data("person_id"), aspectMembership.aspect_ids.length, 'in_aspects');
|
|
||||||
|
|
||||||
Diaspora.page.publish("aspectDropdown/updated", [li.parent().data("person_id"), li.parents(".dropdown").parent(".right").html()]);
|
|
||||||
})
|
|
||||||
.error(function() {
|
|
||||||
var message = Diaspora.I18n.t("aspect_dropdown.error", {name: dropdownList.data('person-short-name')});
|
|
||||||
Diaspora.page.flashMessages.render({success: false, notice: message});
|
|
||||||
dropdown.removeClass('active');
|
|
||||||
})
|
|
||||||
.complete(function() {
|
|
||||||
li.removeClass("loading");
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
$(document).ready(function(){
|
/*
|
||||||
ContactEdit.init();
|
TODO remove me
|
||||||
|
ContactEdit.toggleCheckbox(li);
|
||||||
|
Diaspora.page.publish("aspectDropdown/updated", [li.parent().data("person_id"), li.parents(".dropdown").parent(".right").html()]);
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* TEMPORARY SOLUTION
|
||||||
|
* TODO remove me, when the contacts section is done with Backbone.js ...
|
||||||
|
* (this is about as much covered by tests as the old code ... not at all)
|
||||||
|
*
|
||||||
|
* see also 'aspect-edit-pane.js'
|
||||||
|
*/
|
||||||
|
|
||||||
|
app.tmp || (app.tmp = {});
|
||||||
|
|
||||||
|
// on the contacts page, viewing the list of people in a single aspect
|
||||||
|
app.tmp.ContactAspects = function() {
|
||||||
|
$('#people_stream').on('click', '.contact_remove-from-aspect', _.bind(this.removeFromAspect, this));
|
||||||
|
};
|
||||||
|
_.extend(app.tmp.ContactAspects.prototype, {
|
||||||
|
removeFromAspect: function(evt) {
|
||||||
|
evt.stopImmediatePropagation();
|
||||||
|
evt.preventDefault();
|
||||||
|
|
||||||
|
var el = $(evt.currentTarget);
|
||||||
|
var id = el.data('membership_id');
|
||||||
|
|
||||||
|
var aspect_membership = new app.models.AspectMembership({'id':id});
|
||||||
|
aspect_membership.on('sync', this._successDestroyCb, this);
|
||||||
|
aspect_membership.on('error', function(aspect_membership) {
|
||||||
|
this._displayError('aspect_dropdown.error_remove', aspect_membership.get('id'));
|
||||||
|
}, this);
|
||||||
|
|
||||||
|
aspect_membership.destroy();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
},
|
||||||
|
|
||||||
|
_successDestroyCb: function(aspect_membership) {
|
||||||
|
var membership_id = aspect_membership.get('id');
|
||||||
|
|
||||||
|
$('.stream_element').has('[data-membership_id="'+membership_id+'"]')
|
||||||
|
.fadeOut(300, function() { $(this).remove() });
|
||||||
|
},
|
||||||
|
|
||||||
|
_displayError: function(msg_id, membership_id) {
|
||||||
|
var name = $('.stream_element')
|
||||||
|
.has('[data-membership_id="'+membership_id+'"]')
|
||||||
|
.find('div.bd > a')
|
||||||
|
.text();
|
||||||
|
var msg = Diaspora.I18n.t(msg_id, { 'name': name });
|
||||||
|
Diaspora.page.flashMessages.render({ 'success':false, 'notice':msg });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
var contact_aspects = new app.tmp.ContactAspects();
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -6,49 +6,62 @@
|
||||||
class AspectMembershipsController < ApplicationController
|
class AspectMembershipsController < ApplicationController
|
||||||
before_filter :authenticate_user!
|
before_filter :authenticate_user!
|
||||||
|
|
||||||
respond_to :html, :json, :js
|
respond_to :html, :json
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
#note :id is garbage
|
aspect = current_user.aspects.joins(:aspect_memberships).where(:aspect_memberships=>{:id=>params[:id]}).first
|
||||||
|
contact = current_user.contacts.joins(:aspect_memberships).where(:aspect_memberships=>{:id=>params[:id]}).first
|
||||||
|
|
||||||
@person_id = params[:person_id]
|
raise ActiveRecord::RecordNotFound unless aspect.present? && contact.present?
|
||||||
@aspect_id = params[:aspect_id]
|
|
||||||
|
|
||||||
@contact = current_user.contact_for(Person.where(:id => @person_id).first)
|
raise Diaspora::NotMine unless current_user.mine?(aspect) &&
|
||||||
membership = @contact ? @contact.aspect_memberships.where(:aspect_id => @aspect_id).first : nil
|
current_user.mine?(contact)
|
||||||
|
|
||||||
if membership && membership.destroy
|
membership = contact.aspect_memberships.where(:aspect_id => aspect.id).first
|
||||||
@aspect = membership.aspect
|
|
||||||
|
raise ActiveRecord::RecordNotFound unless membership.present?
|
||||||
|
|
||||||
|
# do it!
|
||||||
|
success = membership.destroy
|
||||||
|
|
||||||
|
# set the flash message
|
||||||
|
if success
|
||||||
flash.now[:notice] = I18n.t 'aspect_memberships.destroy.success'
|
flash.now[:notice] = I18n.t 'aspect_memberships.destroy.success'
|
||||||
|
|
||||||
respond_with do |format|
|
|
||||||
format.json{ render :json => {
|
|
||||||
:person_id => @person_id,
|
|
||||||
:aspect_ids => @contact.aspects.map{|a| a.id}
|
|
||||||
} }
|
|
||||||
format.html{ redirect_to :back }
|
|
||||||
end
|
|
||||||
|
|
||||||
else
|
else
|
||||||
flash.now[:error] = I18n.t 'aspect_memberships.destroy.failure'
|
flash.now[:error] = I18n.t 'aspect_memberships.destroy.failure'
|
||||||
errors = membership ? membership.errors.full_messages : t('aspect_memberships.destroy.no_membership')
|
|
||||||
respond_to do |format|
|
|
||||||
format.js { render :text => errors, :status => 403 }
|
|
||||||
format.html{
|
|
||||||
redirect_to :back
|
|
||||||
}
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
respond_with do |format|
|
||||||
|
format.json do
|
||||||
|
if success
|
||||||
|
render :json => {
|
||||||
|
:person_id => contact.person_id,
|
||||||
|
:aspect_ids => contact.aspects.map{|a| a.id}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
render :text => membership.errors.full_messages, :status => 403
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
format.all { redirect_to :back }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
@person = Person.find(params[:person_id])
|
@person = Person.find(params[:person_id])
|
||||||
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
|
@aspect = current_user.aspects.where(:id => params[:aspect_id]).first
|
||||||
|
|
||||||
@contact = current_user.share_with(@person, @aspect)
|
@contact = current_user.share_with(@person, @aspect)
|
||||||
|
|
||||||
if @contact
|
if @contact.present?
|
||||||
flash.now[:notice] = I18n.t('aspects.add_to_aspect.success')
|
flash.now[:notice] = I18n.t('aspects.add_to_aspect.success')
|
||||||
respond_with AspectMembership.where(:contact_id => @contact.id, :aspect_id => @aspect.id).first
|
respond_with do |format|
|
||||||
|
format.json do
|
||||||
|
render :json => AspectMembership.where(:contact_id => @contact.id, :aspect_id => @aspect.id).first.to_json
|
||||||
|
end
|
||||||
|
|
||||||
|
format.all { redirect_to :back }
|
||||||
|
end
|
||||||
else
|
else
|
||||||
flash.now[:error] = I18n.t('contacts.create.failure')
|
flash.now[:error] = I18n.t('contacts.create.failure')
|
||||||
render :nothing => true, :status => 409
|
render :nothing => true, :status => 409
|
||||||
|
|
@ -58,4 +71,13 @@ class AspectMembershipsController < ApplicationController
|
||||||
rescue_from ActiveRecord::StatementInvalid do
|
rescue_from ActiveRecord::StatementInvalid do
|
||||||
render :text => "Duplicate record rejected.", :status => 400
|
render :text => "Duplicate record rejected.", :status => 400
|
||||||
end
|
end
|
||||||
|
|
||||||
|
rescue_from ActiveRecord::RecordNotFound do
|
||||||
|
render :text => I18n.t('aspect_memberships.destroy.no_membership'), :status => 404
|
||||||
|
end
|
||||||
|
|
||||||
|
rescue_from Diaspora::NotMine do
|
||||||
|
render :text => "You are not allowed to do that.", :status => 403
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -163,15 +163,17 @@ class PeopleController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# shows the dropdown list of aspects the current user has set for the given person.
|
||||||
|
# renders "thats you" in case the current user views himself
|
||||||
def aspect_membership_dropdown
|
def aspect_membership_dropdown
|
||||||
@person = Person.find_by_guid(params[:person_id])
|
@person = Person.find_by_guid(params[:person_id])
|
||||||
if @person == current_user.person
|
|
||||||
render :text => I18n.t('people.person.thats_you')
|
# you are not a contact of yourself...
|
||||||
else
|
return render :text => I18n.t('people.person.thats_you') if @person == current_user.person
|
||||||
|
|
||||||
@contact = current_user.contact_for(@person) || Contact.new
|
@contact = current_user.contact_for(@person) || Contact.new
|
||||||
render :partial => 'aspect_membership_dropdown', :locals => {:contact => @contact, :person => @person, :hang => 'left'}
|
render :partial => 'aspect_membership_dropdown', :locals => {:contact => @contact, :person => @person, :hang => 'left'}
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
def redirect_if_tag_search
|
def redirect_if_tag_search
|
||||||
if search_query.starts_with?('#')
|
if search_query.starts_with?('#')
|
||||||
|
|
|
||||||
|
|
@ -4,20 +4,27 @@
|
||||||
|
|
||||||
module AspectGlobalHelper
|
module AspectGlobalHelper
|
||||||
def aspect_membership_dropdown(contact, person, hang, aspect=nil)
|
def aspect_membership_dropdown(contact, person, hang, aspect=nil)
|
||||||
|
aspect_membership_ids = {}
|
||||||
|
|
||||||
selected_aspects = all_aspects.select{|aspect| contact.in_aspect?(aspect)}
|
selected_aspects = all_aspects.select{|aspect| contact.in_aspect?(aspect)}
|
||||||
|
selected_aspects.each do |a|
|
||||||
|
record = a.aspect_memberships.find { |am| am.contact_id == contact.id }
|
||||||
|
aspect_membership_ids[a.id] = record.id
|
||||||
|
end
|
||||||
|
|
||||||
render "shared/aspect_dropdown",
|
render "shared/aspect_dropdown",
|
||||||
:selected_aspects => selected_aspects,
|
:selected_aspects => selected_aspects,
|
||||||
|
:aspect_membership_ids => aspect_membership_ids,
|
||||||
:person => person,
|
:person => person,
|
||||||
:hang => hang,
|
:hang => hang,
|
||||||
:dropdown_class => "aspect_membership"
|
:dropdown_class => "aspect_membership"
|
||||||
end
|
end
|
||||||
|
|
||||||
def aspect_dropdown_list_item(aspect, checked)
|
def aspect_dropdown_list_item(aspect, am_id=nil)
|
||||||
klass = checked ? "selected" : ""
|
klass = am_id.present? ? "selected" : ""
|
||||||
|
|
||||||
str = <<LISTITEM
|
str = <<LISTITEM
|
||||||
<li data-aspect_id=#{aspect.id} class='#{klass} aspect_selector'>
|
<li data-aspect_id="#{aspect.id}" data-membership_id="#{am_id}" class="#{klass} aspect_selector">
|
||||||
#{aspect.name}
|
#{aspect.name}
|
||||||
</li>
|
</li>
|
||||||
LISTITEM
|
LISTITEM
|
||||||
|
|
|
||||||
|
|
@ -7,25 +7,25 @@ module AspectsHelper
|
||||||
link_to image_tag('icons/monotone_plus_add_round.png'),
|
link_to image_tag('icons/monotone_plus_add_round.png'),
|
||||||
{ :controller => 'aspect_memberships',
|
{ :controller => 'aspect_memberships',
|
||||||
:action => 'create',
|
:action => 'create',
|
||||||
|
:format => :json,
|
||||||
:aspect_id => aspect_id,
|
:aspect_id => aspect_id,
|
||||||
:person_id => person_id},
|
:person_id => person_id
|
||||||
:remote => true,
|
},
|
||||||
:method => 'post',
|
:method => 'post',
|
||||||
:class => 'add button',
|
:class => 'add button',
|
||||||
'data-aspect_id' => aspect_id,
|
'data-aspect_id' => aspect_id,
|
||||||
'data-person_id' => person_id
|
'data-person_id' => person_id
|
||||||
end
|
end
|
||||||
|
|
||||||
def remove_from_aspect_button(aspect_id, person_id)
|
def remove_from_aspect_button(membership_id, aspect_id, person_id)
|
||||||
link_to image_tag('icons/monotone_check_yes.png'),
|
link_to image_tag('icons/monotone_check_yes.png'),
|
||||||
{ :controller => "aspect_memberships",
|
{ :controller => "aspect_memberships",
|
||||||
:action => 'destroy',
|
:action => 'destroy',
|
||||||
:id => 42,
|
:id => membership_id
|
||||||
:aspect_id => aspect_id,
|
},
|
||||||
:person_id => person_id},
|
|
||||||
:remote => true,
|
|
||||||
:method => 'delete',
|
:method => 'delete',
|
||||||
:class => 'added button',
|
:class => 'added button',
|
||||||
|
'data-membership_id' => membership_id,
|
||||||
'data-aspect_id' => aspect_id,
|
'data-aspect_id' => aspect_id,
|
||||||
'data-person_id' => person_id
|
'data-person_id' => person_id
|
||||||
end
|
end
|
||||||
|
|
@ -33,10 +33,11 @@ module AspectsHelper
|
||||||
def aspect_membership_button(aspect, contact, person)
|
def aspect_membership_button(aspect, contact, person)
|
||||||
return if person && person.closed_account?
|
return if person && person.closed_account?
|
||||||
|
|
||||||
if contact.nil? || !contact.aspect_memberships.detect{ |am| am.aspect_id == aspect.id}
|
membership = contact.aspect_memberships.where(:aspect_id => aspect.id).first
|
||||||
|
if contact.nil? || membership.nil?
|
||||||
add_to_aspect_button(aspect.id, person.id)
|
add_to_aspect_button(aspect.id, person.id)
|
||||||
else
|
else
|
||||||
remove_from_aspect_button(aspect.id, person.id)
|
remove_from_aspect_button(membership.id, aspect.id, person.id)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,23 @@
|
||||||
module ContactsHelper
|
module ContactsHelper
|
||||||
def contact_aspect_dropdown(contact)
|
def contact_aspect_dropdown(contact)
|
||||||
if @aspect
|
membership = contact.aspect_memberships.where(:aspect_id => @aspect.id).first unless @aspect.nil?
|
||||||
|
|
||||||
|
if membership
|
||||||
link_to(image_tag('icons/monotone_close_exit_delete.png', :height => 20, :width => 20),
|
link_to(image_tag('icons/monotone_close_exit_delete.png', :height => 20, :width => 20),
|
||||||
{ :controller => "aspect_memberships",
|
{ :controller => "aspect_memberships",
|
||||||
:action => 'destroy',
|
:action => 'destroy',
|
||||||
:id => 42,
|
:id => membership.id
|
||||||
:aspect_id => @aspect.id,
|
|
||||||
:person_id => contact.person_id
|
|
||||||
},
|
},
|
||||||
:title => t('contacts.index.remove_person_from_aspect', :person_name => contact.person_first_name, :aspect_name => @aspect.name),
|
:title => t('contacts.index.remove_person_from_aspect', :person_name => contact.person_first_name, :aspect_name => @aspect.name),
|
||||||
:method => 'delete')
|
:class => 'contact_remove-from-aspect',
|
||||||
|
:method => 'delete',
|
||||||
|
'data-membership_id' => membership.id
|
||||||
|
)
|
||||||
|
|
||||||
else
|
else
|
||||||
render :partial => 'people/relationship_action',
|
render :partial => 'people/relationship_action',
|
||||||
:locals => { :person => contact.person, :contact => contact,
|
:locals => { :person => contact.person,
|
||||||
|
:contact => contact,
|
||||||
:current_user => current_user }
|
:current_user => current_user }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ class AspectMembership < ActiveRecord::Base
|
||||||
:id => self.id,
|
:id => self.id,
|
||||||
:person_id => self.person.id,
|
:person_id => self.person.id,
|
||||||
:contact_id => self.contact.id,
|
:contact_id => self.contact.id,
|
||||||
|
:aspect_id => self.aspect_id,
|
||||||
:aspect_ids => self.contact.aspects.map{|a| a.id}
|
:aspect_ids => self.contact.aspects.map{|a| a.id}
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -406,6 +406,15 @@ class User < ActiveRecord::Base
|
||||||
Role.is_admin?(self.person)
|
Role.is_admin?(self.person)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def mine?(target)
|
||||||
|
if target.present? && target.respond_to?(:user_id)
|
||||||
|
return self.id == target.user_id
|
||||||
|
end
|
||||||
|
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
def guard_unconfirmed_email
|
def guard_unconfirmed_email
|
||||||
self.unconfirmed_email = nil if unconfirmed_email.blank? || unconfirmed_email == email
|
self.unconfirmed_email = nil if unconfirmed_email.blank? || unconfirmed_email == email
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// licensed under the Affero General Public License version 3 or later. See
|
// licensed under the Affero General Public License version 3 or later. See
|
||||||
// the COPYRIGHT file.
|
// the COPYRIGHT file.
|
||||||
|
|
||||||
|
// TODO handle this completely in Backbone.js, then remove this view!
|
||||||
|
|
||||||
var element = $(".add[data-aspect_id=<%= @aspect.id %>][data-person_id=<%= @contact.person_id%>]");
|
var element = $(".add[data-aspect_id=<%= @aspect.id %>][data-person_id=<%= @contact.person_id%>]");
|
||||||
|
|
||||||
if( $("#no_contacts").is(':visible') ) {
|
if( $("#no_contacts").is(':visible') ) {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@
|
||||||
// licensed under the Affero General Public License version 3 or later. See
|
// licensed under the Affero General Public License version 3 or later. See
|
||||||
// the COPYRIGHT file.
|
// the COPYRIGHT file.
|
||||||
|
|
||||||
|
// TODO handle this completely in Backbone.js, then remove this view!
|
||||||
|
|
||||||
var element = $(".added[data-aspect_id=<%= @aspect.id %>][data-person_id=<%= @contact.person_id%>]");
|
var element = $(".added[data-aspect_id=<%= @aspect.id %>][data-person_id=<%= @contact.person_id%>]");
|
||||||
element.parent().html("<%= escape_javascript(render('aspect_memberships/remove_from_aspect', :aspect => @aspect, :person => @contact.person, :contact => @contact)) %>");
|
element.parent().html("<%= escape_javascript(render('aspect_memberships/remove_from_aspect', :aspect => @aspect, :person => @contact.person, :contact => @contact)) %>");
|
||||||
element.fadeTo(200,1);
|
element.fadeTo(200,1);
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,16 @@
|
||||||
// licensed under the Affero General Public License version 3 or later. See
|
// licensed under the Affero General Public License version 3 or later. See
|
||||||
// the COPYRIGHT file.
|
// the COPYRIGHT file.
|
||||||
|
|
||||||
var dropdown = $("ul.dropdown_list[data-person_id=<%= @person.id %>]")
|
// TODO create the aspect and the new aspect membership via Backbone.js and then
|
||||||
|
// remove this view!
|
||||||
|
|
||||||
|
if( app.aspectMemberships ) {
|
||||||
|
var dropdown = $("ul.dropdown_list[data-person_id=<%= @person.id %>]");
|
||||||
$('.newItem', dropdown).before("<%= escape_javascript( aspect_dropdown_list_item(@aspect, @contact.aspects.include?(@aspect))) %>");
|
$('.newItem', dropdown).before("<%= escape_javascript( aspect_dropdown_list_item(@aspect, @contact.aspects.include?(@aspect))) %>");
|
||||||
|
|
||||||
ContactEdit.updateNumber(dropdown, "<%= @person.id %>", <%= @contact.aspects.size %>);
|
app.aspectMemberships.dropdown = dropdown;
|
||||||
|
app.aspectMemberships.updateSummary();
|
||||||
|
|
||||||
$.facebox.close();
|
$.facebox.close();
|
||||||
$('#profile .dropdown').toggleClass("active");
|
$('#profile .dropdown').toggleClass("active");
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
.wrapper
|
.wrapper
|
||||||
%ul.dropdown_list{:unSelectable => 'on', 'data-person_id' => (person.id if defined?(person) && person), 'data-service_uid' => (service_uid if defined?(service_uid)), 'data-person-short-name' => (person.first_name if defined?(person) && person)}
|
%ul.dropdown_list{:unSelectable => 'on', 'data-person_id' => (person.id if defined?(person) && person), 'data-service_uid' => (service_uid if defined?(service_uid)), 'data-person-short-name' => (person.first_name if defined?(person) && person)}
|
||||||
- for aspect in all_aspects
|
- for aspect in all_aspects
|
||||||
= aspect_dropdown_list_item(aspect, selected_aspects.include?(aspect) )
|
= aspect_dropdown_list_item(aspect, aspect_membership_ids[aspect.id] )
|
||||||
|
|
||||||
- if (dropdown_may_create_new_aspect && defined?(person) && person)
|
- if (dropdown_may_create_new_aspect && defined?(person) && person)
|
||||||
%li.newItem
|
%li.newItem
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ en:
|
||||||
stopped_sharing_with: "You have stopped sharing with <%= name %>."
|
stopped_sharing_with: "You have stopped sharing with <%= name %>."
|
||||||
started_sharing_with: "You have started sharing with <%= name %>!"
|
started_sharing_with: "You have started sharing with <%= name %>!"
|
||||||
error: "Couldn't start sharing with <%= name %>. Are you ignoring them?"
|
error: "Couldn't start sharing with <%= name %>. Are you ignoring them?"
|
||||||
|
error_remove: "Couldn't remove <%= name %> from the aspect :("
|
||||||
toggle:
|
toggle:
|
||||||
zero: "Select aspects"
|
zero: "Select aspects"
|
||||||
one: "In <%= count %> aspect"
|
one: "In <%= count %> aspect"
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,10 @@ module Diaspora
|
||||||
# to continue
|
# to continue
|
||||||
class AccountClosed < StandardError
|
class AccountClosed < StandardError
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# something that should be accessed does not belong to the current user and
|
||||||
|
# that prevents further execution
|
||||||
|
class NotMine < StandardError
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ describe AspectMembershipsController do
|
||||||
|
|
||||||
it 'succeeds' do
|
it 'succeeds' do
|
||||||
post :create,
|
post :create,
|
||||||
:format => 'js',
|
:format => :json,
|
||||||
:person_id => bob.person.id,
|
:person_id => bob.person.id,
|
||||||
:aspect_id => @aspect1.id
|
:aspect_id => @aspect1.id
|
||||||
response.should be_success
|
response.should be_success
|
||||||
|
|
@ -34,7 +34,7 @@ describe AspectMembershipsController do
|
||||||
it 'creates an aspect membership' do
|
it 'creates an aspect membership' do
|
||||||
lambda {
|
lambda {
|
||||||
post :create,
|
post :create,
|
||||||
:format => 'js',
|
:format => :json,
|
||||||
:person_id => bob.person.id,
|
:person_id => bob.person.id,
|
||||||
:aspect_id => @aspect1.id
|
:aspect_id => @aspect1.id
|
||||||
}.should change{
|
}.should change{
|
||||||
|
|
@ -47,7 +47,7 @@ describe AspectMembershipsController do
|
||||||
alice.contacts.reload
|
alice.contacts.reload
|
||||||
lambda {
|
lambda {
|
||||||
post :create,
|
post :create,
|
||||||
:format => 'js',
|
:format => :json,
|
||||||
:person_id => @person.id,
|
:person_id => @person.id,
|
||||||
:aspect_id => @aspect0.id
|
:aspect_id => @aspect0.id
|
||||||
}.should change{
|
}.should change{
|
||||||
|
|
@ -58,14 +58,14 @@ describe AspectMembershipsController do
|
||||||
it 'failure flashes error' do
|
it 'failure flashes error' do
|
||||||
alice.should_receive(:share_with).and_return(nil)
|
alice.should_receive(:share_with).and_return(nil)
|
||||||
post :create,
|
post :create,
|
||||||
:format => 'js',
|
:format => :json,
|
||||||
:person_id => @person.id,
|
:person_id => @person.id,
|
||||||
:aspect_id => @aspect0.id
|
:aspect_id => @aspect0.id
|
||||||
flash[:error].should_not be_blank
|
flash[:error].should_not be_blank
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not 500 on a duplicate key error' do
|
it 'does not 500 on a duplicate key error' do
|
||||||
params = {:format => 'js', :person_id => @person.id, :aspect_id => @aspect0.id}
|
params = {:format => :json, :person_id => @person.id, :aspect_id => @aspect0.id}
|
||||||
post :create, params
|
post :create, params
|
||||||
post :create, params
|
post :create, params
|
||||||
response.status.should == 400
|
response.status.should == 400
|
||||||
|
|
@ -74,7 +74,7 @@ describe AspectMembershipsController do
|
||||||
context 'json' do
|
context 'json' do
|
||||||
it 'returns a list of aspect ids for the person' do
|
it 'returns a list of aspect ids for the person' 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
|
||||||
|
|
||||||
|
|
@ -86,44 +86,25 @@ describe AspectMembershipsController do
|
||||||
|
|
||||||
describe "#destroy" do
|
describe "#destroy" do
|
||||||
it 'removes contacts from an aspect' do
|
it 'removes contacts from an aspect' do
|
||||||
alice.add_contact_to_aspect(@contact, @aspect1)
|
membership = alice.add_contact_to_aspect(@contact, @aspect1)
|
||||||
delete :destroy,
|
delete :destroy, :format => :json, :id => membership.id
|
||||||
:format => 'js', :id => 123,
|
|
||||||
:person_id => bob.person.id,
|
|
||||||
:aspect_id => @aspect0.id
|
|
||||||
response.should be_success
|
response.should be_success
|
||||||
@aspect0.reload
|
@aspect1.reload
|
||||||
@aspect0.contacts.include?(@contact).should be false
|
@aspect1.contacts.include?(@contact).should be false
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'does not 500 on an html request' do
|
it 'does not 500 on an html request' do
|
||||||
alice.add_contact_to_aspect(@contact, @aspect1)
|
membership = alice.add_contact_to_aspect(@contact, @aspect1)
|
||||||
delete :destroy,
|
delete :destroy, :id => membership.id
|
||||||
:id => 123,
|
|
||||||
:person_id => bob.person.id,
|
|
||||||
:aspect_id => @aspect0.id
|
|
||||||
response.should redirect_to :back
|
response.should redirect_to :back
|
||||||
@aspect0.reload
|
@aspect1.reload
|
||||||
@aspect0.contacts.include?(@contact).should be false
|
@aspect1.contacts.include?(@contact).should be false
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'aspect membership does not exist' do
|
it 'aspect membership does not exist' do
|
||||||
it 'person does not exist' do
|
delete :destroy, :format => :json, :id => 123
|
||||||
delete :destroy,
|
|
||||||
:format => 'js', :id => 123,
|
|
||||||
:person_id => 4324525,
|
|
||||||
:id => @aspect0.id
|
|
||||||
response.should_not be_success
|
|
||||||
response.body.should include "Could not find the selected person in that aspect"
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'contact is not in the aspect' do
|
|
||||||
delete :destroy,
|
|
||||||
:format => 'js', :id => 123,
|
|
||||||
:person_id => bob.person.id,
|
|
||||||
:aspect_id => 2321
|
|
||||||
response.should_not be_success
|
response.should_not be_success
|
||||||
response.body.should include "Could not find the selected person in that aspect"
|
response.body.should include "Could not find the selected person in that aspect"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
|
||||||
130
spec/javascripts/app/views/aspect_membership_view_spec.js
Normal file
130
spec/javascripts/app/views/aspect_membership_view_spec.js
Normal file
|
|
@ -0,0 +1,130 @@
|
||||||
|
|
||||||
|
describe("app.views.AspectMembership", function(){
|
||||||
|
beforeEach(function() {
|
||||||
|
// mock a dummy aspect dropdown
|
||||||
|
this.person = factory.author({name: "My Name"});
|
||||||
|
spec.content().html(
|
||||||
|
'<div class="aspect_membership dropdown">'+
|
||||||
|
' <div class="button toggle">The Button</div>'+
|
||||||
|
' <ul class="dropdown_list" data-person-short-name="'+this.person.name+'" data-person_id="'+this.person.id+'">'+
|
||||||
|
' <li data-aspect_id="10">Aspect 10</li>'+
|
||||||
|
' <li data-membership_id="99" data-aspect_id="11" class="selected">Aspect 11</li>'+
|
||||||
|
' <li data-aspect_id="12">Aspect 12</li>'+
|
||||||
|
' </ul>'+
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
this.view = new app.views.AspectMembership();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('attaches to the aspect selector', function(){
|
||||||
|
spyOn($.fn, 'on');
|
||||||
|
view = new app.views.AspectMembership();
|
||||||
|
|
||||||
|
expect($.fn.on).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
context('adding to aspects', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.newAspect = spec.content().find('li:eq(0)');
|
||||||
|
this.newAspectId = 10;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls "addMembership"', function() {
|
||||||
|
spyOn(this.view, "addMembership");
|
||||||
|
this.newAspect.trigger('click');
|
||||||
|
|
||||||
|
expect(this.view.addMembership).toHaveBeenCalledWith(this.person.id, this.newAspectId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tries to create a new AspectMembership', function() {
|
||||||
|
spyOn(app.models.AspectMembership.prototype, "save");
|
||||||
|
this.view.addMembership(1, 2);
|
||||||
|
|
||||||
|
expect(app.models.AspectMembership.prototype.save).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays an error when it fails', function() {
|
||||||
|
spyOn(this.view, "_displayError");
|
||||||
|
spyOn(app.models.AspectMembership.prototype, "save").andCallFake(function() {
|
||||||
|
this.trigger('error');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.view.addMembership(1, 2);
|
||||||
|
|
||||||
|
expect(this.view._displayError).toHaveBeenCalledWith('aspect_dropdown.error');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('removing from aspects', function(){
|
||||||
|
beforeEach(function() {
|
||||||
|
this.oldAspect = spec.content().find('li:eq(1)');
|
||||||
|
this.oldMembershipId = 99;
|
||||||
|
});
|
||||||
|
|
||||||
|
it('calls "removeMembership"', function(){
|
||||||
|
spyOn(this.view, "removeMembership");
|
||||||
|
this.oldAspect.trigger('click');
|
||||||
|
|
||||||
|
expect(this.view.removeMembership).toHaveBeenCalledWith(this.oldMembershipId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('tries to destroy an AspectMembership', function() {
|
||||||
|
spyOn(app.models.AspectMembership.prototype, "destroy");
|
||||||
|
this.view.removeMembership(1);
|
||||||
|
|
||||||
|
expect(app.models.AspectMembership.prototype.destroy).toHaveBeenCalled();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('displays an error when it fails', function() {
|
||||||
|
spyOn(this.view, "_displayError");
|
||||||
|
spyOn(app.models.AspectMembership.prototype, "destroy").andCallFake(function() {
|
||||||
|
this.trigger('error');
|
||||||
|
});
|
||||||
|
|
||||||
|
this.view.removeMembership(1);
|
||||||
|
|
||||||
|
expect(this.view._displayError).toHaveBeenCalledWith('aspect_dropdown.error_remove');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
context('summary text in the button', function() {
|
||||||
|
beforeEach(function() {
|
||||||
|
this.btn = spec.content().find('div.button.toggle');
|
||||||
|
this.btn.text(""); // reset
|
||||||
|
this.view.dropdown = spec.content().find('ul.dropdown_list');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows "no aspects" when nothing is selected', function() {
|
||||||
|
spec.content().find('li[data-aspect_id]').removeClass('selected');
|
||||||
|
this.view.updateSummary();
|
||||||
|
|
||||||
|
expect(this.btn.text()).toContain(Diaspora.I18n.t('aspect_dropdown.toggle.zero'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows "all aspects" when everything is selected', function() {
|
||||||
|
spec.content().find('li[data-aspect_id]').addClass('selected');
|
||||||
|
this.view.updateSummary();
|
||||||
|
|
||||||
|
expect(this.btn.text()).toContain(Diaspora.I18n.t('aspect_dropdown.all_aspects'));
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the name of the selected aspect ( == 1 )', function() {
|
||||||
|
var list = spec.content().find('li[data-aspect_id]');
|
||||||
|
list.removeClass('selected'); // reset
|
||||||
|
list.eq(1).addClass('selected');
|
||||||
|
this.view.updateSummary();
|
||||||
|
|
||||||
|
expect(this.btn.text()).toContain(list.eq(1).text());
|
||||||
|
});
|
||||||
|
|
||||||
|
it('shows the number of selected aspects ( > 1)', function() {
|
||||||
|
var list = spec.content().find('li[data-aspect_id]');
|
||||||
|
list.removeClass('selected'); // reset
|
||||||
|
$([list.eq(1), list.eq(2)]).addClass('selected');
|
||||||
|
this.view.updateSummary();
|
||||||
|
|
||||||
|
expect(this.btn.text()).toContain(Diaspora.I18n.t('aspect_dropdown.toggle', { 'count':2 }));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Reference in a new issue