VRFS-3359 : Navigation and additional styling/markup.

This commit is contained in:
Steven Miers 2015-08-12 13:03:32 -05:00
parent 09b7f44a91
commit fee62c225b
20 changed files with 372 additions and 178 deletions

View File

@ -3,29 +3,21 @@ teacherActions = window.JK.Actions.Teacher
logger = context.JK.logger
rest = window.JK.Rest()
@TeacherProfile = React.createClass({
@TeacherProfileBasics = React.createClass({
mixins: [
@TeacherMixin,
@TeacherProfileMixin,
Reflux.listenTo(@AppStore,"onAppInit"),
Reflux.listenTo(TeacherStore, "onTeacherStateChanged")
]
setTeacherError: () ->
screenName: () ->
"basics"
getInitialState: () ->
{}
beforeShow: (data) ->
logger.debug("TeacherProfile beforeShow", data, data.d)
if data? && data.d?
@teacherId = data.d
teacherActions.load.trigger({teacher_id: @teacherId})
else
teacherActions.load.trigger({})
onTeacherStateChanged: (changes) ->
$root = jQuery(this.getDOMNode())
logger.debug("onTeacherStateChanged", changes, changes.errors?, changes.errors)
@ -62,9 +54,9 @@ rest = window.JK.Rest()
});
logger.debug("capturedFormState", this.state, changes)
handleSave: (e) ->
logger.debug("HANDLESAVE: ", this.state, this, e)
teacherActions.change.trigger(this.state)
handleNav: (e) ->
logger.debug("handleNav: ", this.state, this, e)
teacherActions.change.trigger(this.state, e)
render: () ->
logger.debug("RENDERING", this.props, this.state)
@ -92,7 +84,7 @@ rest = window.JK.Rest()
<input className="years-playing-experience" type="number" min="0" max="99" value={this.state.years_playing} onChange={this.captureFormState} placeholder="Select" />
</div>
</div>
<TeacherSetupNav handleSave={this.handleSave}/>
<TeacherSetupNav handleNav={this.handleNav}/>
</div>
`

View File

@ -5,29 +5,42 @@ rest = window.JK.Rest()
@TeacherSetupBasics = React.createClass({
mixins: [
@TeacherMixin,
@TeacherSetupMixin,
Reflux.listenTo(@AppStore,"onAppInit"),
Reflux.listenTo(TeacherStore, "onTeacherStateChanged")
]
setTeacherError: () ->
# onAppInit: (app) ->
# @app=app
# logger.debug("TeacherSetupBasics onAppInit", @app, document.referrer)
# screenBindings = {
# 'beforeShow': @beforeShow
# }
# logger.debug("Binding to: teachers/setup_basics")
# @app.bindScreen("teachers/setup_basics", screenBindings)
# beforeShow: (data) ->
# logger.debug("TeacherSetupBasics beforeShow", data, data.d)
# if data? && data.d?
# @teacherId = data.d
# teacherActions.load.trigger({teacher_id: @teacherId})
# else
# teacherActions.load.trigger({})
setTeacherError: () ->
getInitialState: () ->
{}
screenName: () ->
"basics"
onTeacherStateChanged: (changes) ->
$root = jQuery(this.getDOMNode())
logger.debug("onTeacherStateChanged", changes, changes.errors?, changes.errors)
$(".error-text", $root).remove()
$(".input-error", $root).removeClass("input-error")
if changes.errors?
for k,v of changes.errors
logger.debug("error", k, v)
teacherField = $root.find(".teacher-field[name='#{k}']")
teacherField.append("<div class='error-text'>#{v.join()}</div>")
$("input", teacherField).addClass("input-error")
else
logger.debug("onTeacherBasicsStateChanged", changes, changes.errors?, changes.errors)
unless this.handleErrors(changes)
teacher = changes.teacher
logger.debug("@teacher", teacher)
this.setState({
@ -48,13 +61,28 @@ rest = window.JK.Rest()
});
logger.debug("capturedFormState", this.state, changes)
handleSave: (e) ->
logger.debug("HANDLESAVE: ", this.state, this, e)
teacherActions.change.trigger(this.state)
handleNav: (e) ->
logger.debug("handleNav: ", this.state, this, e)
navTo = this.navDestination(e)
teacherActions.change.trigger(this.state, {navTo: navTo})
navDestination: (instructions) ->
navTo=null
if instructions?
logger.debug("handling instructions", instructions)
if instructions.direction=="cancel"
navTo = @teacherSetupSource()
else if instructions.direction=="back"
navTo = @teacherSetupDestination("introduction")
else if instructions.direction=="next"
navTo = @teacherSetupDestination("experience") # "/client#/teachers/setup/experience"
navTo
render: () ->
logger.debug("RENDERING", this.props, this.state)
`<div className="TeacherSetupComponent" >
logger.debug("RENDERING TeacherSetupBasics", this.props, this.state)
`<div className="TeacherSetupBasics TeacherSetupComponent" >
<div className="teacher-big-column left">
<div className="teacher-field" name="biography">
<label for="teacher-biography">Teacher Bio:</label>
@ -78,7 +106,7 @@ rest = window.JK.Rest()
<input className="years-playing-experience" type="number" min="0" max="99" value={this.state.years_playing} onChange={this.captureFormState} placeholder="Select" />
</div>
</div>
<TeacherSetupNav handleSave={this.handleSave}/>
<TeacherSetupNav handleNav={this.handleNav}/>
</div>
`

View File

@ -0,0 +1,107 @@
context = window
teacherActions = window.JK.Actions.Teacher
logger = context.JK.logger
rest = window.JK.Rest()
@TeacherSetupIntroduction = React.createClass({
mixins: [
@TeacherSetupMixin,
Reflux.listenTo(@AppStore,"onAppInit"),
Reflux.listenTo(TeacherStore, "onTeacherStateChanged")
]
setTeacherError: () ->
getInitialState: () ->
{}
screenName: () ->
"introduction"
navDestination: (instructions) ->
navTo=null
if instructions?
logger.debug("handling instructions", instructions)
if instructions.direction=="cancel" || instructions.direction=="back"
navTo = @teacherSetupSource()
else if instructions.direction=="next"
logger.debug("redireing to basics")
navTo = @teacherSetupDestination('basics')
navTo
# # onTeacherStateChanged: (changes) ->
# $root = jQuery(this.getDOMNode())
# logger.debug("onTeacherIntroStateChanged", changes, changes.errors?, changes.errors)
# unless this.handleErrors(changes)
# teacher = changes.teacher
# logger.debug("@teacher", teacher)
# this.setState({
# biography: teacher.biography,
# introductory_video: teacher.introductory_video,
# years_teaching: teacher.years_teaching,
# years_playing: teacher.years_playing,
# validate_introduction: true
# })
onTeacherStateChanged: (changes) ->
$root = jQuery(this.getDOMNode())
logger.debug("onTeacherIntroStateChanged", changes, changes.errors?, changes.errors)
unless this.handleErrors(changes)
teacher = changes.teacher
logger.debug("@teacher", teacher)
this.setState({
biography: teacher.biography,
introductory_video: teacher.introductory_video,
years_teaching: teacher.years_teaching,
years_playing: teacher.years_playing,
validate_introduction: true
})
captureFormState: (changes) ->
$root = jQuery(this.getDOMNode())
this.setState({
biography: $root.find(".teacher-biography").val(),
introductory_video: $root.find(".teacher-introductory-video").val(),
years_teaching: $root.find(".years-teaching-experience").val(),
years_playing: $root.find(".years-playing-experience").val()
});
logger.debug("capturedFormState", this.state, changes)
handleNav: (e) ->
logger.debug("handleNav: ", this.state, this, e)
navTo = this.navDestination(e)
teacherActions.change.trigger(this.state, {navTo: navTo})
render: () ->
logger.debug("RENDERING TeacherSetupIntroduction", this.props, this.state)
`<div className="TeacherSetupIntroduction TeacherSetupComponent" >
<div className="teacher-big-column left">
<div className="teacher-field" name="biography">
<label for="teacher-biography">Teacher Bio:</label>
<textarea className="teacher-biography" rows="12" value={this.state.biography} onChange={this.captureFormState} required/>
</div>
</div>
<div className="teacher-small-column left">
<div className="teacher-field" name="introductory_video">
<label for="teacher-introductory-video">Teacher Introductory Video:</label>
<input className="teacher-introductory-video youtube-video" type="url" maxLength="1024" value={this.state.introductory_video} onChange={this.captureFormState} required/>
<em>(enter YouTube URL)</em>
</div>
<div className="teacher-field" name="years_teaching">
<label for="years-teaching-experience">Years Teaching Experience:</label>
<input className="years-teaching-experience" type="number" min="0" max="99" value={this.state.years_teaching} onChange={this.captureFormState} placeholder="Select" />
</div>
<div className="teacher-field" name="years_playing">
<label for="teacher-playing-experience">Years Playing Experience:</label>
<input className="years-playing-experience" type="number" min="0" max="99" value={this.state.years_playing} onChange={this.captureFormState} placeholder="Select" />
</div>
</div>
<TeacherSetupNav handleNav={this.handleNav}/>
</div>
`
})

View File

@ -1,19 +1,20 @@
context = window
teacherActions = window.JK.Actions.Teacher
SessionActions = @SessionActions
@TeacherSetupNav = React.createClass({
navPrevious: (e) ->
e.preventDefault();
this.props.handleNav({direction: "back"})
navNext: (e) ->
e.preventDefault()
console.log("navNext this.props", this.state, this.props)
this.props.handleSave()
this.props.handleNav({direction: "next"})
render: () ->
console.log("SetupNav: this.props", this.state, this.props, this.props.handleSave)
console.log("SetupNav: this.props", this.state, this.props, this.props.handleNav)
`<div className="TeacherSetupNav">
<a className="nav-button button-grey" onClick={this.navPrevious}>
BACK

View File

@ -2,7 +2,7 @@ context = window
@TeacherActions = Reflux.createActions({
load: {},
change: {}
change: {}
})
context.JK.Actions.Teacher = TeacherActions

View File

@ -1,14 +0,0 @@
context = window
teacherActions = window.JK.Actions.Teacher
@TeacherMixin = {
onAppInit: (app) ->
logger.debug("TeacherProfile onAppInit", app, document.referrer)
screenBindings = {
'beforeShow': @beforeShow
}
app.bindScreen('teachers/setup/introduction', screenBindings)
}

View File

@ -0,0 +1,25 @@
context = window
teacherActions = window.JK.Actions.Teacher
@TeacherProfileMixin = {
onAppInit: (app) ->
logger.debug("TeacherProfile onAppInit", app, document.referrer)
screenBindings = {
'beforeShow': @beforeShow
}
logger.debug("Binding setup to: teachers/setup/#{@screenName()}")
app.bindScreen("teachers/profile/#{@screenName()}", screenBindings)
beforeShow: (data) ->
logger.debug("TeacherProfile beforeShow", data, data.d)
if data? && data.d?
@teacherId = data.d
teacherActions.load.trigger({teacher_id: @teacherId})
else
teacherActions.load.trigger({})
}

View File

@ -0,0 +1,62 @@
context = window
teacherActions = window.JK.Actions.Teacher
@TeacherSetupMixin = {
onAppInit: (app) ->
@app=app
logger.debug("TeacherSetupIntroduction onAppInit", @app, document.referrer)
screenBindings = {
'beforeShow': @beforeShow
}
logger.debug("Binding to: teachers/setup/#{@screenName()}")
@app.bindScreen("teachers/setup/#{@screenName()}", screenBindings)
beforeShow: (data) ->
logger.debug("TeacherSetupIntroduction beforeShow", data, data.d, window.location.search, window.location, document, document.referrer)
if data? && data.d?
@teacherId = data.d
teacherActions.load.trigger({teacher_id: @teacherId})
else
teacherActions.load.trigger({})
# TODO: Determine who started us and store, so
# we can return there in case of cancel, or being
# done. For now, teacherSetupSource() will return
# a default location:
@postmark = null
# params = this.getParams()
# @postmark = params.p
# logger.debug("Postmark: ", @postmark)
handleErrors: (changes) ->
$root = jQuery(this.getDOMNode())
if changes.errors?
for k,v of changes.errors
logger.debug("error", k, v)
teacherField = $root.find(".teacher-field[name='#{k}']")
teacherField.append("<div class='error-text'>#{v.join()}</div>")
$("input", teacherField).addClass("input-error")
changes.errors?
getParams:() =>
params = {}
q = window.location.href.split("?")[1]
if q?
q = q.split('#')[0]
raw_vars = q.split("&")
for v in raw_vars
[key, val] = v.split("=")
params[key] = decodeURIComponent(val)
params
teacherSetupSource:() ->
if @postmark? then @postmark else "/client#/account"
teacherSetupDestination:(phase) ->
pm = if @postmark? then "?p=#{encodeURIComponent(@postmark)}" else ""
# TODO: encode postmark as part of this URI when available:
"/client#/teachers/setup/#{phase}"
}

View File

@ -3,57 +3,55 @@ context = window
logger = context.JK.logger
rest = context.JK.Rest()
EVENTS = context.JK.EVENTS
@teacherActions = window.JK.Actions.Teacher
@TeacherStore = Reflux.createStore({
listenables: @teacherActions
teacher: null
TeacherActions = @TeacherActions
init: ->
# Register with the app store to get @app
this.listenTo(context.AppStore, this.onAppInit)
this.listenTo(context.TeacherActions.load, this.onLoadTeacher)
this.listenTo(context.TeacherActions.change, this.onSaveTeacher)
@TeacherStore = Reflux.createStore(
{
listenables: TeacherActions
teacher: null
onAppInit: (app) ->
@app = app
init: ->
# Register with the app store to get @app
this.listenTo(context.AppStore, this.onAppInit)
this.listenTo(context.TeacherActions.load, this.onLoadTeacher)
this.listenTo(context.TeacherActions.change, this.onSaveTeacher)
onLoadTeacher: (options) ->
logger.debug("onLoadTeacher", options)
if !options?
throw new Error('@teacher must be specified')
rest.getTeacher(options)
.done((savedTeacher) =>
logger.debug("LOADING TEACHER",savedTeacher)
this.trigger({teacher: savedTeacher}))
.fail((jqXHR, textStatus, errorMessage) =>
logger.debug("FAILED",jqXHR, textStatus, errorMessage)
if (jqXHR.status==404)
this.trigger({teacher: {}})
else
context.JK.app.ajaxError(jqXHR, textStatus, errorMessage)
)
onAppInit: (app) ->
@app = app
onSaveTeacher: (teacher, instructions) ->
logger.debug("onSaveTeacher", teacher, instructions)
rest.updateTeacher(teacher)
.done((savedTeacher) =>
logger.debug("SAVED TEACHER",savedTeacher)
this.trigger({teacher: savedTeacher})
if instructions.navTo?
window.location.href = instructions.navTo
).fail((jqXHR, textStatus, errorMessage) =>
logger.debug("FAILED",jqXHR, textStatus, errorMessage)
#errors = JSON.parse(jqXHR.responseText)
onLoadTeacher: (options) ->
logger.debug("onLoadTeacher", options)
if !options?
throw new Error('@teacher must be specified')
rest.getTeacher(options)
.done((savedTeacher) =>
logger.debug("LOADING TEACHER",savedTeacher)
this.trigger({teacher: savedTeacher}))
.fail((jqXHR, textStatus, errorMessage) =>
logger.debug("FAILED",jqXHR, textStatus, errorMessage)
if (jqXHR.status==404)
this.trigger({teacher: {}})
else
context.JK.app.ajaxError(jqXHR, textStatus, errorMessage)
)
onSaveTeacher: (teacher) ->
logger.debug("onSaveTeacher", teacher)
rest.updateTeacher(teacher)
.done((savedTeacher) =>
logger.debug("SAVED TEACHER",savedTeacher)
this.trigger({teacher: savedTeacher}))
.fail((jqXHR, textStatus, errorMessage) =>
logger.debug("FAILED",jqXHR, textStatus, errorMessage)
#errors = JSON.parse(jqXHR.responseText)
if (jqXHR.status==422)
logger.debug("FAILED422",jqXHR.responseJSON.errors)
this.trigger({errors: jqXHR.responseJSON.errors})
else
context.JK.app.ajaxError(jqXHR, textStatus, errorMessage)
)
if (jqXHR.status==422)
logger.debug("FAILED422",jqXHR.responseJSON.errors)
this.trigger({errors: jqXHR.responseJSON.errors})
else
context.JK.app.ajaxError(textStatus)
)
}
)

View File

@ -1,9 +1,23 @@
@import "client/common.css.scss";
@import "client/screen_common.css.scss";
.teacher-setup {
font-family: Raleway, Arial, Helvetica, verdana, arial, sans-serif;
.teacher-setup-form {
padding: 1em;
.error-text {
display: block;
background-color: #600;
color: #f00;
}
.teacher-small-column {
@extend .w35;
}
.teacher-big-column {
@extend .w65;
}
.teacher-field {
padding: 1em;
@include border_box_sizing;
@ -44,6 +58,11 @@
font-size: 1.05em;
}
.TeacherSetupNav {
clear: both;
float: right;
}
label.strong-label {
font-weight: bold;
font-size: 1.1em;

View File

@ -37,11 +37,10 @@
<%= render "bandProfile" %>
<%= render "band_setup" %>
<%= render "band_setup_photo" %>
<%= render "clients/teachers/about" %>
<%= render "clients/teachers/setup_introduction" %>
<%= render "clients/teachers/setup_basics" %>
<%= render "clients/teachers/setup_experience" %>
<%= render "clients/teachers/setup_pricing" %>
<%= render "clients/teachers/setup/introduction" %>
<%= render "clients/teachers/setup/basics" %>
<%= render "clients/teachers/setup/experience" %>
<%= render "clients/teachers/setup/pricing" %>
<%= render "users/feed_music_session_ajax" %>
<%= render "users/feed_recording_ajax" %>
<%= render "jamtrack_browse" %>

View File

@ -1,26 +0,0 @@
#teacher-setup-basics.screen.secondary layout="screen" layout-id="teachers/setup_basics" layout-arg="id"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-0.teacher-step.content-wrapper
h2 edit teacher: basics
= react_component 'TeacherProfile', {}
.field.teacher-field
label for="teacher-biography"
| Teacher Bio:
textarea.teacher-biography rows="8"
.field.teacher-field
label for="teacher-introductory-video"
| Band Name:
input.teacher-introductory-video type="text" maxlength="1024" value=""

View File

@ -1,24 +0,0 @@
#teacher-setup-experience.screen.secondary layout="screen" layout-id="teachers/setup_experience" layout-arg="id"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-0.teacher-step.content-wrapper
h2 edit teacher: basics
.field.teacher-field
label for="teacher-biography"
| Teacher Bio:
textarea.teacher-biography rows="8"
.field.teacher-field
label for="teacher-introductory-video"
| Band Name:
input.teacher-introductory-video type="text" maxlength="1024" value=""

View File

@ -1,24 +0,0 @@
#teacher-setup-pricing.screen.secondary layout="screen" layout-id="teachers/setup_pricing" layout-arg="id"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-0.teacher-step.content-wrapper
h2 edit teacher: basics
.field.teacher-field
label for="teacher-biography"
| Teacher Bio:
textarea.teacher-biography rows="8"
.field.teacher-field
label for="teacher-introductory-video"
| Band Name:
input.teacher-introductory-video type="text" maxlength="1024" value=""

View File

@ -0,0 +1,13 @@
#teacher-setup-basics.screen.secondary layout="screen" layout-id="teachers/profile/basics"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-0.teacher-step.content-wrapper
h2 edit teacher: basics
= react_component 'TeacherProfileBasics', {}

View File

@ -0,0 +1,13 @@
#teacher-setup-basics.teacher-setup.screen.secondary layout="screen" layout-id="teachers/setup/basics" layout-arg="query"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-1.teacher-step.content-wrapper
h2 edit teacher: basics
= react_component 'TeacherSetupBasics', {}

View File

@ -0,0 +1,13 @@
#teacher-setup-experience.screen.secondary layout="screen" layout-id="teachers/setup/experience"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-2.teacher-step.content-wrapper
h2 edit teacher: experience
//= react_component 'TeacherSetupExperience', {}

View File

@ -10,8 +10,7 @@
form.teacher-setup-form
.teacher-setup-step-0.teacher-step.content-wrapper
h2 edit teacher: introduction
= react_component 'TeacherProfile', {}
= react_component 'TeacherSetupIntroduction', {}
/ .teacher-column.left
/ label for="teacher-biography" Teacher Bio:
/ textarea.teacher-biography rows="12"

View File

@ -0,0 +1,13 @@
#teacher-setup-pricing.screen.secondary layout="screen" layout-id="teachers/setup/pricing"
.content-head
.content-icon
= image_tag "content/icon_bands.png", :size => "19x19"
h1#teacher-setup-title
| my account
= render "screen_navigation"
.content-body
.content-body-scroller
form.teacher-setup-form
.teacher-setup-step-3.teacher-step.content-wrapper
h2 edit teacher: pricing
//= react_component 'TeacherSetupPricing', {}