Merge branch 'feature/login-register' into develop

This commit is contained in:
Michał Romaszkin 2020-11-08 21:53:43 +01:00
commit e87e10ce62
35 changed files with 1863 additions and 2355 deletions

File diff suppressed because it is too large Load Diff

View File

@ -17,6 +17,7 @@
"@angular/platform-browser": "~10.0.0",
"@angular/platform-browser-dynamic": "~10.0.0",
"@angular/router": "~10.0.0",
"@nebular/auth": "^6.2.1",
"@nebular/eva-icons": "5.0.0",
"@nebular/theme": "^5.0.0",
"@ngrx/effects": "^10.0.1",
@ -31,8 +32,8 @@
"zone.js": "~0.10.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^0.1000.0",
"@angular/cli": "~10.0.0",
"@angular-devkit/build-angular": "^0.1002.0",
"@angular/cli": "~10.2.0",
"@angular/compiler-cli": "~10.0.0",
"@angular/language-service": "~10.0.0",
"@schematics/angular": "~9.1.0",

View File

@ -12,6 +12,10 @@ const routes: Routes = [
loadChildren: () =>
import('./main-view/main-view.module').then((m) => m.MainViewModule),
},
{
path: 'auth',
loadChildren: () => import('./auth/auth.module').then((m) => m.AuthModule),
},
];
@NgModule({

View File

@ -14,10 +14,15 @@ import {
NbMenuModule,
NbToastrModule,
} from '@nebular/theme';
import {
NbPasswordAuthStrategy,
NbAuthModule,
NbAuthJWTToken,
} from '@nebular/auth';
import { FrontPageModule } from './front-page/front-page.module';
import { SharedDataService } from './_services/shared-data.service';
import { SidebarItemsService } from './_services/sidebar-items.service';
import { SharedDataService } from './services/shared-data.service';
import { SidebarItemsService } from './services/sidebar-items.service';
import { StoreModule } from '@ngrx/store';
import { reducers, metaReducers } from './reducers';
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
@ -36,6 +41,37 @@ import { EffectsModule } from '@ngrx/effects';
NbEvaIconsModule,
FrontPageModule,
NbToastrModule.forRoot(),
NbAuthModule.forRoot({
strategies: [
NbPasswordAuthStrategy.setup({
name: 'email',
baseEndpoint: 'http://127.0.0.1:8000',
login: {
endpoint: '/login/',
redirect: {
success: '/my-profile',
failure: null,
},
defaultErrors: ['Coś poszło nie tak, proszę spróbować ponownie.'],
},
token: {
class: NbAuthJWTToken,
key: 'token',
},
register: {
endpoint: '/user/',
requireValidToken: false,
method: 'post',
redirect: {
success: '/auth/register-success',
failure: null,
},
defaultErrors: ['Coś poszło nie tak, proszę spróbować ponownie.'],
},
}),
],
forms: {},
}),
StoreModule.forRoot(reducers, {
metaReducers,
}),

View File

@ -0,0 +1,33 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { NbAuthComponent } from '@nebular/auth';
import { LoginComponent } from './login/login.component';
import { RegisterSuccessComponent } from './register-success/register-success.component';
import { RegisterComponent } from './register/register.component';
export const routes: Routes = [
{
path: '',
component: NbAuthComponent,
children: [
{
path: 'login',
component: LoginComponent,
},
{
path: 'register',
component: RegisterComponent,
},
{
path: 'register-success',
component: RegisterSuccessComponent,
},
],
},
];
@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class AuthRoutingModule {}

View File

@ -0,0 +1,32 @@
import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router';
import { AuthRoutingModule } from './auth-routing.module';
import { NbAuthModule } from '@nebular/auth';
import {
NbAlertModule,
NbButtonModule,
NbCheckboxModule,
NbInputModule,
} from '@nebular/theme';
import { LoginComponent } from './login/login.component';
import { RegisterComponent } from './register/register.component';
import { RegisterSuccessComponent } from './register-success/register-success.component';
@NgModule({
imports: [
CommonModule,
FormsModule,
RouterModule,
NbAlertModule,
NbInputModule,
NbButtonModule,
NbCheckboxModule,
AuthRoutingModule,
NbAuthModule,
],
declarations: [LoginComponent, RegisterComponent, RegisterSuccessComponent],
})
export class AuthModule {}

View File

@ -0,0 +1,98 @@
<h1 id="title" class="title">Logowanie</h1>
<p class="sub-title">Zaloguj się przy pomocy adresu e-mail</p>
<nb-alert
*ngIf="showMessages.error && errors?.length && !submitted"
outline="danger"
role="alert"
>
<p class="alert-title"><b>Pojawił się błąd!</b></p>
<ul class="alert-message-list">
<li *ngFor="let error of errors" class="alert-message">{{ error }}</li>
</ul>
</nb-alert>
<nb-alert
*ngIf="showMessages.success && messages?.length && !submitted"
outline="success"
role="alert"
>
<p class="alert-title"><b>Udało się!</b></p>
<ul class="alert-message-list">
<li *ngFor="let message of messages" class="alert-message">
{{ message }}
</li>
</ul>
</nb-alert>
<form (ngSubmit)="login()" #form="ngForm" aria-labelledby="title">
<div class="form-control-group">
<label class="label" for="input-email">Adres email:</label>
<input
nbInput
fullWidth
[(ngModel)]="user.email"
#email="ngModel"
name="email"
id="input-email"
pattern=".+@.+\..+"
placeholder="Email address"
autofocus
[status]="email.dirty ? (email.invalid ? 'danger' : 'success') : 'basic'"
[required]="getConfigValue('forms.validation.email.required')"
[attr.aria-invalid]="email.invalid && email.touched ? true : null"
/>
<ng-container *ngIf="email.invalid && email.touched">
<nb-alert status="danger" class="custom-size-error" *ngIf="email.errors?.required">
E-mail jest wymagany!
</nb-alert>
<nb-alert status="danger" class="custom-size-error" *ngIf="email.errors?.pattern">
Adres e-mail powinien być prawdziwy!
</nb-alert>
</ng-container>
</div>
<div class="form-control-group">
<label class="label" for="input-password">Hasło:</label>
<input
nbInput
fullWidth
[(ngModel)]="user.password"
#password="ngModel"
name="password"
type="password"
id="input-password"
placeholder="Password"
[status]="
password.dirty ? (password.invalid ? 'danger' : 'success') : 'basic'
"
[required]="getConfigValue('forms.validation.password.required')"
[minlength]="getConfigValue('forms.validation.password.minLength')"
[maxlength]="getConfigValue('forms.validation.password.maxLength')"
[attr.aria-invalid]="password.invalid && password.touched ? true : null"
/>
<ng-container *ngIf="password.invalid && password.touched">
<nb-alert status="danger" class="custom-size-error" *ngIf="password.errors?.required">
Hasło jest wymagane
</nb-alert>
<nb-alert
class="custom-size-error"
*ngIf="password.errors?.minlength || password.errors?.maxlength"
>
Hasło powinno zawierać od
{{ getConfigValue("forms.validation.password.minLength") }} do
{{ getConfigValue("forms.validation.password.maxLength") }}
znaków
</nb-alert>
</ng-container>
</div>
<button
nbButton
fullWidth
status="success"
[disabled]="submitted || !form.valid"
[class.btn-pulse]="submitted"
>
Zaloguj
</button>
</form>

View File

@ -0,0 +1,5 @@
.custom-size-error {
padding: 0.5rem !important;
margin-top: 0.5rem !important;
margin-bottom: 0.5rem !important;
}

View File

@ -0,0 +1,11 @@
import { Component } from '@angular/core';
import { NbLoginComponent } from '@nebular/auth';
@Component({
selector: 'login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.scss']
})
export class LoginComponent extends NbLoginComponent {
}

View File

@ -0,0 +1,9 @@
<h1 id="title" class="title">Gratulacje!</h1>
<p class="sub-title">
Udało się utworzyć konto o podanym adresie e-mail. Naciśnij przycisk, aby
kontynuować
</p>
<button nbButton fullWidth status="success" routerLink="../login">
Zaloguj się
</button>

View File

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

View File

@ -0,0 +1,151 @@
<h1 id="title" class="title">Rejestracja</h1>
<nb-alert
*ngIf="showMessages.error && errors?.length && !submitted"
outline="danger"
role="alert"
>
<p class="alert-title"><b>Coś nie wyszło!</b></p>
<ul class="alert-message-list">
<li *ngFor="let error of errors" class="alert-message">{{ error }}</li>
</ul>
</nb-alert>
<nb-alert
*ngIf="showMessages.success && messages?.length && !submitted"
outline="success"
role="alert"
>
<p class="alert-title"><b>Udało się!</b></p>
<ul class="alert-message-list">
<li *ngFor="let message of messages" class="alert-message">
{{ message }}
</li>
</ul>
</nb-alert>
<form (ngSubmit)="register()" #form="ngForm" aria-labelledby="title">
<div class="form-control-group">
<label class="label" for="input-email">Adres e-mail:</label>
<input
nbInput
[(ngModel)]="user.email"
#email="ngModel"
id="input-email"
name="email"
pattern=".+@.+..+"
placeholder="Adres e-mail"
fullWidth
[status]="email.dirty ? (email.invalid ? 'danger' : 'success') : 'basic'"
[required]="getConfigValue('forms.validation.email.required')"
[attr.aria-invalid]="email.invalid && email.touched ? true : null"
/>
<ng-container *ngIf="email.invalid && email.touched">
<nb-alert
status="danger"
*ngIf="email.errors?.required"
class="custom-size-error"
>
Email jest wymagany!
</nb-alert>
<nb-alert
status="danger"
class="custom-size-error"
*ngIf="email.errors?.pattern"
>
Nieprawidłowy mail!
</nb-alert>
</ng-container>
</div>
<div class="form-control-group">
<label class="label" for="input-password">Hasło:</label>
<input
nbInput
[(ngModel)]="user.password"
#password="ngModel"
type="password"
id="input-password"
name="password"
placeholder="Wprowadź bezpieczne hasło"
fullWidth
[status]="email.dirty ? (email.invalid ? 'danger' : 'success') : 'basic'"
[required]="getConfigValue('forms.validation.password.required')"
[minlength]="getConfigValue('forms.validation.password.minLength')"
[maxlength]="getConfigValue('forms.validation.password.maxLength')"
[attr.aria-invalid]="password.invalid && password.touched ? true : null"
/>
<ng-container *ngIf="password.invalid && password.touched">
<nb-alert
status="danger"
class="custom-size-error"
*ngIf="password.errors?.required"
>
Hasło jest wymagane!
</nb-alert>
<nb-alert
status="danger"
class="custom-size-error"
*ngIf="password.errors?.minlength || password.errors?.maxlength"
>
Hasło powinno zawierać od
{{ getConfigValue("forms.validation.password.minLength") }} do
{{ getConfigValue("forms.validation.password.maxLength") }}
znaków
</nb-alert>
</ng-container>
</div>
<div class="form-control-group">
<label class="label" for="input-re-password">Powtórz hasło:</label>
<input
nbInput
[(ngModel)]="user.confirmPassword"
#rePass="ngModel"
type="password"
id="input-re-password"
name="rePass"
fullWidth
[status]="
email.dirty
? email.invalid || password.value != rePass.value
? 'danger'
: 'success'
: 'basic'
"
[required]="getConfigValue('forms.validation.password.required')"
[attr.aria-invalid]="rePass.invalid && rePass.touched ? true : null"
/>
<ng-container *ngIf="rePass.invalid && rePass.touched">
<nb-alert
status="danger"
class="custom-size-error"
*ngIf="rePass.errors?.required"
>
Musisz potwierdzić hasło!
</nb-alert>
<nb-alert
status="danger"
class="custom-size-error"
*ngIf="password.value != rePass.value && !rePass.errors?.required"
>
Hasła się nie zgadzają
</nb-alert>
</ng-container>
</div>
<button
nbButton
fullWidth
status="success"
[disabled]="submitted || !form.valid"
[class.btn-pulse]="submitted"
>
Utwórz konto
</button>
</form>
<section class="another-action" aria-label="Sign in">
Posiadasz już konto?
<a class="text-link" routerLink="../login">Zaloguj się</a>
</section>

View File

@ -0,0 +1,5 @@
.custom-size-error {
padding: 0.5rem !important;
margin-top: 0.5rem !important;
margin-bottom: 0.5rem !important;
}

View File

@ -0,0 +1,11 @@
import { Component } from '@angular/core';
import { NbRegisterComponent } from '@nebular/auth';
@Component({
selector: 'register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.scss'],
})
export class RegisterComponent extends NbRegisterComponent {
}

