Skip to content

Commit

Permalink
Merge branch 'release/1.0.3'
Browse files Browse the repository at this point in the history
  • Loading branch information
stefanseifert committed Nov 15, 2023
2 parents 9264eba + 747a4ce commit 429d605
Show file tree
Hide file tree
Showing 9 changed files with 102 additions and 32 deletions.
13 changes: 11 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@brdgm/carnegie-solo-helper",
"version": "1.0.2",
"version": "1.0.3",
"private": true,
"description": "Carnegie Solo Helper",
"appDeployName": "carnegie",
Expand All @@ -21,6 +21,7 @@
"lodash": "~4.17.21",
"pinia": "^2.1.7",
"pinia-plugin-persistedstate": "^3.2.0",
"set-interval-async": "^3.0.3",
"vue": "~3.3.8",
"vue-i18n": "~9.6.5",
"vue-router": "~4.2.5"
Expand Down
25 changes: 24 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import getErrorMessage from 'brdgm-commons/src/util/error/getErrorMessage'
import showModal, { showModalIfExist } from 'brdgm-commons/src/util/modal/showModal'
import { version, description } from '@/../package.json'
import { registerSW } from 'virtual:pwa-register'
import { setIntervalAsync } from 'set-interval-async';
export default defineComponent({
name: 'App',
Expand All @@ -78,8 +79,30 @@ export default defineComponent({
})
const state = useStateStore()
// PWA refresh
// handle PWA updates with prompt if a new version is detected, check every 8h for a new version
const checkForNewVersionsIntervalMilliseconds = 8 * 60 * 60 * 1000
const updateServiceWorker = registerSW({
// check for new app version, see https://vite-pwa-org.netlify.app/guide/periodic-sw-updates.html
onRegisteredSW(swScriptUrl : string, registration? : ServiceWorkerRegistration) {
registration && setIntervalAsync(async () => {
if (!(!registration.installing && navigator)) {
return
}
if (('connection' in navigator) && !navigator.onLine) {
return
}
const resp = await fetch(swScriptUrl, {
cache: 'no-store',
headers: {
'cache': 'no-store',
'cache-control': 'no-cache',
}
})
if (resp?.status === 200) {
await registration.update()
}
}, checkForNewVersionsIntervalMilliseconds)
},
onNeedRefresh() {
showModalIfExist('serviceWorkerUpdatedRefresh')
}
Expand Down
5 changes: 4 additions & 1 deletion src/components/round/SideBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
</div>

<DepartmentShop id="sidebarDepartmentShopModal" :departments="availableDepartments"
:playerDepartments="playerDepartments" :botDepartments="botDepartments"/>
:playerReserveDepartments="playerReserveDepartments" :playerDepartments="playerDepartments" :botDepartments="botDepartments"/>

<ModalDialog id="sidebarTimelineModal" :title="t('sideBar.timeline')" :size-xl="true" :scrollable="true">
<template #body>
Expand Down Expand Up @@ -74,6 +74,9 @@ export default defineComponent({
return [...removeDepartments(this.navigationState.departments,
this.navigationState.playerNewDepartments, this.navigationState.botNewDepartments)]
},
playerReserveDepartments() : string[] {
return [...removeDepartments(this.navigationState.playerReserveDepartments,this.navigationState.playerNewDepartments)]
},
playerDepartments() : string[] {
return [...addDepartments(this.navigationState.playerDepartments,this.navigationState.playerNewDepartments)]
},
Expand Down
2 changes: 1 addition & 1 deletion src/components/setup/DepartmentSelection.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<h3 class="mt-4 mb-3">{{t('setup.departmentSelection.title')}}</h3>

<div class="row">
<div class="offset-md-1">
<div class="offset-md-1 col-md-10">

<div class="form-check" v-for="departmentSelectionType of departmentSelectionTypes" :key="departmentSelectionType">
<label class="form-check-label">
Expand Down
60 changes: 41 additions & 19 deletions src/components/structure/DepartmentShop.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,39 @@
<template #body>

<ul class="nav nav-tabs">
<li class="nav-item" v-if="(playerReserveDepartments ?? []).length > 0">
<a id="tablink-player-reserve" class="nav-link" :class="{active:departmentView=='playerReserve'}" href="#" @click.prevent="showDepartments('playerReserve')">{{t('departmentShop.playerReserve')}}</a>
</li>
<li class="nav-item">
<a class="nav-link" :class="{active:!departmentView}" href="#" @click.prevent="showDepartments()">{{t('departmentShop.available')}}</a>
<a class="nav-link" :class="{active:departmentView=='available'}" href="#" @click.prevent="showDepartments('available')">{{t('departmentShop.available')}}</a>
</li>
<li class="nav-item" v-if="(playerDepartments ?? []).length > 0">
<a class="nav-link" :class="{active:departmentView==playerPlayer}" href="#" @click.prevent="showDepartments(playerPlayer)">{{t('departmentShop.player')}}</a>
<a class="nav-link" :class="{active:departmentView=='player'}" href="#" @click.prevent="showDepartments('player')">{{t('departmentShop.player')}}</a>
</li>
<li class="nav-item" v-if="(botDepartments ?? []).length > 0">
<a class="nav-link" :class="{active:departmentView==playerBot}" href="#" @click.prevent="showDepartments(playerBot)">{{t('departmentShop.bot')}}</a>
<a class="nav-link" :class="{active:departmentView=='bot'}" href="#" @click.prevent="showDepartments('bot')">{{t('departmentShop.bot')}}</a>
</li>
</ul>

<div class="border departmentContent">
<div v-if="selectedDepartment" class="p-4">
<div class="alert alert-warning" role="alert" v-if="!isAllowed">{{t('departmentShop.selectionNotAllowed')}}</div>
<div class="alert alert-warning" role="alert" v-if="isDepartmentSelectionPossible && isDuplicateDepartment" v-html="t('departmentShop.duplicateDepartmentWarning')"></div>
<div class="alert alert-warning" role="alert" v-if="isDepartmentSelectionPossible && isNotPlayerReserveWhichIsNotEmpty" v-html="t('departmentShop.playerReserveWarning')"></div>
<div class="department float-md-start ms-3 me-4 mb-3">
<AppIcon type="department" :name="selectedDepartment.department.id" extension="jpg"
class="icon single"
:title="t(`department.${selectedDepartment.department.id}.title`)"
@click="backToOverview"/>
</div>
<h5>{{t(`department.${selectedDepartment.department.id}.title`)}}</h5>
<p v-if="!selectedDepartment.department.expansion" v-html="t(`department.${selectedDepartment.department.id}.description`)"></p>
<p v-if="!selectedDepartment.department.expansion" v-html="t(`department.${selectedDepartment.department.id}.description`)" class="fst-italic"></p>
<p v-html="t(`department.${selectedDepartment.department.id}.rules`)"></p>
<div class="clearfix"></div>
<div class="mt-2">
<button class="btn btn-secondary" @click="backToOverview">&lt; {{t('action.back')}}</button>
<button class="btn btn-primary ms-2" data-bs-dismiss="modal" @click="selectDepartment(selectedDepartment.department)"
v-if="select && departmentView == undefined" :disabled="!isAllowed">{{t('departmentShop.selectDepartment')}}</button>
v-if="isDepartmentSelectionPossible"
:disabled="isDuplicateDepartment || isNotPlayerReserveWhichIsNotEmpty">{{t('departmentShop.selectDepartment')}}</button>
</div>
</div>

Expand Down Expand Up @@ -58,7 +63,6 @@ import AppIcon from '@/components/structure/AppIcon.vue'
import GroupedDepartments, { DepartmentCount, DepartmentGroup } from '@/services/GroupedDepartments'
import ModalDialog from 'brdgm-commons/src/components/structure/ModalDialog.vue'
import Department from '@/services/Department'
import Player from '@/services/enum/Player'
export default defineComponent({
name: 'DepartmentShop',
Expand All @@ -74,10 +78,18 @@ export default defineComponent({
type: Array<string>,
required: true
},
playerReserveDepartments: {
type: Array<string>,
required: false
},
playerDepartments: {
type: Array<string>,
required: false
},
playerNewDepartments: {
type: Array<string>,
required: false
},
botDepartments: {
type: Array<string>,
required: false
Expand All @@ -93,7 +105,7 @@ export default defineComponent({
},
data() {
return {
departmentView: undefined as Player|undefined,
departmentView: (this.playerReserveDepartments ?? []).length > 0 ? 'playerReserve' : 'available',
selectedDepartment: undefined as DepartmentCount|undefined
}
},
Expand All @@ -106,6 +118,10 @@ export default defineComponent({
const groupedDepartments = new GroupedDepartments(this.departments)
return groupedDepartments.groups
},
groupsPlayerReserve() : readonly DepartmentGroup[] {
const groupedDepartments = new GroupedDepartments(this.playerReserveDepartments ?? [])
return groupedDepartments.groups
},
groupsPlayer() : readonly DepartmentGroup[] {
const groupedDepartments = new GroupedDepartments(this.playerDepartments ?? [])
return groupedDepartments.groups
Expand All @@ -115,25 +131,30 @@ export default defineComponent({
return groupedDepartments.groups
},
groups() : readonly DepartmentGroup[] {
if (this.departmentView == Player.PLAYER) {
if (this.departmentView == 'playerReserve') {
return this.groupsPlayerReserve
}
if (this.departmentView == 'player') {
return this.groupsPlayer
}
else if (this.departmentView == Player.BOT) {
else if (this.departmentView == 'bot') {
return this.groupsBot
}
else {
return this.groupsAvailable
}
},
playerPlayer() : Player {
return Player.PLAYER
isDepartmentSelectionPossible() : boolean {
return this.select && (this.departmentView == 'available' || this.departmentView == 'playerReserve')
},
playerBot() : Player {
return Player.BOT
isDuplicateDepartment() : boolean {
return !!(this.select && this.selectedDepartment
&& ((this.playerDepartments ?? []).includes(this.selectedDepartment.department.id)
|| (this.playerNewDepartments ?? []).includes(this.selectedDepartment.department.id)))
},
isAllowed() : boolean {
return !(this.select && this.departmentView == undefined && this.selectedDepartment && this.playerDepartments
&& this.playerDepartments.includes(this.selectedDepartment.department.id))
isNotPlayerReserveWhichIsNotEmpty() : boolean {
return !!(this.playerReserveDepartments && this.playerReserveDepartments.length > 0 && this.selectedDepartment
&& !this.playerReserveDepartments.includes(this.selectedDepartment.department.id))
}
},
methods: {
Expand All @@ -145,11 +166,12 @@ export default defineComponent({
},
selectDepartment(department : Department) {
this.selectedDepartment = undefined
this.departmentView = 'available'
this.$emit('selected', department)
},
showDepartments(player?: Player) {
showDepartments(departmentView: string) {
this.selectedDepartment = undefined
this.departmentView = player
this.departmentView = departmentView
}
}
})
Expand Down
6 changes: 4 additions & 2 deletions src/locales/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
"departmentShop": {
"title": "Abteilungen",
"available": "Verfügbare Abteilungen",
"playerReserve": "Spieler-Vorrat",
"player": "Spieler",
"bot": "Andrew",
"selectionNotAllowed": "Du hast diese Abteilung bereits gebaut.",
"duplicateDepartmentWarning": "Du hast diese Abteilung bereits gebaut.",
"playerReserveWarning": "Du musst als erste Abteilung die Abteilung aus dem Spieler-Vorrat bauen.",
"selectDepartment": "Abteilung auswählen"
},
"timelineSelection": {
Expand Down Expand Up @@ -228,7 +230,7 @@
},
"23-payroll-management": {
"title": "Lohnbuchhaltung",
"rules": "Diese Abteilung hat eine dauerhafte Funktion, solange sich dort ein aktiver Mitarbeiter befindet. Diese Funktion gilt aber noch nicht in der Runde, in der der Mitarbeiter dort aktiviert wird. Immer wenn du einen Mitarbeiter in deinem Unternehmen aktivierst, kannst du <b>entweder</b> die auf dem Arbeitsplatz angegebenen Kosten zahlen (wie üblich) <b>oder</b> S2 zusätzlich zu diesen Kosten zahlen und 1 SP erhalten <b>oder</b> S1 statt der abgebildeten Kosten zahlen und 1 SP abgeben. Die letzte Möglichkeit kann nicht gewählt werden, wenn du 0 oder weniger SP besitzt."
"rules": "Diese Abteilung hat eine dauerhafte Funktion, solange sich dort ein aktiver Mitarbeiter befindet. Diese Funktion gilt aber noch nicht in der Runde, in der der Mitarbeiter dort aktiviert wird. Immer wenn du einen Mitarbeiter in deinem Unternehmen aktivierst, kannst du <b>entweder</b> die auf dem Arbeitsplatz angegebenen Kosten zahlen (wie üblich) <b>oder</b> $2 zusätzlich zu diesen Kosten zahlen und 1 SP erhalten <b>oder</b> $1 statt der abgebildeten Kosten zahlen und 1 SP abgeben. Die letzte Möglichkeit kann nicht gewählt werden, wenn du 0 oder weniger SP besitzt."
},
"24-public-relations": {
"title": "Öffentlichkeitsarbeit",
Expand Down
4 changes: 3 additions & 1 deletion src/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,11 @@
"departmentShop": {
"title": "Departments",
"available": "Available Departments",
"playerReserve": "Player Reserve",
"player": "Player",
"bot": "Andrew",
"selectionNotAllowed": "You have already build this department.",
"duplicateDepartmentWarning": "You have already build this department.",
"playerReserveWarning": "You have to build the department from your reserve first.",
"selectDepartment": "Select Department"
},
"timelineSelection": {
Expand Down
16 changes: 12 additions & 4 deletions src/views/RoundActionPlayer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@
</p>
<button class="btn btn-primary" v-if="playerNewDepartments.length < 3"
data-bs-toggle="modal" data-bs-target="#newDepartmentModal">{{t('actionPlayer.selectDepartment')}}</button>
<div class="alert alert-warning mt-2" role="alert" v-if="isManagementDepartmentsBuildNotFromPlayerReserve" v-html="t('departmentShop.playerReserveWarning')"></div>
</div>

<DepartmentShop id="newDepartmentModal" :select="true" @selected="selectDepartment"
:departments="availableDepartments" :playerDepartments="playerDepartments" :botDepartments="botDepartments"/>
:departments="availableDepartments" :playerReserveDepartments="playerReserveDepartments"
:playerDepartments="playerDepartments" :playerNewDepartments="playerNewDepartments" :botDepartments="botDepartments"/>

<button class="btn btn-primary btn-lg mt-4" @click="next()">
<button class="btn btn-primary btn-lg mt-4" @click="next()" :disabled="isManagementDepartmentsBuildNotFromPlayerReserve">
{{t('action.next')}}
</button>

Expand Down Expand Up @@ -63,9 +65,9 @@ export default defineComponent({
const route = useRoute()
const state = useStateStore()
const navigationState = new NavigationState(route, state)
const { round, startPlayer, selectedAction, playerReserveDepartments, botNewDepartments } = navigationState
const { round, startPlayer, selectedAction, botNewDepartments } = navigationState
const playerNewDepartments = ref([...playerReserveDepartments] as string[])
const playerNewDepartments = ref([] as string[])
if (navigationState.startPlayer == Player.BOT) {
navigationState.cardDeck.discardCurrentCard(navigationState.botCardShift)
Expand All @@ -86,9 +88,15 @@ export default defineComponent({
isManagement() : boolean {
return this.selectedAction == Action.MANAGEMENT
},
isManagementDepartmentsBuildNotFromPlayerReserve() : boolean {
return this.isManagement && this.playerNewDepartments.length > 0 && this.playerReserveDepartments.length > 0
},
availableDepartments() : string[] {
return [...removeDepartments(this.navigationState.departments, this.playerNewDepartments, this.botNewDepartments)]
},
playerReserveDepartments() : string[] {
return [...removeDepartments(this.navigationState.playerReserveDepartments, this.playerNewDepartments)]
},
playerDepartments() : string[] {
return [...this.navigationState.playerDepartments]
},
Expand Down

0 comments on commit 429d605

Please sign in to comment.