diff --git a/db/manifest b/db/manifest index 986692c75..9f19d8fe7 100755 --- a/db/manifest +++ b/db/manifest @@ -77,3 +77,4 @@ whats_next.sql add_user_bio.sql users_geocoding.sql recordings_public_launch.sql +notification_band_invite.sql \ No newline at end of file diff --git a/db/up/notification_band_invite.sql b/db/up/notification_band_invite.sql new file mode 100644 index 000000000..7a020c15a --- /dev/null +++ b/db/up/notification_band_invite.sql @@ -0,0 +1,2 @@ +alter table notifications add column band_invitation_id VARCHAR(64) +REFERENCES band_invitations(id) ON DELETE CASCADE; \ No newline at end of file diff --git a/pb/src/client_container.proto b/pb/src/client_container.proto index ebe125766..bb65174dc 100644 --- a/pb/src/client_container.proto +++ b/pb/src/client_container.proto @@ -30,6 +30,8 @@ message ClientMessage { HEARTBEAT_ACK = 117; JOIN_REQUEST_APPROVED = 118; JOIN_REQUEST_REJECTED = 119; + BAND_INVITATION = 120; + BAND_INVITATION_ACCEPTED = 121; TEST_SESSION_MESSAGE = 200; @@ -76,6 +78,8 @@ message ClientMessage { optional HeartbeatAck heartbeat_ack = 117; optional JoinRequestApproved join_request_approved = 118; optional JoinRequestRejected join_request_rejected = 119; + optional BandInvitation band_invitation = 120; + optional BandInvitationAccepted band_invitation_accepted = 121; // Client-Session messages (to/from) optional TestSessionMessage test_session_message = 200; @@ -219,7 +223,7 @@ message JoinRequestApproved { } message JoinRequestRejected { - optional string join_request_id = 1; + optional string invitation_id = 1; optional string session_id = 2; optional string username = 3; optional string photo_url = 4; @@ -228,6 +232,29 @@ message JoinRequestRejected { optional string created_at = 7; } +message BandInvitation { + optional string band_invitation_id = 1; + optional string band_id = 2; + optional string user_id = 3; + optional string username = 4; + optional string photo_url = 5; + optional string band_name = 6; + optional string msg = 7; + optional string notification_id = 8; + optional string created_at = 9; +} + +message BandInvitationAccepted { + optional string band_invitation_id = 1; + optional string user_id = 2; + optional string username = 3; + optional string photo_url = 4; + optional string band_name = 5; + optional string msg = 6; + optional string notification_id = 7; + optional string created_at = 8; +} + // route_to: session // a test message used by ruby-client currently. just gives way to send out to rest of session message TestSessionMessage { diff --git a/ruby/lib/jam_ruby/constants/notification_types.rb b/ruby/lib/jam_ruby/constants/notification_types.rb index dd75281b2..272095f59 100644 --- a/ruby/lib/jam_ruby/constants/notification_types.rb +++ b/ruby/lib/jam_ruby/constants/notification_types.rb @@ -1,23 +1,27 @@ module NotificationTypes - # friend notifications - FRIEND_UPDATE = "FRIEND_UPDATE" - FRIEND_REQUEST = "FRIEND_REQUEST" - FRIEND_REQUEST_ACCEPTED = "FRIEND_REQUEST_ACCEPTED" - FRIEND_SESSION_JOIN = "FRIEND_SESSION_JOIN" + # friend notifications + FRIEND_UPDATE = "FRIEND_UPDATE" + FRIEND_REQUEST = "FRIEND_REQUEST" + FRIEND_REQUEST_ACCEPTED = "FRIEND_REQUEST_ACCEPTED" + FRIEND_SESSION_JOIN = "FRIEND_SESSION_JOIN" - # session notifications - SESSION_INVITATION = "SESSION_INVITATION" - SESSION_ENDED = "SESSION_ENDED" # used to remove session-related notification from sidebar - JOIN_REQUEST = "JOIN_REQUEST" - JOIN_REQUEST_APPROVED = "JOIN_REQUEST_APPROVED" - JOIN_REQUEST_REJECTED = "JOIN_REQUEST_REJECTED" + # session notifications + SESSION_INVITATION = "SESSION_INVITATION" + SESSION_ENDED = "SESSION_ENDED" # used to remove session-related notification from sidebar + JOIN_REQUEST = "JOIN_REQUEST" + JOIN_REQUEST_APPROVED = "JOIN_REQUEST_APPROVED" + JOIN_REQUEST_REJECTED = "JOIN_REQUEST_REJECTED" - # musician notifications - MUSICIAN_SESSION_JOIN = "MUSICIAN_SESSION_JOIN" - MUSICIAN_SESSION_DEPART = "MUSICIAN_SESSION_DEPART" + # musician notifications + MUSICIAN_SESSION_JOIN = "MUSICIAN_SESSION_JOIN" + MUSICIAN_SESSION_DEPART = "MUSICIAN_SESSION_DEPART" - # recording notifications - RECORDING_CREATED = "RECORDING_CREATED" + # recording notifications + RECORDING_CREATED = "RECORDING_CREATED" + + # band notifications + BAND_INVITATION = "BAND_INVITATION" + BAND_INVITATION_ACCEPTED = "BAND_INVITATION_ACCEPTED" end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/message_factory.rb b/ruby/lib/jam_ruby/message_factory.rb index c21df795e..ae522ef84 100644 --- a/ruby/lib/jam_ruby/message_factory.rb +++ b/ruby/lib/jam_ruby/message_factory.rb @@ -24,157 +24,412 @@ # create a login message using user/pass def login_with_user_pass(username, password, options = {}) - login = Jampb::Login.new(:username => username, :password => password, :client_id => options[:client_id]) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LOGIN, :route_to => SERVER_TARGET, :login => login) + login = Jampb::Login.new( + :username => username, + :password => password, + :client_id => options[:client_id] + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LOGIN, + :route_to => SERVER_TARGET, + :login => login + ) end # create a login message using token (a cookie or similar) def login_with_token(token, options = {}) - login = Jampb::Login.new(:token => token, :client_id => options[:client_id]) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LOGIN, :route_to => SERVER_TARGET, :login => login) + login = Jampb::Login.new( + :token => token, + :client_id => options[:client_id] + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LOGIN, + :route_to => SERVER_TARGET, + :login => login + ) end # create a login ack (login was successful) def login_ack(public_ip, client_id, token, heartbeat_interval, music_session_id, reconnected) - login_ack = Jampb::LoginAck.new(:public_ip => public_ip, :client_id => client_id, :token => token, :heartbeat_interval => heartbeat_interval, :music_session_id => music_session_id, :reconnected => reconnected) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LOGIN_ACK, :route_to => CLIENT_TARGET, :login_ack => login_ack) + login_ack = Jampb::LoginAck.new( + :public_ip => public_ip, + :client_id => client_id, + :token => token, + :heartbeat_interval => heartbeat_interval, + :music_session_id => music_session_id, + :reconnected => reconnected + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LOGIN_ACK, + :route_to => CLIENT_TARGET, + :login_ack => login_ack + ) end # create a music session login message def login_music_session(music_session) login_music_session = Jampb::LoginMusicSession.new(:music_session => music_session) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LOGIN_MUSIC_SESSION, :route_to => SERVER_TARGET, :login_music_session => login_music_session) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LOGIN_MUSIC_SESSION, + :route_to => SERVER_TARGET, + :login_music_session => login_music_session + ) end # create a music session login message ack (success or on failure) def login_music_session_ack(error, error_reason) login_music_session_ack = Jampb::LoginMusicSessionAck.new(:error => error, :error_reason => error_reason) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LOGIN_MUSIC_SESSION_ACK, :route_to => CLIENT_TARGET, :login_music_session_ack => login_music_session_ack) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LOGIN_MUSIC_SESSION_ACK, + :route_to => CLIENT_TARGET, + :login_music_session_ack => login_music_session_ack + ) end # create a music session 'leave session' message def leave_music_session(music_session) leave_music_session = Jampb::LeaveMusicSession.new(:music_session => music_session) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LEAVE_MUSIC_SESSION, :route_to => SERVER_TARGET, :leave_music_session => leave_music_session) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LEAVE_MUSIC_SESSION, + :route_to => SERVER_TARGET, + :leave_music_session => leave_music_session + ) end # create a music session leave message ack (success or on failure) def leave_music_session_ack(error, error_reason) leave_music_session_ack = Jampb::LeaveMusicSessionAck.new(:error => error, :error_reason => error_reason) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::LEAVE_MUSIC_SESSION_ACK, :route_to => CLIENT_TARGET, :leave_music_session_ack => leave_music_session_ack) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::LEAVE_MUSIC_SESSION_ACK, + :route_to => CLIENT_TARGET, + :leave_music_session_ack => leave_music_session_ack + ) end # create a server bad state recovered msg def server_bad_state_recovered(original_message_id) recovered = Jampb::ServerBadStateRecovered.new() - return Jampb::ClientMessage.new(:type => ClientMessage::Type::SERVER_BAD_STATE_RECOVERED, :route_to => CLIENT_TARGET, :server_bad_state_recovered => recovered, :in_reply_to => original_message_id) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::SERVER_BAD_STATE_RECOVERED, + :route_to => CLIENT_TARGET, + :server_bad_state_recovered => recovered, + :in_reply_to => original_message_id + ) end # create a server error def server_generic_error(error_msg) error = Jampb::ServerGenericError.new(:error_msg => error_msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::SERVER_GENERIC_ERROR, :route_to => CLIENT_TARGET, :server_generic_error => error) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::SERVER_GENERIC_ERROR, + :route_to => CLIENT_TARGET, + :server_generic_error => error + ) end # create a server rejection error def server_rejection_error(error_msg) error = Jampb::ServerRejectionError.new(:error_msg => error_msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::SERVER_REJECTION_ERROR, :route_to => CLIENT_TARGET, :server_rejection_error => error) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::SERVER_REJECTION_ERROR, + :route_to => CLIENT_TARGET, + :server_rejection_error => error + ) end # create a server rejection error def server_permission_error(original_message_id, error_msg) error = Jampb::ServerPermissionError.new(:error_msg => error_msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::SERVER_PERMISSION_ERROR, :route_to => CLIENT_TARGET, :server_permission_error => error, :in_reply_to => original_message_id) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::SERVER_PERMISSION_ERROR, + :route_to => CLIENT_TARGET, + :server_permission_error => error, + :in_reply_to => original_message_id + ) end # create a server bad state error def server_bad_state_error(original_message_id, error_msg) error = Jampb::ServerBadStateError.new(:error_msg => error_msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::SERVER_BAD_STATE_ERROR, :route_to => CLIENT_TARGET, :server_bad_state_error => error, :in_reply_to => original_message_id) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::SERVER_BAD_STATE_ERROR, + :route_to => CLIENT_TARGET, + :server_bad_state_error => error, + :in_reply_to => original_message_id + ) end # create a friend joined session message def friend_session_join(session_id, user_id, username, photo_url) - join = Jampb::FriendSessionJoin.new(:session_id => session_id, :user_id => user_id, :username => username, :photo_url => photo_url) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_SESSION_JOIN, :route_to => CLIENT_TARGET, :friend_session_join => join) + join = Jampb::FriendSessionJoin.new( + :session_id => session_id, + :user_id => user_id, + :username => username, + :photo_url => photo_url + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::FRIEND_SESSION_JOIN, + :route_to => CLIENT_TARGET, + :friend_session_join => join + ) end # create a musician joined session message def musician_session_join(session_id, user_id, username, photo_url) - join = Jampb::MusicianSessionJoin.new(:session_id => session_id, :user_id => user_id, :username => username, :photo_url => photo_url) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::MUSICIAN_SESSION_JOIN, :route_to => CLIENT_TARGET, :musician_session_join => join) + join = Jampb::MusicianSessionJoin.new( + :session_id => session_id, + :user_id => user_id, + :username => username, + :photo_url => photo_url + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::MUSICIAN_SESSION_JOIN, + :route_to => CLIENT_TARGET, + :musician_session_join => join + ) end # create a musician left session message def musician_session_depart(session_id, user_id, username, photo_url, recordingId = nil) - left = Jampb::MusicianSessionDepart.new(:session_id => session_id, :user_id => user_id, :username => username, :photo_url => photo_url, :recordingId => recordingId) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::MUSICIAN_SESSION_DEPART, :route_to => CLIENT_TARGET, :musician_session_depart => left) + left = Jampb::MusicianSessionDepart.new( + :session_id => session_id, + :user_id => user_id, + :username => username, + :photo_url => photo_url, + :recordingId => recordingId + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::MUSICIAN_SESSION_DEPART, + :route_to => CLIENT_TARGET, + :musician_session_depart => left + ) end # create a musician fresh session message def musician_session_fresh(session_id, user_id, username, photo_url) - fresh = Jampb::MusicianSessionFresh.new(:session_id => session_id, :user_id => user_id, :username => username, :photo_url => photo_url) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::MUSICIAN_SESSION_FRESH, :route_to => CLIENT_TARGET, :musician_session_fresh => fresh) + fresh = Jampb::MusicianSessionFresh.new( + :session_id => session_id, + :user_id => user_id, + :username => username, + :photo_url => photo_url + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::MUSICIAN_SESSION_FRESH, + :route_to => CLIENT_TARGET, + :musician_session_fresh => fresh + ) end # create a musician stale session message def musician_session_stale(session_id, user_id, username, photo_url) - stale = Jampb::MusicianSessionStale.new(:session_id => session_id, :user_id => user_id, :username => username, :photo_url => photo_url) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::MUSICIAN_SESSION_STALE, :route_to => CLIENT_TARGET, :musician_session_stale => stale) + stale = Jampb::MusicianSessionStale.new( + :session_id => session_id, + :user_id => user_id, + :username => username, + :photo_url => photo_url + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::MUSICIAN_SESSION_STALE, + :route_to => CLIENT_TARGET, + :musician_session_stale => stale + ) end # create a join request session message def join_request(join_request_id, session_id, username, photo_url, msg, notification_id, created_at) - req = Jampb::JoinRequest.new(:join_request_id => join_request_id, :session_id => session_id, :username => username, :photo_url => photo_url, :msg => msg, :notification_id => notification_id, :created_at => created_at) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request => req) + req = Jampb::JoinRequest.new( + :join_request_id => join_request_id, + :session_id => session_id, + :username => username, + :photo_url => photo_url, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::JOIN_REQUEST, + :route_to => SESSION_TARGET_PREFIX + session_id, + :join_request => req + ) end # create a join request approved session message def join_request_approved(join_request_id, session_id, username, photo_url, msg, notification_id, created_at) - req_approved = Jampb::JoinRequestApproved.new(:join_request_id => join_request_id, :session_id => session_id, :username => username, :photo_url => photo_url, :msg => msg, :notification_id => notification_id, :created_at => created_at) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST_APPROVED, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request_approved => req_approved) + req_approved = Jampb::JoinRequestApproved.new( + :join_request_id => join_request_id, + :session_id => session_id, + :username => username, + :photo_url => photo_url, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::JOIN_REQUEST_APPROVED, + :route_to => SESSION_TARGET_PREFIX + session_id, + :join_request_approved => req_approved + ) end # create a join request rejected session message def join_request_rejected(join_request_id, session_id, username, photo_url, msg, notification_id, created_at) - req_rejected = Jampb::JoinRequestRejected.new(:join_request_id => join_request_id, :session_id => session_id, :username => username, :photo_url => photo_url, :msg => msg, :notification_id => notification_id, :created_at => created_at) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::JOIN_REQUEST_REJECTED, :route_to => SESSION_TARGET_PREFIX + session_id, :join_request_rejected => req_rejected) + req_rejected = Jampb::JoinRequestRejected.new( + :join_request_id => join_request_id, + :session_id => session_id, + :username => username, + :photo_url => photo_url, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::JOIN_REQUEST_REJECTED, + :route_to => SESSION_TARGET_PREFIX + session_id, + :join_request_rejected => req_rejected + ) + end + + # create a band invitation message + def band_invitation(invitation_id, band_id, receiver_id, username, photo_url, band_name, msg, notification_id, created_at) + band_invitation = Jampb::BandInvitation.new( + :band_invitation_id => invitation_id, + :band_id => band_id, + :user_id => receiver_id, + :username => username, + :photo_url => photo_url, + :band_name => band_name, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::BAND_INVITATION, + :route_to => USER_TARGET_PREFIX + receiver_id, + :band_invitation => band_invitation + ) + end + + # create a band invitation acceptance message + def band_invitation_accepted(invitation_id, receiver_id, username, photo_url, band_name, msg, notification_id, created_at) + band_invitation_accepted = Jampb::BandInvitationAccepted.new( + :band_invitation_id => invitation_id, + :user_id => receiver_id, + :username => username, + :photo_url => photo_url, + :band_name => band_name, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::BAND_INVITATION_ACCEPTED, + :route_to => USER_TARGET_PREFIX + receiver_id, + :band_invitation_accepted => band_invitation_accepted + ) end # create a test message to send in session def test_session_message(session_id, msg) test = Jampb::TestSessionMessage.new(:msg => msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::TEST_SESSION_MESSAGE, :route_to => SESSION_TARGET_PREFIX + session_id, :test_session_message => test) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::TEST_SESSION_MESSAGE, + :route_to => SESSION_TARGET_PREFIX + session_id, + :test_session_message => test + ) end def session_invitation(receiver_id, sender_name, session_id, notification_id, created_at) - session_invitation = Jampb::SessionInvitation.new(:sender_name => sender_name, :session_id => session_id, :notification_id => notification_id, :created_at => created_at) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::SESSION_INVITATION, :route_to => USER_TARGET_PREFIX + receiver_id, :session_invitation => session_invitation) + session_invitation = Jampb::SessionInvitation.new( + :sender_name => sender_name, + :session_id => session_id, + :notification_id => notification_id, + :created_at => created_at + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::SESSION_INVITATION, + :route_to => USER_TARGET_PREFIX + receiver_id, + :session_invitation => session_invitation + ) end # create a friend update message def friend_update(user_id, name, photo_url, online, msg) - friend = Jampb::FriendUpdate.new(:user_id => user_id, :name => name, :photo_url => photo_url, :online => online, :msg => msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_UPDATE, :route_to => USER_TARGET_PREFIX + user_id, :friend_update => friend) + friend = Jampb::FriendUpdate.new( + :user_id => user_id, + :name => name, + :photo_url => photo_url, + :online => online, + :msg => msg + ) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::FRIEND_UPDATE, + :route_to => USER_TARGET_PREFIX + user_id, + :friend_update => friend + ) end # create a friend request message def friend_request(friend_request_id, user_id, name, photo_url, friend_id, msg, notification_id, created_at) - friend_request = Jampb::FriendRequest.new(:friend_request_id => friend_request_id, - :user_id => user_id, :name => name, :photo_url => photo_url, :friend_id => friend_id, :msg => msg, - :notification_id => notification_id, :created_at => created_at) + friend_request = Jampb::FriendRequest.new( + :friend_request_id => friend_request_id, + :user_id => user_id, + :name => name, + :photo_url => photo_url, + :friend_id => friend_id, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST, :route_to => USER_TARGET_PREFIX + friend_id, :friend_request => friend_request) + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::FRIEND_REQUEST, + :route_to => USER_TARGET_PREFIX + friend_id, + :friend_request => friend_request + ) end # create a friend request acceptance message def friend_request_accepted(friend_id, name, photo_url, user_id, msg, notification_id, created_at) - friend_request_accepted = Jampb::FriendRequestAccepted.new(:friend_id => friend_id, - :name => name, :photo_url => photo_url, :user_id => user_id, :msg => msg, - :notification_id => notification_id, :created_at => created_at) + friend_request_accepted = Jampb::FriendRequestAccepted.new( + :friend_id => friend_id, + :name => name, + :photo_url => photo_url, + :user_id => user_id, + :msg => msg, + :notification_id => notification_id, + :created_at => created_at + ) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED, :route_to => USER_TARGET_PREFIX + user_id, :friend_request_accepted => friend_request_accepted) + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::FRIEND_REQUEST_ACCEPTED, + :route_to => USER_TARGET_PREFIX + user_id, + :friend_request_accepted => friend_request_accepted + ) end ############## P2P CLIENT MESSAGES ################# @@ -182,19 +437,37 @@ # send a request to do a ping def ping_request(client_id, from) ping_request = Jampb::PingRequest.new() - return Jampb::ClientMessage.new(:type => ClientMessage::Type::PING_REQUEST, :route_to => CLIENT_TARGET_PREFIX + client_id, :from => from, :ping_request => ping_request) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::PING_REQUEST, + :route_to => CLIENT_TARGET_PREFIX + client_id, + :from => from, + :ping_request => ping_request + ) end # respond to a ping_request with an ack def ping_ack(client_id, from) - ping_ack = Jampb::PingAck.new() - return Jampb::ClientMessage.new(:type => ClientMessage::Type::PING_ACK, :route_to => CLIENT_TARGET_PREFIX + client_id, :from => from, :ping_ack => ping_ack) + ping_ack = Jampb::PingAck.new + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::PING_ACK, + :route_to => CLIENT_TARGET_PREFIX + client_id, + :from => from, + :ping_ack => ping_ack + ) end # create a test message to send in session def test_client_message(client_id, from, msg) test = Jampb::TestClientMessage.new(:msg => msg) - return Jampb::ClientMessage.new(:type => ClientMessage::Type::TEST_CLIENT_MESSAGE, :route_to => CLIENT_TARGET_PREFIX + client_id, :from => from, :test_client_message => test) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::TEST_CLIENT_MESSAGE, + :route_to => CLIENT_TARGET_PREFIX + client_id, + :from => from, + :test_client_message => test + ) end #################################################### @@ -202,13 +475,23 @@ # create a heartbeat def heartbeat() heartbeat = Jampb::Heartbeat.new - return Jampb::ClientMessage.new(:type => ClientMessage::Type::HEARTBEAT, :route_to => SERVER_TARGET, :heartbeat => heartbeat) + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::HEARTBEAT, + :route_to => SERVER_TARGET, + :heartbeat => heartbeat + ) end # create a heartbeat ack def heartbeat_ack() - heartbeat_ack = Jampb::HeartbeatAck.new() - return Jampb::ClientMessage.new(:type => ClientMessage::Type::HEARTBEAT_ACK, :route_to => CLIENT_TARGET, :heartbeat_ack => heartbeat_ack) + heartbeat_ack = Jampb::HeartbeatAck.new + + return Jampb::ClientMessage.new( + :type => ClientMessage::Type::HEARTBEAT_ACK, + :route_to => CLIENT_TARGET, + :heartbeat_ack => heartbeat_ack + ) end # is this message directed to the server? diff --git a/ruby/lib/jam_ruby/models/band_invitation.rb b/ruby/lib/jam_ruby/models/band_invitation.rb index 4459701eb..c8b6b038d 100644 --- a/ruby/lib/jam_ruby/models/band_invitation.rb +++ b/ruby/lib/jam_ruby/models/band_invitation.rb @@ -27,22 +27,38 @@ module JamRuby band_invitation.band_id = band_id band_invitation.user_id = user_id band_invitation.creator_id = creator_id + band_invitation.save + + Notification.send_band_invitation( + band_invitation.band, + band_invitation, + band_invitation.sender, + band_invitation.receiver + ) # only the accepted flag can be updated after initial creation else band_invitation = BandInvitation.find(id) band_invitation.accepted = accepted + band_invitation.save end - band_invitation.updated_at = Time.now.getutc - band_invitation.save - - # accept logic => (1) auto-friend each band member and (2) add the musician to the band + # accept logic: + # (1) auto-friend each band member + # (2) add the musician to the band + # (3) send BAND_INVITATION_ACCEPTED notification if accepted band_musicians = BandMusician.where(:band_id => band_invitation.band.id) - unless band_musicians.nil? + unless band_musicians.blank? + # auto-friend and notify each band member band_musicians.each do |bm| Friendship.save(band_invitation.receiver.id, bm.user_id) + Notification.send_band_invitation_accepted( + band_invitation.band, + band_invitation, + band_invitation.receiver, + bm.user + ) end end @@ -50,7 +66,7 @@ module JamRuby BandMusician.create(:band_id => band_invitation.band.id, :user_id => band_invitation.receiver.id, :admin => false) end end - return band_invitation + band_invitation end end end \ No newline at end of file diff --git a/ruby/lib/jam_ruby/models/notification.rb b/ruby/lib/jam_ruby/models/notification.rb index 4f7a8a284..0d2165ae8 100644 --- a/ruby/lib/jam_ruby/models/notification.rb +++ b/ruby/lib/jam_ruby/models/notification.rb @@ -147,10 +147,12 @@ module JamRuby when NotificationTypes::JOIN_REQUEST_REJECTED return "We're sorry, but you cannot join the session at this time." - # when "social_media_friend_joined" - # when "band_invitation" - # when "band_invitation_accepted" - # when "recording_available" + when NotificationTypes::BAND_INVITATION + return "You have been invited to join the band #{name}." + + when NotificationTypes::BAND_INVITATION_ACCEPTED + return "#{name} has accepted your band invitation." + else return "" end @@ -162,13 +164,18 @@ module JamRuby # (1) get all of this user's friends friend_ids = retrieve_friends(connection, user_id) - if friend_ids.length > 0 + unless friend_ids.blank? user = User.find(user_id) # (2) create notification online_msg = online ? "online." : "offline." notification_msg = format_msg(NotificationTypes::FRIEND_UPDATE, user) + online_msg - msg = @@message_factory.friend_update(user_id, user.name, user.photo_url, online, notification_msg) + msg = @@message_factory.friend_update( + user_id, user.name, + user.photo_url, + online, + notification_msg + ) # (3) send notification @@mq_router.publish_to_friends(friend_ids, msg, user_id) @@ -189,7 +196,16 @@ module JamRuby # (2) create notification notification_msg = format_msg(notification.description, user) - msg = @@message_factory.friend_request(friend_request_id, user_id, user.name, user.photo_url, friend_id, notification_msg, notification.id, notification.created_at.to_s) + msg = @@message_factory.friend_request( + friend_request_id, + user_id, + user.name, + user.photo_url, + friend_id, + notification_msg, + notification.id, + notification.created_at.to_s + ) # (3) send notification @@mq_router.publish_to_user(friend_id, msg) @@ -208,7 +224,14 @@ module JamRuby # (2) create notification notification_msg = format_msg(notification.description, friend) - msg = @@message_factory.friend_request_accepted(friend_id, friend.name, friend.photo_url, user_id, notification_msg, notification.id, notification.created_at.to_s) + msg = @@message_factory.friend_request_accepted( + friend_id, + friend.name, + friend.photo_url, + user_id, notification_msg, + notification.id, + notification.created_at.to_s + ) # (3) send notification @@mq_router.publish_to_user(user_id, msg) @@ -226,48 +249,80 @@ module JamRuby notification.save # (2) create notification - msg = @@message_factory.session_invitation(receiver_id, sender.name, session_id, notification.id, notification.created_at.to_s) + msg = @@message_factory.session_invitation( + receiver_id, + sender.name, + session_id, + notification.id, + notification.created_at.to_s + ) # (3) send notification @@mq_router.publish_to_user(receiver_id, msg) end + ################## SESSION INVITATION ################## def send_musician_session_join(music_session, connection, user) # (1) create notification - msg = @@message_factory.musician_session_join(music_session.id, user.id, user.name, user.photo_url) + msg = @@message_factory.musician_session_join( + music_session.id, + user.id, + user.name, + user.photo_url + ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => connection.client_id}) end + ################## MUSICIAN SESSION DEPART ################## def send_musician_session_depart(music_session, client_id, user, recordingId = nil) # (1) create notification - msg = @@message_factory.musician_session_depart(music_session.id, user.id, user.name, user.photo_url, recordingId) + msg = @@message_factory.musician_session_depart( + music_session.id, + user.id, + user.name, + user.photo_url, + recordingId + ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id}) end + ################## MUSICIAN SESSION FRESH ################## def send_musician_session_fresh(music_session, client_id, user) # (1) create notification - msg = @@message_factory.musician_session_fresh(music_session.id, user.id, user.name, user.photo_url) + msg = @@message_factory.musician_session_fresh( + music_session.id, + user.id, + user.name, + user.photo_url + ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id}) end + ################## MUSICIAN SESSION STALE ################## def send_musician_session_stale(music_session, client_id, user) # (1) create notification - msg = @@message_factory.musician_session_stale(music_session.id, user.id, user.name, user.photo_url) + msg = @@message_factory.musician_session_stale( + music_session.id, + user.id, + user.name, + user.photo_url + ) # (2) send notification @@mq_router.server_publish_to_session(music_session, msg, sender = {:client_id => client_id}) end + ################## FRIEND SESSION JOIN ################## def send_friend_session_join(db_conn, connection, user) ids = retrieve_friends_and_followers_not_in_session(db_conn, user.id, connection.music_session.id) @@ -275,13 +330,18 @@ module JamRuby # (1) save to database # (2) create notification - msg = @@message_factory.friend_session_join(connection.music_session.id, user.id, user.name, user.photo_url) + msg = @@message_factory.friend_session_join( + connection.music_session.id, + user.id, + user.name, + user.photo_url) # (3) send notification @@mq_router.publish_to_friends(ids, msg, sender = {:client_id => connection.client_id}) end end + ################## JOIN REQUEST ################## def send_join_request(music_session, join_request, text) # (1) save to database @@ -294,12 +354,21 @@ module JamRuby # (2) create notification notification_msg = format_msg(notification.description, join_request.user) - msg = @@message_factory.join_request(join_request.id, music_session.id, join_request.user.name, join_request.user.photo_url, notification_msg, notification.id, notification.created_at.to_s) + msg = @@message_factory.join_request( + join_request.id, + music_session.id, + join_request.user.name, + join_request.user.photo_url, + notification_msg, + notification.id, + notification.created_at.to_s + ) # (3) send notification @@mq_router.publish_to_user(music_session.creator.id, msg) end + ################## JOIN REQUEST APPROVED ################## def send_join_request_approved(music_session, join_request) # (1) save to database @@ -312,12 +381,21 @@ module JamRuby # (2) create notification notification_msg = format_msg(notification.description, music_session.creator) - msg = @@message_factory.join_request_approved(join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification_msg, notification.id, notification.created_at.to_s) + msg = @@message_factory.join_request_approved( + join_request.id, + music_session.id, + music_session.creator.name, + music_session.creator.photo_url, + notification_msg, + notification.id, + notification.created_at.to_s + ) # (3) send notification @@mq_router.publish_to_user(join_request.user.id, msg) end + ################## JOIN REQUEST REJECTED ################## def send_join_request_rejected(music_session, join_request) # (1) save to database @@ -330,12 +408,78 @@ module JamRuby # (2) create notification notification_msg = format_msg(notification.description, music_session.creator) - msg = @@message_factory.join_request_rejected(join_request.id, music_session.id, music_session.creator.name, music_session.creator.photo_url, notification_msg, notification.id, notification.created_at.to_s) + msg = @@message_factory.join_request_rejected( + join_request.id, + music_session.id, + music_session.creator.name, + music_session.creator.photo_url, + notification_msg, + notification.id, + notification.created_at.to_s + ) # (3) send notification @@mq_router.publish_to_user(join_request.user.id, msg) end + ################## BAND INVITATION ################## + def send_band_invitation(band, band_invitation, sender, receiver) + + # (1) save to database + notification = Notification.new + notification.band_id = band.id + notification.band_invitation_id = band_invitation.id + notification.description = NotificationTypes::BAND_INVITATION + notification.source_user_id = sender.id + notification.target_user_id = receiver.id + notification.save + + # (2) create notification + notification_msg = format_msg(notification.description, band) + msg = @@message_factory.band_invitation( + band_invitation.id, + band.id, + receiver.id, + sender.name, + sender.photo_url, + band.name, + notification_msg, + notification.id, + notification.created_at.to_s + ) + + # (3) send notification + @@mq_router.publish_to_user(receiver.id, msg) + end + + ################## BAND INVITATION ACCEPTED ################## + def send_band_invitation_accepted(band, band_invitation, sender, receiver) + + # (1) save to database + notification = Notification.new + notification.band_id = band.id + notification.description = NotificationTypes::BAND_INVITATION_ACCEPTED + notification.source_user_id = sender.id + notification.target_user_id = receiver.id + notification.save + + # (2) create notification + notification_msg = format_msg(notification.description, sender) + msg = @@message_factory.band_invitation_accepted( + band_invitation.id, + receiver.id, + sender.name, + sender.photo_url, + band.name, + notification_msg, + notification.id, + notification.created_at.to_s + ) + + # (3) send notification + @@mq_router.publish_to_user(receiver.id, msg) + end + end end end \ No newline at end of file diff --git a/web/app/assets/javascripts/AAB_message_factory.js b/web/app/assets/javascripts/AAB_message_factory.js index 9f17ab77c..b648b7ec9 100644 --- a/web/app/assets/javascripts/AAB_message_factory.js +++ b/web/app/assets/javascripts/AAB_message_factory.js @@ -26,6 +26,8 @@ JOIN_REQUEST_REJECTED : "JOIN_REQUEST_REJECTED", FRIEND_REQUEST : "FRIEND_REQUEST", FRIEND_REQUEST_ACCEPTED : "FRIEND_REQUEST_ACCEPTED", + BAND_INVITATION : "BAND_INVITATION", + BAND_INVITATION_ACCEPTED : "BAND_INVITATION_ACCEPTED", TEST_SESSION_MESSAGE : "TEST_SESSION_MESSAGE", PING_REQUEST : "PING_REQUEST", PING_ACK : "PING_ACK", diff --git a/web/app/assets/javascripts/bandProfile.js b/web/app/assets/javascripts/bandProfile.js index 54d0130d1..fd7938c3f 100644 --- a/web/app/assets/javascripts/bandProfile.js +++ b/web/app/assets/javascripts/bandProfile.js @@ -160,20 +160,27 @@ } function configureMemberFollowingButton(following, userId) { - var $btnFollowMember = $('div[user-id=' + userId + ']', '#band-profile-members').find('#btn-follow-member'); - $btnFollowMember.unbind("click"); - if (following) { - $btnFollowMember.text('UN-FOLLOW'); - $btnFollowMember.click(function() { - removeFollowing(false, userId); - }); + var $btnFollowMember = $('div[user-id=' + userId + ']', '#band-profile-members').find('#btn-follow-member'); + + if (context.JK.currentUserId === userId) { + $btnFollowMember.hide(); } else { - $btnFollowMember.text('FOLLOW'); - $btnFollowMember.click(function() { - addFollowing(false, userId); - }); + $btnFollowMember.unbind("click"); + + if (following) { + $btnFollowMember.text('UN-FOLLOW'); + $btnFollowMember.click(function() { + removeFollowing(false, userId); + }); + } + else { + $btnFollowMember.text('FOLLOW'); + $btnFollowMember.click(function() { + addFollowing(false, userId); + }); + } } } @@ -374,18 +381,27 @@ }); } - function formatGenres(genres) { - var formattedGenres = ''; - if (genres) { - for (var i=0; i < genres.length; i++) { - var genre = genres[i]; - formattedGenres += genre.description; - if (i < genres.length -1) { - formattedGenres += ', '; - } - } - } - return formattedGenres; + // TODO: refactor + function isMember() { + var isMember = false; + var url = "/api/bands/" + bandId + "/musicians"; + $.ajax({ + type: "GET", + dataType: "json", + url: url, + async: false, + processData:false, + success: function(response) { + $.each(response, function(index, val) { + if (val.id === context.JK.currentUserId) { + isMember = true; + } + }); + }, + error: app.ajaxError + }); + + return isMember; } // events for main screen @@ -399,6 +415,16 @@ // wire up Follow click var following = isFollowing(); configureBandFollowingButton(following); + + var member = isMember(); + if (member) { + $("#btn-follow-band").hide(); + $("#btn-edit-band-members").show(); + } + else { + $("#btn-follow-band").show(); + $("#btn-edit-band-members").hide(); + } } function initialize() { diff --git a/web/app/assets/javascripts/band_setup.js b/web/app/assets/javascripts/band_setup.js index 83358a970..523248c3b 100644 --- a/web/app/assets/javascripts/band_setup.js +++ b/web/app/assets/javascripts/band_setup.js @@ -22,27 +22,13 @@ } - // function formatGenres(genres) { - // var formattedGenres = ''; - // if (genres) { - // for (var i=0; i < genres.length; i++) { - // var genre = genres[i]; - // formattedGenres += genre.description; - // if (i < genres.length -1) { - // formattedGenres += ', '; - // } - // } - // } - // return formattedGenres; - // } - function getSelectedGenres() { var genres = []; $('input[type=checkbox]:checked', '#band-genres').each(function(i) { var genre = $(this).val(); genres.push(genre); }); - logger.debug("genres.length=" + genres.length); + return genres; } diff --git a/web/app/assets/javascripts/jam_rest.js b/web/app/assets/javascripts/jam_rest.js index 1768dfd4d..8d03f852e 100644 --- a/web/app/assets/javascripts/jam_rest.js +++ b/web/app/assets/javascripts/jam_rest.js @@ -82,17 +82,14 @@ }); } - function updateBandInvitation(bandId) { - var bandInvitation = {}; - bandInvitation.band_id = bandId; - bandInvitation.user_id = userId; + function updateBandInvitation(bandId, invitationId, isAccepted) { return $.ajax({ type: "POST", dataType: "json", - url: '/api/bands/' + bandId + "/invitations", + url: '/api/bands/' + bandId + "/invitations/" + invitationId, contentType: 'application/json', processData: false, - data: JSON.stringify(bandInvitation) + data: JSON.stringify({"accepted": isAccepted}) }); } diff --git a/web/app/assets/javascripts/profile.js b/web/app/assets/javascripts/profile.js index fb16c59bb..273d88fa9 100644 --- a/web/app/assets/javascripts/profile.js +++ b/web/app/assets/javascripts/profile.js @@ -482,8 +482,6 @@ async: false, processData:false, success: function(response) { - logger.debug("context.JK.currentUserId=" + context.JK.currentUserId); - logger.debug("userId=" + userId); if ( (!response || response.length === 0) && context.JK.currentUserId === userId) { var noBandHtml = $('#template-no-bands').html(); $("#profile-bands").append(noBandHtml); @@ -491,7 +489,7 @@ else { addMoreBandsLink(); - + $.each(response, function(index, val) { // build band member HTML diff --git a/web/app/assets/javascripts/sidebar.js b/web/app/assets/javascripts/sidebar.js index e5fb86dbe..f78fda21e 100644 --- a/web/app/assets/javascripts/sidebar.js +++ b/web/app/assets/javascripts/sidebar.js @@ -183,6 +183,16 @@ else if (type === context.JK.MessageType.JOIN_REQUEST_REJECTED) { $notification.find('#div-actions').hide(); } + else if (type === context.JK.MessageType.BAND_INVITATION) { + var $action_btn = $notification.find('#btn-notification-action'); + $action_btn.text('ACCEPT'); + $action_btn.click(function() { + acceptBandInvitation({ "band_invitation_id": payload.band_invitation_id, "band_id": payload.band_id, "notification_id": payload.notification_id }); + }); + } + else if (type === context.JK.MessageType.BAND_INVITATION_ACCEPTED) { + $notification.find('#div-actions').hide(); + } } function deleteNotificationHandler(evt) { @@ -343,8 +353,10 @@ sidebarText = payload.msg; } + // increment displayed notification count incrementNotificationCount(); + // add notification to sidebar var template = $("#template-notification-panel").html(); var notificationHtml = context.JK.fillTemplate(template, { notificationId: payload.notification_id, @@ -419,6 +431,8 @@ registerJoinRequest(); registerJoinRequestApproved(); registerJoinRequestRejected(); + registerBandInvitation(); + registerBandInvitationAccepted(); // watch for Invite More Users events $('#sidebar-div .btn-email-invitation').click(function() { @@ -461,13 +475,11 @@ "title": "New Friend Request", "text": payload.msg, "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) - }, - { + }, { "ok_text": "ACCEPT", "ok_callback": acceptFriendRequest, "ok_callback_args": { "friend_request_id": payload.friend_request_id, "notification_id": payload.notification_id } - } - ); + }); }); } @@ -577,13 +589,11 @@ app.notify({ "title": "Session Invitation", "text": participantHtml - }, - { + }, { "ok_text": "JOIN SESSION", "ok_callback": openTerms, "ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id } - } - ); + }); }); } @@ -606,19 +616,17 @@ // display notification app.notify({ - "title": "New Join Request", - "text": payload.msg, - "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) - }, - { + "title": "New Join Request", + "text": payload.msg, + "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) + }, { "ok_text": "APPROVE", "ok_callback": approveJoinRequest, "ok_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id }, "cancel_text": "REJECT", "cancel_callback": rejectJoinRequest, "cancel_callback_args": { "join_request_id": payload.join_request_id, "notification_id": payload.notification_id } - } - ); + }); }); } @@ -644,16 +652,14 @@ // display notification app.notify({ - "title": "Join Request Approved", - "text": payload.msg, - "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) - }, - { + "title": "Join Request Approved", + "text": payload.msg, + "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) + }, { "ok_text": "JOIN SESSION", "ok_callback": openTerms, "ok_callback_args": { "session_id": payload.session_id, "notification_id": payload.notification_id } - } - ); + }); }); } @@ -672,6 +678,54 @@ }); } + function registerBandInvitation() { + context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION, function(header, payload) { + logger.debug("Handling BAND_INVITATION msg " + JSON.stringify(payload)); + + handleNotification(payload, header.type); + + // display notification + app.notify({ + "title": "Band Invitation", + "text": payload.msg, + "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) + }, { + "ok_text": "ACCEPT", + "ok_callback": acceptBandInvitation, + "ok_callback_args": { + "band_invitation_id": payload.band_invitation_id, + "band_id": payload.band_id, + "notification_id": payload.notification_id + } + }); + }); + } + + function acceptBandInvitation(args) { + rest.updateBandInvitation( + args.band_id, + args.band_invitation_id, + true + ).done(function(response) { + deleteNotification(args.notification_id); // delete notification corresponding to this friend request + }).error(app.ajaxError); + } + + function registerBandInvitationAccepted() { + context.JK.JamServer.registerMessageCallback(context.JK.MessageType.BAND_INVITATION_ACCEPTED, function(header, payload) { + logger.debug("Handling BAND_INVITATION_ACCEPTED msg " + JSON.stringify(payload)); + + handleNotification(payload, header.type); + + // display notification + app.notify({ + "title": "Band Invitation Accepted", + "text": payload.msg, + "icon_url": context.JK.resolveAvatarUrl(payload.photo_url) + }); + }); + } + this.initialize = function(invitationDialogInstance) { events(); initializeFriendsPanel(); diff --git a/web/app/controllers/api_bands_controller.rb b/web/app/controllers/api_bands_controller.rb index ad75323da..954fc0d59 100644 --- a/web/app/controllers/api_bands_controller.rb +++ b/web/app/controllers/api_bands_controller.rb @@ -162,6 +162,13 @@ class ApiBandsController < ApiController 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]) + end def invitation_destroy begin diff --git a/web/app/views/api_bands/invitation_update.rabl b/web/app/views/api_bands/invitation_update.rabl new file mode 100644 index 000000000..1cc5c9bde --- /dev/null +++ b/web/app/views/api_bands/invitation_update.rabl @@ -0,0 +1,3 @@ +object @invitation + +extends "api_bands/invitation_show" \ No newline at end of file diff --git a/web/app/views/api_users/notification_index.rabl b/web/app/views/api_users/notification_index.rabl index 23f80c077..515a186ec 100644 --- a/web/app/views/api_users/notification_index.rabl +++ b/web/app/views/api_users/notification_index.rabl @@ -1,6 +1,6 @@ collection @notifications -attributes :description, :source_user_id, :target_user_id, :session_id, :recording_id, :invitation_id, :join_request_id, :friend_request_id, :formatted_msg, :created_at, :photo_url +attributes :description, :source_user_id, :target_user_id, :session_id, :recording_id, :invitation_id, :join_request_id, :friend_request_id, :band_id, :band_invitation_id, :formatted_msg, :created_at node :notification_id do |n| n.id diff --git a/web/app/views/clients/_bandProfile.html.erb b/web/app/views/clients/_bandProfile.html.erb index ef791def1..012c19e52 100644 --- a/web/app/views/clients/_bandProfile.html.erb +++ b/web/app/views/clients/_bandProfile.html.erb @@ -18,6 +18,7 @@