merged teacher search
This commit is contained in:
parent
50e2090f25
commit
641a553dcc
|
|
@ -1,40 +1,35 @@
|
|||
ActiveAdmin.register_page "Monthly Stats" do
|
||||
menu :parent => 'Reports'
|
||||
|
||||
distinct_users = MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', msuh.created_at)::date as month, count(distinct(user_id)) from music_sessions_user_history msuh group by month order by month desc;")
|
||||
total_session = MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', ms.created_at)::date as month, count(id) from music_sessions ms where started_at is not null group by month order by month desc;")
|
||||
total_jamtrack_sessions = MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(distinct(music_session_id)) from jam_track_sessions jts where session_type = 'session' group by month order by month desc;")
|
||||
total_webplayer_sessions = MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(id) from jam_track_sessions jts where session_type = 'browser' group by month order by month desc;")
|
||||
distinct_jamtrack_users = MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(distinct(user_id)) from jam_track_sessions jts group by month order by month desc;")
|
||||
|
||||
content :title => "Month Stats" do
|
||||
content :title => "Monthly Stats" do
|
||||
h2 "Distinct Users Playing in Sessions"
|
||||
table_for distinct_users do
|
||||
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', msuh.created_at)::date as month, count(distinct(user_id)) from music_sessions_user_history msuh group by month order by month desc;") do
|
||||
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
|
||||
column "Users", :count
|
||||
end
|
||||
endF
|
||||
|
||||
h2 "Music Sessions"
|
||||
table_for total_session do
|
||||
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', ms.created_at)::date as month, count(id) from music_sessions ms where started_at is not null group by month order by month desc;") do
|
||||
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
|
||||
column "Sessions", :count
|
||||
end
|
||||
|
||||
|
||||
h2 "Distinct Users Who Played with a JamTrack"
|
||||
table_for distinct_jamtrack_users do
|
||||
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(distinct(user_id)) from jam_track_sessions jts group by month order by month desc;") do
|
||||
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
|
||||
column "Users", :count
|
||||
end
|
||||
|
||||
h2 "Music Sessions with JamTracks Played"
|
||||
table_for total_jamtrack_sessions do
|
||||
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(distinct(music_session_id)) from jam_track_sessions jts where session_type = 'session' group by month order by month desc;") do
|
||||
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
|
||||
column "Sessions", :count
|
||||
end
|
||||
|
||||
h2 "JamTrack Web Player Sessions"
|
||||
table_for total_webplayer_sessions do
|
||||
table_for MusicSession.select([:month, :count]).find_by_sql("select date_trunc('month', jts.created_at)::date as month, count(id) from jam_track_sessions jts where session_type = 'browser' group by month order by month desc;") do
|
||||
column "Month", Proc.new { |row| Date.parse(row.month).strftime('%B %Y') }
|
||||
column "Sessions", :count
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,110 +33,201 @@ module JamRuby
|
|||
|
||||
default_scope { includes(:genres) }
|
||||
|
||||
class << self
|
||||
def save_teacher(user, params)
|
||||
teacher = build_teacher(user, params)
|
||||
teacher.save
|
||||
teacher
|
||||
|
||||
def self.index(user, params = {})
|
||||
limit = params[:per_page]
|
||||
limit ||= 20
|
||||
limit = limit.to_i
|
||||
|
||||
query = User.joins(:teacher)
|
||||
|
||||
instruments = params[:instruments]
|
||||
if instruments && !instruments.blank? && instruments.length > 0
|
||||
query = query.joins("inner JOIN teachers_instruments AS tinst ON tinst.teacher_id = teachers.id")
|
||||
.where("tinst.instrument_id IN (?)", instruments)
|
||||
end
|
||||
|
||||
def build_teacher(user, params)
|
||||
# ensure person creating this Teacher is a Musician
|
||||
unless user && user.musician?
|
||||
raise JamPermissionError, "must be a musician"
|
||||
end
|
||||
|
||||
teacher = user.teacher
|
||||
teacher ||= user.build_teacher()
|
||||
teacher.user = user
|
||||
|
||||
teacher.website = params[:website] if params.key?(:website)
|
||||
teacher.biography = params[:biography] if params.key?(:biography)
|
||||
teacher.introductory_video = params[:introductory_video] if params.key?(:introductory_video)
|
||||
|
||||
teacher.introductory_video = params[:introductory_video] if params.key?(:introductory_video)
|
||||
teacher.years_teaching = params[:years_teaching] if params.key?(:years_teaching)
|
||||
teacher.years_playing = params[:years_playing] if params.key?(:years_playing)
|
||||
teacher.teaches_age_lower = params[:teaches_age_lower] if params.key?(:teaches_age_lower)
|
||||
teacher.teaches_age_upper = params[:teaches_age_upper] if params.key?(:teaches_age_upper)
|
||||
teacher.website = params[:website] if params.key?(:website)
|
||||
teacher.biography = params[:biography] if params.key?(:biography)
|
||||
teacher.teaches_beginner = params[:teaches_beginner] if params.key?(:teaches_beginner)
|
||||
teacher.teaches_intermediate = params[:teaches_intermediate] if params.key?(:teaches_intermediate)
|
||||
teacher.teaches_advanced = params[:teaches_advanced] if params.key?(:teaches_advanced)
|
||||
teacher.prices_per_lesson = params[:prices_per_lesson] if params.key?(:prices_per_lesson)
|
||||
teacher.prices_per_month = params[:prices_per_month] if params.key?(:prices_per_month)
|
||||
teacher.lesson_duration_30 = params[:lesson_duration_30] if params.key?(:lesson_duration_30)
|
||||
teacher.lesson_duration_45 = params[:lesson_duration_45] if params.key?(:lesson_duration_45)
|
||||
teacher.lesson_duration_60 = params[:lesson_duration_60] if params.key?(:lesson_duration_60)
|
||||
teacher.lesson_duration_90 = params[:lesson_duration_90] if params.key?(:lesson_duration_90)
|
||||
teacher.lesson_duration_120 = params[:lesson_duration_120] if params.key?(:lesson_duration_120)
|
||||
teacher.price_per_lesson_30_cents = params[:price_per_lesson_30_cents] if params.key?(:price_per_lesson_30_cents)
|
||||
teacher.price_per_lesson_45_cents = params[:price_per_lesson_45_cents] if params.key?(:price_per_lesson_45_cents)
|
||||
teacher.price_per_lesson_60_cents = params[:price_per_lesson_60_cents] if params.key?(:price_per_lesson_60_cents)
|
||||
teacher.price_per_lesson_90_cents = params[:price_per_lesson_90_cents] if params.key?(:price_per_lesson_90_cents)
|
||||
teacher.price_per_lesson_120_cents = params[:price_per_lesson_120_cents] if params.key?(:price_per_lesson_120_cents)
|
||||
teacher.price_per_month_30_cents = params[:price_per_month_30_cents] if params.key?(:price_per_month_30_cents)
|
||||
teacher.price_per_month_45_cents = params[:price_per_month_45_cents] if params.key?(:price_per_month_45_cents)
|
||||
teacher.price_per_month_60_cents = params[:price_per_month_60_cents] if params.key?(:price_per_month_60_cents)
|
||||
teacher.price_per_month_90_cents = params[:price_per_month_90_cents] if params.key?(:price_per_month_90_cents)
|
||||
teacher.price_per_month_120_cents = params[:price_per_month_120_cents] if params.key?(:price_per_month_120_cents)
|
||||
|
||||
# Many-to-many relations:
|
||||
if params.key?(:genres)
|
||||
genres = params[:genres]
|
||||
genres = [] if genres.nil?
|
||||
teacher.genres = genres.collect{|genre_id| Genre.find(genre_id)}
|
||||
end
|
||||
if params.key?(:instruments)
|
||||
instruments = params[:instruments]
|
||||
instruments = [] if instruments.nil?
|
||||
teacher.instruments = instruments.collect{|instrument_id| Instrument.find(instrument_id)}
|
||||
end
|
||||
if params.key?(:subjects)
|
||||
subjects = params[:subjects]
|
||||
subjects = [] if subjects.nil?
|
||||
teacher.subjects = subjects.collect{|subject_id| Subject.find(subject_id)}
|
||||
end
|
||||
if params.key?(:languages)
|
||||
languages = params[:languages]
|
||||
languages = [] if languages.nil?
|
||||
teacher.languages = languages.collect{|language_id| Language.find(language_id)}
|
||||
end
|
||||
|
||||
# Experience:
|
||||
[:teaching, :education, :award].each do |experience_type|
|
||||
key = "experiences_#{experience_type}".to_sym
|
||||
if params.key?(key)
|
||||
list = params[key]
|
||||
list = [] if list.nil?
|
||||
experiences = list.collect do |exp|
|
||||
TeacherExperience.new(
|
||||
name: exp[:name],
|
||||
experience_type: experience_type,
|
||||
organization: exp[:organization],
|
||||
start_year: exp[:start_year],
|
||||
end_year: exp[:end_year]
|
||||
)
|
||||
end # collect
|
||||
|
||||
# we blindly destroy/recreate on every resubmit
|
||||
previous = teacher.send("#{key.to_s}")
|
||||
previous.destroy_all
|
||||
|
||||
# Dynamically call the appropriate method (just setting the
|
||||
# value doesn't result in the behavior we need)
|
||||
teacher.send("#{key.to_s}=", experiences)
|
||||
end # if
|
||||
end # do
|
||||
|
||||
# How to validate:
|
||||
teacher.validate_introduction = !!params[:validate_introduction]
|
||||
teacher.validate_basics = !!params[:validate_basics]
|
||||
teacher.validate_pricing = !!params[:validate_pricing]
|
||||
|
||||
teacher
|
||||
subjects = params[:subjects]
|
||||
if subjects && !subjects.blank? && subjects.length > 0
|
||||
query = query.joins("inner JOIN teachers_subjects AS tsubjs ON tsubjs.teacher_id = teachers.id")
|
||||
.where('tsubjs.subject_id IN (?)', subjects)
|
||||
end
|
||||
|
||||
genres = params[:genres]
|
||||
if genres && !genres.blank? && genres.length > 0
|
||||
query = query.joins("inner JOIN teachers_genres AS tgenres ON tgenres.teacher_id = teachers.id")
|
||||
.where('tgenres.genre_id IN (?)', genres)
|
||||
end
|
||||
|
||||
country = params[:country]
|
||||
if country && country.length > 0
|
||||
query = query.where(country: country)
|
||||
end
|
||||
|
||||
region = params[:region]
|
||||
if region && region.length > 0
|
||||
query = query.where(state: region)
|
||||
end
|
||||
|
||||
languages = params[:languages]
|
||||
if languages && !languages.blank? && languages.length > 0
|
||||
query= query.joins("inner JOIN teachers_languages AS tlang ON tlang.teacher_id = teachers.id")
|
||||
.where('tlang.language_id IN (?)', languages)
|
||||
end
|
||||
|
||||
years_teaching = params[:years_teaching].to_i
|
||||
if years_teaching && years_teaching > 0
|
||||
query = query.where('years_teaching >= ?', years_teaching)
|
||||
end
|
||||
|
||||
teaches_beginner = params[:teaches_beginner]
|
||||
teaches_intermediate = params[:teaches_intermediate]
|
||||
teaches_advanced = params[:teaches_advanced]
|
||||
|
||||
if teaches_beginner || teaches_intermediate || teaches_advanced
|
||||
|
||||
clause = ''
|
||||
|
||||
if teaches_beginner
|
||||
clause << 'teaches_beginner = true'
|
||||
end
|
||||
if teaches_intermediate
|
||||
if clause.length > 0
|
||||
clause << ' OR '
|
||||
end
|
||||
clause << 'teaches_intermediate = true'
|
||||
end
|
||||
if teaches_advanced
|
||||
if clause.length > 0
|
||||
clause << ' OR '
|
||||
end
|
||||
clause << 'teaches_advanced = true'
|
||||
end
|
||||
query = query.where(clause)
|
||||
end
|
||||
|
||||
student_age = params[:student_age].to_i
|
||||
if student_age && student_age > 0
|
||||
query = query.where("teaches_age_lower <= ? AND (CASE WHEN teaches_age_upper = 0 THEN true ELSE teaches_age_upper >= ? END)", student_age, student_age)
|
||||
end
|
||||
|
||||
current_page = params[:page].nil? ? 1 : params[:page].to_i
|
||||
next_page = current_page + 1
|
||||
|
||||
# will_paginate gem
|
||||
query = query.paginate(:page => current_page, :per_page => limit)
|
||||
|
||||
if query.length == 0 # no more results
|
||||
{ query: query, next_page: nil}
|
||||
elsif query.length < limit # no more results
|
||||
{ query: query, next_page: nil}
|
||||
else
|
||||
{ query: query, next_page: next_page }
|
||||
end
|
||||
end
|
||||
|
||||
def self.save_teacher(user, params)
|
||||
teacher = build_teacher(user, params)
|
||||
teacher.save
|
||||
teacher
|
||||
end
|
||||
|
||||
def self.build_teacher(user, params)
|
||||
# ensure person creating this Teacher is a Musician
|
||||
unless user && user.musician?
|
||||
raise JamPermissionError, "must be a musician"
|
||||
end
|
||||
|
||||
teacher = user.teacher
|
||||
teacher ||= user.build_teacher()
|
||||
teacher.user = user
|
||||
|
||||
teacher.website = params[:website] if params.key?(:website)
|
||||
teacher.biography = params[:biography] if params.key?(:biography)
|
||||
teacher.introductory_video = params[:introductory_video] if params.key?(:introductory_video)
|
||||
|
||||
teacher.introductory_video = params[:introductory_video] if params.key?(:introductory_video)
|
||||
teacher.years_teaching = params[:years_teaching] if params.key?(:years_teaching)
|
||||
teacher.years_playing = params[:years_playing] if params.key?(:years_playing)
|
||||
teacher.teaches_age_lower = params[:teaches_age_lower] if params.key?(:teaches_age_lower)
|
||||
teacher.teaches_age_upper = params[:teaches_age_upper] if params.key?(:teaches_age_upper)
|
||||
teacher.website = params[:website] if params.key?(:website)
|
||||
teacher.biography = params[:biography] if params.key?(:biography)
|
||||
teacher.teaches_beginner = params[:teaches_beginner] if params.key?(:teaches_beginner)
|
||||
teacher.teaches_intermediate = params[:teaches_intermediate] if params.key?(:teaches_intermediate)
|
||||
teacher.teaches_advanced = params[:teaches_advanced] if params.key?(:teaches_advanced)
|
||||
teacher.prices_per_lesson = params[:prices_per_lesson] if params.key?(:prices_per_lesson)
|
||||
teacher.prices_per_month = params[:prices_per_month] if params.key?(:prices_per_month)
|
||||
teacher.lesson_duration_30 = params[:lesson_duration_30] if params.key?(:lesson_duration_30)
|
||||
teacher.lesson_duration_45 = params[:lesson_duration_45] if params.key?(:lesson_duration_45)
|
||||
teacher.lesson_duration_60 = params[:lesson_duration_60] if params.key?(:lesson_duration_60)
|
||||
teacher.lesson_duration_90 = params[:lesson_duration_90] if params.key?(:lesson_duration_90)
|
||||
teacher.lesson_duration_120 = params[:lesson_duration_120] if params.key?(:lesson_duration_120)
|
||||
teacher.price_per_lesson_30_cents = params[:price_per_lesson_30_cents] if params.key?(:price_per_lesson_30_cents)
|
||||
teacher.price_per_lesson_45_cents = params[:price_per_lesson_45_cents] if params.key?(:price_per_lesson_45_cents)
|
||||
teacher.price_per_lesson_60_cents = params[:price_per_lesson_60_cents] if params.key?(:price_per_lesson_60_cents)
|
||||
teacher.price_per_lesson_90_cents = params[:price_per_lesson_90_cents] if params.key?(:price_per_lesson_90_cents)
|
||||
teacher.price_per_lesson_120_cents = params[:price_per_lesson_120_cents] if params.key?(:price_per_lesson_120_cents)
|
||||
teacher.price_per_month_30_cents = params[:price_per_month_30_cents] if params.key?(:price_per_month_30_cents)
|
||||
teacher.price_per_month_45_cents = params[:price_per_month_45_cents] if params.key?(:price_per_month_45_cents)
|
||||
teacher.price_per_month_60_cents = params[:price_per_month_60_cents] if params.key?(:price_per_month_60_cents)
|
||||
teacher.price_per_month_90_cents = params[:price_per_month_90_cents] if params.key?(:price_per_month_90_cents)
|
||||
teacher.price_per_month_120_cents = params[:price_per_month_120_cents] if params.key?(:price_per_month_120_cents)
|
||||
|
||||
# Many-to-many relations:
|
||||
if params.key?(:genres)
|
||||
genres = params[:genres]
|
||||
genres = [] if genres.nil?
|
||||
teacher.genres = genres.collect{|genre_id| Genre.find(genre_id)}
|
||||
end
|
||||
if params.key?(:instruments)
|
||||
instruments = params[:instruments]
|
||||
instruments = [] if instruments.nil?
|
||||
teacher.instruments = instruments.collect{|instrument_id| Instrument.find(instrument_id)}
|
||||
end
|
||||
if params.key?(:subjects)
|
||||
subjects = params[:subjects]
|
||||
subjects = [] if subjects.nil?
|
||||
teacher.subjects = subjects.collect{|subject_id| Subject.find(subject_id)}
|
||||
end
|
||||
if params.key?(:languages)
|
||||
languages = params[:languages]
|
||||
languages = [] if languages.nil?
|
||||
teacher.languages = languages.collect{|language_id| Language.find(language_id)}
|
||||
end
|
||||
|
||||
# Experience:
|
||||
[:teaching, :education, :award].each do |experience_type|
|
||||
key = "experiences_#{experience_type}".to_sym
|
||||
if params.key?(key)
|
||||
list = params[key]
|
||||
list = [] if list.nil?
|
||||
experiences = list.collect do |exp|
|
||||
TeacherExperience.new(
|
||||
name: exp[:name],
|
||||
experience_type: experience_type,
|
||||
organization: exp[:organization],
|
||||
start_year: exp[:start_year],
|
||||
end_year: exp[:end_year]
|
||||
)
|
||||
end # collect
|
||||
|
||||
# we blindly destroy/recreate on every resubmit
|
||||
previous = teacher.send("#{key.to_s}")
|
||||
previous.destroy_all
|
||||
|
||||
# Dynamically call the appropriate method (just setting the
|
||||
# value doesn't result in the behavior we need)
|
||||
teacher.send("#{key.to_s}=", experiences)
|
||||
end # if
|
||||
end # do
|
||||
|
||||
# How to validate:
|
||||
teacher.validate_introduction = !!params[:validate_introduction]
|
||||
teacher.validate_basics = !!params[:validate_basics]
|
||||
teacher.validate_pricing = !!params[:validate_pricing]
|
||||
|
||||
teacher
|
||||
end
|
||||
|
||||
def offer_pricing
|
||||
|
|
|
|||
|
|
@ -94,6 +94,10 @@ FactoryGirl.define do
|
|||
end
|
||||
end
|
||||
|
||||
factory :teacher, :class => JamRuby::Teacher do
|
||||
association :user, factory: :user
|
||||
end
|
||||
|
||||
factory :musician_instrument, :class => JamRuby::MusicianInstrument do
|
||||
instrument { JamRuby::Instrument.find('electric guitar') }
|
||||
proficiency_level 1
|
||||
|
|
|
|||
|
|
@ -12,12 +12,177 @@ describe Teacher do
|
|||
let(:instrument1) { FactoryGirl.create(:instrument, :description => 'a great instrument')}
|
||||
let(:instrument2) { FactoryGirl.create(:instrument, :description => 'an ok instrument')}
|
||||
|
||||
describe "index" do
|
||||
it "no params" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil)[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "instruments" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {instruments: ['acoustic guitar']})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.instruments << Instrument.find('acoustic guitar')
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {instruments: ['acoustic guitar']})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teacher.instruments << Instrument.find('electric guitar')
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {instruments: ['acoustic guitar']})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "subjects" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {subjects: ['music-theory']})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.subjects << Subject.find('music-theory')
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {subjects: ['music-theory']})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "genres" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {genres: ['ambient']})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.genres << Genre.find('ambient')
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {genres: ['ambient']})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
|
||||
it "languages" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {languages: ['EN']})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.languages << Language.find('EN')
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {languages: ['EN']})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "country" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {country: 'DO'})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.user.country = 'DO'
|
||||
teacher.user.save!
|
||||
teachers = Teacher.index(nil, {country: 'DO'})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "region" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {region: 'HE'})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.user.state = 'HE'
|
||||
teacher.user.save!
|
||||
teachers = Teacher.index(nil, {region: 'HE'})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "years_teaching" do
|
||||
teacher = FactoryGirl.create(:teacher, years_teaching: 5)
|
||||
teachers = Teacher.index(nil, {years_teaching: 10})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teachers = Teacher.index(nil, {years_teaching: 2})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "teaches beginner/intermediate/advanced" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {teaches_beginner: true})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.teaches_beginner = true
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {teaches_beginner: true})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teachers = Teacher.index(nil, {teaches_intermediate: true})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teachers = Teacher.index(nil, {teaches_beginner: true, teaches_intermediate: true})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teachers = Teacher.index(nil, {teaches_beginner: true, teaches_intermediate: true, teaches_advanced: true})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
end
|
||||
|
||||
it "student_age" do
|
||||
teacher = FactoryGirl.create(:teacher)
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 1
|
||||
|
||||
teacher.teaches_age_lower = 5
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teacher.teaches_age_lower = 6
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 0
|
||||
|
||||
teacher.teaches_age_lower = 4
|
||||
teacher.teaches_age_upper = 6
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teacher.teaches_age_lower = 0
|
||||
teacher.teaches_age_upper = 5
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teacher.teaches_age_lower = 0
|
||||
teacher.teaches_age_upper = 6
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 1
|
||||
teachers[0].should eq(teacher.user)
|
||||
|
||||
teacher.teaches_age_lower = 0
|
||||
teacher.teaches_age_upper = 4
|
||||
teacher.save!
|
||||
teachers = Teacher.index(nil, {student_age: 5})[:query]
|
||||
teachers.length.should eq 0
|
||||
end
|
||||
end
|
||||
|
||||
BIO = "Once a man learned a guitar."
|
||||
GOOD_YOUTUBE_URL = "http://youtube.com/watch?v=1234567890"
|
||||
describe "can create" do
|
||||
it "a simple teacher" do
|
||||
teacher = Teacher.new
|
||||
teacher.user = user;
|
||||
teacher.user = user
|
||||
teacher.biography = BIO
|
||||
teacher.introductory_video = GOOD_YOUTUBE_URL
|
||||
teacher.save.should be_true
|
||||
|
|
|
|||
|
|
@ -95,13 +95,13 @@ end
|
|||
|
||||
config.before(:suite) do
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
|
||||
DatabaseCleaner.clean_with(:deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments languages subjects genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] })
|
||||
end
|
||||
|
||||
config.around(:each) do |example|
|
||||
# set no_transaction: true as metadata on your test to use deletion strategy instead
|
||||
if example.metadata[:no_transaction]
|
||||
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
|
||||
DatabaseCleaner.strategy = :deletion, {pre_count: true, reset_ids:false, :except => %w[gift_card_types instruments languages subjects genres icecast_server_groups jamcompany jamisp geoipblocks geoipisp geoiplocations cities regions countries generic_state spatial_ref_sys] }
|
||||
else
|
||||
DatabaseCleaner.strategy = :transaction
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1974,6 +1974,15 @@
|
|||
});
|
||||
}
|
||||
|
||||
function searchTeachers(query) {
|
||||
return $.ajax({
|
||||
type: "GET",
|
||||
url: "/api/teachers?" + $.param(query),
|
||||
dataType: "json",
|
||||
contentType: 'application/json'
|
||||
});
|
||||
}
|
||||
|
||||
function getMusicianSearchFilter(query) {
|
||||
var qarg = query === undefined ? '' : query;
|
||||
return $.get("/api/search/musicians.json?"+qarg);
|
||||
|
|
@ -2286,6 +2295,7 @@
|
|||
this.updateBillingInfo = updateBillingInfo;
|
||||
this.placeOrder = placeOrder;
|
||||
this.searchMusicians = searchMusicians;
|
||||
this.searchTeachers = searchTeachers;
|
||||
this.resendBandInvitation = resendBandInvitation;
|
||||
this.getMount = getMount;
|
||||
this.createSourceChange = createSourceChange;
|
||||
|
|
|
|||
|
|
@ -18,6 +18,9 @@
|
|||
//= require ./react-components/stores/MixerStore
|
||||
//= require ./react-components/stores/ConfigureTracksStore
|
||||
//= require ./react-components/stores/JamTrackStore
|
||||
//= require ./react-components/stores/LocationStore
|
||||
//= require ./react-components/stores/TeacherSearchStore
|
||||
//= require ./react-components/stores/TeacherSearchResultsStore
|
||||
//= require ./react-components/stores/SessionNotificationStore
|
||||
//= require ./react-components/stores/MediaPlaybackStore
|
||||
//= require ./react-components/stores/BrowserMediaPlaybackStore
|
||||
|
|
|
|||
|
|
@ -4,11 +4,15 @@ logger = context.JK.logger
|
|||
|
||||
@AgeRangeList = React.createClass({
|
||||
ages: [0, 1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,25,30,35,40,45,50,55,60,65,70,75,80,85,90,95,100]
|
||||
agesJsx: []
|
||||
propTypes: {
|
||||
onItemChanged: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
componentDidMount: () ->
|
||||
componentWillMount: () ->
|
||||
@agesJsx = []
|
||||
for age in @ages
|
||||
@agesJsx.push(`<option value={age}>{age == 0 ? 'Any' : age}</option>`)
|
||||
@agesJsx.push(`<option key={age} value={age}>{age == 0 ? 'Any' : age}</option>`)
|
||||
|
||||
getInitialState: () ->
|
||||
{selectedAge:@props.selectedAge}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ logger = context.JK.logger
|
|||
|
||||
mixins: [Reflux.listenTo(@GenreStore,"onGenresChanged")]
|
||||
|
||||
propTypes: {
|
||||
onItemChanged: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
getDefaultProps: () ->
|
||||
selectedGenres: []
|
||||
|
||||
getInitialState:() ->
|
||||
{genres: []}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ logger = context.JK.logger
|
|||
|
||||
mixins: [Reflux.listenTo(@InstrumentStore,"onInstrumentsChanged")]
|
||||
|
||||
propTypes: {
|
||||
onItemChanged: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
getDefaultProps: () ->
|
||||
selectedInstruments: []
|
||||
|
||||
getInitialState: () ->
|
||||
{instruments: []}
|
||||
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@ logger = context.JK.logger
|
|||
|
||||
mixins: [Reflux.listenTo(@LanguageStore,"onLanguagesChanged")]
|
||||
|
||||
propTypes: {
|
||||
onItemChanged: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
getDefaultProps: () ->
|
||||
selectedLanguages: []
|
||||
|
||||
getInitialState: () ->
|
||||
{languages: []}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,62 @@
|
|||
context = window
|
||||
rest = window.JK.Rest()
|
||||
logger = context.JK.logger
|
||||
|
||||
@SelectLocation = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@LocationStore,"onLocationsChanged")]
|
||||
|
||||
propTypes: {
|
||||
onItemChanged: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
getInitialState:() ->
|
||||
{selectedCountry: null, countries:{US: {name: 'United States', region: null}}}
|
||||
|
||||
onLocationsChanged: (countries) ->
|
||||
@setState({countries: countries})
|
||||
|
||||
onCountryChanged: (e) ->
|
||||
val = $(e.target).val()
|
||||
@changed(val, null)
|
||||
@setState({selectedCountry: val, selectedRegion: null })
|
||||
|
||||
if val?
|
||||
LocationActions.selectCountry(val)
|
||||
|
||||
onRegionChanged: (e) ->
|
||||
val = $(e.target).val()
|
||||
@changed(@state.selectedCountry, val)
|
||||
@setState({selectedRegion: val })
|
||||
|
||||
changed: (country, region) ->
|
||||
if country == ''
|
||||
country = null
|
||||
|
||||
if region == ''
|
||||
region = null
|
||||
|
||||
@props.onItemChanged(country, region)
|
||||
|
||||
render: () ->
|
||||
countries = [`<option value="">Any</option>`]
|
||||
for countryId, countryInfo of @state.countries
|
||||
countries.push(`<option value={countryId}>{countryInfo.name}</option>`)
|
||||
|
||||
country = @state.countries[@state.selectedCountry]
|
||||
|
||||
regions = [`<option value="">Any</option>`]
|
||||
|
||||
|
||||
if country? && country.regions
|
||||
for region in country.regions
|
||||
regions.push(`<option value={region.id}>{region.name}</option>`)
|
||||
|
||||
disabled = regions.length == 1
|
||||
`<div className="SelectLocation">
|
||||
<h3>Country:</h3>
|
||||
<select name="countries" onChange={this.onCountryChanged} value={this.state.selectedCountry}>{countries}</select>
|
||||
<h3>State/Region:</h3>
|
||||
<select name="regions" disabled={disabled} onChange={this.onRegionChanged} value={this.state.selectedRegion}>{regions}</select>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -6,6 +6,13 @@ logger = context.JK.logger
|
|||
|
||||
mixins: [Reflux.listenTo(@SubjectStore,"onSubjectsChanged")]
|
||||
|
||||
propTypes: {
|
||||
onItemChanged: React.PropTypes.func.isRequired
|
||||
}
|
||||
|
||||
getDefaultProps: () ->
|
||||
selectedSubjects: []
|
||||
|
||||
getInitialState:() ->
|
||||
{subjects: []}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ logger = context.JK.logger
|
|||
errors = []
|
||||
if this.state.errors?
|
||||
for error in this.state.errors
|
||||
errors.push(error)
|
||||
errors.push(`<span>{error}</span>`)
|
||||
|
||||
`<div className="TeacherExperienceEditableList react-component">
|
||||
<form className="teacher-experience-teaching-form">
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ LanguageStore = context.LanguageStore
|
|||
GenreStore = context.GenreStore
|
||||
UserStore = context.UserStore
|
||||
AppStore = context.AppStore
|
||||
ProfileActions = context.ProfileActions
|
||||
|
||||
profileUtils = context.JK.ProfileUtils
|
||||
|
||||
|
|
@ -44,7 +45,7 @@ proficiencyDescriptionMap = {
|
|||
TILES: ['about', 'experience', 'samples', 'ratings', 'prices']
|
||||
|
||||
onAppInit: (@app) ->
|
||||
@app.bindScreen('profile/teacher', {beforeShow: @beforeShow, afterShow: @afterShow})
|
||||
@app.bindScreen('profile/teacher', {beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide})
|
||||
|
||||
onSubjectsChanged: () ->
|
||||
@setState({subjects: true})
|
||||
|
|
@ -83,15 +84,21 @@ proficiencyDescriptionMap = {
|
|||
)
|
||||
|
||||
|
||||
beforeShow: (e) ->
|
||||
|
||||
userDetailDone: (response) ->
|
||||
if response.id == @state.userId
|
||||
@setState({user: response, isSelf: response.id == context.JK.currentUserId})
|
||||
else
|
||||
logger.debug("ignoring userDetailDone", response.id, @state.userId)
|
||||
|
||||
beforeHide: (e) ->
|
||||
logger.debug("TeacherProfile: beforeHide")
|
||||
ProfileActions.viewTeacherProfileDone()
|
||||
|
||||
beforeShow: (e) ->
|
||||
logger.debug("TeacherProfile: beforeShow")
|
||||
|
||||
afterShow: (e) ->
|
||||
logger.debug("TeacherProfile: afterShow")
|
||||
@setState({userId: e.id, user: null})
|
||||
rest.getUserDetail({
|
||||
id: e.id,
|
||||
|
|
@ -619,6 +626,10 @@ proficiencyDescriptionMap = {
|
|||
|
||||
return `<div key={i} className="profile-tile"><a className={classes} onClick={this.selectionMade.bind(this, tile)}>{tile}</a></div>`
|
||||
|
||||
onCustomBack: (customBack, e) ->
|
||||
e.preventDefault()
|
||||
context.location = customBack
|
||||
|
||||
render: () ->
|
||||
if @state.user?
|
||||
avatar = context.JK.resolveAvatarUrl(@state.user.photo_url);
|
||||
|
|
@ -634,12 +645,10 @@ proficiencyDescriptionMap = {
|
|||
{noTeacherProfile}
|
||||
</div>`
|
||||
|
||||
editButton = `<a href="/client#/account/profile" className="button-orange edit-profile-btn hidden">EDIT PROFILE</a>`
|
||||
actionButtons = `<div className="right hidden">
|
||||
<a id="btn-add-friend" className="button-orange">ADD FRIEND</a>
|
||||
<a id="btn-follow-user" className="button-orange">FOLLOW</a>
|
||||
<a id="btn-message-user" className="button-orange">MESSAGE</a>
|
||||
</div>`
|
||||
if ProfileStore.customBack
|
||||
actionButtons = `<div className="right profileNavActions">
|
||||
<a className="button-orange" onClick={this.onCustomBack.bind(this, ProfileStore.customBack)}>{ProfileStore.customBackDisplay}</a>
|
||||
</div>`
|
||||
|
||||
profileSelections = []
|
||||
for tile, i in @TILES
|
||||
|
|
@ -653,7 +662,6 @@ proficiencyDescriptionMap = {
|
|||
|
||||
<div className="user-header">
|
||||
<h2 id="username"></h2>
|
||||
{editButton}
|
||||
</div>
|
||||
|
||||
{actionButtons}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,137 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
TeacherSearchActions = @TeacherSearchActions
|
||||
LocationActions = @LocationActions
|
||||
|
||||
@TeacherSearchOptionsScreen = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@UserStore, "onUserChanged"),
|
||||
Reflux.listenTo(@TeacherSearchStore, "onTeacherSearchChanged")]
|
||||
|
||||
LIMIT: 20
|
||||
|
||||
getInitialState: () ->
|
||||
{options: {}}
|
||||
|
||||
onAppInit: (@app) ->
|
||||
@app.bindScreen('jamclass/searchOptions', {beforeShow: @beforeShow, afterShow: @afterShow})
|
||||
|
||||
beforeShow: (e) ->
|
||||
LocationActions.load()
|
||||
|
||||
afterShow: (e) ->
|
||||
|
||||
onUserChanged: (@user) ->
|
||||
|
||||
onTeacherSearchChanged: (options) ->
|
||||
@setState({options: options})
|
||||
|
||||
handleListChange: (listName, selectedObjects)->
|
||||
logger.debug("handleListChange:", listName, selectedObjects)
|
||||
options = @state.options
|
||||
options[listName] = selectedObjects
|
||||
@setState({options: options})
|
||||
|
||||
handleLocationChange: (country, region) ->
|
||||
logger.debug("handleLocationChange #{country} #{region}")
|
||||
options = @state.options
|
||||
options['location'] = {country:country, region:region}
|
||||
@setState({options: options})
|
||||
|
||||
onCancel: (e) ->
|
||||
e.preventDefault()
|
||||
window.history.go(-1)
|
||||
|
||||
onSearch: (e) ->
|
||||
e.preventDefault()
|
||||
TeacherSearchActions.search({searchOptions: @state.options})
|
||||
|
||||
|
||||
levelChanged: (e) ->
|
||||
purpose = $(e.target).attr('data-purpose')
|
||||
checked = $(e.target).is(":checked")
|
||||
logger.debug("levelChanged:", purpose, checked)
|
||||
options = @state.options
|
||||
options[purpose] = checked
|
||||
@setState({options: options})
|
||||
|
||||
handleYearsTeaching: (e) ->
|
||||
yearsTeaching = $(e.target).val()
|
||||
|
||||
logger.debug("years teaching:", yearsTeaching)
|
||||
options = @state.options
|
||||
options['years-teaching'] = yearsTeaching
|
||||
@setState({options: options})
|
||||
|
||||
render: () ->
|
||||
selectedAge = null
|
||||
yearsTeaching = []
|
||||
for yr in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 15, 20, 25, 30, 40, 45, 50]
|
||||
yearsTeaching.push(`<option value={yr}>{yr}</option>`)
|
||||
`<div className="content-body-scroller">
|
||||
<div className="screen-content">
|
||||
<h2>search teachers</h2>
|
||||
|
||||
<div className="search-criteria">
|
||||
<h3>Instruments Taught:</h3>
|
||||
<InstrumentCheckBoxList onItemChanged={this.handleListChange} selectedInstruments={this.state.options.instruments}/>
|
||||
</div>
|
||||
|
||||
<div className="search-criteria">
|
||||
<h3>Music Subjects Taught:</h3>
|
||||
<SubjectCheckBoxList onItemChanged={this.handleListChange} selectedSubjects={this.state.options.subjects}/>
|
||||
</div>
|
||||
|
||||
<div className="search-criteria">
|
||||
<h3>Genres Taught:</h3>
|
||||
<GenreCheckBoxList onItemChanged={this.handleListChange} selectedGenres={this.state.options.genres}/>
|
||||
</div>
|
||||
|
||||
<div className="search-criteria">
|
||||
<h3>Languages Spoken:</h3>
|
||||
<LanguageCheckBoxList onItemChanged={this.handleListChange} selectedLanguages={this.state.options.languages}/>
|
||||
</div>
|
||||
|
||||
<br className="clearall"/>
|
||||
|
||||
<div className="search-criteria">
|
||||
<div className="student-levels-taught">
|
||||
<h3>Student Levels Taught:</h3>
|
||||
|
||||
<div className="teaching-level beginner-level">
|
||||
<input name="beginner-level" type="checkbox" data-purpose="teaches_beginner" onChange={this.levelChanged} checked={this.state.options.teaches_beginner}></input>
|
||||
<label for="beginner-level">Beginner</label>
|
||||
</div>
|
||||
<div className="teaching-level intermediate-level">
|
||||
<input name="intermediate-level" type="checkbox" data-purpose="teaches_intermediate" onChange={this.levelChanged} checked={this.state.options.teaches_intermediate}></input>
|
||||
<label for="intermediate-level">Intermediate</label>
|
||||
</div>
|
||||
<div className="teaching-level advanced-level">
|
||||
<input name="advanced-level" type="checkbox" data-purpose="teaches_advanced" onChange={this.levelChanged} checked={this.state.options.teaches_advanced}></input>
|
||||
<label for="advanced-level">Advanced</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="search-criteria">
|
||||
<h3>Student Ages Taught:</h3>
|
||||
<AgeRangeList selectedAge={selectedAge} objectName="ages-taught" onItemChanged={this.handleListChange} selectedAge={this.state.options['ages-taught']} />
|
||||
|
||||
|
||||
<h3 className="years-teaching-header">Years Teaching Experience:</h3>
|
||||
<select name="years-teaching" onChange={this.handleYearsTeaching} value={this.state.options['years-teaching']}>
|
||||
<option value=''>Any</option>
|
||||
{yearsTeaching}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="search-criteria">
|
||||
<SelectLocation onItemChanged={this.handleLocationChange}/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="actions">
|
||||
<a className="button-grey" onClick={this.onCancel}>CANCEL</a>
|
||||
<a className="button-orange" onClick={this.onSearch}>SEARCH</a>
|
||||
</div>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
context = window
|
||||
rest = context.JK.Rest()
|
||||
TeacherSearchStore = @TeacherSearchStore
|
||||
TeacherSearchActions = @TeacherSearchActions
|
||||
TeacherSearchResultsActions = @TeacherSearchResultsActions
|
||||
LocationActions = @LocationActions
|
||||
InstrumentStore = @InstrumentStore
|
||||
SubjectStore = @SubjectStore
|
||||
GenreStore = @GenreStore
|
||||
LanguageStore = @LanguageStore
|
||||
ProfileActions = @ProfileActions
|
||||
|
||||
@TeacherSearchScreen = React.createClass({
|
||||
|
||||
# Reflux.listenTo(@TeacherSearchStore, "onTeacherSearchChanged"),
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@UserStore, "onUserChanged"),
|
||||
Reflux.listenTo(@TeacherSearchResultsStore, "onTeacherSearchResultsStore")]
|
||||
|
||||
LIMIT: 20
|
||||
visible: false
|
||||
|
||||
getInitialState: () ->
|
||||
{searchOptions: {}, results: []}
|
||||
|
||||
onAppInit: (@app) ->
|
||||
@app.bindScreen('teachers/search', {beforeShow: @beforeShow, afterShow: @afterShow, afterHide: @afterHide})
|
||||
|
||||
beforeShow: (e) ->
|
||||
@visible = true
|
||||
|
||||
afterShow: (e) ->
|
||||
@visible = false
|
||||
#@setState(TeacherSearchStore.getState())
|
||||
TeacherSearchResultsActions.reset()
|
||||
|
||||
afterHide: (e) ->
|
||||
|
||||
|
||||
onUserChanged: (@user) ->
|
||||
|
||||
#onTeacherSearchChanged: (options) ->
|
||||
# if @visible
|
||||
# @setState(options)
|
||||
|
||||
componentDidMount: () ->
|
||||
@root = $(@getDOMNode())
|
||||
@resultsNode = @root.find('.results')
|
||||
|
||||
componentDidUpdate: () ->
|
||||
@resultsNode.find('.teacher-bio').each((index, element) => (
|
||||
$this = $(element)
|
||||
if !$this.data('dotdotdot')
|
||||
$this.dotdotdot({
|
||||
after: "a.readmore"
|
||||
})
|
||||
))
|
||||
onTeacherSearchResultsStore: (results) ->
|
||||
@setState(results)
|
||||
|
||||
moreAboutTeacher: (user, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
ProfileActions.viewTeacherProfile(user, '/client#/teachers/search', 'BACK TO TEACHER SEARCH')
|
||||
|
||||
bookTestDrive: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
bookNormalLesson: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
bookFreeLesson: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
readMore: (e) ->
|
||||
e.preventDefault()
|
||||
|
||||
target = $(e.target)
|
||||
teacherBio = target.closest('.teacher-bio')
|
||||
teacherBio.css('height', 'auto')
|
||||
target.trigger( 'destroy.dot' );
|
||||
teacherBio.css('height', 'auto')
|
||||
|
||||
createSearchDescription: () ->
|
||||
searchOptions = TeacherSearchStore.getState().searchOptions
|
||||
|
||||
summary = ''
|
||||
instruments = searchOptions.instruments
|
||||
if instruments? && instruments.length > 0
|
||||
if instruments.length == 1
|
||||
bit = "Instrument = #{InstrumentStore.display(instruments[0])}"
|
||||
else
|
||||
instruments.length > 1
|
||||
bit = "Instruments = #{InstrumentStore.display(instruments[0])}..."
|
||||
summary += " #{bit}"
|
||||
|
||||
subjects = searchOptions.subjects
|
||||
if subjects? && subjects.length > 0
|
||||
if subjects.length == 1
|
||||
bit = "Subject = #{SubjectStore.display(subjects[0])}"
|
||||
else
|
||||
subjects.length > 1
|
||||
bit = "Subjects = #{SubjectStore.display(subjects[0])}..."
|
||||
summary += " #{bit}"
|
||||
|
||||
genres = searchOptions.genres
|
||||
if genres? && genres.length > 0
|
||||
if genres.length == 1
|
||||
bit = "Genre = #{GenreStore.display(genres[0])}"
|
||||
else
|
||||
genres.length > 1
|
||||
bit = "Genres = #{GenreStore.display(genres[0])}..."
|
||||
summary += " #{bit}"
|
||||
|
||||
languages = searchOptions.languages
|
||||
if languages? && languages.length > 0
|
||||
if languages.length == 1
|
||||
bit = "Genre = #{LanguageStore.display(languages[0])}"
|
||||
else
|
||||
languages.length > 1
|
||||
bit = "Genres = #{LanguageStore.display(languages[0])}..."
|
||||
summary += " #{bit}"
|
||||
|
||||
if summary.length == 0
|
||||
summary = 'all teachers'
|
||||
|
||||
summary
|
||||
|
||||
render: () ->
|
||||
|
||||
searchDesc = @createSearchDescription()
|
||||
|
||||
resultsJsx = []
|
||||
|
||||
for user in @state.results
|
||||
|
||||
photo_url = user.photo_url
|
||||
if !photo_url?
|
||||
photo_url = '/assets/shared/avatar_generic.png'
|
||||
|
||||
bio = user.teacher.biography
|
||||
if !bio?
|
||||
bio = 'No bio'
|
||||
|
||||
resultsJsx.push(`<div key={user.id} className="teacher-search-result">
|
||||
<div className="user-avatar">
|
||||
<div className="avatar small">
|
||||
<img src={photo_url} />
|
||||
</div>
|
||||
<div className="user-name">
|
||||
{user.name}
|
||||
</div>
|
||||
</div>
|
||||
<div className="user-info">
|
||||
<div className="teacher-bio">
|
||||
{bio}
|
||||
<a className="readmore" onClick={this.readMore}>more</a>
|
||||
</div>
|
||||
<div className="teacher-actions">
|
||||
<a className="button-orange" onClick={this.moreAboutTeacher.bind(this, user)}>MORE ABOUT THIS TEACHER</a>
|
||||
<a className="button-orange" onClick={this.bookTestDrive}>BOOK TESTDRIVE LESSON</a>
|
||||
<a className="button-orange" onClick={this.bookFreeLesson}>BOOK FREE LESSON</a>
|
||||
<a className="button-orange" onClick={this.bookNormalLesson}>BOOK NORMAL LESSON</a>
|
||||
</div>
|
||||
</div>
|
||||
<br className="clearall" />
|
||||
</div>`)
|
||||
|
||||
`<div className="content-body-scroller">
|
||||
<div className="screen-content">
|
||||
<div className="header">
|
||||
<a href="" onClick={alert.bind('not yet')}>LESSONS HOME</a> :
|
||||
<a href="/client#/jamclass/searchOptions" >TEACHERS SEARCH</a> :
|
||||
<span className="search-results-options">
|
||||
<span className="results-text">SEARCH RESULTS / </span>
|
||||
<span className="search-summary">{searchDesc}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="results">
|
||||
{resultsJsx}
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
context = window
|
||||
|
||||
@LocationActions = Reflux.createActions({
|
||||
|
||||
load: {}
|
||||
selectCountry: {}
|
||||
})
|
||||
|
|
@ -9,4 +9,6 @@ context = window
|
|||
cancelProfileEdit: {}
|
||||
doneProfileEdit: {}
|
||||
editProfileNext: {}
|
||||
viewTeacherProfile: {}
|
||||
viewTeacherProfileDone: {}
|
||||
})
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
context = window
|
||||
|
||||
@TeacherSearchActions = Reflux.createActions({
|
||||
updateOptions: {}
|
||||
search: {}
|
||||
})
|
||||
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
context = window
|
||||
|
||||
@TeacherSearchResultsActions = Reflux.createActions({
|
||||
reset: {}
|
||||
})
|
||||
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
rest = window.JK.Rest()
|
||||
logger = context.JK.logger
|
||||
|
||||
@LocationStore = Reflux.createStore(
|
||||
{
|
||||
listenables: @LocationActions
|
||||
countries: {}
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
changed: () ->
|
||||
@trigger(@countries)
|
||||
|
||||
onSelectCountry: (country) ->
|
||||
@loadRegions(country)
|
||||
|
||||
onLoad: () ->
|
||||
|
||||
# avoid double-loads
|
||||
if Object.keys(@countries).length == 0
|
||||
rest.getCountries().done ((response) =>
|
||||
countries = response.countriesx
|
||||
if Object.keys(@countries).length == 0
|
||||
for country in countries
|
||||
name = country.countryname
|
||||
if !name?
|
||||
name = country.countrycode
|
||||
@countries[country.countrycode] = {name: name, regions:null}
|
||||
|
||||
@loadRegions('US')
|
||||
)
|
||||
|
||||
loadRegions: (loadForCountry) ->
|
||||
if loadForCountry == null
|
||||
return
|
||||
|
||||
country = @countries[loadForCountry]
|
||||
|
||||
if !country?
|
||||
logger.warn("country is null in searching for: " + loadForCountry)
|
||||
return
|
||||
|
||||
regions = country.regions
|
||||
|
||||
# avoid double-loads
|
||||
if regions == null
|
||||
rest.getRegions({country: loadForCountry}).done ((countriesRegions) =>
|
||||
regions = country.regions
|
||||
if regions == null
|
||||
regions = []
|
||||
country.regions = regions
|
||||
|
||||
if regions.length > 0
|
||||
return
|
||||
|
||||
for region in countriesRegions.regions
|
||||
|
||||
id = region.region
|
||||
name = region.name
|
||||
if !name?
|
||||
name = region.region
|
||||
|
||||
regions.push({id: id, name: name})
|
||||
|
||||
@changed()
|
||||
)
|
||||
onAppInit: (@app) ->
|
||||
|
||||
}
|
||||
)
|
||||
|
|
@ -8,6 +8,8 @@ ProfileActions = @ProfileActions
|
|||
{
|
||||
listenables: ProfileActions
|
||||
|
||||
customBack: null
|
||||
customBackDisplay: null
|
||||
returnNav: null
|
||||
solo: false
|
||||
|
||||
|
|
@ -95,6 +97,16 @@ ProfileActions = @ProfileActions
|
|||
@solo = false
|
||||
else
|
||||
context.location = "/client#/account/profile/" + step
|
||||
|
||||
onViewTeacherProfile: (user, customBack, customBackDisplay) ->
|
||||
|
||||
@customBack = customBack
|
||||
@customBackDisplay = customBackDisplay
|
||||
context.location = "/client#/profile/teacher/#{user.id}"
|
||||
|
||||
onViewTeacherProfileDone: () ->
|
||||
@customBack = null
|
||||
@customBackDisplay = null
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
rest = context.JK.Rest()
|
||||
|
||||
TeacherSearchResultsActions = @TeacherSearchResultsActions
|
||||
|
||||
@TeacherSearchResultsStore = Reflux.createStore(
|
||||
{
|
||||
listenables: TeacherSearchResultsActions
|
||||
results: []
|
||||
page: 1
|
||||
limit: 20
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
||||
onReset: () ->
|
||||
@results = []
|
||||
@changed()
|
||||
|
||||
query = @createQuery()
|
||||
|
||||
rest.searchTeachers(query)
|
||||
.done((response) =>
|
||||
@next = response.next
|
||||
|
||||
@results.push.apply(@results, response.entries)
|
||||
@changed()
|
||||
)
|
||||
.fail((jqXHR, textStatus, errorMessage) =>
|
||||
@app.ajaxError(jqXHR, textStatus, errorMessage)
|
||||
)
|
||||
|
||||
getState: () ->
|
||||
({results: @results})
|
||||
|
||||
changed:() ->
|
||||
@trigger(@getState())
|
||||
|
||||
createQuery: () ->
|
||||
|
||||
searchOptions = context.TeacherSearchStore.getState().searchOptions
|
||||
|
||||
query = {}
|
||||
query.page = @page
|
||||
query.limit = @limit
|
||||
query.instruments = searchOptions.instruments
|
||||
query.subjects = searchOptions.subjects
|
||||
query.genres = searchOptions.genres
|
||||
query.languages = searchOptions.languages
|
||||
query.teaches_beginner = searchOptions.teaches_beginner
|
||||
query.teaches_intermediate = searchOptions.teaches_intermediate
|
||||
query.teaches_advanced = searchOptions.teaches_advanced
|
||||
query.student_age = searchOptions['ages-taught']
|
||||
query.years_teaching = searchOptions['years-teaching']
|
||||
query.country = searchOptions.location?.country
|
||||
query.region = searchOptions.location?.region
|
||||
query
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
rest = context.JK.Rest()
|
||||
|
||||
TeacherSearchActions = @TeacherSearchActions
|
||||
|
||||
@TeacherSearchStore = Reflux.createStore(
|
||||
{
|
||||
listenables: TeacherSearchActions
|
||||
searchOptions: {}
|
||||
viewingTeacher: null
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
|
||||
onAppInit: (app) ->
|
||||
@app = app
|
||||
|
||||
onUpdateOptions: (options) ->
|
||||
@searchOptions = options
|
||||
|
||||
onSearch: (searchOptions) ->
|
||||
@searchOptions = searchOptions
|
||||
|
||||
@changed()
|
||||
|
||||
window.location = "/client#/teachers/search"
|
||||
|
||||
getState: () ->
|
||||
({searchOptions: @searchOptions})
|
||||
|
||||
changed:() ->
|
||||
@trigger(@getState())
|
||||
}
|
||||
)
|
||||
|
|
@ -172,6 +172,10 @@
|
|||
}
|
||||
.years {float:right}
|
||||
}
|
||||
.profileNavActions {
|
||||
margin-right: -3px;
|
||||
}
|
||||
|
||||
.ratings-block {
|
||||
|
||||
h3 {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,109 @@
|
|||
@import "client/common";
|
||||
|
||||
#teacherSearch {
|
||||
div[data-react-class="TeacherSearchScreen"] {
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.screen-content {
|
||||
padding:20px;
|
||||
}
|
||||
|
||||
.header {
|
||||
height:20px;
|
||||
margin-bottom:10px;
|
||||
|
||||
a {
|
||||
font-size:16px;
|
||||
text-decoration:underline;
|
||||
}
|
||||
.search-results-options {
|
||||
font-size:16px;
|
||||
color:$ColorTextTypical;
|
||||
}
|
||||
}
|
||||
|
||||
a.readmore {
|
||||
display:none;
|
||||
}
|
||||
|
||||
.search-summary {
|
||||
font-size:11px;
|
||||
}
|
||||
.teacher-search-result {
|
||||
@include border_box_sizing;
|
||||
clear:both;
|
||||
position:relative;
|
||||
margin-bottom:10px;
|
||||
width:100%;
|
||||
min-width:600px;
|
||||
background-color:#242323;
|
||||
color:$ColorTextTypical;
|
||||
//height:110px;
|
||||
padding:10px;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
@include border_box_sizing;
|
||||
width: calc(100% - 150px);
|
||||
//padding:12px 10px 10px;
|
||||
min-width:450px;
|
||||
float:right;
|
||||
}
|
||||
|
||||
.teacher-bio {
|
||||
@include border_box_sizing;
|
||||
height:50px;
|
||||
width:100%;
|
||||
margin-bottom:16px;
|
||||
font-size:12px;
|
||||
}
|
||||
.teacher-actions {
|
||||
a {
|
||||
font-size:12px;
|
||||
|
||||
&:nth-of-type(1) {
|
||||
margin-left:2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-avatar {
|
||||
text-align:center;
|
||||
float:left;
|
||||
width:150px;
|
||||
}
|
||||
.avatar {
|
||||
display:inline-block;
|
||||
padding:1px;
|
||||
width:48px;
|
||||
height:48px;
|
||||
background-color:#ed4818;
|
||||
margin:10px 0 0 0;
|
||||
-webkit-border-radius:24px;
|
||||
-moz-border-radius:24px;
|
||||
border-radius:24px;
|
||||
float:none;
|
||||
}
|
||||
.avatar img {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
-webkit-border-radius:24px;
|
||||
-moz-border-radius:24px;
|
||||
border-radius:24px;
|
||||
}
|
||||
.user-name {
|
||||
text-align:center;
|
||||
display:block;
|
||||
margin-top:8px;
|
||||
clear:both;
|
||||
}
|
||||
|
||||
.actions {
|
||||
float: right;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
padding-right: 31px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,93 @@
|
|||
@import "client/common";
|
||||
|
||||
#teacherSearchOptions {
|
||||
div[data-react-class="TeacherSearchOptionsScreen"] {
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.search-criteria {
|
||||
.checkbox-scroller {
|
||||
height:100px;
|
||||
margin-top:0;
|
||||
}
|
||||
min-width:200px;
|
||||
width:25%;
|
||||
@include border_box_sizing;
|
||||
float:left;
|
||||
padding: 0 10px;
|
||||
margin-bottom:30px;
|
||||
|
||||
&:first-child {
|
||||
padding-left:0;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-right:0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: #FFFFFF;
|
||||
font-size: 14px;
|
||||
font-weight: 400;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
.screen-content {
|
||||
padding:20px;
|
||||
}
|
||||
|
||||
.actions {
|
||||
float: right;
|
||||
width: 100%;
|
||||
text-align: right;
|
||||
padding-right: 31px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
h2 {
|
||||
color: #FFFFFF;
|
||||
font-size: 23px;
|
||||
font-weight: 400;
|
||||
margin-bottom:20px;
|
||||
padding-left:10px;
|
||||
}
|
||||
|
||||
select {
|
||||
@include border_box_sizing;
|
||||
width: 100%;
|
||||
max-width:200px;
|
||||
}
|
||||
|
||||
.SelectLocation {
|
||||
|
||||
select[name="countries"] {
|
||||
//margin-top: 6px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
}
|
||||
|
||||
select[name="years-teaching"] {
|
||||
//margin-top: 6px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.student-levels-taught {
|
||||
.teaching-level {
|
||||
margin-bottom:10px;
|
||||
}
|
||||
label {
|
||||
display:inline-block;
|
||||
}
|
||||
input {
|
||||
display:inline-block;
|
||||
margin-right:10px;
|
||||
}
|
||||
.beginner-level {
|
||||
margin-top:10px;
|
||||
}
|
||||
}
|
||||
|
||||
.years-teaching-header {
|
||||
margin-top:30px;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,13 +1,21 @@
|
|||
class ApiTeachersController < ApiController
|
||||
|
||||
before_filter :api_signed_in_user, :except => [:index, :detail]
|
||||
before_filter :api_signed_in_user, :except => [:index, :detail, :search]
|
||||
before_filter :auth_teacher, :only => [:update, :delete]
|
||||
before_filter :auth_user, :only => [:create, :update]
|
||||
|
||||
respond_to :json
|
||||
|
||||
def index
|
||||
@teachers = Teacher.paginate(page: params[:page])
|
||||
data = Teacher.index(current_user, params)
|
||||
|
||||
@show_profile = true
|
||||
@show_teacher = true
|
||||
|
||||
@users = data[:query]
|
||||
|
||||
@next = data[:next_page]
|
||||
render "api_teachers/index", :layout => nil
|
||||
end
|
||||
|
||||
def detail
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
node :next do |page|
|
||||
@next
|
||||
end
|
||||
|
||||
node :entries do |page|
|
||||
partial "api_users/show", object: @users
|
||||
end
|
||||
|
||||
node :total_entries do |page|
|
||||
@users.total_entries
|
||||
end
|
||||
|
|
@ -3,19 +3,25 @@ object @user
|
|||
attributes :id, :first_name, :last_name, :name, :city, :state, :country, :location, :online, :photo_url, :musician, :gender, :birth_date, :internet_service_provider, :friend_count, :liker_count, :like_count, :follower_count, :following_count,
|
||||
:recording_count, :session_count, :biography, :favorite_count, :audio_latency, :upcoming_session_count, :age, :website, :skill_level, :reuse_card, :email_needs_verification
|
||||
|
||||
if @user.musician?
|
||||
node :location do @user.location end
|
||||
else
|
||||
node :location do @user.online ? 'Online' : 'Offline' end
|
||||
end
|
||||
|
||||
if @show_teacher && @user.teacher
|
||||
node :teacher do
|
||||
partial("api_teachers/detail", :object => @user.teacher)
|
||||
node :location do |user|
|
||||
if user.musician?
|
||||
user.location
|
||||
else
|
||||
user.online ? 'Online' : 'Offline'
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
node :teacher do |user|
|
||||
if @show_teacher && user.teacher
|
||||
partial("api_teachers/detail", :object => user.teacher)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
if @show_profile
|
||||
node :profile do
|
||||
partial("api_users/profile_show", :object => @user)
|
||||
|
|
@ -23,7 +29,8 @@ if @show_profile
|
|||
end
|
||||
|
||||
# give back more info if the user being fetched is yourself
|
||||
if @user == current_user
|
||||
|
||||
if current_user && @user == current_user
|
||||
attributes :email, :original_fpfile, :cropped_fpfile, :crop_selection, :session_settings, :show_whats_next, :show_whats_next_count, :subscribe_email, :auth_twitter, :new_notifications, :sales_count, :reuse_card, :purchased_jamtracks_count, :first_downloaded_client_at, :created_at, :first_opened_jamtrack_web_player, :gifted_jamtracks, :has_redeemable_jamtrack
|
||||
|
||||
node :geoiplocation do |user|
|
||||
|
|
@ -43,34 +50,34 @@ if @user == current_user
|
|||
user.mods_json
|
||||
end
|
||||
|
||||
node :has_recurly_account do
|
||||
@user.recurly_code == @user.id
|
||||
node :has_recurly_account do |user|
|
||||
user.recurly_code == user.id
|
||||
end
|
||||
|
||||
node :is_affiliate_partner do
|
||||
@user.affiliate_partner.present?
|
||||
node :is_affiliate_partner do |user|
|
||||
user.affiliate_partner.present?
|
||||
end
|
||||
|
||||
node :affiliate_referral_count do
|
||||
@user.affiliate_partner.try(:referral_user_count)
|
||||
node :affiliate_referral_count do |user|
|
||||
user.affiliate_partner.try(:referral_user_count)
|
||||
end
|
||||
|
||||
node :affiliate_earnings do
|
||||
@user.affiliate_partner.try(:cumulative_earnings_in_cents)
|
||||
node :affiliate_earnings do |user|
|
||||
user.affiliate_partner.try(:cumulative_earnings_in_cents)
|
||||
end
|
||||
|
||||
elsif current_user
|
||||
node :is_friend do |uu|
|
||||
current_user.friends?(@user)
|
||||
current_user.friends?(uu)
|
||||
end
|
||||
node :is_following do |uu|
|
||||
current_user.following?(@user)
|
||||
current_user.following?(uu)
|
||||
end
|
||||
node :is_liking do |uu|
|
||||
current_user.likes?(@user)
|
||||
current_user.likes?(uu)
|
||||
end
|
||||
node :pending_friend_request do |uu|
|
||||
current_user.pending_friend_request?(@user)
|
||||
current_user.pending_friend_request?(uu)
|
||||
end
|
||||
node :my_audio_latency do |user|
|
||||
current_user.last_jam_audio_latency.round if current_user.last_jam_audio_latency
|
||||
|
|
|
|||
|
|
@ -43,6 +43,8 @@
|
|||
<%= render "clients/teachers/setup/experience" %>
|
||||
<%= render "clients/teachers/setup/pricing" %>
|
||||
<%= render "clients/teachers/profile/profile" %>
|
||||
<%= render "clients/teachers/search/search_options" %>
|
||||
<%= render "clients/teachers/search/search_results" %>
|
||||
<%= render "users/feed_music_session_ajax" %>
|
||||
<%= render "users/feed_recording_ajax" %>
|
||||
<%= render "jamtrack_search" %>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
#teacherSearchOptions.screen.secondary.no-login-required layout='screen' layout-id='jamclass/searchOptions'
|
||||
.content
|
||||
.content-head
|
||||
.content-icon=image_tag("content/icon_account.png", height:20, width:27)
|
||||
h1 jamclass
|
||||
= render "screen_navigation"
|
||||
.content-body
|
||||
= react_component 'TeacherSearchOptionsScreen', {}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#teacherSearch.screen.secondary.no-login-required layout='screen' layout-id='teachers/search'
|
||||
.content
|
||||
.content-head
|
||||
.content-icon=image_tag("content/icon_musicians.png", height:20, width:20)
|
||||
h1 jamclass
|
||||
= render "screen_navigation"
|
||||
.content-body
|
||||
= react_component 'TeacherSearchScreen', {}
|
||||
Loading…
Reference in New Issue