From 91da29088f05bec7667dd3301940c6070c69939c Mon Sep 17 00:00:00 2001
From: Seth Call
Date: Sat, 27 Jan 2018 16:18:04 -0600
Subject: [PATCH] teacher search and cancel powers for slow teacher responsens
---
admin/Gemfile | 2 +-
admin/Gemfile.lock | 61 ++++++-----
admin/app/admin/dashboard.rb | 11 +-
admin/app/admin/jam_ruby_users.rb | 40 +++++--
admin/app/admin/jam_track_right.rb | 1 +
admin/app/admin/slow_responses.rb | 100 ++++++++++++++----
admin/app/admin/teachers.rb | 2 +-
db/manifest | 3 +-
db/up/teacher_search_control.sql | 4 +
.../student_lesson_booking_canceled.html.erb | 7 +-
.../student_lesson_booking_declined.html.erb | 19 +++-
.../student_lesson_canceled.html.erb | 12 ++-
.../teacher_lesson_booking_canceled.html.erb | 13 ++-
.../teacher_lesson_canceled.html.erb | 12 ++-
ruby/lib/jam_ruby/models/jam_track_right.rb | 4 +-
ruby/lib/jam_ruby/models/lesson_booking.rb | 25 +++--
ruby/lib/jam_ruby/models/lesson_session.rb | 73 +++++++++----
ruby/lib/jam_ruby/models/teacher.rb | 3 +-
web/app/assets/javascripts/profile.js | 26 +++++
.../LessonBooking.js.jsx.coffee | 32 ++++--
.../mixins/PostProcessorMixin.js.coffee | 4 +-
web/app/assets/stylesheets/client/client.css | 1 +
.../assets/stylesheets/client/jamkazam.scss | 2 +-
.../assets/stylesheets/client/profile.scss | 12 +++
web/app/assets/stylesheets/client/toggle.scss | 59 +++++++++++
web/app/views/api_lesson_bookings/show.rabl | 2 +-
web/app/views/api_lesson_sessions/show.rabl | 2 +-
web/app/views/api_teachers/detail.rabl | 3 +-
web/app/views/clients/_profile.html.erb | 13 +++
29 files changed, 427 insertions(+), 121 deletions(-)
create mode 100644 db/up/teacher_search_control.sql
create mode 100644 web/app/assets/stylesheets/client/toggle.scss
diff --git a/admin/Gemfile b/admin/Gemfile
index f12413723..595d94904 100644
--- a/admin/Gemfile
+++ b/admin/Gemfile
@@ -108,7 +108,7 @@ end
group :development, :test do
gem 'capybara'
- gem 'rspec-rails', '2.14.2'
+ gem 'rspec-rails' #, '2.14.2'
gem 'jasmine', '1.3.1'
gem 'execjs', '1.4.0'
#gem 'therubyracer' #, '0.11.0beta8'
diff --git a/admin/Gemfile.lock b/admin/Gemfile.lock
index ec7d8fc45..d029ef2ce 100644
--- a/admin/Gemfile.lock
+++ b/admin/Gemfile.lock
@@ -92,7 +92,7 @@ GEM
aws-sdk-v1 (1.67.0)
json (~> 1.4)
nokogiri (~> 1)
- backports (3.11.0)
+ backports (3.11.1)
bcrypt (3.1.11)
bcrypt-ruby (3.0.1)
binding_of_caller (0.8.0)
@@ -100,7 +100,7 @@ GEM
bootstrap-sass (2.0.4.0)
bootstrap-will_paginate (0.0.6)
will_paginate
- bugsnag (6.6.1)
+ bugsnag (6.6.3)
concurrent-ruby (~> 1.0)
builder (3.2.3)
cabin (0.9.0)
@@ -147,7 +147,7 @@ GEM
crass (1.0.3)
database_cleaner (1.6.2)
debug_inspector (0.0.3)
- devise (4.4.0)
+ devise (4.4.1)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0, < 5.2)
@@ -160,7 +160,7 @@ GEM
email_validator (1.6.0)
activemodel
erubis (2.7.0)
- et-orbi (1.0.8)
+ et-orbi (1.0.9)
tzinfo
eventmachine (1.2.3)
excon (0.60.0)
@@ -173,7 +173,7 @@ GEM
railties (>= 3.0.0)
faker (1.3.0)
i18n (~> 0.5)
- faraday (0.13.1)
+ faraday (0.14.0)
multipart-post (>= 1.2, < 3)
ffi (1.9.18)
fission (0.5.0)
@@ -314,10 +314,10 @@ GEM
domain_name (~> 0.5)
httparty (0.15.6)
multi_xml (>= 0.5.2)
- i18n (0.9.1)
+ i18n (0.9.3)
concurrent-ruby (~> 1.0)
inflecto (0.0.2)
- influxdb (0.5.2)
+ influxdb (0.5.3)
influxdb-rails (0.4.3)
influxdb (~> 0.5.0)
railties (> 3)
@@ -374,7 +374,7 @@ GEM
mimemagic (0.3.2)
mini_mime (1.0.0)
mini_portile2 (2.3.0)
- minitest (5.11.1)
+ minitest (5.11.2)
mono_logger (1.1.0)
multi_json (1.13.1)
multi_xml (0.6.0)
@@ -404,7 +404,7 @@ GEM
capybara (~> 2.1)
cliver (~> 0.3.1)
websocket-driver (>= 0.2.0)
- polyamorous (1.3.2)
+ polyamorous (1.3.3)
activerecord (>= 3.0)
postgres-copy (0.6.0)
activerecord (>= 3.0.0)
@@ -428,7 +428,7 @@ GEM
binding_of_caller (>= 0.7)
pry (>= 0.9.11)
public_suffix (3.0.1)
- puma (3.11.0)
+ puma (3.11.2)
rack (1.6.8)
rack-protection (1.5.3)
rack
@@ -464,16 +464,16 @@ GEM
thor (>= 0.18.1, < 2.0)
raindrops (0.19.0)
rake (12.3.0)
- ransack (1.8.4)
+ ransack (1.8.6)
actionpack (>= 3.0)
activerecord (>= 3.0)
activesupport (>= 3.0)
i18n
- polyamorous (~> 1.3)
+ polyamorous (~> 1.3.2)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
- recurly (2.12.0)
+ recurly (2.12.1)
redis (4.0.1)
redis-namespace (1.6.0)
redis (>= 3.0.4)
@@ -507,22 +507,27 @@ GEM
http-cookie (>= 1.0.2, < 2.0)
mime-types (>= 1.16, < 4.0)
netrc (~> 0.8)
- rspec (2.14.1)
- rspec-core (~> 2.14.0)
- rspec-expectations (~> 2.14.0)
- rspec-mocks (~> 2.14.0)
- rspec-core (2.14.8)
- rspec-expectations (2.14.5)
- diff-lcs (>= 1.1.3, < 2.0)
- rspec-mocks (2.14.6)
- rspec-rails (2.14.2)
+ rspec (3.7.0)
+ rspec-core (~> 3.7.0)
+ rspec-expectations (~> 3.7.0)
+ rspec-mocks (~> 3.7.0)
+ rspec-core (3.7.1)
+ rspec-support (~> 3.7.0)
+ rspec-expectations (3.7.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.7.0)
+ rspec-mocks (3.7.0)
+ diff-lcs (>= 1.2.0, < 2.0)
+ rspec-support (~> 3.7.0)
+ rspec-rails (3.7.2)
actionpack (>= 3.0)
- activemodel (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
- rspec-core (~> 2.14.0)
- rspec-expectations (~> 2.14.0)
- rspec-mocks (~> 2.14.0)
+ rspec-core (~> 3.7.0)
+ rspec-expectations (~> 3.7.0)
+ rspec-mocks (~> 3.7.0)
+ rspec-support (~> 3.7.0)
+ rspec-support (3.7.0)
ruby-protocol-buffers (1.2.2)
ruby-xz (0.2.3)
ffi (~> 1.9)
@@ -589,7 +594,7 @@ GEM
tilt (2.0.8)
tzinfo (1.2.4)
thread_safe (~> 0.1)
- uglifier (4.1.3)
+ uglifier (4.1.4)
execjs (>= 0.3.0, < 3)
unf (0.1.3)
unf_ext
@@ -679,7 +684,7 @@ DEPENDENCIES
resque-retry
resque_mailer
rest-client
- rspec-rails (= 2.14.2)
+ rspec-rails
ruby-protocol-buffers (= 1.2.2)
rubyzip
sanitize
diff --git a/admin/app/admin/dashboard.rb b/admin/app/admin/dashboard.rb
index a22643621..51903b216 100644
--- a/admin/app/admin/dashboard.rb
+++ b/admin/app/admin/dashboard.rb
@@ -5,11 +5,14 @@ ActiveAdmin.register_page "Dashboard" do
content :title => proc{ I18n.t("active_admin.dashboard") } do
div :class => "blank_slate_container", :id => "dashboard_default_message" do
span :class => "blank_slate" do
- span "JamKazam Data Administration Portal"
+ span "JamKazam Administration Portal"
small ul do
- li "Admin users are users with the admin boolean set to true"
- li "Invite JamKazam users using the 'Users > Invite' menu in header"
- li "Admin users are created/deleted when toggling the 'admin' flag for JamKazam users"
+ li link_to "Users", admin_users_path
+ li link_to "Teachers", admin_teachers_path
+ li link_to "Onboarding Management", admin_currently_onboardings_path
+ li link_to "Lesson Sessions", admin_lesson_sessions_path
+ li link_to "Slow Lesson Responses", admin_slow_responses_path
+
end
end
end
diff --git a/admin/app/admin/jam_ruby_users.rb b/admin/app/admin/jam_ruby_users.rb
index 2c4029549..cce181faf 100644
--- a/admin/app/admin/jam_ruby_users.rb
+++ b/admin/app/admin/jam_ruby_users.rb
@@ -12,6 +12,8 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
filter :created_at
filter :updated_at
+ includes :purchased_jam_tracks, :jam_track_rights => :jam_track, :taken_lessons => :music_session, :taught_lessons => :music_session
+
form :partial => "form"
show do |user|
@@ -79,7 +81,9 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
else
end
end
- row "Signup" do user.created_at.to_date end
+ row "Signup" do
+ user.created_at.to_date
+ end
row "Assigned", :onboarder_assigned_at
row "Email 1", :onboarding_email_1_sent_at
row "Email 2", :onboarding_email_2_sent_at
@@ -97,6 +101,14 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
end
end
+
+ panel "Teacher Setting" do
+ attributes_table do
+ row :is_searchable
+ end
+ end if user.teacher
+
+
panel "Lessons" do
attributes_table do
row "Taken Lessons" do
@@ -154,6 +166,24 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
end
+ panel "JamTracks" do
+ div do
+ link_to "Give JamTrack", "../jam_track_rights/new"
+ end
+
+ attributes_table do
+ row "Purchased JamTracks" do
+ table_for user.purchased_jam_tracks.unscope(:order).order('original_artist asc', 'name asc') do
+ column "Artist", :original_artist
+ column "Name", :name
+ column "Can Download", :can_download, as: :boolean, hint: 'Can download is the 2.99 value (have download rights)'
+ column "Version", :version
+ column "ID", :id
+ end
+ end
+ end
+ end
+
active_admin_comments
end
@@ -174,22 +204,14 @@ ActiveAdmin.register JamRuby::User, :as => 'Users' do
link_to user.email, resource_path(user)
end
column :admin
- column :updated_at
column :created_at
column :musician do |user|
user.musician? ? true : false
end
column :city
column :state
- column :country
column :first_name
column :last_name
- column :birth_date
- column :gender
- column :email_confirmed
- column :photo_url
- column :session_settings
- column :can_invite
end
controller do
diff --git a/admin/app/admin/jam_track_right.rb b/admin/app/admin/jam_track_right.rb
index 0ea648dcb..6892b6aaf 100644
--- a/admin/app/admin/jam_track_right.rb
+++ b/admin/app/admin/jam_track_right.rb
@@ -49,6 +49,7 @@ ActiveAdmin.register JamRuby::JamTrackRight, :as => 'JamTrackRights' do
f.inputs 'New Jam Track Right' do
f.input :jam_track, :required=>true, collection: JamTrack.all, include_blank: false
f.input :user, :required=>true, collection: User.all, include_blank: false
+ f.input :can_download, :required => true, as: :boolean
end
f.actions
end
diff --git a/admin/app/admin/slow_responses.rb b/admin/app/admin/slow_responses.rb
index 46bb3f919..32f3f3045 100644
--- a/admin/app/admin/slow_responses.rb
+++ b/admin/app/admin/slow_responses.rb
@@ -6,45 +6,101 @@ ActiveAdmin.register JamRuby::LessonSession, :as => 'SlowResponses' do
config.batch_actions = false
config.per_page = 100
config.paginate = true
- config.filters = false
+ config.filters = true
- scope("Slow Responses", default: true) { |scope| scope.unscoped.slow_responses }
- scope("Least Time Left") { |scope| scope.unscoped.least_time_left }
+ filter :intervened_at_null, label: 'Not Yet Intervened', as: :boolean
+
+ scope("72 hours since last request/counter", default: true) { |scope| scope.slow_responses }
+
+ member_action :cancel_lesson, :method => :get do
+ result = resource.cancel_by_admin
+
+ if result.errors.any?
+ redirect_to :back, notice: resource.errors.inspect
+ else
+ redirect_to :back, notice: 'Canceled lesson'
+ end
+ end
+
+ member_action :intervened, :method => :get do
+ resource.intervened
+ redirect_to :back
+ end
index do
- column "Teacher" do |lesson_session|
- teacher = lesson_session.teacher
- span do
- link_to "#{teacher.name} (#{teacher.email})", "#{Rails.application.config.external_root_url}/client#/profile/teacher/#{teacher.id}"
+ column "Not Responded" do |lesson_session|
+ div do
+ if lesson_session.student_last_proposed?
+ "Teacher"
+ else
+ "Student"
+ end
+ end
+ div do
+ late_responder = lesson_session.late_responder
+ span do
+ link_to "#{late_responder.name}", late_responder.admin_url
+ end
+ end
+ div do
+ lesson_session.late_responder.email
end
end
- column "Student" do |lesson_session|
- student = lesson_session.student
- span do
- link_to "#{student.name} (#{student.email})", "#{Rails.application.config.external_root_url}/client#/profile/#{student.id}"
+ column "Proposer" do |lesson_session|
+ div do
+ if lesson_session.student_last_proposed?
+ "Student"
+ else
+ "Teacher"
+ end
+ end
+ div do
+ last_proposer = lesson_session.last_proposer
+ span do
+ link_to "#{last_proposer.name}", last_proposer.admin_url
+ end
+ end
+ div do
+ lesson_session.last_proposer.email
end
end
- column "Type" do |lesson_session|
- link_to lesson_session.display_type
+ column "Lesson Type" do |lesson_session|
+ lesson_session.display_type
end
- column "Start Time" do |lesson_session|
+ column "Proposed Start Time" do |lesson_session|
span do
if lesson_session.music_session.nil?
raise "Lessonsesison with no id #{lesson_session.id}"
else
- lesson_session.music_session.pretty_scheduled_start(true)
+ link_to lesson_session.music_session.pretty_scheduled_start(true), lesson_session.admin_url
+
end
end
end
- column "Last student comms date" do |lesson_session|
- lesson_session.last_student_comm_date
- end
column "Days with no response" do |lesson_session|
- "#{lesson_session.days_no_response} days"
+ if lesson_session.last_response_time.nil?
+ 'N/A'
+ else
+ "#{((Time.now - lesson_session.last_response_time) / 24 / 3600).floor} days"
+ end
end
+ column "Num Reqs/Counters" do |lesson_session|
+ ChatMessage.unscoped.where(lesson_session_id: lesson_session.id).where('purpose = ? OR purpose = ?', "Lesson Requested", "New Time Proposed").count(:purpose)
+ end
+ column "Intervene" do |lesson_session|
+ span do
+ if lesson_session.intervened_at
+ lesson_session.intervened_at.to_date
+ else
+ link_to("intervened", intervened_admin_slow_response_path(lesson_session.id), {confirm: "Mark Lesson as 'Intervened' (i.e., email sent to by hand)?"})
+ end
-
-
+ end
+ end
+ column "Cancel Lesson" do |lesson_session|
+ span do
+ link_to("cancel", cancel_lesson_admin_slow_response_path(lesson_session.id), {confirm: "Cancel Lesson?"})
+ end
+ end
end
-
end
\ No newline at end of file
diff --git a/admin/app/admin/teachers.rb b/admin/app/admin/teachers.rb
index c79cd5bfb..7976a7cd3 100644
--- a/admin/app/admin/teachers.rb
+++ b/admin/app/admin/teachers.rb
@@ -18,7 +18,7 @@ ActiveAdmin.register JamRuby::Teacher, :as => 'Teachers' do
end
filter :teacher_full_name_or_user_email_cont, label: 'Name', as: :string
- filter :user_phantom, label: 'Phantom', as: :boolean, selected: 'false'
+ filter :user_phantom, label: 'Phantom ', as: :boolean, selected: 'false'
#filter :by_search_user_name, label: "Name", as: :string
diff --git a/db/manifest b/db/manifest
index 61df1be7d..19a9059d2 100755
--- a/db/manifest
+++ b/db/manifest
@@ -382,4 +382,5 @@ amazon_signup.sql
age_out_sessions.sql
alter_crash_dumps.sql
onboarding.sql
-better_lesson_notices.sql
\ No newline at end of file
+better_lesson_notices.sql
+teacher_search_control.sql
\ No newline at end of file
diff --git a/db/up/teacher_search_control.sql b/db/up/teacher_search_control.sql
new file mode 100644
index 000000000..60a017ac0
--- /dev/null
+++ b/db/up/teacher_search_control.sql
@@ -0,0 +1,4 @@
+ALTER TABLE teachers ADD COLUMN is_searchable BOOLEAN NOT NULL DEFAULT true;
+ALTER TABLE lesson_sessions ADD COLUMN canceled_by_admin TIMESTAMP without time zone;
+ALTER TABLE lesson_bookings ADD COLUMN canceled_by_admin TIMESTAMP without time zone;
+ALTER TABLE lesson_sessions ADD COLUMN intervened_at TIMESTAMP without time zone;
\ No newline at end of file
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_canceled.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_canceled.html.erb
index 7151dbcfb..a0420f3ef 100644
--- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_canceled.html.erb
+++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_canceled.html.erb
@@ -1,6 +1,9 @@
<% provide(:title, @subject) %>
-<% provide(:photo_url, @lesson_booking.canceler.resolved_photo_url) %>
-
+<% if @lesson_booking.canceler %>
+ <% provide(:photo_url, @lesson_booking.canceler.resolved_photo_url) %>
+<% else %>
+ <% provide(:photo_url, "#{APP_CONFIG.external_root_url}/assets/shared/avatar_generic.png") %>
+<% end %>
<% content_for :note do %>
<% if @lesson_booking.recurring %>
diff --git a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_declined.html.erb b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_declined.html.erb
index 410621edb..b394a33cc 100644
--- a/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_declined.html.erb
+++ b/ruby/lib/jam_ruby/app/views/jam_ruby/user_mailer/student_lesson_booking_declined.html.erb
@@ -4,14 +4,27 @@
<% content_for :note do %>
- This teacher has declined your lesson request.
+ <% if @lesson_booking.canceled_by_admin %>
+ This lesson was canceled by a JamKazam administrator.
+ <% else %>
+ This teacher has declined your lesson request.
+ <% end %>
<% if @message.present? %>
-
<%= @teacher.name %> says:
+ <% if @lesson_booking.canceled_by_admin %>
+
System says:
+ <% else %>
+
<%= @teacher.name %> says:
+ <% end %>
<%= @message %>
<% end %>
-
Click the button below to view the teacher's response.
+ <% if @lesson_booking.canceled_by_admin %>
+
Click the button below to view the administrator's message.
+ <% else %>
+
Click the button below to view the teacher's response.
+ <% end %>
+
<%= @lesson_session.canceler.name %> says:
+ <% if @lesson_session.canceled_by_admin %>
+
System says:
+ <% else %>
+
<%= @lesson_session.canceler.name %> says:
+ <% end %>
<%= @message %>
<% end %>
diff --git a/ruby/lib/jam_ruby/models/jam_track_right.rb b/ruby/lib/jam_ruby/models/jam_track_right.rb
index b9af3eaf8..e02399663 100644
--- a/ruby/lib/jam_ruby/models/jam_track_right.rb
+++ b/ruby/lib/jam_ruby/models/jam_track_right.rb
@@ -7,7 +7,7 @@ module JamRuby
@@log = Logging.logger[JamTrackRight]
attr_accessible :user, :jam_track, :user_id, :jam_track_id, :download_count
- attr_accessible :user_id, :jam_track_id, as: :admin
+ attr_accessible :user_id, :jam_track_id, :can_download, as: :admin
attr_accessible :url_48, :md5_48, :length_48, :url_44, :md5_44, :length_44
belongs_to :user, class_name: "JamRuby::User" # the owner, or purchaser of the jam_track
belongs_to :jam_track, class_name: "JamRuby::JamTrack"
@@ -38,6 +38,8 @@ module JamRuby
key = rsa_key.to_pem()
self.private_key_44 = key
self.private_key_48 = key
+
+ self.version = jam_track.version
end
def after_save
# try to catch major transitions:
diff --git a/ruby/lib/jam_ruby/models/lesson_booking.rb b/ruby/lib/jam_ruby/models/lesson_booking.rb
index 2280ad086..ddd30c2b1 100644
--- a/ruby/lib/jam_ruby/models/lesson_booking.rb
+++ b/ruby/lib/jam_ruby/models/lesson_booking.rb
@@ -741,14 +741,16 @@ module JamRuby
self
end
- def cancel_tracking(canceler, message)
+ def cancel_tracking(canceler, message, canceled_by_admin = false)
canceled_by_student = canceler == student
self.status = STATUS_CANCELED
self.cancel_message = message
- self.canceler = canceler
+ self.canceler = canceler if !canceled_by_admin
self.canceling = true
- if canceled_by_student
+ if canceled_by_admin
+ self.canceled_by_admin = Time.now
+ elsif canceled_by_student
self.student_canceled = true
self.student_canceled_at = Time.now
self.student_canceled_reason = message
@@ -759,16 +761,16 @@ module JamRuby
end
end
- def cancel(canceler, other, message)
+ def cancel(canceler, other, message, canceled_by_admin = false)
- cancel_tracking(canceler, message)
+ cancel_tracking(canceler, message, canceled_by_admin)
self.active = false
success = save
if success
lesson_sessions.upcoming.each do |lesson_session|
lesson_session = LessonSession.find(lesson_session.id) # because .upcoming creates ReadOnly records
- lesson_session.cancel_lesson(canceler, message)
+ lesson_session.cancel_lesson(canceler, message, canceled_by_admin)
if !lesson_session.save
return lesson_session
end
@@ -781,7 +783,12 @@ module JamRuby
UserMailer.teacher_lesson_booking_canceled(self, message).deliver_now
purpose = "Lesson Canceled"
else
- if canceler == student
+ if canceled_by_admin
+ # meh. no two way comm here. just bail
+ #Notification.send_lesson_message('canceled', next_lesson, true)
+ UserMailer.student_lesson_booking_declined(self, message).deliver_now
+ UserMailer.teacher_lesson_booking_canceled(self, message).deliver_now
+ elsif canceler == student
# if it's the first time acceptance student canceling, we call it a 'cancel'
Notification.send_lesson_message('canceled', next_lesson, false)
UserMailer.teacher_lesson_booking_canceled(self, message).deliver_now
@@ -795,7 +802,9 @@ module JamRuby
end
message = '' if message.nil?
- msg = ChatMessage.create(canceler, nil, message, ChatMessage::CHANNEL_LESSON, nil, other, next_lesson, purpose)
+ if !canceled_by_admin
+ msg = ChatMessage.create(canceler, nil, message, ChatMessage::CHANNEL_LESSON, nil, other, next_lesson, purpose)
+ end
else
end
diff --git a/ruby/lib/jam_ruby/models/lesson_session.rb b/ruby/lib/jam_ruby/models/lesson_session.rb
index 2fa288174..3251695d8 100644
--- a/ruby/lib/jam_ruby/models/lesson_session.rb
+++ b/ruby/lib/jam_ruby/models/lesson_session.rb
@@ -79,11 +79,8 @@ module JamRuby
scope :past_cancel_window, -> { joins(:music_session).where('music_sessions.scheduled_start > ?', 24.hours.from_now) }
# show all requested/countered sessions where the student was the last to communicate
scope :slow_responses, -> { joins(:lesson_booking).where('lesson_sessions.status = ? OR lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED, LessonSession::STATUS_COUNTERED)
- .where('lesson_sessions.counterer_id IS NULL OR lesson_sessions.user_id = lesson_sessions.counterer_id')
+ .where("(? - (COALESCE(lesson_sessions.countered_at, lesson_bookings.sent_notices_at))) > INTERVAL '72 hours'", Time.now)
.order('(COALESCE(lesson_sessions.countered_at, lesson_bookings.sent_notices_at)) ASC') }
- scope :least_time_left, -> { joins(:lesson_booking, :music_session).where('lesson_sessions.status = ? OR lesson_sessions.status = ?', LessonSession::STATUS_REQUESTED, LessonSession::STATUS_COUNTERED)
- .where('lesson_sessions.counterer_id IS NULL OR lesson_sessions.user_id = lesson_sessions.counterer_id')
- .order('music_sessions.scheduled_start DESC') }
def create_charge
if payment_if_school_on_school? && !is_test_drive? && !is_monthly_payment?
@@ -222,6 +219,22 @@ module JamRuby
counterer_id.nil? || counterer_id == student_id
end
+ def late_responder
+ if student_last_proposed?
+ teacher
+ else
+ student
+ end
+ end
+
+ def last_proposer
+ if student_last_proposed?
+ student
+ else
+ teacher
+ end
+ end
+
def lesson_is_free?
lesson_booking.booked_price == 0.00
end
@@ -999,15 +1012,17 @@ module JamRuby
response
end
- def cancel_lesson(canceler, message)
+ def cancel_lesson(canceler, message, canceled_by_admin = false)
canceled_by_student = canceler == student
self.status = STATUS_CANCELED
self.cancel_message = message
- self.canceler = canceler
+ self.canceler = canceler if !canceled_by_admin
self.canceling = true
- if canceled_by_student
+ if canceled_by_admin
+
+ elsif canceled_by_student
self.student_canceled = true
self.student_canceled_at = Time.now
self.student_canceled_reason = message
@@ -1059,6 +1074,10 @@ module JamRuby
other = canceled_by_student ? teacher : student
message = params[:message]
message = '' if message.nil?
+ if params[:canceled_by_admin]
+ self.canceled_by_admin = Time.now
+ end
+
if lesson_booking.recurring
update_all = params[:update_all]
@@ -1071,7 +1090,7 @@ module JamRuby
end
if update_all
- response = lesson_booking.cancel(canceler, other, message)
+ response = lesson_booking.cancel(canceler, other, message, params[:canceled_by_admin])
if response.errors.any?
raise ActiveRecord::Rollback
end
@@ -1081,13 +1100,20 @@ module JamRuby
raise ActiveRecord::Rollback
end
else
- cancel_lesson(canceler, message)
+ cancel_lesson(canceler, message, params[:canceled_by_admin])
if !save
response = self
raise ActiveRecord::Rollback
end
- msg = ChatMessage.create(canceler, nil, message, ChatMessage::CHANNEL_LESSON, nil, other, self, "Lesson Canceled")
+ if canceled_by_admin
+ msg = ChatMessage.create(student, nil, message, ChatMessage::CHANNEL_LESSON, nil, teacher, self, "Lesson Canceled")
+ msg = ChatMessage.create(teacher, nil, message, ChatMessage::CHANNEL_LESSON, nil, student, self, "Lesson Canceled")
+ else
+ msg = ChatMessage.create(canceler, nil, message, ChatMessage::CHANNEL_LESSON, nil, other, self, "Lesson Canceled")
+ end
+
+
Notification.send_lesson_message('canceled', self, false)
Notification.send_lesson_message('canceled', self, true)
UserMailer.student_lesson_canceled(self, message).deliver_now
@@ -1108,8 +1134,6 @@ module JamRuby
else
'TBD'
end
-
-
end
def timed_description
if is_test_drive?
@@ -1123,6 +1147,20 @@ module JamRuby
end
end
+ def cancel_by_admin
+ self.cancel({
+ canceler: nil,
+ canceled_by_admin: true,
+ message: 'Canceled by JamKazam administrator',
+ update_all: false
+ })
+ end
+
+ def intervened
+ self.intervened_at = Time.now
+ self.save
+ end
+
def display_type
if is_test_drive?
'TestDrive'
@@ -1137,15 +1175,8 @@ module JamRuby
counterer_id == user_id ? countered_at : sent_notices_at
end
- def days_no_response
- date = last_student_comm_date
- if date.nil?
- '?'
- else
- (Time.now - last_student_comm_date) / (60 * 60 * 24)
- end
-
-
+ def last_response_time
+ [countered_at, lesson_booking.sent_notices_at].find{|x|!x.nil?}
end
def stripe_description(lesson_booking)
diff --git a/ruby/lib/jam_ruby/models/teacher.rb b/ruby/lib/jam_ruby/models/teacher.rb
index 9061dc5a0..09515a4ba 100644
--- a/ruby/lib/jam_ruby/models/teacher.rb
+++ b/ruby/lib/jam_ruby/models/teacher.rb
@@ -64,7 +64,7 @@ module JamRuby
query = User.unscoped.joins(:teacher)
# only show teachers with ready for session set to true
- query = query.where('teachers.ready_for_session_at IS NOT NULL')
+ query = query.where('teachers.ready_for_session_at IS NOT NULL').where('teachers.is_searchable = TRUE')
# always force GuitarCenter users to see only their school's teachers, regardless of what they picked
if user && (user.is_guitar_center_student? || (params[:onlyMySchool] && params[:onlyMySchool] != 'false' && user.school_id))
@@ -222,6 +222,7 @@ module JamRuby
teacher.price_per_month_120_cents = params[:price_per_month_120_cents] if params.key?(:price_per_month_120_cents)
teacher.teaches_test_drive = params[:teaches_test_drive] if params.key?(:teaches_test_drive)
teacher.test_drives_per_week = params[:test_drives_per_week] if params.key?(:test_drives_per_week)
+ teacher.is_searchable = params[:is_searchable] if params.key?(:is_searchable)
teacher.test_drives_per_week = 10 if !params.key?(:test_drives_per_week) # default to 10 in absence of others
if params.key?(:school_id)
teacher.school_id = params[:school_id]
diff --git a/web/app/assets/javascripts/profile.js b/web/app/assets/javascripts/profile.js
index c83fc68e9..7c8b905b3 100644
--- a/web/app/assets/javascripts/profile.js
+++ b/web/app/assets/javascripts/profile.js
@@ -100,6 +100,7 @@
var $btnEdit = $screen.find('.edit-profile-btn');
var $btnTeacherProfileEdit = $screen.find('.edit-teacher-profile-btn');
var $btnTeacherProfileView = $screen.find('.view-teacher-profile-btn');
+ var $toggleTeacherSearchEnabled = $screen.find('.teacher-search-enabled')
var $btnAddFriend = $screen.find('#btn-add-friend');
var $btnFollowUser = $screen.find('#btn-follow-user');
var $btnMessageUser = $screen.find('#btn-message-user');
@@ -232,9 +233,11 @@
$btnTeacherProfileEdit.show();
if (isTeacher()) {
$btnTeacherProfileView.show();
+ $toggleTeacherSearchEnabled.show()
}
else {
$btnTeacherProfileView.hide();
+ $toggleTeacherSearchEnabled.hide()
}
$btnAddFriend.hide();
$btnFollowUser.hide();
@@ -332,6 +335,11 @@
window.ProfileActions.startProfileEdit('experience', true)
return false;
})
+ $toggleTeacherSearchEnabled.find('input').change(function(e) {
+ var $check = $(this)
+ rest.updateTeacher({id: user.teacher.id, is_searchable: $check.is(':checked')})
+ .fail(app.ajaxError);
+ })
}
function playSoundCloudFile(e) {
@@ -520,6 +528,7 @@
renderPerformanceSamples();
renderOnlinePresence();
renderInterests();
+ renderTeacherSearch();
}
}
@@ -565,6 +574,23 @@
}
}
+ function renderTeacherSearch()
+ {
+ if(isTeacher())
+ {
+ if(user.teacher.is_searchable )
+ {
+ $toggleTeacherSearchEnabled.find('input').attr('checked', 'checked')
+ }
+ else
+ {
+ $toggleTeacherSearchEnabled.find('input').removeAttr('checked')
+ }
+
+
+ }
+
+ }
function renderMusicalExperience() {
profileUtils.renderMusicalExperience(user, $screen, isCurrentUser())
}
diff --git a/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee b/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee
index a110ae8e0..0171cf344 100644
--- a/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee
+++ b/web/app/assets/javascripts/react-components/LessonBooking.js.jsx.coffee
@@ -401,11 +401,14 @@ UserStore = context.UserStore
otherCountered: () ->
@myself().id == @counterer().id
+ adminCanceled: () ->
+ this.state.booking?.canceled_by_admin?
+
studentCanceled: () ->
- @canceler().id == @student().id
+ @canceler()?.id == @student().id
selfCanceled: () ->
- @canceler().id == @myself().id
+ @canceler()?.id == @myself().id
studentMadeDefaultSlot: () ->
@student()?.id == @defaultSlot()?.proposer_id
@@ -513,7 +516,7 @@ UserStore = context.UserStore
else if @isCounter()
@counterer().id == @myself().id
else if @isCanceled()
- @canceler().id == @myself().id
+ @canceler()?.id == @myself().id
else if @isSuspended()
@studentViewing()
else
@@ -544,7 +547,9 @@ UserStore = context.UserStore
messageBlock: (selfWroteMessage, message) ->
- if selfWroteMessage
+ if typeof selfWroteMessage == 'string'
+ whoSaid = selfWroteMessage + ' said:'
+ else if selfWroteMessage
whoSaid = "You said:"
else
whoSaid = "Message from #{this.other().first_name}:"
@@ -660,12 +665,16 @@ UserStore = context.UserStore
if !photo_url?
photo_url = '/assets/shared/avatar_generic.png'
+ if user?
+ name = user.name
+ else
+ name = 'System'
`
- {user.name}
+ {name}
`
@@ -1049,7 +1058,9 @@ UserStore = context.UserStore
initial = @neverAccepted()
if initial
- if @studentViewing()
+ if @adminCanceled()
+ action = `
A JamKazam administrator canceled this lesson request.
`
+ else if @studentViewing()
if @studentCanceled()
action = `
You canceled this lesson request.
`
else
@@ -1062,7 +1073,7 @@ UserStore = context.UserStore
if @studentViewing()
- if @studentCanceled()
+ if @adminCanceled() || @studentCanceled()
blurb = `
We're sorry this scheduling attempt did not working out for you. Please search our community of instructors to find someone else who looks like a good fit for you, and submit a new lesson request
`
else
blurb = `
We're sorry this instructor has declined your request. Please search our community of instructors to find someone else who looks like a good fit for you, and submit a new lesson request