only empty seats can be claimed by players and ST can clear seats now

This commit is contained in:
Steffen 2020-12-15 15:59:43 +01:00
parent 7c0f31584c
commit 53d608288d
13 changed files with 68 additions and 50 deletions

View File

@ -3,11 +3,11 @@
id="app" id="app"
@keyup="keyup" @keyup="keyup"
tabindex="-1" tabindex="-1"
v-bind:class="{ :class="{
screenshot: grimoire.isScreenshot, screenshot: grimoire.isScreenshot,
night: grimoire.isNight night: grimoire.isNight
}" }"
v-bind:style="{ :style="{
backgroundImage: grimoire.background backgroundImage: grimoire.background
? `url('${grimoire.background}')` ? `url('${grimoire.background}')`
: '' : ''

View File

@ -26,7 +26,7 @@
:class="{ success: grimoire.isScreenshotSuccess }" :class="{ success: grimoire.isScreenshotSuccess }"
/> />
</span> </span>
<div class="menu" v-bind:class="{ open: grimoire.isMenuOpen }"> <div class="menu" :class="{ open: grimoire.isMenuOpen }">
<font-awesome-icon icon="cog" @click="toggleMenu" /> <font-awesome-icon icon="cog" @click="toggleMenu" />
<ul> <ul>
<li class="tabs" :class="tab"> <li class="tabs" :class="tab">

View File

@ -100,7 +100,7 @@
<div <div
class="name" class="name"
@click="isMenuOpen = !isMenuOpen" @click="isMenuOpen = !isMenuOpen"
v-bind:class="{ active: isMenuOpen }" :class="{ active: isMenuOpen }"
> >
{{ player.name }} {{ player.name }}
</div> </div>
@ -131,13 +131,27 @@
<font-awesome-icon icon="times-circle" /> <font-awesome-icon icon="times-circle" />
Remove Remove
</li> </li>
</template> <li
<li @click="claimSeat" v-if="session.isSpectator"> @click="updatePlayer('id', '', true)"
v-if="player.id && session.sessionId"
>
<font-awesome-icon icon="chair" /> <font-awesome-icon icon="chair" />
<template v-if="player.id !== session.playerId"> Vacate seat
</li>
</template>
<li
@click="claimSeat"
v-if="session.isSpectator"
:class="{ disabled: player.id && player.id !== session.playerId }"
>
<font-awesome-icon icon="chair" />
<template v-if="!player.id">
Claim seat Claim seat
</template> </template>
<template v-else> Vacate seat </template> <template v-else-if="player.id === session.playerId">
Vacate seat
</template>
<template v-else> Seat occupied</template>
</li> </li>
</ul> </ul>
</transition> </transition>
@ -146,14 +160,14 @@
<template v-if="player.reminders"> <template v-if="player.reminders">
<div <div
class="reminder" class="reminder"
v-bind:key="reminder.role + ' ' + reminder.name" :key="reminder.role + ' ' + reminder.name"
v-for="reminder in player.reminders" v-for="reminder in player.reminders"
v-bind:class="[reminder.role]" :class="[reminder.role]"
@click="removeReminder(reminder)" @click="removeReminder(reminder)"
> >
<span <span
class="icon" class="icon"
v-bind:style="{ :style="{
backgroundImage: `url(${reminder.image || backgroundImage: `url(${reminder.image ||
require('../assets/icons/' + reminder.role + '.png')})` require('../assets/icons/' + reminder.role + '.png')})`
}" }"
@ -244,22 +258,23 @@ export default {
changeName() { changeName() {
if (this.session.isSpectator) return; if (this.session.isSpectator) return;
const name = prompt("Player name", this.player.name) || this.player.name; const name = prompt("Player name", this.player.name) || this.player.name;
this.updatePlayer("name", name); this.updatePlayer("name", name, true);
this.isMenuOpen = false;
}, },
removeReminder(reminder) { removeReminder(reminder) {
const reminders = [...this.player.reminders]; const reminders = [...this.player.reminders];
reminders.splice(this.player.reminders.indexOf(reminder), 1); reminders.splice(this.player.reminders.indexOf(reminder), 1);
this.updatePlayer("reminders", reminders); this.updatePlayer("reminders", reminders, true);
this.isMenuOpen = false;
}, },
updatePlayer(property, value) { updatePlayer(property, value, closeMenu = false) {
if (this.session.isSpectator && property !== "reminders") return; if (this.session.isSpectator && property !== "reminders") return;
this.$store.commit("players/update", { this.$store.commit("players/update", {
player: this.player, player: this.player,
property, property,
value value
}); });
if (closeMenu) {
this.isMenuOpen = false;
}
}, },
removePlayer() { removePlayer() {
this.isMenuOpen = false; this.isMenuOpen = false;
@ -661,6 +676,14 @@ li.move:not(.from) .player .overlay svg.move {
li:hover { li:hover {
color: red; color: red;
} }
li.disabled {
cursor: default;
&:hover {
color: white;
}
}
svg { svg {
margin-right: 2px; margin-right: 2px;
} }

View File

@ -3,7 +3,7 @@
<span <span
class="icon" class="icon"
v-if="role.id" v-if="role.id"
v-bind:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${role.image ||
require('../assets/icons/' + role.id + '.png')})` require('../assets/icons/' + role.id + '.png')})`
}" }"
@ -18,7 +18,7 @@
></span> ></span>
<span <span
v-if="role.reminders && role.reminders.length" v-if="role.reminders && role.reminders.length"
v-bind:class="['leaf-top' + role.reminders.length]" :class="['leaf-top' + role.reminders.length]"
></span> ></span>
<span class="leaf-orange" v-if="role.setup"></span> <span class="leaf-orange" v-if="role.setup"></span>
<svg viewBox="0 0 150 150" class="name"> <svg viewBox="0 0 150 150" class="name">
@ -32,17 +32,14 @@
x="66.6%" x="66.6%"
text-anchor="middle" text-anchor="middle"
class="label mozilla" class="label mozilla"
v-bind:font-size="role.name | nameToFontSize" :font-size="role.name | nameToFontSize"
> >
<textPath xlink:href="#curve"> <textPath xlink:href="#curve">
{{ role.name }} {{ role.name }}
</textPath> </textPath>
</text> </text>
</svg> </svg>
<div <div class="edition" :class="[`edition-${role.edition}`, role.team]"></div>
class="edition"
v-bind:class="[`edition-${role.edition}`, role.team]"
></div>
<div class="ability" v-if="role.ability"> <div class="ability" v-if="role.ability">
{{ role.ability }} {{ role.ability }}
</div> </div>

View File

@ -1,6 +1,6 @@
<template> <template>
<ul class="info"> <ul class="info">
<li class="edition" v-bind:class="['edition-' + edition]"></li> <li class="edition" :class="['edition-' + edition]"></li>
<li v-if="players.length - teams.traveler < 5"> <li v-if="players.length - teams.traveler < 5">
Please add more players! Please add more players!
</li> </li>
@ -15,23 +15,23 @@
{{ teams.outsider }} {{ teams.outsider }}
<font-awesome-icon <font-awesome-icon
class="outsider" class="outsider"
v-bind:icon="teams.outsider > 1 ? 'user-friends' : 'user'" :icon="teams.outsider > 1 ? 'user-friends' : 'user'"
/> />
{{ teams.minion }} {{ teams.minion }}
<font-awesome-icon <font-awesome-icon
class="minion" class="minion"
v-bind:icon="teams.minion > 1 ? 'user-friends' : 'user'" :icon="teams.minion > 1 ? 'user-friends' : 'user'"
/> />
{{ teams.demon }} {{ teams.demon }}
<font-awesome-icon <font-awesome-icon
class="demon" class="demon"
v-bind:icon="teams.demon > 1 ? 'user-friends' : 'user'" :icon="teams.demon > 1 ? 'user-friends' : 'user'"
/> />
<template v-if="teams.traveler"> <template v-if="teams.traveler">
{{ teams.traveler }} {{ teams.traveler }}
<font-awesome-icon <font-awesome-icon
class="traveler" class="traveler"
v-bind:icon="teams.traveler > 1 ? 'user-friends' : 'user'" :icon="teams.traveler > 1 ? 'user-friends' : 'user'"
/> />
</template> </template>
<template v-if="grimoire.isNight"> <template v-if="grimoire.isNight">

View File

@ -2,20 +2,20 @@
<div <div
id="townsquare" id="townsquare"
class="square" class="square"
v-bind:class="{ :class="{
public: grimoire.isPublic, public: grimoire.isPublic,
spectator: session.isSpectator, spectator: session.isSpectator,
vote: session.nomination vote: session.nomination
}" }"
> >
<ul class="circle" v-bind:class="['size-' + players.length]"> <ul class="circle" :class="['size-' + players.length]">
<Player <Player
v-for="(player, index) in players" v-for="(player, index) in players"
:key="index" :key="index"
:player="player" :player="player"
@screenshot="$emit('screenshot', $event)" @screenshot="$emit('screenshot', $event)"
@trigger="handleTrigger(index, $event)" @trigger="handleTrigger(index, $event)"
v-bind:class="{ :class="{
from: Math.max(swap, move, nominate) === index, from: Math.max(swap, move, nominate) === index,
swap: swap > -1, swap: swap > -1,
move: move > -1, move: move > -1,

View File

@ -6,8 +6,8 @@
<li <li
v-for="edition in editions" v-for="edition in editions"
class="edition" class="edition"
v-bind:class="['edition-' + edition.id]" :class="['edition-' + edition.id]"
v-bind:key="edition.id" :key="edition.id"
@click="setEdition(edition.id)" @click="setEdition(edition.id)"
> >
{{ edition.name }} {{ edition.name }}
@ -39,7 +39,7 @@
<ul class="scripts"> <ul class="scripts">
<li <li
v-for="(script, index) in scripts" v-for="(script, index) in scripts"
v-bind:key="index" :key="index"
@click="handleURL(script[1])" @click="handleURL(script[1])"
> >
{{ script[0] }} {{ script[0] }}

View File

@ -4,7 +4,7 @@
Choose a fabled character to add to the game Choose a fabled character to add to the game
</h3> </h3>
<ul class="tokens"> <ul class="tokens">
<li v-for="role in fabled" v-bind:key="role.id" @click="setFabled(role)"> <li v-for="role in fabled" :key="role.id" @click="setFabled(role)">
<Token :role="role" /> <Token :role="role" />
</li> </li>
</ul> </ul>

View File

@ -29,7 +29,7 @@
<span <span
class="icon" class="icon"
v-if="role.id" v-if="role.id"
v-bind:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${role.image ||
require('../../assets/icons/' + role.id + '.png')})` require('../../assets/icons/' + role.id + '.png')})`
}" }"
@ -46,7 +46,7 @@
<span <span
class="icon" class="icon"
v-if="role.id" v-if="role.id"
v-bind:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${role.image ||
require('../../assets/icons/' + role.id + '.png')})` require('../../assets/icons/' + role.id + '.png')})`
}" }"

