Add contacts search and port aspect membership save/destroy to backbone

This commit is contained in:
Steffen van Bergerem 2014-08-25 15:50:33 +02:00
parent 9587961883
commit f1408a7a09
16 changed files with 102 additions and 254 deletions

View file

@ -4,13 +4,17 @@ app.views.Contacts = Backbone.View.extend({
events: {
"click #contacts_visibility_toggle" : "toggleContactVisibility",
"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"
},
initialize: function() {
this.visibility_toggle = $("#contacts_visibility_toggle .entypo");
$("#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);
},
@ -20,16 +24,16 @@ app.views.Contacts = Backbone.View.extend({
.addClass("lock")
.tooltip("destroy")
.removeAttr("data-original-title")
.attr("title", Diaspora.I18n.t("aspects.edit.aspect_list_is_not_visible"))
.tooltip();
.attr("title", Diaspora.I18n.t("contacts.aspect_list_is_not_visible"))
.tooltip({'placement': 'bottom'});
}
else {
this.visibility_toggle.removeClass("lock")
.addClass("lock-open")
.tooltip("destroy")
.removeAttr("data-original-title")
.attr("title", Diaspora.I18n.t("aspects.edit.aspect_list_is_visible"))
.tooltip();
.attr("title", Diaspora.I18n.t("contacts.aspect_list_is_visible"))
.tooltip({'placement': 'bottom'});
}
},
@ -43,5 +47,64 @@ app.views.Contacts = Backbone.View.extend({
$("#aspect_nav [data-aspect-id='"+data['id']+"'] .name").text(data['name']);
$(".header > #aspect_name_form").hide();
$(".header > h3").show();
},
addContactToAspect: function(e){
var contact = $(e.currentTarget);
var aspect_membership = new app.models.AspectMembership({
'person_id': contact.data('person_id'),
'aspect_id': contact.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.add_contact'))
.tooltip()
.closest('.stream_element').removeClass('not_in_aspect');
},
error: function(model,response){
alert("SAVE ERROR " + JSON.stringify(model));
}
});
},
removeContactFromAspect: function(e){
var contact = $(e.currentTarget);
var aspect_membership = new app.models.AspectMembership({
'id': contact.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').addClass('not_in_aspect');
},
error: function(model,response){
alert("DESTROY ERROR " + JSON.stringify(model));
}
});
},
searchContactList: function(e) {
var query = new RegExp($(e.target).val(),'i');
$("#people_stream.stream.contacts .stream_element").each(function(){
if($(this).find(".name").text().match(query)){
$(this).show();
} else {
$(this).hide();
}
});
}
});

View file

