feat: admin page, show list of games

This commit is contained in:
Settel 2022-03-16 17:10:50 +01:00
parent 2fd569f825
commit abb86fc451
8 changed files with 141 additions and 8 deletions

View File

@ -0,0 +1,28 @@
<template>
<AdminTile class="admin-tile-games" title="Games">
<table>
<tr>
<th class="admin-tile-games__table-head">Game name</th>
<th class="admin-tile-games__table-head">#&nbsp;players</th>
</tr>
<tr v-for="id in Object.keys(games)" :key="id">
<td>{{ games[id].name }}</td>
<td>{{ games[id].players.length }}</td>
</tr>
</table>
</AdminTile>
</template>
<script>
export default {
props: ['games'],
}
</script>
<style lang="scss">
.admin-tile-games {
&__table-head {
text-align: left;
}
}
</style>

View File

@ -0,0 +1,54 @@
<template>
<div class="page-admin">
<template v-if="user.role === 'admin'">
<div class="page-admin__body">
<div class="page-admin__tiles">
<AdminTileMyself :user="user" />
<AdminTileGames :games="games.games" />
</div>
</div>
</template>
<template v-else>
<p>You are not an admin.</p>
</template>
</div>
</template>
<script>
export default {
async fetch() {
await this.$engine.fetchUserInfo()
await this.$engine.fetchGames()
},
computed: {
isAdmin() {
return this.$store.state.engine.user?.role === 'admin'
},
user() {
return this.$store.state.engine.user || {}
},
games() {
return this.$store.state.engine.games || {}
}
},
}
</script>
<style lang="scss">
@import '~/assets/css/components';
.page-admin {
color: #ffffff;
width: 100%;
height: 100%;
&__body {
position: relative;
}
&__tiles {
display: flex;
padding: 24px;
}
}
</style>

View File

@ -1,9 +1,6 @@
<template> <template>
<div class="page-gamemaster"> <div class="page-gamemaster">
<template v-if="!isGamemasterOrAdmin"> <template v-if="user.role === 'gamemaster'">
<p>You are not a game master.</p>
</template>
<template v-if="isGamemasterOrAdmin">
<GameControls /> <GameControls />
<div class="page-gamemaster__body"> <div class="page-gamemaster__body">
<div v-if="overlay.open" class="page-gamemaster__player-overlay"> <div v-if="overlay.open" class="page-gamemaster__player-overlay">
@ -16,6 +13,9 @@
</div> </div>
</div> </div>
</template> </template>
<template v-else>
<p>You are not a game master.</p>
</template>
</div> </div>
</template> </template>
@ -33,10 +33,6 @@ export default {
} }
}, },
computed: { computed: {
isGamemasterOrAdmin() {
const user = this.$store.state.engine.user
return user && ['gamemaster', 'admin'].indexOf(user.role) != -1
},
user() { user() {
return this.$store.state.engine.user || {} return this.$store.state.engine.user || {}
}, },

View File

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

View File

@ -4,6 +4,7 @@ import stop from './stop'
import fetchUpdate from './fetchUpdate' import fetchUpdate from './fetchUpdate'
import fetchUserInfo from './fetchUserInfo' import fetchUserInfo from './fetchUserInfo'
import fetchGameInfo from './fetchGameInfo' import fetchGameInfo from './fetchGameInfo'
import fetchGames from './fetchGames'
import setGameName from './setGameName' import setGameName from './setGameName'
import savePlayer from './savePlayer' import savePlayer from './savePlayer'
import deletePlayer from './deletePlayer' import deletePlayer from './deletePlayer'
@ -32,6 +33,7 @@ export default (context, inject) => {
fetchUpdate, fetchUpdate,
fetchUserInfo, fetchUserInfo,
fetchGameInfo, fetchGameInfo,
fetchGames,
setGameName, setGameName,
savePlayer, savePlayer,
deletePlayer, deletePlayer,

View File

@ -3,6 +3,7 @@ export const state = () => ({
version: -1, version: -1,
user: undefined, user: undefined,
gameinfo: undefined, gameinfo: undefined,
games: undefined,
}) })
export const mutations = { export const mutations = {
@ -19,4 +20,7 @@ export const mutations = {
setGameInfo(state, gameinfo) { setGameInfo(state, gameinfo) {
state.gameinfo = gameinfo state.gameinfo = gameinfo
}, },
setGames(state, games) {
state.games = games
}
} }

View File

@ -0,0 +1,35 @@
package application
import (
"encoding/json"
"fmt"
"net/http"
"sirlab.de/go/knowyt/game"
"sirlab.de/go/knowyt/user"
)
type Games struct {
Games map[string]*game.GameInfoJson `json:"games"`
}
func (app *Application) GetGames(usr *user.User, w http.ResponseWriter, r *http.Request) {
if !usr.IsAdmin() {
w.WriteHeader(http.StatusForbidden)
fmt.Fprintf(w, "forbidden")
return
}
app.mu.Lock()
defer app.mu.Unlock()
games := Games{
Games: make(map[string]*game.GameInfoJson),
}
for k, gm := range app.games {
games.Games[k] = gm.GetGameInfo()
}
w.Header().Add("Content-Type", "application/json")
jsonString, _ := json.Marshal(games)
fmt.Fprintf(w, string(jsonString))
}

View File

@ -22,6 +22,7 @@ func main() {
mux.PublicHandleFunc("/api/logout", mux.Logout) mux.PublicHandleFunc("/api/logout", mux.Logout)
mux.PrivateHandleFunc("/api/userinfo", mux.GetUserInfo) mux.PrivateHandleFunc("/api/userinfo", mux.GetUserInfo)
mux.PrivateHandleFunc("/api/gameinfo", app.GetGameInfo) mux.PrivateHandleFunc("/api/gameinfo", app.GetGameInfo)
mux.PrivateHandleFunc("/api/games", app.GetGames)
mux.PrivateHandleFunc("/api/setGameName", app.SetGameName) mux.PrivateHandleFunc("/api/setGameName", app.SetGameName)
mux.PrivateHandleFunc("/api/savePlayer", app.SavePlayer) mux.PrivateHandleFunc("/api/savePlayer", app.SavePlayer)
mux.PrivateHandleFunc("/api/deletePlayer", app.DeletePlayer) mux.PrivateHandleFunc("/api/deletePlayer", app.DeletePlayer)