View File

@ -33,7 +33,7 @@
<span <span
class="icon" class="icon"
v-if="role.id" v-if="role.id"
v-bind:style="{ :style="{
backgroundImage: `url(${role.image || backgroundImage: `url(${role.image ||
require('../../assets/icons/' + role.id + '.png')})` require('../../assets/icons/' + role.id + '.png')})`
}" }"

View File

@ -14,8 +14,8 @@
<ul class="tokens"> <ul class="tokens">
<li <li
v-for="role in availableRoles" v-for="role in availableRoles"
v-bind:class="[role.team]" :class="[role.team]"
v-bind:key="role.id" :key="role.id"
@click="setRole(role)" @click="setRole(role)"
> >
<Token :role="role" /> <Token :role="role" />

View File

@ -5,19 +5,15 @@
@close="toggleModal('roles')" @close="toggleModal('roles')"
> >
<h3>Select the characters for {{ nonTravelers }} players:</h3> <h3>Select the characters for {{ nonTravelers }} players:</h3>
<ul <ul class="tokens" v-for="(teamRoles, team) in roleSelection" :key="team">
class="tokens" <li class="count" :class="[team]">
v-for="(teamRoles, team) in roleSelection"
v-bind:key="team"
>
<li class="count" v-bind:class="[team]">
{{ teamRoles.filter(role => role.selected).length }} / {{ teamRoles.filter(role => role.selected).length }} /
{{ game[nonTravelers - 5][team] }} {{ game[nonTravelers - 5][team] }}
</li> </li>
<li <li
v-for="role in teamRoles" v-for="role in teamRoles"
v-bind:class="[role.team, role.selected ? 'selected' : '']" :class="[role.team, role.selected ? 'selected' : '']"
v-bind:key="role.id" :key="role.id"
@click="role.selected = !role.selected" @click="role.selected = !role.selected"
> >
<Token :role="role" /> <Token :role="role" />
@ -31,7 +27,7 @@
<div <div
class="button" class="button"
@click="assignRoles" @click="assignRoles"
v-bind:class="{ :class="{
disabled: selectedRoles > nonTravelers || !selectedRoles disabled: selectedRoles > nonTravelers || !selectedRoles
}" }"
> >

View File

@ -510,11 +510,13 @@ class LiveSession {
/** /**
* Claim a seat, needs to be confirmed by the Storyteller. * Claim a seat, needs to be confirmed by the Storyteller.
* @param seat either -1 or the index of the seat claimed * Seats already occupied can't be claimed.
* @param seat either -1 to vacate or the index of the seat claimed
*/ */
claimSeat(seat) { claimSeat(seat) {
if (!this._isSpectator) return; if (!this._isSpectator) return;
if (this._store.state.players.players.length > seat) { const players = this._store.state.players.players;
if (players.length > seat && (seat < 0 || !players[seat].id)) {
this._send("claim", [seat, this._store.state.session.playerId]); this._send("claim", [seat, this._store.state.session.playerId]);
} }
} }