Migration to SpringBoot 2.1.6 and Angular 8.

This commit is contained in:
2019-08-11 19:47:43 +02:00
parent 53f49ab13f
commit d919f86233
28 changed files with 425 additions and 221 deletions

19
pom.xml
View File

@@ -14,14 +14,14 @@
<parent> <parent>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> <artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.0.RELEASE</version> <version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository --> <relativePath/> <!-- lookup parent from repository -->
</parent> </parent>
<properties> <properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version> <java.version>11</java.version>
</properties> </properties>
<dependencies> <dependencies>
@@ -33,7 +33,6 @@
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> <artifactId>spring-boot-starter-web</artifactId>
</dependency> </dependency>
<dependency> <dependency>
<groupId>org.springframework.boot</groupId> <groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId> <artifactId>spring-boot-devtools</artifactId>
@@ -53,19 +52,8 @@
<dependency> <dependency>
<groupId>org.postgresql</groupId> <groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId> <artifactId>postgresql</artifactId>
<scope>runtime</scope> <version>42.2.6</version>
</dependency> </dependency>
<!-- <dependency> -->
<!-- <groupId>commons-lang</groupId> -->
<!-- <artifactId>commons-lang</artifactId> -->
<!-- <version>2.3</version> -->
<!-- </dependency> -->
<!-- https://mvnrepository.com/artifact/commons-lang/commons-lang -->
<!-- <dependency> -->
<!-- <groupId>org.apache.commons</groupId> -->
<!-- <artifactId>commons-lang3</artifactId> -->
<!-- <version>3.7</version> -->
<!-- </dependency> -->
</dependencies> </dependencies>
<build> <build>
@@ -80,5 +68,4 @@
</plugins> </plugins>
</build> </build>
</project> </project>

View File

@@ -15,7 +15,7 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
@EntityScan("org.minager") @EntityScan("org.minager")
@EnableTransactionManagement @EnableTransactionManagement
@EnableJpaRepositories("org.minager") @EnableJpaRepositories("org.minager")
@PropertySource("classpath:application.properties") @PropertySource("classpath:application.yml")
public class JpaConfiguration { public class JpaConfiguration {
@Value("${spring.datasource.driverClassName}") @Value("${spring.datasource.driverClassName}")

View File

@@ -12,7 +12,7 @@ public enum ResultCode {
val = pVal; val = pVal;
} }
public int val() { public final int val() {
return val; return val;
} }
} }

View File

@@ -1,59 +1,54 @@
package org.minager.serverhandling; package org.minager.serverhandling;
import java.io.IOException;
import javax.servlet.http.HttpServletResponse;
import org.minager.core.constant.ResultCode; import org.minager.core.constant.ResultCode;
import org.minager.core.entities.business.SystemResult; import org.minager.core.entities.business.SystemResult;
import org.minager.core.services.business.SystemService; import org.minager.core.services.business.SystemService;
import org.minager.core.utils.StringUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Service @Service
public class ServerHandlingService { public class ServerHandlingService {
@Autowired @Autowired
private SystemService systemService; private SystemService systemService;
@Value("${minecraft.server.path}") @Value("${minecraft.service.name}")
private String minecraftServerPath; private String minecraftServiceName;
@Value("${minecraft.server.shell.name}")
private String minecraftServerShellName;
private String buildMinecraftServerShellPath() {
return StringUtils.concat(minecraftServerPath,
minecraftServerPath.charAt(minecraftServerPath.length() - 1) == '/' ? "" : '/',
minecraftServerShellName);
}
public int getStatus() { public int getStatus() {
final SystemResult shellResult = systemService.executeCommand(buildMinecraftServerShellPath(), "api_status"); final SystemResult shellResult = systemService.executeCommand("sudo service", minecraftServiceName, "status");
return Integer.parseInt(shellResult.getStdOut()); return shellResult.getResultCode();
} }
private void startOrStopServer(final HttpServletResponse pResponse, final String pAction) throws IOException { private void startOrStopServer(final HttpServletResponse pResponse, final String pAction) throws IOException {
final SystemResult shellResult = systemService.executeCommand(buildMinecraftServerShellPath(), pAction); int serviceStatus = getStatus();
if("start".equals(pAction) && serviceStatus == 0
if(shellResult.getResultCode() == ResultCode.FAILED.val()) { || "stop".equals(pAction) && serviceStatus != 0) {
pResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
} else if(shellResult.getResultCode() == ResultCode.STATE_UNCHANGED.val()) {
pResponse.sendError(HttpServletResponse.SC_CONFLICT); pResponse.sendError(HttpServletResponse.SC_CONFLICT);
} // else -> SUCCESS, so code 200 } else {
final SystemResult shellResult = systemService.executeCommand("sudo service", minecraftServiceName, pAction);
if(shellResult.getResultCode() == ResultCode.SUCCESS.val()) {
pResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
} else { // FAILED
pResponse.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
}
}
} }
public void startServer(final HttpServletResponse pResponse) throws IOException { public void startServer(final HttpServletResponse pResponse) throws IOException {
startOrStopServer(pResponse, "api_start"); startOrStopServer(pResponse, "start");
} }
public void stopServer(final HttpServletResponse pResponse) throws IOException { public void stopServer(final HttpServletResponse pResponse) throws IOException {
startOrStopServer(pResponse, "api_stop"); startOrStopServer(pResponse, "stop");
} }
public void restartServer(final HttpServletResponse pResponse) throws IOException { public void restartServer(final HttpServletResponse pResponse) throws IOException {
startOrStopServer(pResponse, "api_restart"); startOrStopServer(pResponse, "restart");
} }
} }

View File

@@ -1,16 +0,0 @@
# ***********************************************
# Hibernate database configuration
# ***********************************************
spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/db_minager
spring.datasource.username=minager
spring.datasource.password=P@ssword
# Disable feature detection by this undocumented parameter. Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
spring.jpa.properties.hibernate.temp.use_jdbc_metadata_defaults = false
# ***********************************************
# Application custom parameters
# ***********************************************
minager.version=1.0.0
minecraft.server.path=/home/minecraft/server
minecraft.server.shell.name=minecraft-server.sh

View File

@@ -0,0 +1,21 @@
minager:
version: 1.2.0
minecraft:
service:
name: minecraft
spring:
datasource:
driverClassName: org.postgresql.Driver
url: jdbc:postgresql://localhost:5432/db_minager
username: minager
password: P@ssword
jpa:
open-in-view: false
properties:
hibernate:
temp:
# Disable feature detection by this undocumented parameter.
# Check the org.hibernate.engine.jdbc.internal.JdbcServiceImpl.configure method for more details.
use_jdbc_metadata_defaults: false

View File

@@ -0,0 +1,14 @@
#*******&
#***************%
#***********************
***/*********************/*
*(************************# __ __ _
###*#*************$****#### | \/ (_)
#######/****/**$$$$$$$##### | \ / |_ _ __ __ _ __ _ ___ _ __
###########$$$$$$$$$$$$$$$$ | |\/| | | '_ \ / _` |/ _` |/ _ \ '__|
###########$$$$$$$$$$$$$$$$ | | | | | | | | (_| | (_| | __/ |
###########$$$$$$$$$$$$$$$$ |_| |_|_|_| |_|\__,_|\__, |\___|_|
############$$$$$$$$$$$$$$# __/ |
############$$$$$$$$$$$$$ |___/
#########$$$$$$$$$$$
######($$$$$$$

View File

@@ -3,7 +3,7 @@
"version": 1, "version": 1,
"newProjectRoot": "projects", "newProjectRoot": "projects",
"projects": { "projects": {
"ts": { "minager": {
"root": "", "root": "",
"sourceRoot": "src", "sourceRoot": "src",
"projectType": "application", "projectType": "application",
@@ -27,9 +27,12 @@
"src/assets" "src/assets"
], ],
"styles": [ "styles": [
"node_modules/font-awesome/scss/font-awesome.scss", "node_modules/@fortawesome/fontawesome-free/scss/fontawesome.scss",
"node_modules/angular-bootstrap-md/scss/bootstrap/bootstrap.scss", "node_modules/@fortawesome/fontawesome-free/scss/solid.scss",
"node_modules/angular-bootstrap-md/scss/mdb-free.scss", "node_modules/@fortawesome/fontawesome-free/scss/regular.scss",
"node_modules/@fortawesome/fontawesome-free/scss/brands.scss",
"node_modules/angular-bootstrap-md/assets/scss/bootstrap/bootstrap.scss",
"node_modules/angular-bootstrap-md/assets/scss/mdb.scss",
"src/styles.scss" "src/styles.scss"
], ],
"scripts": [ "scripts": [
@@ -77,18 +80,18 @@
"serve": { "serve": {
"builder": "@angular-devkit/build-angular:dev-server", "builder": "@angular-devkit/build-angular:dev-server",
"options": { "options": {
"browserTarget": "ts:build" "browserTarget": "minager:build"
}, },
"configurations": { "configurations": {
"production": { "production": {
"browserTarget": "ts:build:production" "browserTarget": "minager:build:production"
} }
} }
}, },
"extract-i18n": { "extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n", "builder": "@angular-devkit/build-angular:extract-i18n",
"options": { "options": {
"browserTarget": "ts:build" "browserTarget": "minager:build"
} }
}, },
"test": { "test": {
@@ -122,7 +125,7 @@
} }
} }
}, },
"ts-e2e": { "minager-e2e": {
"root": "e2e/", "root": "e2e/",
"projectType": "application", "projectType": "application",
"architect": { "architect": {
@@ -130,11 +133,11 @@
"builder": "@angular-devkit/build-angular:protractor", "builder": "@angular-devkit/build-angular:protractor",
"options": { "options": {
"protractorConfig": "e2e/protractor.conf.js", "protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "ts:serve" "devServerTarget": "minager:serve"
}, },
"configurations": { "configurations": {
"production": { "production": {
"devServerTarget": "ts:serve:production" "devServerTarget": "minager:serve:production"
} }
} }
}, },
@@ -150,5 +153,5 @@
} }
} }
}, },
"defaultProject": "ts" "defaultProject": "minager"
} }

View File

@@ -1,9 +1,9 @@
{ {
"name": "ts", "name": "ts",
"version": "0.0.0", "version": "0.0.1",
"scripts": { "scripts": {
"ng": "ng", "ng": "ng",
"start": "ng serve", "start": "ng serve --proxy-config proxy.conf.json",
"build": "ng build", "build": "ng build",
"test": "ng test", "test": "ng test",
"lint": "ng lint", "lint": "ng lint",
@@ -11,44 +11,44 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "^6.1.0", "@angular/animations": "^8.2.1",
"@angular/common": "^6.1.0", "@angular/common": "^8.2.1",
"@angular/compiler": "^6.1.0", "@angular/compiler": "^8.2.1",
"@angular/core": "^6.1.0", "@angular/core": "^8.2.1",
"@angular/forms": "^6.1.0", "@angular/forms": "^8.2.1",
"@angular/http": "^6.1.0", "@angular/http": "^7.2.15",
"@angular/platform-browser": "^6.1.0", "@angular/platform-browser": "^8.2.1",
"@angular/platform-browser-dynamic": "^6.1.0", "@angular/platform-browser-dynamic": "^8.2.1",
"@angular/router": "^6.1.0", "@angular/router": "^8.2.1",
"@types/chart.js": "^2.7.36", "@types/chart.js": "^2.7.56",
"angular-bootstrap-md": "^6.2.4", "@fortawesome/fontawesome-free": "^5.10.1",
"angular5-csv": "^0.2.10", "angular-bootstrap-md": "^8.1.1",
"chart.js": "^2.5.0", "chart.js": "^2.8.0",
"core-js": "^2.5.4", "core-js": "^3.1.4",
"font-awesome": "^4.7.0",
"hammerjs": "^2.0.8", "hammerjs": "^2.0.8",
"rxjs": "~6.2.0", "rxjs": "~6.5.2",
"zone.js": "~0.8.26" "tslib": "^1.10.0",
"zone.js": "~0.10.1"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~0.8.0", "@angular-devkit/build-angular": "~0.802.1",
"@angular/cli": "~6.2.3", "@angular/cli": "~8.2.1",
"@angular/compiler-cli": "^6.1.0", "@angular/compiler-cli": "^8.2.1",
"@angular/language-service": "^6.1.0", "@angular/language-service": "^8.2.1",
"@types/jasmine": "~2.8.8", "@types/jasmine": "~3.4.0",
"@types/jasminewd2": "~2.0.3", "@types/jasminewd2": "~2.0.6",
"@types/node": "~8.9.4", "@types/node": "~12.7.1",
"codelyzer": "~4.3.0", "codelyzer": "~5.1.0",
"jasmine-core": "~2.99.1", "jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1", "jasmine-spec-reporter": "~4.2.1",
"karma": "~3.0.0", "karma": "~4.2.0",
"karma-chrome-launcher": "~2.2.0", "karma-chrome-launcher": "~3.0.0",
"karma-coverage-istanbul-reporter": "~2.0.1", "karma-coverage-istanbul-reporter": "~2.1.0",
"karma-jasmine": "~1.1.2", "karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^0.2.2", "karma-jasmine-html-reporter": "^1.4.2",
"protractor": "~5.4.0", "protractor": "~5.4.2",
"ts-node": "~7.0.0", "ts-node": "~8.3.0",
"tslint": "~5.11.0", "tslint": "~5.18.0",
"typescript": "~2.9.2" "typescript": "~3.5.3"
} }
} }

View File

@@ -0,0 +1,6 @@
{
"/api": {
"target": "http://localhost:8080",
"secure": false
}
}

View File

@@ -1,4 +1,5 @@
<app-header></app-header> <app-header></app-header>
<app-notifications></app-notifications>
<div id="versionDiv" *ngIf="!loading && connectedToApi"> <div id="versionDiv" *ngIf="!loading && connectedToApi">
APP Version : {{appVersion}} - API Version : {{apiVersion}} APP Version : {{appVersion}} - API Version : {{apiVersion}}
</div> </div>
@@ -9,4 +10,4 @@
Veuillez contacter votre administrateur ou réessayer plus tard. Veuillez contacter votre administrateur ou réessayer plus tard.
</div> </div>
<h3 *ngIf="loading">Chargement...</h3> <h3 *ngIf="loading">Chargement...</h3>
</main> </main>

View File

@@ -20,6 +20,8 @@ import { HeaderComponent } from './header/header.component';
import { ServerComponent } from './server/server.component'; import { ServerComponent } from './server/server.component';
import { LoginComponent } from './login/login.component'; import { LoginComponent } from './login/login.component';
import { DisconnectionComponent } from './disconnection/disconnection.component'; import { DisconnectionComponent } from './disconnection/disconnection.component';
import { NotificationsComponent } from './core/notifications/notifications.component';
import { NotificationElement } from './core/notifications/notification-element/notification-element.component';
// ********************************************** // **********************************************
// App Services // App Services
@@ -40,7 +42,9 @@ import { TokenInterceptor } from './core/interceptors/token-interceptor';
HeaderComponent, HeaderComponent,
ServerComponent, ServerComponent,
LoginComponent, LoginComponent,
DisconnectionComponent DisconnectionComponent,
NotificationsComponent,
NotificationElement
], ],
imports: [ imports: [
BrowserModule, BrowserModule,

View File

@@ -0,0 +1,26 @@
/**
* Class which represents a notification class.
* It serves to set the notification appearence.
*/
export class NotificationClass {
/**
* Default constructor.
* @param {string} icon Class name of font-awsome icon.
* @param {string} clazz The class to set notification style.
*/
constructor(
public icon: string,
public clazz: string,
) {}
}
/**
* Constant instances of NotificationClass.
*/
export const NotificationClasses = Object.freeze({
'Error': new NotificationClass('exclamation-circle ', 'alert-danger'),
'Warn': new NotificationClass('exclamation-triangle', 'alert-warning'),
'Info': new NotificationClass('info-circle', 'alert-info'),
'Success': new NotificationClass('check-circle', 'alert-success')
});

View File

@@ -0,0 +1,7 @@
<div id="notification" #notification class="alert {{model.notificationClass.clazz}}" role="alert">
<mdb-icon fas [icon]="model.notificationClass.icon"></mdb-icon> {{model.content}}
<span id="close">
<i class="fa fa-times-circle fas close"
(click)="model.hide()"></i>
</span>
</div>

View File

@@ -0,0 +1,78 @@
import { NotificationClass } from './../notification-class';
import { Component, Input, OnInit, ViewChild, ElementRef } from '@angular/core';
/**
* Class which represents a notification in the notifications list.
*/
@Component({
selector: 'app-notification-element',
templateUrl: 'notification-element.component.html',
styles: [`
#notification {
transition: all 0.7s ease-out;
position: relative;
}
.close {
position: absolute;
right: 7px;
top: 12px;
font-size: 19px;
opacity: 0;
}
#notification:hover .close {
opacity: 0.5;
}
`]
})
export class NotificationElement implements OnInit {
/**
* The notification model.
*/
@Input() model: NotificationModel;
/**
* The notification DOM element.
*/
@ViewChild('notification', {static: true}) notification: ElementRef;
/**
* Sets the DOM element in the model object and plays with opacity.
*/
ngOnInit(): void {
this.model.notification = this.notification;
this.notification.nativeElement.style.opacity = 0;
setTimeout(() => {
this.notification.nativeElement.style.opacity = 1;
}, 100);
}
}
/**
* Class which represents the notification model.
*/
export class NotificationModel {
/**
* Element which represents the DOM element of the notification element.
*/
notification: ElementRef;
/**
* Default constructor.
* @param {string} content The message of the notification.
* @param {NotificationClass} notificationClass The category of the notification (info, error...).
*/
constructor(
public content: string,
public notificationClass: NotificationClass
) {}
/**
* Hides the notification DOM element.
*/
public hide(): void {
this.notification.nativeElement.style.opacity = 0;
setTimeout(() => {
this.notification.nativeElement.style.display = 'none';
}, 800);
}
}

View File

@@ -0,0 +1,5 @@
<div id="notification-container">
<app-notification-element *ngFor="let notification of notificationList"
[model]="notification"></app-notification-element>
</div>

View File

@@ -0,0 +1,108 @@
import { NotificationClass, NotificationClasses } from './notification-class';
import { NotificationModel } from './notification-element/notification-element.component';
import { Component, OnInit } from '@angular/core';
/**
* Class which offers the notifications service.
*/
@Component({
selector: 'app-notifications',
templateUrl: 'notifications.component.html',
styles: [`
#notification-container {
position: fixed;
top: 50px;
right: 20px;
width: 300px;
z-index: 1100;
}
`]
})
export class NotificationsComponent implements OnInit {
/**
* Singleton of the notification service.
*/
private static component: NotificationsComponent;
/**
* List of notifications model.
*/
notificationList: Array<NotificationModel> = [];
/**
* Creates an error notification.
* @param {string} message The content of the notification.
*/
public static error(message: string): void {
NotificationsComponent.notif(message, NotificationClasses.Error);
}
/**
* Creates a warning notification.
* @param {string} message The content of the notification.
*/
public static warn(message: string): void {
NotificationsComponent.notif(message, NotificationClasses.Warn);
}
/**
* Creates an info notification.
* @param {string} message The content of the notification.
*/
public static info(message: string): void {
NotificationsComponent.notif(message, NotificationClasses.Info);
}
/**
* Creates a success notification.
* @param {string} message The content of the notification.
*/
public static success(message: string): void {
NotificationsComponent.notif(message, NotificationClasses.Success);
}
/**
* Create a notification. The {@code notifClass} param defines the category of
* the notification (info, error...).
* @param {string} message The content of the notification.
* @param {NotificationClass} notifClass The category of the notification.
*/
private static notif(message: string, notifClass: NotificationClass): void {
const elem = new NotificationModel(message, notifClass);
NotificationsComponent.component.notificationList.push(elem);
setTimeout(() => {
elem.hide();
setTimeout(() => {
NotificationsComponent.clearNotificationList();
}, 900);
}, 4500);
}
/**
* Clears the consumed notifications in the list.
* When a notification is created, a cooldown is set to hide it after a certain time period.
* In this cooldown, the notification have only its display as {@code none}, but the
* notification isn't remove from the list. This method removes it.
*/
private static clearNotificationList(): void {
NotificationsComponent.component.notificationList.forEach(elem => {
if (elem.notification.nativeElement.style.display === 'none') {
const index = NotificationsComponent.component.notificationList.indexOf(elem);
if (index > -1) {
NotificationsComponent.component.notificationList.splice(index, 1);
}
}
});
}
/**
* Set the reference of the singleton here because this component
* is created at the application startup.
*/
ngOnInit(): void {
NotificationsComponent.component = this;
}
}

View File

@@ -7,19 +7,22 @@
</a> </a>
</logo> </logo>
<links> <links>
<form class="form-inline waves-light waves-light ml-auto" mdbWavesEffect> <form class="form-inline waves-light waves-light ml-auto">
<a routerLink="/login" <a routerLink="/login"
*ngIf="!isAuthenticated()" *ngIf="!isAuthenticated()"
class="nav-link waves-light" class="btn waves-effect waves-light"
mdbRippleRadius> mdbWavesEffect>
<i class="fa fa-sign-in"></i> Connexion <i class="fa fa-sign-in-alt"></i> Connexion
</a> </a>
<a routerLink="/disconnection" <a routerLink="/disconnection"
*ngIf="isAuthenticated()" *ngIf="isAuthenticated()"
class="nav-link waves-light danger-color-dark" id="sign-out"
mdbRippleRadius > class="btn waves-effect waves-light"
<i class="fa fa-sign-out"></i> Déconnexion mdbTooltip="Déconnexion"
placement="bottom"
mdbWavesEffect>
<i class="fa fa-sign-out-alt fa-sm"></i> Déconnexion
</a> </a>
</form> </form>
</links> </links>
</mdb-navbar> </mdb-navbar>

View File

@@ -10,10 +10,13 @@ import { environment } from '../../environments/environment';
width: 50px; width: 50px;
height: 50px; height: 50px;
} }
a, a:visited { a, a:visited {
color: white; color: white;
} }
#sign-out:hover {
color: white;
background-color: #f44336 !important;
}
`] `]
}) })
export class HeaderComponent { export class HeaderComponent {

View File

@@ -2,9 +2,9 @@
<div class="card-body"> <div class="card-body">
<h4 class="card-title">Connexion</h4> <h4 class="card-title">Connexion</h4>
<form id="form" (ngSubmit)="submitLogin()" #loginForm="ngForm"> <form id="form" (ngSubmit)="submitLogin()" #loginForm="ngForm">
<div class="md-form"> <div class="md-form">
<i class="fa fa-envelope prefix grey-text"></i> <i class="fa fa-envelope prefix grey-text"></i>
<input mdbActive <input mdbInputDirective
id="email" id="email"
name="email" name="email"
type="email" type="email"
@@ -12,13 +12,13 @@
[(ngModel)]="model.email" [(ngModel)]="model.email"
#email="ngModel" #email="ngModel"
data-error="Veuillez saisir une adresse email valide" data-error="Veuillez saisir une adresse email valide"
data-sucess="" [validateSuccess]="false"
required /> required />
<label for="email">Email</label> <label for="email">Email</label>
</div> </div>
<div class="md-form"> <div class="md-form">
<i class="fa fa-lock prefix grey-text"></i> <i class="fa fa-lock prefix grey-text"></i>
<input mdbActive <input mdbInputDirective
id="password" id="password"
name="password" name="password"
type="password" type="password"
@@ -26,17 +26,12 @@
[(ngModel)]="model.password" [(ngModel)]="model.password"
#password="ngModel" #password="ngModel"
data-error="Veuillez saisir votre mot de passe" data-error="Veuillez saisir votre mot de passe"
data-sucess="" [validateSuccess]="false"
required /> required />
<label for="password">Password</label> <label for="password">Mot de passe</label>
</div> </div>
<div id="errorMsg" class="card red lighten-2 text-center z-depth-2">
<div class="card-body">
<p class="white-text mb-0">{{loginError}}</p>
</div>
</div>
<div class="col submitFormArea"> <div class="col submitFormArea">
<button class="float-right waves-effect waves-light indigo btn" <button class="float-right waves-effect waves-light indigo white-text btn"
type="submit" type="submit"
[disabled]="!loginForm.form.valid"> [disabled]="!loginForm.form.valid">
Suivant Suivant
@@ -44,4 +39,4 @@
</div> </div>
</form> </form>
</div> </div>
</div> </div>

View File

@@ -1,8 +1,9 @@
import { Component } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router'; import { Router } from '@angular/router';
import { User } from '../core/entities'; import { User } from '../core/entities';
import { LoginService } from './login.service'; import { LoginService } from './login.service';
import { AuthService } from '../core/services/auth.service'; import { AuthService } from '../core/services/auth.service';
import { NotificationsComponent } from '../core/notifications/notifications.component';
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
@@ -24,37 +25,34 @@ import { AuthService } from '../core/services/auth.service';
} }
`] `]
}) })
export class LoginComponent { export class LoginComponent implements OnInit {
model: User = new User('', '', '', '', undefined, ''); model: User = new User('', '', '', '', undefined, '');
loginError; loginError;
constructor( constructor(
private loginService: LoginService, private loginService: LoginService,
private authService: AuthService, private authService: AuthService,
private router: Router private router: Router,
) {} ) {}
ngOnInit(): void {
if (this.authService.isAuthenticated()) {
this.navigateToServerPage();
}
}
submitLogin(): void { submitLogin(): void {
this.loginService.login(this.model).subscribe(user => { this.loginService.login(this.model).subscribe(user => {
this.authService.setToken(user.token); this.authService.setToken(user.token);
this.authService.setUser(user); this.authService.setUser(user);
this.router.navigate(['/server']); this.navigateToServerPage();
}, error => { }, error => {
this.setMessage('Email ou password incorrect.'); console.error(error);
NotificationsComponent.error('Email ou password incorrect.');
}); });
} }
setMessage(message: string): void { private navigateToServerPage(): void {
this.loginError = message; this.router.navigate(['/server']);
const resultMsgDiv = document.getElementById('errorMsg');
resultMsgDiv.style.maxHeight = '64px';
setTimeout(() => {
resultMsgDiv.style.maxHeight = '0px';
setTimeout(() => {
this.loginError = undefined;
}, 550);
}, 3000);
} }
} }

