feat: make game name and lang editable on gamemaster page

This commit is contained in:
Settel 2022-09-04 14:47:12 +02:00
parent 9a5c647523
commit 604b4f9f08
6 changed files with 285 additions and 24 deletions

View File

@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns="http://www.w3.org/2000/svg"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns:ns1="http://sozi.baierouge.fr"
xmlns:xlink="http://www.w3.org/1999/xlink"
id="svg6254"
sodipodi:docname="新規ドキュメント 9"
viewBox="0 0 128 128"
version="1.1"
inkscape:version="0.48.2 r9819"
>
<title
id="title7073"
>Pencil Pictogram</title
>
<sodipodi:namedview
id="base"
bordercolor="#666666"
inkscape:pageshadow="2"
inkscape:window-y="-4"
fit-margin-left="0"
pagecolor="#000000"
fit-margin-top="0"
inkscape:window-maximized="1"
inkscape:zoom="4.0745363"
inkscape:window-x="-4"
inkscape:window-height="1017"
showgrid="false"
borderopacity="1.0"
inkscape:current-layer="layer1"
inkscape:cx="45.584279"
inkscape:cy="49.522511"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:window-width="1920"
inkscape:pageopacity="0.0"
inkscape:document-units="px"
/>
<g
id="layer1"
inkscape:label="レイヤー 1"
inkscape:groupmode="layer"
transform="translate(-222.76 -630.44)"
>
<g
id="g7066"
transform="matrix(1.7183 0 0 1.7068 -160 -536.05)"
>
<path
id="path5336-6"
sodipodi:nodetypes="ccccc"
style="stroke-linejoin:round;stroke:#ffffff;stroke-linecap:round;stroke-width:2.6122;fill:none"
inkscape:connector-curvature="0"
d="m295.94 710.91l-36.816 36.816-35.073 9.3978 9.3949-35.062 37.195-37.195"
/>
<rect
id="rect5338-48"
style="fill:#fff0ff"
transform="matrix(-.26499 -.96425 .70711 -.70711 0 0)"
rx="1.8358"
ry="1.8187"
height="53.027"
width="9.58"
y="60.3"
x="-820.59"
/>
<rect
id="rect5338-4-2"
ry="1.8187"
style="fill:#fff0ff"
rx="1.377"
transform="rotate(225)"
height="53.819"
width="16.654"
y="-340.44"
x="-702.13"
/>
<rect
id="rect5338-1-1"
style="fill:#fff0ff"
transform="matrix(.96593 .25882 .70711 -.70711 0 0)"
rx="1.836"
ry="1.8187"
height="53.819"
width="9.6152"
y="-734.79"
x="778.66"
/>
<path
id="path5336-1-6"
style="stroke-linejoin:round;stroke:#ffffff;stroke-linecap:round;stroke-width:2.6122;fill:#a0a0a0"
inkscape:connector-curvature="0"
d="m224.06 757.12 18.038-4.8199-13.219-13.219-4.8199 18.038z"
/>
</g
>
</g
>
<metadata
>
<rdf:RDF
>
<cc:Work
>
<dc:format
>image/svg+xml</dc:format
>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage"
/>
<cc:license
rdf:resource="http://creativecommons.org/licenses/publicdomain/"
/>
<dc:publisher
>
<cc:Agent
rdf:about="http://openclipart.org/"
>
<dc:title
>Openclipart</dc:title
>
</cc:Agent
>
</dc:publisher
>
<dc:title
>Pencil Pictogram</dc:title
>
<dc:date
>2013-11-16T20:22:22</dc:date
>
<dc:description
>black pencil pictogram.</dc:description
>
<dc:source
>https://openclipart.org/detail/188837/pencil-pictogram-by-libberry-188837</dc:source
>
<dc:creator
>
<cc:Agent
>
<dc:title
>libberry</dc:title
>
</cc:Agent
>
</dc:creator
>
<dc:subject
>
<rdf:Bag
>
<rdf:li
>learning</rdf:li
>
<rdf:li
>pencil</rdf:li
>
<rdf:li
>stationery</rdf:li
>
<rdf:li
>study</rdf:li
>
<rdf:li
>writing</rdf:li
>
</rdf:Bag
>
</dc:subject
>
</cc:Work
>
<cc:License
rdf:about="http://creativecommons.org/licenses/publicdomain/"
>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Reproduction"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#Distribution"
/>
<cc:permits
rdf:resource="http://creativecommons.org/ns#DerivativeWorks"
/>
</cc:License
>
</rdf:RDF
>
</metadata
>
</svg
>

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -62,7 +62,7 @@
/> />
<rect <rect
id="rect5338-48" id="rect5338-48"
style="fill:#000200" style="fill:#ff0200"
transform="matrix(-.26499 -.96425 .70711 -.70711 0 0)" transform="matrix(-.26499 -.96425 .70711 -.70711 0 0)"
rx="1.8358" rx="1.8358"
ry="1.8187" ry="1.8187"
@ -74,7 +74,7 @@
<rect <rect
id="rect5338-4-2" id="rect5338-4-2"
ry="1.8187" ry="1.8187"
style="fill:#000200" style="fill:#ff0200"
rx="1.377" rx="1.377"
transform="rotate(225)" transform="rotate(225)"
height="53.819" height="53.819"
@ -84,7 +84,7 @@
/> />
<rect <rect
id="rect5338-1-1" id="rect5338-1-1"
style="fill:#000200" style="fill:#ff0200"
transform="matrix(.96593 .25882 .70711 -.70711 0 0)" transform="matrix(.96593 .25882 .70711 -.70711 0 0)"
rx="1.836" rx="1.836"
ry="1.8187" ry="1.8187"

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,36 +1,46 @@
<template> <template>
<AdminTile title="Game"> <AdminTile title="Game">
<table> <table>
<tr> <tr class="gameinfo-tile__row">
<td>{{ $t('name') }}:</td> <td>{{ $t('name') }}:</td>
<td>{{ gameinfo.name }}</td> <td>{{ gameinfo.name }}</td>
<td> <td>
<div class="gameinfo-tile__edit-game-name" @click="editName"></div> <div class="gameinfo-tile__edit" @click="editName">
<Icon name="edit-white" />
</div>
</td> </td>
</tr> </tr>
<tr> <tr class="gameinfo-tile__row">
<td>{{ $t('language') }}:</td> <td>{{ $t('language') }}:</td>
<td>{{ gameinfo.lang }}</td> <td v-if="!editLangShowDropdown">{{ gameinfo.lang }}</td>
<td> <td v-if="!editLangShowDropdown">
<div class="gameinfo-tile__edit-lang" @click="editLang"></div> <div class="gameinfo-tile__edit" @click="editLang">
<Icon name="edit-white" />
</div>
</td>
<td v-if="editLangShowDropdown" colspan="2">
<select v-model="lang" @change="editLangChange">
<option value="en">en</option>
<option value="de">de</option>
</select>
</td> </td>
</tr> </tr>
<tr> <tr class="gameinfo-tile__row">
<td>{{ $t('created') }}:</td> <td>{{ $t('created') }}:</td>
<td colspan="2">{{ date(gameinfo.created) }}</td> <td colspan="2">{{ date(gameinfo.created) }}</td>
</tr> </tr>
<tr> <tr class="gameinfo-tile__row">
<td>{{ $t('num-players') }}:</td> <td>{{ $t('num-players') }}:</td>
<td colspan="2">{{ gameinfo.players.length }}</td> <td colspan="2">{{ gameinfo.players.length }}</td>
</tr> </tr>
<tr> <tr class="gameinfo-tile__row">
<td>{{ $t('num-quotes-played') }}:</td> <td>{{ $t('num-quotes-played') }}:</td>
<td colspan="2">{{ gameinfo.numQuotesLeft - gameinfo.numQuotesLeft }} / {{ gameinfo.numQuotesTotal }}</td> <td colspan="2">{{ gameinfo.numQuotesLeft - gameinfo.numQuotesLeft }} / {{ gameinfo.numQuotesTotal }}</td>
</tr> </tr>
<tr v-if="!showId" @click="showId = true"> <tr class="gameinfo-tile__row" v-if="!showId" @click="showId = true">
<td colspan="3">&nbsp;</td> <td colspan="3">&nbsp;</td>
</tr> </tr>
<tr v-if="showId"> <tr class="gameinfo-tile__row" v-if="showId">
<td colspan="3">{{ gameinfo.id }}</td> <td colspan="3">{{ gameinfo.id }}</td>
</tr> </tr>
</table> </table>
@ -41,13 +51,15 @@
import { ref } from 'vue' import { ref } from 'vue'
import useI18n from '@/composables/useI18n' import useI18n from '@/composables/useI18n'
import useDateFormatter from '@/composables/useDateFormatter'; import useDateFormatter from '@/composables/useDateFormatter';
import useEngine from '@/composables/useEngine'
import type { GameInfo } from '@/composables/engine.d' import type { GameInfo } from '@/composables/engine.d'
const { date } = useDateFormatter() const { date } = useDateFormatter()
defineProps<{ const props = defineProps<{
gameinfo: GameInfo gameinfo: GameInfo
}>() }>()
const emit = defineEmits(['update'])
const { $t } = useI18n({ const { $t } = useI18n({
id: { en: 'Id', de: 'Id' }, id: { en: 'Id', de: 'Id' },
@ -55,13 +67,28 @@ const { $t } = useI18n({
language: { en: 'Language', de: 'Sprache' }, language: { en: 'Language', de: 'Sprache' },
created: { en: 'Created', de: 'Erstellt' }, created: { en: 'Created', de: 'Erstellt' },
'num-players': { en: '# Players', de: '# Spieler' }, 'num-players': { en: '# Players', de: '# Spieler' },
'num-quotes-played': { en: '# Quotes played', de: '# Aussagen gespielt'} 'num-quotes-played': { en: '# Quotes played', de: '# Aussagen gespielt' },
'new-game-name': { en: 'New game name', de: 'Neuer Spielname' },
}) })
const editName = () => { alert('not yet implemented') }
const editLang = () => { alert('not yet implemented') }
const showId = ref(false) const showId = ref(false)
const editName = async (): Promise<void> => {
const name = window.prompt(`${$t('new-game-name')}: `)
if (name) {
await useEngine().setGameName(name)
emit('update')
}
}
const lang = ref(props.gameinfo.lang)
const editLangShowDropdown = ref(false)
const editLang = () => { editLangShowDropdown.value = true }
const editLangChange = async (): Promise<void> => {
editLangShowDropdown.value = false
await useEngine().setGameLang(lang.value)
emit('update')
}
</script> </script>
<style lang="scss"> <style lang="scss">
@ -70,5 +97,16 @@ const showId = ref(false)
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
&__row {
height: 24px;
}
&__edit {
margin-left: 24px;
width: 16px;
height: 16px;
cursor: pointer;
}
} }
</style> </style>

