last version-refactoring

parent d44dbdac
......@@ -5985,6 +5985,14 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true
},
"ng-lazyload-image": {
"version": "9.1.2",
"resolved": "https://registry.npmjs.org/ng-lazyload-image/-/ng-lazyload-image-9.1.2.tgz",
"integrity": "sha512-E5oz5HdTRtYW/TH+jceT4VMcRXKdX9Ut82eEwt2K0/bFAXKU14HluCFa8cMidPBgSa08Mlf+gmoKCTvAfUPgag==",
"requires": {
"tslib": "^2.3.0"
}
},
"nice-napi": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/nice-napi/-/nice-napi-1.0.2.tgz",
......
......@@ -21,6 +21,7 @@
"@ngxs/storage-plugin": "^3.5.0",
"@ngxs/store": "^3.5.0",
"lazysizes": "^5.3.2",
"ng-lazyload-image": "^9.1.2",
"primeflex": "~3.1.3",
"primeicons": "~5.0.0",
"primeng": "~13.2.1",
......
......@@ -6,15 +6,17 @@ import {AddResourceComponent} from "./component/add-resource/add-resource.compon
import {ApproveResourceComponent} from "./component/approve-resource/approve-resource.component";
import {LoginComponent} from "./component/login/login.component";
import {AuthGuard} from "./guard/auth.guard";
import {ChangePasswordComponent} from "./component/change-password/change-password.component";
const routes: Routes = [
{path: '', component: HomeComponent, pathMatch: 'full'},
{path: 'home', component: HomeComponent, pathMatch: 'full',runGuardsAndResolvers: 'always'},
{path: 'home', component: HomeComponent, pathMatch: 'full'},
{path:'resource/approve', component:ApproveResourceComponent, pathMatch:'full',canActivate:[AuthGuard]},
{path:'resource/add', component:AddResourceComponent, pathMatch:'full'},
{path:'resource/edit/:id',component:AddResourceComponent,pathMatch:'full',canActivate:[AuthGuard]},
{path:'resource/:id', component:ResourceComponent, pathMatch:'full'},
{path:'login', component:LoginComponent, pathMatch:'full'},
{path:'changePassword/:token', component:ChangePasswordComponent, pathMatch:'full'}
......
......@@ -2,3 +2,4 @@
<div class="container-fluid py-4">
<router-outlet></router-outlet>
</div>
<app-footer></app-footer>
......@@ -47,7 +47,10 @@ import {ImageModule} from "primeng/image";
import {ConfirmPopupModule} from 'primeng/confirmpopup';
import {ConfirmationService} from 'primeng/api';
import {ConfirmDialogModule} from "primeng/confirmdialog";
import {LAZYLOAD_IMAGE_HOOKS, LazyLoadImageModule, ScrollHooks} from 'ng-lazyload-image';
import { FooterComponent } from './component/footer/footer.component';
import { ChangePasswordComponent } from './component/change-password/change-password.component';
import { CheckPasswordDirective } from './validator/check-password.directive';
@NgModule({
declarations: [
......@@ -57,7 +60,10 @@ import {ConfirmDialogModule} from "primeng/confirmdialog";
AddResourceComponent,
ApproveResourceComponent,
LoginComponent,
HeaderMenuComponent
HeaderMenuComponent,
FooterComponent,
ChangePasswordComponent,
CheckPasswordDirective
],
imports: [
BrowserModule,
......@@ -100,9 +106,11 @@ import {ConfirmDialogModule} from "primeng/confirmdialog";
ToastModule,
ImageModule,
ConfirmPopupModule,
ConfirmDialogModule
ConfirmDialogModule,
LazyLoadImageModule
],
providers: [MessageService,ConfirmationService,{
providers: [MessageService,ConfirmationService,
{
provide: LocationStrategy, useClass: HashLocationStrategy,
},{
provide: HTTP_INTERCEPTORS,
......
.imageSizeHome{
max-width: 100%;
max-height: 120px;
display: block;
margin-left: auto;
margin-right: auto;
}
<div class="card pt-6 pl-6 pr-6">
<p class="text-3xl"> Add resource</p>
<p *ngIf="(!edit)" class="text-3xl"> Add resource</p>
<p *ngIf="(edit)" class="text-3xl"> Edit resource</p>
<form #resourceForm="ngForm" (ngSubmit)="saveResource()">
<div class="p-fluid">
<div class="field grid">
......@@ -103,14 +104,39 @@
<div class="field grid">
<label class="col-12 mb-2 md:col-2 md:mb-0">Language</label>
<div class="col-12 md:col-10">
<p-dropdown [options]="languages" optionLabel="name" name="language" placeholder="Select language" [(ngModel)]="resource.language"></p-dropdown>
<p-dropdown [options]="languages" optionLabel="name" name="languages" placeholder="Select language" [(ngModel)]="resource.language"></p-dropdown>
</div>
</div>
<div class="field grid">
<div *ngIf="logoExist" class="field grid">
<label class="col-12 mb-2 md:col-2 md:mb-0">Project logo</label>
<div class="col-12 md:col-10">
<p-fileUpload name="logo" (onRemove) = removeLogo() [maxFileSize]=5242880 chooseLabel="Change project logo" (onSelect)=hideOldLogo() [previewWidth]=250 [auto]=true accept="image/*" [showUploadButton]=false [customUpload]=true (uploadHandler)="fileUploader('logo',$event)">
<ng-template pTemplate="content" let-files >
<p-image [src]="imagePath+'/'+resource.idResource+'/logo'" *ngIf="showOldLogo" [preview]="true" width="250"></p-image>
</ng-template>
</p-fileUpload>
</div>
</div>
<div class="field grid" *ngIf="!edit || !logoExist">
<label class="col-12 mb-2 md:col-2 md:mb-0">Upload project logo</label>
<div class="col-12 md:col-10">
<p-fileUpload name="logo" [previewWidth]=250 [auto]=true accept="image/*" [maxFileSize]=5242880 [auto]=true [showUploadButton]=false [customUpload]=true (uploadHandler)="fileUploader('logo',$event)"></p-fileUpload>
</div>
</div>
<div *ngIf="imageExist" class="field grid">
<label class="col-12 mb-2 md:col-2 md:mb-0">Uploaded image</label>
<div class="col-12 md:col-10">
<p-fileUpload name="image" (onRemove) = removeImage() [maxFileSize]=5242880 chooseLabel="Change image" (onSelect)=hideOldImage() [previewWidth]=250 [auto]=true accept="image/*" [showUploadButton]=false [customUpload]=true (uploadHandler)="fileUploader('image',$event)">
<ng-template pTemplate="content" let-files >
<p-image [src]="imagePath+'/'+resource.idResource+'/image'" *ngIf="showOldImg" [preview]="true" width="250"></p-image>
</ng-template>
</p-fileUpload>
</div>
</div>
<div class="field grid" *ngIf="!edit || !imageExist">
<label class="col-12 mb-2 md:col-2 md:mb-0">Upload image</label>
<div class="col-12 md:col-10">
<p-fileUpload name="image" [maxFileSize]=5242880 [auto]=true [showUploadButton]=false [customUpload]=true (uploadHandler)="fileUploader('image',$event)"></p-fileUpload>
<p-fileUpload name="image" [previewWidth]=250 [auto]=true accept="image/*" [maxFileSize]=5242880 [auto]=true [showUploadButton]=false [customUpload]=true (uploadHandler)="fileUploader('image',$event)"></p-fileUpload>
</div>
</div>
<div class="field grid">
......@@ -164,10 +190,15 @@
</div>
</div>
</div>
<div class="col-12 pt-3 justify-content-center flex" >
<div class="col-12 pt-3 justify-content-center flex" *ngIf="!edit">
<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 class="col-12 pt-3 justify-content-center flex" *ngIf="edit" >
<p-button label="Back" icon="pi pi-step-backward" class="pr-5"routerLink="/resource/{{resource.idResource}}" type="button" ></p-button>
<p-button label="Save resource" icon="pi pi-save" [loading]="false" type="submit" [disabled]="resourceForm.form.invalid"></p-button>
</div>
</form>
</div>
<p-toast></p-toast>
......
......@@ -2,8 +2,9 @@ import { Component, OnInit } from '@angular/core';
import {ResourceType, Language, Region, Sector, Project, Resource, Pest, Crop} from "../../model/resource";
import {ResourceService} from "../../service/resource.service";
import {MessageService} from 'primeng/api';
import {Router} from "@angular/router";
import {ActivatedRoute, Router} from "@angular/router";
import {FormControl} from "@angular/forms";
import {environment} from "../../../environments/environment";
@Component({
......@@ -27,8 +28,16 @@ export class AddResourceComponent implements OnInit {
newPest:Pest = {};
newCrop: Crop = {};
resourceControl = new FormControl('');
resourceId?:string;
edit:boolean = false;
imageExist:boolean = false;
imagePath = environment.baseUrl+"/resource/image/raw";
showOldImg = true;
logo: any;
showOldLogo = true;
logoExist:boolean = false;
constructor(private resourceService:ResourceService,private messageService: MessageService, private router: Router) { }
constructor(private resourceService:ResourceService, private route: ActivatedRoute, private messageService: MessageService, private router: Router) { }
ngOnInit(): void {
this.resourceService.getAllSectors().subscribe((sectors: Sector[]) => {
......@@ -46,14 +55,39 @@ export class AddResourceComponent implements OnInit {
this.resourceService.getAllCrops().subscribe((crops: Crop[]) => {
this.crops = crops;});
// @ts-ignore
this.resourceId = this.route.snapshot.paramMap.get('id');
if(this.resourceId != undefined){
// @ts-ignore
this.resourceService.getResource(this.resourceId).subscribe(data =>{
this.resource = data;
this.edit = true;
});
this.resourceService.hasImage(this.resourceId,"image").subscribe( data =>{
this.imageExist = data
});
this.resourceService.hasImage(this.resourceId,"logo").subscribe( data =>{
this.logoExist = data
});
}
}
saveResource(){
this.resourceService.saveResource(this.resource).subscribe((data: Resource) => {
this.resourceService.saveResource(this.resource,this.edit).subscribe((data: Resource) => {
this.resource = 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.router.navigate(['/resource/add']);
console.log(this.image)
console.log(this.logo)
this.resourceService.addFiles(this.image, this.logo, this.resourceContent, this.resource.idResource).subscribe(data => {
if(!this.edit){
this.messageService.add({severity: 'success', detail: 'Resource is saved, but need to be approved by administrator!'});
this.router.navigate(['/home']);
}else{
this.messageService.add({severity: 'success', detail: 'Resource is updated!'});
this.router.navigate(['/resource/'+this.resourceId]);
}
}, error => {
this.messageService.add({severity: 'error', detail: 'Some error occurred!'})
......@@ -67,7 +101,11 @@ export class AddResourceComponent implements OnInit {
public fileUploader(type:string,event:any){
if(type === 'image'){
this.image = event.files[0]
}else{
}
else if(type === 'logo'){
this.logo = event.files[0]
}
else{
this.resourceContent = event.files;
}
}
......@@ -104,4 +142,18 @@ export class AddResourceComponent implements OnInit {
this.newCrop={};
this.displayCropModal=false;
}
hideOldImage(){
this.showOldImg = false;
}
removeImage(){
this.image=undefined;
this.showOldImg = true;
}
hideOldLogo(){
this.showOldLogo = false;
}
removeLogo(){
this.logo=undefined;
this.showOldLogo = true;
}
}
File mode changed from 100755 to 100644
......@@ -5,22 +5,22 @@
<div class="field">
<span class="p-float-label">
<input type="password" id="password" pInputText formControlName="password">
<label for="password" i18n="@@{new_password}">Enter new password...</label>
<label for="password">Enter new password...</label>
</span>
</div>
<div class="field">
<span class="p-float-label">
<input type="password" id="confirmedPassword" pInputText formControlName="confirmedPassword">
<label for="confirmedPassword" i18n="@@{retype_pass}">Retype password again...</label>
<label for="confirmedPassword">Retype password again...</label>
</span>
</div>
<div *ngIf="changeForm.errors?.['notSame'] && (changeForm.touched || changeForm.dirty)" class="text-xs p-error " i18n="@@{pass_error}">
<div *ngIf="changeForm.errors?.['notSame'] && (changeForm.touched || changeForm.dirty)" class="text-xs p-error ">
Passwords does not match!
</div>
</div>
<div class="field flex justify-content-center pt-4">
<p-button class="pr-4" type="submit" [disabled]="changeForm.invalid" (click)="changePassword()" i18n="@@{change_password}">Change password</p-button>
<p-button class="pr-4" type="submit" [disabled]="changeForm.invalid" (click)="changePassword()">Change password</p-button>
</div>
</form>
</div>
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -15,7 +15,7 @@
<img src="assets/EUFlag.png"/>
</div>
<div>
<p class="pl-5 pt-2 align-self-center" i18n="@@{project_ack}">
<p class="pl-5 pt-2 align-self-center">
This project has received funding from the European Union’s Horizon 2020 research and innovation programme under grant agreement No. 101000339.
</p>
</div>
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
<p-menubar [model]="items">
<ng-template pTemplate="start">
<img src="assets/logo-white.png" height="50" class="p-mr-2" routerLink="/home" alt="brand logo">
</ng-template>
<ng-template pTemplate="end">
<div *ngIf="!logged">
<p-button label="Login" icon="pi pi-login" iconPos="left" class="p-menuitem-text" routerLink="/login"></p-button>
</div>
<div *ngIf="logged">
<p-button label="Logout" icon="pi pi-login" iconPos="left" class="p-menuitem-text" routerLink="" (click)="logout()"></p-button>
</div>
<img src="assets/logo.jpg" height="97" class="pl-6 mr-8" routerLink="/home" alt="brand logo">
</ng-template>
</p-menubar>
<p-toast></p-toast>
......@@ -28,7 +28,7 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{
{
label: 'Home',
routerLink:'/home',
styleClass:"ml-5 pr-2 ",
styleClass:"pr-2 ",
},
{
label: 'Add resource',
......@@ -41,6 +41,24 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{
routerLink:'/resource/approve',
styleClass:"pr-2",
visible:this.isUserAdmin()
},
{
label: 'IPMWORKS',
url:'http://ipmworks.net',
styleClass:"pr-2",
target:"_blank"
},
{
label: 'Logout',
command:(event) => {this.logout()},
styleClass:"pr-2",
visible:this.logged
},
{
label: 'Login',
routerLink:'/login',
styleClass:"pr-2",
visible:!this.logged
}
]
}
......@@ -48,6 +66,7 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{
this.router.events.pipe(filter((event) => event instanceof NavigationEnd),
takeUntil(this.destroyed)
).subscribe(() => {
this.router.routeReuseStrategy.shouldReuseRoute = function() { return false; };
this.initialise();
});
}
......
......@@ -10,6 +10,7 @@
box-shadow: 0 2px 1px -1px rgba(0, 0, 0, 0.2), 0 1px 1px 0 rgba(0, 0, 0, 0.14), 0 1px 3px 0 rgba(0, 0, 0, 0.12);
border-radius: 4px;
margin-bottom: 2rem;
justify-content: space-between;
}
.button-center{
display: flex;
......
......@@ -3,18 +3,17 @@
<div class="col-3">
<form #searchForm="ngForm" (ngSubmit)="searchResource()">
<p class="text-xl">Sectors</p>
<p-multiSelect [selectionLimit]="1" defaultLabel="Select sector" [options]="sectors" name="sector" [(ngModel)]="searchModel.sector" optionLabel="name"></p-multiSelect>
<p-multiSelect defaultLabel="Select sector" [options]="sectors" name="sector" [(ngModel)]="searchModel.sector" optionLabel="name"></p-multiSelect>
<p class="text-xl">Country of origin</p>
<p-multiSelect [selectionLimit]="1" defaultLabel="Select region" [options]="regions" name="region" [(ngModel)]="searchModel.region" optionLabel="name"></p-multiSelect>
<p-multiSelect defaultLabel="Select region" [options]="regions" name="region" [(ngModel)]="searchModel.region" optionLabel="name"></p-multiSelect>
<!-- <div class="field">
<p class="text-xl">Pest type</p>
<p-dropdown autoWidth="false" [style]="{'width':'100%'}" placeholder="Select pest type" [options]="pestType" name="pestType"[(ngModel)]="searchModel.pestType" optionLabel="name" ></p-dropdown>
</div>-->
<p class="text-xl">Project</p>
<input id="project" type="text" pInputText name="project" [(ngModel)]="searchModel.project" placeholder="Add project">
<p-dropdown autoWidth="false" [style]="{'width':'100%'}" placeholder="Select projecte" [(ngModel)]="searchModel.project" [options]="projects" name="project" optionLabel="name" ></p-dropdown>
<p class="text-xl">Resource types</p>
<p-multiSelect placeholder="Select resource type" [selectionLimit]="1" name="resourceType" [(ngModel)]="searchModel.resourceType" [options]="contentTypes" optionLabel="name">
<p-multiSelect placeholder="Select resource type" name="resourceType" [(ngModel)]="searchModel.resourceType" [options]="contentTypes" optionLabel="name">
</p-multiSelect>
......@@ -27,7 +26,7 @@
</div>
<div *ngIf="more">
<p class="text-xl">Specific pest</p>
<p-multiSelect defaultLabel="Select pests" [selectionLimit]="1" [options]="pests" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="searchModel.pest" name="pest">
<p-multiSelect defaultLabel="Select pests" [options]="pests" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="searchModel.pest" name="pest">
<ng-template let-pest pTemplate="item">
<div>{{pest.commonName}} <i *ngIf="pest.latinName !=undefined">
({{pest.latinName}}, {{pest.eppo}})</i></div>
......@@ -36,7 +35,7 @@
<p class="text-xl">Specific crop</p>
<p-multiSelect defaultLabel="Select crops" [selectionLimit]="1" [options]="crops" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="searchModel.crop" name="crop">
<p-multiSelect defaultLabel="Select crops" [options]="crops" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="searchModel.crop" name="crop">
<ng-template let-crop pTemplate="item">
<div>{{crop.commonName}} <i *ngIf="crop.latinName !=undefined">
({{crop.latinName}}, {{crop.eppo}})</i></div>
......@@ -44,20 +43,25 @@
</p-multiSelect>
<p class="text-xl">Languages</p>
<p-multiSelect defaultLabel="Select language" [selectionLimit]="1" [options]="languages" name="language" [(ngModel)]="searchModel.language" optionLabel="name"></p-multiSelect>
<p-multiSelect defaultLabel="Select language" [options]="languages" name="language" [(ngModel)]="searchModel.language" optionLabel="name"></p-multiSelect>
<!--<h3>Arbitrary text search</h3>
<input type="text" pInputText [(ngModel)]="searchTerm"/>-->
</div>
<div class="pt-3 button-center">
<p-button type="submit" label="Search" icon="pi pi-search" [loading]="false"></p-button>
<div class="flex justify-content-center">
<div class="pt-3 pr-3">
<p-button type="submit" label="Search" [disabled] = "isEmptySearch()" icon="pi pi-search" [loading]="false"></p-button>
</div>
<div class="pt-3 pl-3">
<p-button type="submit" label="Reset" icon="pi pi-refresh" (click)="resetSearch()" [loading]="false"></p-button>
</div>
</div>
</form>
</div>
<div class="col-9">
<p-card>
<p-dataView [value]="resources" [lazy]="true" (onLazyLoad)="onPageChange($event)" (onPage)="onPageChange($event)" [totalRecords]="totalElements" [paginator]="true" [rowsPerPageOptions]=[10,50,100] [rows]="10" layout="grid">
<p-dataView [value]="resources" [lazy]="true" (onLazyLoad)="onPageChange($event)" (onPage)="onPageChange($event)" [totalRecords]="totalElements" [paginator]="true" [rowsPerPageOptions]=[12,24,48,96] [rows]="12" layout="grid">
<ng-template let-resource pTemplate="gridItem">
<div class="card col-12 md:col-4 flex flex-column p-3 mt-3" routerLink="/resource/{{resource.idResource}}">
<div class="pb-1 align-self-end">
......@@ -65,7 +69,7 @@
</p-tag>
</div>
<div class="">
<img [src]="imagePath+'/'+resource.idResource" class="imageSizeHome"/>
<img [defaultImage]="'assets/sectors/multi.jpg'" [useSrcset]="true" [lazyLoad]="imagePath+'/'+resource.idResource" class="imageSizeHome"/>
<p class="text-center">{{resource.resourceName}}</p>
</div>
<div class="align-self-center">
......
......@@ -25,9 +25,7 @@ export class HomeComponent implements OnInit{
resources: Resource[] = [];
pageableResponse?: PageableResource;
pageSize = 10;
currentPage = 0;
totalElements: number = 0;
elements?: Resource[] = [];
sectors: Sector[] = [];
regions: Region[] = [];
projects: Project[] = [];
......@@ -50,7 +48,8 @@ export class HomeComponent implements OnInit{
searchTerm: string = "";
more= false;
imagePath = environment.baseUrl+"/resource/image";
searchModel:SearchModel={};
imagePathRaw = environment.baseUrl+"/resource/image/raw";
searchModel:SearchModel = {};
constructor(private resourceService:ResourceService, private router:Router) {
this.pageableResponse = {totalElements:0}
......@@ -85,8 +84,11 @@ export class HomeComponent implements OnInit{
this.more = !this.more;
}
public searchResource(){
// @ts-ignore
this.resourceService.searchResource(this.searchModel).subscribe((resources: Resource[]) => {
this.resources = resources;});
this.resources = resources;
this.totalElements = resources.length
});
}
onPageChange(event:any) {
......@@ -101,4 +103,17 @@ export class HomeComponent implements OnInit{
// @ts-ignore
this.totalElements = this.pageableResponse.totalElements;
}
public resetSearch(){
this.resourceService.getAllResources().subscribe((resources: PageableResource) => {
// @ts-ignore
this.resources = resources.content;
// @ts-ignore
this.totalElements = resources.totalElements;
this.searchModel = {};
});
}
isEmptySearch(){
return JSON.stringify(this.searchModel) === '{}';
}
}
......@@ -14,8 +14,17 @@
</span>
</div>
<div class="field flex justify-content-center pt-4">
<p-button class="" type="submit" (click)="signIn()">Login</p-button>
<p-button class="pr-4" type="submit" (click)="signIn()">Login</p-button>
<p-button label="Forgot password?" (click)="displayDialog()" styleClass="p-button-link"></p-button>
</div>
</form>
</div>
</div>
<p-dialog [(visible)]="display" [breakpoints]="{'960px': '75vw', '640px': '100vw'}" [style]="{width: '50vw'} ">
<p>If you want to change your password, please enter your e-mail used to login. If we find email in our system, we will send you instructions to follow.</p>
<input type="text" pInputText [(ngModel)]="email">
<div class="pt-4" >
<button type="button" pButton autofocus (click)="sendPasswordChange()" [disabled]="email.length == 0" > Send email</button>
</div>
</p-dialog>
......@@ -4,6 +4,7 @@ import {Actions, ofActionCompleted, Store} from '@ngxs/store';
import {LoginAction, LogoutAction, UserState} from '../../states/user.state';
import {Router} from '@angular/router';
import {MessageService} from "primeng/api";
import {LoginService} from "../../service/login.service";
@Component({
selector: 'app-login',
......@@ -15,9 +16,10 @@ export class LoginComponent implements OnInit {
username: new FormControl(),
password: new FormControl(),
});
display:boolean = false;
email:string = "";
// tslint:disable-next-line:max-line-length
constructor(private action: Actions, private router: Router, private messageService: MessageService, private store: Store) { }
constructor(private action: Actions, private router: Router, private messageService: MessageService, private store: Store, private loginService:LoginService) { }
ngOnInit() {
this.action.pipe(ofActionCompleted(LoginAction)).subscribe(res => {
if (res.result.error) {
......@@ -38,4 +40,13 @@ export class LoginComponent implements OnInit {
const password = this.loginForm.value.password.trim();
this.store.dispatch(new LoginAction(username, password));
}
displayDialog(){
this.display = true;
}
sendPasswordChange(){
// @ts-ignore
this.loginService.startChangingPassword(this.email).subscribe(d =>{
})
this.display = false;
}
}
......@@ -21,3 +21,9 @@
.overflow-text{
overflow-wrap: anywhere;
}
.link-wrap {
white-space: pre-wrap; /* CSS3 */
white-space: -moz-pre-wrap; /* Mozilla, since 1999 */
white-space: -o-pre-wrap; /* Opera 7 */
word-wrap: break-word; /* Internet Explorer 5.5+ */
}
......@@ -2,9 +2,9 @@
<div class="flex col-12 justify-content-center">
<p class="text-3xl">{{resource.resourceName}}</p>
</div>
<div class="col-6 flex flex-column justify-content-center">
<div class="col-6 flex flex-column">
<div class="col-12 text-center">
<img [src]="imagePath+'/'+resource.idResource" class="imageSize" >
<img [src]="imagePath+'/'+resourceId" class="imageSize" >
</div>
<div class="col-12">
<p-panel class="col-12 inline">
......@@ -14,23 +14,21 @@
<div class="flex align-items-center"><div class="col-3 inline my-0" [ngStyle]="{color:'var(--surface-500)'}">Organization name</div><div class="my-0">{{resource.contactInstitution}}</div></div>
<div class="flex align-items-center"><div class="col-3 inline my-0"[ngStyle]="{color:'var(--surface-500)'}">Contact email</div><div class="my-0"></div>{{resource.contactEmail}}</div>
<div class="flex align-items-center"><div class="col-3 inline my-0"[ngStyle]="{color:'var(--surface-500)'}">Contact phone</div><div class="my-0">{{resource.contactPhone}}</div></div>
<div class="flex align-items-center"><div class="col-3 inline my-0" [ngStyle]="{color:'var(--surface-500)'}">Resource main url</div><div class="overflow-text my-0"><a href="{{resource.mainURL}}">{{resource.mainURL}}</a></div></div>
<div class="flex align-items-center"><div class="col-3 inline my-0" [ngStyle]="{color:'var(--surface-500)'}">Citation (DOI)</div><div class="overflow-text my-0">{{resource.citation}}</div></div>
</p-panel>
</div>
</div>
<div class="col-6 flex flex-column">
<p-panel header="Short summary" class="col-12 p-d-block">
<div class="flex "> {{resource.description}}</div>
<div class="flex mt-5 ">
<div class="flex"> {{resource.description}}</div>
<div class="flex mt-5">
<div class="inline col-3 my-0"[ngStyle]="{color:'var(--surface-500)'}">Sectors</div>
<div class="inline my-0" *ngFor="let sector of resource.sectors">
<img class="sector mx-2" [src]="'assets/sectors/'+sector.sectorIcon" pTooltip="{{sector.name}}">
</div>
</div>
<div class="flex ">
<div class="flex flex-wrap">
<div class="inline col-3 my-0" [ngStyle]="{color:'var(--surface-500)'}">Regions</div>
<div *ngFor="let region of resource.regions" class="inline my-0">
<p class=" my-0 py-2 mx-2" >{{region.name}}</p>
</div>
......@@ -50,14 +48,14 @@
</div>
</div>
</p-panel>
<p-panel class="col-12" header="Find out more">
<p-panel class="col-12 p-d-block" header="Find out more" *ngIf="(resource.fileNames != undefined) || (resource.links != undefined)">
<div *ngFor="let file of resource.fileNames" >
<i class="pi pi-file p-mr-2" style="font-size: 2rem"></i>
<button pButton type="button" label="{{file}}" class="p-button-link button-link" (click)="downloadFile(file)"></button>
</div>
<div class="mt-2" *ngFor="let link of resource.links" >
<i class="pi pi-link p-mr-2" style="font-size: 2rem"></i>
<a href="{{link}}">{{link}}</a>
<a class="link-wrap" href="{{link}}">{{link}}</a>
</div>
</p-panel>
</div>
......@@ -68,8 +66,11 @@
<div class="pr-2" *ngIf="!resource.approved && (loggeduser| async)?.roles?.includes('ADMIN')">
<p-button label="Approve" icon="pi pi-check" (onClick)="approve($event)" [loading]="false"></p-button>
</div>
<div class="pr-2" *ngIf="(loggeduser| async)?.roles?.includes('ADMIN')">
<p-button label="Edit" icon="pi pi-pencil" routerLink="/resource/edit/{{resourceId}}" [loading]="false"></p-button>
</div>
<div *ngIf="(loggeduser| async)?.roles?.includes('ADMIN')">
<p-button label="Edit" icon="pi pi-pencil" (onClick)="showInfo()" routerLink="/resource/edit" [loading]="false"></p-button>
<p-button label="Delete" icon="pi pi-trash" (onClick)="delete($event)" [loading]="false"></p-button>
</div>
</div>
</div>
......
......@@ -66,6 +66,22 @@ export class ResourceComponent implements OnInit {
}
});
}
delete(event: Event) {
this.confirmationService.confirm({
message: 'Are you sure that you want to delete resource?',
icon: 'pi pi-exclamation-triangle',
accept: () => {
// @ts-ignore
this.resourceService.deleteResource(this.resourceId).subscribe(r =>{
this.messageService.add({severity:'success', detail:'Resource has been deletede.'});
this.router.navigate(['/home'])
},error =>{
this.messageService.add({severity:'error', detail:'Some error occured!'});
}
);
}
});
}
showInfo() {
this.messageService.add({severity:'info', summary: 'Info', detail: 'This feature has not been implemented yet!'});
}
......
......@@ -6,32 +6,25 @@ export interface Resource {
links?:string[];
fileNames?:string[];
resourceOrigin?: string;
countryOrigin?:Country;
resourceType?: ResourceType;
sectors?: Sector[];
regions?: Region[];
crops?:Crop[];
pests?:Pest[];
keywordsTemp?:string[];
keywords?: Keyword[];
//keywordsTemp?:string[];
//keywords?: Keyword[];
language?: Language;
project?: Project;
projectWeb?: string;
projectGrantNo?:string;
contactName?: string;
contactInstitution?: string;
contactEmail?: string;
contactPhone?: string;
mainURL?:string;
citation?:string;
creationDate?:Date;
approved?:boolean;
}
export class Country{
public idCountry!:string;
public name!: string;
}
export class Crop{
public idCrop?:string;
public commonName?: string;
......
import {Crop, Language, Pest, Region, ResourceType, Sector} from "./resource";
import {Crop, Language, Pest, Project, Region, ResourceType, Sector} from "./resource";
export class SearchModel {
sector?:Sector[];
region?: Region[];
pestType?: string ;
project?: string ;
project?: Project ;
resourceType?: ResourceType[];
pest?: Pest[];
crop?: Crop[];
......
import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {AppConfig} from "../../config/app.config";
import {User} from "../model/user";
@Injectable({
providedIn: 'root'
......@@ -12,4 +13,14 @@ export class LoginService {
const data = {username, password};
return this.httpClient.post(`${AppConfig.ApiPaths.login}`, data);
}
public startChangingPassword(username: string) {
return this.httpClient.post(`${AppConfig.ApiPaths.startChangingPassword}`, username);
}
public checkToken(token: string) {
return this.httpClient.get<User>(`${AppConfig.ApiPaths.getUserName}`+"/"+token);
}
public changePassword(username: string,password:string) {
const data = {username, password};
return this.httpClient.post(`${AppConfig.ApiPaths.changePassword}`, data);
}
}
......@@ -37,18 +37,26 @@ export class ResourceService {
public getResource(id:string) {
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.getResource}`+"/"+id);
}
public hasImage(id:string,type:string) {
return this._httpClient.get<boolean>(`${AppConfig.ApiPaths.hasImage}`+"/"+type+"/"+id);
}
public approveResource(id:string) {
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.approveResource}`+"/"+id);
}
public deleteResource(id:string) {
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.deleteResource}`+"/"+id);
}
public downloadFile(name: string) {
const httpOptions = {
responseType: 'blob' as 'json',
};
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.getFile}`+"/"+name, httpOptions);
}
public saveResource(resource: Resource) {
public saveResource(resource: Resource,edit:boolean) {
resource.creationDate = new Date();
resource.approved = false;
if(!edit){
resource.approved = false;
}
return this._httpClient.post<Resource>(`${AppConfig.ApiPaths.saveResource}`, resource);
}
......@@ -56,12 +64,15 @@ export class ResourceService {
return this._httpClient.post<Resource[]>(`${AppConfig.ApiPaths.searchResource}`, search);
}
public addFiles(image:File,resourceContent:File[],idResource:any){
public addFiles(image:File,logo:File,resourceContent:File[],idResource:any){
const formData: FormData = new FormData();
if(image != undefined) {
formData.append("image", image);
}
if(logo != undefined) {
formData.append("logo", logo);
}
resourceContent.forEach(r =>{
formData.append("files",r);
})
......@@ -71,7 +82,7 @@ export class ResourceService {
return this._httpClient.get<Sector[]>(`${AppConfig.ApiPaths.getAllSectors}`);
}
public getAllRegions() {
return this._httpClient.get<Region[]>(`${AppConfig.ApiPaths.getAllCountries}`);
return this._httpClient.get<Region[]>(`${AppConfig.ApiPaths.getAllRegions}`);
}
public getAllResourceTypes() {
return this._httpClient.get<ResourceType[]>(`${AppConfig.ApiPaths.getAllResourceTypes}`);
......@@ -90,7 +101,6 @@ export class ResourceService {
}
public getAllKeywords() {
return this._httpClient.get<Keyword[]>(`${AppConfig.ApiPaths.getAllKeywords}`);
}
}
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
......@@ -8,7 +8,10 @@ export class AppConfig {
getAllResources: `${AppConfig.Origin}/resource/getAllResources`,
getResourcesForApproval: `${AppConfig.Origin}/admin/getResourceForApproval`,
getResource: `${AppConfig.Origin}/resource/get`,
hasImage: `${AppConfig.Origin}/resource/imageExist`,
approveResource: `${AppConfig.Origin}/admin/approve`,
deleteResource: `${AppConfig.Origin}/admin/delete`,
getFile: `${AppConfig.Origin}/resource/file`,
......@@ -19,19 +22,17 @@ export class AppConfig {
getAllLanguages: `${AppConfig.Origin}/codebooks/getAllLanguages`,
getAllSectors: `${AppConfig.Origin}/codebooks/getAllSectors`,
getAllCountries: `${AppConfig.Origin}/codebooks/getAllCountries`,
getAllRegions: `${AppConfig.Origin}/codebooks/getAllRegions`,
getAllResourceTypes: `${AppConfig.Origin}/codebooks/getAllResourceTypes`,
getAllProjects: `${AppConfig.Origin}/codebooks/getAllProjects`,
getAllPests: `${AppConfig.Origin}/codebooks/getAllPests`,
getAllCrops: `${AppConfig.Origin}/codebooks/getAllCrops`,
getAllKeywords: `${AppConfig.Origin}/codebooks/getAllKeywords`,
login:`${AppConfig.Origin}/authenticate`
login:`${AppConfig.Origin}/auth/authenticate`,
startChangingPassword:`${AppConfig.Origin}/auth/startChangingPassword`,
getUserName:`${AppConfig.Origin}/auth/validateToken`,
changePassword:`${AppConfig.Origin}/auth/changePassword`
};
......
*{
font-family: 'Roboto', sans-serif;
}
.container-fluid {
min-height: 100vh;
}
.p-menubar{
margin:-8px;
background-color:#00662e !important;
background-color:white !important;
min-height:170px;
border-bottom: 10px solid #71B532 !important;
justify-content: space-between !important;
align-items: baseline !important;
}
.p-menuitem-text{
text-transform: uppercase;
}
.p-menubar-root-list{
padding-left:120px !important;
}
.p-button:not(.p-button-outlined){
background-color:#00662e !important;
......@@ -53,5 +67,18 @@
}
}
.p-menuitem-text{
color: white !important;
color: #003519 !important;
}
.p-message.p-message-info{
background:#71B532 !important;
color:white !important;
}
.p-message.p-message-info .p-message-icon{
color:white !important;
}
.p-message.p-message-info .p-message-close{
color:white !important;
}
.p-button.p-button-link{
background-color: transparent !important;
}
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