oglimmer/podcast-human-syncer

View on GitHub
routes/rooms/[roomname].html

Summary

Maintainability
Test Coverage
<:Head>
  <title>Podcast-human-syncer</title>
</:Head>

<Layout page='rooms'>

  {{#if username}}
    <div>
      {{#each connected as userConnected, index }}
        <div>
          <span class='userSpan' on:click='onClickBtnTookOver(userConnected)'>
            {{userConnected}}
          </span>
          ({{totalTime && totalTime[userConnected] ? totalTime[userConnected] : 0}}s)
          {{#if userConnected == username}}
            <input bind:value='inputChat' style='width:400px'/>
          {{elseif chatMessages && chatMessages[userConnected]}}
            {{chatMessages[userConnected]}}
          {{/if}}
        </div>
      {{/each}}
      <br/>
      {{#if current !== username && next === '' && urgent === ''}}
        <button class='action' on:click="onClickBtnNext()">I'm next</button>
      {{/if}}
      {{#if current !== username && urgent !== username}}
        <button class='action' on:click="onClickBtnUrgent()">NOW!!!</button>
      {{/if}}
      {{#if current !== username}}
        <button class='action' on:click="onClickBtnTookOver()">I took over</button>
      {{/if}}
      {{#if current === username && wantToFinish !== username}}
        <button class='action' on:click="onClickBtnFinished()">I want to finish</button>
      {{/if}}
    </div>
    <div>
      {{#if currentImagePath}}
        <img src="/images/{{currentImagePath}}" alt="current speeker" />
      {{/if}}
      {{#if queueImagePath}}
        <img src="/images/{{queueImagePath}}" alt="next speeker" />
      {{/if}}
    </div>
    <div>
      since {{lastTakerOver}} secs. <button on:click='onClickBtnReset()'>reset all timers</button>
    </div>

  {{else}}

    <div>
      Enter your username:
      <input bind:value='inputUsername' />
      <button on:click='connect()'>Go</button>
    </div>

  {{/if}}

</Layout>

<style>
  button.action {
    font-size: 30px;
    margin-bottom: 10px;
    padding: 12px;
  }

  .userSpan {
    border: 2px solid white;
  }

  .userSpan:hover {
    border: 2px solid red;
  }
</style>

<script>
import Cookies from 'js-cookie'
import Layout from '../_components/Layout.html'
import io from '../../node_modules/socket.io-client'

function getCurrentImagePath (wantToFinish, current) {
  if (wantToFinish) {
    return `done_${wantToFinish.toLowerCase()}.png`
  } else if (current) {
    return `profile_${current.toLowerCase()}.png`
  }
  return ''
}

function getQueueImagePath (urgent, next) {
  if (urgent) {
    return `urgent_${urgent.toLowerCase()}.gif`
  } else if (next) {
    return `next_${next.toLowerCase()}.png`
  }
  return ''
}

function getChatMessage (chatMessages, username) {
  if (chatMessages && chatMessages[username]) {
    return chatMessages[username]
  }
  return ''
}

export default {
  async preload (req) {
    const { roomname } = req.params
    const { name } = req.query
    const cookieName = `${roomname}_username`
    var username = ''
    if (name) {
      username = name
    } else if (req.cookies && req.cookies[cookieName]) {
      username = req.cookies[cookieName]
    } else if (Cookies.get(cookieName)) {
      username = Cookies.get(cookieName)
    }

    var url = `/api/rooms/${roomname}`
    if (username) {
      url += `?username=${username}`
    }
    const resp = await global.fetch(url)
    const { connected, current, next, urgent, wantToFinish, lastTakerOver, totalTime, chatMessages } = await resp.json()
    return {
      roomname,
      username,
      current,
      wantToFinish,
      next,
      urgent,
      connected,
      lastTakerOver,
      totalTime,
      chatMessages,
      inputChat: getChatMessage(chatMessages, username)
    }
  },
  components: {
    Layout
  },
  data () {
    return {
      // pure client-side
      socket: null,
      inputUsername: '',
      inputChat: '',
      // from request/cookie
      roomname: 'error:roomname not set',
      username: null,
      // from DB
      lastTakerOver: 0,
      totalTime: {},
      connected: [],
      current: '',
      wantToFinish: '',
      next: '',
      urgent: '',
      // from server
      chatMessages: {}
    }
  },
  computed: {
    currentImagePath: (wantToFinish, current) => getCurrentImagePath(wantToFinish, current),
    queueImagePath: (urgent, next) => getQueueImagePath(urgent, next)
  },
  methods: {
    connect () {
      const { inputUsername: username, roomname } = this.get()
      this.get('socket').emit('transfer name', { username, roomname })
    },
    onClickBtnNext () {
      const { username, roomname } = this.get()
      this.get('socket').emit('ask for next', { username, roomname })
    },
    onClickBtnUrgent () {
      const { username, roomname } = this.get()
      this.get('socket').emit('ask for urgent', { username, roomname })
    },
    onClickBtnTookOver (username = this.get('username')) {
      const roomname = this.get('roomname')
      this.get('socket').emit('took over', { username, roomname })
    },
    onClickBtnFinished () {
      const { username, roomname } = this.get()
      this.get('socket').emit('want to finish', { username, roomname })
    },
    onClickBtnReset () {
      if (window.confirm('Really!??!?!')) {
        const { roomname } = this.get()
        this.get('socket').emit('reset all timers', { roomname })
      }
    }
  },
  oncreate () {
    const { roomname, username } = this.get()
    const socket = io()
    this.set({ socket })

    socket.on('update status', data => {
      this.set(data)
    })

    socket.on('user accepted', data => {
      this.set(data)
      Cookies.set(`${roomname}_username`, data.username, { expires: 365 })
    })

    socket.on('user join failed', error => {
      this.set({ username: '' })
      Cookies.remove(`${roomname}_username`)
      window.alert(error)
    })

    setInterval(() => {
      this.set({ lastTakerOver: this.get('lastTakerOver') + 1 })
    }, 1000)

    this.observe('inputChat', inputChat => {
      const { username } = this.get()
      this.get('socket').emit('change chat', { inputChat, username, roomname })
    })

    if (username) {
      this.get('socket').emit('rejoin user', { username, roomname })
    }
  }
}
</script>