View File

@ -43,3 +43,19 @@ export async function fetchGameInfo(this: EngineContext): Promise<GameInfo> {
g: userInfoStore.gameId, g: userInfoStore.gameId,
}) as GameInfo }) as GameInfo
} }
export async function setGameLang(this: EngineContext, lang: string): Promise<void> {
const userInfoStore = useUserinfoStore()
await this.callApi('/api/setGameLang', {
g: userInfoStore.gameId,
lang,
})
}
export async function setGameName(this: EngineContext, name: string): Promise<void> {
const userInfoStore = useUserinfoStore()
await this.callApi('/api/setGameName', {
g: userInfoStore.gameId,
name,
})
}

View File

@ -3,7 +3,7 @@ import { callApi, QueryParams } from '@/composables/engine/callApi'
import { start, stop } from '@/composables/engine/startStop' import { start, stop } from '@/composables/engine/startStop'
import { fetchUpdate } from '@/composables/engine/fetchUpdate' import { fetchUpdate } from '@/composables/engine/fetchUpdate'
import { loadQuotes, getQuotesRef, deleteQuote, saveQuote } from '@/composables/engine/quotes' import { loadQuotes, getQuotesRef, deleteQuote, saveQuote } from '@/composables/engine/quotes'
import { collectQuotes, startGame, continueGame, resetGame, finishGame, fetchGameInfo } from '@/composables/engine/gamemaster' import { collectQuotes, startGame, continueGame, resetGame, finishGame, fetchGameInfo, setGameLang, setGameName } from '@/composables/engine/gamemaster'
import { saveSelection } from '@/composables/engine/play' import { saveSelection } from '@/composables/engine/play'
import type { Quotes, GameInfo } from '@/composables/engine.d' import type { Quotes, GameInfo } from '@/composables/engine.d'
@ -37,6 +37,8 @@ export interface useEngine {
finishGame: () => Promise<void> finishGame: () => Promise<void>
saveSelection: (selection: string) => Promise<void> saveSelection: (selection: string) => Promise<void>
fetchGameInfo: () => Promise<GameInfo> fetchGameInfo: () => Promise<GameInfo>
setGameLang: (lang: string) => Promise<void>
setGameName: (name: string) => Promise<void>
} }
export default (): useEngine => { export default (): useEngine => {
@ -71,5 +73,7 @@ export default (): useEngine => {
finishGame: () => finishGame.apply(context), finishGame: () => finishGame.apply(context),
saveSelection: (selection: string) => saveSelection.apply(context, [selection]), saveSelection: (selection: string) => saveSelection.apply(context, [selection]),
fetchGameInfo: () => fetchGameInfo.apply(context), fetchGameInfo: () => fetchGameInfo.apply(context),
setGameLang: (lang: string) => setGameLang.apply(context, [lang]),
setGameName: (name: string) => setGameName.apply(context, [name]),
} }
} }

