Merge branch 'develop' of bitbucket.org:jamkazam/jam-cloud into develop
This commit is contained in:
commit
5f9986b30e
|
|
@ -241,3 +241,4 @@ jam_track_available.sql
|
|||
active_jam_track.sql
|
||||
bpms_on_tap_in.sql
|
||||
jamtracks_job.sql
|
||||
text_messages.sql
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
CREATE TABLE text_messages (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
source_user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
|
||||
target_user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
|
||||
message TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
|
@ -197,6 +197,7 @@ require "jam_ruby/models/jam_company"
|
|||
require "jam_ruby/models/user_sync"
|
||||
require "jam_ruby/models/video_source"
|
||||
require "jam_ruby/models/recorded_video"
|
||||
require "jam_ruby/models/text_message"
|
||||
require "jam_ruby/jam_tracks_manager"
|
||||
|
||||
include Jampb
|
||||
|
|
|
|||
|
|
@ -290,13 +290,8 @@ module JamRuby
|
|||
}
|
||||
)
|
||||
|
||||
if (offset)
|
||||
query = query.offset(offset)
|
||||
end
|
||||
|
||||
if (limit)
|
||||
query = query.limit(limit)
|
||||
end
|
||||
query = query.offset(offset) if offset
|
||||
query = query.limit(limit) if limit
|
||||
|
||||
if as_musician
|
||||
query = query.where(
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
include Devise::Models
|
||||
|
||||
module JamRuby
|
||||
class TextMessage < ActiveRecord::Base
|
||||
|
||||
self.primary_key = 'id'
|
||||
|
||||
default_scope order('created_at DESC')
|
||||
|
||||
attr_accessible :target_user_id, :source_user_id, :message
|
||||
|
||||
belongs_to :target_user, :class_name => "JamRuby::User", :foreign_key => "target_user_id"
|
||||
belongs_to :source_user, :class_name => "JamRuby::User", :foreign_key => "source_user_id"
|
||||
|
||||
validates :message, length: {minimum: 1, maximum: 400}, no_profanity: true
|
||||
|
||||
def self.index(target_user_id, source_user_id, options = {})
|
||||
offset = options[:offset]
|
||||
limit = options[:limit]
|
||||
|
||||
# if not specified, default offset to 0
|
||||
offset ||= 0
|
||||
offset = offset.to_i
|
||||
|
||||
# if not specified, default limit to 10
|
||||
limit ||= 10
|
||||
limit = limit.to_i
|
||||
|
||||
TextMessage
|
||||
.offset(offset)
|
||||
.limit(limit)
|
||||
.where('(source_user_id = (?) AND target_user_id = (?)) OR (source_user_id = (?) AND target_user_id = (?))', source_user_id, target_user_id, target_user_id, source_user_id)
|
||||
|
||||
end
|
||||
|
||||
def self.create(message, target_user_id, source_user_id)
|
||||
sanitized_text = Sanitize.fragment(message, elements: HtmlSanitize::SAFE)
|
||||
|
||||
# create new message
|
||||
tm = TextMessage.new
|
||||
tm.message = sanitized_text
|
||||
tm.target_user_id = target_user_id
|
||||
tm.source_user_id = source_user_id
|
||||
|
||||
# send notification
|
||||
@notification = Notification.send_text_message(sanitized_text, source_user_id, User.find_by_id(target_user_id))
|
||||
|
||||
tm
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -79,6 +79,9 @@ module JamRuby
|
|||
# self.id = followable_id in follows table
|
||||
has_many :followers, :as => :followable, :class_name => "JamRuby::Follow", :dependent => :destroy
|
||||
|
||||
# text messages
|
||||
has_many :text_messages, :class_name => "JamRuby:TextMessage", :foreign_key => "target_user_id"
|
||||
|
||||
# notifications
|
||||
has_many :notifications, :class_name => "JamRuby::Notification", :foreign_key => "target_user_id"
|
||||
has_many :inverse_notifications, :through => :notifications, :class_name => "JamRuby::User"
|
||||
|
|
@ -1017,6 +1020,8 @@ module JamRuby
|
|||
|
||||
user.save
|
||||
|
||||
user.errors.add("recaptcha", "verification failed") if recaptcha_failed
|
||||
|
||||
if user.errors.any?
|
||||
raise ActiveRecord::Rollback
|
||||
else
|
||||
|
|
@ -1033,16 +1038,9 @@ module JamRuby
|
|||
UserMailer.confirm_email(user, signup_confirm_url.nil? ? nil : (signup_confirm_url + "/" + user.signup_token) ).deliver
|
||||
end
|
||||
end
|
||||
|
||||
if recaptcha_failed
|
||||
user.errors.add "recaptcha", "verification failed"
|
||||
raise ActiveRecord::Rollback
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return user
|
||||
end
|
||||
user
|
||||
end # def signup
|
||||
|
||||
# this is intended to be development-mode or test-mode only; VRFS-149
|
||||
# it creates or updates one user per developer, so that we aren't in the business
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe TextMessage do
|
||||
|
||||
before do
|
||||
TextMessage.delete_all
|
||||
User.delete_all
|
||||
@target_user = FactoryGirl.create(:user)
|
||||
@source_user = FactoryGirl.create(:user)
|
||||
|
||||
@msg = TextMessage.new(:target_user_id => @target_user.id, :source_user_id => @source_user.id)
|
||||
end
|
||||
|
||||
describe "index" do
|
||||
|
||||
it "should retrieve conversation for both users" do
|
||||
@msg.message = "Test message"
|
||||
@msg.save!
|
||||
|
||||
messages = TextMessage.index(@target_user.id, @source_user.id)
|
||||
messages.count.should == 1
|
||||
|
||||
messages = TextMessage.index(@source_user.id, @target_user.id)
|
||||
messages.count.should == 1
|
||||
end
|
||||
|
||||
it "should page records" do
|
||||
11.times do |n|
|
||||
message = TextMessage.new(:target_user_id => @target_user.id, :source_user_id => @source_user.id)
|
||||
message.message = "Message #{n}"
|
||||
message.save!
|
||||
end
|
||||
|
||||
messages = TextMessage.index(@target_user.id, @source_user.id, {:offset => 0})
|
||||
messages.count.should == 10
|
||||
|
||||
messages = TextMessage.index(@target_user.id, @source_user.id, {:offset => 10})
|
||||
messages.count.should == 1
|
||||
end
|
||||
|
||||
it "should not allow empty message" do
|
||||
expect { @msg.save! }.to raise_error(ActiveRecord::RecordInvalid)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
@ -339,7 +339,14 @@
|
|||
|
||||
if ("instrument_list" in pending_rsvp_request && pending_rsvp_request.instrument_list != null) {
|
||||
$.each(pending_rsvp_request.instrument_list, function (index, instrument) {
|
||||
var instrumentId = context.JK.getInstrumentId(instrument.id);
|
||||
var instrumentId;
|
||||
|
||||
if (instrument) {
|
||||
instrumentId = context.JK.getInstrumentId(instrument.id);
|
||||
}
|
||||
else {
|
||||
instrumentId = 'other';
|
||||
}
|
||||
var inst = context.JK.getInstrumentIcon24(instrumentId);
|
||||
instrumentLogoHtml += '<img title="' + instrumentId + '" hoveraction="instrument" data-instrument-id="' + instrumentId + '" src="' + inst + '" width="24" height="24" /> ';
|
||||
instrumentDesc.push(instrumentId);
|
||||
|
|
@ -378,7 +385,14 @@
|
|||
$.each(sessionData.approved_rsvps, function(index, approved_rsvp) {
|
||||
if ("instrument_list" in approved_rsvp) {
|
||||
$.each(approved_rsvp.instrument_list, function(index, instrument) {
|
||||
var instrumentId = context.JK.getInstrumentId(instrument.id);
|
||||
var instrumentId;
|
||||
|
||||
if (instrument) {
|
||||
instrumentId = context.JK.getInstrumentId(instrument.id);
|
||||
}
|
||||
else {
|
||||
instrumentId = 'other';
|
||||
}
|
||||
var inst = context.JK.getInstrumentIcon24(instrumentId);
|
||||
instrumentLogoHtml += '<img title="' + instrumentId + '" hoveraction="instrument" data-instrument-id="' + instrumentId + '" src="' + inst + '" width="24" height="24" /> ';
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,130 @@
|
|||
(function(context,$) {
|
||||
|
||||
"use strict";
|
||||
context.JK = context.JK || {};
|
||||
context.JK.SessionStartDialog = function(app, session) {
|
||||
var logger = context.JK.logger;
|
||||
var sessionUtils = context.JK.SessionUtils;
|
||||
var $dialog = null;
|
||||
var dialogId = 'session-start-dialog';
|
||||
var $btnStartSession = null;
|
||||
|
||||
function beforeShow(data) {
|
||||
}
|
||||
|
||||
function afterShow(data) {
|
||||
}
|
||||
|
||||
function afterHide() {
|
||||
}
|
||||
|
||||
function showDialog() {
|
||||
return app.layout.showDialog(dialogId);
|
||||
}
|
||||
|
||||
function events() {
|
||||
$btnStartSession.unbind('click');
|
||||
$btnStartSession.click(function(e) {
|
||||
context.location = '/client#/session/' + session.id;
|
||||
app.layout.closeDialog(dialogId);
|
||||
});
|
||||
}
|
||||
|
||||
function initializeSessionDetails() {
|
||||
$dialog.find('#session-start-type-disp').html('Now!');
|
||||
$dialog.find('#session-name-disp').html(session.name);
|
||||
$dialog.find('#session-description-disp').html(session.description);
|
||||
|
||||
if (session.music_notations && session.music_notations.length > 0) {
|
||||
$dialog.find('#session-notations-disp').html("Notations: " + session.music_notations.join(', '));
|
||||
}
|
||||
|
||||
if (session.band) {
|
||||
$dialog.find('#session-band-disp').html(band.name);
|
||||
}
|
||||
else {
|
||||
$dialog.find('#session-band-disp').html('N/A');
|
||||
}
|
||||
|
||||
$dialog.find('#session-language-disp').html(session.language_description);
|
||||
|
||||
var invitedFriends = session.invitations;
|
||||
|
||||
var sessionInvited = [];
|
||||
$.each(invitedFriends, function(index, invitation) {
|
||||
sessionInvited.push(invitation.receiver_name);
|
||||
});
|
||||
|
||||
var sessionInvitedString = sessionInvited.join(', ');
|
||||
|
||||
if (session.musician_access && session.approval_required) {
|
||||
if (session.open_rsvps) {
|
||||
if (invitedFriends.length == 0)
|
||||
sessionInvitedString = "Any interested JamKazam musicians that I approve";
|
||||
else
|
||||
sessionInvitedString += ", plus any interested JamKazam musicians that I approve";
|
||||
}
|
||||
else {
|
||||
if (invitedFriends.length == 0) {
|
||||
sessionInvitedString = "No open RSVPs";
|
||||
}
|
||||
else {
|
||||
sessionInvitedString += " (No open RSVPs)";
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (session.musician_access && !session.approval_required) {
|
||||
if (invitedFriends.length == 0)
|
||||
sessionInvitedString = "Any interested JamKazam musicians who want to join us";
|
||||
else
|
||||
sessionInvitedString += ", plus any interested JamKazam musicians who want to join us";
|
||||
}
|
||||
|
||||
$dialog.find('#session-invited-disp').html(sessionInvitedString);
|
||||
|
||||
var instrumentsMe = [], instrumentsOthers = [];
|
||||
|
||||
$.each(session.approved_rsvps, function(index, rsvp) {
|
||||
if (rsvp.id === context.JK.currentUserId) {
|
||||
$.each(rsvp.instrument_list, function(index, instrument) {
|
||||
instrumentsMe.push(instrument.desc);
|
||||
});
|
||||
}
|
||||
else {
|
||||
$.each(rsvp.instrument_list, function(index, instrument) {
|
||||
instrumentsOthers.push(instrument.desc);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$dialog.find('#session-instruments-me-disp').html(instrumentsMe.join(', '));
|
||||
$dialog.find('#session-instruments-rsvp-disp').html(instrumentsOthers.join(', '));
|
||||
|
||||
$dialog.find('#session-musician-access-disp').html('Musicians: ' + session.musician_access_description);
|
||||
$dialog.find('#session-fans-access-disp').html('Fans: ' + session.fan_access_description);
|
||||
$dialog.find('#session-policy-disp').html(session.legal_policy);
|
||||
}
|
||||
|
||||
function initialize() {
|
||||
|
||||
var dialogBindings = {
|
||||
'beforeShow' : beforeShow,
|
||||
'afterShow' : afterShow,
|
||||
'afterHide': afterHide
|
||||
};
|
||||
|
||||
app.bindDialog(dialogId, dialogBindings);
|
||||
|
||||
$dialog = $('[layout-id="' + dialogId + '"]');
|
||||
$btnStartSession = $dialog.find('.btnStartSession');
|
||||
|
||||
initializeSessionDetails();
|
||||
events();
|
||||
}
|
||||
|
||||
this.initialize = initialize;
|
||||
this.showDialog = showDialog;
|
||||
}
|
||||
|
||||
return this;
|
||||
})(window,jQuery);
|
||||
|
|
@ -163,6 +163,7 @@
|
|||
}
|
||||
$sendTextMessage.click(sendMessage);
|
||||
|
||||
// TODO: PULL FROM NEW TABLE
|
||||
rest.getNotifications(buildParams())
|
||||
.done(function (response) {
|
||||
context._.each(response, function (textMessage) {
|
||||
|
|
|
|||
|
|
@ -1258,6 +1258,7 @@
|
|||
});
|
||||
}
|
||||
|
||||
// TODO: push into new table
|
||||
function createTextMessage(options) {
|
||||
var id = getId(options);
|
||||
return $.ajax({
|
||||
|
|
@ -1269,6 +1270,17 @@
|
|||
});
|
||||
}
|
||||
|
||||
function getTextMessages(options) {
|
||||
if(!options) options = {};
|
||||
var id = getId(options);
|
||||
return $.ajax({
|
||||
type: "GET",
|
||||
url: '/api/users/' + id + '/text_messages?' + $.param(options),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
});
|
||||
}
|
||||
|
||||
function getNotifications(options) {
|
||||
if(!options) options = {};
|
||||
var id = getId(options);
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@
|
|||
function updateNotificationList(response) {
|
||||
$.each(response, function(index, val) {
|
||||
|
||||
if(val.description == 'TEXT_MESSAGE') {
|
||||
if(val.description == context.JK.MessageType.TEXT_MESSAGE) {
|
||||
val.formatted_msg = textMessageDialog.formatTextMessage(val.message.substring(0, 200), val.source_user_id, val.source_user.name, val.message.length > 200).html();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -200,14 +200,14 @@
|
|||
|
||||
createSessionSettings.startDate = createSessionSettings.startDate || (new Date().toDateString());
|
||||
|
||||
$("#session-start-date").val(createSessionSettings.startDate);
|
||||
$screen.find("#session-start-date").val(createSessionSettings.startDate);
|
||||
toggleDate(true);
|
||||
toggleStartTime();
|
||||
toggleStepStatus();
|
||||
sessionUtils.defaultTimezone($timezoneList);
|
||||
if(firstTimeShown) {
|
||||
firstTimeShown = false;
|
||||
$('#session-when-start-scheduled').iCheck('check');
|
||||
$screen.find('#session-when-start-scheduled').iCheck('check');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +217,7 @@
|
|||
function beforeShowStep3() {
|
||||
rest.getBands(context.JK.currentUserId)
|
||||
.done(function(result) {
|
||||
var options = $("#session-band-list");
|
||||
var options = $screen.find("#session-band-list");
|
||||
options.empty();
|
||||
options.append($("<option />").val('').text('No'));
|
||||
$.each(result, function(idx, item) {
|
||||
|
|
@ -251,10 +251,10 @@
|
|||
|
||||
var sessionName = createSessionSettings.name;
|
||||
sessionName += ' (' + createSessionSettings.genresValues[0] + ')';
|
||||
$('#session-name-disp').html(sessionName);
|
||||
$screen.find('#session-name-disp').html(sessionName);
|
||||
|
||||
var sessionDescription = createSessionSettings.description;
|
||||
$('#session-description-disp').html(sessionDescription);
|
||||
$screen.find('#session-description-disp').html(sessionDescription);
|
||||
|
||||
var sessionNotations = [];
|
||||
for (var i = 0; i < createSessionSettings.notations.length; i++) {
|
||||
|
|
@ -262,16 +262,16 @@
|
|||
sessionNotations.push(name);
|
||||
}
|
||||
if(sessionNotations.length > 0) {
|
||||
$('#session-notations-disp').html("Notations: " + sessionNotations.join(', '));
|
||||
$screen.find('#session-notations-disp').html("Notations: " + sessionNotations.join(', '));
|
||||
}
|
||||
else {
|
||||
$('#session-notations-disp').html('');
|
||||
$screen.find('#session-notations-disp').html('');
|
||||
}
|
||||
|
||||
$('#session-language-disp').html(createSessionSettings.language.label);
|
||||
$('#session-band-disp').html(createSessionSettings.band.label);
|
||||
$screen.find('#session-language-disp').html(createSessionSettings.language.label);
|
||||
$screen.find('#session-band-disp').html(createSessionSettings.band.label);
|
||||
|
||||
var plusMusicians = $('#session-plus-musicians')[0].checked;
|
||||
var plusMusicians = $screen.find('#session-plus-musicians')[0].checked;
|
||||
|
||||
var sessionInvited = [];
|
||||
var invitedFriends = inviteMusiciansUtil.getInvitedFriendNames();
|
||||
|
|
@ -302,7 +302,7 @@
|
|||
else
|
||||
sessionInvitedString += ", plus any interested JamKazam musicians who want to join us";
|
||||
}
|
||||
$('#session-invited-disp').html(sessionInvitedString);
|
||||
$screen.find('#session-invited-disp').html(sessionInvitedString);
|
||||
|
||||
if (createSessionSettings.createType == '<%= MusicSession::CREATE_TYPE_START_SCHEDULED%>') {
|
||||
var session = scheduledSessions[createSessionSettings.selectedSessionId];
|
||||
|
|
@ -315,7 +315,7 @@
|
|||
});
|
||||
}
|
||||
});
|
||||
$('#session-instruments-me-disp').html(instruments_me.join(', '));
|
||||
$screen.find('#session-instruments-me-disp').html(instruments_me.join(', '));
|
||||
}
|
||||
|
||||
if (session.open_slots.length > 0) {
|
||||
|
|
@ -334,7 +334,7 @@
|
|||
$.map(instruments_rsvp_arr, function(val, i) {
|
||||
instruments_str_arr.push(i + ' (' + val.count + ') (' + val.level + ')');
|
||||
})
|
||||
$('#session-instruments-rsvp-disp').html(instruments_str_arr.join(', '));
|
||||
$screen.find('#session-instruments-rsvp-disp').html(instruments_str_arr.join(', '));
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
|
@ -342,7 +342,7 @@
|
|||
$.each(getCreatorInstruments(), function(index, instrument) {
|
||||
instruments_me.push(instrument.name);
|
||||
});
|
||||
$('#session-instruments-me-disp').html(instruments_me.join(', '));
|
||||
$screen.find('#session-instruments-me-disp').html(instruments_me.join(', '));
|
||||
|
||||
var instruments_rsvp = [];
|
||||
var otherInstruments = instrumentRSVP.getSelectedInstruments();
|
||||
|
|
@ -353,13 +353,13 @@
|
|||
$.each(otherInstruments, function(index, instrument) {
|
||||
instruments_rsvp.push(instrument.name + ' (' + instrument.count + ') (' + proficiencyDescriptionMap[instrument.level] + ')');
|
||||
});
|
||||
$('#session-instruments-rsvp-disp').html(instruments_rsvp.join(', '));
|
||||
$screen.find('#session-instruments-rsvp-disp').html(instruments_rsvp.join(', '));
|
||||
}
|
||||
|
||||
$('#session-musician-access-disp').html('Musicians: ' + createSessionSettings.musician_access.label);
|
||||
$('#session-fans-access-disp').html('Fans: ' + createSessionSettings.fans_access.label);
|
||||
$screen.find('#session-musician-access-disp').html('Musicians: ' + createSessionSettings.musician_access.label);
|
||||
$screen.find('#session-fans-access-disp').html('Fans: ' + createSessionSettings.fans_access.label);
|
||||
|
||||
$('#session-policy-disp').html(createSessionSettings.session_policy);
|
||||
$screen.find('#session-policy-disp').html(createSessionSettings.session_policy);
|
||||
}
|
||||
|
||||
function beforeMoveStep1() {
|
||||
|
|
@ -428,7 +428,7 @@
|
|||
createSessionSettings.recurring_mode.value = 'once';
|
||||
}
|
||||
else {
|
||||
createSessionSettings.startDate = $('#session-start-date').val();
|
||||
createSessionSettings.startDate = $screen.find('#session-start-date').val();
|
||||
createSessionSettings.startTime = $startTimeList.val();
|
||||
createSessionSettings.endTime = $endTimeList.val();
|
||||
createSessionSettings.notations = [];
|
||||
|
|
@ -437,7 +437,7 @@
|
|||
createSessionSettings.timezone.label = $timezoneList.get(0).options[$timezoneList.get(0).selectedIndex].text;
|
||||
createSessionSettings.recurring_mode.label = $recurringModeList.get(0).options[$recurringModeList.get(0).selectedIndex].text;
|
||||
createSessionSettings.recurring_mode.value = $recurringModeList.val();
|
||||
createSessionSettings.open_rsvps = $('#session-plus-musicians')[0].checked;
|
||||
createSessionSettings.open_rsvps = $screen.find('#session-plus-musicians')[0].checked;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
@ -503,22 +503,22 @@
|
|||
|
||||
function beforeMoveStep2() {
|
||||
var isValid = true;
|
||||
var name = $('#session-name').val();
|
||||
var name = $screen.find('#session-name').val();
|
||||
if (!name) {
|
||||
$('#divSessionName .error-text').remove();
|
||||
$('#divSessionName').addClass("error");
|
||||
$('#session-name').after("<ul class='error-text'><li>Name is required</li></ul>");
|
||||
$screen.find('#session-name').after("<ul class='error-text'><li>Name is required</li></ul>");
|
||||
isValid = false;
|
||||
}
|
||||
else {
|
||||
$('#divSessionName').removeClass("error");
|
||||
}
|
||||
|
||||
var description = $('#session-description').val();
|
||||
var description = $screen.find('#session-description').val();
|
||||
if (!description) {
|
||||
$('#divSessionDescription .error-text').remove();
|
||||
$('#divSessionDescription').addClass("error");
|
||||
$('#session-description').after("<ul class='error-text'><li>Description is required</li></ul>");
|
||||
$screen.find('#session-description').after("<ul class='error-text'><li>Description is required</li></ul>");
|
||||
isValid = false;
|
||||
}
|
||||
else {
|
||||
|
|
@ -558,13 +558,13 @@
|
|||
else
|
||||
createSessionSettings.band.label = $bandList.get(0).options[$bandList.get(0).selectedIndex].text;
|
||||
|
||||
createSessionSettings.open_rsvps = $('#session-plus-musicians')[0].checked;
|
||||
createSessionSettings.open_rsvps = $screen.find('#session-plus-musicians')[0].checked;
|
||||
return true;
|
||||
}
|
||||
|
||||
function beforeMoveStep4() {
|
||||
var isValid = true;
|
||||
var sessionPolicyChecked = $('#session-policy-confirm').is(':checked');
|
||||
var sessionPolicyChecked = $screen.find('#session-policy-confirm').is(':checked');
|
||||
if (!sessionPolicyChecked) {
|
||||
$('#divSessionPolicy .error-text').remove();
|
||||
$('#divSessionPolicy').addClass("error");
|
||||
|
|
@ -576,11 +576,11 @@
|
|||
}
|
||||
|
||||
createSessionSettings.session_policy = $('input[name="session-policy-type"][checked="checked"]').attr('policy-id');
|
||||
var $musicianAccess = $('#session-musician-access');
|
||||
var $musicianAccess = $screen.find('#session-musician-access');
|
||||
createSessionSettings.musician_access.value = $musicianAccess.val();
|
||||
createSessionSettings.musician_access.label = $musicianAccess.get(0).options[$musicianAccess.get(0).selectedIndex].text;
|
||||
|
||||
var $fansAccess = $('#session-fans-access');
|
||||
var $fansAccess = $screen.find('#session-fans-access');
|
||||
createSessionSettings.fans_access.value = $fansAccess.val();
|
||||
createSessionSettings.fans_access.label = $fansAccess.get(0).options[$fansAccess.get(0).selectedIndex].text;
|
||||
|
||||
|
|
@ -975,7 +975,7 @@
|
|||
}
|
||||
|
||||
function toggleDate(dontRebuildDropdowns) {
|
||||
var selectedDate = new Date($('#session-start-date').val());
|
||||
var selectedDate = new Date($screen.find('#session-start-date').val());
|
||||
var currentDate = new Date();
|
||||
var startIndex = 0;
|
||||
|
||||
|
|
@ -1046,7 +1046,7 @@
|
|||
radioClass: 'iradio_minimal',
|
||||
inheritClass: true
|
||||
});
|
||||
$("#session-start-date").datepicker({
|
||||
$screen.find("#session-start-date").datepicker({
|
||||
dateFormat: "D d MM yy",
|
||||
onSelect: function() { toggleDate(); }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
var $musicianTemplate = $('#template-musician-info');
|
||||
var showJoinLink = true;
|
||||
var showListenLink = true;
|
||||
var showRsvpLink = true;
|
||||
var MAX_MINUTES_SHOW_START = 15;
|
||||
|
||||
// related to listen
|
||||
function stateChange(e, data) {
|
||||
|
|
@ -369,11 +369,39 @@
|
|||
|
||||
var showRsvpLink = true;
|
||||
var noLinkText = '';
|
||||
$('.rsvp-link-text', $parentRow).hide();
|
||||
|
||||
if (approvedRsvpId) {
|
||||
function showStartSessionButton(scheduledStart) {
|
||||
var now = new Date();
|
||||
var scheduledDate = new Date(scheduledStart);
|
||||
var minutesFromStart = (scheduledDate.getTime() - now.getTime()) / (1000 * 60);
|
||||
return minutesFromStart <= MAX_MINUTES_SHOW_START;
|
||||
};
|
||||
|
||||
if (session.creator.id === context.JK.currentUserId) {
|
||||
showRsvpLink = false;
|
||||
noLinkText = $('<span class="text">You have been confirmed for this session. <a href="#" style="color: #fc0">Cancel</a></span>');
|
||||
noLinkText = $('<span class="text"><a class="start" style="color: #fc0">Start session now?</a></span>');
|
||||
noLinkText.find('a').click(function() {
|
||||
ui.launchSessionStartDialog(session);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else if (approvedRsvpId) {
|
||||
showRsvpLink = false;
|
||||
|
||||
if (session.scheduled_start && showStartSessionButton(session.scheduled_start)) {
|
||||
noLinkText = $('<span class="text"><a class="start" style="color: #fc0">Start session now?</a> | <a class="cancel" style="color: #fc0">Cancel RSVP</a></span>');
|
||||
noLinkText.find('a.start').click(function() {
|
||||
ui.launchSessionStartDialog(session);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
else {
|
||||
noLinkText = $('<span class="text"><a class="cancel" style="color: #fc0">Cancel RSVP</a></span>');
|
||||
}
|
||||
|
||||
// wire cancel link
|
||||
noLinkText.find('a.cancel').click(function() {
|
||||
ui.launchRsvpCancelDialog(session.id, approvedRsvpId)
|
||||
.one(EVENTS.RSVP_CANCELED, function() {
|
||||
rest.getSessionHistory(session.id)
|
||||
|
|
@ -387,9 +415,20 @@
|
|||
return false;
|
||||
});
|
||||
}
|
||||
else if (hasInvitation) {
|
||||
showRsvpLink = false;
|
||||
|
||||
if (session.scheduled_start && showStartSessionButton(session.scheduled_start)) {
|
||||
noLinkText = $('<span class="text"><a class="start" style="color: #fc0">Start session now?</a></span>');
|
||||
noLinkText.find('a').click(function() {
|
||||
ui.launchSessionStartDialog(session);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
||||
else if (pendingRsvpId) {
|
||||
showRsvpLink = false;
|
||||
noLinkText = $('<span class="text">You have RSVP\'ed to this session. <a href="#" style="color: #fc0">Cancel</a></span>');
|
||||
noLinkText = $('<span class="text"><a class="cancel" style="color: #fc0">Cancel RSVP</a></span>');
|
||||
noLinkText.find('a').click(function() {
|
||||
ui.launchRsvpCancelDialog(session.id, pendingRsvpId)
|
||||
.one(EVENTS.RSVP_CANCELED, function() {
|
||||
|
|
@ -416,6 +455,7 @@
|
|||
if (showRsvpLink) {
|
||||
$('.rsvp-msg', $parentRow).hide();
|
||||
$('.rsvp-link', $parentRow).show();
|
||||
$('.rsvp-link-text', $parentRow).show();
|
||||
|
||||
$('.rsvp-link', $parentRow).click(function(evt) {
|
||||
ui.launchRsvpSubmitDialog(session.id)
|
||||
|
|
|
|||
|
|
@ -53,6 +53,12 @@
|
|||
return rsvpDialog.showDialog();
|
||||
}
|
||||
|
||||
function launchSessionStartDialog(session) {
|
||||
var sessionStartDialog = new JK.SessionStartDialog(JK.app, session);
|
||||
sessionStartDialog.initialize();
|
||||
return sessionStartDialog.showDialog();
|
||||
}
|
||||
|
||||
this.addSessionLike = addSessionLike;
|
||||
this.addRecordingLike = addRecordingLike;
|
||||
this.launchCommentDialog = launchCommentDialog;
|
||||
|
|
@ -60,6 +66,7 @@
|
|||
this.launchRsvpSubmitDialog = launchRsvpSubmitDialog;
|
||||
this.launchRsvpCancelDialog = launchRsvpCancelDialog;
|
||||
this.launchRsvpCreateSlotDialog = launchRsvpCreateSlotDialog;
|
||||
this.launchSessionStartDialog = launchSessionStartDialog;
|
||||
|
||||
return this;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -127,6 +127,10 @@ table.findsession-table, table.local-recordings, table.open-jam-tracks {
|
|||
vertical-align:top;
|
||||
}
|
||||
|
||||
.musician-groups td.nowrap {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
a {
|
||||
color:#fff;
|
||||
text-decoration:none;
|
||||
|
|
|
|||
|
|
@ -70,8 +70,8 @@
|
|||
min-height: 600px;
|
||||
}
|
||||
|
||||
.dialog-overlay-sm {
|
||||
width: 600px;
|
||||
.dialog-overlay-lg {
|
||||
width: 800px;
|
||||
height: auto;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
|
|
@ -90,6 +90,18 @@
|
|||
color: #aaa;
|
||||
}
|
||||
|
||||
.dialog-overlay-sm {
|
||||
width: 600px;
|
||||
height: auto;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 20%;
|
||||
margin-left: -300px;
|
||||
background-color: #333;
|
||||
border: 1px solid #ed3618;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.dialog-overlay-sm .dialog-inner {
|
||||
width: 550px;
|
||||
height: auto;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
.session-wrapper {
|
||||
padding: 10px 35px 0 0px;
|
||||
white-space: initial;
|
||||
|
||||
h3 {
|
||||
font-weight: bold;
|
||||
color:#dedede;
|
||||
}
|
||||
|
||||
> div.session {
|
||||
width: 50%;
|
||||
|
||||
&.right {
|
||||
font-size: 13px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
require 'sanitize'
|
||||
class ApiTextMessagesController < ApiController
|
||||
|
||||
before_filter :api_signed_in_user
|
||||
before_filter :auth_user, :only => [:index, :create]
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
@text_messages = TextMessage.index(params[:target_user_id], @user.id, {:offset => params[:offset]})
|
||||
respond_with @text_messages, responder: ApiResponder, :status => 200
|
||||
end
|
||||
|
||||
def create
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -98,7 +98,9 @@ else
|
|||
|
||||
node do |invitation|
|
||||
user_score(invitation.receiver.id).merge({
|
||||
receiver_avatar_url: invitation.receiver.resolved_photo_url, audio_latency: last_jam_audio_latency(invitation.receiver)
|
||||
receiver_name: invitation.receiver.name,
|
||||
receiver_avatar_url: invitation.receiver.resolved_photo_url,
|
||||
audio_latency: last_jam_audio_latency(invitation.receiver)
|
||||
})
|
||||
end
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
collection @text_messages
|
||||
|
||||
attributes :id, :source_user_id, :target_user_id, :message, :created_at
|
||||
|
||||
node :source_user do |msg|
|
||||
attributes :id, :name
|
||||
end
|
||||
|
||||
node :target_user do |msg|
|
||||
attributes :id, :name
|
||||
end
|
||||
|
|
@ -196,7 +196,7 @@
|
|||
<tr>
|
||||
<td>
|
||||
</td>
|
||||
<td>
|
||||
<td class="nowrap">
|
||||
<span class="rsvp-msg" style="display:none;">You cannot RSVP to this session.</span>
|
||||
<a class="rsvp-link">
|
||||
<%= image_tag "content/rsvp-icon.jpg", :size => "40x40" %>
|
||||
|
|
|
|||
|
|
@ -402,9 +402,9 @@
|
|||
|
||||
<h3 class="mt20">What instruments/parts do you need?</h3>
|
||||
<div class="left ib w20 mt5">Me:</div>
|
||||
<div class="left ib w75 mt5" id="session-instruments-me-disp" class="mt5"></div>
|
||||
<div class="left ib w75 mt5" id="session-instruments-me-disp"></div>
|
||||
<div class="clearall left ib w20">Others:</div>
|
||||
<div class="left ib w75" id="session-instruments-rsvp-disp" class="mt5"></div><br clear="all">
|
||||
<div class="left ib w75 mt5" id="session-instruments-rsvp-disp"></div><br clear="all">
|
||||
|
||||
<h3 class="mt20">What access policies are in effect?</h3>
|
||||
<div id="session-musician-access-disp" class="mt5"></div>
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
= render 'dialogs/rsvpSubmitDialog'
|
||||
= render 'dialogs/rsvpCancelDialog'
|
||||
= render 'dialogs/rsvpCreateSlotDialog'
|
||||
= render 'dialogs/sessionStartDialog'
|
||||
= render 'dialogs/sessionCancelDialog'
|
||||
= render 'dialogs/signinDialog'
|
||||
= render 'dialogs/signupDialog'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
.dialog.dialog-overlay-lg layout='dialog' layout-id='session-start-dialog' id='session-start-dialog'
|
||||
.content-head
|
||||
= image_tag "content/icon_add.png", {:width => 24, :height => 24, :class => 'content-icon' }
|
||||
h1 Start Session
|
||||
|
||||
.dialog-inner
|
||||
.session-wrapper
|
||||
.left.w55
|
||||
h3 When are you starting your session?
|
||||
.mt5 id='session-start-type-disp'
|
||||
h3.mb5.mt20 What are you playing?
|
||||
em id='session-name-disp'
|
||||
#session-description-disp.mt5
|
||||
#session-notations-disp.mt5
|
||||
|
||||
h3.mt20 Which band is playing?
|
||||
#session-band-disp.mt5
|
||||
|
||||
h3.mt20 What language will be spoken?
|
||||
#session-language-disp.mt5
|
||||
.right.w40
|
||||
h3 Who is invited?
|
||||
#session-invited-disp.mt5
|
||||
|
||||
h3.mt20 What instruments/parts do you need?
|
||||
.left.ib.w20.mt5 Me:
|
||||
#session-instruments-me-disp.left.ib.w75.mt5
|
||||
.clearall.left.ib.w20.mt5 Others:
|
||||
#session-instruments-rsvp-disp.left.ib.w75.mt5
|
||||
br clear='all'
|
||||
|
||||
h3.mt20 What access policies are in effect?
|
||||
#session-musician-access-disp.mt5
|
||||
#session-fans-access-disp
|
||||
|
||||
h3.mt20 What legal policy is in effect?
|
||||
#session-policy-disp.mt5
|
||||
.clearall
|
||||
br
|
||||
br
|
||||
.buttons
|
||||
.right
|
||||
a.button-grey class='btnCancel' layout-action='cancel' CANCEL
|
||||
a.button-orange class='btnStartSession' START SESSION
|
||||
|
|
@ -296,6 +296,10 @@ SampleApp::Application.routes.draw do
|
|||
match '/users/:id/friends/:friend_id' => 'api_users#friend_show', :via => :get, :as => 'api_friend_detail'
|
||||
match '/users/:id/friends/:friend_id' => 'api_users#friend_destroy', :via => :delete
|
||||
|
||||
# text messages
|
||||
match '/text_messages' => 'api_text_messages#index', :via => :get
|
||||
match '/text_messages' => 'api_text_messages#create', :via => :post
|
||||
|
||||
# notifications
|
||||
match '/users/:id/notifications' => 'api_users#notification_index', :via => :get
|
||||
match '/users/:id/notifications/:notification_id' => 'api_users#notification_destroy', :via => :delete
|
||||
|
|
|
|||
|
|
@ -192,6 +192,121 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
|
|||
end
|
||||
end
|
||||
|
||||
describe "start session behavior" do
|
||||
before(:each) do
|
||||
stub_const("APP_CONFIG", web_config)
|
||||
@music_session = FactoryGirl.create(:music_session, creator: user)
|
||||
|
||||
@invited_user = FactoryGirl.create(:user)
|
||||
FactoryGirl.create(:friendship, :user => @invited_user, :friend => user)
|
||||
FactoryGirl.create(:friendship, :user => user, :friend => @invited_user)
|
||||
@invitation = FactoryGirl.create(:invitation, :sender => user, :receiver => @invited_user, :music_session => @music_session)
|
||||
|
||||
@rsvp_user = FactoryGirl.create(:user)
|
||||
@rsvp_slot = FactoryGirl.create(:rsvp_slot, music_session: @music_session)
|
||||
@rsvp_request = FactoryGirl.create(:rsvp_request_for_slots, chosen: nil, user: @rsvp_user, slots: [@rsvp_slot])
|
||||
end
|
||||
|
||||
it "should always show start session link for session creator" do
|
||||
pending
|
||||
# sign in as creator
|
||||
fast_signin(user, Nav.find_session)
|
||||
find("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
fast_signout
|
||||
end
|
||||
|
||||
it "should not show start session link for anyone who is not creator, invitee, or RSVP user" do
|
||||
pending
|
||||
random_user = FactoryGirl.create(:user)
|
||||
fast_signin(random_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start")
|
||||
fast_signout
|
||||
end
|
||||
|
||||
it "should show start session link for invited or RSVP users" do
|
||||
pending
|
||||
# make session date/time TBD
|
||||
@music_session.scheduled_start = Time.now + 5.minutes
|
||||
@music_session.save!
|
||||
|
||||
# invited user
|
||||
fast_signin(@invited_user, Nav.find_session)
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
fast_signout
|
||||
|
||||
# RSVP user
|
||||
fast_signin(@rsvp_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
fast_signout
|
||||
|
||||
# now approve the RSVP
|
||||
@rsvp_request.rsvp_requests_rsvp_slots[0].chosen = true
|
||||
@rsvp_request.rsvp_requests_rsvp_slots[0].save!
|
||||
|
||||
fast_signin(@rsvp_user, Nav.find_session)
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
fast_signout
|
||||
end
|
||||
|
||||
it "should not show start session link for invited or RSVP users when date/time is TBD" do
|
||||
pending
|
||||
# make session date/time TBD
|
||||
@music_session.scheduled_start = nil
|
||||
@music_session.save!
|
||||
|
||||
# invited user
|
||||
fast_signin(@invited_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
fast_signout
|
||||
|
||||
# RSVP user
|
||||
fast_signin(@rsvp_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
fast_signout
|
||||
|
||||
# now approve the RSVP
|
||||
@rsvp_request.rsvp_requests_rsvp_slots[0].chosen = true
|
||||
@rsvp_request.rsvp_requests_rsvp_slots[0].save!
|
||||
|
||||
# "start session" should still be hidden
|
||||
fast_signin(@rsvp_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
fast_signout
|
||||
end
|
||||
|
||||
it "should not show start session link for invited or RSVP users when more than 15 minutes remain to start time" do
|
||||
pending
|
||||
# make session date/time more than 15 min away
|
||||
@music_session.scheduled_start = Time.now + 60.minutes
|
||||
@music_session.save!
|
||||
|
||||
# invited user
|
||||
fast_signin(@invited_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
fast_signout
|
||||
|
||||
# RSVP user
|
||||
fast_signin(@rsvp_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
fast_signout
|
||||
|
||||
# now approve the RSVP
|
||||
@rsvp_request.rsvp_requests_rsvp_slots[0].chosen = true
|
||||
@rsvp_request.rsvp_requests_rsvp_slots[0].save!
|
||||
|
||||
# "start session" should still be hidden
|
||||
fast_signin(@rsvp_user, Nav.find_session)
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.start", text: "Start session now?")
|
||||
page.should have_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
fast_signout
|
||||
end
|
||||
end
|
||||
|
||||
describe "rsvp behavior" do
|
||||
before(:each) do
|
||||
stub_const("APP_CONFIG", web_config)
|
||||
|
|
@ -222,10 +337,9 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
|
|||
it "RSVP text shows correctly" do
|
||||
music_session = FactoryGirl.create(:music_session, creator: user)
|
||||
|
||||
# session creator cannot cancel
|
||||
fast_signin(user, Nav.find_session)
|
||||
|
||||
find("#sessions-scheduled .rsvp-msg span.text", text: "You have been confirmed for this session. ")
|
||||
|
||||
page.should have_no_selector("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
sign_out
|
||||
|
||||
# create a slot so the session can be joined
|
||||
|
|
@ -241,15 +355,15 @@ describe "Find Session", :js => true, :type => :feature, :capybara_feature => tr
|
|||
# first state: an unconfirmed RSVP
|
||||
go_to_root
|
||||
fast_signin(finder, Nav.find_session)
|
||||
find("#sessions-scheduled .rsvp-msg span.text", text: "You have RSVP'ed to this session. ")
|
||||
find("#sessions-scheduled .rsvp-msg span.text a.cancel", text: "Cancel RSVP")
|
||||
|
||||
rsvp_request.rsvp_requests_rsvp_slots[0].chosen = true
|
||||
rsvp_request.rsvp_requests_rsvp_slots[0].save!
|
||||
|
||||
# second state: a connfirmed RSVP
|
||||
# second state: a confirmed RSVP
|
||||
go_to_root
|
||||
fast_signin(finder, Nav.find_session)
|
||||
find("#sessions-scheduled .rsvp-msg span.text", text: "You have been confirmed for this session. ")
|
||||
find("#sessions-scheduled a.cancel", text: "Cancel RSVP")
|
||||
|
||||
|
||||
# need to now CANCEL, and check what it says: // VRFS-1891
|
||||
|
|
|
|||
|
|
@ -666,6 +666,7 @@ describe UserManager do
|
|||
before(:each) do
|
||||
@old_recaptcha=Rails.application.config.recaptcha_enable
|
||||
Rails.application.config.recaptcha_enable=true
|
||||
UserMailer.deliveries.clear
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
|
|
@ -687,6 +688,7 @@ describe UserManager do
|
|||
signup_confirm_url: "http://localhost:3000/confirm")
|
||||
|
||||
user.errors.any?.should be_true
|
||||
UserMailer.deliveries.should have(0).items
|
||||
end
|
||||
|
||||
it "passes when facebook signup" do
|
||||
|
|
|
|||
Loading…
Reference in New Issue