initial pfp in Join and Lobby
This commit is contained in:
parent
53edb8c7da
commit
31db2f0fc1
|
|
@ -5,10 +5,11 @@ const PlayerModel = require("../models/PlayerModel");
|
||||||
* @param {String} hostName
|
* @param {String} hostName
|
||||||
* @returns A promise which resolves when a new player has been created. Rejects if an error occurs
|
* @returns A promise which resolves when a new player has been created. Rejects if an error occurs
|
||||||
*/
|
*/
|
||||||
exports.addPlayer = (playerName) => {
|
exports.addPlayer = (playerName, playerImage) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let newPlayer = new PlayerModel({
|
let newPlayer = new PlayerModel({
|
||||||
name: playerName,
|
name: playerName,
|
||||||
|
pfpFilename: playerImage,
|
||||||
points: 0,
|
points: 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ const PlayerSchema = new Schema({
|
||||||
name: { type: String, required: true, maxLength: 100 },
|
name: { type: String, required: true, maxLength: 100 },
|
||||||
points: { type: Number },
|
points: { type: Number },
|
||||||
acceptAnswers: { type: Boolean, default: false },
|
acceptAnswers: { type: Boolean, default: false },
|
||||||
|
pfpFilename: { type: String, default: null, required: false },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Export model
|
// Export model
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ const UserSchema = new Schema({
|
||||||
},
|
},
|
||||||
password: { type: String, required: true, },
|
password: { type: String, required: true, },
|
||||||
boards: [{ type: Schema.Types.ObjectId, ref: "Board" }],
|
boards: [{ type: Schema.Types.ObjectId, ref: "Board" }],
|
||||||
pfpFilename: [{ type: String, required: false, default: null }],
|
pfpFilename: { type: String, required: false, default: null },
|
||||||
});
|
});
|
||||||
|
|
||||||
// Virtual for player's URL
|
// Virtual for player's URL
|
||||||
|
|
|
||||||
|
|
@ -21,24 +21,24 @@ app.use(cors({
|
||||||
credentials: true,
|
credentials: true,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
app.use(helmet(
|
// app.use(helmet(
|
||||||
{
|
// {
|
||||||
contentSecurityPolicy: {
|
// contentSecurityPolicy: {
|
||||||
// useDefaults: false,
|
// // useDefaults: false,
|
||||||
directives: {
|
// directives: {
|
||||||
"default-src": ["'self'"],
|
// "default-src": ["'self'"],
|
||||||
"object-src": ["'none'"],
|
// "object-src": ["'none'"],
|
||||||
"script-src": ["'unsafe-inline'", "'unsafe-eval'", "'self'" ],
|
// "script-src": ["'unsafe-inline'", "'unsafe-eval'", "'self'" ],
|
||||||
"base-uri": ["'none'"],
|
// "base-uri": ["'none'"],
|
||||||
"frame-src": ["'none'"],
|
// "frame-src": ["'none'"],
|
||||||
"media-src": ["'self'", "data:"],
|
// "media-src": ["'self'", "data:"],
|
||||||
"style-src-elem": ["'self'", "'unsafe-inline'"],
|
// "style-src-elem": ["'self'", "'unsafe-inline'"],
|
||||||
"connect-src": ["'self'", "ws:"],
|
// "connect-src": ["'self'", "ws:"],
|
||||||
"img-src": ["'self'", "blob:", "data:"],
|
// "img-src": ["'self'", "blob:", "data:"],
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
));
|
// ));
|
||||||
|
|
||||||
|
|
||||||
const mongoDB = process.env.API_MONGO_CONN_URI;
|
const mongoDB = process.env.API_MONGO_CONN_URI;
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ exports.handleMessage = ( gameSocketList, socket, dataRaw ) => {
|
||||||
switch( data.event ){
|
switch( data.event ){
|
||||||
case "joinGame":
|
case "joinGame":
|
||||||
if( payload.gameCode !== undefined && payload.playerName !== undefined ){
|
if( payload.gameCode !== undefined && payload.playerName !== undefined ){
|
||||||
playerController.addPlayer( payload.playerName )
|
playerController.addPlayer( payload.playerName, payload.playerImage )
|
||||||
.then( ( player ) => {
|
.then( ( player ) => {
|
||||||
if( socket.locals === undefined ){
|
if( socket.locals === undefined ){
|
||||||
socket.locals = {};
|
socket.locals = {};
|
||||||
|
|
|
||||||
|
|
@ -194,4 +194,6 @@ $utilities: map-merge(
|
||||||
|
|
||||||
.pfp{
|
.pfp{
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
max-width: 100vw;
|
||||||
|
max-height: 100vh;
|
||||||
}
|
}
|
||||||
|
|
@ -9,9 +9,9 @@ const props = defineProps({
|
||||||
default: null,
|
default: null,
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
sizingClasses: {
|
sizing: {
|
||||||
type: Array,
|
type: String,
|
||||||
default: () => ["pfp-sizing"],
|
default: "10rem",
|
||||||
required: false,
|
required: false,
|
||||||
},
|
},
|
||||||
isPreview: {
|
isPreview: {
|
||||||
|
|
@ -47,7 +47,7 @@ const pfpSrc = computed( () => {
|
||||||
<template>
|
<template>
|
||||||
<div>
|
<div>
|
||||||
<div class="border border-1 border-white rounded-3 overflow-hidden">
|
<div class="border border-1 border-white rounded-3 overflow-hidden">
|
||||||
<img :src="pfpSrc" alt="Profile Picture of the user" class="pfp" :class="sizingClasses" />
|
<img :src="pfpSrc" alt="Profile Picture of the user" class="pfp" :style="[ { 'width': props.sizing }, { 'height': props.sizing } ]" />
|
||||||
<div v-show="props.isPreview" class="position-relative">
|
<div v-show="props.isPreview" class="position-relative">
|
||||||
<span class="position-absolute bottom-0 end-0 bg-black bg-opacity-50 px-1 rounded-2">
|
<span class="position-absolute bottom-0 end-0 bg-black bg-opacity-50 px-1 rounded-2">
|
||||||
Preview
|
Preview
|
||||||
|
|
@ -57,16 +57,3 @@ const pfpSrc = computed( () => {
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.pfp-sizing{
|
|
||||||
height: 10rem;
|
|
||||||
width: 10rem;
|
|
||||||
max-height: 100vh;
|
|
||||||
max-width: 100vw;
|
|
||||||
}
|
|
||||||
.pfp-sizing-navbar{
|
|
||||||
height: 2em;
|
|
||||||
width: 2em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -72,7 +72,7 @@ function logoutButtonClicked(_event){
|
||||||
<font-awesome-icon icon="fa-solid fa-angle-down" size="sm" class="me-2"/>
|
<font-awesome-icon icon="fa-solid fa-angle-down" size="sm" class="me-2"/>
|
||||||
<span class="me-1">{{ userStore.username }}</span>
|
<span class="me-1">{{ userStore.username }}</span>
|
||||||
<ProfilePicture
|
<ProfilePicture
|
||||||
:sizingClasses="['pfp-sizing-navbar']"
|
:sizing="'2em'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
@ -107,7 +107,7 @@ function logoutButtonClicked(_event){
|
||||||
<font-awesome-icon icon="fa-solid fa-angle-down" size="sm" class="me-2"/>
|
<font-awesome-icon icon="fa-solid fa-angle-down" size="sm" class="me-2"/>
|
||||||
<span class="me-1">{{ userStore.username }}</span>
|
<span class="me-1">{{ userStore.username }}</span>
|
||||||
<ProfilePicture
|
<ProfilePicture
|
||||||
:sizingClasses="['pfp-sizing-navbar']"
|
:sizing="'2em'"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useRouter, useRoute } from "vue-router";
|
import { useRouter, useRoute } from "vue-router";
|
||||||
|
import { ref } from "vue";
|
||||||
|
|
||||||
import { useUserStore } from "@/stores/UserStore";
|
import { useUserStore } from "@/stores/UserStore";
|
||||||
import { useGameStore } from "@/stores/GameStore";
|
import { useGameStore } from "@/stores/GameStore";
|
||||||
import { ref } from "vue";
|
import ProfilePicture from "@/components/blocks/ProfilePicture.vue";
|
||||||
|
|
||||||
let errorMessage = ref("");
|
let errorMessage = ref("");
|
||||||
let playerName = ref("");
|
let playerName = ref("");
|
||||||
|
|
@ -12,13 +14,14 @@ let forwardTo = { name: "gameLobby", params: { gameId: -1 } };
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const gameStore = useGameStore();
|
const gameStore = useGameStore();
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
function joinButtonClicked(_event) {
|
function joinButtonClicked(_event) {
|
||||||
if( joinRequest.value === true ){
|
if( joinRequest.value === true ){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
joinRequest.value = true;
|
joinRequest.value = true;
|
||||||
gameStore.joinGame( playerName.value )
|
gameStore.joinGame( playerName.value, userStore.pfpFilename )
|
||||||
.then( ( gameId ) => {
|
.then( ( gameId ) => {
|
||||||
forwardTo.params.gameId = gameId;
|
forwardTo.params.gameId = gameId;
|
||||||
router.push( forwardTo );
|
router.push( forwardTo );
|
||||||
|
|
@ -31,6 +34,10 @@ function joinButtonClicked(_event) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( userStore.loggedIn ){
|
||||||
|
playerName.value = userStore.username;
|
||||||
|
}
|
||||||
|
|
||||||
let gameId = route.params.gameId;
|
let gameId = route.params.gameId;
|
||||||
if( gameId ){
|
if( gameId ){
|
||||||
joinRequest.value = true;
|
joinRequest.value = true;
|
||||||
|
|
@ -91,6 +98,11 @@ if( gameId ){
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center">
|
<div class="card-body text-center">
|
||||||
<div class="d-flex flex-column h-100 w-100 align-items-center justify-content-center">
|
<div class="d-flex flex-column h-100 w-100 align-items-center justify-content-center">
|
||||||
|
<div>
|
||||||
|
<ProfilePicture
|
||||||
|
:sizing="'8rem'"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="d-flex px-3 w-100">
|
<div class="d-flex px-3 w-100">
|
||||||
<div class="w-100 text-start">
|
<div class="w-100 text-start">
|
||||||
<label for="username" class="fs-5 mb-1">Username</label>
|
<label for="username" class="fs-5 mb-1">Username</label>
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,8 @@ import { onMounted, onUnmounted, ref } from 'vue';
|
||||||
import { useRouter, onBeforeRouteLeave, useRoute } from 'vue-router';
|
import { useRouter, onBeforeRouteLeave, useRoute } from 'vue-router';
|
||||||
|
|
||||||
import { useGameStore } from '@/stores/GameStore';
|
import { useGameStore } from '@/stores/GameStore';
|
||||||
|
|
||||||
import BoardListView from "@/components/views/BoardListView.vue";
|
import BoardListView from "@/components/views/BoardListView.vue";
|
||||||
|
import ProfilePicture from '@/components/blocks/ProfilePicture.vue';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
@ -13,6 +13,13 @@ const gameStore = useGameStore();
|
||||||
let selectedBoardId = ref("0");
|
let selectedBoardId = ref("0");
|
||||||
let showBoardMessage = ref( false );
|
let showBoardMessage = ref( false );
|
||||||
|
|
||||||
|
let protocol = ('https:' == document.location.protocol ? 'https://' : 'http://');
|
||||||
|
let hostname = window.location.hostname;
|
||||||
|
if( window.location.hostname.includes("localhost" ) ){
|
||||||
|
hostname += ':3000';
|
||||||
|
}
|
||||||
|
const API_URL = `${protocol}${hostname}/api`;
|
||||||
|
|
||||||
|
|
||||||
function startGame(){
|
function startGame(){
|
||||||
if( selectedBoardId.value !== "0" ){
|
if( selectedBoardId.value !== "0" ){
|
||||||
|
|
@ -127,7 +134,15 @@ onBeforeRouteLeave((to, from) => {
|
||||||
<div class="col-4 my-3">
|
<div class="col-4 my-3">
|
||||||
<div class="card bg-primary">
|
<div class="card bg-primary">
|
||||||
<div class="card-body fs-4 text-center">
|
<div class="card-body fs-4 text-center">
|
||||||
|
<div class="d-flex justify-content-center align-items-center">
|
||||||
|
<ProfilePicture
|
||||||
|
:srcOverride="API_URL + '/user/pfp/' + player.pfpFilename"
|
||||||
|
:sizing="'2.5em'"
|
||||||
|
/>
|
||||||
|
<span class="ms-3">
|
||||||
{{ playerIdx + 1 }} - {{ player.name }}
|
{{ playerIdx + 1 }} - {{ player.name }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -135,7 +135,7 @@ export const useGameStore = defineStore('game', {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
joinGame( playerName ){
|
joinGame( playerName, playerImage ){
|
||||||
return new Promise( ( resolve, reject ) =>{
|
return new Promise( ( resolve, reject ) =>{
|
||||||
if( this.websocketConnection.readyState === 1 ){
|
if( this.websocketConnection.readyState === 1 ){
|
||||||
|
|
||||||
|
|
@ -160,6 +160,7 @@ export const useGameStore = defineStore('game', {
|
||||||
payload: {
|
payload: {
|
||||||
gameCode: this.gameCode,
|
gameCode: this.gameCode,
|
||||||
playerName: this.playerName,
|
playerName: this.playerName,
|
||||||
|
playerImage: playerImage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.websocketConnection.send( JSON.stringify( sendObj ) );
|
this.websocketConnection.send( JSON.stringify( sendObj ) );
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,11 @@ export const useUserStore = defineStore('user', {
|
||||||
setUser( user ){
|
setUser( user ){
|
||||||
this.loggedIn = true;
|
this.loggedIn = true;
|
||||||
this.username = user.username;
|
this.username = user.username;
|
||||||
|
if( user.pfpFilename ){
|
||||||
this.pfpFilename = user.pfpFilename;
|
this.pfpFilename = user.pfpFilename;
|
||||||
|
} else {
|
||||||
|
this.pfpFilename = null;
|
||||||
|
}
|
||||||
},
|
},
|
||||||
resetInitialUserDataPromise(){
|
resetInitialUserDataPromise(){
|
||||||
this.initialUserPromise = new Promise( (resolve, reject ) => {
|
this.initialUserPromise = new Promise( (resolve, reject ) => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue