Browse Source

open profile after login; use appStates for profiles and histories

master
nicolas-arnaud 2 years ago
parent
commit
82e1a4ca5d
  1. 2
      back/src/auth/auth.controller.ts
  2. 39
      front/src/App.svelte
  3. 4
      front/src/components/Channels.svelte
  4. 6
      front/src/components/Chat.svelte
  5. 8
      front/src/components/Friends.svelte
  6. 41
      front/src/components/MatchHistory.svelte
  7. 81
      front/src/components/Profile.svelte

2
back/src/auth/auth.controller.ts

@ -42,7 +42,7 @@ export class AuthController {
@Get('inReturn') @Get('inReturn')
@UseGuards(FtOauthGuard) @UseGuards(FtOauthGuard)
@Redirect(`http://${frontHost}:${frontPort}`) @Redirect(`http://${frontHost}:${frontPort}/profile`)
ftAuthCallback ( ftAuthCallback (
@Res({ passthrough: true }) response: Response, @Res({ passthrough: true }) response: Response,
@Req() request: Request @Req() request: Request

39
front/src/App.svelte

@ -3,13 +3,11 @@
HOME = "/", HOME = "/",
PROFILE = "/profile", PROFILE = "/profile",
HISTORY = "/history", HISTORY = "/history",
HISTORY_ID = "/history_id",
FRIENDS = "/friends", FRIENDS = "/friends",
CHANNELS = "/channels", CHANNELS = "/channels",
LEADERBOARD = "/leaderboard", LEADERBOARD = "/leaderboard",
CREATE_GAME = "/create-game", CREATE_GAME = "/create-game",
MATCHMAKING = "/matchmaking", MATCHMAKING = "/matchmaking",
PROFILE_ID = "/profile_id",
} }
</script> </script>
@ -90,7 +88,10 @@
} }
onMount(() => { onMount(() => {
history.replaceState({ appState: "" }, "", "/"); if (window.location.pathname === "/profile")
history.replaceState({ appState: APPSTATE.PROFILE }, "", APPSTATE.PROFILE);
else
history.replaceState({ appState: "" }, "", "/");
window.onpopstate = (e: PopStateEvent) => { window.onpopstate = (e: PopStateEvent) => {
if (e.state) { if (e.state) {
appState = e.state.appState; appState = e.state.appState;
@ -103,16 +104,17 @@
}, 15000); }, 15000);
function clickProfile() { function clickProfile() {
profileUsername = $store.username
setAppState(APPSTATE.PROFILE); setAppState(APPSTATE.PROFILE);
} }
let profileUsername: string = $store?.username ?? "";
async function openIdProfile(event: CustomEvent<string>) { async function openIdProfile(event: CustomEvent<string>) {
profileUsername = event.detail; setAppState(APPSTATE.PROFILE + "#" + event.detail);
setAppState(APPSTATE.PROFILE_ID);
} }
$: console.log("New profileUsername:", profileUsername)
async function openIdHistory(event: CustomEvent<string>) {
setAppState(APPSTATE.HISTORY + "#" + event.detail);
}
async function clickHistory() { async function clickHistory() {
setAppState(APPSTATE.HISTORY); setAppState(APPSTATE.HISTORY);
} }
@ -176,8 +178,7 @@
{failedGameLogIn} {failedGameLogIn}
{gamePlaying} {gamePlaying}
/> />
{#if appState.includes(`${APPSTATE.CHANNELS}#`)}
{#if appState.includes(`${APPSTATE.CHANNELS}#`)}
{#key appState} {#key appState}
<div <div
on:click={() => setAppState(APPSTATE.CHANNELS)} on:click={() => setAppState(APPSTATE.CHANNELS)}
@ -195,8 +196,8 @@
</div> </div>
{/key} {/key}
{/if} {/if}
{#if appState.includes(APPSTATE.CHANNELS)} {#if appState.includes(APPSTATE.CHANNELS)}
<div <div
class="{appState !== APPSTATE.CHANNELS ? 'hidden' : ''}" class="{appState !== APPSTATE.CHANNELS ? 'hidden' : ''}"
on:click={resetAppState} on:click={resetAppState}
on:keydown={resetAppState} on:keydown={resetAppState}
@ -219,32 +220,32 @@
{/if} {/if}
{#if appState === APPSTATE.HISTORY} {#if appState === APPSTATE.HISTORY}
<div on:click={resetAppState} on:keydown={resetAppState}> <div on:click={resetAppState} on:keydown={resetAppState}>
<MatchHistory /> <MatchHistory {appState} />
</div> </div>
{/if} {/if}
{#if appState === APPSTATE.HISTORY_ID} {#if appState.includes(`${APPSTATE.HISTORY}#`)}
<div <div
on:click={() => setAppState(APPSTATE.PROFILE)} on:click={() => setAppState(APPSTATE.PROFILE)}
on:keydown={() => setAppState(APPSTATE.PROFILE)} on:keydown={() => setAppState(APPSTATE.PROFILE)}
> >
<MatchHistory username={profileUsername} /> <MatchHistory {appState} />
</div> </div>
{/if} {/if}
{#if appState === APPSTATE.PROFILE} {#if appState === APPSTATE.PROFILE}
<div on:click={resetAppState} on:keydown={resetAppState}> <div on:click={resetAppState} on:keydown={resetAppState}>
<Profile {resetGameConnection} {gamePlaying} bind:username={profileUsername} on:view-history={() => setAppState(APPSTATE.HISTORY_ID)} /> <Profile {appState} {resetGameConnection} {gamePlaying} on:view-history={openIdHistory} />
</div> </div>
{/if} {/if}
{#if appState === APPSTATE.PROFILE_ID} {#if appState.includes(`${APPSTATE.PROFILE}#`)}
<div <div
on:click={() => setAppState(history.state.prevState)} on:click={() => setAppState(history.state.prevState)}
on:keydown={() => setAppState(history.state.prevState)} on:keydown={() => setAppState(history.state.prevState)}
> >
<Profile <Profile
{appState}
{gamePlaying} {gamePlaying}
bind:username={profileUsername}
on:send-message={openDirectChat} on:send-message={openDirectChat}
on:view-history={() => setAppState(APPSTATE.HISTORY_ID)} on:view-history={openIdHistory}
on:add-friend={addFriend} on:add-friend={addFriend}
on:invite-to-game={pong.inviteToGame} on:invite-to-game={pong.inviteToGame}
/> />

4
front/src/components/Channels.svelte

@ -1,6 +1,6 @@
<script lang="ts" context="module"> <script lang="ts" context="module">
import { content, popup, show_popup } from './Alert/content' import { content, show_popup } from './Alert/content'
import { onMount, tick } from "svelte"; import { onMount } from "svelte";
import { API_URL, store } from "../Auth"; import { API_URL, store } from "../Auth";
import type User from "./Profile.svelte"; import type User from "./Profile.svelte";
import type { CreateChannelDto } from './dtos/create-channel.dto'; import type { CreateChannelDto } from './dtos/create-channel.dto';

6
front/src/components/Chat.svelte

@ -341,8 +341,8 @@
{#if !message.hidden} {#if !message.hidden}
<span <span
class="message-name" class="message-name"
on:click={() => dispatch("view-profile", message.author.username)} on:click={() => dispatch("view-profile", message.author.ftId)}
on:keydown={() => dispatch("view-profile", message.author.username)} on:keydown={() => dispatch("view-profile", message.author.ftId)}
style="cursor: pointer;" style="cursor: pointer;"
> >
{message.author.username} {message.author.username}
@ -374,7 +374,7 @@
<li> <li>
<p> <p>
{member.username} {member.username}
<button on:click={() => dispatch("view-profile", member.username)}> profile </button> <button on:click={() => dispatch("view-profile", member.ftId)}> profile </button>
<button on:click={() => banUser(member.username)}> ban </button> <button on:click={() => banUser(member.username)}> ban </button>
<button on:click={() => kickUser(member.username)}> kick </button> <button on:click={() => kickUser(member.username)}> kick </button>
<button on:click={() => muteUser(member.username)}> mute </button> <button on:click={() => muteUser(member.username)}> mute </button>

8
front/src/components/Friends.svelte

@ -78,8 +78,8 @@
{#each friends as friend} {#each friends as friend}
<li> <li>
<span class="message-name" <span class="message-name"
on:click={() => dispatch("view-profile", friend.username)} on:click={() => dispatch("view-profile", friend.ftId)}
on:keydown={() => dispatch("view-profile", friend.username)} on:keydown={() => dispatch("view-profile", friend.ftId)}
style="cursor: pointer;" style="cursor: pointer;"
>{friend.username} is {friend.status}</span> >{friend.username} is {friend.status}</span>
</li> </li>
@ -94,8 +94,8 @@
{#each invits as invit} {#each invits as invit}
<li> <li>
<span class="message-name" <span class="message-name"
on:click={() => dispatch("view-profile", invit.username)} on:click={() => dispatch("view-profile", invit.ftId)}
on:keydown={() => dispatch("view-profile", invit.username)} on:keydown={() => dispatch("view-profile", invit.ftId)}
style="cursor: pointer;" style="cursor: pointer;"
>{invit.username} invited you to be friend.</span> >{invit.username} invited you to be friend.</span>
</li> </li>

41
front/src/components/MatchHistory.svelte

@ -12,23 +12,33 @@
<script lang="ts"> <script lang="ts">
import InfiniteScroll from "./infiniteScroll.svelte"; import InfiniteScroll from "./infiniteScroll.svelte";
import { onMount } from "svelte"; import { onMount } from "svelte";
import { APPSTATE } from "../App.svelte";
export let username: string = "Global"; export let appState: string = APPSTATE.HISTORY
let username = "";
let page: number = 1; let page: number = 1;
let data: Array<Match> = []; let data: Array<Match> = [];
let newBatch: Array<Match> = []; let newBatch: Array<Match> = [];
onMount(() => {
fetchData();
});
$: data = [...data, ...newBatch];
async function fetchData() { async function fetchData() {
let response: Response; let response: Response;
if (username === "Global") { if (appState === APPSTATE.HISTORY) {
response = await fetch(`${API_URL}/results/global?page=${page}`, { response = await fetch(`${API_URL}/results/global?page=${page}`, {
credentials: "include", credentials: "include",
mode: "cors", mode: "cors",
}); });
} else { } else {
response = await fetch(`${API_URL}/users/${username}/byname`); let userId = appState.split("#")[1];
response = await fetch(`${API_URL}/users/${userId}`);
if (response.ok) { if (response.ok) {
let user = await response.json(); let user = await response.json();
username = user.username;
response = await fetch(`${API_URL}/results/${user.ftId}?page=${page}`, { response = await fetch(`${API_URL}/results/${user.ftId}?page=${page}`, {
credentials: "include", credentials: "include",
mode: "cors", mode: "cors",
@ -53,23 +63,22 @@
} }
} }
onMount(() => {
fetchData();
});
$: data = [...data, ...newBatch];
</script> </script>
<div class="overlay"> <div class="overlay">
<div class="history" on:click|stopPropagation on:keydown|stopPropagation> <div class="history" on:click|stopPropagation on:keydown|stopPropagation>
<div> <div>
{#if data.length > 0} <table>
<table> <thead>
<thead> <tr>
<tr> {#if username === ""}
<th colspan="3">{username}'s last matchs</th> <th colspan="3">Global history</th>
</tr> {:else}
</thead> <th colspan="3">History of {username}</th>
{/if}
</tr>
</thead>
{#if data.length > 0}
<tbody> <tbody>
<tr> <tr>
<td>Date</td> <td>Date</td>
@ -89,10 +98,10 @@
</tr> </tr>
{/each} {/each}
</tbody> </tbody>
</table>
{:else} {:else}
<p>No matches to display</p> <p>No matches to display</p>
{/if} {/if}
</table>
</div> </div>
<InfiniteScroll <InfiniteScroll
hasMore={newBatch.length > 0} hasMore={newBatch.length > 0}

81
front/src/components/Profile.svelte

@ -14,22 +14,49 @@
<script lang="ts"> <script lang="ts">
import { createEventDispatcher, onMount } from "svelte"; import { createEventDispatcher, onMount } from "svelte";
import { bind } from 'svelte-simple-modal';
import { API_URL, store, logout } from "../Auth"; import { API_URL, store, logout } from "../Auth";
import Alert from "./Alert/Alert.svelte";
import { popup } from "./Alert/content";
import type { UserDto } from "./dtos/user.dto"; import type { UserDto } from "./dtos/user.dto";
import { show_popup } from "./Alert/content"; import { show_popup } from "./Alert/content";
import { APPSTATE } from "../App.svelte";
export let username: string = $store.username;
export let email: string = $store.email;
export let gamePlaying: boolean; export let gamePlaying: boolean;
export let resetGameConnection: () => void = () => {}; export let resetGameConnection: () => void = () => {};
export let appState: string = APPSTATE.PROFILE;
let edit: boolean = true; let edit: boolean = true;
let user: Player = $store; let user: Player = $store;
let userId: string = $store.ftId;
let username: string = $store.username;
let email: string = $store.email;
let blockedUsers: Array<Player> = []; let blockedUsers: Array<Player> = [];
let avatarForm: HTMLFormElement; let avatarForm: HTMLFormElement;
async function getUser() {
if ( appState !== APPSTATE.PROFILE) {
edit = false;
userId = appState.split("#")[1]
let res = await fetch(API_URL + "/users/" + userId, {
mode: "cors",
});
if (res.ok) user = await res.json();
}
}
async function getBlockeds() {
let res = await fetch(API_URL + "/users/blocked/", {
credentials: "include",
mode: "cors",
});
if (res.ok) blockedUsers = await res.json();
}
onMount(() => {
getUser();
getBlockeds();
});
const dispatch = createEventDispatcher();
//--------------------------------------------------------------------------------//
export const blockUser = async (username: string) => { export const blockUser = async (username: string) => {
let response = await fetch(API_URL + "/users/" + username + "/byname", { let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include", credentials: "include",
@ -42,18 +69,19 @@
credentials: "include", credentials: "include",
mode: "cors" mode: "cors"
}); });
dispatch("update-hiddens", username) if (response.ok) {
} blockedUsers.push(target);
if (response.ok) await show_popup("User blocked", false); await show_popup("User blocked", false);
else { } else {
const error = await response.json();
await show_popup(error.message, false);
}
} else {
const error = await response.json(); const error = await response.json();
await show_popup(error.message, false); await show_popup(error.message, false);
} }
dispatch("close")
}; };
//--------------------------------------------------------------------------------/
export const unblockUser = async (username: string) => { export const unblockUser = async (username: string) => {
let response = await fetch(API_URL + "/users/" + username + "/byname", { let response = await fetch(API_URL + "/users/" + username + "/byname", {
credentials: "include", credentials: "include",
@ -68,7 +96,10 @@
}); });
dispatch("update-hiddens", username) dispatch("update-hiddens", username)
} }
if (response.ok) await show_popup("User unblocked", false); if (response.ok) {
await show_popup("User unblocked", false);
blockedUsers = blockedUsers.filter((user) => user.username !== username);
}
else { else {
const error = await response.json(); const error = await response.json();
await show_popup(error.message, false); await show_popup(error.message, false);
@ -76,28 +107,6 @@
dispatch("close") dispatch("close")
}; };
async function getUser() {
if (username !== $store.username) {
edit = false;
let res = await fetch(API_URL + "/users/" + username + "/byname", {
mode: "cors",
});
user = await res.json();
res = await fetch(API_URL + "/users/blocked/", {
credentials: "include",
mode: "cors",
});
if (res.ok) blockedUsers = await res.json();
}
}
onMount(() => {
getUser();
});
const dispatch = createEventDispatcher();
async function handleSubmit() { async function handleSubmit() {
if (gamePlaying) { if (gamePlaying) {
await show_popup("Cannot change username while playing.", false) await show_popup("Cannot change username while playing.", false)
@ -202,7 +211,7 @@
</p> </p>
{/if} {/if}
<p> <p>
<button on:click={() => dispatch("view-history")} <button on:click={() => dispatch("view-history", user.ftId)}
>View History</button >View History</button
> >
</p> </p>

Loading…
Cancel
Save