Skip to content

Commit 38091aa

Browse files
committed
Progress with gameOver, errorManagement in JS
1 parent b13f2ae commit 38091aa

24 files changed

+439
-174
lines changed

js/e2e-tests/fake-player.mjs

+6-2
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ export default {
4747
await page.getByRole("button", { name: "Prefill with an example move" }).click();
4848
await page.getByText("greedy").click();
4949
await page.getByRole("button", { name: "Submit" }).click();
50-
await expect(page.getByText("11111111-1111-1111-1111-111111111111 has score")).toBeVisible();
50+
// TODO Find a way to properly test the leaderboard
51+
await expect(page.getByText("11111111-1111-1111-1111-111111111111")).toBeVisible();
52+
await expect(page.getByText("has score")).toBeVisible();
5153
},
5254

5355
async playMultiplayers(page, gameRegex) {
@@ -73,6 +75,8 @@ export default {
7375
await page.getByRole("button", { name: "Prefill with an example move" }).click();
7476
await page.getByTestId("move_0").click();
7577
await page.getByRole("button", { name: "Submit" }).click();
76-
await expect(page.getByText("11111111-1111-1111-1111-111111111111 has score")).toBeVisible();
78+
// TODO Find a way to properly test the leaderboard
79+
await expect(page.getByText("11111111-1111-1111-1111-111111111111")).toBeVisible();
80+
await expect(page.getByText("has score")).toBeVisible();
7781
},
7882
};

js/src/main/resources/static/ui/js/kumite-account-me.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import KumiteMeLoggedIn from "./kumite-account-me-loggedin.js";
66

77
export default {
88
components: {
9-
LoginRef,
9+
LoginRef,
1010
KumiteMeLoggedIn,
1111
},
1212
computed: {

js/src/main/resources/static/ui/js/kumite-account-ref.js

+14-14
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,19 @@ export default {
3232
return {};
3333
},
3434
template: /* HTML */ `
35-
<span v-if="account.accountId === accountId">
36-
<RouterLink :to="{path:'/html/me'}">
37-
<i class="bi bi-person"></i>accountId: {{ accountId }}<span > (You)</span>
38-
39-
<Flag :country="account.details.countryCode" v-if="account.details.countryCode" />
40-
</RouterLink>
41-
</span>
42-
<span v-else>
43-
<RouterLink :to="{path:'/html/accounts/' + accountId}">
44-
<i class="bi bi-person"></i>accountId: {{ accountId }}
45-
46-
<Flag :country="account.details.countryCode" v-if="account.details.countryCode" />
47-
</RouterLink>
48-
</span>
35+
<span v-if="account.accountId === accountId">
36+
<RouterLink :to="{path:'/html/me'}">
37+
<i class="bi bi-person"></i>accountId: {{ accountId }}<span> (You)</span>
38+
39+
<Flag :country="account.details.countryCode" v-if="account.details.countryCode" />
40+
</RouterLink>
41+
</span>
42+
<span v-else>
43+
<RouterLink :to="{path:'/html/accounts/' + accountId}">
44+
<i class="bi bi-person"></i>accountId: {{ accountId }}
45+
46+
<Flag :country="account.details.countryCode" v-if="account.details.countryCode" />
47+
</RouterLink>
48+
</span>
4949
`,
5050
};

js/src/main/resources/static/ui/js/kumite-app.js

+4
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,13 @@ import LoginRef from "./login-ref.js";
1111
import KumiteAccountRef from "./kumite-account-ref.js";
1212
import KumitePlayerRef from "./kumite-player-ref.js";
1313

14+
import LoginModal from "./login-modal.js";
15+
1416
export default {
1517
components: {
1618
KumiteNavbar,
1719
LoginRef,
20+
LoginModal,
1821
KumiteAccountRef,
1922
KumitePlayerRef,
2023
},
@@ -60,6 +63,7 @@ export default {
6063
<RouterView />
6164
</main>
6265
66+
<LoginModal />
6367
<span v-if="$route.fullPath !== '/html/login'">
6468
<!--LoginRef /-->
6569
</span>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { mapState } from "pinia";
2+
import { useKumiteStore } from "./store.js";
3+
import { useUserStore } from "./store-user.js";
4+
5+
export function isReady(gameId, contestId) {
6+
const store = useKumiteStore();
7+
8+
if (!store.games[gameId] || store.games[gameId].error) {
9+
return false;
10+
}
11+
12+
if (!store.contests[contestId] || store.contests[contestId].error) {
13+
return false;
14+
}
15+
16+
if (!store.contests[contestId].board || store.contests[contestId].board.error) {
17+
return false;
18+
}
19+
20+
return true;
21+
}
22+
23+
export default {
24+
components: {},
25+
props: {
26+
contestId: {
27+
type: String,
28+
required: true,
29+
},
30+
gameId: {
31+
type: String,
32+
required: true,
33+
},
34+
},
35+
computed: {
36+
...mapState(useUserStore, ["playingPlayerId"]),
37+
...mapState(useKumiteStore, ["nbGameFetching", "nbContestFetching", "nbBoardFetching"]),
38+
...mapState(useKumiteStore, {
39+
game(store) {
40+
return store.games[this.gameId] || { error: "not_loaded" };
41+
},
42+
contest(store) {
43+
return store.contests[this.contestId] || { error: "not_loaded" };
44+
},
45+
board(store) {
46+
return store.contests[this.contestId]?.board || { error: "not_loaded" };
47+
},
48+
}),
49+
},
50+
setup(props) {
51+
const store = useKumiteStore();
52+
const userStore = useUserStore();
53+
54+
return {};
55+
},
56+
// https://stackoverflow.com/questions/7717929/how-do-i-get-pre-style-overflow-scroll-height-150px-to-display-at-parti
57+
template: /* HTML */ `
58+
<div v-if="(!game || !contest || !board)">
59+
<div class="spinner-border" role="status" v-if="(nbGameFetching > 0 || nbContestFetching > 0 || nbBoardFetching > 0)">
60+
<span class="visually-hidden">Loading board for contestId={{contestId}}</span>
61+
</div>
62+
<div v-else>
63+
<span>Issue loading board for contestId={{contestId}}</span>
64+
</div>
65+
</div>
66+
<div v-if="game.error">game.error={{game.error}}</div>
67+
<div v-if="contest.error">contest.error={{contest.error}}</div>
68+
<div v-if="board.error">board.error={{board.error}}</div>
69+
`,
70+
};

js/src/main/resources/static/ui/js/kumite-board-overview-inner.js

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import KumiteBoardOverviewPlay from "./kumite-board-overview-play.js";
77

88
import KumiteBoardOverviewCurl from "./kumite-board-overview-curl.js";
99
import KumiteLeaderboard from "./kumite-leaderboard.js";
10+
import KumiteContestWebsocket from "./kumite-contest-websocket.js";
1011

1112
import KumiteJsonBoardState from "./board-renderers/kumite-json-board-state.js";
1213
import KumiteTSPBoardState from "./board-renderers/kumite-tsp-board-state.js";
@@ -17,6 +18,7 @@ export default {
1718
KumiteBoardOverviewPlay,
1819
KumiteBoardOverviewCurl,
1920
KumiteLeaderboard,
21+
KumiteContestWebsocket,
2022

2123
KumiteJsonBoardState,
2224
KumiteTSPBoardState,
@@ -72,6 +74,7 @@ export default {
7274
</div>
7375
<div v-else-if="game.error || contest.error || board.error">{{game.error || contest.error || board.error}}</div>
7476
<div v-else>
77+
<KumiteContestWebsocket :gameId="gameId" :contestId="contestId" />
7578
<div class="border position-relative">
7679
<i class="bi bi-motherboard">Board</i>
7780
<!-- https://stackoverflow.com/questions/43658481/passing-props-dynamically-to-dynamic-component-in-vuejs -->

js/src/main/resources/static/ui/js/kumite-board-overview.js

+15-23
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { computed } from "vue";
2+
13
import { mapState } from "pinia";
24
import { useKumiteStore } from "./store.js";
35
import { useUserStore } from "./store-user.js";
@@ -7,12 +9,16 @@ import KumiteContestHeader from "./kumite-contest-header.js";
79

810
import KumiteBoardOverviewInner from "./kumite-board-overview-inner.js";
911

12+
import KumiteBoardNotReady from "./kumite-board-notready.js";
13+
import { isReady } from "./kumite-board-notready.js";
14+
1015
export default {
1116
components: {
1217
KumiteGameHeader,
1318
KumiteContestHeader,
1419

1520
KumiteBoardOverviewInner,
21+
KumiteBoardNotReady,
1622
},
1723
props: {
1824
contestId: {
@@ -26,18 +32,6 @@ export default {
2632
},
2733
computed: {
2834
...mapState(useUserStore, ["playingPlayerId"]),
29-
...mapState(useKumiteStore, ["nbGameFetching", "nbContestFetching", "nbBoardFetching"]),
30-
...mapState(useKumiteStore, {
31-
game(store) {
32-
return store.games[this.gameId] || { error: "not_loaded" };
33-
},
34-
contest(store) {
35-
return store.contests[this.contestId] || { error: "not_loaded" };
36-
},
37-
board(store) {
38-
return store.contests[this.contestId]?.board || { error: "not_loaded" };
39-
},
40-
}),
4135
},
4236
setup(props) {
4337
const store = useKumiteStore();
@@ -47,25 +41,23 @@ export default {
4741
userStore
4842
.loadCurrentAccountPlayers()
4943
.then(() => {
50-
return store.loadBoard(props.gameId, props.contestId, userStore.playingPlayerId);
44+
if (userStore.playingPlayerId) {
45+
return store.loadBoard(props.gameId, props.contestId, userStore.playingPlayerId);
46+
} else {
47+
console.log("Skip loading board as seemingly not logged-in");
48+
}
5149
})
5250
.then((board) => {
5351
console.log("We loaded board", board);
5452
});
5553

56-
return {};
54+
const weAreReady = computed(() => isReady(props.gameId, props.contestId));
55+
56+
return { weAreReady };
5757
},
5858
// https://stackoverflow.com/questions/7717929/how-do-i-get-pre-style-overflow-scroll-height-150px-to-display-at-parti
5959
template: /* HTML */ `
60-
<div v-if="(!game || !contest || !board)">
61-
<div class="spinner-border" role="status" v-if="(nbGameFetching > 0 || nbContestFetching > 0 || nbBoardFetching > 0)">
62-
<span class="visually-hidden">Loading board for contestId={{contestId}}</span>
63-
</div>
64-
<div v-else>
65-
<span>Issue loading board for contestId={{contestId}}</span>
66-
</div>
67-
</div>
68-
<div v-else-if="game.error || contest.error || board.error">{{game.error || contest.error || board.error}}</div>
60+
<KumiteBoardNotReady v-if="!weAreReady" :gameId="gameId" :contestId="contestId" />
6961
<div v-else class="container">
7062
<KumiteGameHeader class="row" :gameId="gameId" />
7163
<KumiteContestHeader class="row" :gameId="gameId" :contestId="contestId" />

js/src/main/resources/static/ui/js/kumite-contest-delete.js

+32-32
Original file line numberDiff line numberDiff line change
@@ -29,44 +29,44 @@ export default {
2929
const store = useKumiteStore();
3030

3131
store.loadContestIfMissing(props.contestId, props.gameId);
32-
33-
const doGameover = function() {
34-
console.log("DELETE contest", contestId);
3532

36-
async function deleteFromUrl(url) {
37-
try {
38-
const fetchOptions = {
39-
method: "DELETE",
40-
headers: { "Content-Type": "application/json" },
41-
};
42-
const response = await store.authenticatedFetch(url, fetchOptions);
43-
if (!response.ok) {
44-
throw store.newNetworkError("Rejected DELETE for move for contestId=" + contestId, url, response);
45-
}
33+
const doGameover = function () {
34+
console.log("DELETE contest", contestId);
4635

47-
const contest = await response.json();
48-
console.log("Created contest", contest);
36+
async function deleteFromUrl(url) {
37+
try {
38+
const fetchOptions = {
39+
method: "DELETE",
40+
headers: { "Content-Type": "application/json" },
41+
};
42+
const response = await store.authenticatedFetch(url, fetchOptions);
43+
if (!response.ok) {
44+
throw store.newNetworkError("Rejected DELETE for move for contestId=" + contestId, url, response);
45+
}
4946

50-
{
51-
console.log("Registering contestId", contest.contestId);
52-
store.$patch({
53-
contests: {
54-
...store.contests,
55-
[contest.contestId]: contest,
56-
},
57-
});
58-
}
47+
const contest = await response.json();
48+
console.log("Created contest", contest);
5949

60-
createdContest.value = contest;
61-
} catch (e) {
62-
console.error("Issue on Network:", e);
63-
}
64-
}
50+
{
51+
console.log("Registering contestId", contest.contestId);
52+
store.$patch({
53+
contests: {
54+
...store.contests,
55+
[contest.contestId]: contest,
56+
},
57+
});
58+
}
6559

66-
return deleteFromUrl(`/contests?contest_id=${props.contestId}`);
67-
};
60+
createdContest.value = contest;
61+
} catch (e) {
62+
console.error("Issue on Network:", e);
63+
}
64+
}
6865

69-
return {doGameover};
66+
return deleteFromUrl(`/contests?contest_id=${props.contestId}`);
67+
};
68+
69+
return { doGameover };
7070
},
7171
template: /* HTML */ ` <button class="btn btn-danger" @click="doGameover">Archive this contest (force gameOver)</button> `,
7272
};

js/src/main/resources/static/ui/js/kumite-contest-form.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import KumiteGameHeader from "./kumite-game-header.js";
99

1010
export default {
1111
components: {
12-
KumiteContestRef,
12+
KumiteContestRef,
1313
KumiteGameHeader,
1414
},
1515
props: {
@@ -34,7 +34,7 @@ export default {
3434
setup(props) {
3535
const store = useKumiteStore();
3636

37-
store.loadGameIfMissing(props.gameId);
37+
store.loadGameIfMissing(props.gameId);
3838

3939
const contestName = ref("");
4040
const createdContest = ref({});
@@ -92,9 +92,9 @@ export default {
9292
<div v-else>{{ game.error }}</div>
9393
</div>
9494
95-
<div v-if="createdContest.contestId">
95+
<div v-if="createdContest.contestId">
9696
<KumiteContestRef :gameId="gameId" :contestId="createdContest.contestId" />
97-
</div>
97+
</div>
9898
<div v-else>
9999
<KumiteGameHeader :gameId="gameId" v-if="showGame" />
100100

js/src/main/resources/static/ui/js/kumite-contest-header.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import KumiteContestDelete from "./kumite-contest-delete.js";
99

1010
export default {
1111
components: {
12-
KumiteContestRef,
12+
KumiteContestRef,
1313
KumiteAccountRef,
1414
KumiteContestDelete,
1515
},
@@ -88,7 +88,7 @@ export default {
8888
<div v-else-if="game.error || contest.error">{{game.error || contest.error}}</div>
8989
<span v-else>
9090
<h2>
91-
<KumiteContestRef :contestId="contestId"/>
91+
<KumiteContestRef :contestId="contestId" />
9292
<RouterLink :to="{path:'/html/games/' + gameId}"><i class="bi bi-arrow-90deg-left"></i></RouterLink>
9393
</h2>
9494

0 commit comments

Comments
 (0)