* working minus ratings
This commit is contained in:
parent
48bd7ae2da
commit
14643531dc
|
|
@ -1,6 +1,5 @@
|
|||
CREATE TABLE teachers (
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
user_id VARCHAR(64) REFERENCES users(id) ON DELETE CASCADE,
|
||||
introductory_video VARCHAR(1024) NULL,
|
||||
years_teaching SMALLINT NOT NULL DEFAULT 0,
|
||||
years_playing SMALLINT NOT NULL DEFAULT 0,
|
||||
|
|
@ -32,6 +31,8 @@ CREATE TABLE teachers (
|
|||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
|
||||
ALTER TABLE users ADD COLUMN teacher_id VARCHAR(64) REFERENCES teachers(id) ON DELETE SET NULL;
|
||||
|
||||
CREATE TABLE subjects(
|
||||
id VARCHAR(64) PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
description VARCHAR(1024) NULL
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ module JamRuby
|
|||
has_many :experiences_teaching, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'teaching'}
|
||||
has_many :experiences_education, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'education'}
|
||||
has_many :experiences_award, :class_name => "JamRuby::TeacherExperience", conditions: {experience_type: 'award'}
|
||||
belongs_to :user, :class_name => 'JamRuby::User'
|
||||
has_one :user, :class_name => 'JamRuby::User'
|
||||
|
||||
validates :user, :presence => true
|
||||
validates :biography, length: {minimum: 5, maximum: 4096}, :if => :validate_introduction
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ module JamRuby
|
|||
|
||||
has_one :musician_search, :class_name => 'JamRuby::MusicianSearch'
|
||||
has_one :band_search, :class_name => 'JamRuby::BandSearch'
|
||||
belongs_to :teacher, :class_name => 'JamRuby::Teacher'
|
||||
|
||||
before_save :default_anonymous_names
|
||||
before_save :create_remember_token, :if => :should_validate_password?
|
||||
|
|
|
|||
|
|
@ -170,11 +170,11 @@
|
|||
|
||||
function navToEditProfile() {
|
||||
resetForm()
|
||||
window.location = '/client#/account/profile'
|
||||
window.ProfileActions.startProfileEdit(null, false)
|
||||
}
|
||||
|
||||
function navToEditSubscriptions() {
|
||||
window.location = '/client#/account/profile'
|
||||
window.ProfileActions.startProfileEdit(null, false)
|
||||
}
|
||||
|
||||
function navToEditPayments() {
|
||||
|
|
|
|||
|
|
@ -220,7 +220,7 @@
|
|||
function events() {
|
||||
$btnCancel.click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
navToAccount();
|
||||
window.ProfileActions.cancelProfileEdit()
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
@ -302,7 +302,7 @@
|
|||
|
||||
function postUpdateProfileSuccess(response) {
|
||||
$document.triggerHandler(EVENTS.USER_UPDATED, response);
|
||||
context.location = "/client#/account/profile/experience";
|
||||
window.ProfileActions.editProfileNext('experience');
|
||||
}
|
||||
|
||||
function postUpdateProfileFailure(xhr, textStatus, errorMessage) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,13 @@
|
|||
}
|
||||
|
||||
function afterShow(data) {
|
||||
if (window.ProfileStore.solo) {
|
||||
$btnBack.hide()
|
||||
}
|
||||
else {
|
||||
$btnBack.show()
|
||||
}
|
||||
|
||||
resetForm();
|
||||
renderExperience();
|
||||
}
|
||||
|
|
@ -115,7 +122,7 @@
|
|||
function events() {
|
||||
$btnCancel.click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
navigateTo('/client#/profile/' + context.JK.currentUserId);
|
||||
window.ProfileActions.cancelProfileEdit()
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
@ -179,7 +186,7 @@
|
|||
|
||||
function postUpdateProfileSuccess(response) {
|
||||
$document.triggerHandler(EVENTS.USER_UPDATED, response);
|
||||
context.location = "/client#/account/profile/interests";
|
||||
ProfileActions.editProfileNext('interests')
|
||||
}
|
||||
|
||||
function postUpdateProfileFailure(xhr, textStatus, errorMessage) {
|
||||
|
|
|
|||
|
|
@ -70,7 +70,14 @@
|
|||
}
|
||||
|
||||
function afterShow(data) {
|
||||
renderInterests()
|
||||
if (window.ProfileStore.solo) {
|
||||
$btnBack.hide()
|
||||
}
|
||||
else {
|
||||
$btnBack.show()
|
||||
}
|
||||
|
||||
renderInterests()
|
||||
}
|
||||
|
||||
function resetForm() {
|
||||
|
|
@ -187,7 +194,7 @@
|
|||
|
||||
$btnCancel.click(function(e) {
|
||||
e.stopPropagation()
|
||||
navigateTo('/client#/profile/' + context.JK.currentUserId)
|
||||
window.ProfileActions.cancelProfileEdit()
|
||||
return false
|
||||
})
|
||||
|
||||
|
|
@ -310,7 +317,7 @@
|
|||
|
||||
function postUpdateProfileSuccess(response) {
|
||||
$document.triggerHandler(EVENTS.USER_UPDATED, response)
|
||||
context.location = "/client#/account/profile/samples"
|
||||
ProfileActions.editProfileNext('samples')
|
||||
}
|
||||
|
||||
function postUpdateProfileFailure(xhr, textStatus, errorMessage) {
|
||||
|
|
|
|||
|
|
@ -43,7 +43,6 @@
|
|||
var $btnBack = parent.find('.account-edit-profile-back')
|
||||
var $btnSubmit = parent.find('.account-edit-profile-submit')
|
||||
|
||||
|
||||
var urlValidator=null
|
||||
var soundCloudValidator=null
|
||||
var reverbNationValidator=null
|
||||
|
|
@ -59,9 +58,16 @@
|
|||
}
|
||||
|
||||
function afterShow(data) {
|
||||
if (window.ProfileStore.solo) {
|
||||
$btnBack.hide()
|
||||
}
|
||||
else {
|
||||
$btnBack.show()
|
||||
}
|
||||
|
||||
$.when(loadFn())
|
||||
.done(function(targetPlayer) {
|
||||
if (targetPlayer && targetPlayer.keys && targetPlayer.keys.length > 0) {
|
||||
if (targetPlayer) {
|
||||
renderPlayer(targetPlayer)
|
||||
}
|
||||
})
|
||||
|
|
@ -207,7 +213,9 @@
|
|||
|
||||
$btnCancel.click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
navigateTo('/client#/profile/' + context.JK.currentUserId);
|
||||
|
||||
window.ProfileActions.cancelProfileEdit()
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
|
|
@ -334,7 +342,7 @@
|
|||
|
||||
function postUpdateProfileSuccess(response) {
|
||||
$document.triggerHandler(EVENTS.USER_UPDATED, response);
|
||||
context.location = "/client#/profile/" + context.JK.currentUserId;
|
||||
ProfileActions.doneProfileEdit()
|
||||
}
|
||||
|
||||
function postUpdateProfileFailure(xhr, textStatus, errorMessage) {
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@
|
|||
//= require ga
|
||||
//= require utils
|
||||
//= require subscription_utils
|
||||
//= require profile_utils
|
||||
//= require custom_controls
|
||||
//= require react
|
||||
//= require react_ujs
|
||||
|
|
|
|||
|
|
@ -582,13 +582,16 @@
|
|||
}
|
||||
|
||||
function getUserDetail(options) {
|
||||
if(!options) {
|
||||
options = {}
|
||||
}
|
||||
var id = getId(options);
|
||||
var detail = null;
|
||||
if (id != null && typeof(id) != 'undefined') {
|
||||
detail = $.ajax({
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
url: "/api/users/" + id,
|
||||
url: "/api/users/" + id + '?'+ $.param(options),
|
||||
processData: false
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
var $btnAddRecordings = $screen.find('.add-recordings');
|
||||
var $btnAddSites = $screen.find('.add-sites');
|
||||
var $btnAddInterests = $screen.find('.add-interests');
|
||||
var $btnAddExperiences = $screen.find('.add-experiences')
|
||||
|
||||
// social
|
||||
var $socialLeft = $screen.find('.profile-social-left');
|
||||
|
|
@ -251,6 +252,37 @@
|
|||
|
||||
// Hook up soundcloud player:
|
||||
$soundCloudSamples.off("click", "a.sound-cloud-playable") .on("click", "a.sound-cloud-playable", playSoundCloudFile)
|
||||
|
||||
$btnEdit.click(function(e) {
|
||||
e.preventDefault()
|
||||
window.ProfileActions.startProfileEdit(null, false)
|
||||
return false;
|
||||
})
|
||||
$btnEditBio.click(function(e) {
|
||||
e.preventDefault()
|
||||
window.ProfileActions.startProfileEdit(null, true)
|
||||
return false;
|
||||
})
|
||||
$btnAddRecordings.click(function(e) {
|
||||
e.preventDefault()
|
||||
window.ProfileActions.startProfileEdit('samples', true)
|
||||
return false;
|
||||
})
|
||||
$btnAddSites.click(function(e) {
|
||||
e.preventDefault()
|
||||
window.ProfileActions.startProfileEdit('samples', true)
|
||||
return false;
|
||||
})
|
||||
$btnAddInterests.click(function(e) {
|
||||
e.preventDefault()
|
||||
window.ProfileActions.startProfileEdit('interests', true)
|
||||
return false;
|
||||
});
|
||||
$btnAddExperiences.click(function(e) {
|
||||
e.preventDefault()
|
||||
window.ProfileActions.startProfileEdit('experience', true)
|
||||
return false;
|
||||
})
|
||||
}
|
||||
|
||||
function playSoundCloudFile(e) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
var NOT_SPECIFIED_TEXT = 'Not specified';
|
||||
|
||||
profileUtils.NOT_SPECIFIED_TEXT = NOT_SPECIFIED_TEXT
|
||||
|
||||
var proficiencyDescriptionMap = {
|
||||
"1": "BEGINNER",
|
||||
"2": "INTERMEDIATE",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,9 @@
|
|||
//= require ./react-components/stores/AppStore
|
||||
//= require ./react-components/stores/InstrumentStore
|
||||
//= require ./react-components/stores/LanguageStore
|
||||
//= require ./react-components/stores/GenreStore
|
||||
//= require ./react-components/stores/SubjectStore
|
||||
//= require ./react-components/stores/ProfileStore
|
||||
//= require ./react-components/stores/PlatformStore
|
||||
//= require ./react-components/stores/BrowserMediaStore
|
||||
//= require ./react-components/stores/RecordingStore
|
||||
|
|
|
|||
|
|
@ -3,16 +3,18 @@ rest = window.JK.Rest()
|
|||
logger = context.JK.logger
|
||||
|
||||
@GenreCheckBoxList = React.createClass({
|
||||
genres: []
|
||||
componentDidUnmount: () ->
|
||||
@genres = []
|
||||
|
||||
componentDidMount: () ->
|
||||
rest.getGenres().done (genres) =>
|
||||
@genres = genres
|
||||
mixins: [Reflux.listenTo(@GenreStore,"onGenresChanged")]
|
||||
|
||||
getInitialState:() ->
|
||||
{genres: []}
|
||||
|
||||
onGenresChanged: (genres) ->
|
||||
@setState({genres: genres})
|
||||
|
||||
|
||||
render: () ->
|
||||
`<div className="GenreCheckBoxList react-component">
|
||||
<CheckBoxList objectName='genres' onItemChanged={this.props.onItemChanged} sourceObjects={this.genres} selectedObjects={this.props.selectedGenres}/>
|
||||
<CheckBoxList objectName='genres' onItemChanged={this.props.onItemChanged} sourceObjects={this.state.genres} selectedObjects={this.props.selectedGenres}/>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -3,16 +3,17 @@ rest = window.JK.Rest()
|
|||
logger = context.JK.logger
|
||||
|
||||
@SubjectCheckBoxList = React.createClass({
|
||||
subjects: []
|
||||
componentDidUnmount: () ->
|
||||
@subjects = []
|
||||
|
||||
componentDidMount: () ->
|
||||
rest.getSubjects().done (subjects) =>
|
||||
@subjects = subjects
|
||||
mixins: [Reflux.listenTo(@SubjectStore,"onSubjectsChanged")]
|
||||
|
||||
getInitialState:() ->
|
||||
{subjects: []}
|
||||
|
||||
onSubjectsChanged: (subjects) ->
|
||||
@setState({subjects: subjects})
|
||||
|
||||
render: () ->
|
||||
`<div className="SubjectCheckBoxList react-component">
|
||||
<CheckBoxList objectName='subjects' onItemChanged={this.props.onItemChanged} sourceObjects={this.subjects} selectedObjects={this.props.selectedSubjects}/>
|
||||
<CheckBoxList objectName='subjects' onItemChanged={this.props.onItemChanged} sourceObjects={this.state.subjects} selectedObjects={this.props.selectedSubjects}/>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -1,32 +1,613 @@
|
|||
|
||||
context = window
|
||||
MIX_MODES = context.JK.MIX_MODES
|
||||
rest = context.JK.Rest()
|
||||
logger = context.JK.logger
|
||||
|
||||
SubjectStore = context.SubjectStore
|
||||
InstrumentStore = context.InstrumentStore
|
||||
LanguageStore = context.LanguageStore
|
||||
GenreStore = context.GenreStore
|
||||
UserStore = context.UserStore
|
||||
AppStore = context.AppStore
|
||||
|
||||
profileUtils = context.JK.ProfileUtils
|
||||
|
||||
proficiencyCssMap = {
|
||||
"1": "proficiency-beginner",
|
||||
"2": "proficiency-intermediate",
|
||||
"3": "proficiency-expert"
|
||||
};
|
||||
|
||||
proficiencyDescriptionMap = {
|
||||
"1": "BEGINNER",
|
||||
"2": "INTERMEDIATE",
|
||||
"3": "EXPERT"
|
||||
};
|
||||
|
||||
@TeacherProfile = React.createClass({
|
||||
|
||||
mixins: [Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@UserStore, "onUserChanged")]
|
||||
mixins: [
|
||||
Reflux.listenTo(AppStore, "onAppInit"),
|
||||
Reflux.listenTo(UserStore, "onUserChanged"),
|
||||
Reflux.listenTo(SubjectStore, "onSubjectsChanged"),
|
||||
Reflux.listenTo(GenreStore, "onGenresChanged"),
|
||||
Reflux.listenTo(InstrumentStore, "onInstrumentsChanged"),
|
||||
Reflux.listenTo(LanguageStore, "onLanguagesChanged")
|
||||
]
|
||||
|
||||
TILE_ABOUT: 'about'
|
||||
TILE_EXPERIENCE: 'experience'
|
||||
TILE_SAMPLES: 'samples'
|
||||
TILE_RATINGS: 'ratings'
|
||||
TILE_PRICES: 'prices'
|
||||
|
||||
TILES: ['about', 'experience', 'samples', 'ratings', 'prices']
|
||||
|
||||
onAppInit: (@app) ->
|
||||
@app.bindScreen('/teacher/profile', {beforeShow: @beforeShow, afterShow: @afterShow})
|
||||
@app.bindScreen('profile/teacher', {beforeShow: @beforeShow, afterShow: @afterShow})
|
||||
|
||||
onSubjectsChanged: () ->
|
||||
@setState({subjects: true})
|
||||
|
||||
onInstrumentsChanged: () ->
|
||||
@setState({instruments: true})
|
||||
|
||||
onGenresChanged: () ->
|
||||
@setState({genres: true})
|
||||
|
||||
onLanguagesChanged: () ->
|
||||
@setState({languages: true})
|
||||
|
||||
beforeShow: (e) ->
|
||||
console.log(arguments)
|
||||
rest.getUserDetail('')
|
||||
|
||||
@setState({userId: e.id, user: null})
|
||||
rest.getUserDetail({
|
||||
id: e.id,
|
||||
show_teacher: true,
|
||||
show_profile: true
|
||||
}).done((response) => @userDetailDone(response)).fail(@app.ajaxError)
|
||||
|
||||
userDetailDone: (response) ->
|
||||
if response.id == @state.userId
|
||||
@setState({user: response, isSelf: response.id == context.JK.currentUserId})
|
||||
|
||||
|
||||
afterShow: () ->
|
||||
console.log(arguments)
|
||||
|
||||
getInitialState: () ->
|
||||
{user: null}
|
||||
{
|
||||
userId: null,
|
||||
user: null,
|
||||
selected: @TILE_ABOUT,
|
||||
isSelf: false,
|
||||
subjects: false,
|
||||
instruments: false,
|
||||
genres: false,
|
||||
languages: false
|
||||
}
|
||||
|
||||
onUserChanged: (userState) ->
|
||||
@user = userState?.user
|
||||
@onUser(userState.user) if userState.user
|
||||
|
||||
editProfile: (selected, e) ->
|
||||
e.preventDefault()
|
||||
logger.debug("edit profile requested for state " + selected)
|
||||
ProfileActions.startTeacherEdit(selected, true)
|
||||
|
||||
editMusicProfile: (selected, e) ->
|
||||
e.preventDefault()
|
||||
logger.debug("edit music profile requested " + selected)
|
||||
ProfileActions.startProfileEdit(selected, true)
|
||||
|
||||
editProfileLink: (text, selected) ->
|
||||
if @state.isSelf
|
||||
`<a className="edit-link" onClick={this.editProfile.bind(this, selected)}>{text}</a>`
|
||||
|
||||
editMusicProfileLink: (text, selected) ->
|
||||
if @state.isSelf
|
||||
`<a className="edit-link" onClick={this.editMusicProfile.bind(this, selected)}>{text}</a>`
|
||||
|
||||
|
||||
teacherBio: (user, teacher) ->
|
||||
if teacher.biography?
|
||||
biography = teacher.biography
|
||||
else
|
||||
biography = 'No bio defined yet'
|
||||
|
||||
biography = biography.replace(/\n/g, "<br/>")
|
||||
|
||||
`<div className="section bio">
|
||||
<h3>Teacher Profile {this.editProfileLink('edit profile', 'introduction')}</h3>
|
||||
<div className="section-content">
|
||||
<div dangerouslySetInnerHTML={{__html: biography}}></div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
sampleVideo: (user, teacher) ->
|
||||
if teacher.introductory_video?
|
||||
videoUrl = teacher.introductory_video
|
||||
|
||||
if videoUrl.indexOf(window.location.protocol) != 0
|
||||
console.log("replacing video")
|
||||
if window.location.protocol == 'http:'
|
||||
console.log("replacing https: " + videoUrl)
|
||||
videoUrl = videoUrl.replace('https://', 'http://')
|
||||
console.log("replaced : " + videoUrl)
|
||||
else
|
||||
videoUrl = videoUrl.replace('http://', 'https://')
|
||||
|
||||
videoUrl = videoUrl.replace("watch?v=", "v/")
|
||||
|
||||
|
||||
return `<div className="section introductory-video">
|
||||
<h3>Intro Video</h3>
|
||||
|
||||
<div className="section-content">
|
||||
<div className="video-wrapper">
|
||||
<div className="video-container">
|
||||
<iframe src={videoUrl} frameborder="0" allowfullscreen="allowfullscreen"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
|
||||
teachesInfo: (user, teacher) ->
|
||||
teachesInfo = []
|
||||
|
||||
instruments = teacher.instruments.map((id) -> InstrumentStore.display(id))
|
||||
instrumentData = instruments.join(', ')
|
||||
teachesInfo.push(`<tr>
|
||||
<td>Instruments</td>
|
||||
<td>{instrumentData}</td>
|
||||
</tr>`)
|
||||
|
||||
subjects = teacher.subjects.map((id) -> SubjectStore.display(id))
|
||||
subjectsData = subjects.join(', ')
|
||||
teachesInfo.push(`<tr>
|
||||
<td>Subjects</td>
|
||||
<td>{subjectsData}</td>
|
||||
</tr>`)
|
||||
|
||||
genres = teacher.genres.map((id) -> GenreStore.display(id))
|
||||
genresData = genres.join(', ')
|
||||
teachesInfo.push(`<tr>
|
||||
<td>Genres</td>
|
||||
<td>{genresData}</td>
|
||||
</tr>`)
|
||||
|
||||
levels = []
|
||||
if teacher.teaches_beginner
|
||||
levels.push('Beginner')
|
||||
if teacher.teaches_intermediate
|
||||
levels.push('Intermediate')
|
||||
if teacher.teaches_advanced
|
||||
levels.push('Advanced')
|
||||
levelsData = levels.join(', ')
|
||||
teachesInfo.push(`<tr>
|
||||
<td>Levels</td>
|
||||
<td>{levelsData}</td>
|
||||
</tr>`)
|
||||
|
||||
ageData = '?'
|
||||
if teacher.teaches_age_lower == 0 && teacher.teaches_age_upper == 0
|
||||
ageData = 'Any'
|
||||
else if teacher.teaches_age_lower != 0 && teacher.teaches_age_upper != 0
|
||||
ageData = "#{teacher.teaches_age_lower} to #{teacher.teaches_age_upper}"
|
||||
else if teacher.teaches_age_lower == 0
|
||||
ageData = "Age #{teacher.teaches_age_upper} and younger"
|
||||
else if teacher.teaches_age_upper == 0
|
||||
ageData = "Ages #{teacher.teaches_age_lower} and up"
|
||||
teachesInfo.push(`<tr>
|
||||
<td>Ages</td>
|
||||
<td>{ageData}</td>
|
||||
</tr>`)
|
||||
|
||||
languages = teacher.languages.map((id) -> LanguageStore.display(id))
|
||||
languagesData = languages.join(', ')
|
||||
teachesInfo.push(`<tr>
|
||||
<td>Languages</td>
|
||||
<td>{languagesData}</td>
|
||||
</tr>`)
|
||||
`<div className="section teachers">
|
||||
<h3>{this.state.user.first_name} Teaches {this.editProfileLink('edit teaching', 'basics')}</h3>
|
||||
|
||||
<div className="section-content">
|
||||
<table className="jamtable" cellspacing="0" cellpadding="0" border="0">
|
||||
<tbody>
|
||||
{teachesInfo}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
musicianBio: (user, teacher) ->
|
||||
|
||||
if user.biography?
|
||||
musicianBio = user.biography
|
||||
else
|
||||
musicianBio = 'None specified.'
|
||||
|
||||
musicianBio = musicianBio.replace(/\n/g, "<br/>")
|
||||
|
||||
`<div className="section musician-bio">
|
||||
<h3>Musical Profile {this.editMusicProfileLink('update bio', '')}</h3>
|
||||
|
||||
<div className="section-content" dangerouslySetInnerHTML={{__html: musicianBio}}></div>
|
||||
</div>`
|
||||
|
||||
plays: (user, teacher) ->
|
||||
if user.profile.concert_count > 0
|
||||
gigs = "Has played #{profileUtils.gigMap[user.profile.concert_count]} concert gigs"
|
||||
else
|
||||
gigs = "Has played an unknown # of concert gigs"
|
||||
|
||||
if user.profile.studio_session_count > 0
|
||||
studioSessions = "Has played #{profileUtils.gigMap[user.profile.studio_session_count]} studio sessions"
|
||||
else
|
||||
studioSessions = "Has played an unknown # of studio sessions"
|
||||
|
||||
|
||||
gigTable = `<table className="jamtable giginfo">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{gigs}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{studioSessions}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>`
|
||||
|
||||
display_instruments = []
|
||||
for instrument in user.instruments
|
||||
|
||||
description = InstrumentStore.display(instrument.instrument_id)
|
||||
proficiency = instrument.proficiency_level;
|
||||
instrument_icon_url = context.JK.getInstrumentIcon256(instrument.instrument_id);
|
||||
display_instruments.push(`<div className="profile-instrument">
|
||||
<img src={instrument_icon_url} width="70" height="70"/><br />
|
||||
<span>{description}</span><br />
|
||||
<span className={proficiencyCssMap[proficiency]}>{proficiencyDescriptionMap[proficiency]}</span>
|
||||
</div>`)
|
||||
|
||||
`<div className="section plays">
|
||||
<h3>{this.state.user.first_name} Plays {this.editMusicProfileLink('update instruments', 'experience')}</h3>
|
||||
|
||||
<div className="section-content">
|
||||
{display_instruments}
|
||||
{gigTable}
|
||||
</div>
|
||||
<br className="clearall"/>
|
||||
</div>`
|
||||
|
||||
createPresence: (className, url, img) ->
|
||||
`<div className={className + "-presence logo online-presence-option"}>
|
||||
<a href={url}><img className="logo" src={img}/></a>
|
||||
</div>`
|
||||
|
||||
|
||||
onlinePresences: (user, teacher) ->
|
||||
online_presences = user.profile.online_presences
|
||||
|
||||
presences = []
|
||||
|
||||
if user.profile.website
|
||||
# make sure website is rooted
|
||||
website = user.profile.website
|
||||
if website.indexOf('http') == -1
|
||||
website = 'http://' + website
|
||||
presences.push(@createPresence("user-website", website, "/assets/content/website-logo.png"))
|
||||
|
||||
matches = profileUtils.soundCloudPresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("soundcloud", "http://www.soundcloud.com/#{matches[0].username}",
|
||||
"/assets/content/soundcloud-logo.png"))
|
||||
|
||||
matches = profileUtils.reverbNationPresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("reverbnation", "http://www.reverbnation.com/#{matches[0].username}",
|
||||
"/assets/content/reverbnation-logo.png"))
|
||||
|
||||
matches = profileUtils.bandCampPresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("bandcamp", 'http://' + matches[0].username + '.bandcamp.com/',
|
||||
"/assets/content/bandcamp-logo.png"))
|
||||
|
||||
matches = profileUtils.fandalismPresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("fandalism", 'http://www.fandalism.com/' + matches[0].username,
|
||||
"/assets/content/fandalism-logo.png"))
|
||||
|
||||
matches = profileUtils.youTubePresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("youtube", 'http://www.youtube.com/' + matches[0].username,
|
||||
"/assets/content/youtube-logo.png"))
|
||||
|
||||
matches = profileUtils.facebookPresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("facebook", 'http://www.facebook.com/' + matches[0].username,
|
||||
"/assets/content/facebook-logo.png"))
|
||||
|
||||
matches = profileUtils.twitterPresences(online_presences)
|
||||
if matches.length > 0
|
||||
presences.push(@createPresence("twitter", 'http://www.twitter.com/' + matches[0].username,
|
||||
"/assets/content/twitter-logo.png"))
|
||||
|
||||
if presences.length == 0
|
||||
presences = `<div className="no-online-presence">None specified</div>`
|
||||
|
||||
|
||||
`<div className="section plays">
|
||||
<h3>Online Presence {this.editMusicProfileLink('update presence', 'samples')}</h3>
|
||||
|
||||
<div className="section-content">
|
||||
{presences}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
about: () ->
|
||||
user = @state.user
|
||||
teacher = user.teacher
|
||||
|
||||
`<div className="about-block info-block">
|
||||
{this.sampleVideo(user, teacher)}
|
||||
|
||||
{this.teacherBio(user, teacher)}
|
||||
|
||||
{this.teachesInfo(user, teacher)}
|
||||
|
||||
{this.musicianBio(user, teacher)}
|
||||
|
||||
{this.plays(user, teacher)}
|
||||
|
||||
{this.onlinePresences(user, teacher)}
|
||||
</div>`
|
||||
|
||||
experiences: (title, attr, update, user, teacher) ->
|
||||
teachingExperiences = []
|
||||
|
||||
for teachingExperience in teacher['experiences_' + attr]
|
||||
years = ''
|
||||
if teachingExperience.start_year > 0
|
||||
if teachingExperience.end_year && teachingExperience.end_year > 0
|
||||
years = "#{teachingExperience.start_year} - #{teachingExperience.end_year}"
|
||||
else
|
||||
years = "#{teachingExperience.start_year} - Present"
|
||||
|
||||
teachingExperiences.push(`<div className="experience">
|
||||
<div className="years">{years}</div>
|
||||
<h4>{teachingExperience.name}</h4>
|
||||
|
||||
<div className="org">{teachingExperience.organization}</div>
|
||||
</div>`)
|
||||
|
||||
if update?
|
||||
updateLink = this.editProfileLink('update ' + update, 'experience')
|
||||
|
||||
if teachingExperiences.length == 0
|
||||
teachingExperiences = `<div>None specified</div>`
|
||||
`<div className="section teaching-experience">
|
||||
<h3>{title} {updateLink}</h3>
|
||||
|
||||
<div className="section-content">
|
||||
{teachingExperiences}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
sampleClicked: (e) ->
|
||||
e.preventDefault()
|
||||
context.JK.popExternalLink($(e.target).attr('href'))
|
||||
|
||||
|
||||
musicSamples: (user, teacher) ->
|
||||
performance_samples = user.profile.performance_samples
|
||||
|
||||
jamkazamSamples = []
|
||||
samples = profileUtils.jamkazamSamples(performance_samples);
|
||||
for sample in samples
|
||||
jamkazamSamples.push(`<a className="jamkazam-playable playable" href={"/recordings/" + sample.claimed_recording.id} onClick={this.sampleClicked}>{sample.claimed_recording.name}</a>`)
|
||||
|
||||
soundCloudSamples= []
|
||||
samples = profileUtils.soundCloudSamples(performance_samples);
|
||||
for sample in samples
|
||||
soundCloudSamples.push(`<a className="sound-cloud-playable playable" href={sample.url} onClick={this.sampleClicked}>{sample.description}</a>`)
|
||||
|
||||
youTubeSamples = []
|
||||
samples = profileUtils.youTubeSamples(performance_samples);
|
||||
for sample in samples
|
||||
youTubeSamples.push(`<a className="youtube-playable playable" href={sample.url} onClick={this.sampleClicked}>{sample.description}</a>`)
|
||||
|
||||
sampleJsx = []
|
||||
|
||||
if jamkazamSamples.length > 0
|
||||
sampleJsx.push(`<div className="jamkazam-samples logo performance-sample-option">
|
||||
<img className="logo" src="/assets/header/logo.png" />
|
||||
{jamkazamSamples}
|
||||
</div>`)
|
||||
|
||||
if soundCloudSamples.length > 0
|
||||
sampleJsx.push(`<div className="soundcloud-samples logo performance-sample-option">
|
||||
<img className="logo" src="/assets/content/soundcloud-logo.png" />
|
||||
{soundCloudSamples}
|
||||
</div>`)
|
||||
|
||||
if youTubeSamples.length > 0
|
||||
sampleJsx.push(`<div className="youtube-samples logo performance-sample-option">
|
||||
<img className="logo" src="/assets/content/youtube-logo.png" />
|
||||
{youTubeSamples}
|
||||
</div>`)
|
||||
|
||||
|
||||
`<div className="section samples">
|
||||
<h3>Performance Samples {this.editMusicProfileLink('update samples', 'samples')}</h3>
|
||||
|
||||
<div className="section-content">
|
||||
{sampleJsx}
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
experience: () ->
|
||||
user = @state.user
|
||||
teacher = user.teacher
|
||||
|
||||
`<div className="experience-block info-block">
|
||||
{this.experiences('Teaching Experience', 'teaching', 'experience', user, teacher)}
|
||||
|
||||
{this.experiences('Music Education', 'education', null, user, teacher)}
|
||||
|
||||
{this.experiences('Music Awards', 'award', null, user, teacher)}
|
||||
</div>`
|
||||
|
||||
samples: () ->
|
||||
user = @state.user
|
||||
teacher = user.teacher
|
||||
|
||||
`<div className="samples-block info-block">
|
||||
{this.musicSamples(user, teacher)}
|
||||
</div>`
|
||||
|
||||
ratings: () ->
|
||||
user = @state.user
|
||||
teacher = user.teacher
|
||||
|
||||
`<div className="ratings-block info-block">
|
||||
Coming Soon!
|
||||
</div>`
|
||||
|
||||
prices: () ->
|
||||
user = @state.user
|
||||
teacher = user.teacher
|
||||
|
||||
rows = []
|
||||
|
||||
for minutes in [30, 45, 60, 90, 120]
|
||||
lesson_price = teacher["price_per_lesson_#{minutes}_cents"]
|
||||
monthly_price = teacher["price_per_month_#{minutes}_cents"]
|
||||
duration_enabled = teacher["lesson_duration_#{minutes}"]
|
||||
|
||||
console.log("lesson_price", lesson_price)
|
||||
console.log("monthly_price", monthly_price)
|
||||
console.log("duration neabled", duration_enabled)
|
||||
if duration_enabled && teacher.prices_per_lesson && lesson_price? && lesson_price > 0
|
||||
lessonPriceFormatted = '$ ' + (lesson_price / 100).toFixed(2)
|
||||
else
|
||||
lessonPriceFormatted = 'N/A'
|
||||
|
||||
if duration_enabled && teacher.prices_per_month && monthly_price? && monthly_price > 0
|
||||
monthlyPriceFormatted = '$ ' + (monthly_price / 100).toFixed(2)
|
||||
else
|
||||
monthlyPriceFormatted = 'N/A'
|
||||
|
||||
rows.push(`<tr><td>{minutes + " Minutes"}</td><td>{lessonPriceFormatted}</td><td>{monthlyPriceFormatted}</td></tr>`)
|
||||
|
||||
`<div className="prices-block info-block">
|
||||
<h3>Lesson Prices {this.editProfileLink('update prices', 'pricing')}</h3>
|
||||
|
||||
<div className="section-content">
|
||||
<table className="jamtable price-table">
|
||||
<thead>
|
||||
<tr><th>LESSON LENGTH</th><th>PRICE PER LESSON</th><th>PRICE PER MONTH</th></tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{rows}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
mainContent: () ->
|
||||
if @state.selected == @TILE_ABOUT
|
||||
@about()
|
||||
else if @state.selected == @TILE_EXPERIENCE
|
||||
@experience()
|
||||
else if @state.selected == @TILE_SAMPLES
|
||||
@samples()
|
||||
else if @state.selected == @TILE_RATINGS
|
||||
@ratings()
|
||||
else if @state.selected == @TILE_PRICES
|
||||
@prices()
|
||||
|
||||
profileLeft: () ->
|
||||
`<div className="profile-about-left">
|
||||
<div className="left-content">
|
||||
<div className="location">
|
||||
<div className="city">{this.state.user.city}</div>
|
||||
<div className="state">{this.state.user.state}</div>
|
||||
<div className="country">{this.state.user.country}</div>
|
||||
<div className="age">{this.state.user.age} years old</div>
|
||||
</div>
|
||||
|
||||
<div className="activity">
|
||||
<div className="last-signed-in">Last Signed In:</div>
|
||||
<div>{"very recently"}</div>
|
||||
</div>
|
||||
|
||||
<div className="backgroundCheck">
|
||||
<div className="background-check">Background Check:</div>
|
||||
<div className="last-verified">last verified</div>
|
||||
<div className="last-verified-time">3 months ago</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
|
||||
selectionMade: (selection, e) ->
|
||||
e.preventDefault()
|
||||
|
||||
@setState({selected: selection})
|
||||
|
||||
render: () ->
|
||||
`<div className="content-body-scroller">
|
||||
if @state.user?
|
||||
avatar = context.JK.resolveAvatarUrl(@state.user.photo_url);
|
||||
if @state.user?.teacher?
|
||||
mainContent = @mainContent()
|
||||
profileLeft = @profileLeft()
|
||||
|
||||
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>`
|
||||
profileSelections = []
|
||||
|
||||
for tile, i in @TILES
|
||||
classes = classNames({last: i == @TILES.length - 1, active: @state.selected == tile})
|
||||
|
||||
profileSelections.push(`<div className="profile-tile"><a className={classes}
|
||||
onClick={this.selectionMade.bind(this, tile)}>{tile}</a>
|
||||
</div>`)
|
||||
|
||||
`<div className="content-body-scroller">
|
||||
<div className="profile-header profile-head">
|
||||
|
||||
<div className="user-header">
|
||||
<h2 id="username"></h2>
|
||||
{editButton}
|
||||
</div>
|
||||
|
||||
{actionButtons}
|
||||
<br clear="all"/><br />
|
||||
|
||||
<div className="profile-photo">
|
||||
<div className="avatar-profile">
|
||||
<img width="200" height="200" src={avatar}/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="profile-nav">
|
||||
{profileSelections}
|
||||
</div>
|
||||
<div className="clearall"></div>
|
||||
</div>
|
||||
|
||||
<div className="profile-body">
|
||||
<div className="profile-wrapper">
|
||||
{profileLeft}
|
||||
<div className="main-content">
|
||||
{mainContent}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -70,7 +70,7 @@ rest = window.JK.Rest()
|
|||
<input className="years-playing-experience" name="years_playing" ref="years_playing_experience" type="number" min="0" max="99" value={this.state.years_playing} onChange={this.handleTextChange} placeholder="Select" />
|
||||
</div>
|
||||
</div>
|
||||
<TeacherSetupNav handleNav={this.handleNav}/>
|
||||
<TeacherSetupNav hideBack={true} handleNav={this.handleNav}/>
|
||||
</div>`
|
||||
|
||||
})
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
context = window
|
||||
teacherActions = window.JK.Actions.Teacher
|
||||
SessionActions = @SessionActions
|
||||
ProfileActions = @ProfileActions
|
||||
|
||||
@TeacherSetupNav = React.createClass({
|
||||
|
||||
|
|
@ -9,19 +10,32 @@ SessionActions = @SessionActions
|
|||
console.log("navBack this.props", this.state, this.props)
|
||||
this.props.handleNav({direction: "back"})
|
||||
|
||||
navCancel: (e) ->
|
||||
ProfileActions.cancelTeacherEdit()
|
||||
|
||||
navNext: (e) ->
|
||||
e.preventDefault()
|
||||
console.log("navNext this.props", this.state, this.props)
|
||||
this.props.handleNav({direction: "next"})
|
||||
|
||||
render: () ->
|
||||
#console.log("SetupNav: this.props", this.state, this.ref, this.props.handleNav)
|
||||
if window.ProfileStore.solo
|
||||
saveText = 'SAVE'
|
||||
else
|
||||
saveText = 'SAVE & NEXT'
|
||||
|
||||
if !this.props.hideBack && !window.ProfileStore.solo
|
||||
back = `<a className="nav-button button-grey" onClick={this.navBack}>
|
||||
BACK
|
||||
</a>`
|
||||
|
||||
`<div className="TeacherSetupNav right">
|
||||
<a className="nav-button button-grey" onClick={this.navBack}>
|
||||
BACK
|
||||
<a className="nav-button button-grey" onClick={this.navCancel}>
|
||||
CANCEL
|
||||
</a>
|
||||
{back}
|
||||
<a className="nav-button button-orange" onClick={this.navNext}>
|
||||
NEXT
|
||||
{saveText}
|
||||
</a>
|
||||
</div>`
|
||||
})
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
context = window
|
||||
|
||||
@GenreActions = Reflux.createActions({
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
context = window
|
||||
|
||||
@ProfileActions = Reflux.createActions({
|
||||
|
||||
startTeacherEdit: {}
|
||||
cancelTeacherEdit: {}
|
||||
doneTeacherEdit: {}
|
||||
startProfileEdit: {}
|
||||
cancelProfileEdit: {}
|
||||
doneProfileEdit: {}
|
||||
editProfileNext: {}
|
||||
})
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
context = window
|
||||
|
||||
@SubjectActions = Reflux.createActions({
|
||||
|
||||
})
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
|
||||
@GenreStore = Reflux.createStore(
|
||||
{
|
||||
listenables: @GenreActions
|
||||
genres: []
|
||||
genresLookup: {}
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
onAppInit: (@app) ->
|
||||
rest.getGenres().done (genres) =>
|
||||
@genres = genres
|
||||
for genre in genres
|
||||
@genresLookup[genre.id] = genre.description
|
||||
|
||||
@trigger(@genres)
|
||||
|
||||
display: (id) ->
|
||||
@genresLookup[id]
|
||||
}
|
||||
)
|
||||
|
|
@ -6,6 +6,7 @@ logger = context.JK.logger
|
|||
{
|
||||
listenables: @InstrumentActions
|
||||
instruments: []
|
||||
instrumentLookup: {}
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
|
|
@ -14,7 +15,12 @@ logger = context.JK.logger
|
|||
onAppInit: (@app) ->
|
||||
rest.getInstruments().done (instruments) =>
|
||||
@instruments = instruments
|
||||
for instrument in instruments
|
||||
@instrumentLookup[instrument.id] = instrument.description
|
||||
|
||||
@trigger(@instruments)
|
||||
|
||||
display: (id) ->
|
||||
@instrumentLookup[id]
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ logger = context.JK.logger
|
|||
{
|
||||
listenables: @LanguageActions
|
||||
languages: []
|
||||
languageLookup: {}
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
|
|
@ -14,7 +15,11 @@ logger = context.JK.logger
|
|||
onAppInit: (@app) ->
|
||||
rest.getLanguages().done (languages) =>
|
||||
@languages = languages
|
||||
for language in @languages
|
||||
@languageLookup[language.id] = language.description
|
||||
@trigger(@languages)
|
||||
|
||||
display: (id) ->
|
||||
@languageLookup[id]
|
||||
}
|
||||
)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
|
||||
ProfileActions = @ProfileActions
|
||||
|
||||
@ProfileStore = Reflux.createStore(
|
||||
{
|
||||
listenables: ProfileActions
|
||||
|
||||
returnNav: null
|
||||
solo: false
|
||||
|
||||
# step can be:
|
||||
# introduction
|
||||
# basics
|
||||
# pricing
|
||||
# experience
|
||||
onStartProfileEdit: (step, solo) ->
|
||||
|
||||
if !step?
|
||||
step = ''
|
||||
|
||||
if step != '' && step != 'samples' && step != 'interests' && step != 'experience'
|
||||
alert("invalid step: " + step)
|
||||
return
|
||||
|
||||
@solo = solo
|
||||
@returnNav = window.location.href
|
||||
|
||||
window.location = '/client#/account/profile/' + step
|
||||
|
||||
onDoneProfileEdit: () ->
|
||||
|
||||
if @returnNav
|
||||
window.location = @returnNav
|
||||
@returnNav = null
|
||||
else
|
||||
window.location = "/client#/profile/" + context.JK.currentUserId;
|
||||
|
||||
@solo = false
|
||||
|
||||
onCancelProfileEdit: () ->
|
||||
|
||||
if @returnNav
|
||||
window.location = @returnNav
|
||||
@returnNav = null
|
||||
else
|
||||
window.location = '/client#/profile/' + context.JK.currentUserId
|
||||
@solo = false
|
||||
|
||||
onStartTeacherEdit: (step, solo) ->
|
||||
|
||||
if !step?
|
||||
step = 'introduction'
|
||||
|
||||
if step != 'introduction' && step != 'basics' && step != 'pricing' && step != 'experience'
|
||||
alert("invalid step: " + step)
|
||||
return
|
||||
|
||||
@solo = solo
|
||||
@returnNav = window.location.href
|
||||
|
||||
window.location = '/client#/teachers/setup/' + step
|
||||
|
||||
onDoneTeacherEdit: () ->
|
||||
|
||||
if @solo
|
||||
if @returnNav
|
||||
window.location = @returnNav
|
||||
@returnNav = null
|
||||
else
|
||||
window.location = '/client#/home'
|
||||
|
||||
@solo = false
|
||||
|
||||
onCancelTeacherEdit: () ->
|
||||
|
||||
if @returnNav
|
||||
window.location = @returnNav
|
||||
@returnNav = null
|
||||
else
|
||||
window.location = '/client#/home'
|
||||
|
||||
@solo = false
|
||||
|
||||
onEditProfileNext: (step) ->
|
||||
|
||||
if @solo
|
||||
if @returnNav
|
||||
window.location = @returnNav
|
||||
@returnNav = null
|
||||
else
|
||||
window.location = '/client#/home'
|
||||
@solo = false
|
||||
else
|
||||
context.location = "/client#/account/profile/" + step
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
$ = jQuery
|
||||
context = window
|
||||
logger = context.JK.logger
|
||||
|
||||
@SubjectStore = Reflux.createStore(
|
||||
{
|
||||
listenables: @SubjectActions
|
||||
subjects: []
|
||||
subjectLookup: {}
|
||||
|
||||
init: ->
|
||||
# Register with the app store to get @app
|
||||
this.listenTo(context.AppStore, this.onAppInit)
|
||||
|
||||
onAppInit: (@app) ->
|
||||
rest.getSubjects().done (subjects) =>
|
||||
@subjects = subjects
|
||||
for subject in subjects
|
||||
@subjectLookup[subject.id] = subject.description
|
||||
|
||||
@trigger(@subjects)
|
||||
|
||||
display: (id) ->
|
||||
@subjectLookup[id]
|
||||
|
||||
}
|
||||
)
|
||||
|
|
@ -56,9 +56,12 @@ EVENTS = context.JK.EVENTS
|
|||
.done((savedTeacher) =>
|
||||
logger.debug("SAVED TEACHER",savedTeacher)
|
||||
this.trigger({teacher: savedTeacher})
|
||||
if instructions.navTo?
|
||||
logger.debug("NAVIGATING TO",instructions.navTo)
|
||||
window.location = instructions.navTo
|
||||
if ProfileStore.solo
|
||||
ProfileActions.doneTeacherEdit()
|
||||
else
|
||||
if instructions.navTo?
|
||||
logger.debug("NAVIGATING TO",instructions.navTo)
|
||||
window.location = instructions.navTo
|
||||
).fail((jqXHR, textStatus, errorMessage) =>
|
||||
logger.debug("FAILED",jqXHR, textStatus, errorMessage)
|
||||
#errors = JSON.parse(jqXHR.responseText)
|
||||
|
|
|
|||
|
|
@ -205,7 +205,7 @@ mixins.push(Reflux.listenTo(VideoStore, 'onVideoStateChanged'))
|
|||
componentWillUpdate: (nextProps, nextState) ->
|
||||
# protect against non-video clients pointed at video-enabled server from getting into a session
|
||||
|
||||
@logger.debug("webcam devices", nextState.deviceNames, @state.deviceNames)
|
||||
#@logger.debug("webcam devices", nextState.deviceNames, @state.deviceNames)
|
||||
|
||||
if !@initialScan?
|
||||
@initialScan = true
|
||||
|
|
@ -352,7 +352,7 @@ mixins.push(Reflux.listenTo(VideoStore, 'onVideoStateChanged'))
|
|||
webcamName = null
|
||||
# protect against non-video clients pointed at video-enabled server from getting into a session
|
||||
webcam = state.currentDevice
|
||||
@logger.debug("currently selected video device", webcam)
|
||||
#@logger.debug("currently selected video device", webcam)
|
||||
if (webcam? && Object.keys(webcam).length>0)
|
||||
webcamName = Object.keys(webcam)[0]
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,165 @@
|
|||
@import "client/common";
|
||||
|
||||
#teacher-profile {
|
||||
div[data-react-class="TeacherProfile"] {
|
||||
height:100%;
|
||||
}
|
||||
|
||||
.profile-nav a {
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
height: 100%;
|
||||
width: 98%;
|
||||
margin: 0 auto;
|
||||
padding: 57px 0 0 0;
|
||||
@include border-box_sizing;
|
||||
}
|
||||
|
||||
.profile-tile {
|
||||
width:20%;
|
||||
float:left;
|
||||
@include border-box_sizing;
|
||||
height:87px;
|
||||
position:relative;
|
||||
}
|
||||
.profile-about-left {
|
||||
@include border-box_sizing;
|
||||
width:16%;
|
||||
}
|
||||
.profile-body {
|
||||
padding-top:159px;
|
||||
}
|
||||
.left-content {
|
||||
width:88px;
|
||||
text-align:center;
|
||||
}
|
||||
.profile-photo {
|
||||
width:16%;
|
||||
@include border-box_sizing;
|
||||
}
|
||||
.profile-nav {
|
||||
margin:0;
|
||||
width:84%;
|
||||
}
|
||||
.profile-wrapper {
|
||||
padding:10px 20px
|
||||
}
|
||||
|
||||
.main-content {
|
||||
float:left;
|
||||
@include border-box_sizing;
|
||||
width:84%;
|
||||
}
|
||||
|
||||
.edit-link {
|
||||
font-size:12px;
|
||||
margin-left:11px;
|
||||
font-weight:normal;
|
||||
}
|
||||
.activity {
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
.backgroundCheck {
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
.introductory-video {
|
||||
float:right;
|
||||
width:40%;
|
||||
position:relative;
|
||||
}
|
||||
|
||||
.info-block {
|
||||
h3 {
|
||||
font-weight:bold;
|
||||
font-size:18px;
|
||||
margin-bottom:10px;
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom:40px;
|
||||
&.teachers {
|
||||
clear:both;
|
||||
}
|
||||
}
|
||||
|
||||
table.jamtable {
|
||||
font-size:14px;
|
||||
width:100%;
|
||||
|
||||
&.price-table {
|
||||
max-width:600px;
|
||||
|
||||
|
||||
th:nth-child(2) {
|
||||
text-align:right;
|
||||
}
|
||||
th:nth-child(3) {
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
td:nth-child(2) {
|
||||
text-align:right;
|
||||
}
|
||||
td:nth-child(3) {
|
||||
text-align:right;
|
||||
}
|
||||
}
|
||||
&.giginfo {
|
||||
top: 10px;
|
||||
position: relative;
|
||||
min-width: 200px;
|
||||
width:auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.online-presence-option, .performance-sample-option {
|
||||
display:block;
|
||||
vertical-align:middle;
|
||||
&.no-online-presence {
|
||||
display:block;
|
||||
}
|
||||
float:left;
|
||||
margin-right:20px;
|
||||
margin-top:20px;
|
||||
}
|
||||
|
||||
.performance-sample-option {
|
||||
margin-right:40px;
|
||||
a {
|
||||
display:block;
|
||||
}
|
||||
img {
|
||||
margin-bottom:5px;
|
||||
}
|
||||
}
|
||||
|
||||
.video-container {
|
||||
width: 100%;
|
||||
padding-bottom: 53.33%;
|
||||
|
||||
}
|
||||
|
||||
.profile-instrument {
|
||||
float: left;
|
||||
margin-right: 15px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.experience {
|
||||
width:600px;
|
||||
margin-bottom:20px;
|
||||
h4 {
|
||||
font-size:14px;
|
||||
font-weight:bold;
|
||||
margin-bottom:6px;
|
||||
color:white;
|
||||
}
|
||||
.org {
|
||||
font-size:14px;
|
||||
}
|
||||
.years {float:right}
|
||||
}
|
||||
}
|
||||
|
|
@ -77,6 +77,10 @@ body.web.individual_jamtrack {
|
|||
}
|
||||
}
|
||||
|
||||
.edit-link {
|
||||
font-size:12px;
|
||||
}
|
||||
|
||||
.video-container {
|
||||
width: 420px;
|
||||
padding-bottom: 53.33%;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
class ApiTeachersController < ApiController
|
||||
|
||||
before_filter :api_signed_in_user, :except => [:index, :show]
|
||||
before_filter :api_signed_in_user, :except => [:index, :detail]
|
||||
before_filter :auth_teacher, :only => [:update, :delete]
|
||||
before_filter :auth_user, :only => [:create, :update]
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ ApiUsersController < ApiController
|
|||
def show
|
||||
@user=lookup_user
|
||||
|
||||
@show_teacher = params[:show_teacher]
|
||||
@show_profile = params[:show_profile]
|
||||
|
||||
respond_with @user, responder: ApiResponder, :status => 200
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -35,24 +35,24 @@ attributes :id,
|
|||
:errors
|
||||
|
||||
|
||||
node :instruments do
|
||||
@teacher.instruments.collect{|o|o.id}
|
||||
node :instruments do |teacher|
|
||||
teacher.instruments.collect{|o|o.id}
|
||||
end
|
||||
|
||||
node :subjects do
|
||||
@teacher.subjects.collect{|o|o.id}
|
||||
node :subjects do |teacher|
|
||||
teacher.subjects.collect{|o|o.id}
|
||||
end
|
||||
|
||||
node :genres do
|
||||
@teacher.genres.collect{|o|o.id}
|
||||
node :genres do |teacher|
|
||||
teacher.genres.collect{|o|o.id}
|
||||
end
|
||||
|
||||
node :languages do
|
||||
@teacher.languages.collect{|o|o.id}
|
||||
node :languages do |teacher|
|
||||
teacher.languages.collect{|o|o.id}
|
||||
end
|
||||
|
||||
node :experiences_teaching do
|
||||
@teacher.experiences_teaching.collect do |o|
|
||||
node :experiences_teaching do |teacher|
|
||||
teacher.experiences_teaching.collect do |o|
|
||||
{
|
||||
name: o.name,
|
||||
experience_type: o.experience_type,
|
||||
|
|
@ -63,8 +63,8 @@ node :experiences_teaching do
|
|||
end # collect
|
||||
end
|
||||
|
||||
node :experiences_education do
|
||||
@teacher.experiences_education.collect do |o|
|
||||
node :experiences_education do |teacher|
|
||||
teacher.experiences_education.collect do |o|
|
||||
{
|
||||
name: o.name,
|
||||
experience_type: o.experience_type,
|
||||
|
|
@ -75,8 +75,8 @@ node :experiences_education do
|
|||
end # collect
|
||||
end
|
||||
|
||||
node :experiences_award do
|
||||
@teacher.experiences_award.collect do |o|
|
||||
node :experiences_award do |teacher|
|
||||
teacher.experiences_award.collect do |o|
|
||||
{
|
||||
name: o.name,
|
||||
experience_type: o.experience_type,
|
||||
|
|
|
|||
|
|
@ -9,6 +9,19 @@ 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)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if @show_profile
|
||||
node :profile do
|
||||
partial("api_users/profile_show", :object => @user)
|
||||
end
|
||||
end
|
||||
|
||||
# give back more info if the user being fetched is yourself
|
||||
if @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
|
||||
|
|
@ -115,3 +128,4 @@ end
|
|||
node :last_jam_audio_latency do |user|
|
||||
user.last_jam_audio_latency.round if user.last_jam_audio_latency
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@
|
|||
var accountProfileInterests = new JK.AccountProfileInterests(JK.app);
|
||||
accountProfileInterests.initialize();
|
||||
|
||||
var accountProfileSamples = new JK.AccountProfileSamples(JK.app, $(".account-profile-samples"), api.getUserProfile, api.updateUser)
|
||||
var accountProfileSamples = new JK.AccountProfileSamples(JK.app, $(".screen.account-profile-samples"), api.getUserProfile, api.updateUser)
|
||||
accountProfileSamples.initialize();
|
||||
|
||||
var accountAudioProfile = new JK.AccountAudioProfile(JK.app);
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#teacher-profile.screen.secondary layout="screen" layout-id="teachers/profile" layout-arg="id"
|
||||
#teacher-profile.screen.secondary.no-login-required layout="screen" layout-id="profile/teacher" layout-arg="id"
|
||||
.content-head
|
||||
.content-icon
|
||||
= image_tag "content/icon_profile.png", :size => "19x19"
|
||||
|
|
@ -6,6 +6,5 @@
|
|||
| teacher profile
|
||||
= render "screen_navigation"
|
||||
.content-body
|
||||
.content-body-scroller
|
||||
= react_component 'TeacherProfile', {}
|
||||
= react_component 'TeacherProfile', {}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue