add customer page: password-change.component.html

This commit is contained in:
Roland Schneider 2021-09-12 20:50:07 +02:00
parent 18cd8312b5
commit 3c03e49b99
78 changed files with 641 additions and 304 deletions

View File

@ -27,7 +27,6 @@
"src/assets"
],
"styles": [
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
"src/styles.scss"
],
"scripts": [

View File

@ -254,9 +254,9 @@
}
},
"@angular/animations": {
"version": "12.2.4",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.4.tgz",
"integrity": "sha512-UpTddGkftkW/vOhF19Z6lbtvhUX+LpMw+1qC2miM65XNrOWBe5bojX9/9pwGd1CpP189aRFHl933YLCgVxGKPA==",
"version": "12.2.5",
"resolved": "https://registry.npmjs.org/@angular/animations/-/animations-12.2.5.tgz",
"integrity": "sha512-a8jRimgrATq2CS95SO5yjsZo2d4FbfmN2SrPu6lZjWIdstXm4KQSJFslyxovhoUjGNu5cZgzfXTvWkXRxJYCxA==",
"requires": {
"tslib": "^2.2.0"
}
@ -3006,9 +3006,9 @@
"dev": true
},
"bootstrap": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-4.3.1.tgz",
"integrity": "sha512-rXqOmH1VilAt2DyPzluTi2blhk17bO7ef+zLLPlWvG494pDxcM234pJ8wTc/6R40UWizAIIMgxjvxZg5kmsbag=="
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.1.tgz",
"integrity": "sha512-/jUa4sSuDZWlDLQ1gwQQR8uoYSvLJzDd8m5o6bPKh3asLAMYVZKdRCjb1joUd5WXf0WwCNzd2EjwQQhupou0dA=="
},
"brace-expansion": {
"version": "1.1.11",
@ -7714,6 +7714,14 @@
"resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-5.0.0.tgz",
"integrity": "sha512-5TTFP9s3wfiRychGcdyvpCvvxtxW1Nf2Dqmk2YBzuIhHHLT6gRq1Fsic4lYrtAUwmy0PSLhOY/XW/saYKlrSJw=="
},
"ngx-toastr": {
"version": "14.1.3",
"resolved": "https://registry.npmjs.org/ngx-toastr/-/ngx-toastr-14.1.3.tgz",
"integrity": "sha512-UzOl3xqhd0t1CcCBNZZ5GzVOOAFuaaEcF8KdQ4CgVp2CY1sdmUdJcnlAvjvL2Cjz3G0sSVVYtF5UdPa+d0gzZA==",
"requires": {
"tslib": "^2.2.0"
}
},
"nice-napi": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz",

View File

