Browse Source

*fonctional history

master
nicolas-arnaud 2 years ago
parent
commit
40b6f166a2
  1. 1523
      back/volume/package-lock.json
  2. 2
      back/volume/src/pong/pong.service.ts
  3. 2
      back/volume/src/users/entity/user.entity.ts
  4. 3
      back/volume/src/users/users.controller.ts
  5. 5
      back/volume/src/users/users.module.ts
  6. 8
      back/volume/src/users/users.service.ts
  7. 35
      front/volume/src/App.svelte
  8. 42
      front/volume/src/components/Chat2.svelte
  9. 10
      front/volume/src/components/Friends.svelte
  10. 18
      front/volume/src/components/Leaderboard.svelte
  11. 16
      front/volume/src/components/MatchHistory.svelte
  12. 2
      front/volume/src/components/NavBar.svelte
  13. 32
      front/volume/src/components/Profile.svelte

1523
back/volume/package-lock.json

File diff suppressed because it is too large

2
back/volume/src/pong/pong.service.ts

@ -22,7 +22,7 @@ export class PongService {
else player.looses++
player.winrate = (100 * player.wins) / player.matchs
player.rank = (await this.usersService.getRank(player.ftId)) + 1
// player.results.push(result)
player.results.push(result)
this.usersService.save(player)
}

2
back/volume/src/users/entity/user.entity.ts

