From d5dc807b0916d26862a2e6c787b67c329a99b5dd Mon Sep 17 00:00:00 2001 From: Gregoire Parant Date: Mon, 21 Dec 2020 16:48:40 +0100 Subject: [PATCH] Login & Sign in Create html element to log in and sign in --- .../resources/html/gameForgotPassword.html | 105 ++++++ front/dist/resources/html/gameLogin.html | 111 +++++++ front/dist/resources/html/gameMenu.html | 3 + front/dist/resources/html/gameRegister.html | 117 +++++++ front/dist/resources/html/gameShare.html | 106 ++++++ front/src/Connexion/ConnectionManager.ts | 54 ++- front/src/Connexion/LocalUser.ts | 10 + front/src/Exception/ErrorConnectedError.ts | 1 + front/src/Exception/NotConnectedError.ts | 1 + front/src/Phaser/Menu/MenuScene.ts | 311 +++++++++++++++++- 10 files changed, 813 insertions(+), 6 deletions(-) create mode 100644 front/dist/resources/html/gameForgotPassword.html create mode 100644 front/dist/resources/html/gameLogin.html create mode 100644 front/dist/resources/html/gameRegister.html create mode 100644 front/dist/resources/html/gameShare.html create mode 100644 front/src/Exception/ErrorConnectedError.ts create mode 100644 front/src/Exception/NotConnectedError.ts diff --git a/front/dist/resources/html/gameForgotPassword.html b/front/dist/resources/html/gameForgotPassword.html new file mode 100644 index 00000000..691a7d0c --- /dev/null +++ b/front/dist/resources/html/gameForgotPassword.html @@ -0,0 +1,105 @@ + + + + diff --git a/front/dist/resources/html/gameLogin.html b/front/dist/resources/html/gameLogin.html new file mode 100644 index 00000000..98df47ea --- /dev/null +++ b/front/dist/resources/html/gameLogin.html @@ -0,0 +1,111 @@ + + + diff --git a/front/dist/resources/html/gameMenu.html b/front/dist/resources/html/gameMenu.html index 88c76ca2..3a6b833b 100644 --- a/front/dist/resources/html/gameMenu.html +++ b/front/dist/resources/html/gameMenu.html @@ -38,5 +38,8 @@ +
+ +
diff --git a/front/dist/resources/html/gameRegister.html b/front/dist/resources/html/gameRegister.html new file mode 100644 index 00000000..5be17a0c --- /dev/null +++ b/front/dist/resources/html/gameRegister.html @@ -0,0 +1,117 @@ + + + diff --git a/front/dist/resources/html/gameShare.html b/front/dist/resources/html/gameShare.html new file mode 100644 index 00000000..4e487328 --- /dev/null +++ b/front/dist/resources/html/gameShare.html @@ -0,0 +1,106 @@ + + + diff --git a/front/src/Connexion/ConnectionManager.ts b/front/src/Connexion/ConnectionManager.ts index a113a00c..fa09a046 100644 --- a/front/src/Connexion/ConnectionManager.ts +++ b/front/src/Connexion/ConnectionManager.ts @@ -4,15 +4,24 @@ import {RoomConnection} from "./RoomConnection"; import {OnConnectInterface, PositionInterface, ViewportInterface} from "./ConnexionModels"; import {GameConnexionTypes, urlManager} from "../Url/UrlManager"; import {localUserStore} from "./LocalUserStore"; -import {LocalUser} from "./LocalUser"; +import {ConnectedUser, LocalUser} from "./LocalUser"; import {Room} from "./Room"; +import {NotConnectedError} from "../Exception/NotConnectedError"; +import {ErrorConnectedError} from "../Exception/ErrorConnectedError"; const URL_ROOM_STARTED = '/Floor0/floor0.json'; class ConnectionManager { private localUser!:LocalUser; - private connexionType?: GameConnexionTypes + private connexionType?: GameConnexionTypes; + + private connectedUser?: ConnectedUser|null; + + constructor() { + this.verifyLoggedUser(); + } + /** * Tries to login to the node server and return the starting map url to be loaded */ @@ -109,6 +118,47 @@ class ConnectionManager { get getConnexionType(){ return this.connexionType; } + + public verifyLoggedUser(){ + //Verify spark session + Axios.get('http://admin.workadventure.localhost/user/connected').then((res) => { + console.log('res', res); + Axios.get('http://admin.workadventure.localhost/notifications/recent').then((res) => { + this.connectedUser = res.data; + }).catch((err) => { + console.error(err); + this.connectedUser = null; + throw new ErrorConnectedError('Error to get user element'); + }); + }).catch((err) => { + if(err instanceof ErrorConnectedError) { + throw err; + } + console.log('err', err); + this.connectedUser = null; + throw new NotConnectedError('User not connected'); + }); + } + + /** + * RegisterUser + * + * @param name + * @param email + * @param password + * @param confirmPassword + */ + public registerUser(name: string, email: string, password: string, confirmPassword: string){ + Axios.get('http://admin.workadventure.localhost/member/register') + .then((res) => { + this.connectedUser = res.data; + }) + .catch((err) => { + this.connectedUser = null; + console.log(err); + throw err; + }) + } } export const connectionManager = new ConnectionManager(); diff --git a/front/src/Connexion/LocalUser.ts b/front/src/Connexion/LocalUser.ts index 06d98b70..62918814 100644 --- a/front/src/Connexion/LocalUser.ts +++ b/front/src/Connexion/LocalUser.ts @@ -9,3 +9,13 @@ export class LocalUser { constructor(public readonly uuid:string, public readonly jwtToken: string, public readonly textures: CharacterTexture[]) { } } + +export class ConnectedUser { + constructor( + public readonly name:string, + public readonly email: string, + public readonly notification: [], + public readonly announcements: [], + ) { + } +} diff --git a/front/src/Exception/ErrorConnectedError.ts b/front/src/Exception/ErrorConnectedError.ts new file mode 100644 index 00000000..783e93ed --- /dev/null +++ b/front/src/Exception/ErrorConnectedError.ts @@ -0,0 +1 @@ +export class ErrorConnectedError extends Error{} \ No newline at end of file diff --git a/front/src/Exception/NotConnectedError.ts b/front/src/Exception/NotConnectedError.ts new file mode 100644 index 00000000..387a1ce3 --- /dev/null +++ b/front/src/Exception/NotConnectedError.ts @@ -0,0 +1 @@ +export class NotConnectedError extends Error{} \ No newline at end of file diff --git a/front/src/Phaser/Menu/MenuScene.ts b/front/src/Phaser/Menu/MenuScene.ts index e0817d39..559204f4 100644 --- a/front/src/Phaser/Menu/MenuScene.ts +++ b/front/src/Phaser/Menu/MenuScene.ts @@ -9,6 +9,10 @@ export const MenuSceneName = 'MenuScene'; const gameMenuKey = 'gameMenu'; const gameMenuIconKey = 'gameMenuIcon'; const gameSettingsMenuKey = 'gameSettingsMenu'; +const gameLogin = 'gameLogin'; +const gameForgotPassword = 'gameForgotPassword'; +const gameRegister = 'gameRegister'; +const gameShare = 'gameShare'; const closedSideMenuX = -200; const openedSideMenuX = 0; @@ -19,8 +23,14 @@ const openedSideMenuX = 0; export class MenuScene extends Phaser.Scene { private menuElement!: Phaser.GameObjects.DOMElement; private gameQualityMenuElement!: Phaser.GameObjects.DOMElement; + private gameLoginElement!: Phaser.GameObjects.DOMElement; + private gameForgotPasswordElement!: Phaser.GameObjects.DOMElement; + private gameRegisterElement!: Phaser.GameObjects.DOMElement; + private gameShareElement!: Phaser.GameObjects.DOMElement; private sideMenuOpened = false; private settingsMenuOpened = false; + private gameLoginMenuOpened = false; + private gameShareOpened = false; private gameQualityValue: number; private videoQualityValue: number; private menuButton!: Phaser.GameObjects.DOMElement; @@ -36,6 +46,10 @@ export class MenuScene extends Phaser.Scene { this.load.html(gameMenuKey, 'resources/html/gameMenu.html'); this.load.html(gameMenuIconKey, 'resources/html/gameMenuIcon.html'); this.load.html(gameSettingsMenuKey, 'resources/html/gameQualityMenu.html'); + this.load.html(gameLogin, 'resources/html/gameLogin.html'); + this.load.html(gameForgotPassword, 'resources/html/gameForgotPassword.html'); + this.load.html(gameRegister, 'resources/html/gameRegister.html'); + this.load.html(gameShare, 'resources/html/gameShare.html'); } create() { @@ -47,6 +61,62 @@ export class MenuScene extends Phaser.Scene { this.gameQualityMenuElement = this.add.dom(middleX, -400).createFromCache(gameSettingsMenuKey); this.revealMenusAfterInit(this.gameQualityMenuElement, 'gameQuality'); + this.gameLoginElement = this.add.dom(middleX, -400).createFromCache(gameLogin); + this.revealMenusAfterInit(this.gameLoginElement, gameLogin); + this.gameLoginElement.addListener('click'); + this.gameLoginElement.on('click', (event:MouseEvent) => { + event.preventDefault(); + if((event?.target as HTMLInputElement).id === 'gameLoginFormCancel') { + this.closeGameLogin(); + }else if((event?.target as HTMLInputElement).id === 'gameLoginFormSubmit') { + this.login(); + }else if((event?.target as HTMLInputElement).id === 'gameLoginFormForgotPassword') { + this.closeGameLogin(); + this.openGameForgotPassword(); + }else if((event?.target as HTMLInputElement).id === 'gameLoginFormRegister') { + this.closeGameLogin(); + this.openGameRegister(); + } + }); + + this.gameForgotPasswordElement = this.add.dom(middleX, -400).createFromCache(gameForgotPassword); + this.revealMenusAfterInit(this.gameForgotPasswordElement, gameForgotPassword); + this.gameForgotPasswordElement.addListener('click'); + this.gameForgotPasswordElement.on('click', (event:MouseEvent) => { + event.preventDefault(); + if((event?.target as HTMLInputElement).id === 'gameLoginFormForgotPasswordSubmit') { + this.sendEmail(); + }else if((event?.target as HTMLInputElement).id === 'gameLoginFormForgotPasswordCancel') { + this.closeGameForgotPassword(); + this.openGameLogin(); + } + }); + + this.gameRegisterElement = this.add.dom(middleX, -400).createFromCache(gameRegister); + this.revealMenusAfterInit(this.gameRegisterElement, gameRegister); + this.gameRegisterElement.addListener('click'); + this.gameRegisterElement.on('click', (event:MouseEvent) => { + event.preventDefault(); + if((event?.target as HTMLInputElement).id === 'gameRegisterFormSubmit') { + this.register(); + }else if((event?.target as HTMLInputElement).id === 'gameRegisterFormCancel') { + this.closeGameRegister(); + this.openGameLogin(); + } + }); + + this.gameShareElement = this.add.dom(middleX, -400).createFromCache(gameShare); + this.revealMenusAfterInit(this.gameShareElement, gameShare); + this.gameShareElement.addListener('click'); + this.gameShareElement.on('click', (event:MouseEvent) => { + event.preventDefault(); + if((event?.target as HTMLInputElement).id === 'gameShareFormSubmit') { + this.copyLink(); + }else if((event?.target as HTMLInputElement).id === 'gameShareFormCancel') { + this.closeGameShare(); + } + }); + this.input.keyboard.on('keyup-TAB', () => { this.sideMenuOpened ? this.closeSideMenu() : this.openSideMenu(); }); @@ -91,7 +161,11 @@ export class MenuScene extends Phaser.Scene { private closeSideMenu(): void { if (!this.sideMenuOpened) return; this.sideMenuOpened = false; - this.closeGameQualityMenu() + this.closeGameQualityMenu(); + this.closeGameForgotPassword(); + this.closeGameLogin(); + this.closeGameRegister(); + this.closeGameShare(); this.menuButton.getChildByID('openMenuButton').innerHTML = ``; gameManager.getCurrentGameScene(this).ConsoleGlobalMessageManager.disabledMessageConsole(); this.tweens.add({ @@ -158,7 +232,231 @@ export class MenuScene extends Phaser.Scene { }); } + private openGameLogin(): void{ + this.closeGameRegister(); + this.closeGameForgotPassword(); + if (this.gameLoginMenuOpened) { + this.closeGameLogin(); + return; + } + this.gameLoginMenuOpened = true; + let middleY = (window.innerHeight / 3) - (257); + if(middleY < 0){ + middleY = 0; + } + let middleX = (window.innerWidth / 3) - 298; + if(middleX < 0){ + middleX = 0; + } + this.tweens.add({ + targets: this.gameLoginElement, + y: middleY, + x: middleX, + duration: 1000, + ease: 'Power3' + }); + } + + private closeGameLogin(): void{ + this.gameLoginMenuOpened = false; + this.tweens.add({ + targets: this.gameLoginElement, + y: -400, + duration: 1000, + ease: 'Power3' + }); + } + + private openGameShare(): void{ + if (this.gameShareOpened) { + this.closeGameShare(); + return; + } + + const gameShareLink = this.gameShareElement.getChildByID('gameShareLink') as HTMLInputElement; + gameShareLink.value = location.toString(); + + this.gameShareOpened = true; + + let middleY = (window.innerHeight / 3) - (257); + if(middleY < 0){ + middleY = 0; + } + let middleX = (window.innerWidth / 3) - 298; + if(middleX < 0){ + middleX = 0; + } + this.tweens.add({ + targets: this.gameShareElement, + y: middleY, + x: middleX, + duration: 1000, + ease: 'Power3' + }); + } + + private closeGameShare(): void{ + const gameShareInfo = this.gameShareElement.getChildByID('gameShareInfo') as HTMLParagraphElement; + gameShareInfo.innerText = ''; + gameShareInfo.style.display = 'none'; + this.gameShareOpened = false; + this.tweens.add({ + targets: this.gameShareElement, + y: -400, + duration: 1000, + ease: 'Power3' + }); + } + + private login(): void{ + let errorForm = false; + const gameLoginEmail = this.gameLoginElement.getChildByID('gameLoginEmail') as HTMLInputElement; + const gameLoginPassword = this.gameLoginElement.getChildByID('gameLoginPassword') as HTMLInputElement; + const gameLoginError = this.gameLoginElement.getChildByID('gameLoginError') as HTMLInputElement; + + gameLoginError.innerText = ''; + gameLoginError.style.display = 'none'; + + if (!gameLoginEmail.value || gameLoginEmail.value === '') { + gameLoginEmail.style.borderColor = 'red'; + errorForm = true; + }else{ + gameLoginEmail.style.borderColor = 'black'; + } + + if (!gameLoginPassword.value || gameLoginPassword.value === '') { + gameLoginPassword.style.borderColor = 'red'; + errorForm = true; + }else{ + gameLoginPassword.style.borderColor = 'black'; + } + + if(errorForm){return;} + + gameLoginError.innerText = 'Login or password incorrect'; + gameLoginError.style.display = 'block'; + //TODO login user in back + } + + private sendEmail(){ + const gameForgotPasswordInfo = this.gameForgotPasswordElement.getChildByID('gameForgotPasswordInfo') as HTMLParagraphElement; + gameForgotPasswordInfo.style.display = 'none'; + gameForgotPasswordInfo.innerText = ''; + + const gameForgotPasswordError = this.gameForgotPasswordElement.getChildByID('gameForgotPasswordError') as HTMLParagraphElement; + gameForgotPasswordError.style.display = 'none'; + gameForgotPasswordError.innerText = ''; + + const gameLoginForgotPasswordEmail = this.gameForgotPasswordElement.getChildByID('gameLoginForgotPasswordEmail') as HTMLInputElement; + gameLoginForgotPasswordEmail.style.borderColor = 'black'; + if(!gameLoginForgotPasswordEmail.value || gameLoginForgotPasswordEmail.value === ''){ + gameForgotPasswordError.innerText = 'The email field is required.'; + gameForgotPasswordError.style.display = 'block'; + gameLoginForgotPasswordEmail.style.borderColor = 'red'; + return; + } + //TODO send email + gameForgotPasswordInfo.style.display = 'block'; + gameForgotPasswordInfo.innerText = 'We have emailed your password reset link!'; + } + + private register(){ + const gameRegisterName = this.gameRegisterElement.getChildByID('gameRegisterName') as HTMLInputElement; + gameRegisterName.style.borderColor = 'black'; + const gameRegisterEmail = this.gameRegisterElement.getChildByID('gameRegisterEmail') as HTMLInputElement; + gameRegisterEmail.style.borderColor = 'black'; + const gameRegisterPassword = this.gameRegisterElement.getChildByID('gameRegisterPassword') as HTMLInputElement; + gameRegisterPassword.style.borderColor = 'black'; + const gameRegisterConfirmPassword = this.gameRegisterElement.getChildByID('gameRegisterConfirmPassword') as HTMLInputElement; + gameRegisterConfirmPassword.style.borderColor = 'black'; + + let hasError = false; + if(!gameRegisterName.value || gameRegisterName.value === ''){ + gameRegisterName.style.borderColor = 'red'; + hasError = true; + } + if(!gameRegisterEmail.value || gameRegisterEmail.value === ''){ + gameRegisterEmail.style.borderColor = 'red'; + hasError = true; + } + if(!gameRegisterPassword.value || gameRegisterPassword.value === ''){ + gameRegisterPassword.style.borderColor = 'red'; + hasError = true; + } + if( + !gameRegisterConfirmPassword.value + || gameRegisterConfirmPassword.value === '' + || gameRegisterConfirmPassword.value !== gameRegisterPassword.value + ){ + gameRegisterConfirmPassword.style.borderColor = 'red'; + hasError = true; + } + + const gameRegisterInfo = this.gameRegisterElement.getChildByID('gameRegisterInfo') as HTMLParagraphElement; + gameRegisterInfo.style.display = 'none'; + gameRegisterInfo.innerText = ''; + + const gameRegisterError = this.gameRegisterElement.getChildByID('gameRegisterError') as HTMLParagraphElement; + gameRegisterError.style.display = 'none'; + gameRegisterError.innerText = ''; + + if(hasError){return;} + } + + private openGameForgotPassword(): void{ + let middleY = (window.innerHeight / 3) - (257); + if(middleY < 0){ + middleY = 0; + } + let middleX = (window.innerWidth / 3) - 298; + if(middleX < 0){ + middleX = 0; + } + this.tweens.add({ + targets: this.gameForgotPasswordElement, + y: middleY, + x: middleX, + duration: 1000, + ease: 'Power3' + }); + } + + private closeGameForgotPassword(): void{ + this.tweens.add({ + targets: this.gameForgotPasswordElement, + y: -400, + duration: 1000, + ease: 'Power3' + }); + } + + private openGameRegister(): void{ + let middleY = (window.innerHeight / 3) - (257); + if(middleY < 0){ + middleY = 0; + } + let middleX = (window.innerWidth / 3) - 298; + if(middleX < 0){ + middleX = 0; + } + this.tweens.add({ + targets: this.gameRegisterElement, + y: middleY, + x: middleX, + duration: 1000, + ease: 'Power3' + }); + } + + private closeGameRegister(): void{ + this.tweens.add({ + targets: this.gameRegisterElement, + y: -400, + duration: 1000, + ease: 'Power3' + }); + } private onMenuClick(event:MouseEvent) { event.preventDefault(); @@ -179,7 +477,7 @@ export class MenuScene extends Phaser.Scene { this.closeSideMenu(); break; case 'shareButton': - this.shareUrl(); + this.openGameShare(); break; case 'editGameSettingsButton': this.openGameSettingsMenu(); @@ -187,12 +485,17 @@ export class MenuScene extends Phaser.Scene { case 'adminConsoleButton': gameManager.getCurrentGameScene(this).ConsoleGlobalMessageManager.activeMessageConsole(); break; + case 'gameLoginMenu': + this.openGameLogin(); + break; } } - private async shareUrl() { + private async copyLink() { await navigator.clipboard.writeText(location.toString()); - alert('URL is copied to your clipboard!'); + const gameShareInfo = this.gameShareElement.getChildByID('gameShareInfo') as HTMLParagraphElement; + gameShareInfo.innerText = 'Link copied, you can share it now!'; + gameShareInfo.style.display = 'block'; } private saveSetting(valueGame: number, valueVideo: number){