View File

@ -2,7 +2,7 @@
<div class="gamemaster__container"> <div class="gamemaster__container">
<TopBar /> <TopBar />
<div class="gamemaster__tiles"> <div class="gamemaster__tiles">
<AdminGameInfoTile :gameinfo="gameinfo" /> <AdminGameInfoTile :gameinfo="gameinfo" @update="updateGameinfo" />
<div class="gamemaster__tiles-spacer" /> <div class="gamemaster__tiles-spacer" />
</div> </div>
</div> </div>
@ -10,7 +10,7 @@
<script setup lang="ts"> <script setup lang="ts">
import { navigateTo } from '#app' import { navigateTo } from '#app'
import { onMounted, onBeforeUnmount } from 'vue' import { ref } from 'vue'
import useAuth from '@/composables/useAuth' import useAuth from '@/composables/useAuth'
import useEngine from '@/composables/useEngine' import useEngine from '@/composables/useEngine'
@ -23,7 +23,10 @@ try {
} }
const { fetchGameInfo } = useEngine() const { fetchGameInfo } = useEngine()
const gameinfo = await fetchGameInfo() const gameinfo = ref(await fetchGameInfo())
const updateGameinfo = async (): Promise<void> => {
gameinfo.value = await fetchGameInfo()
}
</script> </script>
<style lang="scss"> <style lang="scss">