View File

@@ -5,13 +5,12 @@
<h1 class="card-title">Serveur Minecraft</h1> <h1 class="card-title">Serveur Minecraft</h1>
<div> <div>
Status du serveur : Status du serveur :
<span *ngIf="!serverStartedChecked" class="badge badge-warning"> <mdb-badge *ngIf="!serverStartedChecked" color="amber darken-2">
Vérification Vérification
</span> </mdb-badge>
<span *ngIf="serverStartedChecked" class="badge" <mdb-badge *ngIf="serverStartedChecked" [ngClass]="serverStarted ? 'green' : 'red'">
[ngClass]="serverStarted ? 'badge-success' : 'badge-danger'">
{{serverStarted ? 'Démarré' : 'Éteint'}} {{serverStarted ? 'Démarré' : 'Éteint'}}
</span> </mdb-badge>
</div> </div>
<div> <div>
Adresse du serveur de jeu : Adresse du serveur de jeu :
@@ -26,44 +25,24 @@
Copié ! Copié !
</span> </span>
</div> </div>
<div style="text-align:center; margin-top: 15px;" *ngIf="isAuthenticated()"> <div id="action-btn-div" *ngIf="isAuthenticated()">
<button mdbBtn <button class="waves-effect waves-light indigo white-text btn"
*ngIf="serverStarted"
type="button" type="button"
class="waves-light indigo btn-rounded"
[disabled]="restarting"
(click)="restartServer()" (click)="restartServer()"
[disabled]="restarting || !serverStarted"
mdbWavesEffect> mdbWavesEffect>
<i class="fa fa-refresh"></i>&nbsp; Redémarrer
Redémarrer
</button> </button>
<button mdbBtn <button class="waves-effect waves-light white-text btn"
type="button" type="button"
class="waves-light btn-rounded"
[ngClass]="serverStarted ? 'red' : 'green'" [ngClass]="serverStarted ? 'red' : 'green'"
[disabled]="restarting"
(click)="startOrStopServer()" (click)="startOrStopServer()"
[disabled]="restarting"
mdbWavesEffect> mdbWavesEffect>
<i class="fa" [ngClass]="serverStarted ? 'fa-stop-circle' : 'fa-play-circle'"></i>&nbsp;
{{serverStarted ? 'Éteindre' : 'Démarrer'}} {{serverStarted ? 'Éteindre' : 'Démarrer'}}
</button> </button>
<div id="errorMsg" class="msg card red lighten-2 text-center z-depth-2">
<div class="card-body">
<p class="white-text mb-0">{{errorMsg}}</p>
</div>
</div>
<div id="warnMsg" class="msg card orange lighten-2 text-center z-depth-2">
<div class="card-body">
<p class="white-text mb-0">{{warnMsg}}</p>
</div>
</div>
<div id="successMsg" class="msg card green lighten-2 text-center z-depth-2">
<div class="card-body">
<p class="white-text mb-0">{{successMsg}}</p>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -1,6 +1,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ServerService } from './server.service'; import { ServerService } from './server.service';
import { AuthService } from '../core/services/auth.service'; import { AuthService } from '../core/services/auth.service';
import { NotificationsComponent } from '../core/notifications/notifications.component';
@Component({ @Component({
selector: 'app-server', selector: 'app-server',
@@ -16,15 +17,19 @@ import { AuthService } from '../core/services/auth.service';
margin-top: 25px; margin-top: 25px;
cursor: pointer; cursor: pointer;
} }
#action-btn-div {
text-align:center;
margin-top: 15px;
}
#action-btn-div button {
margin-right: 15px;
}
`] `]
}) })
export class ServerComponent implements OnInit { export class ServerComponent implements OnInit {
serverAddress = '176.188.217.1:54311'; serverAddress = '176.188.217.1:54311';
serverStartedChecked = false; serverStartedChecked = false;
serverStarted = false; serverStarted = false;
errorMsg;
warnMsg;
successMsg;
restarting = false; restarting = false;
constructor( constructor(
@@ -35,7 +40,7 @@ export class ServerComponent implements OnInit {
ngOnInit(): void { ngOnInit(): void {
this.serverService.getStatus().subscribe(pServerStatus => { this.serverService.getStatus().subscribe(pServerStatus => {
this.serverStartedChecked = true; this.serverStartedChecked = true;
this.serverStarted = pServerStatus === 1; this.serverStarted = pServerStatus === 0;
}); });
} }
@@ -47,10 +52,10 @@ export class ServerComponent implements OnInit {
this.restarting = true; this.restarting = true;
this.serverService.restartServer().subscribe(() => { this.serverService.restartServer().subscribe(() => {
this.setMessage('Serveur redémarré.', 'successMsg'); NotificationsComponent.success('Serveur redémarré.');
}, error => { }, error => {
this.setMessage('Une erreur est survenue lors du redémarrage du serveur.', console.error(error);
'errorMsg'); NotificationsComponent.error('Une erreur est survenue lors du redémarrage du serveur.');
}, () => { }, () => {
this.restarting = false; this.restarting = false;
}); });
@@ -58,36 +63,18 @@ export class ServerComponent implements OnInit {
startOrStopServer(): void { startOrStopServer(): void {
this.serverService[(this.serverStarted ? 'stop' : 'start') + 'Server']().subscribe(() => { this.serverService[(this.serverStarted ? 'stop' : 'start') + 'Server']().subscribe(() => {
this.setMessage('Serveur ' + (this.serverStarted ? 'éteint' : 'démarré') + '.', 'successMsg'); NotificationsComponent.success(`Serveur ${this.serverStarted ? 'éteint' : 'démarré'}.`);
this.serverStarted = !this.serverStarted; this.serverStarted = !this.serverStarted;
}, error => { }, error => {
if (error.status === 409) { if (error.status === 409) {
this.setMessage('Le serveur est déjà ' NotificationsComponent.warn(`Le serveur est déjà ${this.serverStarted ? 'éteint' : 'démarré'}.`);
+ (this.serverStarted ? 'éteint' : 'démarré') + '.',
'warnMsg');
} else { } else {
this.setMessage('Une erreur est survenue lors ' NotificationsComponent.error(`Une erreur est survenue lors ${this.serverStarted
+ (this.serverStarted ? 'de l\'extinction' : 'du démarrage') ? 'de l\'extinction' : 'du démarrage'} du serveur.`);
+ 'du serveur.',
'errorMsg');
} }
}); });
} }
setMessage(message: string, type: string): void {
this[type] = message;
const resultMsgDiv = document.getElementById(type);
resultMsgDiv.style.maxHeight = '64px';
setTimeout(() => {
resultMsgDiv.style.maxHeight = '0px';
setTimeout(() => {
this[type] = undefined;
}, 550);
}, 3000);
}
copyToClipBoard(): void { copyToClipBoard(): void {
document.addEventListener('copy', (e: ClipboardEvent) => { document.addEventListener('copy', (e: ClipboardEvent) => {
e.clipboardData.setData('text/plain', (this.serverAddress)); e.clipboardData.setData('text/plain', (this.serverAddress));

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 MiB

View File

@@ -4,7 +4,7 @@
export const environment = { export const environment = {
production: false, production: false,
appVersion: '1.0.1', appVersion: '1.2.0',
title: 'LOCAL' title: 'LOCAL'
}; };

View File

@@ -43,7 +43,7 @@
/** Evergreen browsers require these. **/ /** Evergreen browsers require these. **/
// Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove. // Used for reflect-metadata in JIT. If you use AOT (and only Angular decorators), you can remove.
import 'core-js/es7/reflect'; // import 'core-js/es7/reflect';
/** /**

View File

@@ -12,7 +12,7 @@ body {
flex-direction: column; flex-direction: column;
justify-content:space-between; justify-content:space-between;
min-height: 100%; min-height: 100%;
background-image: url("./assets/images/background.png"); background-image: url("./assets/images/background.jpg");
background-color: #fff; background-color: #fff;
background-position: center; background-position: center;
background-repeat: no-repeat; background-repeat: no-repeat;
@@ -21,4 +21,4 @@ body {
.btn { .btn {
border-radius: 10em; border-radius: 10em;
} }