diff --git a/db/up/sms_index_optimize.sql b/db/up/sms_index_optimize.sql index 9f013d902..d5120f165 100644 --- a/db/up/sms_index_optimize.sql +++ b/db/up/sms_index_optimize.sql @@ -9,7 +9,7 @@ CREATE OR REPLACE FUNCTION sms_index (my_user_id VARCHAR, my_locidispid BIGINT, -- XXX: we should pass in enough info to match pagination/query to reduce the impact of this step INSERT INTO sms_music_session_tmp SELECT DISTINCT id, NULL::INTEGER AS tag, NULL::INTEGER AS latency FROM music_sessions - WHERE (scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute'))) + WHERE old = FALSE AND (scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute'))) AND canceled = FALSE AND description != 'Jam Track Session' AND id NOT IN (SELECT id FROM active_music_sessions); @@ -204,6 +204,24 @@ CREATE INDEX index_music_sessions_on_canceled ON music_sessions USING btree(canc CREATE INDEX index_music_sessions_on_session_removed_at ON music_sessions USING btree(session_removed_at); CREATE INDEX index_music_sessions_on_started_at ON music_sessions USING btree(started_at); +CREATE INDEX index_recordings_on_first_quick_mix_id ON recordings USING btree(first_quick_mix_id); +CREATE INDEX index_recordings_on_has_final_mix ON recordings USING btree(has_final_mix); +CREATE INDEX index_quick_mixes_on_recording_id ON quick_mixes USING btree(recording_id); +CREATE INDEX index_quick_mixes_on_cleaned ON quick_mixes USING btree(cleaned); +CREATE INDEX index_quick_mixes_on_completed ON quick_mixes USING btree(completed); +CREATE INDEX index_recordings_on_deleted ON recordings USING btree(deleted); +CREATE INDEX index_recordings_on_all_discarded ON recordings USING btree(all_discarded); +CREATE INDEX index_claimed_recordings_on_is_public ON claimed_recordings USING btree(is_public); +CREATE INDEX index_claimed_recordings_on_recording_id ON claimed_recordings USING btree(recording_id); + + +CREATE INDEX index_charges_on_type ON charges USING btree(type); +CREATE INDEX index_charges_on_billing_should_retry ON charges USING btree(billing_should_retry); +CREATE INDEX index_lesson_sessions_on_charge_id ON lesson_sessions USING btree(charge_id); +CREATE INDEX index_music_sessions_on_lesson_session_id ON music_sessions USING btree(lesson_session_id); +CREATE INDEX index_lesson_sessions_on_status ON lesson_sessions USING btree(status); +CREATE INDEX index_lesson_sessions_on_sent_counter_reminder ON lesson_sessions USING btree(sent_counter_reminder); + -- update music_sessions set canceled = true WHERE (scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute'))) AND canceled = FALSE AND description != 'Jam Track Session' AND id NOT IN (SELECT id FROM active_music_sessions) AND id NOT IN (select distinct on(name, user_id) id FROM music_sessions WHERE (scheduled_start IS NULL OR scheduled_start > (NOW() - (interval '15 minute'))) AND canceled = FALSE AND description != 'Jam Track Session' AND id NOT IN (SELECT id FROM active_music_sessions) order by name, user_id); diff --git a/ruby/lib/jam_ruby/models/active_music_session.rb b/ruby/lib/jam_ruby/models/active_music_session.rb index 41a8ebfa5..a24595552 100644 --- a/ruby/lib/jam_ruby/models/active_music_session.rb +++ b/ruby/lib/jam_ruby/models/active_music_session.rb @@ -552,6 +552,10 @@ module JamRuby icecast_server = IcecastServer.find_best_server_for_user(user) if music_session.fan_access icecast_server.lock! if icecast_server + music_session.running_recordings.each do |recording| + recording.stop + end + # check if we are connected to rabbitmq active_music_session = ActiveMusicSession.new active_music_session.id = music_session.id # copy the .id from music_session to active_music_session diff --git a/ruby/lib/jam_ruby/models/chat_message.rb b/ruby/lib/jam_ruby/models/chat_message.rb index bd38c1c1f..b67a619ab 100644 --- a/ruby/lib/jam_ruby/models/chat_message.rb +++ b/ruby/lib/jam_ruby/models/chat_message.rb @@ -114,12 +114,19 @@ module JamRuby attachment_type = music_notation.attachment_type attachment_name = music_notation.file_name elsif claimed_recording - attachment_id = claimed_recording.id - attachment_type = 'recording' - attachment_name = claimed_recording.name + if purpose == 'Video Uploaded' + attachment_id = claimed_recording.video_id + attachment_type = 'video' + else + attachment_id = claimed_recording.id + attachment_type = 'recording' + attachment_name = claimed_recording.name + + end end + msg = @@message_factory.chat_message( music_session_id, user.name, diff --git a/ruby/lib/jam_ruby/models/claimed_recording.rb b/ruby/lib/jam_ruby/models/claimed_recording.rb index 7d2727138..15d91fae6 100644 --- a/ruby/lib/jam_ruby/models/claimed_recording.rb +++ b/ruby/lib/jam_ruby/models/claimed_recording.rb @@ -31,6 +31,9 @@ module JamRuby SHARE_TOKEN_LENGTH = 8 FIXNUM_MAX = (2**(0.size * 8 -2) -1) + def video_id + recording.external_video_id + end def user_belongs_to_recording if user && recording && !recording.users.exists?(user.id) diff --git a/ruby/lib/jam_ruby/models/lesson_booking.rb b/ruby/lib/jam_ruby/models/lesson_booking.rb index 3d2eb41b6..2280ad086 100644 --- a/ruby/lib/jam_ruby/models/lesson_booking.rb +++ b/ruby/lib/jam_ruby/models/lesson_booking.rb @@ -470,6 +470,10 @@ module JamRuby active end + def has_access?(user) + user.id == student.id || user.id == teacher.id || (self.school.nil? ? false : self.school.user.id == user.id) + end + def validate_accepted # accept is multipe purpose; either accept the initial request, or a counter slot if self.status_was != STATUS_REQUESTED && self.status_was != STATUS_COUNTERED diff --git a/ruby/lib/jam_ruby/models/lesson_session.rb b/ruby/lib/jam_ruby/models/lesson_session.rb index 66760d083..bb97f9d2c 100644 --- a/ruby/lib/jam_ruby/models/lesson_session.rb +++ b/ruby/lib/jam_ruby/models/lesson_session.rb @@ -11,7 +11,7 @@ module JamRuby @@log = Logging.logger[LessonSession] delegate :sent_billing_notices, :last_billing_attempt_at, :billing_attempts, :billing_should_retry, :billed_at, :billing_error_detail, :billing_error_reason, :is_card_declined?, :is_card_expired?, :last_billed_at_date, :sent_billing_notices, to: :lesson_payment_charge, allow_nil: true - delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, :school_on_school?, :school_on_school_payment?, :no_school_on_school_payment?, :payment_if_school_on_school?, :scheduling_email, :teacher_school_emails, :school_and_teacher, :school_over_teacher, :school_and_teacher_ids, :school_over_teacher_ids, :posa_card, :remaining_roll_forward_amount_in_cents, :has_recurring_counter?, :ever_accepted?, to: :lesson_booking + delegate :is_test_drive?, :is_single_free?, :is_normal?, :approved_before?, :is_active?, :recurring, :is_monthly_payment?, :school_on_school?, :school_on_school_payment?, :no_school_on_school_payment?, :payment_if_school_on_school?, :scheduling_email, :teacher_school_emails, :school_and_teacher, :school_over_teacher, :school_and_teacher_ids, :school_over_teacher_ids, :posa_card, :remaining_roll_forward_amount_in_cents, :has_recurring_counter?, :ever_accepted?, :has_access?, to: :lesson_booking delegate :pretty_scheduled_start, to: :music_session @@ -338,6 +338,21 @@ module JamRuby self.save(validate: false) end + def video_uploaded(user, recording, data) + + claim = recording.claim_for_user(user) + msg = ChatMessage.create(user, nil, "Video Recording '#{claim.name}'", ChatMessage::CHANNEL_LESSON, nil, other_user(user), self, "Video Uploaded", nil, claim) + Notification.send_lesson_message('video uploaded', self, false) + Notification.send_lesson_message('video uploaded', self, true) + end + + def other_user(user) + if user.id == student.id + teacher + else + student + end + end def session_completed LessonSession.transaction do self.lock! diff --git a/ruby/lib/jam_ruby/models/music_session.rb b/ruby/lib/jam_ruby/models/music_session.rb index 290cf416c..544b61a5b 100644 --- a/ruby/lib/jam_ruby/models/music_session.rb +++ b/ruby/lib/jam_ruby/models/music_session.rb @@ -482,10 +482,22 @@ module JamRuby if self.musician_access || self.fan_access true else - self.creator == user || self.invited_musicians.exists?(user.id) + self.creator == user || self.invited_musicians.exists?(user.id) || self.approved_rsvps.include?(user) || self.has_lesson_access?(user) end end + def has_lesson_access?(user) + if is_lesson? + puts "HAS LESSON ACCESS" + result = lesson_session.has_access?(user) + puts "HAS LESSON ACCESS #{ result}" + result + else + false + end + + end + def set_session_controller(current_user, user) # only allow update of session controller by the creator or the currently marked user @@ -896,6 +908,9 @@ module JamRuby RsvpRequest.index(self, nil, {status: 'pending'}) end + def running_recordings + recordings.where(duration: nil) + end def recordings Recording.where(music_session_id: self.id) end diff --git a/ruby/lib/jam_ruby/models/recording.rb b/ruby/lib/jam_ruby/models/recording.rb index 348ab6de5..46fac5e82 100644 --- a/ruby/lib/jam_ruby/models/recording.rb +++ b/ruby/lib/jam_ruby/models/recording.rb @@ -755,8 +755,12 @@ module JamRuby self.save(:validate => false) end - def add_video_data(data) + def add_video_data(user, data) Recording.where(id: self.id).update_all(external_video_id: data[:video_id]) + + if music_session.music_session.is_lesson? + music_session.lesson_session.video_uploaded(user, self, data) + end end def add_timeline(timeline) diff --git a/ruby/lib/jam_ruby/models/user_authorization.rb b/ruby/lib/jam_ruby/models/user_authorization.rb index a78bad549..28853954b 100644 --- a/ruby/lib/jam_ruby/models/user_authorization.rb +++ b/ruby/lib/jam_ruby/models/user_authorization.rb @@ -38,6 +38,10 @@ module JamRuby auth.save return auth rescue Exception => e + puts "could not refresh; #{e}" + if auth + auth.destroy + end # couldn't refresh; probably the user has revoked the app's rights return nil end diff --git a/web/app/assets/javascripts/react-components/ChatDialog.js.jsx.coffee b/web/app/assets/javascripts/react-components/ChatDialog.js.jsx.coffee index 3b012781b..27b77eec6 100644 --- a/web/app/assets/javascripts/react-components/ChatDialog.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/ChatDialog.js.jsx.coffee @@ -2,7 +2,7 @@ context = window @ChatDialog = React.createClass({ - mixins: [@PostProcessorMixin, Reflux.listenTo(@AppStore, "onAppInit")] + mixins: [@PostProcessorMixin, Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@SessionStore, 'onSessionChanged')] teacher: false beforeShow: (args) -> @@ -27,7 +27,8 @@ context = window @app.ajaxError(jqXHR) afterHide: () -> - window.ChatActions.activateChannel('global') + if !@session?.isLesson + window.ChatActions.activateChannel('global') parseId:(id) -> if !id? @@ -47,6 +48,9 @@ context = window @app.bindDialog('chat-dialog', dialogBindings); + onSessionChanged: (session) -> + @session = session + componentDidMount: () -> @root = $(@getDOMNode()) diff --git a/web/app/assets/javascripts/react-components/ChatWindow.js.jsx.coffee b/web/app/assets/javascripts/react-components/ChatWindow.js.jsx.coffee index beb1fc840..901be0624 100644 --- a/web/app/assets/javascripts/react-components/ChatWindow.js.jsx.coffee +++ b/web/app/assets/javascripts/react-components/ChatWindow.js.jsx.coffee @@ -45,6 +45,7 @@ ChatActions = @ChatActions when 'Audio File' then 'attached an audio file' when 'JamKazam Recording' then 'attached a recording' when 'Lesson Timeout' then 'canceled by system' + when 'Video Uploaded' then 'uploaded video' else purpose notationClicked: (music_notation, e) -> @@ -61,6 +62,10 @@ ChatActions = @ChatActions e.preventDefault() context.JK.popExternalLink("/recordings/#{recording.id}") + videoClicked: (recording, e) -> + e.preventDefault() + context.JK.popExternalLink("https://www.youtube.com/watch?v=#{recording.video_id}") + openMenu: (lesson, e) -> $this = $(e.target) if !$this.is('.lesson-session-actions-btn') @@ -132,6 +137,8 @@ ChatActions = @ChatActions additional = `{msg.music_notation.file_name}` else if msg.purpose == 'JamKazam Recording' additional = `{msg.claimed_recording.name}` + else if msg.purpose == 'Video Uploaded' + additional = `Watch on YouTube` msgs.push(`