@ -1,89 +0,0 @@
/**
* 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.btn', _.bind(this.addToAspect, this));
$('body').on('click', '#aspect_edit_pane a.added.btn', _.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);
el.find('div').removeClass('icons-monotone_plus_add_round')
.addClass('icons-monotone_check_yes');
},
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');
el.find('div').removeClass('icons-monotone_check_yes')
.addClass('icons-monotone_plus_add_round');
},
_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();
});

View file

@ -1,58 +0,0 @@
// Copyright (c) 2010-2011, Diaspora Inc. This file is
// licensed under the Affero General Public License version 3 or later. See
// the COPYRIGHT file.
/**
* 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();
});

View file

@ -4,37 +4,6 @@
*/
var List = {
initialize: function() {
$(document).on("keyup", ".contact_list_search", function(e) {
var search = $(this);
var list = $(".contacts", ".searchable");
var query = new RegExp(search.val(),'i');
$("> .contact", list).each( function(idx, element) {
element = $(element);
if( !element.find(".name").text().match(query) ) {
element.addClass('hidden');
} else {
element.removeClass('hidden');
}
});
});
},
disconnectUser: function(contact_id){
$.ajax({
url: "/contacts/" + contact_id,
type: "DELETE",
success: function(){
if( $('.searchable').length == 1){
$('.searchable .contact[data-contact_id='+contact_id+']').fadeOut(200);
} else if($('#aspects_list').length == 1) {
$.facebox.close();
};
}
});
},
runDelayedSearch: function( searchTerm ) {
$.getJSON('/people/refresh_search',
{ q: searchTerm },
@ -77,6 +46,4 @@ $(document).ready(function() {
$this.removeClass("remove");
$this.children("img").attr("src","/images/icons/monotone_check_yes.png");
});
List.initialize();
});

View file

@ -3,5 +3,4 @@
* the COPYRIGHT file.
*/
//= require aspect-edit-pane
//= require fileuploader-custom

View file

@ -32,8 +32,6 @@
//= require_tree ./widgets
//= require view
//= require aspects-dropdown
//= require contact-edit
//= require contact-list
//= require mentions
//= require bootstrap-tooltip
//= require bootstrap-popover

View file

@ -2,7 +2,6 @@
* licensed under the Affero General Public License version 3 or later. See
* the COPYRIGHT file.
*/
//= require aspect-edit-pane
//= require fileuploader-custom
//= require jquery.autoSuggest.custom

View file

@ -14,6 +14,10 @@
}
.btn { margin-top: 10px; }
}
#contact_list_search {
margin: 6px 30px 0 0;
width: 150px;
}
& > a, #aspect_controls > a {
text-decoration: none;
margin-right: 25px;
@ -27,15 +31,18 @@
#suggest_member.btn { margin-top: 8px; }
}
.stream_element {
.contact_remove-from-aspect, .contact_add-to-aspect {
text-decoration: none;
.entypo {
cursor: pointer;
font-size: 20px;
line-height: 50px;
margin: 10px;
color: lighten($black,75%);
&:hover { color: $black; }
}
&.not_in_aspect { background-color: $background-grey; }
}
.no_contacts {

View file

@ -86,7 +86,7 @@ form.block-form {
}
}
textarea, input[type=text], input[type=password] {
textarea, input[type=text], input[type=password], input[type=search] {
&:focus, &:invalid:focus {
border: 1px solid $border-dark-grey;
outline: none;

View file

@ -67,28 +67,6 @@ class AspectsController < ApplicationController
end
end
def edit
@aspect = current_user.aspects.where(:id => params[:id]).includes(:contacts => {:person => :profile}).first
@contacts_in_aspect = @aspect.contacts.includes(:aspect_memberships, :person => :profile).to_a.sort_by { |c| c.person.name }
c = Contact.arel_table
if @contacts_in_aspect.empty?
@contacts_not_in_aspect = current_user.contacts.includes(:aspect_memberships, :person => :profile).to_a.sort_by { |c| c.person.name }
else
@contacts_not_in_aspect = current_user.contacts.where(c[:id].not_in(@contacts_in_aspect.map(&:id))).includes(:aspect_memberships, :person => :profile).to_a.sort_by { |c| c.person.name }
end
@contacts = @contacts_not_in_aspect
unless @aspect
render :file => Rails.root.join('public', '404.html').to_s, :layout => false, :status => 404
else
@aspect_ids = [@aspect.id]
@aspect_contacts_count = @aspect.contacts.size
render :layout => false
end
end
def update
@aspect = current_user.aspects.where(:id => params[:id]).first

View file

@ -3,16 +3,11 @@ module ContactsHelper
membership = contact.aspect_memberships.where(:aspect_id => @aspect.id).first unless @aspect.nil?
if membership
link_to(content_tag(:i, nil, :class => 'entypo circled-cross'),
{ :controller => "aspect_memberships",
:action => 'destroy',
:id => membership.id
},
content_tag(:i, nil, :class => 'entypo circled-cross contact_remove-from-aspect',
:title => t('contacts.index.remove_person_from_aspect', :person_name => contact.person_first_name, :aspect_name => @aspect.name),
:class => 'contact_remove-from-aspect',
:method => 'delete',
'data-membership_id' => membership.id
)
'data-aspect_id' => @aspect.id,
'data-person_id' => contact.person_id,
'data-membership_id' => membership.id )
elsif @aspect.nil?
render :partial => 'people/relationship_action',
@ -20,18 +15,10 @@ module ContactsHelper
:contact => contact,
:current_user => current_user }
else
link_to(content_tag(:i, nil, :class => 'entypo circled-plus'),
{ :controller => "aspect_memberships",
:action => 'create',
:person_id => contact.person_id,
:aspect_id => @aspect.id
},
content_tag(:i, nil, :class => 'entypo circled-plus contact_add-to-aspect',
:title => t('people.person.add_contact'),
:class => 'contact_add-to-aspect',
:method => 'create',
'data-aspect_id' => @aspect.id,
'data-person_id' => contact.person_id
)
'data-person_id' => contact.person_id )
end
end

View file

@ -1,13 +0,0 @@
#people_stream.stream.contacts
- @contacts.each do |contact|
.media.stream_element{:id => contact.person_id}
.pull-right.contact_add-to-aspect
%i.entypo.circled-plus{:title => t('people.person.add_contact')}
.media-object.pull-left
= person_image_link(contact.person, :size => :thumb_small)
.media-body
= person_link(contact.person)
.info.diaspora_handle
= contact.person_diaspora_handle
.info.tags
= Diaspora::Taggable.format_tags(contact.person.profile.tag_string)

View file

@ -1,10 +1,11 @@
.media.stream_element{:id => contact.person_id}
- membership = contact.aspect_memberships.where(:aspect_id => @aspect.id).first unless @aspect.nil?
.media.stream_element{:id => contact.person_id, :class => ("not_in_aspect" unless 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)
= person_link(contact.person, :class => 'name')
.info.diaspora_handle
= contact.person_diaspora_handle
.info.tags

View file

@ -12,7 +12,8 @@
= link_to @aspect, method: "delete", data: { confirm: t('aspects.edit.confirm_remove_aspect') }, class: 'delete' do
%i.entypo.trash.contacts-header-icon{:title => t('delete')}
.pull-right
= search_field_tag :contact_search, "", id: "contact_list_search", placeholder: t('contacts.index.user_search')
%h3
%span#aspect_name
= @aspect.name
@ -21,7 +22,7 @@
#aspect_name_form
= form_for @aspect, :remote => true do |aspect|
= aspect.text_field :name, :maxlength => 20
= aspect.submit t('aspects.edit.update'), 'data-disable-with' => t('aspects.edit.updating'), :class => "btn green"
= aspect.submit t('aspects.edit.update'), 'data-disable-with' => t('aspects.edit.updating'), :class => "btn"
- else
%h3

View file

@ -345,6 +345,7 @@ en:
only_sharing_with_me: "Only sharing with me"
remove_person_from_aspect: "Remove %{person_name} from \"%{aspect_name}\""
many_people_are_you_sure: "Are you sure you want to start a private conversation with more than %{suggested_limit} contacts? Posting to this aspect may be a better way to contact them."
user_search: "User Search"
spotlight:
community_spotlight: "Community Spotlight"
suggest_member: "Suggest a member"

View file

@ -38,6 +38,13 @@ en:
years: "%d years"
wordSeparator: " "
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."
remove_contact: "Remove contact"
my_activity: "My Activity"
my_stream: "Stream"
my_aspects: "My Aspects"