context = window
rest = new context.JK.Rest()
ChatActions = @ChatActions
@ChatWindow = React.createClass({
mixins: [Reflux.listenTo(@AppStore, "onAppInit"), Reflux.listenTo(@UserStore, "onUserChanged"),
Reflux.listenTo(@ChatStore, "onChatChanged")]
lastChannel: null
getInitialState: () ->
state = context.ChatStore.getState()
state
getInitialProps: () ->
{newFormat:true}
onChatChanged: (chatState) ->
@setState(chatState)
onUserChanged: (userState) ->
@setState(userState)
onAppInit: (app) ->
@app = app
activateChannel: (channel, e) ->
e.preventDefault()
ChatActions.activateChannel(channel);
convertPurpose: (purpose) ->
if !purpose?
return ''
switch purpose
when 'Lesson Requested' then 'requested lesson'
when 'Lesson Canceled' then 'canceled lesson'
when 'Lesson Approved' then 'approved lesson'
when 'All Lesson Times Updated' then 'updated all lesson times'
when 'Lesson Updated Time Approved' then 'updated lesson time'
when 'New Time Proposed' then 'proposed new time'
when 'Lesson Declined' then 'declined lesson'
when 'Notation File' then 'attached a notation file'
when 'Audio File' then 'attached an audio file'
when 'JamKazam Recording' then 'attached a recording'
when 'Lesson Timeout' then 'canceled by system'
else purpose
notationClicked: (music_notation, e) ->
e.preventDefault()
context.JK.popExternalLink("/api/music_notations/#{music_notation.id}?target=_blank")
audioClicked: (music_notation, e) ->
e.preventDefault()
context.JK.popExternalLink("/api/music_notations/#{music_notation.id}?target=_blank")
recordingClicked: (recording, e) ->
e.preventDefault()
context.JK.popExternalLink("/recordings/#{recording.id}")
openMenu: (lesson, e) ->
$this = $(e.target)
if !$this.is('.lesson-session-actions-btn')
$this = $this.closest('.lesson-session-actions-btn')
$this.btOn()
render: () ->
if @state.channel == 'lesson'
chatTabs = `
`
else if !this.props.hideHeader
tabs = []
for channel of @state.msgs
classes = {}
classes[channel] = true
classes['chat-tab'] = true
classes['active'] = channel == @state.channel
if channel == 'global'
display = 'Global'
else if channel == 'session'
display = 'Session'
else if channel == 'lesson'
display = 'Lesson'
else if !channel?
display = 'Global'
else
display = 'Unknown'
if display == 'Unknown'
continue
tabs.push(``)
chatTabs = `
{tabs}
`
msgs = []
if @activeChannelType() == 'lesson'
activeChannel = @state.lessonSessionId
else
activeChannel = @state.channel
activeMsgs = @state.msgs[activeChannel] || []
for msg in activeMsgs
timeago = $.timeago(msg.created_at)
if msg.sender_id == context.JK.currentUserId
sender = "me"
else
sender = msg.sender_name
if msg.purpose
purpose = `{this.convertPurpose(msg.purpose)}
`
else
purpose = null
additional = null
if msg.purpose == 'Notation File'
additional = `{msg.music_notation.file_name}`
else if msg.purpose == 'Audio File'
additional = `{msg.music_notation.file_name}`
else if msg.purpose == 'JamKazam Recording'
additional = `{msg.claimed_recording.name}`
msgs.push(`
{sender}{purpose}
{msg.msg}
{additional}
`)
if this.props?.showEmailNotice
otherName = this.props?.other?.name
emailSentNotice = `an email will be sent if {otherName} is offline
`
if this.props?.showClose
closeBtn = `CLOSE`
topClasses = {ChatWindow: true}
if this.props?.rootClass?
topClasses[this.props.rootClass] = true
if this.props.rootClass == 'ChatDialog'
attachFiles = `attach file
`
``
activeChannelType: () ->
@state.channelType
sendMessage:()->
if !context.JK.JamServer.connected
return false
msg = @textBox.val()
if !msg? || msg == ''
# don't bother the server with empty messages
return false;
if !@sendingMessage
@sendingMessage = true
target_user_id = this.props?.other?.id
ChatActions.sendMsg(msg, @sendMsgDone, @sendMsgFail, target_user_id, @activeChannelType())
sendMsgDone: () ->
@textBox.val('')
@sendingMessage = false
sendMsgFail: (jqXHR) ->
if jqXHR.status == 404
@app.notifyServerError(jqXHR, 'Session chat is only available while in session.')
else
@app.notifyServerError(jqXHR, 'Unable to Send Chat Message')
@sendingMessage = false
handleSendMessage: (e) ->
e.preventDefault()
@sendMessage()
handleCloseMessage: (e) ->
e.preventDefault()
this.props.onCloseClicked()
componentDidMount: () ->
@root = $(@getDOMNode())
@textBox = @root.find('textarea')
componentDidUpdate: () ->
if @lastChannel != @state.channel
speed = 0
else
speed = 'slow'
@lastChannel = @state.channel
#speed = 0 #slow
$scroller = @root.find('.chat-list-scroller')
$scroller.animate({scrollTop: $scroller[0].scrollHeight}, speed)
items = @root.find('.chat-tabs .lesson-session-actions-btn')
@hookupMenu(items)
items = @root.find('#attach-files-chat-dialog')
@hookupMenu(items)
hookupMenu: (items) ->
$.each(items, (i, node) => (
$node = $(node)
chat_dialog = this.props.rootClass == 'ChatDialog'
lesson = {id: $node.attr('data-lesson-id'), attachments_only: true, chat_dialog: chat_dialog}
$node.lessonSessionActions(lesson).off(context.JK.EVENTS.LESSON_SESSION_ACTION).on(context.JK.EVENTS.LESSON_SESSION_ACTION, @lessonSessionActionSelected)
))
lessonSessionActionSelected: (e, data) ->
lessonId = data.options.id
if data.lessonAction == 'attach-recording'
window.AttachmentActions.startAttachRecording(lessonId)
else if data.lessonAction == 'attach-notation'
window.AttachmentActions.startAttachNotation(lessonId)
else if data.lessonAction == 'attach-audio'
window.AttachmentActions.startAttachAudio(lessonId)
pasteIntoInput: (el, text) ->
el.focus();
if typeof el.selectionStart == "number" && typeof el.selectionEnd == "number"
val = el.value
selStart = el.selectionStart
el.value = val.slice(0, selStart) + text + val.slice(el.selectionEnd)
el.selectionEnd = el.selectionStart = selStart + text.length
else if typeof document.selection != "undefined"
textRange = document.selection.createRange()
textRange.text = text
textRange.collapse(false)
textRange.select()
handleEnter: (evt) ->
if evt.keyCode == 13 && evt.shiftKey
evt.preventDefault()
@pasteIntoInput($(evt.target).get(0), "\n")
else if evt.keyCode == 13 && !evt.shiftKey
@sendMessage()
})