feat: admin interface, game name

This commit is contained in:
Settel 2022-02-27 20:54:13 +01:00
parent defb20cc7c
commit addfcdea86
15 changed files with 186 additions and 4 deletions

View File

@ -0,0 +1,34 @@
<template>
<div class="admin-tile">
<div v-if="title" class="admin-tile__title">
{{ title }}
</div>
<div class="admin-tile__body">
<slot />
</div>
</div>
</template>
<script>
export default {
props: ['title'],
}
</script>
<style lang="scss">
.admin-tile {
width: 300px;
margin: 16px;
&__title {
font-size: 32px;
font-family: Dosis;
border-bottom: 1px solid #ffffff;
margin-bottom: 16px;
}
&__body {
font-family: Dosis;
font-size: 18px;
}
}
</style>

View File

@ -22,7 +22,7 @@
export default {
computed: {
title() {
return 'Hall of Fame'
return this.$store.state.game.name
},
players() {
var players = [...this.$store.state.players.players]

View File

@ -5,6 +5,7 @@
<button @click="continueGame">Continue</button>
<button @click="resetGame">Idle</button>
<button @click="finishGame">Finish Game</button>
<button @click="admin">Admin Interface</button>
</nav>
</template>
@ -35,6 +36,9 @@ export default {
finishGame() {
this.$engine.finishGame()
},
admin() {
this.$router.push({ path: '/admin' })
},
},
}
</script>

View File

@ -0,0 +1,71 @@
<template>
<div class="page-admin">
<template v-if="!isGamemasterOrAdmin">
<p>You are not a game master.</p>
<button @click="login">Go to login page</button>
</template>
<template v-if="isGamemasterOrAdmin">
<GameControls />
<button class="page-admin__back-button" @click="login">Go to login page</button>
<div class="page-admin__tiles">
<AdminTile title="Myself">
<table>
<tr>
<td>Name:</td>
<td>{{ user.name }}</td>
</tr>
<tr>
<td>Role:</td>
<td>{{ user.role }}</td>
</tr>
</table>
</AdminTile>
<AdminTile title="Players">
<ul>
<li>Player #1</li>
<li>Player #2</li>
<li>Player #3</li>
</ul>
</AdminTile>
</div>
</template>
</div>
</template>
<script>
export default {
async fetch() {
await this.$engine.fetchUserInfo()
await this.$engine.fetchGameInfo({ g: this.$store.state.engine.user.game })
},
computed: {
isGamemasterOrAdmin() {
const user = this.$store.state.engine.user
return user && ['gamemaster', 'admin'].indexOf(user.role) != -1
},
user() {
console.log(this.$store.state.engine.user)
return this.$store.state.engine.user
},
},
methods: {
login() {
this.$router.push({ path: '/' })
},
},
}
</script>
<style lang="scss">
.page-admin {
&__tiles {
display: flex;
margin: 24px;
}
&__back-button {
margin: 16px;
}
color: #ffffff;
}
</style>

View File

@ -0,0 +1,13 @@
export default async function({ g }) {
const { store } = this.context
try {
const response = await this.callApi('/api/gameinfo', { g })
store.commit('engine/setGameInfo', response.data)
} catch(e) {
store.commit('engine/setGameInfo', undefined)
return false
}
return true
}

View File

@ -3,6 +3,7 @@ import start from './start'
import stop from './stop'
import fetchUpdate from './fetchUpdate'
import fetchUserInfo from './fetchUserInfo'
import fetchGameInfo from './fetchGameInfo'
import collectQuotes from './collectQuotes'
import startGame from './startGame'
import resetGame from './resetGame'
@ -27,6 +28,7 @@ export default (context, inject) => {
stop,
fetchUpdate,
fetchUserInfo,
fetchGameInfo,
collectQuotes,
getMyQuotes,
saveQuote,

View File

@ -2,6 +2,7 @@ export const state = () => ({
json: {},
version: -1,
user: undefined,
gameinfo: undefined,
})
export const mutations = {
@ -15,4 +16,7 @@ export const mutations = {
setUser(state, user) {
state.user = user
},
setGameInfo(state, gameinfo) {
state.gameinfo = gameinfo
},
}

View File

@ -1,17 +1,20 @@
export const state = () => ({
state: "",
phase: "",
name: "",
})
export const mutations = {
setStateAndPhase(state, game) {
if (game) {
const { state: gameState, phase } = game
const { state: gameState, phase, name } = game
state.state = gameState
state.phase = phase
state.name = name
} else {
state.state = ""
state.phase = ""
state.name = ""
}
},
}

View File

@ -0,0 +1,30 @@
package application
import (
"encoding/json"
"fmt"
"net/http"
"sirlab.de/go/knyt/user"
)
func (app *Application) GetGameInfo(usr *user.User, w http.ResponseWriter, r *http.Request) {
gameRef := r.URL.Query().Get("g")
gm, err := app.GetGameById(gameRef)
if err != nil {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "game not found")
return
}
if usr.GetGameId() != gameRef || !usr.IsGamemaster() {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "forbidden")
return
}
gameInfo := gm.GetGameInfo()
w.Header().Add("Content-Type", "application/json")
jsonString, _ := json.Marshal(gameInfo)
fmt.Fprintf(w, string(jsonString))
}

View File

@ -0,0 +1,13 @@
package game
import ()
func (gm *Game) GetGameInfo() *GameInfoJson {
gm.mu.Lock()
defer gm.mu.Unlock()
gameInfo := GameInfoJson{
Name: gm.name,
}
return &gameInfo
}

View File

@ -16,6 +16,7 @@ func (gm *Game) populateGameInfo() syncdata.GameInfo {
return syncdata.GameInfo{
GameId: gm.id,
Name: gm.name,
State: gm.state,
Phase: gm.phase,
Players: gm.populateGetPlayers(),

View File

@ -5,8 +5,8 @@ import (
)
func (gm *Game) StartGame() {
// go gm.runCountdown()
go gm.runRound()
go gm.runCountdown()
// go gm.runRound()
}
func (gm *Game) ResetGame() {

View File

@ -70,6 +70,11 @@ type GameJson struct {
Name string `json:"name"`
}
type GameInfoJson struct {
Name string `json:"name"`
Players map[string]playerInfo `json:"players"`
}
type GameStateJson struct {
Scores map[string]int `json:"scores"`
QuotesPlayed []string `json:"quotesPlayed"`

View File

@ -22,6 +22,7 @@ func main() {
mux.PublicHandleFunc("/api/login", mux.Login)
mux.PublicHandleFunc("/api/logout", mux.Logout)
mux.PrivateHandleFunc("/api/userinfo", mux.GetUserInfo)
mux.PrivateHandleFunc("/api/gameinfo", app.GetGameInfo)
mux.PrivateHandleFunc("/api/sync", app.SyncHandler)
mux.PrivateHandleFunc("/api/collectQuotes", app.CollectQuotes)
mux.PrivateHandleFunc("/api/startGame", app.StartGame)

View File

@ -32,6 +32,7 @@ type RoundInfo struct {
type GameInfo struct {
GameId string `json:"id"`
Name string `json:"name"`
State string `json:"state"`
Phase string `json:"phase"`
Players []PlayerInfo `json:"players"`