login, approval

parent bd1ea5e9
plugins { plugins {
id 'java' id 'java'
id "com.github.node-gradle.node" version "2.2.4" id "com.github.node-gradle.node" version "2.2.4"
id 'war' id 'war'
} }
...@@ -11,8 +10,8 @@ repositories { ...@@ -11,8 +10,8 @@ repositories {
} }
node { node {
version = '12.18.2' version = '14.15.5'
npmVersion = '7.15.0' npmVersion = '6.14.11'
download = true download = true
} }
......
...@@ -3,18 +3,25 @@ import { RouterModule, Routes } from '@angular/router'; ...@@ -3,18 +3,25 @@ import { RouterModule, Routes } from '@angular/router';
import {HomeComponent} from './component/home/home.component'; import {HomeComponent} from './component/home/home.component';
import {ResourceComponent} from "./component/resource/resource.component"; import {ResourceComponent} from "./component/resource/resource.component";
import {AddResourceComponent} from "./component/add-resource/add-resource.component"; import {AddResourceComponent} from "./component/add-resource/add-resource.component";
import {ApproveResourceComponent} from "./component/approve-resource/approve-resource.component";
import {LoginComponent} from "./component/login/login.component";
import {AuthGuard} from "./guard/auth.guard";
const routes: Routes = [ const routes: Routes = [
{path: '', component: HomeComponent, pathMatch: 'full'}, {path: '', component: HomeComponent, pathMatch: 'full'},
{path: 'home', component: HomeComponent, pathMatch: 'full'}, {path: 'home', component: HomeComponent, pathMatch: 'full',runGuardsAndResolvers: 'always'},
{path:'resource/approve', component:ApproveResourceComponent, pathMatch:'full',canActivate:[AuthGuard]},
{path:'resource/add', component:AddResourceComponent, pathMatch:'full'}, {path:'resource/add', component:AddResourceComponent, pathMatch:'full'},
{path:'resource/:id', component:ResourceComponent, pathMatch:'full'} {path:'resource/:id', component:ResourceComponent, pathMatch:'full'},
{path:'login', component:LoginComponent, pathMatch:'full'},
]; ];
@NgModule({ @NgModule({
imports: [RouterModule.forRoot(routes)], imports: [RouterModule.forRoot(routes,{ onSameUrlNavigation: 'reload' })],
exports: [RouterModule] exports: [RouterModule]
}) })
export class AppRoutingModule { } export class AppRoutingModule { }
<p-menubar> <app-header-menu></app-header-menu>
<ng-template pTemplate="start"> <div class="container-fluid py-4">
<img src="assets/logo-white.png" height="50" class="p-mr-2" routerLink="/home"alt="brand logo"> <router-outlet></router-outlet>
</ng-template> </div>
<ng-template pTemplate="end">
<p-button label="Login" icon="pi pi-login" iconPos="left" styleClass="buttonColor"></p-button>
</ng-template>
</p-menubar>
<div class="container-fluid py-4">
<router-outlet></router-outlet>
</div>
import {Component, ViewEncapsulation} from '@angular/core'; import {Component, OnDestroy, OnInit} from "@angular/core";
import {MenuItem, PrimeNGConfig} from "primeng/api"; import {LogoutAction, UserState} from "./states/user.state";
import {filter, takeUntil} from "rxjs/operators";
import {NavigationEnd, Router} from "@angular/router";
import {MenuItem, MessageService, PrimeNGConfig} from "primeng/api";
import {Select, Store} from "@ngxs/store";
import {Observable, Subject} from "rxjs";
import {User} from "./model/user";
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
templateUrl: './app.component.html', templateUrl: './app.component.html',
styleUrls: ['./app.component.css'] styleUrls: ['./app.component.css']
}) })
export class AppComponent {
title = 'ipmworks-web';
items: MenuItem[] = [] ;
constructor(private primengConfig: PrimeNGConfig) { }
ngOnInit() { export class AppComponent{
title = 'ipmworks-web';
constructor(private primengConfig: PrimeNGConfig, private store: Store, private router: Router,private messageService: MessageService) {}
}
} }
...@@ -10,11 +10,11 @@ import {HomeComponent} from './component/home/home.component'; ...@@ -10,11 +10,11 @@ import {HomeComponent} from './component/home/home.component';
import {AccordionModule} from 'primeng/accordion'; import {AccordionModule} from 'primeng/accordion';
import {MessageService, SharedModule} from "primeng/api"; import {MessageService, SharedModule} from "primeng/api";
import {CheckboxModule} from 'primeng/checkbox'; import {CheckboxModule} from 'primeng/checkbox';
import {FormsModule} from "@angular/forms"; import {FormsModule, ReactiveFormsModule} from "@angular/forms";
import {DataViewModule} from "primeng/dataview"; import {DataViewModule} from "primeng/dataview";
import {RatingModule} from "primeng/rating"; import {RatingModule} from "primeng/rating";
import {RouterModule} from "@angular/router"; import {RouterModule} from "@angular/router";
import {HttpClientModule} from "@angular/common/http"; import {HTTP_INTERCEPTORS, HttpClientModule} from "@angular/common/http";
import {MultiSelectModule} from 'primeng/multiselect'; import {MultiSelectModule} from 'primeng/multiselect';
import {DropdownModule} from "primeng/dropdown"; import {DropdownModule} from "primeng/dropdown";
import {InputTextModule} from "primeng/inputtext"; import {InputTextModule} from "primeng/inputtext";
...@@ -34,8 +34,19 @@ import {PanelModule} from "primeng/panel"; ...@@ -34,8 +34,19 @@ import {PanelModule} from "primeng/panel";
import {HashLocationStrategy, LocationStrategy} from "@angular/common"; import {HashLocationStrategy, LocationStrategy} from "@angular/common";
import {CascadeSelectModule} from 'primeng/cascadeselect'; import {CascadeSelectModule} from 'primeng/cascadeselect';
import {DialogModule} from 'primeng/dialog'; import {DialogModule} from 'primeng/dialog';
import { ApproveResourceComponent } from './component/approve-resource/approve-resource.component';
import {TableModule} from "primeng/table";
import { LoginComponent } from './component/login/login.component';
import {NgxsStoragePluginModule} from '@ngxs/storage-plugin';
import {NgxsModule} from '@ngxs/store';
import {UserState} from "./states/user.state";
import {environment} from "../environments/environment";
import {AuthInterceptor} from "./guard/auth.interceptor";
import { HeaderMenuComponent } from './component/header-menu/header-menu.component';
import {ImageModule} from "primeng/image";
import {ConfirmPopupModule} from 'primeng/confirmpopup';
import {ConfirmationService} from 'primeng/api';
import {ConfirmDialogModule} from "primeng/confirmdialog";
@NgModule({ @NgModule({
...@@ -43,45 +54,60 @@ import {DialogModule} from 'primeng/dialog'; ...@@ -43,45 +54,60 @@ import {DialogModule} from 'primeng/dialog';
AppComponent, AppComponent,
HomeComponent, HomeComponent,
ResourceComponent, ResourceComponent,
AddResourceComponent AddResourceComponent,
ApproveResourceComponent,
LoginComponent,
HeaderMenuComponent
],
imports: [
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
MenubarModule,
ButtonModule,
MenuModule,
AccordionModule,
SharedModule,
CheckboxModule,
FormsModule,
DataViewModule,
RatingModule,
RouterModule,
HttpClientModule,
MultiSelectModule,
DropdownModule,
InputTextModule,
TooltipModule,
CardModule,
TagModule,
InputTextModule,
CheckboxModule,
ButtonModule,
RadioButtonModule,
InputTextareaModule,
FileUploadModule,
ChipsModule,
MessagesModule,
MessageModule,
ToastModule,
PanelModule,
CascadeSelectModule,
DialogModule,
TableModule,
NgxsModule.forRoot([UserState], {developmentMode: !environment.production}),
NgxsStoragePluginModule.forRoot(),
ReactiveFormsModule,
ToastModule,
ImageModule,
ConfirmPopupModule,
ConfirmDialogModule
], ],
imports: [ providers: [MessageService,ConfirmationService,{
BrowserModule,
BrowserAnimationsModule,
AppRoutingModule,
MenubarModule,
ButtonModule,
MenuModule,
AccordionModule,
SharedModule,
CheckboxModule,
FormsModule,
DataViewModule,
RatingModule,
RouterModule,
HttpClientModule,
MultiSelectModule,
DropdownModule,
InputTextModule,
TooltipModule,
CardModule,
TagModule,
InputTextModule,
CheckboxModule,
ButtonModule,
RadioButtonModule,
InputTextareaModule,
FileUploadModule,
ChipsModule,
MessagesModule,
MessageModule,
ToastModule,
PanelModule,
CascadeSelectModule,
DialogModule
],
providers: [MessageService,{
provide: LocationStrategy, useClass: HashLocationStrategy, provide: LocationStrategy, useClass: HashLocationStrategy,
},{
provide: HTTP_INTERCEPTORS,
useClass: AuthInterceptor,
multi: true
}], }],
bootstrap: [AppComponent] bootstrap: [AppComponent]
}) })
......
.button-center{
display: flex;
justify-content: space-around;
}
...@@ -164,8 +164,9 @@ ...@@ -164,8 +164,9 @@
</div> </div>
</div> </div>
</div> </div>
<div class="col-12 pt-3 button-center"> <div class="col-12 pt-3 justify-content-center flex" >
<p-button label="Save resource" icon="pi pi-save"[loading]="false" [disabled]="resourceForm.form.invalid" (submit)="saveResource();resourceForm.control.markAsTouched()"></p-button> <p-button label="Back" icon="pi pi-step-backward" class="pr-5"routerLink="/home" type="button" ></p-button>
<p-button label="Save resource" icon="pi pi-save" [loading]="false" type="submit" [disabled]="resourceForm.form.invalid"></p-button>
</div> </div>
</form> </form>
</div> </div>
......
...@@ -53,7 +53,7 @@ export class AddResourceComponent implements OnInit { ...@@ -53,7 +53,7 @@ export class AddResourceComponent implements OnInit {
this.resource = data; this.resource = data;
this.resourceService.addFiles(this.image, this.resourceContent, this.resource.idResource).subscribe(data => { this.resourceService.addFiles(this.image, this.resourceContent, this.resource.idResource).subscribe(data => {
this.messageService.add({severity: 'success', detail: 'Resource is saved, but need to be approved by administrator!'}); this.messageService.add({severity: 'success', detail: 'Resource is saved, but need to be approved by administrator!'});
this.router.navigate(['/home']); this.router.navigate(['/resource/add']);
}, error => { }, error => {
this.messageService.add({severity: 'error', detail: 'Some error occurred!'}) this.messageService.add({severity: 'error', detail: 'Some error occurred!'})
......
<div class="card pt-6 pl-6 pr-6">
<p class="text-3xl"> Approve resources</p>
<p-table [value]="resources" [paginator]="true" [rows]="10" >
<ng-template pTemplate="header">
<tr>
<th>Resource name</th>
<th>Resource type</th>
<th>Creation date</th>
<th></th>
</tr>
</ng-template>
<ng-template pTemplate="body" let-resource>
<tr>
<td>{{resource.resourceName}}</td>
<td>{{resource.resourceType?.name}}</td>
<td>{{resource.creationDate| date:"d.M.yyyy, h:mm a"}}</td>
<td>
<button pButton type="button" routerLink="/resource/{{resource.idResource}}" icon="pi pi-pencil"></button>
</td>
</tr>
</ng-template>
</p-table>
</div>
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ApproveResourceComponent } from './approve-resource.component';
describe('ApproveResourceComponent', () => {
let component: ApproveResourceComponent;
let fixture: ComponentFixture<ApproveResourceComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ ApproveResourceComponent ]
})
.compileComponents();
});
beforeEach(() => {
fixture = TestBed.createComponent(ApproveResourceComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit } from '@angular/core';
import {TableModule} from 'primeng/table';
import {PageableResource, Resource} from "../../model/resource";
import {ResourceService} from "../../service/resource.service";
@Component({
selector: 'app-approve-resource',
templateUrl: './approve-resource.component.html',
styleUrls: ['./approve-resource.component.css']
})
export class ApproveResourceComponent implements OnInit {
resources: Resource[] = [];
constructor(private resourceService:ResourceService) { }
ngOnInit(): void {
this.resourceService.getResourcesForApproval().subscribe((resources: Resource[]) => {
// @ts-ignore
this.resources = resources});
}
}
import { TestBed } from '@angular/core/testing';
import { AuthGuard } from './auth.guard';
describe('AuthGuard', () => {
let guard: AuthGuard;
beforeEach(() => {
TestBed.configureTestingModule({});
guard = TestBed.inject(AuthGuard);
});
it('should be created', () => {
expect(guard).toBeTruthy();
});
});
import { Injectable } from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree} from '@angular/router';
import { Observable } from 'rxjs';
import {Store} from "@ngxs/store";
import {UserState} from "../states/user.state";
@Injectable({
providedIn: 'root'
})
export class AuthGuard implements CanActivate {
constructor(private router: Router, private store: Store) {
}
// @ts-ignore
canActivate(){
const token = this.store.selectSnapshot(UserState.getToken);
const userroles = this.store.selectSnapshot(UserState.getRoles);
if (token == null) {
this.router.navigate(['/login']);
}
else if (userroles?.includes('ADMIN')) {
return true;
}else {
this.router.navigate(['/home']);
}
}
}
import { TestBed } from '@angular/core/testing';
import { AuthInterceptor } from './auth.interceptor';
describe('AuthInterceptor', () => {
beforeEach(() => TestBed.configureTestingModule({
providers: [
AuthInterceptor
]
}));
it('should be created', () => {
const interceptor: AuthInterceptor = TestBed.inject(AuthInterceptor);
expect(interceptor).toBeTruthy();
});
});
import {Injectable} from "@angular/core";
import {HttpEvent, HttpHandler, HttpInterceptor, HttpRequest} from "@angular/common/http";
import {Store} from "@ngxs/store";
import {Observable} from "rxjs";
import {UserState} from "../states/user.state";
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private store: Store) {
}
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const token = this.store.selectSnapshot(UserState.getToken);
if (token != null) {
request = request.clone({
setHeaders: {
Authorization: 'Bearer ' + token,
}
});
}
return next.handle(request);
}
}
...@@ -6,21 +6,27 @@ export class AppConfig { ...@@ -6,21 +6,27 @@ export class AppConfig {
public static ApiPaths = { public static ApiPaths = {
getAllResources: `${AppConfig.Origin}/resource/getAllResources`, getAllResources: `${AppConfig.Origin}/resource/getAllResources`,
getResourcesForApproval: `${AppConfig.Origin}/admin/getResourceForApproval`,
getResource: `${AppConfig.Origin}/resource/get`, getResource: `${AppConfig.Origin}/resource/get`,
approveResource: `${AppConfig.Origin}/admin/approve`,
getFile: `${AppConfig.Origin}/resource/file`, getFile: `${AppConfig.Origin}/resource/file`,
saveResource: `${AppConfig.Origin}/resource/saveResource`, saveResource: `${AppConfig.Origin}/resource/saveResource`,
addFile: `${AppConfig.Origin}/resource/add`, searchResource: `${AppConfig.Origin}/resource/search`,
addFile: `${AppConfig.Origin}/resource/add`,
getAllLanguages: `${AppConfig.Origin}/codebooks/getAllLanguages`, getAllLanguages: `${AppConfig.Origin}/codebooks/getAllLanguages`,
getAllSectors: `${AppConfig.Origin}/codebooks/getAllSectors`, getAllSectors: `${AppConfig.Origin}/codebooks/getAllSectors`,
getAllRegions: `${AppConfig.Origin}/codebooks/getAllRegions`, getAllCountries: `${AppConfig.Origin}/codebooks/getAllCountries`,
getAllResourceTypes: `${AppConfig.Origin}/codebooks/getAllResourceTypes`, getAllResourceTypes: `${AppConfig.Origin}/codebooks/getAllResourceTypes`,
getAllProjects: `${AppConfig.Origin}/codebooks/getAllProjects`, getAllProjects: `${AppConfig.Origin}/codebooks/getAllProjects`,
getAllPests: `${AppConfig.Origin}/codebooks/getAllPests`, getAllPests: `${AppConfig.Origin}/codebooks/getAllPests`,
getAllCrops: `${AppConfig.Origin}/codebooks/getAllCrops`, getAllCrops: `${AppConfig.Origin}/codebooks/getAllCrops`,
getAllKeywords: `${AppConfig.Origin}/codebooks/getAllKeywords` getAllKeywords: `${AppConfig.Origin}/codebooks/getAllKeywords`,
login:`${AppConfig.Origin}/authenticate`
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment