VRFS-1442 band deletion; band member layout; invitations; band admin support
This commit is contained in:
parent
220fd639e0
commit
9bdddc22ff
|
|
@ -26,30 +26,30 @@ module JamRuby
|
|||
before_save :check_website_url
|
||||
|
||||
# musicians
|
||||
has_many :band_musicians, :class_name => "JamRuby::BandMusician"
|
||||
has_many :band_musicians, :class_name => "JamRuby::BandMusician", dependent: :destroy
|
||||
has_many :users, :through => :band_musicians, :class_name => "JamRuby::User"
|
||||
|
||||
# genres
|
||||
has_many :band_genres, class_name: "JamRuby::BandGenre"
|
||||
has_many :band_genres, class_name: "JamRuby::BandGenre", dependent: :destroy
|
||||
has_many :genres, class_name: "JamRuby::Genre", :through => :band_genres
|
||||
|
||||
# recordings
|
||||
has_many :recordings, :class_name => "JamRuby::Recording", :foreign_key => "band_id"
|
||||
has_many :recordings, :class_name => "JamRuby::Recording", :foreign_key => "band_id", dependent: :destroy
|
||||
|
||||
# self.id = likable_id in likes table
|
||||
has_many :likers, :as => :likable, :class_name => "JamRuby::Like", :dependent => :destroy
|
||||
has_many :likers, :as => :likable, :class_name => "JamRuby::Like", :dependent => :destroy, dependent: :destroy
|
||||
|
||||
# self.id = followable_id in follows table
|
||||
has_many :followers, :as => :followable, :class_name => "JamRuby::Follow", :dependent => :destroy
|
||||
has_many :followers, :as => :followable, :class_name => "JamRuby::Follow", :dependent => :destroy, dependent: :destroy
|
||||
|
||||
# invitations
|
||||
has_many :invitations, :inverse_of => :band, :class_name => "JamRuby::BandInvitation", :foreign_key => "band_id"
|
||||
has_many :invitations, :inverse_of => :band, :class_name => "JamRuby::BandInvitation", :foreign_key => "band_id", dependent: :destroy
|
||||
|
||||
# music_sessions
|
||||
has_many :music_sessions, :class_name => "JamRuby::MusicSession", foreign_key: :band_id, :inverse_of => :band
|
||||
has_many :music_sessions, :class_name => "JamRuby::MusicSession", foreign_key: :band_id, :inverse_of => :band, dependent: :destroy
|
||||
|
||||
# events
|
||||
has_many :event_sessions, :class_name => "JamRuby::EventSession"
|
||||
has_many :event_sessions, :class_name => "JamRuby::EventSession", dependent: :destroy
|
||||
|
||||
include Geokit::ActsAsMappable::Glue unless defined?(acts_as_mappable)
|
||||
acts_as_mappable
|
||||
|
|
@ -114,11 +114,16 @@ module JamRuby
|
|||
end
|
||||
|
||||
def self.musician_index(band_id)
|
||||
@musicians = User.joins(:band_musicians).where(:bands_musicians => {:band_id => "#{band_id}"})
|
||||
@musicians = User
|
||||
.select("users.*, bands_musicians.admin AS band_admin")
|
||||
.joins(:band_musicians)
|
||||
.where(:bands_musicians => {:band_id => "#{band_id}"})
|
||||
end
|
||||
|
||||
def self.pending_musicians(band_id)
|
||||
@musicians = User.joins(:received_band_invitations)
|
||||
@musicians = User
|
||||
.select("users.*, band_invitations.id AS invitation_id")
|
||||
.joins(:received_band_invitations)
|
||||
.where(:band_invitations => {:band_id => "#{band_id}"})
|
||||
.where(:band_invitations => {:accepted => nil})
|
||||
end
|
||||
|
|
@ -285,6 +290,12 @@ module JamRuby
|
|||
Band.connection.execute("UPDATE bands SET lat = geo.latitude, lng = geo.longitude FROM geoiplocations#{table_suffix} as geo WHERE bands.city = geo.city AND bands.state = geo.region AND bands.country = geo.countrycode")
|
||||
end
|
||||
|
||||
def self.is_member?(band_id, user_id)
|
||||
BandMusician.where(band_id: band_id, user_id: user_id)
|
||||
.limit(1)
|
||||
.present?
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def require_at_least_one_genre
|
||||
|
|
|
|||
|
|
@ -7,11 +7,13 @@ module JamRuby
|
|||
|
||||
BAND_INVITATION_FAN_RECIPIENT_ERROR = "A Band invitation can only be sent to a Musician."
|
||||
|
||||
validates_uniqueness_of :user_id, scope: :band_id
|
||||
|
||||
belongs_to :receiver, :inverse_of => :received_band_invitations, :foreign_key => "user_id", :class_name => "JamRuby::User"
|
||||
belongs_to :sender, :inverse_of => :sent_band_invitations, :foreign_key => "creator_id", :class_name => "JamRuby::User"
|
||||
belongs_to :band, :inverse_of => :invitations, :foreign_key => "band_id", :class_name => "JamRuby::Band"
|
||||
|
||||
def self.save(id, band_id, user_id, creator_id, accepted)
|
||||
def self.save(id, band_id, user_id, creator_id, accepted, resend=false)
|
||||
|
||||
band_invitation = BandInvitation.new()
|
||||
|
||||
|
|
@ -39,8 +41,17 @@ module JamRuby
|
|||
# only the accepted flag can be updated after initial creation
|
||||
else
|
||||
band_invitation = BandInvitation.find(id)
|
||||
band_invitation.accepted = accepted
|
||||
band_invitation.save
|
||||
if resend
|
||||
Notification.send_band_invitation(
|
||||
band_invitation.band,
|
||||
band_invitation,
|
||||
band_invitation.sender,
|
||||
band_invitation.receiver
|
||||
)
|
||||
else
|
||||
band_invitation.accepted = accepted
|
||||
band_invitation.save
|
||||
end
|
||||
end
|
||||
|
||||
# accept logic:
|
||||
|
|
@ -69,4 +80,4 @@ module JamRuby
|
|||
band_invitation
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
var rest = context.JK.Rest();
|
||||
var bandId;
|
||||
var isMember = false;
|
||||
var isAdmin = false;
|
||||
var band = {};
|
||||
var instrument_logo_map = context.JK.getInstrumentIconMap24();
|
||||
|
||||
|
|
@ -146,7 +147,8 @@
|
|||
$("#btn-edit-band-profile").show();
|
||||
$("#btn-edit-band-info").show();
|
||||
$("#btn-edit-band-members").show();
|
||||
$("#btn-edit-band-delete").show();
|
||||
if (isAdmin)
|
||||
$("#btn-edit-band-delete").show();
|
||||
}
|
||||
else {
|
||||
$("#btn-follow-band").show();
|
||||
|
|
@ -369,6 +371,8 @@
|
|||
var memberHtml = context.JK.fillTemplate(template, {
|
||||
userId: musician.id,
|
||||
band_admin: bandAdmin,
|
||||
is_pending: isPending,
|
||||
invitation_id: isPending ? musician.invitation_id : '',
|
||||
profile_url: "/client#/profile/" + musician.id,
|
||||
avatar_url: context.JK.resolveAvatarUrl(musician.photo_url),
|
||||
name: musician.name,
|
||||
|
|
@ -391,11 +395,25 @@
|
|||
// var friend = isFriend(musician.id);
|
||||
// configureMemberFriendButton(friend, musician.id);
|
||||
});
|
||||
if (isPending) {
|
||||
$('div[pending-member=true] .btn-reinvite-member').each(function() {
|
||||
var btn = $(this);
|
||||
btn.show();
|
||||
btn.unbind('click');
|
||||
btn.click(function() {
|
||||
var inviteid = $(this).closest('.band-profile-members').attr('invitation-id');
|
||||
rest.resendBandInvitation(bandId, inviteid)
|
||||
.done(function (response) {
|
||||
app.notifyAlert('Band Invitation', 'Your invitation has been re-sent');
|
||||
}).fail(app.ajaxError);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function configureRemoveMemberButton(userId, isPending, bandAdmin) {
|
||||
var $divMember = $('div[user-id=' + userId + ']', '#band-profile-members');
|
||||
var $btnRemoveMember = $divMember.find('#btn-remove-member');
|
||||
var $btnRemoveMember = $divMember.find('.btn-remove-member');
|
||||
if (isMember && !isPending && !bandAdmin) {
|
||||
$btnRemoveMember.show();
|
||||
$btnRemoveMember.unbind("click");
|
||||
|
|
@ -411,6 +429,13 @@
|
|||
rest.removeBandMember(bandId, userId)
|
||||
.done(function() {
|
||||
$divMember.remove();
|
||||
if (userId == context.JK.currentUserId) {
|
||||
$('#btn-edit-band-profile').hide();
|
||||
$('#btn-edit-band-info').hide();
|
||||
$('#btn-edit-band-members').hide();
|
||||
$('.btn-remove-member').each(function(idx) { $(this).hide(); });
|
||||
$('.btn-reinvite-member').each(function(idx) { $(this).hide(); });
|
||||
}
|
||||
})
|
||||
.fail(app.ajaxError);
|
||||
});
|
||||
|
|
@ -435,10 +460,13 @@
|
|||
error: app.ajaxError
|
||||
})
|
||||
.done(function(response) {
|
||||
isMember = false;
|
||||
isAdmin = isMember = false;
|
||||
$.each(response, function(index, val) {
|
||||
if (val.id === context.JK.currentUserId) {
|
||||
isMember = true;
|
||||
if (val.band_admin) {
|
||||
isAdmin = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
|
@ -464,6 +492,23 @@
|
|||
context.location = "/client#/band/setup/" + bandId + '/step2';
|
||||
return false;
|
||||
});
|
||||
$("#btn-edit-band-delete").unbind('click').click(function() {
|
||||
var confirmDialog = new context.JK.ConfirmDialog(app,
|
||||
"DELETE",
|
||||
"Are you sure you want to delete this band? This is a permanent action which cannot be undone.",
|
||||
"Delete Band",
|
||||
function() {
|
||||
app.layout.closeDialog('confirm');
|
||||
rest.deleteBand(bandId)
|
||||
.done(function() {
|
||||
context.location = "/client#/profile/"+context.JK.currentUserId;
|
||||
})
|
||||
.fail(app.ajaxError);
|
||||
});
|
||||
confirmDialog.initialize();
|
||||
context.JK.app.layout.showDialog('confirm');
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
|
|
|||
|
|
@ -127,6 +127,10 @@
|
|||
return band;
|
||||
}
|
||||
|
||||
function showProfile(band_id) {
|
||||
context.location = "/client#/bandProfile/" + band_id;
|
||||
}
|
||||
|
||||
function saveBand() {
|
||||
if (isSaving) return;
|
||||
isSaving = true;
|
||||
|
|
@ -137,9 +141,12 @@
|
|||
rest.createBand(band)
|
||||
.done(function (response) {
|
||||
isSaving = false;
|
||||
createBandInvitations(response.id, function () {
|
||||
context.location = "/client#/bandProfile/" + response.id;
|
||||
});
|
||||
if (0 < $('#selected-friends-band .invitation').length) {
|
||||
createBandInvitations(response.id, function () {
|
||||
showProfile(response.id);
|
||||
});
|
||||
} else
|
||||
showProfile(response.id);
|
||||
})
|
||||
.fail(function (jqXHR) {
|
||||
isSaving = false;
|
||||
|
|
@ -154,7 +161,7 @@
|
|||
.done(function (response) {
|
||||
isSaving = false;
|
||||
createBandInvitations(band.id, function () {
|
||||
context.location = "/client#/bandProfile/" + band.id;
|
||||
showProfile(band.id);
|
||||
});
|
||||
}).fail(function (jqXHR) {
|
||||
isSaving = false;
|
||||
|
|
@ -172,10 +179,13 @@
|
|||
});
|
||||
} else if (step2) {
|
||||
isSaving = false;
|
||||
createBandInvitations(bandId, function () {
|
||||
app.notifyAlert('Band Members', 'Your invitations have been sent');
|
||||
context.location = "/client#/bandProfile/" + bandId;
|
||||
});
|
||||
if (0 < $('#selected-friends-band .invitation').length) {
|
||||
createBandInvitations(bandId, function () {
|
||||
app.notifyAlert('Band Members', 'Your invitations have been sent');
|
||||
showProfile(bandId);
|
||||
});
|
||||
} else
|
||||
showProfile(bandId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -488,8 +498,7 @@
|
|||
$("#band-setup-step-1").show();
|
||||
$("#band-setup-step-2").hide();
|
||||
} else {
|
||||
resetForm();
|
||||
window.history.go(-1);
|
||||
showProfile(bandId);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -350,6 +350,17 @@
|
|||
return deferred;
|
||||
}
|
||||
|
||||
function deleteBand(bandId) {
|
||||
var url = "/api/bands/" + bandId;
|
||||
return $.ajax({
|
||||
type: "DELETE",
|
||||
dataType: "json",
|
||||
url: url,
|
||||
contentType: 'application/json',
|
||||
processData:false
|
||||
});
|
||||
}
|
||||
|
||||
function updateBand(band) {
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
|
|
@ -396,6 +407,17 @@
|
|||
return deferred;
|
||||
}
|
||||
|
||||
function resendBandInvitation(bandId, invitationId) {
|
||||
return $.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
url: '/api/bands/' + bandId + "/invitations/" + invitationId,
|
||||
contentType: 'application/json',
|
||||
processData: false,
|
||||
data: JSON.stringify({"resend": true})
|
||||
})
|
||||
}
|
||||
|
||||
function removeBandMember(bandId, userId) {
|
||||
var url = "/api/bands/" + bandId + "/musicians/" + userId;
|
||||
return $.ajax({
|
||||
|
|
@ -1456,6 +1478,7 @@
|
|||
this.updateBand = updateBand;
|
||||
this.updateBandPhoto = updateBandPhoto;
|
||||
this.deleteBandPhoto = deleteBandPhoto;
|
||||
this.deleteBand = deleteBand;
|
||||
this.getBandPhotoFilepickerPolicy = getBandPhotoFilepickerPolicy;
|
||||
this.getBand = getBand;
|
||||
this.validateBand = validateBand;
|
||||
|
|
@ -1486,6 +1509,7 @@
|
|||
this.updateBillingInfo = updateBillingInfo;
|
||||
this.placeOrder = placeOrder;
|
||||
this.searchMusicians = searchMusicians;
|
||||
this.resendBandInvitation = resendBandInvitation;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ class ApiBandsController < ApiController
|
|||
:recording_create, :recording_update, :recording_destroy,
|
||||
:invitation_index, :invitation_show, :invitation_create, :invitation_destroy,
|
||||
:update_photo, :delete_photo, :generate_filepicker_policy]
|
||||
before_filter :auth_band_admin, :only => [:delete]
|
||||
|
||||
respond_to :json
|
||||
|
||||
|
|
@ -17,6 +18,11 @@ class ApiBandsController < ApiController
|
|||
respond_with_model(@band)
|
||||
end
|
||||
|
||||
def delete
|
||||
@band.try(:destroy)
|
||||
respond_with @band, responder => ApiResponder
|
||||
end
|
||||
|
||||
def create
|
||||
@band = Band.save(current_user, params)
|
||||
|
||||
|
|
@ -148,21 +154,32 @@ class ApiBandsController < ApiController
|
|||
end
|
||||
|
||||
def invitation_create
|
||||
@invitation = BandInvitation.save(nil,
|
||||
params[:id],
|
||||
params[:user_id],
|
||||
current_user.id,
|
||||
params[:accepted])
|
||||
|
||||
respond_with @invitation, responder: ApiResponder, :status => 201, :location => api_band_invitation_detail_url(@band, @invitation)
|
||||
unless Band.is_member?(params[:id], params[:user_id])
|
||||
@invitation = BandInvitation.save(nil,
|
||||
params[:id],
|
||||
params[:user_id],
|
||||
current_user.id,
|
||||
params[:accepted])
|
||||
end
|
||||
respond_with @invitation, responder: ApiResponder, :status => 201
|
||||
# respond_with @invitation, responder: ApiResponder, :status => 201, :location => api_band_invitation_detail_url(@band, @invitation)
|
||||
end
|
||||
|
||||
def invitation_update
|
||||
@invitation = BandInvitation.save(params[:invitation_id],
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
params[:accepted])
|
||||
if params[:resend]
|
||||
@invitation = BandInvitation.save(params[:invitation_id],
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
false,
|
||||
true)
|
||||
else
|
||||
@invitation = BandInvitation.save(params[:invitation_id],
|
||||
nil,
|
||||
nil,
|
||||
nil,
|
||||
params[:accepted])
|
||||
end
|
||||
end
|
||||
|
||||
def invitation_destroy
|
||||
|
|
@ -236,4 +253,11 @@ class ApiBandsController < ApiController
|
|||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
end
|
||||
def auth_band_admin
|
||||
uid = current_user.id
|
||||
@band = Band.find(params[:id])
|
||||
unless @band.band_musicians.detect { |bm| bm.user_id == uid && bm.admin? }
|
||||
raise PermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,7 +3,11 @@ collection @musicians
|
|||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count, :recording_count, :session_count, :biography
|
||||
|
||||
node :band_admin do |musician|
|
||||
't' == musician.band_admin ? true : false
|
||||
musician.respond_to?(:band_admin) && 't' == musician.band_admin ? true : false
|
||||
end
|
||||
|
||||
node :invitation_id do |musician|
|
||||
musician.respond_to?(:invitation_id) ? musician.invitation_id : nil
|
||||
end
|
||||
|
||||
node :instruments do |musician|
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@
|
|||
</div>
|
||||
|
||||
<script type="text/template" id="template-band-profile-members">
|
||||
<div user-id="{userId}" class="band-profile-members" band-admin="{band_admin}">
|
||||
<div user-id="{userId}" class="band-profile-members" band-admin="{band_admin}" pending-member="{is_pending}" invitation-id="{invitation_id}">
|
||||
<div class="left" style="width:63px;">
|
||||
<div class="avatar-small">
|
||||
<img src="{avatar_url}" />
|
||||
|
|
@ -117,9 +117,10 @@
|
|||
</div>
|
||||
<div class="result-list-button-wrapper">
|
||||
<a class="button-orange smallbutton" href="{profile_url}">PROFILE</a>
|
||||
<a id="btn-follow-member" class="button-orange smallbutton">FOLLOW</a>
|
||||
<a id="btn-remove-member" class="button-orange smallbutton">REMOVE MEMBER</a>
|
||||
<a id="btn-friend-member" style="display:none;" class="button-orange smallbutton">CONNECT</a>
|
||||
<a class="btn-follow-member button-orange smallbutton">FOLLOW</a>
|
||||
<a class="btn-remove-member button-orange smallbutton">REMOVE MEMBER</a>
|
||||
<a style="display:none;" class="btn-reinvite-member button-orange smallbutton">RESEND INVITATION</a>
|
||||
<a style="display:none;" class="btn-friend-member button-orange smallbutton">CONNECT</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -209,7 +209,6 @@
|
|||
<span class="profile-band-link-member-false"><a id="btn-follow-band-2" class="button-orange smallbutton">FOLLOW</a></span>
|
||||
<span class="profile-band-link-member-true"><a href="{band_edit_url}" class="button-orange smallbutton">EDIT BAND</a></span>
|
||||
<span class="profile-band-link-member-true"><a href="{band_member_url}" class="button-orange smallbutton">INVITE MEMBERS</a></span>
|
||||
<span class="profile-band-link-delete"><a href="{band_delete_url}" class="button-orange smallbutton">DELETE</a></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ SampleApp::Application.routes.draw do
|
|||
match '/bands/:id' => 'api_bands#show', :via => :get, :as => 'api_band_detail'
|
||||
match '/bands' => 'api_bands#create', :via => :post
|
||||
match '/bands/:id' => 'api_bands#update', :via => :post
|
||||
match '/bands/:id' => 'api_bands#delete', :via => :delete
|
||||
|
||||
# photo
|
||||
match '/bands/:id/photo' => 'api_bands#update_photo', :via => :post
|
||||
|
|
|
|||
Loading…
Reference in New Issue