@ -33,7 +33,7 @@ export class User {
@Column({ default: 'online' })
status: string
@Column({ name: 'avatar'})
@Column({ name: 'avatar' })
avatar: string
@Column({ default: 0 })

3
back/volume/src/users/users.controller.ts

@ -137,6 +137,9 @@ export class UsersController {
@FtUser() profile: Profile,
@Param('id', ParseIntPipe) id: number
): Promise<NotFoundException | null | undefined> {
if (profile.id == id) {
throw new BadRequestException("You can't invit yourself.")
}
return await this.usersService.invit(profile.id, id)
}

5
back/volume/src/users/users.module.ts

@ -6,10 +6,7 @@ import { UsersService } from './users.service'
import { PongModule } from 'src/pong/pong.module'
@Module({
imports: [
forwardRef(() => PongModule),
TypeOrmModule.forFeature([User])
],
imports: [forwardRef(() => PongModule), TypeOrmModule.forFeature([User])],
controllers: [UsersController],
providers: [UsersService],
exports: [UsersService]

8
back/volume/src/users/users.service.ts

@ -31,8 +31,8 @@ export class UsersService {
}
@Cron('0 * * * * *')
async updateStatus() {
let users = await this.usersRepository.find({})
async updateStatus () {
const users = await this.usersRepository.find({})
users.forEach((usr) => {
if (Date.now() - usr.lastAccess > 60000) {
usr.status = 'offline'
@ -111,7 +111,9 @@ export class UsersService {
const user = await this.usersRepository.findOne({
where: { ftId },
relations: {
results: true
results: {
players: true
}
}
})
if (user != null) return user.results

35
front/volume/src/App.svelte

@ -4,8 +4,8 @@
import Profile from "./components/Profile.svelte";
import MatchHistory from "./components/MatchHistory.svelte";
import type { Match } from "./components/MatchHistory.svelte";
import Friends,{addFriend} from "./components/Friends.svelte";
import type { Friend} from "./components/Friends.svelte";
import Friends, { addFriend } from "./components/Friends.svelte";
import type { Friend } from "./components/Friends.svelte";
import Spectate from "./components/Spectate.svelte";
import type { SpectateType } from "./components/Spectate.svelte";
import Pong from "./components/Pong/Pong.svelte";
@ -13,7 +13,7 @@
import Channels from "./components/Channels.svelte";
import type { ChannelsType } from "./components/Channels.svelte";
import Leaderboard from "./components/Leaderboard.svelte";
import type { Player } from "./components/Leaderboard.svelte"
import type { Player } from "./components/Leaderboard.svelte";
import { store, getUser, login, logout, API_URL } from "./Auth";
@ -34,7 +34,7 @@
let userProfile;
let isIdProfileOpen = false;
async function openIdProfile(event) {
console.log("Opening profile: " + event.detail)
console.log("Opening profile: " + event.detail);
isIdProfileOpen = true;
const res = await fetch(API_URL + "/user/" + event.detail, {
method: "get",
@ -48,18 +48,19 @@
// HISTORY
let matches: Array<Match>;
let isHistoryOpen = false;
function clickHistory() {
isHistoryOpen = true;
getHistory();
}
let matches: Array<Match>;
export async function getHistory(): Promise<Match[]> {
let response = await fetch(API_URL + "/history/" + $store.ftId, {
credentials: "include",
mode: "cors",
});
return await response.json();
matches = await response.json();
}
// FRIENDS
@ -144,7 +145,6 @@
isLeaderboardOpen = true;
leaderboard = await getLeader();
}
</script>
<main>
@ -166,8 +166,11 @@
on:click={() => (selectedChannel = undefined)}
on:keydown={() => (selectedChannel = undefined)}
>
<Chat2 chatMessages={selectedChannel.messages}
on:view-profile={openIdProfile} on:add-friend={addFriend} />
<Chat2
chatMessages={selectedChannel.messages}
on:view-profile={openIdProfile}
on:add-friend={addFriend}
/>
</div>
{/if}
{#if !selectedChannel}
@ -192,7 +195,7 @@
on:click={() => (isLeaderboardOpen = false)}
on:keydown={() => (isLeaderboardOpen = false)}
>
<Leaderboard {leaderboard}/>
<Leaderboard {leaderboard} />
</div>
{/if}
{#if isFriendOpen}
@ -203,7 +206,7 @@
}}
on:keydown={() => {
isFriendOpen = false;
clearInterval(friendsInterval)
clearInterval(friendsInterval);
}}
>
<Friends {friends} {invits} />
@ -222,10 +225,7 @@
on:click={() => (isProfileOpen = false)}
on:keydown={() => (isProfileOpen = false)}
>
<Profile
user = {$store}
edit = 1
/>
<Profile user={$store} edit={1} />
</div>
{/if}
{#if isIdProfileOpen}
@ -233,10 +233,7 @@
on:click={() => (isIdProfileOpen = false)}
on:keydown={() => (isIdProfileOpen = false)}
>
<Profile
user = {userProfile}
edit = 0
/>
<Profile user={userProfile} edit={0} />
</div>
{/if}
<Pong />

42
front/volume/src/components/Chat2.svelte

@ -5,7 +5,7 @@
text: string;
}
import { createEventDispatcher, onMount } from "svelte";
import { store } from "../Auth"
import { store } from "../Auth";
</script>
<script lang="ts">
@ -32,7 +32,7 @@
const dispatch = createEventDispatcher();
let showProfileMenu = false;
let selectedUser = null;
function openProfile(username : string) {
function openProfile(username: string) {
showProfileMenu = true;
selectedUser = username;
}
@ -40,7 +40,7 @@
showProfileMenu = false;
selectedUser = "";
}
onMount(closeProfileMenu)
onMount(closeProfileMenu);
</script>
<div class="overlay">
@ -60,7 +60,11 @@
{/each}
</div>
{#if showProfileMenu}
<div class="profile-menu" on:click|stopPropagation on:keydown|stopPropagation>
<div
class="profile-menu"
on:click|stopPropagation
on:keydown|stopPropagation
>
<ul>
<!-- if admin
<li><button on:click={() => dispatch('delete-user', selectedUser)}>Delete User</button></li>
@ -68,11 +72,31 @@
<li><button on:click={() => dispatch('mute-user', selectedUser)}>Mute User</button></li>
<li><button on:click={() => dispatch('promote-user', selectedUser)}>Promote User</button></li>
-->
<li><button on:click={() => dispatch('send-message', selectedUser)}>Send Message</button></li>
<li><button on:click={() => dispatch('view-profile', selectedUser)}>View Profile</button></li>
<li><button on:click={() => dispatch('add-friend', selectedUser)}>Add Friend</button></li>
<li><button on:click={() => dispatch('invite-to-game', selectedUser)}>Invite to Game</button></li>
<li><button on:click={() => dispatch('block-user', selectedUser)}>Block User</button></li>
<li>
<button on:click={() => dispatch("send-message", selectedUser)}
>Send Message</button
>
</li>
<li>
<button on:click={() => dispatch("view-profile", selectedUser)}
>View Profile</button
>
</li>
<li>
<button on:click={() => dispatch("add-friend", selectedUser)}
>Add Friend</button
>
</li>
<li>
<button on:click={() => dispatch("invite-to-game", selectedUser)}
>Invite to Game</button
>
</li>
<li>
<button on:click={() => dispatch("block-user", selectedUser)}
>Block User</button
>
</li>
<li><button on:click={closeProfileMenu}>Close</button></li>
</ul>
</div>

10
front/volume/src/components/Friends.svelte

@ -8,8 +8,8 @@
console.log(typeof event);
event.preventDefault();
const username = event.target ?
event.target.querySelector('input[type="text"]').value
const username = event.target
? event.target.querySelector('input[type="text"]').value
: event.detail;
let response = await fetch(API_URL + "/user/" + username, {
@ -23,11 +23,10 @@
mode: "cors",
});
if (response.ok) {
console.log("Invitation send.");
alert("Invitation send.");
} else {
console.log("Unknown user.");
alert("Invitation refused.");
}
alert("Trying to add friend: " + username);
}
</script>
@ -36,7 +35,6 @@
export let friends: Friend[];
export let invits: Friend[];
</script>
<div class="overlay">

18
front/volume/src/components/Leaderboard.svelte

@ -2,7 +2,7 @@
export interface Player {
username: string;
wins: number;
losses: number;
looses: number;
winrate: number;
rank: number;
}
@ -17,11 +17,11 @@
<div>
{#if leaderboard.length > 0}
<h2>Leaderboard</h2>
{#each leaderboard.slice(0, 10) as match}
{#each leaderboard.slice(0, 10) as player}
<li>
<span>{match.username}</span>
<span>{match.wins} - {match.losses}</span>
<span>MP | rank #{match.rank}</span>
<span>{player.username}</span>
<span>{player.wins} - {player.looses} - {player.winrate}%wins</span>
<span> | rank #{player.rank}</span>
</li>
{/each}
{:else}
@ -32,7 +32,7 @@
</div>
<style>
.overlay {
.overlay {
position: fixed;
top: 0;
left: 0;
@ -43,13 +43,13 @@
display: flex;
justify-content: center;
align-items: center;
}
}
.history {
.history {
background-color: #fff;
border: 1px solid #ccc;
border-radius: 5px;
padding: 1rem;
width: 300px;
}
}
</style>

16
front/volume/src/components/MatchHistory.svelte

@ -1,15 +1,19 @@
<script lang="ts" context="module">
import type user from './Profile.svelte'
import type user from "./Profile.svelte";
export interface Match {
players: Array<user>;
scores: Array<number>;
score: Array<number>;
date: Date;
}
</script>
<script lang="ts">
export let matches: Array<Match> = [];
function displayDate(str: string) {
const splitT = str.split("T");
const splitdot = splitT[1].split(".");
return splitT[0] + "-" + splitdot[0];
}
</script>
<div class="overlay">
@ -19,7 +23,11 @@
<h2>Last 10 monkey games</h2>
{#each matches.slice(0, 10) as match}
<li>
<span>{match.date.toString()}: {match.players[0].username} {match.scores[0]} - {match.scores[1]} {match.players[1].username}</span>
<span
>{displayDate(match.date.toString())}: {match.players[0].username}
{match.scores[0]} - {match.scores[1]}
{match.players[1].username}</span
>
<!---
{#if match.points > 0}
<span>+{match.points}</span>

2
front/volume/src/components/NavBar.svelte

@ -10,7 +10,7 @@
{ text: "Channels" },
{ text: "History" },
{ text: "Friends" },
{ text: "Leaderboard"},
{ text: "Leaderboard" },
{ text: "Profile" },
];
export let clickProfile = () => {};

32
front/volume/src/components/Profile.svelte

@ -1,15 +1,15 @@
<script lang="ts">
import { API_URL, store, logout } from "../Auth";
export let edit = 0
export let edit = 0;
export let user = {
username: "",
wins: 0,
losses: 0,
looses: 0,
winrate: 0,
rank: -1,
is2faEnabled: false
}
is2faEnabled: false,
};
async function handleSubmit() {
let response = await fetch(API_URL, {
@ -39,7 +39,6 @@
<div class="overlay">
<div class="profile" on:click|stopPropagation on:keydown|stopPropagation>
<h3>===| <mark>{user.username}'s Profile</mark> |===</h3>
<div class="profile-header">
{#if edit == 0}
@ -51,22 +50,33 @@
enctype="multipart/form-data"
id="upload_avatar"
>
<input type="file" id="avatar-input" name="avatar" on:change={submitAvatar} />
<input
type="file"
id="avatar-input"
name="avatar"
on:change={submitAvatar}
/>
</form>
<label class="img-class" for="avatar-input">
<img src={API_URL + "/avatar"} alt="avatar" class="profile-img"/>
<img src={API_URL + "/avatar"} alt="avatar" class="profile-img" />
</label>
{/if}
</div>
<div class="profile-body">
<p>Wins: {user.wins}</p>
<p>Losses: {user.losses}</p>
<p>Looses: {user.looses}</p>
<p>Winrate: {user.winrate}%</p>
<p>Rank: {user.rank}</p>
{#if edit == 1}
<form id="username-form" class="username" on:submit|preventDefault={handleSubmit}>
<form
id="username-form"
class="username"
on:submit|preventDefault={handleSubmit}
>
<input type="text" id="username" bind:value={user.username} />
<button type="submit" class="username" form="username-form">Change</button>
<button type="submit" class="username" form="username-form"
>Change</button
>
</form>
<button type="button" on:click={handle2fa}>
{#if user.is2faEnabled}
@ -109,7 +119,7 @@
}
.profile-header {
margin:auto;
margin: auto;
justify-content: center;
}

Loading…
Cancel
Save