context = window rest = context.JK.Rest() logger = context.JK.logger JamBlasterActions = @JamBlasterActions @JamBlasterScreen = React.createClass({ mixins: [ @ICheckMixin, @PostProcessorMixin, @BonjourMixin, Reflux.listenTo(AppStore, "onAppInit"), Reflux.listenTo(UserStore, "onUserChanged"), Reflux.listenTo(JamBlasterStore, "onJamBlasterChanged") ] TILE_AUDIO: 'audio' TILE_INTERNET: 'internet' TILE_MANAGEMENT: 'management' TILE_USB: 'usb' TILES: ['management', 'audio', 'internet'] networkStale: false ipRegex: /^0([0-9])+/ onAppInit: (@app) -> @app.bindScreen('jamblaster', {beforeShow: @beforeShow, afterShow: @afterShow, beforeHide: @beforeHide}) onUserChanged: (userState) -> @setState({user: userState?.user}) onJamBlasterChanged: (jamblasterState) -> @setState(jamblasterState) componentDidMount: () -> @checkboxes = [{selector: 'input.dhcp', stateKey: 'userdhcp'}] @root = $(@getDOMNode()) @iCheckify() componentDidUpdate: () -> @iCheckify() items = @root.find('.jamtable .optionsColumn .jamblaster-options-btn') $.each(items, (i, node) => ( $node = $(node) jamblaster = @findJamBlaster({ server_id: $node.attr('data-jamblaster-id'), ipv6_addr: $node.attr('data-jamblaster-addr') }) $node.jamblasterOptions(jamblaster).off(context.JK.EVENTS.JAMBLASTER_ACTION).on(context.JK.EVENTS.JAMBLASTER_ACTION, @jamblasterOptionSelected) )) @root.find('input.networksettings').inputmask({ alias: "ip", "placeholder": "_" }); checkboxChanged: (e) -> checked = $(e.target).is(':checked') value = $(e.target).val() console.log("checkbox changed: ", value) @setState({userdhcp: "true" == value}) componentWillUpdate: (nextProps, nextState) -> if @networkStale && @state.pairedJamBlaster? console.log("stale network update", @state) nextState.userdhcp = @state.pairedJamBlaster.network?.dhcp nextState.useraddr = @state.pairedJamBlaster.network?.addr nextState.usersubnet = @state.pairedJamBlaster.network?.subnet nextState.usergateway = @state.pairedJamBlaster.network?.gateway nextState.userdns1 = @state.pairedJamBlaster.network?.dns1 nextState.userdns2 = @state.pairedJamBlaster.network?.dns2 nextState.userdhcperror = false nextState.useraddrerror = false nextState.usersubneterror = false nextState.usergatewayerror = false nextState.userdns1error = false nextState.userdns2error = false @networkStale = false #context.JK.popExternalLinks(@root) # jamblasterOptionSelected: (e, data) -> # jamblaster = data.options # jamblaster = @findJamBlaster(jamblaster) # if data.option == 'auto-connect' # JamBlasterActions.setAutoPair(!jamblaster.autoconnect) # else if data.option == 'restart' # context.JK.Banner.showYesNo({ # title: "reboot JamBlaster", # html: "Are you sure?" # yes: => # result = context.jamClient.rebootJamBlaster() # if result # setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting", # "It should be back online within a minute.")), 1) # setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) # else # setTimeout((() => context.JK.Banner.showAlert("could not reboot", # "The JamBlaster could not be rebooted remotely. Please cycle the power manually.")), 1) # }) # else if data.option == 'name' # @app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED, # (e, data) => # setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) # ) # else if data.option == 'check-for-updates' # context.JK.Banner.showNotice('Check for Update', # 'The JamBlaster only checks for updates when booting up. Please reboot the JamBlaster to initiate an update check.') # else if data.option == 'set-static-ports' # if jamblaster.isDynamicPorts # context.JK.Banner.showYesNo({ # title: "revert to dynamic ports", # html: "Your JamBlaster is currently configured to use ports #{jamblaster.portState.static_port} - #{jamblaster.portState.static_port + 10}). Would you like to revert to the use of dynamic ports for UDP communication?" # yes: => # context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000}) # JamBlasterActions.clearPortBindState() # #setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) # JamBlasterActions.resyncBonjour() # setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster", # "For these settings to take effect, you must restart the JamBlaster.")), 1) # }) # else # @app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => # JamBlasterActions.clearPortBindState() # JamBlasterActions.resyncBonjour() # context.JK.Banner.showNotice("reboot JamBlaster", # "For these settings to take effect, you must restart the JamBlaster.") # ) # else if data.option == 'factory-reset' # context.JK.Banner.showNotice('Factory Reset', # 'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.

Please reboot the JamBlaster to initiate an update check.') # else # logger.debug("unknown action") jamblasterOptionSelected: `function(e, data) { let jamblaster = data.options; jamblaster = this.findJamBlaster(jamblaster); if (data.option === 'auto-connect') { return JamBlasterActions.setAutoPair(!jamblaster.autoconnect); } else if (data.option === 'restart') { return context.JK.Banner.showYesNo({ title: "reboot JamBlaster", html: "Are you sure?", yes: async () => { const result = await context.jamClient.rebootJamBlaster(); if (result) { setTimeout((() => context.JK.Banner.showNotice("JamBlaster is rebooting", "It should be back online within a minute.")), 1); return setTimeout((() => JamBlasterActions.resyncBonjour()), 1000); } else { return setTimeout((() => context.JK.Banner.showAlert("could not reboot", "The JamBlaster could not be rebooted remotely. Please cycle the power manually.")), 1); } } }); } else if (data.option === 'name') { return this.app.layout.showDialog('jamblaster-name-dialog', {d1: jamblaster.name}).one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => { return setTimeout((() => JamBlasterActions.resyncBonjour()), 1000); }); } else if (data.option === 'check-for-updates') { return context.JK.Banner.showNotice('Check for Update', 'The JamBlaster only checks for updates when booting up. Please reboot the JamBlaster to initiate an update check.'); } else if (data.option === 'set-static-ports') { if (jamblaster.isDynamicPorts) { return context.JK.Banner.showYesNo({ title: "revert to dynamic ports", html: 'Your JamBlaster is currently configured to use ports '+jamblaster.portState.static_port+' - '+(jamblaster.portState.static_port + 10)+'. Would you like to revert to the use of dynamic ports for UDP communication?', yes: async () => { await context.jamClient.setJbPortBindState({use_static_port: false, static_port: 12000}); JamBlasterActions.clearPortBindState(); //setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) JamBlasterActions.resyncBonjour(); return setTimeout((() => context.JK.Banner.showNotice("reboot JamBlaster", "For these settings to take effect, you must restart the JamBlaster.")), 1); } }); } else { return this.app.layout.showDialog('jamblaster-port-dialog').one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => { JamBlasterActions.clearPortBindState(); JamBlasterActions.resyncBonjour(); return context.JK.Banner.showNotice("reboot JamBlaster", "For these settings to take effect, you must restart the JamBlaster."); }); } } else if (data.option === 'factory-reset') { return context.JK.Banner.showNotice('Factory Reset', 'The JamBlaster only checks for updates when it boots up, and if there is an update available, it will automatically begin updating.

Please reboot the JamBlaster to initiate an update check.'); } else { return logger.debug("unknown action"); } }` getInitialState: () -> { selected: 'management', user: null, userJamBlasters: [], localJamBlasters: [], allJamBlasters: [] } beforeHide: (e) -> @clearTimer() beforeShow: (e) -> @setTimer() afterShow: (e) -> JamBlasterActions.resyncBonjour() openMenu: (client, e) -> logger.debug("open jamblaster options menu") $this = $(e.target) if !$this.is('.jamblaster-options-btn') $this = $this.closest('.jamblaster-options-btn') $this.btOn() clearTimer: () -> if @interval? clearInterval(@interval) @interval = null # Refresh bonjour status every 30 second, so that we catch major changes setTimer: () -> @clearTimer() time = 30000 # every 30 seconds @interval = setInterval((() => JamBlasterActions.resyncBonjour()), time) connect: (client, e) -> logger.debug("beginning pairing to #{client.connect_url}") @clearTimer() @app.layout.showDialog('jamblaster-pairing-dialog', {d1: client}).one(context.JK.EVENTS.DIALOG_CLOSED, (e, data) => JamBlasterActions.resyncBonjour() @setTimer() ) # disconnect: (client, e) -> # logger.debug("disconnecting from currently paired client #{client.connect_url}") # context.jamClient.endPairing() # setTimeout((() => JamBlasterActions.resyncBonjour()), 1000) disconnect: `async function(client,e){ logger.debug('disconnecting from currently paired client' +client.connect_url); await context.jamClient.endPairing(); setTimeout((()=>JamBlasterActions.resyncBonjour()),1000); }` mergeClients: () -> clientsJsx = [] for client in @state.allJamBlasters if client.display_name? displayName = client.display_name else displayName = client.name if client.serial_no? && displayName? && displayName.indexOf(client.serial_no) == -1 displayName = "#{displayName} (#{client.serial_no})" name = `{displayName}` if client.isPaired connect = `disconnect` else if client.has_local connect = `connect` else connect = `offline` options = `more options
` clientsJsx.push(` {name}{options}{connect} `) clientsJsx mainContent: () -> if !@state.user?.id || !@state.userJamBlasters? || !@state.localJamBlasters? return `
Loading ...
` if @state.selected == @TILE_AUDIO @audio() else if @state.selected == @TILE_INTERNET @internet() else if @state.selected == @TILE_MANAGEMENT @management() else if @state.selected == @TILE_USB @usb() audio: () -> `
To edit the JamBlaster audio settings, get into a session, and click the Settings link under My Tracks.
` ipSettingsChanged: (key, e) -> userKey = 'user' + key state = {} ip = $(e.target).val() state[userKey] = ip if ip? bits = ip.split('.') console.log("bits", bits) for bit in bits result = @ipRegex.test(bit.replace(/_/g, '')) console.log("STILL GOT THAT _?", result) error = false if result == true || bit == "___" error = true break if error console.log("SETTING ERROR for " + userKey + 'error') state[userKey + 'error'] = true else state[userKey + 'error'] = false this.setState(state) onSaveNetworkSettings: (e) -> e.preventDefault() settings = { dhcp: this.state.userdhcp, addr: this.state.useraddr, gateway: this.state.usergateway, subnet: this.state.usersubnet, dns1: this.state.userdns1, dns2: this.state.userdns2 } logger.debug("saving network settings", settings) JamBlasterActions.saveNetworkSettings(settings) @networkStale = true usb: () -> `

USB Settings

` internet: () -> pairedJamBlaster = this.state.pairedJamBlaster hasPairedJamBlaster = pairedJamBlaster? isJamBlasterDhcp = !!this.state.userdhcp if hasPairedJamBlaster status = `
Ethernet:Connected
Internet:Connected
Streaming:Supported
` else status = `
Ethernet:Unknown
Internet:Unknown
Streaming:Unknown
` addrClasses = {field: true, error: this.state.useraddrerror} subnetClasses = {field: true, error: this.state.usersubneterror} gatewayClasses = {field: true, error: this.state.usergatewayerror} dns1Classes = {field: true, error: this.state.userdns1error} dns2Classes = {field: true, error: this.state.userdns2error} saveBtnClasses = {} saveBtnClasses["save-settings-btn"] = true saveBtnClasses["button-orange"] = true saveBtnClasses["disabled"] = !hasPairedJamBlaster ipdisabled = !hasPairedJamBlaster || isJamBlasterDhcp `

Internet Settings

Assign IP Address

Manual Settings

SAVE SETTINGS

Network Status

{status}
` management: () -> clients = @mergeClients() if @state.refreshingBonjour refreshingText = 'SCANNING' else refreshingText = 'SCAN NETWORK' refreshClasses = {"resync-bonjour": true, "button-orange": true, disabled: @state.refreshingBonjour} `
{clients}
JAMBLASTERS ON YOUR NETWORK
{refreshingText}

If you don't see your JamBlaster listed above, please check to make sure you have power connected to your JamBlaster, and make sure your JamBlaster is connected via an Ethernet cable to the same router/network as the device on which you are viewing this application.

` tiles: () -> @TILES selectionMade: (selection, e) -> e.preventDefault() if selection == @TILE_INTERNET @networkStale = true @setState({selected: selection}) createTileLink: (i, tile) -> if this.state.selected? active = this.state.selected == tile else active = tile == @TILE_MANAGEMENT tileClasses = {activeTile: active, 'jamblaster-tile': true} tileClasses = classNames(tileClasses) classes = classNames({last: i == @tiles().length - 1}) return `
{tile}
` render: () -> disabled = @state.updating tiles = [] for tile, i in @tiles() tiles.push(@createTileLink(i, tile)) `

jamblaster settings

{tiles}
{this.mainContent()}

` })