Skip to content

Commit e5351f4

Browse files
authored
Prepare nav for new games (#312)
Add an optional contextual navigation to the header #15. Additionally, move some controllers to their respective context #269.
1 parent 7d6ec02 commit e5351f4

File tree

34 files changed

+445
-221
lines changed

34 files changed

+445
-221
lines changed

assets/css/app.css

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,22 @@ html {
22
scroll-padding-top: 10px;
33
}
44

5-
html:has(.navbar.sticky-top) {
5+
html:has(.sticky-top > .navbar) {
66
scroll-padding-top: 66px;
77
}
88

9-
html:has(.navbar.sticky-top) .page-body .sticky-md-top {
9+
html:has(.sticky-top > .navbar) .page-body .sticky-md-top {
1010
top: 66px;
1111
}
1212

13+
html:has(.sticky-top > .navbar + .navbar) {
14+
scroll-padding-top: 120px;
15+
}
16+
17+
html:has(.sticky-top > .navbar + .navbar) .page-body .sticky-md-top {
18+
top: 120px;
19+
}
20+
1321
[data-title] {
1422
position: relative;
1523
}

assets/js/Common/VolumeControl.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ customElements.define('volume-control', class extends HTMLElement {
55
connectedCallback() {
66
this.append(html`
77
<input type="checkbox" class="gp-dropdown-toggle" id="volume-control-dropdown">
8-
<label class="nav-link" for="volume-control-dropdown">
8+
<label class="nav-link cursor-pointer" for="volume-control-dropdown">
99
${this._iconHighVolume = html`
1010
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none"
1111
stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {html} from 'uhtml/node.js'
2+
3+
customElements.define('connect-four-animated-game', class extends HTMLElement {
4+
#plainElement; #moveElements; #abortController;
5+
6+
connectedCallback() {
7+
this.#plainElement = html`<div class="gp-cf-game__field"></div>`;
8+
this.#moveElements = Array.from(this.querySelectorAll('[data-move]')).sort((a, b) => {
9+
return parseInt(a.dataset.move) - parseInt(b.dataset.move);
10+
});
11+
this.#abortController = new AbortController();
12+
13+
if (typeof AbortSignal?.timeout !== 'function' || typeof AbortSignal?.any !== 'function') {
14+
return;
15+
}
16+
17+
this.addEventListener('mouseenter', this.#onMouseEnter);
18+
this.addEventListener('mouseleave', this.#onMouseLeave);
19+
}
20+
21+
disconnectedCallback() {
22+
this.#abortController.abort();
23+
}
24+
25+
#onMouseEnter = () => {
26+
this.#abortController = new AbortController();
27+
this.#runAnimation();
28+
}
29+
30+
#onMouseLeave = () => {
31+
this.#abortController.abort();
32+
this.#showFinalState();
33+
}
34+
35+
#runAnimation = async () => {
36+
this.#clear();
37+
38+
for (const [i, moveElement] of this.#moveElements.entries()) {
39+
this.#moveElements.forEach(e => {
40+
e.classList.remove('gp-cf-game__field--highlight', 'gp-cf-game__field--current')
41+
});
42+
moveElement.classList.add('gp-cf-game__field--highlight', 'gp-cf-game__field--current');
43+
this.querySelector('[data-move="' + moveElement.dataset.move + '"]').replaceWith(moveElement);
44+
45+
const isLastMove = i === this.#moveElements.length - 1;
46+
isLastMove && this.#showFinalState();
47+
48+
try {
49+
await new Promise((resolve, reject) => {
50+
AbortSignal.any([this.#abortController.signal, AbortSignal.timeout(isLastMove ? 1500 : 350)])
51+
.addEventListener('abort', reject);
52+
});
53+
} catch {
54+
if (this.#abortController.signal.aborted) return;
55+
}
56+
}
57+
58+
this.#runAnimation();
59+
}
60+
61+
#clear() {
62+
this.#moveElements.forEach(e => {
63+
e.classList.remove('gp-cf-game__field--highlight', 'gp-cf-game__field--current');
64+
const clone = this.#plainElement.cloneNode();
65+
clone.dataset.move = e.dataset.move;
66+
clone.dataset.win = e.dataset.win;
67+
this.querySelector('[data-move="' + e.dataset.move + '"]').replaceWith(clone);
68+
});
69+
}
70+
71+
#showFinalState() {
72+
this.#moveElements.forEach((e, k) => {
73+
e.classList.remove('gp-cf-game__field--highlight', 'gp-cf-game__field--current');
74+
k === this.#moveElements.length - 1 && e.classList.add('gp-cf-game__field--current');
75+
e.hasAttribute('data-win') && e.classList.add('gp-cf-game__field--highlight');
76+
this.querySelector('[data-move="' + e.dataset.move + '"]').replaceWith(e);
77+
});
78+
}
79+
});

assets/js/ConnectFour/GameService.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class GameService {
1313
*/
1414
redirectTo(gameId) {
1515
this.httpClient.redirectTo(
16-
'/game/' + gameId
16+
'/connect-four/game/' + gameId
1717
);
1818
}
1919

config/connect-four/importmap.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
'connect-four-running-games' => ['path' => 'js/ConnectFour/RunningGames.js'],
99
'connect-four-game-list' => ['path' => 'js/ConnectFour/GameList.js'],
1010
'connect-four-game' => ['path' => 'js/ConnectFour/Game.js'],
11+
'connect-four-animated-game' => ['path' => 'js/ConnectFour/AnimatedGame.js'],
1112
'connect-four-player-status' => ['path' => 'js/ConnectFour/PlayerStatus.js'],
1213
'connect-four-player-username' => ['path' => 'js/ConnectFour/PlayerUsername.js'],
1314
'connect-four-timer' => ['path' => 'js/ConnectFour/Timer.js'],

config/connect-four/routing.yml

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,35 @@
1+
connect_four_lobby:
2+
path: /connect-four
3+
methods: [GET]
4+
controller: connect-four.page-controller::lobbyAction
5+
6+
connect_four_history:
7+
path: /connect-four/history
8+
methods: [GET]
9+
controller: connect-four.page-controller::historyAction
10+
11+
connect_four_game:
12+
path: /connect-four/game/{id}
13+
methods: [GET]
14+
controller: connect-four.page-controller::gameAction
15+
116
connect_four_open:
2-
path: /api/connect-four/games/open
17+
path: /connect-four/games/open
318
methods: [POST]
419
controller: connect-four.challenge-controller::openAction
520

621
connect_four_abort_challenge:
7-
path: /challenge/{id}/abort
22+
path: /connect-four/challenge/{id}/abort
823
methods: [POST]
924
controller: connect-four.challenge-controller::abortChallengeAction
1025

1126
connect_four_accept_challenge:
12-
path: /challenge/{id}/accept
27+
path: /connect-four/challenge/{id}/accept
1328
methods: [POST]
1429
controller: connect-four.challenge-controller::acceptChallengeAction
1530

1631
connect_four_challenge:
17-
path: /challenge/{id}
32+
path: /connect-four/challenge/{id}
1833
methods: [GET]
1934
controller: connect-four.challenge-controller::showAction
2035

config/connect-four/services/controller.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
services:
2+
connect-four.page-controller:
3+
class: Gaming\ConnectFour\Port\Adapter\Http\PageController
4+
arguments: ['@connect-four.query-bus', '@gaming.usernames']
5+
calls: [[setContainer, ['@Psr\Container\ContainerInterface']]]
6+
tags: ['controller.service_arguments', 'container.service_subscriber']
7+
28
connect-four.fragment-controller:
39
class: Gaming\ConnectFour\Port\Adapter\Http\FragmentController
410
arguments: ['@connect-four.query-bus', '@gaming.usernames']

config/identity/services/controller.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,8 @@ services:
1919
- '@gaming.form-violation-mapper'
2020
calls: [[setContainer, ['@Psr\Container\ContainerInterface']]]
2121
tags: ['controller.service_arguments', 'container.service_subscriber']
22+
23+
identity.fragment-controller:
24+
class: Gaming\Identity\Port\Adapter\Http\FragmentController
25+
calls: [[setContainer, ['@Psr\Container\ContainerInterface']]]
26+
tags: ['controller.service_arguments', 'container.service_subscriber']

config/web-interface/routing.yml

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,13 @@
1-
lobby:
1+
home:
22
path: /
33
methods: [GET]
4-
controller: web-interface.page-controller::lobbyAction
4+
controller: web-interface.page-controller::homeAction
55

66
metrics:
77
path: /metrics
88
methods: [GET]
99
controller: web-interface.metrics-controller::showAction
1010

11-
profile:
12-
path: /profile
13-
methods: [GET]
14-
controller: web-interface.page-controller::profileAction
15-
16-
game:
17-
path: /game/{id}
18-
methods: [GET]
19-
controller: web-interface.page-controller::gameAction
20-
2111
server_time:
2212
path: /api/server-time
2313
methods: [GET]

config/web-interface/services/controller.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
services:
22
web-interface.page-controller:
33
class: Gaming\WebInterface\Presentation\Http\PageController
4-
arguments: ['@connect-four.query-bus', '@gaming.usernames']
54
calls: [[setContainer, ['@Psr\Container\ContainerInterface']]]
65
tags: ['controller.service_arguments', 'container.service_subscriber']
76

0 commit comments

Comments
 (0)