Initial application generated by JHipster-5.8.2
This commit is contained in:
61
src/main/webapp/404.html
Normal file
61
src/main/webapp/404.html
Normal file
@ -0,0 +1,61 @@
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Page Not Found</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="shortcut icon" href="favicon.ico" />
|
||||
<style>
|
||||
|
||||
* {
|
||||
line-height: 1.2;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
color: #888;
|
||||
display: table;
|
||||
font-family: sans-serif;
|
||||
height: 100%;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
display: table-cell;
|
||||
vertical-align: middle;
|
||||
margin: 2em auto;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #555;
|
||||
font-size: 2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0 auto;
|
||||
width: 280px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 280px) {
|
||||
|
||||
body, p {
|
||||
width: 95%;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 1.5em;
|
||||
margin: 0 0 0.3em;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Page Not Found</h1>
|
||||
<p>Sorry, but the page you were trying to view does not exist.</p>
|
||||
</body>
|
||||
</html>
|
||||
<!-- IE needs 512+ bytes: http://blogs.msdn.com/b/ieinternals/archive/2010/08/19/http-error-pages-in-internet-explorer.aspx -->
|
30
src/main/webapp/app/account/account.module.ts
Normal file
30
src/main/webapp/app/account/account.module.ts
Normal file
@ -0,0 +1,30 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HsadminNgSharedModule } from 'app/shared';
|
||||
|
||||
import {
|
||||
PasswordStrengthBarComponent,
|
||||
RegisterComponent,
|
||||
ActivateComponent,
|
||||
PasswordComponent,
|
||||
PasswordResetInitComponent,
|
||||
PasswordResetFinishComponent,
|
||||
SettingsComponent,
|
||||
accountState
|
||||
} from './';
|
||||
|
||||
@NgModule({
|
||||
imports: [HsadminNgSharedModule, RouterModule.forChild(accountState)],
|
||||
declarations: [
|
||||
ActivateComponent,
|
||||
RegisterComponent,
|
||||
PasswordComponent,
|
||||
PasswordStrengthBarComponent,
|
||||
PasswordResetInitComponent,
|
||||
PasswordResetFinishComponent,
|
||||
SettingsComponent
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HsadminNgAccountModule {}
|
12
src/main/webapp/app/account/account.route.ts
Normal file
12
src/main/webapp/app/account/account.route.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
import { activateRoute, passwordRoute, passwordResetFinishRoute, passwordResetInitRoute, registerRoute, settingsRoute } from './';
|
||||
|
||||
const ACCOUNT_ROUTES = [activateRoute, passwordRoute, passwordResetFinishRoute, passwordResetInitRoute, registerRoute, settingsRoute];
|
||||
|
||||
export const accountState: Routes = [
|
||||
{
|
||||
path: '',
|
||||
children: ACCOUNT_ROUTES
|
||||
}
|
||||
];
|
17
src/main/webapp/app/account/activate/activate.component.html
Normal file
17
src/main/webapp/app/account/activate/activate.component.html
Normal file
@ -0,0 +1,17 @@
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h1 jhiTranslate="activate.title">Activation</h1>
|
||||
|
||||
<div class="alert alert-success" *ngIf="success">
|
||||
<span jhiTranslate="activate.messages.success"><strong>Your user account has been activated.</strong> Please </span>
|
||||
<a class="alert-link" (click)="login()" jhiTranslate="global.messages.info.authenticated.link">sign in</a>.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="error" jhiTranslate="activate.messages.error">
|
||||
<strong>Your user could not be activated.</strong> Please use the registration form to sign up.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
37
src/main/webapp/app/account/activate/activate.component.ts
Normal file
37
src/main/webapp/app/account/activate/activate.component.ts
Normal file
@ -0,0 +1,37 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { LoginModalService } from 'app/core';
|
||||
import { ActivateService } from './activate.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-activate',
|
||||
templateUrl: './activate.component.html'
|
||||
})
|
||||
export class ActivateComponent implements OnInit {
|
||||
error: string;
|
||||
success: string;
|
||||
modalRef: NgbModalRef;
|
||||
|
||||
constructor(private activateService: ActivateService, private loginModalService: LoginModalService, private route: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.queryParams.subscribe(params => {
|
||||
this.activateService.get(params['key']).subscribe(
|
||||
() => {
|
||||
this.error = null;
|
||||
this.success = 'OK';
|
||||
},
|
||||
() => {
|
||||
this.success = null;
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
login() {
|
||||
this.modalRef = this.loginModalService.open();
|
||||
}
|
||||
}
|
12
src/main/webapp/app/account/activate/activate.route.ts
Normal file
12
src/main/webapp/app/account/activate/activate.route.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { ActivateComponent } from './activate.component';
|
||||
|
||||
export const activateRoute: Route = {
|
||||
path: 'activate',
|
||||
component: ActivateComponent,
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'activate.title'
|
||||
}
|
||||
};
|
16
src/main/webapp/app/account/activate/activate.service.ts
Normal file
16
src/main/webapp/app/account/activate/activate.service.ts
Normal file
@ -0,0 +1,16 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class ActivateService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
get(key: string): Observable<any> {
|
||||
return this.http.get(SERVER_API_URL + 'api/activate', {
|
||||
params: new HttpParams().set('key', key)
|
||||
});
|
||||
}
|
||||
}
|
19
src/main/webapp/app/account/index.ts
Normal file
19
src/main/webapp/app/account/index.ts
Normal file
@ -0,0 +1,19 @@
|
||||
export * from './activate/activate.component';
|
||||
export * from './activate/activate.service';
|
||||
export * from './activate/activate.route';
|
||||
export * from './password/password.component';
|
||||
export * from './password/password-strength-bar.component';
|
||||
export * from './password/password.service';
|
||||
export * from './password/password.route';
|
||||
export * from './password-reset/finish/password-reset-finish.component';
|
||||
export * from './password-reset/finish/password-reset-finish.service';
|
||||
export * from './password-reset/finish/password-reset-finish.route';
|
||||
export * from './password-reset/init/password-reset-init.component';
|
||||
export * from './password-reset/init/password-reset-init.service';
|
||||
export * from './password-reset/init/password-reset-init.route';
|
||||
export * from './register/register.component';
|
||||
export * from './register/register.service';
|
||||
export * from './register/register.route';
|
||||
export * from './settings/settings.component';
|
||||
export * from './settings/settings.route';
|
||||
export * from './account.route';
|
@ -0,0 +1,77 @@
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-4">
|
||||
<h1 jhiTranslate="reset.finish.title">Reset password</h1>
|
||||
|
||||
<div class="alert alert-danger" jhiTranslate="reset.finish.messages.keymissing" *ngIf="keyMissing">
|
||||
<strong>The password reset key is missing.</strong>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" *ngIf="!success && !keyMissing">
|
||||
<p jhiTranslate="reset.finish.messages.info">Choose a new password</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="error">
|
||||
<p jhiTranslate="reset.finish.messages.error">Your password couldn't be reset. Remember a password request is only valid for 24 hours.</p>
|
||||
</div>
|
||||
|
||||
<p class="alert alert-success" *ngIf="success">
|
||||
<span jhiTranslate="reset.finish.messages.success"><strong>Your password has been reset.</strong> Please </span>
|
||||
<a class="alert-link" (click)="login()" jhiTranslate="global.messages.info.authenticated.link">sign in</a>.
|
||||
</p>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch">
|
||||
The password and its confirmation do not match!
|
||||
</div>
|
||||
|
||||
<div *ngIf="!keyMissing">
|
||||
<form *ngIf="!success" name="form" role="form" (ngSubmit)="finishReset()" #passwordForm="ngForm">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="password" jhiTranslate="global.form.newpassword">New password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" #passwordInput="ngModel"
|
||||
placeholder="{{'global.form.newpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="resetAccount.password" minlength=4 maxlength=50 required>
|
||||
<div *ngIf="passwordInput.dirty && passwordInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="passwordInput.errors.required" jhiTranslate="global.messages.validate.newpassword.required">
|
||||
Your password is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="passwordInput.errors.minlength" jhiTranslate="global.messages.validate.newpassword.minlength">
|
||||
Your password is required to be at least 4 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="passwordInput.errors.maxlength" jhiTranslate="global.messages.validate.newpassword.maxlength">
|
||||
Your password cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
<jhi-password-strength-bar [passwordToCheck]="resetAccount.password"></jhi-password-strength-bar>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="confirmPassword" jhiTranslate="global.form.confirmpassword">New password confirmation</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" #confirmPasswordInput="ngModel"
|
||||
placeholder="{{'global.form.confirmpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="confirmPassword" minlength=4 maxlength=50 required>
|
||||
<div *ngIf="confirmPasswordInput.dirty && confirmPasswordInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="confirmPasswordInput.errors.required" jhiTranslate="global.messages.validate.confirmpassword.required">
|
||||
Your password confirmation is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="confirmPasswordInput.errors.minlength" jhiTranslate="global.messages.validate.confirmpassword.minlength">
|
||||
Your password confirmation is required to be at least 4 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="confirmPasswordInput.errors.maxlength" jhiTranslate="global.messages.validate.confirmpassword.maxlength">
|
||||
Your password confirmation cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" [disabled]="passwordForm.form.invalid" class="btn btn-primary" jhiTranslate="reset.finish.form.button">Reset Password</button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,65 @@
|
||||
import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core';
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { LoginModalService } from 'app/core';
|
||||
import { PasswordResetFinishService } from './password-reset-finish.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-password-reset-finish',
|
||||
templateUrl: './password-reset-finish.component.html'
|
||||
})
|
||||
export class PasswordResetFinishComponent implements OnInit, AfterViewInit {
|
||||
confirmPassword: string;
|
||||
doNotMatch: string;
|
||||
error: string;
|
||||
keyMissing: boolean;
|
||||
resetAccount: any;
|
||||
success: string;
|
||||
modalRef: NgbModalRef;
|
||||
key: string;
|
||||
|
||||
constructor(
|
||||
private passwordResetFinishService: PasswordResetFinishService,
|
||||
private loginModalService: LoginModalService,
|
||||
private route: ActivatedRoute,
|
||||
private elementRef: ElementRef,
|
||||
private renderer: Renderer
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.queryParams.subscribe(params => {
|
||||
this.key = params['key'];
|
||||
});
|
||||
this.resetAccount = {};
|
||||
this.keyMissing = !this.key;
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
if (this.elementRef.nativeElement.querySelector('#password') != null) {
|
||||
this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#password'), 'focus', []);
|
||||
}
|
||||
}
|
||||
|
||||
finishReset() {
|
||||
this.doNotMatch = null;
|
||||
this.error = null;
|
||||
if (this.resetAccount.password !== this.confirmPassword) {
|
||||
this.doNotMatch = 'ERROR';
|
||||
} else {
|
||||
this.passwordResetFinishService.save({ key: this.key, newPassword: this.resetAccount.password }).subscribe(
|
||||
() => {
|
||||
this.success = 'OK';
|
||||
},
|
||||
() => {
|
||||
this.success = null;
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
login() {
|
||||
this.modalRef = this.loginModalService.open();
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { PasswordResetFinishComponent } from './password-reset-finish.component';
|
||||
|
||||
export const passwordResetFinishRoute: Route = {
|
||||
path: 'reset/finish',
|
||||
component: PasswordResetFinishComponent,
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'global.menu.account.password'
|
||||
}
|
||||
};
|
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PasswordResetFinishService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
save(keyAndPassword: any): Observable<any> {
|
||||
return this.http.post(SERVER_API_URL + 'api/account/reset-password/finish', keyAndPassword);
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h1 jhiTranslate="reset.request.title">Reset your password</h1>
|
||||
|
||||
<div class="alert alert-danger" jhiTranslate="reset.request.messages.notfound" *ngIf="errorEmailNotExists">
|
||||
<strong>Email address isn't registered!</strong> Please check and try again.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" *ngIf="!success">
|
||||
<p jhiTranslate="reset.request.messages.info">Enter the email address you used to register.</p>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" *ngIf="success === 'OK'">
|
||||
<p jhiTranslate="reset.request.messages.success">Check your emails for details on how to reset your password.</p>
|
||||
</div>
|
||||
|
||||
<form *ngIf="!success" name="form" role="form" (ngSubmit)="requestReset()" #resetRequestForm="ngForm">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="email" jhiTranslate="global.form.email">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="{{'global.form.email.placeholder' | translate}}"
|
||||
[(ngModel)]="resetAccount.email" minlength=5 maxlength=254 #emailInput="ngModel" email required>
|
||||
<div *ngIf="emailInput.dirty && emailInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.required" jhiTranslate="global.messages.validate.email.required">
|
||||
Your email is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.email" jhiTranslate="global.messages.validate.email.invalid">
|
||||
Your email is invalid.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.minlength" jhiTranslate="global.messages.validate.email.minlength">
|
||||
Your email is required to be at least 5 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.maxlength" jhiTranslate="global.messages.validate.email.maxlength">
|
||||
Your email cannot be longer than 100 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<button type="submit" [disabled]="resetRequestForm.form.invalid" class="btn btn-primary" jhiTranslate="reset.request.form.button">Reset</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,43 @@
|
||||
import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core';
|
||||
import { EMAIL_NOT_FOUND_TYPE } from 'app/shared';
|
||||
import { PasswordResetInitService } from './password-reset-init.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-password-reset-init',
|
||||
templateUrl: './password-reset-init.component.html'
|
||||
})
|
||||
export class PasswordResetInitComponent implements OnInit, AfterViewInit {
|
||||
error: string;
|
||||
errorEmailNotExists: string;
|
||||
resetAccount: any;
|
||||
success: string;
|
||||
|
||||
constructor(private passwordResetInitService: PasswordResetInitService, private elementRef: ElementRef, private renderer: Renderer) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.resetAccount = {};
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#email'), 'focus', []);
|
||||
}
|
||||
|
||||
requestReset() {
|
||||
this.error = null;
|
||||
this.errorEmailNotExists = null;
|
||||
|
||||
this.passwordResetInitService.save(this.resetAccount.email).subscribe(
|
||||
() => {
|
||||
this.success = 'OK';
|
||||
},
|
||||
response => {
|
||||
this.success = null;
|
||||
if (response.status === 400 && response.error.type === EMAIL_NOT_FOUND_TYPE) {
|
||||
this.errorEmailNotExists = 'ERROR';
|
||||
} else {
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { PasswordResetInitComponent } from './password-reset-init.component';
|
||||
|
||||
export const passwordResetInitRoute: Route = {
|
||||
path: 'reset/request',
|
||||
component: PasswordResetInitComponent,
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'global.menu.account.password'
|
||||
}
|
||||
};
|
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PasswordResetInitService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
save(mail: string): Observable<any> {
|
||||
return this.http.post(SERVER_API_URL + 'api/account/reset-password/init', mail);
|
||||
}
|
||||
}
|
@ -0,0 +1,85 @@
|
||||
import { Component, ElementRef, Input, Renderer } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-password-strength-bar',
|
||||
template: `
|
||||
<div id="strength">
|
||||
<small jhiTranslate="global.messages.validate.newpassword.strength">Password strength:</small>
|
||||
<ul id="strengthBar">
|
||||
<li class="point"></li>
|
||||
<li class="point"></li>
|
||||
<li class="point"></li>
|
||||
<li class="point"></li>
|
||||
<li class="point"></li>
|
||||
</ul>
|
||||
</div>
|
||||
`,
|
||||
styleUrls: ['password-strength-bar.css']
|
||||
})
|
||||
export class PasswordStrengthBarComponent {
|
||||
colors = ['#F00', '#F90', '#FF0', '#9F0', '#0F0'];
|
||||
|
||||
constructor(private renderer: Renderer, private elementRef: ElementRef) {}
|
||||
|
||||
measureStrength(p: string): number {
|
||||
let force = 0;
|
||||
const regex = /[$-/:-?{-~!"^_`\[\]]/g; // "
|
||||
const lowerLetters = /[a-z]+/.test(p);
|
||||
const upperLetters = /[A-Z]+/.test(p);
|
||||
const numbers = /[0-9]+/.test(p);
|
||||
const symbols = regex.test(p);
|
||||
|
||||
const flags = [lowerLetters, upperLetters, numbers, symbols];
|
||||
const passedMatches = flags.filter((isMatchedFlag: boolean) => {
|
||||
return isMatchedFlag === true;
|
||||
}).length;
|
||||
|
||||
force += 2 * p.length + (p.length >= 10 ? 1 : 0);
|
||||
force += passedMatches * 10;
|
||||
|
||||
// penalty (short password)
|
||||
force = p.length <= 6 ? Math.min(force, 10) : force;
|
||||
|
||||
// penalty (poor variety of characters)
|
||||
force = passedMatches === 1 ? Math.min(force, 10) : force;
|
||||
force = passedMatches === 2 ? Math.min(force, 20) : force;
|
||||
force = passedMatches === 3 ? Math.min(force, 40) : force;
|
||||
|
||||
return force;
|
||||
}
|
||||
|
||||
getColor(s: number): any {
|
||||
let idx = 0;
|
||||
if (s <= 10) {
|
||||
idx = 0;
|
||||
} else if (s <= 20) {
|
||||
idx = 1;
|
||||
} else if (s <= 30) {
|
||||
idx = 2;
|
||||
} else if (s <= 40) {
|
||||
idx = 3;
|
||||
} else {
|
||||
idx = 4;
|
||||
}
|
||||
return { idx: idx + 1, col: this.colors[idx] };
|
||||
}
|
||||
|
||||
@Input()
|
||||
set passwordToCheck(password: string) {
|
||||
if (password) {
|
||||
const c = this.getColor(this.measureStrength(password));
|
||||
const element = this.elementRef.nativeElement;
|
||||
if (element.className) {
|
||||
this.renderer.setElementClass(element, element.className, false);
|
||||
}
|
||||
const lis = element.getElementsByTagName('li');
|
||||
for (let i = 0; i < lis.length; i++) {
|
||||
if (i < c.idx) {
|
||||
this.renderer.setElementStyle(lis[i], 'backgroundColor', c.col);
|
||||
} else {
|
||||
this.renderer.setElementStyle(lis[i], 'backgroundColor', '#DDD');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,24 @@
|
||||
/* ==========================================================================
|
||||
start Password strength bar style
|
||||
========================================================================== */
|
||||
ul#strengthBar {
|
||||
display: inline;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
margin-left: 15px;
|
||||
padding: 0;
|
||||
vertical-align: 2px;
|
||||
}
|
||||
|
||||
.point {
|
||||
background: #ddd;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
height: 5px;
|
||||
margin-right: 1px;
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.point:last-child {
|
||||
margin: 0 !important;
|
||||
}
|
77
src/main/webapp/app/account/password/password.component.html
Normal file
77
src/main/webapp/app/account/password/password.component.html
Normal file
@ -0,0 +1,77 @@
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h2 jhiTranslate="password.title" [translateValues]="{username: account.login}" *ngIf="account">Password for [<b>{{account.login}}</b>]</h2>
|
||||
|
||||
<div class="alert alert-success" *ngIf="success" jhiTranslate="password.messages.success">
|
||||
<strong>Password changed!</strong>
|
||||
</div>
|
||||
<div class="alert alert-danger" *ngIf="error" jhiTranslate="password.messages.error">
|
||||
<strong>An error has occurred!</strong> The password could not be changed.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch">
|
||||
The password and its confirmation do not match!
|
||||
</div>
|
||||
|
||||
<form name="form" role="form" (ngSubmit)="changePassword()" #passwordForm="ngForm">
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="currentPassword" jhiTranslate="global.form.currentpassword">Current password</label>
|
||||
<input type="password" class="form-control" id="currentPassword" name="currentPassword" #currentPasswordInput="ngModel"
|
||||
placeholder="{{'global.form.currentpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="currentPassword" required>
|
||||
<div *ngIf="currentPasswordInput.dirty && currentPasswordInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="currentPasswordInput.errors.required" jhiTranslate="global.messages.validate.newpassword.required">
|
||||
Your password is required.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="newPassword" jhiTranslate="global.form.newpassword">New password</label>
|
||||
<input type="password" class="form-control" id="newPassword" name="newPassword" #newPasswordInput="ngModel"
|
||||
placeholder="{{'global.form.newpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="newPassword" minlength=4 maxlength=50 required>
|
||||
<div *ngIf="newPasswordInput.dirty && newPasswordInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="newPasswordInput.errors.required" jhiTranslate="global.messages.validate.newpassword.required">
|
||||
Your password is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="newPasswordInput.errors.minlength" jhiTranslate="global.messages.validate.newpassword.minlength">
|
||||
Your password is required to be at least 4 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="newPasswordInput.errors.maxlength" jhiTranslate="global.messages.validate.newpassword.maxlength">
|
||||
Your password cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
<jhi-password-strength-bar [passwordToCheck]="newPassword"></jhi-password-strength-bar>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="confirmPassword" jhiTranslate="global.form.confirmpassword">New password confirmation</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" #confirmPasswordInput="ngModel"
|
||||
placeholder="{{'global.form.confirmpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="confirmPassword" minlength=4 maxlength=50 required>
|
||||
<div *ngIf="confirmPasswordInput.dirty && confirmPasswordInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="confirmPasswordInput.errors.required" jhiTranslate="global.messages.validate.confirmpassword.required">
|
||||
Your confirmation password is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="confirmPasswordInput.errors.minlength" jhiTranslate="global.messages.validate.confirmpassword.minlength">
|
||||
Your confirmation password is required to be at least 4 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="confirmPasswordInput.errors.maxlength" jhiTranslate="global.messages.validate.confirmpassword.maxlength">
|
||||
Your confirmation password cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" [disabled]="passwordForm.form.invalid" class="btn btn-primary" jhiTranslate="password.form.button">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
46
src/main/webapp/app/account/password/password.component.ts
Normal file
46
src/main/webapp/app/account/password/password.component.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { AccountService } from 'app/core';
|
||||
import { PasswordService } from './password.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-password',
|
||||
templateUrl: './password.component.html'
|
||||
})
|
||||
export class PasswordComponent implements OnInit {
|
||||
doNotMatch: string;
|
||||
error: string;
|
||||
success: string;
|
||||
account: any;
|
||||
currentPassword: string;
|
||||
newPassword: string;
|
||||
confirmPassword: string;
|
||||
|
||||
constructor(private passwordService: PasswordService, private accountService: AccountService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.accountService.identity().then(account => {
|
||||
this.account = account;
|
||||
});
|
||||
}
|
||||
|
||||
changePassword() {
|
||||
if (this.newPassword !== this.confirmPassword) {
|
||||
this.error = null;
|
||||
this.success = null;
|
||||
this.doNotMatch = 'ERROR';
|
||||
} else {
|
||||
this.doNotMatch = null;
|
||||
this.passwordService.save(this.newPassword, this.currentPassword).subscribe(
|
||||
() => {
|
||||
this.error = null;
|
||||
this.success = 'OK';
|
||||
},
|
||||
() => {
|
||||
this.success = null;
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
14
src/main/webapp/app/account/password/password.route.ts
Normal file
14
src/main/webapp/app/account/password/password.route.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { UserRouteAccessService } from 'app/core';
|
||||
import { PasswordComponent } from './password.component';
|
||||
|
||||
export const passwordRoute: Route = {
|
||||
path: 'password',
|
||||
component: PasswordComponent,
|
||||
data: {
|
||||
authorities: ['ROLE_USER'],
|
||||
pageTitle: 'global.menu.account.password'
|
||||
},
|
||||
canActivate: [UserRouteAccessService]
|
||||
};
|
14
src/main/webapp/app/account/password/password.service.ts
Normal file
14
src/main/webapp/app/account/password/password.service.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PasswordService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
save(newPassword: string, currentPassword: string): Observable<any> {
|
||||
return this.http.post(SERVER_API_URL + 'api/account/change-password', { currentPassword, newPassword });
|
||||
}
|
||||
}
|
124
src/main/webapp/app/account/register/register.component.html
Normal file
124
src/main/webapp/app/account/register/register.component.html
Normal file
@ -0,0 +1,124 @@
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h1 jhiTranslate="register.title">Registration</h1>
|
||||
|
||||
<div class="alert alert-success" *ngIf="success" jhiTranslate="register.messages.success">
|
||||
<strong>Registration saved!</strong> Please check your email for confirmation.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="error" jhiTranslate="register.messages.error.fail">
|
||||
<strong>Registration failed!</strong> Please try again later.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="errorUserExists" jhiTranslate="register.messages.error.userexists">
|
||||
<strong>Login name already registered!</strong> Please choose another one.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="errorEmailExists" jhiTranslate="register.messages.error.emailexists">
|
||||
<strong>Email is already in use!</strong> Please choose another one.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-danger" *ngIf="doNotMatch" jhiTranslate="global.messages.error.dontmatch">
|
||||
The password and its confirmation do not match!
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<form name="form" role="form" (ngSubmit)="register()" #registerForm="ngForm" *ngIf="!success">
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="login" jhiTranslate="global.form.username">Username</label>
|
||||
<input type="text" class="form-control" [(ngModel)]="registerAccount.login" id="login" name="login" #login="ngModel" placeholder="{{'global.form.username.placeholder' | translate}}"
|
||||
required minlength="1" maxlength="50" pattern="^[_.@A-Za-z0-9-]*$">
|
||||
<div *ngIf="login.dirty && login.invalid">
|
||||
<small class="form-text text-danger" *ngIf="login.errors.required" jhiTranslate="register.messages.validate.login.required">
|
||||
Your username is required.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="login.errors.minlength"
|
||||
jhiTranslate="register.messages.validate.login.minlength">
|
||||
Your username is required to be at least 1 character.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="login.errors.maxlength"
|
||||
jhiTranslate="register.messages.validate.login.maxlength">
|
||||
Your username cannot be longer than 50 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="login.errors.pattern"
|
||||
jhiTranslate="register.messages.validate.login.pattern">
|
||||
Your username can only contain letters and digits.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="email" jhiTranslate="global.form.email">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" #email="ngModel" placeholder="{{'global.form.email.placeholder' | translate}}"
|
||||
[(ngModel)]="registerAccount.email" minlength=5 maxlength=254 email required>
|
||||
<div *ngIf="email.dirty && email.invalid">
|
||||
<small class="form-text text-danger" *ngIf="email.errors.required"
|
||||
jhiTranslate="global.messages.validate.email.required">
|
||||
Your email is required.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="email.errors.invalid"
|
||||
jhiTranslate="global.messages.validate.email.invalid">
|
||||
Your email is invalid.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="email.errors.minlength"
|
||||
jhiTranslate="global.messages.validate.email.minlength">
|
||||
Your email is required to be at least 5 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="email.errors.maxlength"
|
||||
jhiTranslate="global.messages.validate.email.maxlength">
|
||||
Your email cannot be longer than 100 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="password" jhiTranslate="global.form.newpassword">New password</label>
|
||||
<input type="password" class="form-control" id="password" name="password" #password="ngModel" placeholder="{{'global.form.newpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="registerAccount.password" minlength=4 maxlength=50 required>
|
||||
<div *ngIf="password.dirty && password.invalid">
|
||||
<small class="form-text text-danger" *ngIf="password.errors.required"
|
||||
jhiTranslate="global.messages.validate.newpassword.required">
|
||||
Your password is required.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="password.errors.minlength"
|
||||
jhiTranslate="global.messages.validate.newpassword.minlength">
|
||||
Your password is required to be at least 4 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="password.errors.maxlength"
|
||||
jhiTranslate="global.messages.validate.newpassword.maxlength">
|
||||
Your password cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
<jhi-password-strength-bar [passwordToCheck]="registerAccount.password"></jhi-password-strength-bar>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="confirmPassword" jhiTranslate="global.form.confirmpassword">New password confirmation</label>
|
||||
<input type="password" class="form-control" id="confirmPassword" name="confirmPassword" #confirmPasswordInput="ngModel" placeholder="{{'global.form.confirmpassword.placeholder' | translate}}"
|
||||
[(ngModel)]="confirmPassword" minlength=4 maxlength=50 required>
|
||||
<div *ngIf="confirmPasswordInput.dirty && confirmPasswordInput.invalid">
|
||||
<small class="form-text text-danger" *ngIf="confirmPasswordInput.errors.required"
|
||||
jhiTranslate="global.messages.validate.confirmpassword.required">
|
||||
Your confirmation password is required.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="confirmPasswordInput.errors.minlength"
|
||||
jhiTranslate="global.messages.validate.confirmpassword.minlength">
|
||||
Your confirmation password is required to be at least 4 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger" *ngIf="confirmPasswordInput.errors.maxlength"
|
||||
jhiTranslate="global.messages.validate.confirmpassword.maxlength">
|
||||
Your confirmation password cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<button type="submit" [disabled]="registerForm.form.invalid" class="btn btn-primary" jhiTranslate="register.form.button">Register</button>
|
||||
</form>
|
||||
<p></p>
|
||||
<div class="alert alert-warning">
|
||||
<span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span>
|
||||
<a class="alert-link" (click)="openLogin()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
75
src/main/webapp/app/account/register/register.component.ts
Normal file
75
src/main/webapp/app/account/register/register.component.ts
Normal file
@ -0,0 +1,75 @@
|
||||
import { Component, OnInit, AfterViewInit, Renderer, ElementRef } from '@angular/core';
|
||||
import { HttpErrorResponse } from '@angular/common/http';
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { JhiLanguageService } from 'ng-jhipster';
|
||||
|
||||
import { EMAIL_ALREADY_USED_TYPE, LOGIN_ALREADY_USED_TYPE } from 'app/shared';
|
||||
import { LoginModalService } from 'app/core';
|
||||
import { Register } from './register.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-register',
|
||||
templateUrl: './register.component.html'
|
||||
})
|
||||
export class RegisterComponent implements OnInit, AfterViewInit {
|
||||
confirmPassword: string;
|
||||
doNotMatch: string;
|
||||
error: string;
|
||||
errorEmailExists: string;
|
||||
errorUserExists: string;
|
||||
registerAccount: any;
|
||||
success: boolean;
|
||||
modalRef: NgbModalRef;
|
||||
|
||||
constructor(
|
||||
private languageService: JhiLanguageService,
|
||||
private loginModalService: LoginModalService,
|
||||
private registerService: Register,
|
||||
private elementRef: ElementRef,
|
||||
private renderer: Renderer
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.success = false;
|
||||
this.registerAccount = {};
|
||||
}
|
||||
|
||||
ngAfterViewInit() {
|
||||
this.renderer.invokeElementMethod(this.elementRef.nativeElement.querySelector('#login'), 'focus', []);
|
||||
}
|
||||
|
||||
register() {
|
||||
if (this.registerAccount.password !== this.confirmPassword) {
|
||||
this.doNotMatch = 'ERROR';
|
||||
} else {
|
||||
this.doNotMatch = null;
|
||||
this.error = null;
|
||||
this.errorUserExists = null;
|
||||
this.errorEmailExists = null;
|
||||
this.languageService.getCurrent().then(key => {
|
||||
this.registerAccount.langKey = key;
|
||||
this.registerService.save(this.registerAccount).subscribe(
|
||||
() => {
|
||||
this.success = true;
|
||||
},
|
||||
response => this.processError(response)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
openLogin() {
|
||||
this.modalRef = this.loginModalService.open();
|
||||
}
|
||||
|
||||
private processError(response: HttpErrorResponse) {
|
||||
this.success = null;
|
||||
if (response.status === 400 && response.error.type === LOGIN_ALREADY_USED_TYPE) {
|
||||
this.errorUserExists = 'ERROR';
|
||||
} else if (response.status === 400 && response.error.type === EMAIL_ALREADY_USED_TYPE) {
|
||||
this.errorEmailExists = 'ERROR';
|
||||
} else {
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
}
|
||||
}
|
12
src/main/webapp/app/account/register/register.route.ts
Normal file
12
src/main/webapp/app/account/register/register.route.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { RegisterComponent } from './register.component';
|
||||
|
||||
export const registerRoute: Route = {
|
||||
path: 'register',
|
||||
component: RegisterComponent,
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'register.title'
|
||||
}
|
||||
};
|
14
src/main/webapp/app/account/register/register.service.ts
Normal file
14
src/main/webapp/app/account/register/register.service.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class Register {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
save(account: any): Observable<any> {
|
||||
return this.http.post(SERVER_API_URL + 'api/register', account);
|
||||
}
|
||||
}
|
86
src/main/webapp/app/account/settings/settings.component.html
Normal file
86
src/main/webapp/app/account/settings/settings.component.html
Normal file
@ -0,0 +1,86 @@
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8">
|
||||
<h2 jhiTranslate="settings.title" [translateValues]="{username: settingsAccount.login}" *ngIf="settingsAccount">User settings for [<b>{{settingsAccount.login}}</b>]</h2>
|
||||
|
||||
<div class="alert alert-success" *ngIf="success" jhiTranslate="settings.messages.success">
|
||||
<strong>Settings saved!</strong>
|
||||
</div>
|
||||
|
||||
<jhi-alert-error></jhi-alert-error>
|
||||
|
||||
<form name="form" role="form" (ngSubmit)="save()" #settingsForm="ngForm" *ngIf="settingsAccount" novalidate>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="firstName" jhiTranslate="settings.form.firstname">First Name</label>
|
||||
<input type="text" class="form-control" id="firstName" name="firstName" placeholder="{{'settings.form.firstname.placeholder' | translate}}"
|
||||
[(ngModel)]="settingsAccount.firstName" minlength=1 maxlength=50 #firstNameInput="ngModel" required>
|
||||
<div *ngIf="firstNameInput.dirty && firstNameInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="firstNameInput.errors.required" jhiTranslate="settings.messages.validate.firstname.required">
|
||||
Your first name is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="firstNameInput.errors.minlength" jhiTranslate="settings.messages.validate.firstname.minlength">
|
||||
Your first name is required to be at least 1 character.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="firstNameInput.errors.maxlength" jhiTranslate="settings.messages.validate.firstname.maxlength">
|
||||
Your first name cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="lastName" jhiTranslate="settings.form.lastname">Last Name</label>
|
||||
<input type="text" class="form-control" id="lastName" name="lastName" placeholder="{{'settings.form.lastname.placeholder' | translate}}"
|
||||
[(ngModel)]="settingsAccount.lastName" minlength=1 maxlength=50 #lastNameInput="ngModel" required>
|
||||
<div *ngIf="lastNameInput.dirty && lastNameInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="lastNameInput.errors.required" jhiTranslate="settings.messages.validate.lastname.required">
|
||||
Your last name is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="lastNameInput.errors.minlength" jhiTranslate="settings.messages.validate.lastname.minlength">
|
||||
Your last name is required to be at least 1 character.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="lastNameInput.errors.maxlength" jhiTranslate="settings.messages.validate.lastname.maxlength">
|
||||
Your last name cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" for="email" jhiTranslate="global.form.email">Email</label>
|
||||
<input type="email" class="form-control" id="email" name="email" placeholder="{{'global.form.email.placeholder' | translate}}"
|
||||
[(ngModel)]="settingsAccount.email" minlength="5" maxlength="254" #emailInput="ngModel" email required>
|
||||
<div *ngIf="emailInput.dirty && emailInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.required" jhiTranslate="global.messages.validate.email.required">
|
||||
Your email is required.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.email" jhiTranslate="global.messages.validate.email.invalid">
|
||||
Your email is invalid.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.minlength" jhiTranslate="global.messages.validate.email.minlength">
|
||||
Your email is required to be at least 5 characters.
|
||||
</small>
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.maxlength" jhiTranslate="global.messages.validate.email.maxlength">
|
||||
Your email cannot be longer than 100 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" *ngIf="languages && languages.length > 0">
|
||||
<label for="langKey" jhiTranslate="settings.form.language">Language</label>
|
||||
<select class="form-control" id="langKey" name="langKey" [(ngModel)]="settingsAccount.langKey">
|
||||
<option *ngFor="let language of languages" [value]="language">{{language | findLanguageFromKey}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<button type="submit" [disabled]="settingsForm.form.invalid" class="btn btn-primary" jhiTranslate="settings.form.button">Save</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
63
src/main/webapp/app/account/settings/settings.component.ts
Normal file
63
src/main/webapp/app/account/settings/settings.component.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { JhiLanguageService } from 'ng-jhipster';
|
||||
|
||||
import { AccountService, JhiLanguageHelper } from 'app/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-settings',
|
||||
templateUrl: './settings.component.html'
|
||||
})
|
||||
export class SettingsComponent implements OnInit {
|
||||
error: string;
|
||||
success: string;
|
||||
settingsAccount: any;
|
||||
languages: any[];
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private languageService: JhiLanguageService,
|
||||
private languageHelper: JhiLanguageHelper
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.accountService.identity().then(account => {
|
||||
this.settingsAccount = this.copyAccount(account);
|
||||
});
|
||||
this.languageHelper.getAll().then(languages => {
|
||||
this.languages = languages;
|
||||
});
|
||||
}
|
||||
|
||||
save() {
|
||||
this.accountService.save(this.settingsAccount).subscribe(
|
||||
() => {
|
||||
this.error = null;
|
||||
this.success = 'OK';
|
||||
this.accountService.identity(true).then(account => {
|
||||
this.settingsAccount = this.copyAccount(account);
|
||||
});
|
||||
this.languageService.getCurrent().then(current => {
|
||||
if (this.settingsAccount.langKey !== current) {
|
||||
this.languageService.changeLanguage(this.settingsAccount.langKey);
|
||||
}
|
||||
});
|
||||
},
|
||||
() => {
|
||||
this.success = null;
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
copyAccount(account) {
|
||||
return {
|
||||
activated: account.activated,
|
||||
email: account.email,
|
||||
firstName: account.firstName,
|
||||
langKey: account.langKey,
|
||||
lastName: account.lastName,
|
||||
login: account.login,
|
||||
imageUrl: account.imageUrl
|
||||
};
|
||||
}
|
||||
}
|
14
src/main/webapp/app/account/settings/settings.route.ts
Normal file
14
src/main/webapp/app/account/settings/settings.route.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { UserRouteAccessService } from 'app/core';
|
||||
import { SettingsComponent } from './settings.component';
|
||||
|
||||
export const settingsRoute: Route = {
|
||||
path: 'settings',
|
||||
component: SettingsComponent,
|
||||
data: {
|
||||
authorities: ['ROLE_USER'],
|
||||
pageTitle: 'global.menu.account.settings'
|
||||
},
|
||||
canActivate: [UserRouteAccessService]
|
||||
};
|
54
src/main/webapp/app/admin/admin.module.ts
Normal file
54
src/main/webapp/app/admin/admin.module.ts
Normal file
@ -0,0 +1,54 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { JhiLanguageService } from 'ng-jhipster';
|
||||
import { JhiLanguageHelper } from 'app/core';
|
||||
import { HsadminNgSharedModule } from 'app/shared';
|
||||
/* jhipster-needle-add-admin-module-import - JHipster will add admin modules imports here */
|
||||
|
||||
import {
|
||||
adminState,
|
||||
AuditsComponent,
|
||||
UserMgmtComponent,
|
||||
UserMgmtDetailComponent,
|
||||
UserMgmtUpdateComponent,
|
||||
UserMgmtDeleteDialogComponent,
|
||||
LogsComponent,
|
||||
JhiMetricsMonitoringComponent,
|
||||
JhiHealthModalComponent,
|
||||
JhiHealthCheckComponent,
|
||||
JhiConfigurationComponent,
|
||||
JhiDocsComponent
|
||||
} from './';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
HsadminNgSharedModule,
|
||||
RouterModule.forChild(adminState)
|
||||
/* jhipster-needle-add-admin-module - JHipster will add admin modules here */
|
||||
],
|
||||
declarations: [
|
||||
AuditsComponent,
|
||||
UserMgmtComponent,
|
||||
UserMgmtDetailComponent,
|
||||
UserMgmtUpdateComponent,
|
||||
UserMgmtDeleteDialogComponent,
|
||||
LogsComponent,
|
||||
JhiConfigurationComponent,
|
||||
JhiHealthCheckComponent,
|
||||
JhiHealthModalComponent,
|
||||
JhiDocsComponent,
|
||||
JhiMetricsMonitoringComponent
|
||||
],
|
||||
providers: [{ provide: JhiLanguageService, useClass: JhiLanguageService }],
|
||||
entryComponents: [UserMgmtDeleteDialogComponent, JhiHealthModalComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HsadminNgAdminModule {
|
||||
constructor(private languageService: JhiLanguageService, private languageHelper: JhiLanguageHelper) {
|
||||
this.languageHelper.language.subscribe((languageKey: string) => {
|
||||
if (languageKey !== undefined) {
|
||||
this.languageService.changeLanguage(languageKey);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
18
src/main/webapp/app/admin/admin.route.ts
Normal file
18
src/main/webapp/app/admin/admin.route.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Routes } from '@angular/router';
|
||||
|
||||
import { auditsRoute, configurationRoute, docsRoute, healthRoute, logsRoute, metricsRoute, userMgmtRoute } from './';
|
||||
|
||||
import { UserRouteAccessService } from 'app/core';
|
||||
|
||||
const ADMIN_ROUTES = [auditsRoute, configurationRoute, docsRoute, healthRoute, logsRoute, ...userMgmtRoute, metricsRoute];
|
||||
|
||||
export const adminState: Routes = [
|
||||
{
|
||||
path: '',
|
||||
data: {
|
||||
authorities: ['ROLE_ADMIN']
|
||||
},
|
||||
canActivate: [UserRouteAccessService],
|
||||
children: ADMIN_ROUTES
|
||||
}
|
||||
];
|
3
src/main/webapp/app/admin/audits/audit-data.model.ts
Normal file
3
src/main/webapp/app/admin/audits/audit-data.model.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export class AuditData {
|
||||
constructor(public remoteAddress: string, public sessionId: string) {}
|
||||
}
|
5
src/main/webapp/app/admin/audits/audit.model.ts
Normal file
5
src/main/webapp/app/admin/audits/audit.model.ts
Normal file
@ -0,0 +1,5 @@
|
||||
import { AuditData } from './audit-data.model';
|
||||
|
||||
export class Audit {
|
||||
constructor(public data: AuditData, public principal: string, public timestamp: string, public type: string) {}
|
||||
}
|
52
src/main/webapp/app/admin/audits/audits.component.html
Normal file
52
src/main/webapp/app/admin/audits/audits.component.html
Normal file
@ -0,0 +1,52 @@
|
||||
<div *ngIf="audits">
|
||||
<h2 id="audits-page-heading" jhiTranslate="audits.title">Audits</h2>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-5">
|
||||
<h4 jhiTranslate="audits.filter.title">Filter by date</h4>
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" jhiTranslate="audits.filter.from">from</span>
|
||||
</div>
|
||||
<input type="date" class="form-control" name="start" [(ngModel)]="fromDate" (ngModelChange)="transition()" required/>
|
||||
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text" jhiTranslate="audits.filter.to">To</span>
|
||||
</div>
|
||||
<input type="date" class="form-control" name="end" [(ngModel)]="toDate" (ngModelChange)="transition()" required/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped">
|
||||
<thead>
|
||||
<tr jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="transition.bind(this)">
|
||||
<th jhiSortBy="auditEventDate"><span jhiTranslate="audits.table.header.date">Date</span><fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th jhiSortBy="principal"><span jhiTranslate="audits.table.header.principal">User</span><fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th jhiSortBy="auditEventType"><span jhiTranslate="audits.table.header.status">State</span><fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th><span jhiTranslate="audits.table.header.data">Extra data</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let audit of audits">
|
||||
<td><span>{{audit.timestamp| date:'medium'}}</span></td>
|
||||
<td><small>{{audit.principal}}</small></td>
|
||||
<td>{{audit.type}}</td>
|
||||
<td>
|
||||
<span *ngIf="audit.data" ng-show="audit.data.message">{{audit.data.message}}</span>
|
||||
<span *ngIf="audit.data" ng-show="audit.data.remoteAddress"><span jhiTranslate="audits.table.data.remoteAddress">Remote Address</span> {{audit.data.remoteAddress}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<div class="row justify-content-center">
|
||||
<jhi-item-count [page]="page" [total]="totalItems" [itemsPerPage]="itemsPerPage"></jhi-item-count>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<ngb-pagination [collectionSize]="totalItems" [(page)]="page" [pageSize]="itemsPerPage" [maxSize]="5" [rotate]="true" [boundaryLinks]="true" (pageChange)="loadPage(page)"></ngb-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
126
src/main/webapp/app/admin/audits/audits.component.ts
Normal file
126
src/main/webapp/app/admin/audits/audits.component.ts
Normal file
@ -0,0 +1,126 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { HttpResponse } from '@angular/common/http';
|
||||
import { DatePipe } from '@angular/common';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { JhiParseLinks, JhiAlertService } from 'ng-jhipster';
|
||||
|
||||
import { ITEMS_PER_PAGE } from 'app/shared';
|
||||
import { Audit } from './audit.model';
|
||||
import { AuditsService } from './audits.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-audit',
|
||||
templateUrl: './audits.component.html'
|
||||
})
|
||||
export class AuditsComponent implements OnInit, OnDestroy {
|
||||
audits: Audit[];
|
||||
fromDate: string;
|
||||
itemsPerPage: any;
|
||||
links: any;
|
||||
page: number;
|
||||
routeData: any;
|
||||
predicate: any;
|
||||
previousPage: any;
|
||||
reverse: boolean;
|
||||
toDate: string;
|
||||
totalItems: number;
|
||||
|
||||
constructor(
|
||||
private auditsService: AuditsService,
|
||||
private alertService: JhiAlertService,
|
||||
private parseLinks: JhiParseLinks,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private datePipe: DatePipe,
|
||||
private router: Router
|
||||
) {
|
||||
this.itemsPerPage = ITEMS_PER_PAGE;
|
||||
this.routeData = this.activatedRoute.data.subscribe(data => {
|
||||
this.page = data['pagingParams'].page;
|
||||
this.previousPage = data['pagingParams'].page;
|
||||
this.reverse = data['pagingParams'].ascending;
|
||||
this.predicate = data['pagingParams'].predicate;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.today();
|
||||
this.previousMonth();
|
||||
this.loadAll();
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.routeData.unsubscribe();
|
||||
}
|
||||
|
||||
previousMonth() {
|
||||
const dateFormat = 'yyyy-MM-dd';
|
||||
let fromDate: Date = new Date();
|
||||
|
||||
if (fromDate.getMonth() === 0) {
|
||||
fromDate = new Date(fromDate.getFullYear() - 1, 11, fromDate.getDate());
|
||||
} else {
|
||||
fromDate = new Date(fromDate.getFullYear(), fromDate.getMonth() - 1, fromDate.getDate());
|
||||
}
|
||||
|
||||
this.fromDate = this.datePipe.transform(fromDate, dateFormat);
|
||||
}
|
||||
|
||||
today() {
|
||||
const dateFormat = 'yyyy-MM-dd';
|
||||
// Today + 1 day - needed if the current day must be included
|
||||
const today: Date = new Date();
|
||||
today.setDate(today.getDate() + 1);
|
||||
const date = new Date(today.getFullYear(), today.getMonth(), today.getDate());
|
||||
this.toDate = this.datePipe.transform(date, dateFormat);
|
||||
}
|
||||
|
||||
loadAll() {
|
||||
this.auditsService
|
||||
.query({
|
||||
page: this.page - 1,
|
||||
size: this.itemsPerPage,
|
||||
sort: this.sort(),
|
||||
fromDate: this.fromDate,
|
||||
toDate: this.toDate
|
||||
})
|
||||
.subscribe(
|
||||
(res: HttpResponse<Audit[]>) => this.onSuccess(res.body, res.headers),
|
||||
(res: HttpResponse<any>) => this.onError(res.body)
|
||||
);
|
||||
}
|
||||
|
||||
sort() {
|
||||
const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')];
|
||||
if (this.predicate !== 'id') {
|
||||
result.push('id');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
loadPage(page: number) {
|
||||
if (page !== this.previousPage) {
|
||||
this.previousPage = page;
|
||||
this.transition();
|
||||
}
|
||||
}
|
||||
|
||||
transition() {
|
||||
this.router.navigate(['/admin/audits'], {
|
||||
queryParams: {
|
||||
page: this.page,
|
||||
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc')
|
||||
}
|
||||
});
|
||||
this.loadAll();
|
||||
}
|
||||
|
||||
private onSuccess(data, headers) {
|
||||
this.links = this.parseLinks.parse(headers.get('link'));
|
||||
this.totalItems = headers.get('X-Total-Count');
|
||||
this.audits = data;
|
||||
}
|
||||
|
||||
private onError(error) {
|
||||
this.alertService.error(error.error, error.message, null);
|
||||
}
|
||||
}
|
17
src/main/webapp/app/admin/audits/audits.route.ts
Normal file
17
src/main/webapp/app/admin/audits/audits.route.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Route } from '@angular/router';
|
||||
import { JhiPaginationUtil, JhiResolvePagingParams } from 'ng-jhipster';
|
||||
|
||||
import { AuditsComponent } from './audits.component';
|
||||
|
||||
export const auditsRoute: Route = {
|
||||
path: 'audits',
|
||||
component: AuditsComponent,
|
||||
resolve: {
|
||||
pagingParams: JhiResolvePagingParams
|
||||
},
|
||||
data: {
|
||||
pageTitle: 'audits.title',
|
||||
defaultSort: 'auditEventDate,desc'
|
||||
}
|
||||
};
|
25
src/main/webapp/app/admin/audits/audits.service.ts
Normal file
25
src/main/webapp/app/admin/audits/audits.service.ts
Normal file
@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpParams, HttpResponse } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { createRequestOption } from 'app/shared';
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
import { Audit } from './audit.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AuditsService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
query(req: any): Observable<HttpResponse<Audit[]>> {
|
||||
const params: HttpParams = createRequestOption(req);
|
||||
params.set('fromDate', req.fromDate);
|
||||
params.set('toDate', req.toDate);
|
||||
|
||||
const requestURL = SERVER_API_URL + 'management/audits';
|
||||
|
||||
return this.http.get<Audit[]>(requestURL, {
|
||||
params,
|
||||
observe: 'response'
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
<div *ngIf="allConfiguration && configuration">
|
||||
<h2 id="configuration-page-heading" jhiTranslate="configuration.title">Configuration</h2>
|
||||
|
||||
<span jhiTranslate="configuration.filter">Filter (by prefix)</span> <input type="text" [(ngModel)]="filter" class="form-control">
|
||||
<h3>Spring configuration</h3>
|
||||
<table class="table table-striped table-bordered table-responsive d-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-40" (click)="orderProp = 'prefix'; reverse=!reverse"><span jhiTranslate="configuration.table.prefix">Prefix</span></th>
|
||||
<th class="w-60" (click)="orderProp = 'properties'; reverse=!reverse"><span jhiTranslate="configuration.table.properties">Properties</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let entry of (configuration | pureFilter:filter:'prefix' | orderBy:orderProp:reverse)">
|
||||
<td><span>{{entry.prefix}}</span></td>
|
||||
<td>
|
||||
<div class="row" *ngFor="let key of keys(entry.properties)">
|
||||
<div class="col-md-4">{{key}}</div>
|
||||
<div class="col-md-8">
|
||||
<span class="float-right badge-secondary break">{{entry.properties[key] | json}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div *ngFor="let key of keys(allConfiguration)">
|
||||
<h4><span>{{key}}</span></h4>
|
||||
<table class="table table-sm table-striped table-bordered table-responsive d-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="w-40">Property</th>
|
||||
<th class="w-60">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let item of allConfiguration[key]">
|
||||
<td class="break">{{item.key}}</td>
|
||||
<td class="break">
|
||||
<span class="float-right badge-secondary break">{{item.val}}</span>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,43 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { JhiConfigurationService } from './configuration.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-configuration',
|
||||
templateUrl: './configuration.component.html'
|
||||
})
|
||||
export class JhiConfigurationComponent implements OnInit {
|
||||
allConfiguration: any = null;
|
||||
configuration: any = null;
|
||||
configKeys: any[];
|
||||
filter: string;
|
||||
orderProp: string;
|
||||
reverse: boolean;
|
||||
|
||||
constructor(private configurationService: JhiConfigurationService) {
|
||||
this.configKeys = [];
|
||||
this.filter = '';
|
||||
this.orderProp = 'prefix';
|
||||
this.reverse = false;
|
||||
}
|
||||
|
||||
keys(dict): Array<string> {
|
||||
return dict === undefined ? [] : Object.keys(dict);
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.configurationService.get().subscribe(configuration => {
|
||||
this.configuration = configuration;
|
||||
|
||||
for (const config of configuration) {
|
||||
if (config.properties !== undefined) {
|
||||
this.configKeys.push(Object.keys(config.properties));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.configurationService.getEnv().subscribe(configuration => {
|
||||
this.allConfiguration = configuration;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { JhiConfigurationComponent } from './configuration.component';
|
||||
|
||||
export const configurationRoute: Route = {
|
||||
path: 'jhi-configuration',
|
||||
component: JhiConfigurationComponent,
|
||||
data: {
|
||||
pageTitle: 'configuration.title'
|
||||
}
|
||||
};
|
@ -0,0 +1,67 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpResponse } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class JhiConfigurationService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
get(): Observable<any> {
|
||||
return this.http.get(SERVER_API_URL + 'management/configprops', { observe: 'response' }).pipe(
|
||||
map((res: HttpResponse<any>) => {
|
||||
const properties: any[] = [];
|
||||
const propertiesObject = this.getConfigPropertiesObjects(res.body);
|
||||
for (const key in propertiesObject) {
|
||||
if (propertiesObject.hasOwnProperty(key)) {
|
||||
properties.push(propertiesObject[key]);
|
||||
}
|
||||
}
|
||||
|
||||
return properties.sort((propertyA, propertyB) => {
|
||||
return propertyA.prefix === propertyB.prefix ? 0 : propertyA.prefix < propertyB.prefix ? -1 : 1;
|
||||
});
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
getConfigPropertiesObjects(res: Object) {
|
||||
// This code is for Spring Boot 2
|
||||
if (res['contexts'] !== undefined) {
|
||||
for (const key in res['contexts']) {
|
||||
// If the key is not bootstrap, it will be the ApplicationContext Id
|
||||
// For default app, it is baseName
|
||||
// For microservice, it is baseName-1
|
||||
if (!key.startsWith('bootstrap')) {
|
||||
return res['contexts'][key]['beans'];
|
||||
}
|
||||
}
|
||||
}
|
||||
// by default, use the default ApplicationContext Id
|
||||
return res['contexts']['hsadminNg']['beans'];
|
||||
}
|
||||
|
||||
getEnv(): Observable<any> {
|
||||
return this.http.get(SERVER_API_URL + 'management/env', { observe: 'response' }).pipe(
|
||||
map((res: HttpResponse<any>) => {
|
||||
const properties: any = {};
|
||||
const propertySources = res.body['propertySources'];
|
||||
|
||||
for (const propertyObject of propertySources) {
|
||||
const name = propertyObject['name'];
|
||||
const detailProperties = propertyObject['properties'];
|
||||
const vals: any[] = [];
|
||||
for (const keyDetail in detailProperties) {
|
||||
if (detailProperties.hasOwnProperty(keyDetail)) {
|
||||
vals.push({ key: keyDetail, val: detailProperties[keyDetail]['value'] });
|
||||
}
|
||||
}
|
||||
properties[name] = vals;
|
||||
}
|
||||
return properties;
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
2
src/main/webapp/app/admin/docs/docs.component.html
Normal file
2
src/main/webapp/app/admin/docs/docs.component.html
Normal file
@ -0,0 +1,2 @@
|
||||
<iframe src="swagger-ui/index.html" width="100%" height="900" seamless
|
||||
target="_top" title="Swagger UI" class="border-0"></iframe>
|
9
src/main/webapp/app/admin/docs/docs.component.ts
Normal file
9
src/main/webapp/app/admin/docs/docs.component.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-docs',
|
||||
templateUrl: './docs.component.html'
|
||||
})
|
||||
export class JhiDocsComponent {
|
||||
constructor() {}
|
||||
}
|
11
src/main/webapp/app/admin/docs/docs.route.ts
Normal file
11
src/main/webapp/app/admin/docs/docs.route.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { JhiDocsComponent } from './docs.component';
|
||||
|
||||
export const docsRoute: Route = {
|
||||
path: 'docs',
|
||||
component: JhiDocsComponent,
|
||||
data: {
|
||||
pageTitle: 'global.menu.admin.apidocs'
|
||||
}
|
||||
};
|
36
src/main/webapp/app/admin/health/health-modal.component.html
Normal file
36
src/main/webapp/app/admin/health/health-modal.component.html
Normal file
@ -0,0 +1,36 @@
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" id="showHealthLabel">
|
||||
{{'health.indicator.' + baseName(currentHealth.name) | translate}}
|
||||
{{subSystemName(currentHealth.name)}}
|
||||
</h4>
|
||||
<button aria-label="Close" data-dismiss="modal" class="close" type="button" (click)="activeModal.dismiss('closed')"><span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body pad">
|
||||
<div *ngIf="currentHealth.details">
|
||||
<h5 jhiTranslate="health.details.properties">Properties</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="text-left" jhiTranslate="health.details.name">Name</th>
|
||||
<th class="text-left" jhiTranslate="health.details.value">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let entry of currentHealth.details.details | keys">
|
||||
<td class="text-left">{{entry.key}}</td>
|
||||
<td class="text-left">{{readableValue(entry.value)}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="currentHealth.error">
|
||||
<h4 jhiTranslate="health.details.error">Error</h4>
|
||||
<pre>{{currentHealth.error}}</pre>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button data-dismiss="modal" class="btn btn-secondary float-left" type="button" (click)="activeModal.dismiss('closed')">Done</button>
|
||||
</div>
|
41
src/main/webapp/app/admin/health/health-modal.component.ts
Normal file
41
src/main/webapp/app/admin/health/health-modal.component.ts
Normal file
@ -0,0 +1,41 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { JhiHealthService } from './health.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-health-modal',
|
||||
templateUrl: './health-modal.component.html'
|
||||
})
|
||||
export class JhiHealthModalComponent {
|
||||
currentHealth: any;
|
||||
|
||||
constructor(private healthService: JhiHealthService, public activeModal: NgbActiveModal) {}
|
||||
|
||||
baseName(name) {
|
||||
return this.healthService.getBaseName(name);
|
||||
}
|
||||
|
||||
subSystemName(name) {
|
||||
return this.healthService.getSubSystemName(name);
|
||||
}
|
||||
|
||||
readableValue(value: number) {
|
||||
if (this.currentHealth.name === 'diskSpace') {
|
||||
// Should display storage space in an human readable unit
|
||||
const val = value / 1073741824;
|
||||
if (val > 1) {
|
||||
// Value
|
||||
return val.toFixed(2) + ' GB';
|
||||
} else {
|
||||
return (value / 1048576).toFixed(2) + ' MB';
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof value === 'object') {
|
||||
return JSON.stringify(value);
|
||||
} else {
|
||||
return value.toString();
|
||||
}
|
||||
}
|
||||
}
|
34
src/main/webapp/app/admin/health/health.component.html
Normal file
34
src/main/webapp/app/admin/health/health.component.html
Normal file
@ -0,0 +1,34 @@
|
||||
<div>
|
||||
<h2>
|
||||
<span id="health-page-heading" jhiTranslate="health.title">Health Checks</span>
|
||||
<button class="btn btn-primary float-right" (click)="refresh()">
|
||||
<fa-icon [icon]="'sync'"></fa-icon> <span jhiTranslate="health.refresh.button">Refresh</span>
|
||||
</button>
|
||||
</h2>
|
||||
<div class="table-responsive">
|
||||
<table id="healthCheck" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th jhiTranslate="health.table.service">Service Name</th>
|
||||
<th class="text-center" jhiTranslate="health.table.status">Status</th>
|
||||
<th class="text-center" jhiTranslate="health.details.details">Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr *ngFor="let health of healthData">
|
||||
<td>{{'health.indicator.' + baseName(health.name) | translate}} {{subSystemName(health.name)}}</td>
|
||||
<td class="text-center">
|
||||
<span class="badge" [ngClass]="getBadgeClass(health.status)" jhiTranslate="{{'health.status.' + health.status}}">
|
||||
{{health.status}}
|
||||
</span>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<a class="hand" (click)="showHealth(health)" *ngIf="health.details || health.error">
|
||||
<fa-icon [icon]="'eye'"></fa-icon>
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
66
src/main/webapp/app/admin/health/health.component.ts
Normal file
66
src/main/webapp/app/admin/health/health.component.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { JhiHealthService } from './health.service';
|
||||
import { JhiHealthModalComponent } from './health-modal.component';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-health',
|
||||
templateUrl: './health.component.html'
|
||||
})
|
||||
export class JhiHealthCheckComponent implements OnInit {
|
||||
healthData: any;
|
||||
updatingHealth: boolean;
|
||||
|
||||
constructor(private modalService: NgbModal, private healthService: JhiHealthService) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
baseName(name: string) {
|
||||
return this.healthService.getBaseName(name);
|
||||
}
|
||||
|
||||
getBadgeClass(statusState) {
|
||||
if (statusState === 'UP') {
|
||||
return 'badge-success';
|
||||
} else {
|
||||
return 'badge-danger';
|
||||
}
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.updatingHealth = true;
|
||||
|
||||
this.healthService.checkHealth().subscribe(
|
||||
health => {
|
||||
this.healthData = this.healthService.transformHealthData(health);
|
||||
this.updatingHealth = false;
|
||||
},
|
||||
error => {
|
||||
if (error.status === 503) {
|
||||
this.healthData = this.healthService.transformHealthData(error.error);
|
||||
this.updatingHealth = false;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
showHealth(health: any) {
|
||||
const modalRef = this.modalService.open(JhiHealthModalComponent);
|
||||
modalRef.componentInstance.currentHealth = health;
|
||||
modalRef.result.then(
|
||||
result => {
|
||||
// Left blank intentionally, nothing to do here
|
||||
},
|
||||
reason => {
|
||||
// Left blank intentionally, nothing to do here
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
subSystemName(name: string) {
|
||||
return this.healthService.getSubSystemName(name);
|
||||
}
|
||||
}
|
11
src/main/webapp/app/admin/health/health.route.ts
Normal file
11
src/main/webapp/app/admin/health/health.route.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { JhiHealthCheckComponent } from './health.component';
|
||||
|
||||
export const healthRoute: Route = {
|
||||
path: 'jhi-health',
|
||||
component: JhiHealthCheckComponent,
|
||||
data: {
|
||||
pageTitle: 'health.title'
|
||||
}
|
||||
};
|
133
src/main/webapp/app/admin/health/health.service.ts
Normal file
133
src/main/webapp/app/admin/health/health.service.ts
Normal file
@ -0,0 +1,133 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class JhiHealthService {
|
||||
separator: string;
|
||||
|
||||
constructor(private http: HttpClient) {
|
||||
this.separator = '.';
|
||||
}
|
||||
|
||||
checkHealth(): Observable<any> {
|
||||
return this.http.get(SERVER_API_URL + 'management/health');
|
||||
}
|
||||
|
||||
transformHealthData(data): any {
|
||||
const response = [];
|
||||
this.flattenHealthData(response, null, data.details);
|
||||
return response;
|
||||
}
|
||||
|
||||
getBaseName(name): string {
|
||||
if (name) {
|
||||
const split = name.split('.');
|
||||
return split[0];
|
||||
}
|
||||
}
|
||||
|
||||
getSubSystemName(name): string {
|
||||
if (name) {
|
||||
const split = name.split('.');
|
||||
split.splice(0, 1);
|
||||
const remainder = split.join('.');
|
||||
return remainder ? ' - ' + remainder : '';
|
||||
}
|
||||
}
|
||||
|
||||
/* private methods */
|
||||
private addHealthObject(result, isLeaf, healthObject, name): any {
|
||||
const healthData: any = {
|
||||
name
|
||||
};
|
||||
|
||||
const details = {};
|
||||
let hasDetails = false;
|
||||
|
||||
for (const key in healthObject) {
|
||||
if (healthObject.hasOwnProperty(key)) {
|
||||
const value = healthObject[key];
|
||||
if (key === 'status' || key === 'error') {
|
||||
healthData[key] = value;
|
||||
} else {
|
||||
if (!this.isHealthObject(value)) {
|
||||
details[key] = value;
|
||||
hasDetails = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add the details
|
||||
if (hasDetails) {
|
||||
healthData.details = details;
|
||||
}
|
||||
|
||||
// Only add nodes if they provide additional information
|
||||
if (isLeaf || hasDetails || healthData.error) {
|
||||
result.push(healthData);
|
||||
}
|
||||
return healthData;
|
||||
}
|
||||
|
||||
private flattenHealthData(result, path, data): any {
|
||||
for (const key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
const value = data[key];
|
||||
if (this.isHealthObject(value)) {
|
||||
if (this.hasSubSystem(value)) {
|
||||
this.addHealthObject(result, false, value, this.getModuleName(path, key));
|
||||
this.flattenHealthData(result, this.getModuleName(path, key), value);
|
||||
} else {
|
||||
this.addHealthObject(result, true, value, this.getModuleName(path, key));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private getModuleName(path, name): string {
|
||||
let result;
|
||||
if (path && name) {
|
||||
result = path + this.separator + name;
|
||||
} else if (path) {
|
||||
result = path;
|
||||
} else if (name) {
|
||||
result = name;
|
||||
} else {
|
||||
result = '';
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private hasSubSystem(healthObject): boolean {
|
||||
let result = false;
|
||||
|
||||
for (const key in healthObject) {
|
||||
if (healthObject.hasOwnProperty(key)) {
|
||||
const value = healthObject[key];
|
||||
if (value && value.status) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private isHealthObject(healthObject): boolean {
|
||||
let result = false;
|
||||
|
||||
for (const key in healthObject) {
|
||||
if (healthObject.hasOwnProperty(key)) {
|
||||
if (key === 'status') {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
27
src/main/webapp/app/admin/index.ts
Normal file
27
src/main/webapp/app/admin/index.ts
Normal file
@ -0,0 +1,27 @@
|
||||
export * from './audits/audits.component';
|
||||
export * from './audits/audits.service';
|
||||
export * from './audits/audits.route';
|
||||
export * from './audits/audit.model';
|
||||
export * from './audits/audit-data.model';
|
||||
export * from './configuration/configuration.component';
|
||||
export * from './configuration/configuration.service';
|
||||
export * from './configuration/configuration.route';
|
||||
export * from './docs/docs.component';
|
||||
export * from './docs/docs.route';
|
||||
export * from './health/health.component';
|
||||
export * from './health/health-modal.component';
|
||||
export * from './health/health.service';
|
||||
export * from './health/health.route';
|
||||
export * from './logs/logs.component';
|
||||
export * from './logs/logs.service';
|
||||
export * from './logs/logs.route';
|
||||
export * from './logs/log.model';
|
||||
export * from './metrics/metrics.component';
|
||||
export * from './metrics/metrics.service';
|
||||
export * from './metrics/metrics.route';
|
||||
export * from './user-management/user-management-update.component';
|
||||
export * from './user-management/user-management-delete-dialog.component';
|
||||
export * from './user-management/user-management-detail.component';
|
||||
export * from './user-management/user-management.component';
|
||||
export * from './user-management/user-management.route';
|
||||
export * from './admin.route';
|
3
src/main/webapp/app/admin/logs/log.model.ts
Normal file
3
src/main/webapp/app/admin/logs/log.model.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export class Log {
|
||||
constructor(public name: string, public level: string) {}
|
||||
}
|
28
src/main/webapp/app/admin/logs/logs.component.html
Normal file
28
src/main/webapp/app/admin/logs/logs.component.html
Normal file
@ -0,0 +1,28 @@
|
||||
<div class="table-responsive" *ngIf="loggers">
|
||||
<h2 id="logs-page-heading" jhiTranslate="logs.title">Logs</h2>
|
||||
|
||||
<p jhiTranslate="logs.nbloggers" [translateValues]="{total: loggers.length}">There are {{ loggers.length }} loggers.</p>
|
||||
|
||||
<span jhiTranslate="logs.filter">Filter</span> <input type="text" [(ngModel)]="filter" class="form-control">
|
||||
|
||||
<table class="table table-sm table-striped table-bordered">
|
||||
<thead>
|
||||
<tr title="click to order">
|
||||
<th (click)="orderProp = 'name'; reverse=!reverse"><span jhiTranslate="logs.table.name">Name</span></th>
|
||||
<th (click)="orderProp = 'level'; reverse=!reverse"><span jhiTranslate="logs.table.level">Level</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tr *ngFor="let logger of (loggers | pureFilter:filter:'name' | orderBy:orderProp:reverse)">
|
||||
<td><small>{{logger.name | slice:0:140}}</small></td>
|
||||
<td>
|
||||
<button (click)="changeLevel(logger.name, 'TRACE')" [ngClass]="(logger.level=='TRACE') ? 'btn-primary' : 'btn-light'" class="btn btn-sm">TRACE</button>
|
||||
<button (click)="changeLevel(logger.name, 'DEBUG')" [ngClass]="(logger.level=='DEBUG') ? 'btn-success' : 'btn-light'" class="btn btn-sm">DEBUG</button>
|
||||
<button (click)="changeLevel(logger.name, 'INFO')" [ngClass]="(logger.level=='INFO') ? 'btn-info' : 'btn-light'" class="btn btn-sm">INFO</button>
|
||||
<button (click)="changeLevel(logger.name, 'WARN')" [ngClass]="(logger.level=='WARN') ? 'btn-warning' : 'btn-light'" class="btn btn-sm">WARN</button>
|
||||
<button (click)="changeLevel(logger.name, 'ERROR')" [ngClass]="(logger.level=='ERROR') ? 'btn-danger' : 'btn-light'" class="btn btn-sm">ERROR</button>
|
||||
<button (click)="changeLevel(logger.name, 'OFF')" [ngClass]="(logger.level=='OFF') ? 'btn-secondary' : 'btn-light'" class="btn btn-sm">OFF</button>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
32
src/main/webapp/app/admin/logs/logs.component.ts
Normal file
32
src/main/webapp/app/admin/logs/logs.component.ts
Normal file
@ -0,0 +1,32 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
|
||||
import { Log } from './log.model';
|
||||
import { LogsService } from './logs.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-logs',
|
||||
templateUrl: './logs.component.html'
|
||||
})
|
||||
export class LogsComponent implements OnInit {
|
||||
loggers: Log[];
|
||||
filter: string;
|
||||
orderProp: string;
|
||||
reverse: boolean;
|
||||
|
||||
constructor(private logsService: LogsService) {
|
||||
this.filter = '';
|
||||
this.orderProp = 'name';
|
||||
this.reverse = false;
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.logsService.findAll().subscribe(response => (this.loggers = response.body));
|
||||
}
|
||||
|
||||
changeLevel(name: string, level: string) {
|
||||
const log = new Log(name, level);
|
||||
this.logsService.changeLevel(log).subscribe(() => {
|
||||
this.logsService.findAll().subscribe(response => (this.loggers = response.body));
|
||||
});
|
||||
}
|
||||
}
|
11
src/main/webapp/app/admin/logs/logs.route.ts
Normal file
11
src/main/webapp/app/admin/logs/logs.route.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { LogsComponent } from './logs.component';
|
||||
|
||||
export const logsRoute: Route = {
|
||||
path: 'logs',
|
||||
component: LogsComponent,
|
||||
data: {
|
||||
pageTitle: 'logs.title'
|
||||
}
|
||||
};
|
19
src/main/webapp/app/admin/logs/logs.service.ts
Normal file
19
src/main/webapp/app/admin/logs/logs.service.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpResponse } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
import { Log } from './log.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LogsService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
changeLevel(log: Log): Observable<HttpResponse<any>> {
|
||||
return this.http.put(SERVER_API_URL + 'management/logs', log, { observe: 'response' });
|
||||
}
|
||||
|
||||
findAll(): Observable<HttpResponse<Log[]>> {
|
||||
return this.http.get<Log[]>(SERVER_API_URL + 'management/logs', { observe: 'response' });
|
||||
}
|
||||
}
|
56
src/main/webapp/app/admin/metrics/metrics.component.html
Normal file
56
src/main/webapp/app/admin/metrics/metrics.component.html
Normal file
@ -0,0 +1,56 @@
|
||||
<div>
|
||||
<h2>
|
||||
<span id="metrics-page-heading" jhiTranslate="metrics.title">Application Metrics</span>
|
||||
<button class="btn btn-primary float-right" (click)="refresh()">
|
||||
<fa-icon [icon]="'sync'"></fa-icon> <span jhiTranslate="metrics.refresh.button">Refresh</span>
|
||||
</button>
|
||||
</h2>
|
||||
|
||||
<h3 jhiTranslate="metrics.jvm.title">JVM Metrics</h3>
|
||||
<div class="row" *ngIf="!updatingMetrics">
|
||||
<jhi-jvm-memory
|
||||
class="col-md-4"
|
||||
[updating]="updatingMetrics"
|
||||
[jvmMemoryMetrics]="metrics.jvm">
|
||||
</jhi-jvm-memory>
|
||||
<jhi-jvm-threads class="col-md-4" [threadData]="threadData"></jhi-jvm-threads>
|
||||
<jhi-metrics-system
|
||||
class="col-md-4"
|
||||
[updating]="updatingMetrics"
|
||||
[systemMetrics]="metrics.processMetrics">
|
||||
</jhi-metrics-system>
|
||||
</div>
|
||||
|
||||
<div *ngIf="isObjectExisting(metrics, 'garbageCollector')">
|
||||
<h3 jhiTranslate="metrics.jvm.gc.title">Garbage collector statistics</h3>
|
||||
<jhi-metrics-garbagecollector [updating]="updatingMetrics" [garbageCollectorMetrics]="metrics.garbageCollector"></jhi-metrics-garbagecollector>
|
||||
</div>
|
||||
|
||||
<div class="well well-lg" *ngIf="updatingMetrics" jhiTranslate="metrics.updating">Updating...</div>
|
||||
|
||||
<jhi-metrics-request
|
||||
*ngIf="isObjectExisting(metrics, 'http.server.requests')"
|
||||
[updating]="updatingMetrics"
|
||||
[requestMetrics]="metrics['http.server.requests']">
|
||||
</jhi-metrics-request>
|
||||
|
||||
<div >
|
||||
<jhi-metrics-endpoints-requests
|
||||
*ngIf="isObjectExisting(metrics, 'services')"
|
||||
[updating]="updatingMetrics"
|
||||
[endpointsRequestsMetrics]="metrics.services">
|
||||
</jhi-metrics-endpoints-requests>
|
||||
|
||||
<jhi-metrics-cache
|
||||
*ngIf="isObjectExisting(metrics, 'cache')"
|
||||
[updating]="updatingMetrics"
|
||||
[cacheMetrics]="metrics.cache">
|
||||
</jhi-metrics-cache>
|
||||
|
||||
<jhi-metrics-datasource
|
||||
*ngIf="isObjectExistingAndNotEmpty(metrics, 'databases')"
|
||||
[updating]="updatingMetrics"
|
||||
[datasourceMetrics]="metrics.databases">
|
||||
</jhi-metrics-datasource>
|
||||
|
||||
</div>
|
42
src/main/webapp/app/admin/metrics/metrics.component.ts
Normal file
42
src/main/webapp/app/admin/metrics/metrics.component.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { JhiMetricsService } from './metrics.service';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-metrics',
|
||||
templateUrl: './metrics.component.html'
|
||||
})
|
||||
export class JhiMetricsMonitoringComponent implements OnInit {
|
||||
metrics: any = {};
|
||||
threadData: any = {};
|
||||
updatingMetrics = true;
|
||||
JCACHE_KEY: string;
|
||||
|
||||
constructor(private modalService: NgbModal, private metricsService: JhiMetricsService) {
|
||||
this.JCACHE_KEY = 'jcache.statistics';
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.refresh();
|
||||
}
|
||||
|
||||
refresh() {
|
||||
this.updatingMetrics = true;
|
||||
this.metricsService.getMetrics().subscribe(metrics => {
|
||||
this.metrics = metrics;
|
||||
this.metricsService.threadDump().subscribe(data => {
|
||||
this.threadData = data.threads;
|
||||
this.updatingMetrics = false;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isObjectExisting(metrics: any, key: string) {
|
||||
return metrics && metrics[key];
|
||||
}
|
||||
|
||||
isObjectExistingAndNotEmpty(metrics: any, key: string) {
|
||||
return this.isObjectExisting(metrics, key) && JSON.stringify(metrics[key]) !== '{}';
|
||||
}
|
||||
}
|
11
src/main/webapp/app/admin/metrics/metrics.route.ts
Normal file
11
src/main/webapp/app/admin/metrics/metrics.route.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { JhiMetricsMonitoringComponent } from './metrics.component';
|
||||
|
||||
export const metricsRoute: Route = {
|
||||
path: 'jhi-metrics',
|
||||
component: JhiMetricsMonitoringComponent,
|
||||
data: {
|
||||
pageTitle: 'metrics.title'
|
||||
}
|
||||
};
|
18
src/main/webapp/app/admin/metrics/metrics.service.ts
Normal file
18
src/main/webapp/app/admin/metrics/metrics.service.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class JhiMetricsService {
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
getMetrics(): Observable<any> {
|
||||
return this.http.get(SERVER_API_URL + 'management/jhi-metrics');
|
||||
}
|
||||
|
||||
threadDump(): Observable<any> {
|
||||
return this.http.get(SERVER_API_URL + 'management/threaddump');
|
||||
}
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
<form name="deleteForm" (ngSubmit)="confirmDelete(user.login)">
|
||||
<div class="modal-header">
|
||||
<h4 class="modal-title" jhiTranslate="entity.delete.title">Confirm delete operation</h4>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"
|
||||
(click)="clear()">×</button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<jhi-alert-error></jhi-alert-error>
|
||||
<p jhiTranslate="userManagement.delete.question" [translateValues]="{login: user.login}">Are you sure you want to delete this User?</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal" (click)="clear()">
|
||||
<fa-icon [icon]="'ban'"></fa-icon> <span jhiTranslate="entity.action.cancel">Cancel</span>
|
||||
</button>
|
||||
<button type="submit" class="btn btn-danger">
|
||||
<fa-icon [icon]="'times'"></fa-icon> <span jhiTranslate="entity.action.delete">Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
@ -0,0 +1,29 @@
|
||||
import { Component } from '@angular/core';
|
||||
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { JhiEventManager } from 'ng-jhipster';
|
||||
|
||||
import { User, UserService } from 'app/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-user-mgmt-delete-dialog',
|
||||
templateUrl: './user-management-delete-dialog.component.html'
|
||||
})
|
||||
export class UserMgmtDeleteDialogComponent {
|
||||
user: User;
|
||||
|
||||
constructor(private userService: UserService, public activeModal: NgbActiveModal, private eventManager: JhiEventManager) {}
|
||||
|
||||
clear() {
|
||||
this.activeModal.dismiss('cancel');
|
||||
}
|
||||
|
||||
confirmDelete(login) {
|
||||
this.userService.delete(login).subscribe(response => {
|
||||
this.eventManager.broadcast({
|
||||
name: 'userListModification',
|
||||
content: 'Deleted a user'
|
||||
});
|
||||
this.activeModal.dismiss(true);
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8">
|
||||
<div *ngIf="user">
|
||||
<h2>
|
||||
<span jhiTranslate="userManagement.detail.title">User</span> [<b>{{user.login}}</b>]
|
||||
</h2>
|
||||
<dl class="row-md jh-entity-details">
|
||||
<dt><span jhiTranslate="userManagement.login">Login</span></dt>
|
||||
<dd>
|
||||
<span>{{user.login}}</span>
|
||||
<jhi-boolean
|
||||
[value]="user.activated"
|
||||
[textTrue]="'userManagement.activated' | translate"
|
||||
[textFalse]="'userManagement.deactivated' | translate">
|
||||
</jhi-boolean>
|
||||
</dd>
|
||||
<dt><span jhiTranslate="userManagement.firstName">First Name</span></dt>
|
||||
<dd>{{user.firstName}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.lastName">Last Name</span></dt>
|
||||
<dd>{{user.lastName}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.email">Email</span></dt>
|
||||
<dd>{{user.email}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.langKey">Lang Key</span></dt>
|
||||
<dd>{{user.langKey}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.createdBy">Created By</span></dt>
|
||||
<dd>{{user.createdBy}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.createdDate">Created Date</span></dt>
|
||||
<dd>{{user.createdDate | date:'dd/MM/yy HH:mm' }}</dd>
|
||||
<dt><span jhiTranslate="userManagement.lastModifiedBy">Last Modified By</span></dt>
|
||||
<dd>{{user.lastModifiedBy}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.lastModifiedDate">Last Modified Date</span></dt>
|
||||
<dd>{{user.lastModifiedDate | date:'dd/MM/yy HH:mm'}}</dd>
|
||||
<dt><span jhiTranslate="userManagement.profiles">Profiles</span></dt>
|
||||
<dd>
|
||||
<ul class="list-unstyled">
|
||||
<li *ngFor="let authority of user.authorities">
|
||||
<span class="badge badge-info">{{authority}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</dd>
|
||||
</dl>
|
||||
<button type="submit"
|
||||
routerLink="../../"
|
||||
class="btn btn-info">
|
||||
<fa-icon [icon]="'arrow-left'"></fa-icon> <span jhiTranslate="entity.action.back"> Back</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,20 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { User } from 'app/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-user-mgmt-detail',
|
||||
templateUrl: './user-management-detail.component.html'
|
||||
})
|
||||
export class UserMgmtDetailComponent implements OnInit {
|
||||
user: User;
|
||||
|
||||
constructor(private route: ActivatedRoute) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.route.data.subscribe(({ user }) => {
|
||||
this.user = user.body ? user.body : user;
|
||||
});
|
||||
}
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8">
|
||||
<form name="editForm" role="form" novalidate (ngSubmit)="save()" #editForm="ngForm">
|
||||
<h2 id="myUserLabel" jhiTranslate="userManagement.home.createOrEditLabel">
|
||||
Create or edit a User
|
||||
</h2>
|
||||
<div>
|
||||
<jhi-alert-error></jhi-alert-error>
|
||||
<div class="form-group" [hidden]="!user.id">
|
||||
<label jhiTranslate="global.field.id">ID</label>
|
||||
<input type="text" class="form-control" name="id"
|
||||
[(ngModel)]="user.id" readonly>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" jhiTranslate="userManagement.login">Login</label>
|
||||
<input type="text" class="form-control" name="login" #loginInput="ngModel"
|
||||
[(ngModel)]="user.login" required minlength="1" maxlength="50" pattern="^[_.@A-Za-z0-9-]*$">
|
||||
|
||||
<div *ngIf="loginInput.dirty && loginInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="loginInput.errors.required" jhiTranslate="entity.validation.required">
|
||||
This field is required.
|
||||
</small>
|
||||
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="loginInput.errors.maxlength" jhiTranslate="entity.validation.maxlength"
|
||||
[translateValues]="{max: 50}">
|
||||
This field cannot be longer than 50 characters.
|
||||
</small>
|
||||
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="loginInput.errors.pattern" jhiTranslate="entity.validation.patternLogin">
|
||||
This field can only contain letters, digits and e-mail addresses.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" jhiTranslate="userManagement.firstName">First Name</label>
|
||||
<input type="text" class="form-control" name="firstName" #firstNameInput="ngModel"
|
||||
[(ngModel)]="user.firstName" maxlength="50">
|
||||
|
||||
<div *ngIf="firstNameInput.dirty && firstNameInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="firstNameInput.errors.maxlength" jhiTranslate="entity.validation.maxlength"
|
||||
[translateValues]="{max: 50}">
|
||||
This field cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label jhiTranslate="userManagement.lastName">Last Name</label>
|
||||
<input type="text" class="form-control" name="lastName" #lastNameInput="ngModel"
|
||||
[(ngModel)]="user.lastName" maxlength="50">
|
||||
|
||||
<div *ngIf="lastNameInput.dirty && lastNameInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="lastNameInput.errors.maxlength" jhiTranslate="entity.validation.maxlength"
|
||||
[translateValues]="{max: 50}">
|
||||
This field cannot be longer than 50 characters.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-control-label" jhiTranslate="userManagement.email">Email</label>
|
||||
<input type="email" class="form-control" name="email" #emailInput="ngModel"
|
||||
[(ngModel)]="user.email" minlength="5" required maxlength="254" email>
|
||||
|
||||
<div *ngIf="emailInput.dirty && emailInput.invalid">
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.required" jhiTranslate="entity.validation.required">
|
||||
This field is required.
|
||||
</small>
|
||||
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.maxlength" jhiTranslate="entity.validation.maxlength"
|
||||
[translateValues]="{max: 100}">
|
||||
This field cannot be longer than 100 characters.
|
||||
</small>
|
||||
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.minlength" jhiTranslate="entity.validation.minlength"
|
||||
[translateValues]="{min: 5}">
|
||||
This field is required to be at least 5 characters.
|
||||
</small>
|
||||
|
||||
<small class="form-text text-danger"
|
||||
*ngIf="emailInput.errors.email" jhiTranslate="global.messages.validate.email.invalid">
|
||||
Your email is invalid.
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<label class="form-check-label" for="activated">
|
||||
<input class="form-check-input" [disabled]="user.id === null" type="checkbox" id="activated" name="activated" [(ngModel)]="user.activated">
|
||||
<span jhiTranslate="userManagement.activated">Activated</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="form-group" *ngIf="languages && languages.length > 0">
|
||||
<label jhiTranslate="userManagement.langKey">Lang Key</label>
|
||||
<select class="form-control" id="langKey" name="langKey" [(ngModel)]="user.langKey">
|
||||
<option *ngFor="let language of languages" [value]="language">{{language | findLanguageFromKey}}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label jhiTranslate="userManagement.profiles">Profiles</label>
|
||||
<select class="form-control" multiple name="authority" [(ngModel)]="user.authorities">
|
||||
<option *ngFor="let authority of authorities" [value]="authority">{{authority}}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-secondary" (click)="previousState()">
|
||||
<fa-icon [icon]="'ban'"></fa-icon> <span
|
||||
jhiTranslate="entity.action.cancel">Cancel</span>
|
||||
</button>
|
||||
<button type="submit" [disabled]="editForm.form.invalid || isSaving" class="btn btn-primary">
|
||||
<fa-icon [icon]="'save'"></fa-icon> <span jhiTranslate="entity.action.save">Save</span>
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,58 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
|
||||
import { JhiLanguageHelper, User, UserService } from 'app/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-user-mgmt-update',
|
||||
templateUrl: './user-management-update.component.html'
|
||||
})
|
||||
export class UserMgmtUpdateComponent implements OnInit {
|
||||
user: User;
|
||||
languages: any[];
|
||||
authorities: any[];
|
||||
isSaving: boolean;
|
||||
|
||||
constructor(
|
||||
private languageHelper: JhiLanguageHelper,
|
||||
private userService: UserService,
|
||||
private route: ActivatedRoute,
|
||||
private router: Router
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.isSaving = false;
|
||||
this.route.data.subscribe(({ user }) => {
|
||||
this.user = user.body ? user.body : user;
|
||||
});
|
||||
this.authorities = [];
|
||||
this.userService.authorities().subscribe(authorities => {
|
||||
this.authorities = authorities;
|
||||
});
|
||||
this.languageHelper.getAll().then(languages => {
|
||||
this.languages = languages;
|
||||
});
|
||||
}
|
||||
|
||||
previousState() {
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
save() {
|
||||
this.isSaving = true;
|
||||
if (this.user.id !== null) {
|
||||
this.userService.update(this.user).subscribe(response => this.onSaveSuccess(response), () => this.onSaveError());
|
||||
} else {
|
||||
this.userService.create(this.user).subscribe(response => this.onSaveSuccess(response), () => this.onSaveError());
|
||||
}
|
||||
}
|
||||
|
||||
private onSaveSuccess(result) {
|
||||
this.isSaving = false;
|
||||
this.previousState();
|
||||
}
|
||||
|
||||
private onSaveError() {
|
||||
this.isSaving = false;
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
<div>
|
||||
<h2>
|
||||
<span id="user-management-page-heading" jhiTranslate="userManagement.home.title">Users</span>
|
||||
<button class="btn btn-primary float-right jh-create-entity" [routerLink]="['./new']">
|
||||
<fa-icon [icon]="'plus'"></fa-icon> <span jhiTranslate="userManagement.home.createLabel">Create a new User</span>
|
||||
</button>
|
||||
</h2>
|
||||
<jhi-alert></jhi-alert>
|
||||
<div class="table-responsive" *ngIf="users">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr jhiSort [(predicate)]="predicate" [(ascending)]="reverse" [callback]="transition.bind(this)">
|
||||
<th jhiSortBy="id"><span jhiTranslate="global.field.id">ID</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th jhiSortBy="login"><span jhiTranslate="userManagement.login">Login</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th jhiSortBy="email"><span jhiTranslate="userManagement.email">Email</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th></th>
|
||||
<th jhiSortBy="langKey"> <span jhiTranslate="userManagement.langKey">Lang Key</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th><span jhiTranslate="userManagement.profiles">Profiles</span></th>
|
||||
<th jhiSortBy="createdDate"><span jhiTranslate="userManagement.createdDate">Created Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th jhiSortBy="lastModifiedBy"><span jhiTranslate="userManagement.lastModifiedBy">Last Modified By</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th jhiSortBy="lastModifiedDate"><span jhiTranslate="userManagement.lastModifiedDate">Last Modified Date</span> <fa-icon [icon]="'sort'"></fa-icon></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody *ngIf ="users">
|
||||
<tr *ngFor="let user of users; trackBy: trackIdentity">
|
||||
<td><a [routerLink]="['./', user.login, 'view']">{{user.id}}</a></td>
|
||||
<td>{{user.login}}</td>
|
||||
<td>{{user.email}}</td>
|
||||
<td>
|
||||
<button class="btn btn-danger btn-sm" (click)="setActive(user, true)" *ngIf="!user.activated"
|
||||
jhiTranslate="userManagement.deactivated">Deactivated</button>
|
||||
<button class="btn btn-success btn-sm" (click)="setActive(user, false)" *ngIf="user.activated"
|
||||
[disabled]="currentAccount.login === user.login" jhiTranslate="userManagement.activated">Activated</button>
|
||||
</td>
|
||||
<td>{{user.langKey}}</td>
|
||||
<td>
|
||||
<div *ngFor="let authority of user.authorities">
|
||||
<span class="badge badge-info">{{ authority }}</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{user.createdDate | date:'dd/MM/yy HH:mm'}}</td>
|
||||
<td>{{user.lastModifiedBy}}</td>
|
||||
<td>{{user.lastModifiedDate | date:'dd/MM/yy HH:mm'}}</td>
|
||||
<td class="text-right">
|
||||
<div class="btn-group flex-btn-group-container">
|
||||
<button type="submit"
|
||||
[routerLink]="['./', user.login, 'view']"
|
||||
class="btn btn-info btn-sm">
|
||||
<fa-icon [icon]="'eye'"></fa-icon>
|
||||
<span class="d-none d-md-inline" jhiTranslate="entity.action.view">View</span>
|
||||
</button>
|
||||
<button type="submit"
|
||||
[routerLink]="['./', user.login, 'edit']"
|
||||
queryParamsHandling="merge"
|
||||
class="btn btn-primary btn-sm">
|
||||
<fa-icon [icon]="'pencil-alt'"></fa-icon>
|
||||
<span class="d-none d-md-inline" jhiTranslate="entity.action.edit">Edit</span>
|
||||
</button>
|
||||
<button type="button" (click)="deleteUser(user)"
|
||||
class="btn btn-danger btn-sm" [disabled]="currentAccount.login === user.login">
|
||||
<fa-icon [icon]="'times'"></fa-icon>
|
||||
<span class="d-none d-md-inline" jhiTranslate="entity.action.delete">Delete</span>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div *ngIf="users">
|
||||
<div class="row justify-content-center">
|
||||
<jhi-item-count [page]="page" [total]="totalItems" [itemsPerPage]="itemsPerPage"></jhi-item-count>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<ngb-pagination [collectionSize]="totalItems" [(page)]="page" [pageSize]="itemsPerPage" [maxSize]="5" [rotate]="true" [boundaryLinks]="true" (pageChange)="loadPage(page)"></ngb-pagination>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -0,0 +1,144 @@
|
||||
import { Component, OnInit, OnDestroy } from '@angular/core';
|
||||
import { HttpResponse } from '@angular/common/http';
|
||||
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { ActivatedRoute, Router } from '@angular/router';
|
||||
import { JhiEventManager, JhiParseLinks, JhiAlertService } from 'ng-jhipster';
|
||||
|
||||
import { ITEMS_PER_PAGE } from 'app/shared';
|
||||
import { AccountService, UserService, User } from 'app/core';
|
||||
import { UserMgmtDeleteDialogComponent } from 'app/admin';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-user-mgmt',
|
||||
templateUrl: './user-management.component.html'
|
||||
})
|
||||
export class UserMgmtComponent implements OnInit, OnDestroy {
|
||||
currentAccount: any;
|
||||
users: User[];
|
||||
error: any;
|
||||
success: any;
|
||||
routeData: any;
|
||||
links: any;
|
||||
totalItems: any;
|
||||
itemsPerPage: any;
|
||||
page: any;
|
||||
predicate: any;
|
||||
previousPage: any;
|
||||
reverse: any;
|
||||
|
||||
constructor(
|
||||
private userService: UserService,
|
||||
private alertService: JhiAlertService,
|
||||
private accountService: AccountService,
|
||||
private parseLinks: JhiParseLinks,
|
||||
private activatedRoute: ActivatedRoute,
|
||||
private router: Router,
|
||||
private eventManager: JhiEventManager,
|
||||
private modalService: NgbModal
|
||||
) {
|
||||
this.itemsPerPage = ITEMS_PER_PAGE;
|
||||
this.routeData = this.activatedRoute.data.subscribe(data => {
|
||||
this.page = data['pagingParams'].page;
|
||||
this.previousPage = data['pagingParams'].page;
|
||||
this.reverse = data['pagingParams'].ascending;
|
||||
this.predicate = data['pagingParams'].predicate;
|
||||
});
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.accountService.identity().then(account => {
|
||||
this.currentAccount = account;
|
||||
this.loadAll();
|
||||
this.registerChangeInUsers();
|
||||
});
|
||||
}
|
||||
|
||||
ngOnDestroy() {
|
||||
this.routeData.unsubscribe();
|
||||
}
|
||||
|
||||
registerChangeInUsers() {
|
||||
this.eventManager.subscribe('userListModification', response => this.loadAll());
|
||||
}
|
||||
|
||||
setActive(user, isActivated) {
|
||||
user.activated = isActivated;
|
||||
|
||||
this.userService.update(user).subscribe(response => {
|
||||
if (response.status === 200) {
|
||||
this.error = null;
|
||||
this.success = 'OK';
|
||||
this.loadAll();
|
||||
} else {
|
||||
this.success = null;
|
||||
this.error = 'ERROR';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
loadAll() {
|
||||
this.userService
|
||||
.query({
|
||||
page: this.page - 1,
|
||||
size: this.itemsPerPage,
|
||||
sort: this.sort()
|
||||
})
|
||||
.subscribe(
|
||||
(res: HttpResponse<User[]>) => this.onSuccess(res.body, res.headers),
|
||||
(res: HttpResponse<any>) => this.onError(res.body)
|
||||
);
|
||||
}
|
||||
|
||||
trackIdentity(index, item: User) {
|
||||
return item.id;
|
||||
}
|
||||
|
||||
sort() {
|
||||
const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')];
|
||||
if (this.predicate !== 'id') {
|
||||
result.push('id');
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
loadPage(page: number) {
|
||||
if (page !== this.previousPage) {
|
||||
this.previousPage = page;
|
||||
this.transition();
|
||||
}
|
||||
}
|
||||
|
||||
transition() {
|
||||
this.router.navigate(['/admin/user-management'], {
|
||||
queryParams: {
|
||||
page: this.page,
|
||||
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc')
|
||||
}
|
||||
});
|
||||
this.loadAll();
|
||||
}
|
||||
|
||||
deleteUser(user: User) {
|
||||
const modalRef = this.modalService.open(UserMgmtDeleteDialogComponent, { size: 'lg', backdrop: 'static' });
|
||||
modalRef.componentInstance.user = user;
|
||||
modalRef.result.then(
|
||||
result => {
|
||||
// Left blank intentionally, nothing to do here
|
||||
},
|
||||
reason => {
|
||||
// Left blank intentionally, nothing to do here
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
private onSuccess(data, headers) {
|
||||
this.links = this.parseLinks.parse(headers.get('link'));
|
||||
this.totalItems = headers.get('X-Total-Count');
|
||||
this.users = data;
|
||||
}
|
||||
|
||||
private onError(error) {
|
||||
this.alertService.error(error.error, error.message, null);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Resolve, ActivatedRouteSnapshot, RouterStateSnapshot, Routes, CanActivate } from '@angular/router';
|
||||
import { JhiPaginationUtil, JhiResolvePagingParams } from 'ng-jhipster';
|
||||
|
||||
import { AccountService, User, UserService } from 'app/core';
|
||||
import { UserMgmtComponent } from './user-management.component';
|
||||
import { UserMgmtDetailComponent } from './user-management-detail.component';
|
||||
import { UserMgmtUpdateComponent } from './user-management-update.component';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserResolve implements CanActivate {
|
||||
constructor(private accountService: AccountService) {}
|
||||
|
||||
canActivate() {
|
||||
return this.accountService.identity().then(account => this.accountService.hasAnyAuthority(['ROLE_ADMIN']));
|
||||
}
|
||||
}
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserMgmtResolve implements Resolve<any> {
|
||||
constructor(private service: UserService) {}
|
||||
|
||||
resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
|
||||
const id = route.params['login'] ? route.params['login'] : null;
|
||||
if (id) {
|
||||
return this.service.find(id);
|
||||
}
|
||||
return new User();
|
||||
}
|
||||
}
|
||||
|
||||
export const userMgmtRoute: Routes = [
|
||||
{
|
||||
path: 'user-management',
|
||||
component: UserMgmtComponent,
|
||||
resolve: {
|
||||
pagingParams: JhiResolvePagingParams
|
||||
},
|
||||
data: {
|
||||
pageTitle: 'userManagement.home.title',
|
||||
defaultSort: 'id,asc'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'user-management/:login/view',
|
||||
component: UserMgmtDetailComponent,
|
||||
resolve: {
|
||||
user: UserMgmtResolve
|
||||
},
|
||||
data: {
|
||||
pageTitle: 'userManagement.home.title'
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'user-management/new',
|
||||
component: UserMgmtUpdateComponent,
|
||||
resolve: {
|
||||
user: UserMgmtResolve
|
||||
}
|
||||
},
|
||||
{
|
||||
path: 'user-management/:login/edit',
|
||||
component: UserMgmtUpdateComponent,
|
||||
resolve: {
|
||||
user: UserMgmtResolve
|
||||
}
|
||||
}
|
||||
];
|
23
src/main/webapp/app/app-routing.module.ts
Normal file
23
src/main/webapp/app/app-routing.module.ts
Normal file
@ -0,0 +1,23 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
import { errorRoute, navbarRoute } from './layouts';
|
||||
import { DEBUG_INFO_ENABLED } from 'app/app.constants';
|
||||
|
||||
const LAYOUT_ROUTES = [navbarRoute, ...errorRoute];
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forRoot(
|
||||
[
|
||||
{
|
||||
path: 'admin',
|
||||
loadChildren: './admin/admin.module#HsadminNgAdminModule'
|
||||
},
|
||||
...LAYOUT_ROUTES
|
||||
],
|
||||
{ useHash: true, enableTracing: DEBUG_INFO_ENABLED }
|
||||
)
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class HsadminNgAppRoutingModule {}
|
8
src/main/webapp/app/app.constants.ts
Normal file
8
src/main/webapp/app/app.constants.ts
Normal file
@ -0,0 +1,8 @@
|
||||
// These constants are injected via webpack environment variables.
|
||||
// You can add more variables in webpack.common.js or in profile specific webpack.<dev|prod>.js files.
|
||||
// If you change the values in the webpack config files, you need to re run webpack to update the application
|
||||
|
||||
export const VERSION = process.env.VERSION;
|
||||
export const DEBUG_INFO_ENABLED: boolean = !!process.env.DEBUG_INFO_ENABLED;
|
||||
export const SERVER_API_URL = process.env.SERVER_API_URL;
|
||||
export const BUILD_TIMESTAMP = process.env.BUILD_TIMESTAMP;
|
14
src/main/webapp/app/app.main.ts
Normal file
14
src/main/webapp/app/app.main.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||||
import { ProdConfig } from './blocks/config/prod.config';
|
||||
import { HsadminNgAppModule } from './app.module';
|
||||
|
||||
ProdConfig();
|
||||
|
||||
if (module['hot']) {
|
||||
module['hot'].accept();
|
||||
}
|
||||
|
||||
platformBrowserDynamic()
|
||||
.bootstrapModule(HsadminNgAppModule, { preserveWhitespaces: true })
|
||||
.then(success => console.log(`Application started`))
|
||||
.catch(err => console.error(err));
|
72
src/main/webapp/app/app.module.ts
Normal file
72
src/main/webapp/app/app.module.ts
Normal file
@ -0,0 +1,72 @@
|
||||
import './vendor.ts';
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { HTTP_INTERCEPTORS } from '@angular/common/http';
|
||||
import { NgbDatepickerConfig } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { Ng2Webstorage } from 'ngx-webstorage';
|
||||
import { NgJhipsterModule } from 'ng-jhipster';
|
||||
|
||||
import { AuthInterceptor } from './blocks/interceptor/auth.interceptor';
|
||||
import { AuthExpiredInterceptor } from './blocks/interceptor/auth-expired.interceptor';
|
||||
import { ErrorHandlerInterceptor } from './blocks/interceptor/errorhandler.interceptor';
|
||||
import { NotificationInterceptor } from './blocks/interceptor/notification.interceptor';
|
||||
import { HsadminNgSharedModule } from 'app/shared';
|
||||
import { HsadminNgCoreModule } from 'app/core';
|
||||
import { HsadminNgAppRoutingModule } from './app-routing.module';
|
||||
import { HsadminNgHomeModule } from './home/home.module';
|
||||
import { HsadminNgAccountModule } from './account/account.module';
|
||||
import { HsadminNgEntityModule } from './entities/entity.module';
|
||||
import * as moment from 'moment';
|
||||
// jhipster-needle-angular-add-module-import JHipster will add new module here
|
||||
import { JhiMainComponent, NavbarComponent, FooterComponent, PageRibbonComponent, ActiveMenuDirective, ErrorComponent } from './layouts';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
BrowserModule,
|
||||
Ng2Webstorage.forRoot({ prefix: 'jhi', separator: '-' }),
|
||||
NgJhipsterModule.forRoot({
|
||||
// set below to true to make alerts look like toast
|
||||
alertAsToast: false,
|
||||
alertTimeout: 5000,
|
||||
i18nEnabled: true,
|
||||
defaultI18nLang: 'de'
|
||||
}),
|
||||
HsadminNgSharedModule.forRoot(),
|
||||
HsadminNgCoreModule,
|
||||
HsadminNgHomeModule,
|
||||
HsadminNgAccountModule,
|
||||
// jhipster-needle-angular-add-module JHipster will add new module here
|
||||
HsadminNgEntityModule,
|
||||
HsadminNgAppRoutingModule
|
||||
],
|
||||
declarations: [JhiMainComponent, NavbarComponent, ErrorComponent, PageRibbonComponent, ActiveMenuDirective, FooterComponent],
|
||||
providers: [
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: AuthInterceptor,
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: AuthExpiredInterceptor,
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: ErrorHandlerInterceptor,
|
||||
multi: true
|
||||
},
|
||||
{
|
||||
provide: HTTP_INTERCEPTORS,
|
||||
useClass: NotificationInterceptor,
|
||||
multi: true
|
||||
}
|
||||
],
|
||||
bootstrap: [JhiMainComponent]
|
||||
})
|
||||
export class HsadminNgAppModule {
|
||||
constructor(private dpConfig: NgbDatepickerConfig) {
|
||||
this.dpConfig.minDate = { year: moment().year() - 100, month: 1, day: 1 };
|
||||
}
|
||||
}
|
9
src/main/webapp/app/blocks/config/prod.config.ts
Normal file
9
src/main/webapp/app/blocks/config/prod.config.ts
Normal file
@ -0,0 +1,9 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
import { DEBUG_INFO_ENABLED } from 'app/app.constants';
|
||||
|
||||
export function ProdConfig() {
|
||||
// disable debug data on prod profile to improve performance
|
||||
if (!DEBUG_INFO_ENABLED) {
|
||||
enableProdMode();
|
||||
}
|
||||
}
|
14
src/main/webapp/app/blocks/config/uib-pagination.config.ts
Normal file
14
src/main/webapp/app/blocks/config/uib-pagination.config.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NgbPaginationConfig } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { ITEMS_PER_PAGE } from 'app/shared';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class PaginationConfig {
|
||||
// tslint:disable-next-line: no-unused-variable
|
||||
constructor(private config: NgbPaginationConfig) {
|
||||
config.boundaryLinks = true;
|
||||
config.maxSize = 5;
|
||||
config.pageSize = ITEMS_PER_PAGE;
|
||||
config.size = 'sm';
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
import { LoginService } from 'app/core/login/login.service';
|
||||
|
||||
@Injectable()
|
||||
export class AuthExpiredInterceptor implements HttpInterceptor {
|
||||
constructor(private loginService: LoginService) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(request).pipe(
|
||||
tap(
|
||||
(event: HttpEvent<any>) => {},
|
||||
(err: any) => {
|
||||
if (err instanceof HttpErrorResponse) {
|
||||
if (err.status === 401) {
|
||||
this.loginService.logout();
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
27
src/main/webapp/app/blocks/interceptor/auth.interceptor.ts
Normal file
27
src/main/webapp/app/blocks/interceptor/auth.interceptor.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { LocalStorageService, SessionStorageService } from 'ngx-webstorage';
|
||||
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable()
|
||||
export class AuthInterceptor implements HttpInterceptor {
|
||||
constructor(private localStorage: LocalStorageService, private sessionStorage: SessionStorageService) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
if (!request || !request.url || (/^http/.test(request.url) && !(SERVER_API_URL && request.url.startsWith(SERVER_API_URL)))) {
|
||||
return next.handle(request);
|
||||
}
|
||||
|
||||
const token = this.localStorage.retrieve('authenticationToken') || this.sessionStorage.retrieve('authenticationToken');
|
||||
if (!!token) {
|
||||
request = request.clone({
|
||||
setHeaders: {
|
||||
Authorization: 'Bearer ' + token
|
||||
}
|
||||
});
|
||||
}
|
||||
return next.handle(request);
|
||||
}
|
||||
}
|
@ -0,0 +1,25 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { JhiEventManager } from 'ng-jhipster';
|
||||
import { HttpInterceptor, HttpRequest, HttpErrorResponse, HttpHandler, HttpEvent } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class ErrorHandlerInterceptor implements HttpInterceptor {
|
||||
constructor(private eventManager: JhiEventManager) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(request).pipe(
|
||||
tap(
|
||||
(event: HttpEvent<any>) => {},
|
||||
(err: any) => {
|
||||
if (err instanceof HttpErrorResponse) {
|
||||
if (!(err.status === 401 && (err.message === '' || (err.url && err.url.includes('/api/account'))))) {
|
||||
this.eventManager.broadcast({ name: 'hsadminNgApp.httpError', content: err });
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import { JhiAlertService } from 'ng-jhipster';
|
||||
import { HttpInterceptor, HttpRequest, HttpResponse, HttpHandler, HttpEvent } from '@angular/common/http';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { tap } from 'rxjs/operators';
|
||||
|
||||
@Injectable()
|
||||
export class NotificationInterceptor implements HttpInterceptor {
|
||||
constructor(private alertService: JhiAlertService) {}
|
||||
|
||||
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
|
||||
return next.handle(request).pipe(
|
||||
tap(
|
||||
(event: HttpEvent<any>) => {
|
||||
if (event instanceof HttpResponse) {
|
||||
const arr = event.headers.keys();
|
||||
let alert = null;
|
||||
let alertParams = null;
|
||||
arr.forEach(entry => {
|
||||
if (entry.toLowerCase().endsWith('app-alert')) {
|
||||
alert = event.headers.get(entry);
|
||||
} else if (entry.toLowerCase().endsWith('app-params')) {
|
||||
alertParams = event.headers.get(entry);
|
||||
}
|
||||
});
|
||||
if (alert) {
|
||||
if (typeof alert === 'string') {
|
||||
this.alertService.success(alert, { param: alertParams }, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
(err: any) => {}
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
114
src/main/webapp/app/core/auth/account.service.ts
Normal file
114
src/main/webapp/app/core/auth/account.service.ts
Normal file
@ -0,0 +1,114 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { JhiLanguageService } from 'ng-jhipster';
|
||||
import { SessionStorageService } from 'ngx-webstorage';
|
||||
import { HttpClient, HttpResponse } from '@angular/common/http';
|
||||
import { Observable, Subject } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
import { Account } from 'app/core/user/account.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AccountService {
|
||||
private userIdentity: any;
|
||||
private authenticated = false;
|
||||
private authenticationState = new Subject<any>();
|
||||
|
||||
constructor(private languageService: JhiLanguageService, private sessionStorage: SessionStorageService, private http: HttpClient) {}
|
||||
|
||||
fetch(): Observable<HttpResponse<Account>> {
|
||||
return this.http.get<Account>(SERVER_API_URL + 'api/account', { observe: 'response' });
|
||||
}
|
||||
|
||||
save(account: any): Observable<HttpResponse<any>> {
|
||||
return this.http.post(SERVER_API_URL + 'api/account', account, { observe: 'response' });
|
||||
}
|
||||
|
||||
authenticate(identity) {
|
||||
this.userIdentity = identity;
|
||||
this.authenticated = identity !== null;
|
||||
this.authenticationState.next(this.userIdentity);
|
||||
}
|
||||
|
||||
hasAnyAuthority(authorities: string[]): boolean {
|
||||
if (!this.authenticated || !this.userIdentity || !this.userIdentity.authorities) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (let i = 0; i < authorities.length; i++) {
|
||||
if (this.userIdentity.authorities.includes(authorities[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
hasAuthority(authority: string): Promise<boolean> {
|
||||
if (!this.authenticated) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return this.identity().then(
|
||||
id => {
|
||||
return Promise.resolve(id.authorities && id.authorities.includes(authority));
|
||||
},
|
||||
() => {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
identity(force?: boolean): Promise<any> {
|
||||
if (force) {
|
||||
this.userIdentity = undefined;
|
||||
}
|
||||
|
||||
// check and see if we have retrieved the userIdentity data from the server.
|
||||
// if we have, reuse it by immediately resolving
|
||||
if (this.userIdentity) {
|
||||
return Promise.resolve(this.userIdentity);
|
||||
}
|
||||
|
||||
// retrieve the userIdentity data from the server, update the identity object, and then resolve.
|
||||
return this.fetch()
|
||||
.toPromise()
|
||||
.then(response => {
|
||||
const account = response.body;
|
||||
if (account) {
|
||||
this.userIdentity = account;
|
||||
this.authenticated = true;
|
||||
// After retrieve the account info, the language will be changed to
|
||||
// the user's preferred language configured in the account setting
|
||||
const langKey = this.sessionStorage.retrieve('locale') || this.userIdentity.langKey;
|
||||
this.languageService.changeLanguage(langKey);
|
||||
} else {
|
||||
this.userIdentity = null;
|
||||
this.authenticated = false;
|
||||
}
|
||||
this.authenticationState.next(this.userIdentity);
|
||||
return this.userIdentity;
|
||||
})
|
||||
.catch(err => {
|
||||
this.userIdentity = null;
|
||||
this.authenticated = false;
|
||||
this.authenticationState.next(this.userIdentity);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
isAuthenticated(): boolean {
|
||||
return this.authenticated;
|
||||
}
|
||||
|
||||
isIdentityResolved(): boolean {
|
||||
return this.userIdentity !== undefined;
|
||||
}
|
||||
|
||||
getAuthenticationState(): Observable<any> {
|
||||
return this.authenticationState.asObservable();
|
||||
}
|
||||
|
||||
getImageUrl(): string {
|
||||
return this.isIdentityResolved() ? this.userIdentity.imageUrl : null;
|
||||
}
|
||||
}
|
59
src/main/webapp/app/core/auth/auth-jwt.service.ts
Normal file
59
src/main/webapp/app/core/auth/auth-jwt.service.ts
Normal file
@ -0,0 +1,59 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { LocalStorageService, SessionStorageService } from 'ngx-webstorage';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class AuthServerProvider {
|
||||
constructor(private http: HttpClient, private $localStorage: LocalStorageService, private $sessionStorage: SessionStorageService) {}
|
||||
|
||||
getToken() {
|
||||
return this.$localStorage.retrieve('authenticationToken') || this.$sessionStorage.retrieve('authenticationToken');
|
||||
}
|
||||
|
||||
login(credentials): Observable<any> {
|
||||
const data = {
|
||||
username: credentials.username,
|
||||
password: credentials.password,
|
||||
rememberMe: credentials.rememberMe
|
||||
};
|
||||
return this.http.post(SERVER_API_URL + 'api/authenticate', data, { observe: 'response' }).pipe(map(authenticateSuccess.bind(this)));
|
||||
|
||||
function authenticateSuccess(resp) {
|
||||
const bearerToken = resp.headers.get('Authorization');
|
||||
if (bearerToken && bearerToken.slice(0, 7) === 'Bearer ') {
|
||||
const jwt = bearerToken.slice(7, bearerToken.length);
|
||||
this.storeAuthenticationToken(jwt, credentials.rememberMe);
|
||||
return jwt;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
loginWithToken(jwt, rememberMe) {
|
||||
if (jwt) {
|
||||
this.storeAuthenticationToken(jwt, rememberMe);
|
||||
return Promise.resolve(jwt);
|
||||
} else {
|
||||
return Promise.reject('auth-jwt-service Promise reject'); // Put appropriate error message here
|
||||
}
|
||||
}
|
||||
|
||||
storeAuthenticationToken(jwt, rememberMe) {
|
||||
if (rememberMe) {
|
||||
this.$localStorage.store('authenticationToken', jwt);
|
||||
} else {
|
||||
this.$sessionStorage.store('authenticationToken', jwt);
|
||||
}
|
||||
}
|
||||
|
||||
logout(): Observable<any> {
|
||||
return new Observable(observer => {
|
||||
this.$localStorage.clear('authenticationToken');
|
||||
this.$sessionStorage.clear('authenticationToken');
|
||||
observer.complete();
|
||||
});
|
||||
}
|
||||
}
|
11
src/main/webapp/app/core/auth/csrf.service.ts
Normal file
11
src/main/webapp/app/core/auth/csrf.service.ts
Normal file
@ -0,0 +1,11 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CookieService } from 'ngx-cookie';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class CSRFService {
|
||||
constructor(private cookieService: CookieService) {}
|
||||
|
||||
getCSRF(name = 'XSRF-TOKEN') {
|
||||
return this.cookieService.get(name);
|
||||
}
|
||||
}
|
46
src/main/webapp/app/core/auth/state-storage.service.ts
Normal file
46
src/main/webapp/app/core/auth/state-storage.service.ts
Normal file
@ -0,0 +1,46 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { SessionStorageService } from 'ngx-webstorage';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class StateStorageService {
|
||||
constructor(private $sessionStorage: SessionStorageService) {}
|
||||
|
||||
getPreviousState() {
|
||||
return this.$sessionStorage.retrieve('previousState');
|
||||
}
|
||||
|
||||
resetPreviousState() {
|
||||
this.$sessionStorage.clear('previousState');
|
||||
}
|
||||
|
||||
storePreviousState(previousStateName, previousStateParams) {
|
||||
const previousState = { name: previousStateName, params: previousStateParams };
|
||||
this.$sessionStorage.store('previousState', previousState);
|
||||
}
|
||||
|
||||
getDestinationState() {
|
||||
return this.$sessionStorage.retrieve('destinationState');
|
||||
}
|
||||
|
||||
storeUrl(url: string) {
|
||||
this.$sessionStorage.store('previousUrl', url);
|
||||
}
|
||||
|
||||
getUrl() {
|
||||
return this.$sessionStorage.retrieve('previousUrl');
|
||||
}
|
||||
|
||||
storeDestinationState(destinationState, destinationStateParams, fromState) {
|
||||
const destinationInfo = {
|
||||
destination: {
|
||||
name: destinationState.name,
|
||||
data: destinationState.data
|
||||
},
|
||||
params: destinationStateParams,
|
||||
from: {
|
||||
name: fromState.name
|
||||
}
|
||||
};
|
||||
this.$sessionStorage.store('destinationState', destinationInfo);
|
||||
}
|
||||
}
|
52
src/main/webapp/app/core/auth/user-route-access-service.ts
Normal file
52
src/main/webapp/app/core/auth/user-route-access-service.ts
Normal file
@ -0,0 +1,52 @@
|
||||
import { Injectable, isDevMode } from '@angular/core';
|
||||
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
|
||||
|
||||
import { AccountService } from '../';
|
||||
import { LoginModalService } from '../login/login-modal.service';
|
||||
import { StateStorageService } from './state-storage.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserRouteAccessService implements CanActivate {
|
||||
constructor(
|
||||
private router: Router,
|
||||
private loginModalService: LoginModalService,
|
||||
private accountService: AccountService,
|
||||
private stateStorageService: StateStorageService
|
||||
) {}
|
||||
|
||||
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | Promise<boolean> {
|
||||
const authorities = route.data['authorities'];
|
||||
// We need to call the checkLogin / and so the accountService.identity() function, to ensure,
|
||||
// that the client has a principal too, if they already logged in by the server.
|
||||
// This could happen on a page refresh.
|
||||
return this.checkLogin(authorities, state.url);
|
||||
}
|
||||
|
||||
checkLogin(authorities: string[], url: string): Promise<boolean> {
|
||||
return this.accountService.identity().then(account => {
|
||||
if (!authorities || authorities.length === 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (account) {
|
||||
const hasAnyAuthority = this.accountService.hasAnyAuthority(authorities);
|
||||
if (hasAnyAuthority) {
|
||||
return true;
|
||||
}
|
||||
if (isDevMode()) {
|
||||
console.error('User has not any of required authorities: ', authorities);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
this.stateStorageService.storeUrl(url);
|
||||
this.router.navigate(['accessdenied']).then(() => {
|
||||
// only show the login dialog, if the user hasn't logged in yet
|
||||
if (!account) {
|
||||
this.loginModalService.open();
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
}
|
24
src/main/webapp/app/core/core.module.ts
Normal file
24
src/main/webapp/app/core/core.module.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { NgModule, LOCALE_ID } from '@angular/core';
|
||||
import { DatePipe, registerLocaleData } from '@angular/common';
|
||||
import { HttpClientModule } from '@angular/common/http';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import locale from '@angular/common/locales/de';
|
||||
|
||||
@NgModule({
|
||||
imports: [HttpClientModule],
|
||||
exports: [],
|
||||
declarations: [],
|
||||
providers: [
|
||||
Title,
|
||||
{
|
||||
provide: LOCALE_ID,
|
||||
useValue: 'de'
|
||||
},
|
||||
DatePipe
|
||||
]
|
||||
})
|
||||
export class HsadminNgCoreModule {
|
||||
constructor() {
|
||||
registerLocaleData(locale);
|
||||
}
|
||||
}
|
13
src/main/webapp/app/core/index.ts
Normal file
13
src/main/webapp/app/core/index.ts
Normal file
@ -0,0 +1,13 @@
|
||||
export * from './auth/csrf.service';
|
||||
export * from './auth/state-storage.service';
|
||||
export * from './auth/account.service';
|
||||
export * from './auth/auth-jwt.service';
|
||||
export * from './language/language.helper';
|
||||
export * from './language/language.constants';
|
||||
export * from './user/account.model';
|
||||
export * from './user/user.model';
|
||||
export * from './auth/user-route-access-service';
|
||||
export * from './login/login-modal.service';
|
||||
export * from './login/login.service';
|
||||
export * from './user/user.service';
|
||||
export * from './core.module';
|
9
src/main/webapp/app/core/language/language.constants.ts
Normal file
9
src/main/webapp/app/core/language/language.constants.ts
Normal file
@ -0,0 +1,9 @@
|
||||
/*
|
||||
Languages codes are ISO_639-1 codes, see http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
|
||||
They are written in English to avoid character encoding issues (not a perfect solution)
|
||||
*/
|
||||
export const LANGUAGES: string[] = [
|
||||
'de',
|
||||
'en'
|
||||
// jhipster-needle-i18n-language-constant - JHipster will add/remove languages in this array
|
||||
];
|
65
src/main/webapp/app/core/language/language.helper.ts
Normal file
65
src/main/webapp/app/core/language/language.helper.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import { Injectable, RendererFactory2, Renderer2 } from '@angular/core';
|
||||
import { Title } from '@angular/platform-browser';
|
||||
import { Router, ActivatedRouteSnapshot } from '@angular/router';
|
||||
import { TranslateService, LangChangeEvent } from '@ngx-translate/core';
|
||||
import { BehaviorSubject, Observable } from 'rxjs';
|
||||
|
||||
import { LANGUAGES } from 'app/core/language/language.constants';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class JhiLanguageHelper {
|
||||
renderer: Renderer2 = null;
|
||||
private _language: BehaviorSubject<string>;
|
||||
|
||||
constructor(
|
||||
private translateService: TranslateService,
|
||||
private titleService: Title,
|
||||
private router: Router,
|
||||
rootRenderer: RendererFactory2
|
||||
) {
|
||||
this._language = new BehaviorSubject<string>(this.translateService.currentLang);
|
||||
this.renderer = rootRenderer.createRenderer(document.querySelector('html'), null);
|
||||
this.init();
|
||||
}
|
||||
|
||||
getAll(): Promise<any> {
|
||||
return Promise.resolve(LANGUAGES);
|
||||
}
|
||||
|
||||
get language(): Observable<string> {
|
||||
return this._language.asObservable();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the window title using params in the following
|
||||
* order:
|
||||
* 1. titleKey parameter
|
||||
* 2. $state.$current.data.pageTitle (current state page title)
|
||||
* 3. 'global.title'
|
||||
*/
|
||||
updateTitle(titleKey?: string) {
|
||||
if (!titleKey) {
|
||||
titleKey = this.getPageTitle(this.router.routerState.snapshot.root);
|
||||
}
|
||||
|
||||
this.translateService.get(titleKey).subscribe(title => {
|
||||
this.titleService.setTitle(title);
|
||||
});
|
||||
}
|
||||
|
||||
private init() {
|
||||
this.translateService.onLangChange.subscribe((event: LangChangeEvent) => {
|
||||
this._language.next(this.translateService.currentLang);
|
||||
this.renderer.setAttribute(document.querySelector('html'), 'lang', this.translateService.currentLang);
|
||||
this.updateTitle();
|
||||
});
|
||||
}
|
||||
|
||||
private getPageTitle(routeSnapshot: ActivatedRouteSnapshot) {
|
||||
let title: string = routeSnapshot.data && routeSnapshot.data['pageTitle'] ? routeSnapshot.data['pageTitle'] : 'hsadminNgApp';
|
||||
if (routeSnapshot.firstChild) {
|
||||
title = this.getPageTitle(routeSnapshot.firstChild) || title;
|
||||
}
|
||||
return title;
|
||||
}
|
||||
}
|
27
src/main/webapp/app/core/login/login-modal.service.ts
Normal file
27
src/main/webapp/app/core/login/login-modal.service.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
|
||||
import { JhiLoginModalComponent } from 'app/shared/login/login.component';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LoginModalService {
|
||||
private isOpen = false;
|
||||
constructor(private modalService: NgbModal) {}
|
||||
|
||||
open(): NgbModalRef {
|
||||
if (this.isOpen) {
|
||||
return;
|
||||
}
|
||||
this.isOpen = true;
|
||||
const modalRef = this.modalService.open(JhiLoginModalComponent);
|
||||
modalRef.result.then(
|
||||
result => {
|
||||
this.isOpen = false;
|
||||
},
|
||||
reason => {
|
||||
this.isOpen = false;
|
||||
}
|
||||
);
|
||||
return modalRef;
|
||||
}
|
||||
}
|
38
src/main/webapp/app/core/login/login.service.ts
Normal file
38
src/main/webapp/app/core/login/login.service.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
import { AccountService } from 'app/core/auth/account.service';
|
||||
import { AuthServerProvider } from 'app/core/auth/auth-jwt.service';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class LoginService {
|
||||
constructor(private accountService: AccountService, private authServerProvider: AuthServerProvider) {}
|
||||
|
||||
login(credentials, callback?) {
|
||||
const cb = callback || function() {};
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
this.authServerProvider.login(credentials).subscribe(
|
||||
data => {
|
||||
this.accountService.identity(true).then(account => {
|
||||
resolve(data);
|
||||
});
|
||||
return cb();
|
||||
},
|
||||
err => {
|
||||
this.logout();
|
||||
reject(err);
|
||||
return cb(err);
|
||||
}
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
loginWithToken(jwt, rememberMe) {
|
||||
return this.authServerProvider.loginWithToken(jwt, rememberMe);
|
||||
}
|
||||
|
||||
logout() {
|
||||
this.authServerProvider.logout().subscribe();
|
||||
this.accountService.authenticate(null);
|
||||
}
|
||||
}
|
12
src/main/webapp/app/core/user/account.model.ts
Normal file
12
src/main/webapp/app/core/user/account.model.ts
Normal file
@ -0,0 +1,12 @@
|
||||
export class Account {
|
||||
constructor(
|
||||
public activated: boolean,
|
||||
public authorities: string[],
|
||||
public email: string,
|
||||
public firstName: string,
|
||||
public langKey: string,
|
||||
public lastName: string,
|
||||
public login: string,
|
||||
public imageUrl: string
|
||||
) {}
|
||||
}
|
47
src/main/webapp/app/core/user/user.model.ts
Normal file
47
src/main/webapp/app/core/user/user.model.ts
Normal file
@ -0,0 +1,47 @@
|
||||
export interface IUser {
|
||||
id?: any;
|
||||
login?: string;
|
||||
firstName?: string;
|
||||
lastName?: string;
|
||||
email?: string;
|
||||
activated?: boolean;
|
||||
langKey?: string;
|
||||
authorities?: any[];
|
||||
createdBy?: string;
|
||||
createdDate?: Date;
|
||||
lastModifiedBy?: string;
|
||||
lastModifiedDate?: Date;
|
||||
password?: string;
|
||||
}
|
||||
|
||||
export class User implements IUser {
|
||||
constructor(
|
||||
public id?: any,
|
||||
public login?: string,
|
||||
public firstName?: string,
|
||||
public lastName?: string,
|
||||
public email?: string,
|
||||
public activated?: boolean,
|
||||
public langKey?: string,
|
||||
public authorities?: any[],
|
||||
public createdBy?: string,
|
||||
public createdDate?: Date,
|
||||
public lastModifiedBy?: string,
|
||||
public lastModifiedDate?: Date,
|
||||
public password?: string
|
||||
) {
|
||||
this.id = id ? id : null;
|
||||
this.login = login ? login : null;
|
||||
this.firstName = firstName ? firstName : null;
|
||||
this.lastName = lastName ? lastName : null;
|
||||
this.email = email ? email : null;
|
||||
this.activated = activated ? activated : false;
|
||||
this.langKey = langKey ? langKey : null;
|
||||
this.authorities = authorities ? authorities : null;
|
||||
this.createdBy = createdBy ? createdBy : null;
|
||||
this.createdDate = createdDate ? createdDate : null;
|
||||
this.lastModifiedBy = lastModifiedBy ? lastModifiedBy : null;
|
||||
this.lastModifiedDate = lastModifiedDate ? lastModifiedDate : null;
|
||||
this.password = password ? password : null;
|
||||
}
|
||||
}
|
39
src/main/webapp/app/core/user/user.service.ts
Normal file
39
src/main/webapp/app/core/user/user.service.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import { HttpClient, HttpResponse } from '@angular/common/http';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { SERVER_API_URL } from 'app/app.constants';
|
||||
import { createRequestOption } from 'app/shared/util/request-util';
|
||||
import { IUser } from './user.model';
|
||||
|
||||
@Injectable({ providedIn: 'root' })
|
||||
export class UserService {
|
||||
public resourceUrl = SERVER_API_URL + 'api/users';
|
||||
|
||||
constructor(private http: HttpClient) {}
|
||||
|
||||
create(user: IUser): Observable<HttpResponse<IUser>> {
|
||||
return this.http.post<IUser>(this.resourceUrl, user, { observe: 'response' });
|
||||
}
|
||||
|
||||
update(user: IUser): Observable<HttpResponse<IUser>> {
|
||||
return this.http.put<IUser>(this.resourceUrl, user, { observe: 'response' });
|
||||
}
|
||||
|
||||
find(login: string): Observable<HttpResponse<IUser>> {
|
||||
return this.http.get<IUser>(`${this.resourceUrl}/${login}`, { observe: 'response' });
|
||||
}
|
||||
|
||||
query(req?: any): Observable<HttpResponse<IUser[]>> {
|
||||
const options = createRequestOption(req);
|
||||
return this.http.get<IUser[]>(this.resourceUrl, { params: options, observe: 'response' });
|
||||
}
|
||||
|
||||
delete(login: string): Observable<HttpResponse<any>> {
|
||||
return this.http.delete(`${this.resourceUrl}/${login}`, { observe: 'response' });
|
||||
}
|
||||
|
||||
authorities(): Observable<string[]> {
|
||||
return this.http.get<string[]>(SERVER_API_URL + 'api/users/authorities');
|
||||
}
|
||||
}
|
15
src/main/webapp/app/entities/entity.module.ts
Normal file
15
src/main/webapp/app/entities/entity.module.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
/* jhipster-needle-add-entity-route - JHipster will add entity modules routes here */
|
||||
])
|
||||
],
|
||||
declarations: [],
|
||||
entryComponents: [],
|
||||
providers: [],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HsadminNgEntityModule {}
|
41
src/main/webapp/app/home/home.component.html
Normal file
41
src/main/webapp/app/home/home.component.html
Normal file
@ -0,0 +1,41 @@
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<span class="hipster img-fluid rounded"></span>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<h1 class="display-4" jhiTranslate="home.title">Welcome, Java Hipster!</h1>
|
||||
<p class="lead" jhiTranslate="home.subtitle">This is your homepage</p>
|
||||
|
||||
<div [ngSwitch]="isAuthenticated()">
|
||||
<div class="alert alert-success" *ngSwitchCase="true">
|
||||
<span id="home-logged-message" *ngIf="account" jhiTranslate="home.logged.message"
|
||||
[translateValues]="{username: account.login}"> You are logged in as user "{{account.login}}". </span>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning" *ngSwitchCase="false">
|
||||
<span jhiTranslate="global.messages.info.authenticated.prefix">If you want to </span>
|
||||
<a class="alert-link" (click)="login()" jhiTranslate="global.messages.info.authenticated.link">sign in</a><span jhiTranslate="global.messages.info.authenticated.suffix">, you can try the default accounts:<br/>- Administrator (login="admin" and password="admin") <br/>- User (login="user" and password="user").</span>
|
||||
</div>
|
||||
<div class="alert alert-warning" *ngSwitchCase="false">
|
||||
<span jhiTranslate="global.messages.info.register.noaccount">You don't have an account yet?</span>
|
||||
<a class="alert-link" routerLink="register" jhiTranslate="global.messages.info.register.link">Register a new account</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p jhiTranslate="home.question">
|
||||
If you have any question on JHipster:
|
||||
</p>
|
||||
|
||||
<ul>
|
||||
<li><a href="https://www.jhipster.tech/" target="_blank" rel="noopener" jhiTranslate="home.link.homepage">JHipster homepage</a></li>
|
||||
<li><a href="http://stackoverflow.com/tags/jhipster/info" target="_blank" rel="noopener" jhiTranslate="home.link.stackoverflow">JHipster on Stack Overflow</a></li>
|
||||
<li><a href="https://github.com/jhipster/generator-jhipster/issues?state=open" target="_blank" rel="noopener" jhiTranslate="home.link.bugtracker">JHipster bug tracker</a></li>
|
||||
<li><a href="https://gitter.im/jhipster/generator-jhipster" target="_blank" rel="noopener" jhiTranslate="home.link.chat">JHipster public chat room</a></li>
|
||||
<li><a href="https://twitter.com/java_hipster" target="_blank" rel="noopener" jhiTranslate="home.link.follow">follow @java_hipster on Twitter</a></li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<span jhiTranslate="home.like">If you like JHipster, don't forget to give us a star on</span> <a href="https://github.com/jhipster/generator-jhipster" target="_blank" rel="noopener" jhiTranslate="home.github">GitHub</a>!
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
44
src/main/webapp/app/home/home.component.ts
Normal file
44
src/main/webapp/app/home/home.component.ts
Normal file
@ -0,0 +1,44 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { NgbModalRef } from '@ng-bootstrap/ng-bootstrap';
|
||||
import { JhiEventManager } from 'ng-jhipster';
|
||||
|
||||
import { LoginModalService, AccountService, Account } from 'app/core';
|
||||
|
||||
@Component({
|
||||
selector: 'jhi-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['home.css']
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
account: Account;
|
||||
modalRef: NgbModalRef;
|
||||
|
||||
constructor(
|
||||
private accountService: AccountService,
|
||||
private loginModalService: LoginModalService,
|
||||
private eventManager: JhiEventManager
|
||||
) {}
|
||||
|
||||
ngOnInit() {
|
||||
this.accountService.identity().then((account: Account) => {
|
||||
this.account = account;
|
||||
});
|
||||
this.registerAuthenticationSuccess();
|
||||
}
|
||||
|
||||
registerAuthenticationSuccess() {
|
||||
this.eventManager.subscribe('authenticationSuccess', message => {
|
||||
this.accountService.identity().then(account => {
|
||||
this.account = account;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
isAuthenticated() {
|
||||
return this.accountService.isAuthenticated();
|
||||
}
|
||||
|
||||
login() {
|
||||
this.modalRef = this.loginModalService.open();
|
||||
}
|
||||
}
|
23
src/main/webapp/app/home/home.css
Normal file
23
src/main/webapp/app/home/home.css
Normal file
@ -0,0 +1,23 @@
|
||||
/* ==========================================================================
|
||||
Main page styles
|
||||
========================================================================== */
|
||||
|
||||
.hipster {
|
||||
display: inline-block;
|
||||
width: 347px;
|
||||
height: 497px;
|
||||
background: url('../../content/images/jhipster_family_member_3.svg') no-repeat center top;
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
/* wait autoprefixer update to allow simple generation of high pixel density media query */
|
||||
@media only screen and (-webkit-min-device-pixel-ratio: 2),
|
||||
only screen and (-moz-min-device-pixel-ratio: 2),
|
||||
only screen and (-o-min-device-pixel-ratio: 2/1),
|
||||
only screen and (min-resolution: 192dpi),
|
||||
only screen and (min-resolution: 2dppx) {
|
||||
.hipster {
|
||||
background: url('../../content/images/jhipster_family_member_3.svg') no-repeat center top;
|
||||
background-size: contain;
|
||||
}
|
||||
}
|
12
src/main/webapp/app/home/home.module.ts
Normal file
12
src/main/webapp/app/home/home.module.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { RouterModule } from '@angular/router';
|
||||
|
||||
import { HsadminNgSharedModule } from 'app/shared';
|
||||
import { HOME_ROUTE, HomeComponent } from './';
|
||||
|
||||
@NgModule({
|
||||
imports: [HsadminNgSharedModule, RouterModule.forChild([HOME_ROUTE])],
|
||||
declarations: [HomeComponent],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class HsadminNgHomeModule {}
|
12
src/main/webapp/app/home/home.route.ts
Normal file
12
src/main/webapp/app/home/home.route.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import { Route } from '@angular/router';
|
||||
|
||||
import { HomeComponent } from './';
|
||||
|
||||
export const HOME_ROUTE: Route = {
|
||||
path: '',
|
||||
component: HomeComponent,
|
||||
data: {
|
||||
authorities: [],
|
||||
pageTitle: 'home.title'
|
||||
}
|
||||
};
|
3
src/main/webapp/app/home/index.ts
Normal file
3
src/main/webapp/app/home/index.ts
Normal file
@ -0,0 +1,3 @@
|
||||
export * from './home.component';
|
||||
export * from './home.route';
|
||||
export * from './home.module';
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user