2020-04-29 20:51:50 +00:00
context = window
rest = window . JK . Rest ( )
logger = context . JK . logger
2020-05-06 19:42:52 +00:00
EVENTS = context . JK . EVENTS
SessionsActions = context . SessionsActions
AppStore = context . AppStore
MAX_MINUTES_SHOW_START = 15
2021-06-16 08:11:59 +00:00
SessionUtils = context . JK . SessionUtils
2020-04-29 20:51:50 +00:00
@FindSessionRow = React . createClass ( {
2021-06-16 08:11:59 +00:00
mixins: [ Reflux . listenTo ( @ LatencyStore , " onLatencyUpdate " ) ]
2020-05-06 19:42:52 +00:00
ui: null
getInitialState: () ->
2021-06-18 14:57:21 +00:00
{ rsvpToggle: false , openSlotToggle: false , userLatencies: [ ] , userLatenciesFailed: [ ] }
2020-05-06 19:42:52 +00:00
2020-04-29 20:51:50 +00:00
createInstrument: (participant) ->
instruments = [ ]
existingTracks = [ ]
2020-04-30 17:05:59 +00:00
for track in participant . tracks
2020-04-29 20:51:50 +00:00
if existingTracks . indexOf ( track . instrument_id ) < 0
existingTracks . push ( track . instrument_id )
inst = context . JK . getInstrumentIcon24 ( track . instrument_id )
instruments . push ( ` < img title = { context . JK . getInstrumentId ( track . instrument_id ) } hoveraction = " instrument " data - instrument - id = { track . instrument_id } src = { inst } width = " 24 " height = " 24 " / > ` )
instruments
2021-06-18 14:57:21 +00:00
createLatencyBadge: (userId) ->
2021-06-19 16:43:54 +00:00
2021-06-19 11:48:59 +00:00
latency = null
failed = false
if @ state . userLatencies . latencies
latency = @ state . userLatencies . latencies . find ( (userLatency) ->
userLatency . user_id == userId
)
if @ state . userLatenciesFailed
failed = @ state . userLatenciesFailed . find ( (failedId) ->
failedId == userId
)
2021-06-16 08:11:59 +00:00
2021-06-18 14:57:21 +00:00
` < LatencyBadge latency = { latency } failed = { failed } / > `
2021-06-16 08:11:59 +00:00
2020-04-29 20:51:50 +00:00
createInSessionUser: (participant) ->
2021-06-16 08:11:59 +00:00
instruments = @ createInstrument ( participant )
2021-06-18 14:57:21 +00:00
latencyBadge = @ createLatencyBadge ( participant . user . id )
2020-04-29 20:51:50 +00:00
2021-06-18 14:57:21 +00:00
` < HoverUser more = { null } user = { participant . user } instruments = { instruments } latencyBadge = { latencyBadge } / > `
2020-04-29 20:51:50 +00:00
2020-05-06 19:42:52 +00:00
createOpenSlot : (slot, isLast) ->
2020-04-29 20:51:50 +00:00
2020-04-30 17:05:59 +00:00
inst = context . JK . getInstrumentIcon24 ( slot . instrument_id ) ;
2020-04-29 20:51:50 +00:00
2020-04-30 17:05:59 +00:00
proficiency_desc = slot . proficiency_desc
if ! proficiency_desc
# this is to allow unstructured RSVPs to not specify proficiency_desc
proficiency_desc = " Any Skill Level "
2020-05-06 19:42:52 +00:00
toggle = @ state . openSlotToggle
2020-04-30 17:05:59 +00:00
if isLast
2020-05-06 19:42:52 +00:00
remainingStyles = { }
text = null
computedClass = " details-arrow "
if toggle
text = ' less '
computedClass += " arrow-up-orange "
else
text = ' more '
computedClass += " arrow-down-orange "
moreLinkHtml = ` < td > < span > < a onClick = { this . toggleOpenSlot . bind ( this ) } className = " rsvps more " > { text } < / a > < a className = { computedClass } > < / a > < / span > < / td > `
2020-04-30 17:05:59 +00:00
instrument_url = inst
instrument = slot . description
proficiency = proficiency_desc
more_link = moreLinkHtml
2020-05-06 19:42:52 +00:00
` < tr key = { slot . id } >
2020-04-29 20:51:50 +00:00
< td width = " 24 " >
2020-05-06 19:42:52 +00:00
< img src = { instrument_url } / >
2020-04-29 20:51:50 +00:00
< / td >
< td >
< div className = " instruments nowrap " > { instrument } ( { proficiency } ) < / div >
< / td >
< td > { more_link } & nbsp ; < / td >
< / tr > `
createRsvpUser: (user, session, isLast) ->
2020-04-30 17:05:59 +00:00
instruments = [ ]
2020-04-29 20:51:50 +00:00
if user . instrument_list
2020-04-30 17:05:59 +00:00
for instrument in user . instrument_list
2020-04-29 20:51:50 +00:00
inst = context . JK . getInstrumentIcon24 ( instrument . id ) ;
2020-04-30 17:05:59 +00:00
instruments . push ( ` < img title = { context . JK . getInstrumentId ( instrument . id ) } hoveraction = " instrument " data - instrument - id = { instrument . id } key = { instrument . id } src = { inst } width = " 24 " height = " 24 " / > ` )
2020-04-29 20:51:50 +00:00
moreLinkHtml = ' ' ;
if isLast
2020-05-06 19:42:52 +00:00
# false means hide, true means show
toggle = @ state . rsvpToggle
remainingStyles = { }
text = null
computedClass = " details-arrow "
if toggle
text = ' less '
computedClass += " arrow-up-orange "
else
text = ' more '
computedClass += " arrow-down-orange "
moreLinkHtml = ` < td > < span > < a onClick = { this . toggleRsvp . bind ( this ) } className = " rsvps more " > { text } < / a > < a className = { computedClass } > < / a > < / span > < / td > `
2021-06-18 14:57:21 +00:00
latencyBadge = @ createLatencyBadge ( user . id )
2020-05-06 19:42:52 +00:00
2021-06-18 14:57:21 +00:00
` < HoverUser user = { user } instruments = { instruments } more = { moreLinkHtml } latencyBadge = { latencyBadge } / > `
2020-04-29 20:51:50 +00:00
inSessionUsersHtml: (session) ->
inSessionUsers = [ ]
result = [ ]
2020-04-30 17:05:59 +00:00
if session . active_music_session && session . active_music_session . participants && session . active_music_session . participants . length > 0
for participant in session . active_music_session . participants
2020-04-29 20:51:50 +00:00
inSessionUsers . push ( participant . user . id ) ;
result . push ( @ createInSessionUser ( participant ) )
2020-05-06 19:42:52 +00:00
if result . length == 0
result = ` < span > Abandoned < / span > `
else
result = ` < table className = " musicians musicians-category " cellpadding = " 0 " cellspacing = " 0 " width = " 100% " >
{ result }
< / table > `
2020-04-29 20:51:50 +00:00
return [ result , inSessionUsers ]
2020-04-30 17:05:59 +00:00
createRsvpUsers : (session) ->
2020-04-29 20:51:50 +00:00
firstResults = [ ]
lastResults = [ ]
approvedRsvpCount = session . approved_rsvps . length
if session . approved_rsvps
first = session . approved_rsvps . slice ( 0 , 3 )
last = session . approved_rsvps . slice ( 3 )
2020-04-30 17:05:59 +00:00
for approved_rsvp in first
2020-05-06 19:42:52 +00:00
if approved_rsvp . id == session . user_id
continue
firstResults . push ( @ createRsvpUser ( approved_rsvp , session , approvedRsvpCount > 3 && i == 0 ) )
2020-04-30 17:05:59 +00:00
for approved_rsvp in last
2020-05-06 19:42:52 +00:00
if approved_rsvp . id == session . user_id
continue
2020-04-30 17:05:59 +00:00
lastResults . push ( @ createRsvpUser ( approved_rsvp , session , false ) )
2020-04-29 20:51:50 +00:00
[ firstResults , lastResults ]
2020-04-30 17:05:59 +00:00
createOpenSlots: (session) ->
2020-04-29 20:51:50 +00:00
firstResults = [ ]
remainingResults = [ ]
if session [ ' is_unstructured_rsvp? ' ]
firstResults . push ( @ createOpenSlot ( { description: ' Any Instrument ' } ) )
2020-05-06 19:42:52 +00:00
i = 0
2020-04-29 20:51:50 +00:00
if session . open_slots
2020-05-06 19:42:52 +00:00
2020-04-29 20:51:50 +00:00
openSlotCount = session . open_slots . length
2020-04-30 17:05:59 +00:00
for openSlot in session . open_slots
2020-04-29 20:51:50 +00:00
if i < 3
2020-04-30 17:05:59 +00:00
firstResults . push ( @ createOpenSlot ( openSlot , openSlotCount > 3 && i == 2 ) )
2020-04-29 20:51:50 +00:00
else
2020-04-30 17:05:59 +00:00
remainingResults . push ( @ createOpenSlot ( openSlot , false ) )
2020-05-06 19:42:52 +00:00
i ++
2020-04-29 20:51:50 +00:00
return [ firstResults , remainingResults ]
2020-05-06 19:42:52 +00:00
joinLink: (session, inSessionUsers) ->
#showJoinLink = session.musician_access
#if session.approved_rsvps
# for approved_rsvps in session.approved_rsvps
# # do not show the user in this section if he is already in the session
# if $.inArray(approved_rsvps.id, inSessionUsers) == -1
# if approved_rsvps.id == context.JK.currentUserId
# showJoinLink = true
# else
# showJoinLink = true
if @ props . mode == ' upcoming '
return null
2020-04-29 20:51:50 +00:00
2020-05-06 19:42:52 +00:00
joinText = ' Join '
if session . highlight
highlight = session . highlight
if highlight . updated
joinText = ' Ready! '
` < div className = " center " >
< a className = " join-link " onClick = { this . joinLinkClicked . bind ( this , session ) } >
< div className = " join-icon " > < / div >
< / a >
< div className = " join-link-text " > { joinText } < / div >
< / div > `
rsvpLink: (session) ->
pendingRsvpId = null
approvedRsvpId = null
hasInvitation = false
for pending_rsvp_request in session . pending_rsvp_requests
if pending_rsvp_request . user_id == context . JK . currentUserId
pendingRsvpId = pending_rsvp_request . id
break
for approved_rsvp in session . approved_rsvps
if approved_rsvp . id == context . JK . currentUserId
approvedRsvpId = approved_rsvp . rsvp_request_id
break
if session . invitations
for pending_invitation in session . invitations
if context . JK . currentUserId == pending_invitation . receiver_id
hasInvitation = true
break
errorMsg = null
error = false
if error
errorMsg = ` < span className = " rsvp-msg " style = " display:none; " > You cannot RSVP to this session . < / span > `
# if this is your own session, let you start it immediately
if context . JK . currentUserId == session . user_id
result = ` < div className = " center " > < span className = " text " > < a onClick = { this . startSessionNow . bind ( this , session ) } className = " start " style = { { color: ' # fc0 ' } } > Start session now ? < /a><br/ > < br / > This is your session . < / span > < / div > `
return result
# if you are approved RSVP person, let you cancel it
if approvedRsvpId
if session . scheduled_start && @ showStartSessionButton ( session . scheduled_start )
# give user both option to start session, and also cancel RSVP
result = ` < div className = " center " > < span className = " text " > < a onClick = { this . startSessionNow . bind ( this , session ) } className = " start " > Start session now ? < / a > & nbsp ; | & nbsp ; < a onClick = { this . cancelRsvpClicked . bind ( this , session , approvedRsvpId ) } className = " cancel " > Cancel RSVP < / a > < / span > < / div > `
return result
else
# user can just cancel their RSVP
result = ` < div className = " center " > < span className = " text " > < a onClick = { this . cancelRsvpClicked . bind ( this , session , approvedRsvpId ) } className = " cancel " > Cancel RSVP < / a > < / span > < / div > `
return result
else if hasInvitation
if session . scheduled_start && @ showStartSessionButton ( session . scheduled_start )
# give user both option to start session, and also cancel RSVP
result = ` < div className = " center " > < span className = " text " > < a onClick = { this . startSessionNow . bind ( this , session ) } className = " start " > Start session now ? < /a> | You have an invite to this session.<br/ > < br / > You can join it when it starts . < / span > < / div > `
return result
else
# user can just cancel their RSVP
result = ` < div className = " center " > < span className = " text " > You have an invite to this session . < br / > < br / > You can join it when it starts . < / span > < / div > `
return result
else if pendingRsvpId
result = ` < div className = " center " > < span className = " text " > < a onClick = { this . cancelRsvpClicked . bind ( this , session , pendingRsvpId ) } className = " cancel " > Cancel RSVP < / a > < / span > < / div > `
return result
else if ! session [ ' is_unstructured_rsvp? ' ] && session . open_slots . length == 0
result = ` < div className = " center " > < span className = " text " > No more open positions . < / span > < / div > `
return result
else if ! session . open_rsvps && ! hasInvitation
result = ` < div className = " center " > < span className = " text " > You need an invitation to RSVP to this session . < / span > < / div > `
return result
` < div className = " center " >
{ errorMsg }
< a className = " rsvp-link " onClick = { this . rsvpLinkClicked . bind ( this , session ) } >
< div className = " rsvp-icon " > < / div >
< / a >
< div className = " rsvp-link-text " > RSVP < / div >
< / div > `
openSlots: (session, open_slots_first_3, open_slots_remaining) ->
# false means hide, true means show
openSlotToggle = @ state . openSlotToggle
remainingStyles = { }
if openSlotToggle
remainingStyles.display = ' block '
else
remainingStyles.display = ' none '
` < tr className = " musicians-detail " >
< td className = " musicians-header " > < span > Still Needed : < / span > < / td >
< td >
< table className = " musicians musicians-category " cellpadding = " 0 " cellspacing = " 0 " width = " 100% " >
< tbody >
{ open_slots_first_3 }
< / tbody >
< / table >
< div style = { remainingStyles } >
< table className = " musicians remaining " cellpadding = " 0 " cellspacing = " 0 " width = " 100% " >
< tbody >
{ open_slots_remaining }
< / tbody >
< / table >
< / div >
< / td >
< / tr > `
2020-04-29 20:51:50 +00:00
2020-05-06 19:42:52 +00:00
rsvps: (session, rsvp_musicians_first_3, rsvp_musicians_remaining, open_slots_first_3) ->
2020-04-30 17:05:59 +00:00
2020-05-06 19:42:52 +00:00
if session . create_type == ' quick-start ' || ( ( ! rsvp_musicians_first_3 || rsvp_musicians_first_3 . length == 0 ) && ( ! open_slots_first_3 || open_slots_first_3 . length == 0 ) )
2020-04-30 17:05:59 +00:00
return null
2020-05-06 19:42:52 +00:00
# if no rsvps yet some open slots
if ( ! rsvp_musicians_first_3 || rsvp_musicians_first_3 . length == 0 ) && ( open_slots_first_3 && open_slots_first_3 . length > 0 )
return ` < tr className = " musicians-detail " >
< td className = " musicians-header " > < span > RSVPs : < / span > < / td >
< td >
< div className = " none-yet " >
None yet
< / div >
< / td >
< / tr > `
# false means hide, true means show
rsvpToggle = @ state . rsvpToggle
remainingStyles = { }
if rsvpToggle
remainingStyles.display = ' block '
else
remainingStyles.display = ' none '
` < tr className = " musicians-detail " >
< td className = " musicians-header " > < span > RSVPs : < / span > < / td >
2020-04-30 17:05:59 +00:00
< td >
2020-05-06 19:42:52 +00:00
< table className = " musicians musicians-category " cellpadding = " 0 " cellspacing = " 0 " width = " 100% " >
< tbody >
2020-04-30 17:05:59 +00:00
{ rsvp_musicians_first_3 }
2020-05-06 19:42:52 +00:00
< / tbody >
2020-04-30 17:05:59 +00:00
< / table >
2020-05-06 19:42:52 +00:00
< div style = { remainingStyles } >
2020-04-30 17:05:59 +00:00
< table className = " musicians " cellpadding = " 0 " cellspacing = " 0 " width = " 100% " >
2020-05-06 19:42:52 +00:00
< tbody >
2020-04-30 17:05:59 +00:00
{ rsvp_musicians_remaining }
2020-05-06 19:42:52 +00:00
< / tbody >
2020-04-30 17:05:59 +00:00
< / table >
< / div >
< / td >
< / tr > `
2020-04-29 20:51:50 +00:00
2020-05-06 19:42:52 +00:00
componentDidMount: () ->
@ui = new context . JK . UIHelper ( AppStore . app )
ensuredCallback: (sessionId) ->
context . JK . SessionUtils . joinSession ( sessionId )
joinLinkClicked: (session) ->
2020-10-14 02:05:08 +00:00
context . JK . SessionUtils . ensureValidClient ( AppStore . app , context . JK . GearUtils , @ ensuredCallback . bind ( this , session . id ) )
2020-05-06 19:42:52 +00:00
rsvpLinkClicked: (session) ->
@ ui . launchRsvpSubmitDialog ( session . id )
. one ( EVENTS . RSVP_SUBMITTED , () -> SessionsActions . updateSession . trigger ( session . id ) )
. one ( EVENTS . DIALOG_CLOSED , () ->
$ ( this ) . unbind ( EVENTS . RSVP_SUBMITTED ) ;
)
return false
toggleRsvp: () ->
@ setState ( rsvpToggle: ! @ state . rsvpToggle )
toggleOpenSlot: (sessionId) ->
@ setState ( openSlotToggle: ! @ state . openSlotToggle )
startSessionNow: (session) ->
@ ui . launchSessionStartDialog ( session )
showStartSessionButton: (scheduledStart) ->
now = new Date ( )
scheduledDate = new Date ( scheduledStart )
minutesFromStart = ( scheduledDate . getTime ( ) - now . getTime ( ) ) / ( 1000 * 60 )
minutesFromStart <= MAX_MINUTES_SHOW_START
cancelRsvpClicked: (session, approvedRsvpId) ->
@ ui . launchRsvpCancelDialog ( session . id , approvedRsvpId )
. one ( EVENTS . RSVP_CANCELED , () -> SessionsActions . updateSession . trigger ( session . id ) )
. one ( EVENTS . DIALOG_CLOSED , () ->
$ ( this ) . unbind ( EVENTS . RSVP_CANCELED ) ;
)
return false
inSessionMusicians: (in_session_musicians) ->
if @ props . mode == ' upcoming '
return null
` < tr className = " musicians-detail " >
< td className = " musicians-header " > < span > In Session : < / span > < / td >
< td >
{ in_session_musicians }
< / td >
< / tr > `
2020-05-07 02:45:32 +00:00
createListenLink: () ->
null
2021-06-16 08:11:59 +00:00
2021-06-18 14:57:21 +00:00
onLatencyUpdate: (latencyResp) ->
2021-06-19 11:48:59 +00:00
logger . debug ( " latencyResp}}}}}}}}}}}}}}}} " , latencyResp )
2021-06-18 14:57:21 +00:00
if latencyResp . users
@ setState ( userLatencies: latencyResp . users )
else if latencyResp . user_ids
@ setState ( userLatenciesFailed: latencyResp . user_ids )
2021-06-16 08:11:59 +00:00
2020-04-29 20:51:50 +00:00
render: () ->
session = @ props . session
id = session . id
name = session . name
description = session . description || " (No description) "
2020-05-06 19:53:47 +00:00
genres = session . genres . join ( ' , ' )
if session . genres . length > 1
genres = ` < span > < span className = " bold " > Genres: < / span > { genres } < / span > `
else
genres = ` < span > < span className = " bold " > Genre: < / span > { genres } < / span > `
2020-04-30 17:05:59 +00:00
[ in_session_musicians , inSessionUsers ] = @ inSessionUsersHtml ( session )
[ rsvp_musicians_first_3 , rsvp_musicians_remaining ] = @ createRsvpUsers ( session )
[ open_slots_first_3 , open_slots_remaining ] = @ createOpenSlots ( session )
2020-05-06 19:42:52 +00:00
rsvps = @ rsvps ( session , rsvp_musicians_first_3 , rsvp_musicians_remaining , open_slots_first_3 )
joinLink = @ joinLink ( session , inSessionUsers )
2020-04-29 20:51:50 +00:00
showListenLink = session . fan_access && session . active_music_session && session . active_music_session . mount
2020-05-06 19:42:52 +00:00
showListenLink = false # for now... XXX
openSlots = null
scheduled_start = null
rsvpLink = null
if @ props . mode == ' upcoming '
openSlots = @ openSlots ( session , open_slots_first_3 , open_slots_remaining )
scheduled_start = ` < tr >
< td colspan = " 2 " > { session . pretty_scheduled_start_with_timezone } < / td >
< / tr > `
rsvpLink = @ rsvpLink ( session )
2020-04-29 20:51:50 +00:00
listen_link_display_style = { display: " none " }
if showListenLink
listen_link_display_style = { display: " inline-block " }
listen_link_text = ' '
if ! session . fan_access
listen_link_text = ' '
else if session . active_music_session && session . active_music_session . mount
listen_link_text = ' Listen '
else
listen_link_text = ' ' ;
2020-05-06 19:42:52 +00:00
remark = null
if session . highlight
highlight = session . highlight
if highlight . new
2020-05-06 23:25:10 +00:00
remark = ` < div className = " highlight new " > NEW < / div > `
2020-05-06 19:42:52 +00:00
inSessionMusicians = @ inSessionMusicians ( in_session_musicians )
2020-05-07 02:45:32 +00:00
listenLink = @ createListenLink ( session )
2020-04-29 20:51:50 +00:00
` < tr data - session - id = { id } className = " found-session " >
2020-04-30 17:05:59 +00:00
< td width = " 40% " className = " session-cell " >
2020-05-06 19:42:52 +00:00
{ remark }
2020-04-29 20:51:50 +00:00
< table className = " musician-groups " cellpadding = " 0 " cellspacing = " 0 " width = " 100% " >
2020-05-06 19:42:52 +00:00
< tbody >
< tr >
< td className = " bold " > < a className = " session-name " href = { " /sessions/ " + id } rel = " external " > { name } < / a > < / td >
2020-05-06 19:53:47 +00:00
2020-05-06 19:42:52 +00:00
< / tr >
< tr >
< td colspan = " 2 " className = " session-description " > { description } < / td >
2020-05-06 19:53:47 +00:00
< / tr >
< tr >
< td className = " session-genre " > { genres } < / td >
2020-05-06 19:42:52 +00:00
< / tr >
{ scheduled_start }
< / tbody >
2020-04-29 20:51:50 +00:00
< / table >
2020-04-30 17:05:59 +00:00
< div className = " spacer " > < / div >
2020-04-29 20:51:50 +00:00
< / td >
2020-04-30 17:05:59 +00:00
< td width = " 45% " className = " session-musicians " >
2020-04-29 20:51:50 +00:00
< table className = " musicians " cellpadding = " 0 " cellspacing = " 0 " >
2020-05-06 19:42:52 +00:00
< tbody >
{ inSessionMusicians }
2020-04-30 17:05:59 +00:00
{ rsvps }
2020-05-06 19:42:52 +00:00
{ openSlots }
< / tbody >
2020-04-29 20:51:50 +00:00
< / table >
2020-04-30 17:05:59 +00:00
< div className = " spacer " > < / div >
2020-04-29 20:51:50 +00:00
< / td >
2020-04-30 17:05:59 +00:00
< td width = " 10% " className = " actions " >
2020-05-07 02:45:32 +00:00
{ listenLink }
2020-05-06 19:42:52 +00:00
{ joinLink }
{ rsvpLink }
2020-04-30 17:05:59 +00:00
< div className = " spacer " > < / div >
2020-04-29 20:51:50 +00:00
< / td >
< / tr > `
} )