View File

@ -1,12 +1,11 @@
import { Injectable } from '@angular/core';
import { SendDataService } from '../_services/send-data.service';
import { SendDataService } from '../services/send-data.service';
import * as FrontPageActions from '../actions/front-page.actions';
import * as FrontPageSelectors from '../selectors/front-page.selectors';
import { Actions, ofType, createEffect } from '@ngrx/effects';
import { State as AppState } from '../reducers/index';
import { Store } from '@ngrx/store';
import {
exhaustMap,
withLatestFrom,
tap,
map,
@ -51,9 +50,17 @@ export class FrontPageEffect {
ofType(FrontPageActions.sendFileError),
tap(({ error }) => {
if (error.status === 406) {
this.toastService.danger('', 'Format pliku jest niepoprawny!', {
this.toastService.danger('', 'Format pliku jest niepoprawny', {
icon: 'alert-circle',
});
} else {
this.toastService.danger(
'',
'Coś poszło nie tak, spróbuj ponownie',
{
icon: 'alert-circle',
}
);
}
})
),

View File

@ -3,8 +3,12 @@
<div class="header__container">
<div class="header__logo-container"><span>nkadf</span></div>
<div class="header__buttons-container">
<!-- <button nbButton outline status="primary">Zaloguj</button>
<button nbButton outline status="success">Utwórz konto</button> -->
<button nbButton outline status="primary" (click)="login()">
Zaloguj
</button>
<button nbButton outline status="success" (click)="register()">
Zarejestruj się
</button>
</div>
</div>
</nb-layout-header>

View File

@ -4,6 +4,7 @@ import { State } from '../reducers/index';
import { Observable } from 'rxjs';
import * as Selectors from '../selectors/front-page.selectors';
import { fetchFile, sendFile } from '../actions/front-page.actions';
import { Router } from '@angular/router';
@Component({
selector: 'app-front-page',
@ -15,7 +16,7 @@ export class FrontPageComponent implements OnInit {
fileName$: Observable<string>;
isFileFetched$: Observable<boolean>;
constructor(private store: Store<State>) {}
constructor(private store: Store<State>, private router: Router) {}
ngOnInit() {
this.file$ = this.store.select(Selectors.selectFile);
@ -29,7 +30,6 @@ export class FrontPageComponent implements OnInit {
openFileDialog(event: any): void {
event.preventDefault();
const element: HTMLElement = document.getElementById(
'input-for-file'
) as HTMLElement;
@ -40,6 +40,14 @@ export class FrontPageComponent implements OnInit {
this.store.dispatch(fetchFile({ file: event.target.files[0] }));
}
login(): void {
this.router.navigate(['/auth/login']);
}
register(): void {
this.router.navigate(['/auth/register']);
}
sendFile(event: any): void {
this.store.dispatch({ type: '[FrontPage Component] Send File' });
}

View File

@ -1,7 +1,6 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FrontPageComponent } from './front-page.component';
import { SendDataService } from '../_services/send-data.service';
import {
NbLayoutModule,
NbButtonModule,
@ -11,6 +10,7 @@ import {
} from '@nebular/theme';
import { EffectsModule } from '@ngrx/effects';
import { FrontPageEffect } from '../effects/front-page.effects';
import { SendDataService } from '../services/send-data.service';
@NgModule({
declarations: [FrontPageComponent],

View File

@ -4,13 +4,13 @@ import {
OnDestroy,
ChangeDetectionStrategy,
} from '@angular/core';
import { SharedDataService } from '../../_services/shared-data.service';
import { SharedDataService } from '../../services/shared-data.service';
import { Colors } from '../../_types/color';
import { CustomForumData } from '../../_interfaces/customforumdata';
import { Subscription } from 'rxjs';
import { NbMenuItem } from '@nebular/theme';
import { Router } from '@angular/router';
import { MapIdService } from 'src/app/_services/map-id.service';
import { MapIdService } from 'src/app/services/map-id.service';
// interface CustomForumData {
// id: string;

View File

@ -1,10 +1,10 @@
import { Component, OnInit, OnDestroy } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { GetDiscussionService } from '../../_services/get-discussion.service';
import { GetDiscussionService } from '../../services/get-discussion.service';
import { PredictedPost } from '../../_interfaces/predictedposts';
import { Subscription } from 'rxjs';
import { concatMap, defaultIfEmpty, map } from 'rxjs/operators';
import { ParagraphService } from 'src/app/_services/paragraph.service';
import { ParagraphService } from 'src/app/services/paragraph.service';
import {
NbToastrService,
NbLayoutScrollService,

View File

@ -1,11 +1,11 @@
import { Component, OnInit, AfterContentInit } from '@angular/core';
import { Router } from '@angular/router';
import { SharedDataService } from '../_services/shared-data.service';
import { SharedDataService } from '../services/shared-data.service';
import { NbSidebarService, NbMenuItem } from '@nebular/theme';
import { Subscription } from 'rxjs';
import { SidebarItemsService } from '../_services/sidebar-items.service';
import { SidebarItemsService } from '../services/sidebar-items.service';
import { CustomForumData } from '../_interfaces/customforumdata';
@Component({

View File

@ -6,9 +6,9 @@ import { DiscussionChooserComponent } from './discussion-chooser/discussion-choo
import { MainViewRoutingModule } from './main-view-routing.module';
import { DiscussionViewerComponent } from './discussion-viewer/discussion-viewer.component';
import { GetDiscussionService } from '../_services/get-discussion.service';
import { ParagraphService } from '../_services/paragraph.service';
import { MapIdService } from '../_services/map-id.service';
import { GetDiscussionService } from '../services/get-discussion.service';
import { ParagraphService } from '../services/paragraph.service';
import { MapIdService } from '../services/map-id.service';
import { StyledParagraphComponent } from './styled-paragraph/styled-paragraph.component';
import { IdToNamePipe } from '../_pipes/id-to-name.pipe';

View File

@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { ParagraphService } from 'src/app/_services/paragraph.service';
import { ParagraphService } from 'src/app/services/paragraph.service';
@Component({
selector: 'app-styled-paragraph',

View File

@ -6,7 +6,7 @@ import {
AfterViewInit,
} from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { GetVisualizationDataService } from '../../_services/get-visualization-data.service';
import { GetVisualizationDataService } from '../../services/get-visualization-data.service';
import { Subscription } from 'rxjs';
import { concatMap } from 'rxjs/operators';
import { Post } from 'src/app/_interfaces/post';

View File

@ -2,7 +2,7 @@ import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { VisualizeForumComponent } from './visualize-forum.component';
import { VisualizeForumRoutingModule } from './visualize-forum-routing.module';
import { GetVisualizationDataService } from '../../_services/get-visualization-data.service';
import { GetVisualizationDataService } from '../../services/get-visualization-data.service';
@NgModule({
declarations: [VisualizeForumComponent],

View File

@ -0,0 +1,9 @@
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class AuthGuardService {
constructor() { }
}

View File

@ -1,9 +1,11 @@
@import "themes";
@import "~@nebular/theme/styles/globals";
@import "~@nebular/auth/styles/globals";
@include nb-install() {
@include nb-theme-global();
@include nb-auth-global();
}
/* You can add global styles to this file, and also import other style files */
.menu-title {