@ -11,7 +11,7 @@
},
"private": true,
"dependencies": {
"@angular/animations": "~12.2.4",
"@angular/animations": "^12.2.5",
"@angular/common": "~12.2.4",
"@angular/compiler": "~12.2.4",
"@angular/core": "~12.2.4",
@ -22,9 +22,10 @@
"@fortawesome/angular-fontawesome": "^0.9.0",
"@fortawesome/fontawesome-svg-core": "^1.2.36",
"@fortawesome/free-solid-svg-icons": "^5.15.4",
"bootstrap": "^4.3.1",
"bootstrap": "^5.1.1",
"moment": "^2.24.0",
"ngx-bootstrap": "^5.0.0",
"ngx-toastr": "^14.1.3",
"rxjs": "~6.6.7",
"tslib": "^2.0.0",
"zone.js": "~0.11.4"

View File

@ -8,21 +8,48 @@ import {EventsComponent} from "./pages/events/events.component";
import {EventDetailsComponent} from "./pages/event-details/event-details.component";
import {RegistrationsComponent} from "./pages/registrations/registrations.component";
import {RegistrationComponent} from "./pages/registration/registration.component";
import {GuestLayoutComponent} from "./layout/guest-layout/guest-layout.component";
import {SecuredLayoutComponent} from "./layout/secured-layout/secured-layout.component";
import {PasswordChangeComponent} from "./pages/password-change/password-change.component";
const routes: Routes = [
{ path: 'home', component: HomeComponent },
{ path: '', redirectTo: '/home' , pathMatch: 'full'},
{ path: 'login', component: LoginComponent },
{ path: 'logout', redirectTo: '/login' , pathMatch: 'full'},
{ path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
{ path: 'events', component: EventsComponent, canActivate: [AuthGuard] },
{ path: 'event-details/:idEvent', component: EventDetailsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
{ path: 'registrations', component: RegistrationsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
{ path: 'registration/:idRegistration', component: RegistrationComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
{
path: '',
component: GuestLayoutComponent,
children: [
{ path: '', component: LoginComponent, pathMatch: 'full'},
{ path: 'login', component: LoginComponent , pathMatch: 'full'}
]
},
{
path: '',
component: SecuredLayoutComponent,
children: [
{ path: 'home', component: HomeComponent , pathMatch: 'full'},
{ path: 'logout', redirectTo: '/login' , pathMatch: 'full'},
{ path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
{ path: 'events', component: EventsComponent, canActivate: [AuthGuard] },
{ path: 'event-details/:idEvent', component: EventDetailsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
{ path: 'registrations', component: RegistrationsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
{ path: 'registration/:idRegistration', component: RegistrationComponent },
{ path: 'password-change', component: PasswordChangeComponent }
]
},
{ path: '**', redirectTo: '' }
// { path: 'home', component: HomeComponent },
// { path: '', redirectTo: '/home' , pathMatch: 'full'},
// { path: 'login', component: LoginComponent },
// { path: 'logout', redirectTo: '/login' , pathMatch: 'full'},
// { path: 'profile', component: ProfileComponent, canActivate: [AuthGuard] },
// { path: 'events', component: EventsComponent, canActivate: [AuthGuard] },
// { path: 'event-details/:idEvent', component: EventDetailsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
// { path: 'registrations', component: RegistrationsComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
// { path: 'registration/:idRegistration', component: RegistrationComponent, canActivate: [AuthGuard] , pathMatch: 'full' },
];
@NgModule({
imports: [RouterModule.forRoot(routes, { relativeLinkResolution: 'legacy' })],
imports: [RouterModule.forRoot(routes, { useHash: true })],
exports: [RouterModule]
})
export class AppRoutingModule { }

View File

@ -1,3 +1 @@
<fit-navigation></fit-navigation>
<!--<fit-slides></fit-slides>-->
<router-outlet></router-outlet>

View File

@ -0,0 +1,4 @@
div{
height: 100%;
}

View File

@ -1,35 +0,0 @@
import { TestBed, waitForAsync } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
RouterTestingModule
],
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
});
it(`should have as title 'app'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
});
it('should render title in a h1 tag', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
});
});

View File

@ -1,4 +1,5 @@
import { Component } from '@angular/core';
import {AuthenticationService} from "./services/authentication.service";
@Component({
selector: 'app-root',
@ -7,4 +8,7 @@ import { Component } from '@angular/core';
})
export class AppComponent {
title = 'app';
constructor( public authenticationService: AuthenticationService ) {
}
}

View File

@ -30,6 +30,10 @@ import { MonthCalendarEventComponent } from './components/month-calendar-event/m
import { EventDetailsComponent } from './pages/event-details/event-details.component';
import { RegistrationsComponent } from './pages/registrations/registrations.component';
import { RegistrationComponent } from './pages/registration/registration.component';
import { GuestLayoutComponent } from './layout/guest-layout/guest-layout.component';
import { SecuredLayoutComponent } from './layout/secured-layout/secured-layout.component';
import { PasswordChangeComponent } from './pages/password-change/password-change.component';
import {ToastrModule} from "ngx-toastr";
@ -54,8 +58,12 @@ registerLocaleData(localeHu, 'hu');
EventDetailsComponent,
RegistrationsComponent,
RegistrationComponent,
GuestLayoutComponent,
SecuredLayoutComponent,
PasswordChangeComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
@ -64,6 +72,8 @@ registerLocaleData(localeHu, 'hu');
HttpClientModule,
TypeaheadModule.forRoot(),
FontAwesomeModule,
BrowserAnimationsModule, // required animations module
ToastrModule.forRoot(), // ToastrModule added
],
providers: [
{ provide: LOCALE_ID, useValue: "hu-hu" },

View File

@ -4,3 +4,8 @@ export interface CalendarEvent{
event: Event;
registrations: Registration;
}
export interface PasswordChangeRequest{
passwordOld: string;
password: string;
}

View File

@ -1,5 +1,5 @@
.fit-navbar {
background: transparent !important;
//background: transparent !important;
}
.fit-navbar-absolute {
@ -13,14 +13,14 @@
@media (max-width: 991.98px) {
.fit-navbar {
background: #000 !important;
//background: #000 !important;
position: relative;
top: 0;
}
}
.fit-navbar .navbar-brand {
color: #fff;
//color: #fff;
}

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { FitNavigationComponent } from './fit-navigation.component';
describe('FitNavigationComponent', () => {
let component: FitNavigationComponent;
let fixture: ComponentFixture<FitNavigationComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ FitNavigationComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FitNavigationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -36,6 +36,11 @@ export class FitNavigationComponent implements OnInit {
label: 'Bejelentkezés',
roles: ['!']
},
{
route: '/password-change',
label: 'Jelszó módosítása',
roles: ['@']
},
{
route: '/logout',
label: 'Kijelentkezés',

View File

@ -41,6 +41,8 @@ export class MonthCalendarDayComponent implements OnInit {
let styleClass = "day col-sm p-2 border border-left-0 border-top-0 text-truncate";
if ( !this.day.active ){
styleClass += " d-none d-sm-inline-block bg-light text-muted";
} else {
styleClass += " bg-primary text-light"
}
return styleClass;
}

View File

@ -1,7 +1,7 @@
<div class="container-fluid">
<header>
<h4 class="display-4 mb-4 text-center">Naptár</h4>
<div class="row d-none d-sm-flex p-1 bg-dark text-white">
<h1 class="text-center">Naptár</h1>
<div class="row d-none d-sm-flex p-1 bg-primary text-white">
<h5 *ngFor="let dayOfWeek of daysOfWeek" class="col-sm p-1 text-center name-of-day-of-week">{{dayOfWeek.name}}</h5>
</div>
</header>

View File

@ -0,0 +1,3 @@
<div class="h-100">
<router-outlet></router-outlet>
</div>

View File

@ -0,0 +1,4 @@
div{
background: url("/assets/images/cutlercross-background.jpg");
background-repeat: repeat-y;
}

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-guest-layout',
templateUrl: './guest-layout.component.html',
styleUrls: ['./guest-layout.component.scss']
})
export class GuestLayoutComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -0,0 +1,4 @@
<fit-navigation></fit-navigation>
<div class="container " style="height: calc(100% - 85px)">
<router-outlet></router-outlet>
</div>

View File

@ -0,0 +1,15 @@
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-secured-layout',
templateUrl: './secured-layout.component.html',
styleUrls: ['./secured-layout.component.scss']
})
export class SecuredLayoutComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { EventDetailsComponent } from './event-details.component';
describe('EventDetailsComponent', () => {
let component: EventDetailsComponent;
let fixture: ComponentFixture<EventDetailsComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ EventDetailsComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(EventDetailsComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -24,6 +24,7 @@ export class EventDetailsComponent implements OnInit {
) { }
ngOnInit() {
console.info("event details")
this.formControls = {
idEvent: ["", [Validators.required ]],
}

View File

@ -1,9 +1,7 @@
<div class="container">
<!-- <app-fit-weekday-selector [days]="(availableEvents | async)?.days" ></app-fit-weekday-selector>-->
<ng-container *ngIf="availableEvents | async">
<app-month-calendar
(onEvent)="handleEvent($event)"
[eventsAvailableResponse]="availableEvents | async "></app-month-calendar>
</ng-container>
</div>

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { HomeComponent } from './home.component';
describe('HomeComponent', () => {
let component: HomeComponent;
let fixture: ComponentFixture<HomeComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ HomeComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HomeComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -1,9 +1,11 @@
<div class="container fit-content">
<div class="row">
<div class="col-lg-6 col-sm-12 offset-lg-3 pt-2 pb-3 mt-lg-5 "
style=" background-color: #0a0a0b; border: 1px solid gray; ">
<div class="container h-100">
<div class="row h-100">
<div class="col-lg-6 col-sm-12 offset-lg-3 " >
<div class="d-flex align-items-center justify-content-center h-100 flex-column ">
<form class="login-form" [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<img class="mw2-sm-50 mw2-100" src="/assets/images/cutlercross-logo-light.svg">
<form class="login-form w-100" [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="inputUsername">Felhasználónév</label>
<input type="text" formControlName="username" class="form-control" id="inputUsername"
@ -23,6 +25,7 @@
<button [disabled]="loading" class="btn btn-primary ">Bejelentkezés</button>
<div *ngIf="error" class="alert alert-danger mt-2">{{error}}</div>
</form>
</div>
</div>
</div>
</div>
</div>

View File

@ -1,8 +0,0 @@
//.btn-primary{
// background-color: #e5ce48;
// color: orangered;
// border: 1px solid orangered;
//}
//.btn-primary:hover{
// background-color: orange;
//}

View File

@ -1,25 +0,0 @@
import { ComponentFixture, TestBed, waitForAsync } from '@angular/core/testing';
import { LoginComponent } from './login.component';
describe('LoginComponent', () => {
let component: LoginComponent;
let fixture: ComponentFixture<LoginComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
declarations: [ LoginComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(LoginComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -32,7 +32,7 @@ export class LoginComponent implements OnInit {
this.authenticationService.logout();
// get return url from route parameters or default to '/'
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/';
this.returnUrl = this.route.snapshot.queryParams['returnUrl'] || '/home';
}

View File

@ -0,0 +1,37 @@
<div class="d-flex h-100 align-items-center justify-content-center" (submit)="changePassword()">
<form [formGroup]="passwordChangeForm">
<h1>Jelszó módosítása</h1>
<div class="mb-3">
<label for="password_old" class="form-label">Jelenlegi jelszó</label>
<input type="password" class="form-control" id="password_old" placeholder="Jelenlegi jelszó"
formControlName="passwordOld">
<div *ngIf="validationService.showControlError(passwordChangeForm,'passwordOld','required')" class="text-danger">A 'jelenlegi jelszó' megadása kötelező</div>
</div>
<div class="mb-3">
<label for="password" class="form-label">Új jelszó</label>
<input type="password" class="form-control" id="password" placeholder="Új jelszó" formControlName="password">
<div *ngIf="validationService.showControlError(passwordChangeForm,'password','required')" class="text-danger">A jelszó megadása kötelező</div>
<div *ngIf="validationService.showControlError(passwordChangeForm,'password','minlength')" class="text-danger">A jelszó nem felel meg a formai követelményeknek</div>
</div>
<div class="mb-3">
<label for="password_repeat" class="form-label">Új jelszó mégegyszer</label>
<input type="password" class="form-control" id="password_repeat" placeholder="Új jelszó mégegyszer"
formControlName="passwordRepeat">
<div *ngIf="validationService.showControlError(passwordChangeForm,'passwordRepeat','required')" class="text-danger">A 'jelszó mégegyszer' megadása kötelező</div>
<div *ngIf="validationService.showControlError(passwordChangeForm,'passwordRepeat','minlength')" class="text-danger">A 'jelszó mégegyszer' nem felel meg a formai követelményeknek</div>
<div *ngIf="validationService.showControlError(passwordChangeForm,null,'notSame')" class="text-danger">A jelszó és a jelszó mégegyszer' nem egyezik</div>
</div>
<div class="mb-3">
* A jelszónak legalább 6 karakterből kell állnia
</div>
<div class="text-center">
<button class="btn btn-primary" type="submit" [disabled]="!passwordChangeForm.valid || loading">Jelszó megváltoztatása</button>
</div>
</form>
</div>

View File

@ -0,0 +1,69 @@
import { Component, OnInit } from '@angular/core';
import {AbstractControl, FormControl, FormGroup, ValidationErrors, ValidatorFn, Validators} from "@angular/forms";
import {FormHelperService} from "../../services/form-helper.service";
import {AuthenticationService} from "../../services/authentication.service";
import {ToastrService} from "ngx-toastr";
@Component({
selector: 'app-password-change',
templateUrl: './password-change.component.html',
styleUrls: ['./password-change.component.scss']
})
export class PasswordChangeComponent implements OnInit {
public passwordChangeForm: FormGroup ;
public loading: boolean = false;
constructor(
public validationService: FormHelperService,
public authenticationService: AuthenticationService,
private toastr: ToastrService
) { }
ngOnInit(): void {
this.passwordChangeForm = new FormGroup({
passwordOld: new FormControl(null, [ Validators.required, ]),
password: new FormControl(null, [ Validators.required,Validators.minLength(6)]),
passwordRepeat: new FormControl(null, [ Validators.required,Validators.minLength(6)]),
},
{
validators: [this.checkPasswords]
});
}
changePassword() {
if (!this.passwordChangeForm.valid){
return;
}
this.loading = true;
this.authenticationService.passwordChange({
passwordOld: this.passwordChangeForm.value.passwordOld,
password: this.passwordChangeForm.value.password
}).subscribe(value => {
this.loading = false;
this.toastr.success('Sikeresen megváltoztatta a jelszavát', 'Jelszó módosítás');
this.passwordChangeForm.reset();
},
error => {
this.loading = false;
this.toastr.error(error, 'Jelszó módosítás');
})
}
checkPasswords: ValidatorFn = (group: AbstractControl): ValidationErrors | null => {
if ( group.hasError("password") || group.hasError("passwordRepeat")){
return null;
}
if ( !group.get("passwordRepeat").dirty || !group.get("passwordRepeat").touched ){
return null;
}
let password = this.validationService.getValue(this.passwordChangeForm,"password");
let passwordRepeat = this.validationService.getValue(this.passwordChangeForm,"passwordRepeat");
return password === passwordRepeat ? null : { notSame: true }
}
}

View File

@ -3,6 +3,7 @@ import { HttpClient } from "@angular/common/http";
import { map } from 'rxjs/operators';
import {Endpoints} from "./endpoints";
import {BehaviorSubject} from "rxjs";
import {PasswordChangeRequest} from "../app.types";
@Injectable({
providedIn: 'root'
@ -35,6 +36,10 @@ export class AuthenticationService {
);
}
passwordChange(passwordChangeRequest: PasswordChangeRequest){
return this.http.post<any>(Endpoints.POST_USER_PASSWORD_CHANGE(), passwordChangeRequest)
}
get user() {
return this._user;
}

View File

@ -6,6 +6,10 @@ export class Endpoints {
return `${this.baseUrl}user/login`;
}
public static POST_USER_PASSWORD_CHANGE(){
return `${this.baseUrl}user/password-change`;
}
public static GET_EVENTS( ){
return `${this.baseUrl}/events`;
}

View File

@ -0,0 +1,53 @@
import {Injectable} from '@angular/core';
import {FormGroup} from "@angular/forms";
@Injectable({
providedIn: 'root'
})
export class FormHelperService {
constructor() {
}
public reset(formGroup: FormGroup) {
formGroup.reset();
}
public showControlError(formGroup: FormGroup, formControlName: string, errorType: string = null): boolean {
if (formGroup.valid) {
return false;
}
if ( formControlName == null ){
if ( errorType ){
return formGroup.errors ? formGroup.errors[errorType]: false;
}else {
return formGroup.invalid;
}
}
let control = formGroup.get(formControlName);
if ( !control.dirty || !control.touched ){
return false;
}
let hasErrors = control.invalid;
if (!hasErrors) {
return false;
}
if (errorType == null) {
return true;
}
return control?.errors[errorType];
}
public getValue(formGroup: FormGroup, control: string) {
return formGroup.get(control).value
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 420 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 31 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Before

Width:  |  Height:  |  Size: 455 KiB

After

Width:  |  Height:  |  Size: 455 KiB

View File

Before

Width:  |  Height:  |  Size: 203 KiB

After

Width:  |  Height:  |  Size: 203 KiB

View File

Before

Width:  |  Height:  |  Size: 316 KiB

After

Width:  |  Height:  |  Size: 316 KiB

View File

Before

Width:  |  Height:  |  Size: 245 KiB

After

Width:  |  Height:  |  Size: 245 KiB

View File

Before

Width:  |  Height:  |  Size: 618 KiB

After

Width:  |  Height:  |  Size: 618 KiB

View File

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 221 KiB

View File

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

View File

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 120 KiB

View File

Before

Width:  |  Height:  |  Size: 194 KiB

After

Width:  |  Height:  |  Size: 194 KiB

View File

Before

Width:  |  Height:  |  Size: 110 KiB

After

Width:  |  Height:  |  Size: 110 KiB

View File

Before

Width:  |  Height:  |  Size: 27 KiB

After

Width:  |  Height:  |  Size: 27 KiB

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Before

Width:  |  Height:  |  Size: 149 KiB

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 35 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

Before

Width:  |  Height:  |  Size: 34 KiB

After

Width:  |  Height:  |  Size: 34 KiB

View File

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View File

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

View File

Before

Width:  |  Height:  |  Size: 86 KiB

After

Width:  |  Height:  |  Size: 86 KiB

View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

View File

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 88 KiB

View File

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

View File

Before

Width:  |  Height:  |  Size: 39 KiB

After

Width:  |  Height:  |  Size: 39 KiB

View File

Before

Width:  |  Height:  |  Size: 161 KiB

After

Width:  |  Height:  |  Size: 161 KiB

View File

Before

Width:  |  Height:  |  Size: 85 KiB

After

Width:  |  Height:  |  Size: 85 KiB

View File

Before

Width:  |  Height:  |  Size: 96 KiB

After

Width:  |  Height:  |  Size: 96 KiB

View File

Before

Width:  |  Height:  |  Size: 103 KiB

After

Width:  |  Height:  |  Size: 103 KiB

View File

Before

Width:  |  Height:  |  Size: 154 KiB

After

Width:  |  Height:  |  Size: 154 KiB

View File

Before

Width:  |  Height:  |  Size: 148 KiB

After

Width:  |  Height:  |  Size: 148 KiB

View File

@ -1,110 +1,27 @@
/* You can add global styles to this file, and also import other style files */
$font-size-xs: 0.625rem;
$font-size-sm: 1rem;
$font-size-md: 1.25rem;
$font-size-lg: 2.5rem;
$font-size-xl: 6.25rem;
$primary: #E3000E ;
$secondary: #D2D2D2 ;
$light: #FFFFFF ;
$dark: #3A3A39 ;
// regular style toast
@import '~ngx-toastr/toastr';
@import "styles/bootstrap-custom";
html{
height: 100%;
}
body{
font-family: "Poppins", Arial, sans-serif;
background: #151111;
font-size: 15px;
line-height: 1.8;
font-weight: 300;
color: gray;
background: url("/assets/images/bg_4.jpg") no-repeat fixed;
background-size: cover;
min-height: 100%;
height: 100%;
}
.fit-content{
.fit-navbar{
position: relative;
}
}
.btn {
cursor: pointer;
-webkit-border-radius: 0;
-moz-border-radius: 0;
-ms-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: none !important;
box-shadow: none !important;
font-size: 13px; }
.btn:hover, .btn:active, .btn:focus {
outline: none; }
.btn.btn-primary {
background: #e5ce48;
border: 1px solid #e5ce48;
color: #000; }
.btn.btn-primary:hover,.btn.btn-primary:active, .btn-primary:not(:disabled):not(.disabled):active {
border: 1px solid #e5ce48;
background: transparent;
color: #e5ce48; }
.btn.btn-primary.btn-outline-primary {
border: 1px solid #e5ce48;
background: transparent;
color: #e5ce48; }
.btn.btn-primary.btn-outline-primary:hover {
border: 1px solid transparent;
background: #e5ce48;
color: #fff; }
.btn.btn-white {
background: #fff;
border: 1px solid #fff;
color: #000; }
.btn.btn-white:hover {
border: 1px solid #000;
background: #000;
color: #fff; }
.btn.btn-white.btn-outline-white {
border-color: rgba(255, 255, 255, 0.8);
background: none;
border-width: 1px;
color: #fff; }
.btn.btn-white.btn-outline-white:hover, .btn.btn-white.btn-outline-white:focus, .btn.btn-white.btn-outline-white:active {
background: #e5ce48;
border-color: #e5ce48;
color: #000; }
.btn.btn-outline-black {
border-color: black;
background: none;
border-width: 1px;
color: #000; }
.btn.btn-outline-black:hover, .btn.btn-outline-black:focus, .btn.btn-outline-black:active {
background: #000;
border-color: #000;
color: #fff; }
.login-form .form-group {
position: relative; }
.login-form .form-control {
border: transparent !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
height: 58px !important;
padding-left: 0;
padding-right: 0;
background: transparent !important;
color: rgba(255, 255, 255, 0.9) !important;
font-size: 13px;
border-radius: 0px;
-webkit-box-shadow: none !important;
box-shadow: none !important; }
.login-form .form-control::-webkit-input-placeholder {
/* Chrome/Opera/Safari */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control::-moz-placeholder {
/* Firefox 19+ */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control:-ms-input-placeholder {
/* IE 10+ */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control:-moz-placeholder {
/* Firefox 18- */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control:focus, .login-form .form-control:active {
border-color: #e5ce48 !important; }
.login-form textarea.form-control {
height: inherit !important; }

View File

@ -0,0 +1,68 @@
/*!
* Bootstrap v5.1.1 (https://getbootstrap.com/)
* Copyright 2011-2021 The Bootstrap Authors
* Copyright 2011-2021 Twitter, Inc.
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
*/
// scss-docs-start import-stack
// Configuration
@import "node_modules/bootstrap/scss/functions";
@import "node_modules/bootstrap/scss/variables";
@import "node_modules/bootstrap/scss/mixins";
@import "node_modules/bootstrap/scss/utilities";
$utilities: () !default;
$utilities: map-merge(
(
// scss-docs-start utils-vertical-align
"max-width2": (
property: max-width,
responsive: true,
class: mw2,
values: ( 25: 25%, 50: 50%, 100: 100%)
),
),
$utilities
);
@import "node_modules/bootstrap/scss/root";
@import "node_modules/bootstrap/scss/reboot";
@import "node_modules/bootstrap/scss/type";
@import "node_modules/bootstrap/scss/images";
@import "node_modules/bootstrap/scss/containers";
@import "node_modules/bootstrap/scss/grid";
@import "node_modules/bootstrap/scss/tables";
@import "node_modules/bootstrap/scss/forms";
@import "node_modules/bootstrap/scss/buttons";
@import "node_modules/bootstrap/scss/transitions";
@import "node_modules/bootstrap/scss/dropdown";
@import "node_modules/bootstrap/scss/button-group";
@import "node_modules/bootstrap/scss/nav";
@import "node_modules/bootstrap/scss/navbar";
@import "node_modules/bootstrap/scss/card";
@import "node_modules/bootstrap/scss/accordion";
@import "node_modules/bootstrap/scss/breadcrumb";
@import "node_modules/bootstrap/scss/pagination";
// Layout & components
@import "node_modules/bootstrap/scss/badge";
@import "node_modules/bootstrap/scss/alert";
@import "node_modules/bootstrap/scss/progress";
@import "node_modules/bootstrap/scss/list-group";
@import "node_modules/bootstrap/scss/close";
@import "node_modules/bootstrap/scss/toasts";
@import "node_modules/bootstrap/scss/modal";
@import "node_modules/bootstrap/scss/tooltip";
@import "node_modules/bootstrap/scss/popover";
@import "node_modules/bootstrap/scss/carousel";
@import "node_modules/bootstrap/scss/spinners";
@import "node_modules/bootstrap/scss/offcanvas";
@import "node_modules/bootstrap/scss/placeholders";
// Helpers
@import "node_modules/bootstrap/scss/helpers";
// Utilities
@import "node_modules/bootstrap/scss/utilities/api";
// scss-docs-end import-stack

View File

@ -0,0 +1,98 @@
.fit-content{
.fit-navbar{
position: relative;
}
}
.btn {
cursor: pointer;
-webkit-border-radius: 0;
-moz-border-radius: 0;
-ms-border-radius: 0;
border-radius: 0;
-webkit-box-shadow: none !important;
box-shadow: none !important;
font-size: 13px; }
.btn:hover, .btn:active, .btn:focus {
outline: none; }
.btn.btn-primary {
background: #e5ce48;
border: 1px solid #e5ce48;
color: #000; }
.btn.btn-primary:hover,.btn.btn-primary:active, .btn-primary:not(:disabled):not(.disabled):active {
border: 1px solid #e5ce48;
background: transparent;
color: #e5ce48; }
.btn.btn-primary.btn-outline-primary {
border: 1px solid #e5ce48;
background: transparent;
color: #e5ce48; }
.btn.btn-primary.btn-outline-primary:hover {
border: 1px solid transparent;
background: #e5ce48;
color: #fff; }
.btn.btn-white {
background: #fff;
border: 1px solid #fff;
color: #000; }
.btn.btn-white:hover {
border: 1px solid #000;
background: #000;
color: #fff; }
.btn.btn-white.btn-outline-white {
border-color: rgba(255, 255, 255, 0.8);
background: none;
border-width: 1px;
color: #fff; }
.btn.btn-white.btn-outline-white:hover, .btn.btn-white.btn-outline-white:focus, .btn.btn-white.btn-outline-white:active {
background: #e5ce48;
border-color: #e5ce48;
color: #000; }
.btn.btn-outline-black {
border-color: black;
background: none;
border-width: 1px;
color: #000; }
.btn.btn-outline-black:hover, .btn.btn-outline-black:focus, .btn.btn-outline-black:active {
background: #000;
border-color: #000;
color: #fff; }
.login-form .form-group {
position: relative; }
.login-form .form-control {
border: transparent !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.08) !important;
height: 58px !important;
padding-left: 0;
padding-right: 0;
background: transparent !important;
color: rgba(255, 255, 255, 0.9) !important;
font-size: 13px;
border-radius: 0px;
-webkit-box-shadow: none !important;
box-shadow: none !important; }
.login-form .form-control::-webkit-input-placeholder {
/* Chrome/Opera/Safari */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control::-moz-placeholder {
/* Firefox 19+ */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control:-ms-input-placeholder {
/* IE 10+ */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control:-moz-placeholder {
/* Firefox 18- */
color: rgba(255, 255, 255, 0.9); }
.login-form .form-control:focus, .login-form .form-control:active {
border-color: #e5ce48 !important; }
.login-form textarea.form-control {
height: inherit !important; }

View File

@ -105,7 +105,7 @@ class EventController extends CustomerApiController
->innerJoinWith('trainer')
->innerJoinWith('eventType')
->innerJoinWith('room')
->joinWith('activeEventRegistrations as registrations')
->joinWith('activeEventRegistrations')
->andWhere(['>=', 'event.start', $interval->firstActiveDate->getTimestamp()])
->andWhere(['<', 'event.start', (clone $interval->lastActiveDate)->modify('+1 day')->getTimestamp()])
->andWhere(['event.active' => '1']);

View File

@ -10,13 +10,15 @@ namespace customerapi\controllers;
use common\models\Customer;
use customerapi\models\LoginForm;
use customerapi\models\PasswordChangeForm;
use sizeg\jwt\Jwt;
use sizeg\jwt\JwtHttpBearerAuth;
use Yii;
use yii\web\BadRequestHttpException;
/** @noinspection PhpUnused */
class UserController extends RestController
class UserController extends RestController
{
@ -26,36 +28,36 @@ class UserController extends RestController
*
*/
/** @noinspection PhpUnused */
public function actionLogin( )
public function actionLogin()
{
// $customer = new Customer();
// $customer->setPassword("test");
$form = new LoginForm();
$form->load(\Yii::$app->request->post( ), '');
$form->load(\Yii::$app->request->post(), '');
if ( $form->validate() ){
if ($form->validate()) {
/** @var Jwt $jwt */
$jwt = Yii::$app->jwt;
$signer = $jwt->getSigner('HS256');
$key = $jwt->getKey();
$time = time();
/** @var Jwt $jwt */
$jwt = Yii::$app->jwt;
$signer = $jwt->getSigner('HS256');
$key = $jwt->getKey();
$time = time();
// Adoption for lcobucci/jwt ^4.0 version
$token = $jwt->getBuilder()
->issuedBy('customerapi')// Configures the issuer (iss claim)
->permittedFor('customer')// Configures the audience (aud claim)
->identifiedBy('A989C57D19E2AF756BA9585AC4CFAF7974AE3D2BCA7CCA7307B39AB28CC7C2C8', true)// Configures the id (jti claim), replicating as a header item
->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + 3600)// Configures the expiration time of the token (exp claim)
->withClaim('uid', $form->getCustomer()->getId())// Configures a new claim, called "uid"
->getToken($signer, $key); // Retrieves the generated token
// Adoption for lcobucci/jwt ^4.0 version
$token = $jwt->getBuilder()
->issuedBy('customerapi')// Configures the issuer (iss claim)
->permittedFor('customer')// Configures the audience (aud claim)
->identifiedBy('A989C57D19E2AF756BA9585AC4CFAF7974AE3D2BCA7CCA7307B39AB28CC7C2C8', true)// Configures the id (jti claim), replicating as a header item
->issuedAt($time)// Configures the time that the token was issue (iat claim)
->expiresAt($time + 3600)// Configures the expiration time of the token (exp claim)
->withClaim('uid', $form->getCustomer()->getId())// Configures a new claim, called "uid"
->getToken($signer, $key); // Retrieves the generated token
return $this->asJson([
'token' => (string)$token,
]);
return $this->asJson([
'token' => (string)$token,
]);
} else {
return $this->asJson(
[
@ -66,6 +68,33 @@ class UserController extends RestController
}
/**
* @throws \yii\base\InvalidConfigException
* @throws \yii\base\Exception
* @throws BadRequestHttpException
*/
public function actionPasswordChange()
{
$form = new PasswordChangeForm();
$form->scenario = "default";
$form->load(\Yii::$app->request->post(), '');
if (!$form->validate()) {
throw new BadRequestHttpException( $form->getErrorSummary(false)[0]);
}
$customer = Customer::findOne(\Yii::$app->user->id);
if (!$customer->validatePassword($form->passwordOld)) {
throw new BadRequestHttpException("Jelenlegi jelszó nem egyezik", "2");
}
$customer->setPassword($form->password);
$customer->save();
}
protected function getOptionalActions()
{
return ['login'];

View File

@ -0,0 +1,32 @@
<?php
namespace customerapi\models;
use yii\base\Model;
class PasswordChangeForm extends Model
{
public $passwordOld;
public $password;
/**
* @inheritdoc
*/
public function rules()
{
return [
// 123456123456123456123456123456123456
// passwordOld and password are both required
[['passwordOld', 'password'], 'required'],
[['passwordOld', 'password'], 'string', 'length' => [6, 24] ],
];
}
public function attributeLabels(){
return [
'passwordOld' => "Jelenlegi jelszó",
'password' => "Jelszó"
];
}
}