login, approval

parent fa52955a
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -10,34 +10,37 @@ ...@@ -10,34 +10,37 @@
}, },
"private": true, "private": true,
"dependencies": { "dependencies": {
"@angular/animations": "~12.0.2", "@angular/animations": "~13.2.6",
"@angular/common": "~12.0.2", "@angular/common": "~13.2.6",
"@angular/compiler": "~12.0.2", "@angular/compiler": "~13.2.6",
"@angular/core": "~12.0.2", "@angular/core": "~13.2.6",
"@angular/forms": "~12.0.2", "@angular/forms": "~13.2.6",
"@angular/platform-browser": "~12.0.2", "@angular/platform-browser": "~13.2.6",
"@angular/platform-browser-dynamic": "~12.0.2", "@angular/platform-browser-dynamic": "~13.2.6",
"@angular/router": "~12.0.2", "@angular/router": "~13.2.6",
"primeflex": "3.0.0", "@ngxs/storage-plugin": "^3.5.0",
"primeicons": "~4.1.0", "@ngxs/store": "^3.5.0",
"primeng": "~12.0.0-rc.1", "lazysizes": "^5.3.2",
"primeflex": "~3.1.3",
"primeicons": "~5.0.0",
"primeng": "~13.2.1",
"rxjs": "~6.6.0", "rxjs": "~6.6.0",
"tslib": "^2.1.0", "tslib": "^2.1.0",
"zone.js": "~0.11.4" "zone.js": "~0.11.4"
}, },
"devDependencies": { "devDependencies": {
"@angular-devkit/build-angular": "~12.0.2", "@angular-devkit/build-angular": "^13.2.6",
"@angular/cdk": "~12.0.2", "@angular/cdk": "~13.2.6",
"@angular/cli": "~12.0.2", "@angular/cli": "~13.2.6",
"@angular/compiler-cli": "~12.0.2", "@angular/compiler-cli": "~13.2.6",
"@types/jasmine": "~3.6.0", "@types/jasmine": "~3.10.3",
"@types/node": "^12.11.1", "@types/node": "^14.0.0",
"jasmine-core": "~3.7.0", "jasmine-core": "~4.0.1",
"karma": "~6.3.0", "karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0", "karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.0.3", "karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0", "karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "^1.5.0", "karma-jasmine-html-reporter": "^1.5.0",
"typescript": "~4.2.3" "typescript": "~4.4.2"
} }
} }
@media only screen and (min-width: 60.0px) {
.flag{
width: 45px;
}
}
:host ::ng-deep .p-dropdown{
border:0px !important;
}
:host ::ng-deep .p-dropdown:not(.p-disabled).p-focus {
box-shadow: none;
}
:host ::ng-deep .p-menubar-end{
align-self: auto !important;
}
:host ::ng-deep .p-dropdown-trigger {
display: none !important;
}
<p-menubar [model]="items" [ngStyle]="{'display': hideheader}"> <p-menubar [model]="items">
<ng-template pTemplate="start"> <ng-template pTemplate="start">
<a href="http://ipmworks.net"> <img src="assets/logo-white.png" height="50" class="p-mr-2" routerLink="/home" alt="brand logo">
<img src="assets/logo.jpg" height="97" class="pl-6 mr-8" alt="brand logo">
</a>
</ng-template> </ng-template>
<ng-template pTemplate="end"> <ng-template pTemplate="end">
<p-dropdown [options]="languages" [(ngModel)]="selectedLanguage" optionLabel="name" class="col-4" (onChange)="reloadTranslate($event)" appendTo="body"> <div *ngIf="!logged">
<ng-template pTemplate="selectedItem"> <p-button label="Login" icon="pi pi-login" iconPos="left" class="p-menuitem-text" routerLink="/login"></p-button>
<div *ngIf="selectedLanguage"> </div>
<img src="assets/languages/{{locale}}.png" class="flag pr-2"/> <div *ngIf="logged">
</div> <p-button label="Logout" icon="pi pi-login" iconPos="left" class="p-menuitem-text" routerLink="" (click)="logout()"></p-button>
</ng-template> </div>
<ng-template let-language pTemplate="item">
<div class="flex">
<img src="assets/languages/{{language.code}}.png" class="flag pr-2"/>
<div>{{language.name}}</div>
</div>
</ng-template>
</p-dropdown>
</ng-template> </ng-template>
</p-menubar> </p-menubar>
<p-toast></p-toast> <p-toast></p-toast>
File mode changed from 100755 to 100644
import {Component, Input, OnDestroy, OnInit} from '@angular/core'; import {Component, OnDestroy, OnInit} from '@angular/core';
import {MenuItem, MessageService, PrimeNGConfig} from "primeng/api"; import {MenuItem, MessageService, PrimeNGConfig} from "primeng/api";
import {Observable, Subject} from "rxjs"; import {Observable, Subject} from "rxjs";
import {User} from "../../model/user"; import {User} from "../../model/user";
import {LogoutAction, UserState} from "../../states/user.state"; import {LogoutAction, UserState} from "../../states/user.state";
import {Select, Store} from "@ngxs/store"; import {Select, Store} from "@ngxs/store";
import {ActivatedRoute, NavigationEnd, Router, RouterEvent} from "@angular/router"; import {NavigationEnd, Router, RouterEvent} from "@angular/router";
import {filter, takeUntil} from "rxjs/operators"; import {filter, takeUntil} from "rxjs/operators";
import { LOCALE_ID, Inject } from '@angular/core';
export class LanguageTrans{
public name?: string;
public code?:string;
}
@Component({ @Component({
selector: 'app-header-menu', selector: 'app-header-menu',
templateUrl: './header-menu.component.html', templateUrl: './header-menu.component.html',
...@@ -24,92 +19,37 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{ ...@@ -24,92 +19,37 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{
// @ts-ignore // @ts-ignore
public loggeduser: Observable<User> = this.store.select(UserState.userDetails); public loggeduser: Observable<User> = this.store.select(UserState.userDetails);
logged?:boolean logged?:boolean
selectedLanguage?:LanguageTrans;
languages :LanguageTrans[] = [];
@Input() hideheader?:string|null; constructor(private primengConfig: PrimeNGConfig, private store: Store, private router: Router,private messageService: MessageService) {}
constructor(private route:ActivatedRoute,private primengConfig: PrimeNGConfig, private store: Store, private router: Router,private messageService: MessageService, @Inject(LOCALE_ID) public locale: string) {}
initialise() { initialise() {
this.logged = this.isLogged(); this.logged = this.isLogged();
// @ts-ignore // @ts-ignore
this.items = [ this.items = [
{ {
label: $localize `Home`, label: 'Home',
routerLink:'/home', routerLink:'/home',
styleClass:"pr-2 ", styleClass:"ml-5 pr-2 ",
}, },
{ {
label: $localize `Add resource`, label: 'Add resource',
url:'#/resource/add', url:'#/resource/add',
styleClass:"pr-2", styleClass:"pr-2",
target:"_blank" target:"_blank"
}, },
{ {
label: $localize `Approve`, label: 'Approve',
routerLink:'/resource/approve', routerLink:'/resource/approve',
styleClass:"pr-2", styleClass:"pr-2",
visible:this.isUserAdmin() visible:this.isUserAdmin()
},
{
label:$localize `IPMWORKS Project`,
url:'http://ipmworks.net',
styleClass:"pr-2",
target:"_blank"
},
{
label: $localize`Help and Support`,
routerLink:'/help',
styleClass:"pr-2",
target:"_blank"
},
{
label: $localize `Logout`,
command:(event) => {this.logout()},
styleClass:"pr-2",
visible:this.logged
},
{
label: $localize `Login`,
routerLink:'/login',
styleClass:"pr-2",
visible:!this.logged
} }
] ]
} }
ngOnInit(): void { ngOnInit(): void {
this.languages = [
{ name: $localize `Dutch`, code: "nl" },
{ name: $localize `Danish`, code: "da" },
{ name: $localize `English`, "code": "en" },
{ name: $localize `Finnish`, code: "fi" },
{ name: $localize `French`, code: "fr" },
{ name: $localize `German`, code: "de" },
{ name: $localize `Greek`, code: "el" },
{ name: $localize `Italian`, code: "it" },
{ name: $localize `Polish`, code: "pl" },
{ name: $localize `Portuguese`, code: "pt" },
{ name: $localize `Serbian`, "code": "sr" },
{ name: $localize `Slovenian`, code: "sl" },
{ name: $localize `Spanish`, code: "es" }
]
this.findSelectedLanguage();
this.router.events.pipe(filter((event) => event instanceof NavigationEnd), this.router.events.pipe(filter((event) => event instanceof NavigationEnd),
takeUntil(this.destroyed) takeUntil(this.destroyed)
).subscribe(() => { ).subscribe(() => {
this.router.routeReuseStrategy.shouldReuseRoute = function() { return false; };
this.initialise(); this.initialise();
}); });
}
public findSelectedLanguage(){
console.log("locale:"+this.locale)
var selected = this.languages.filter(l=>l.code===this.locale);
if(selected.length !== 0){
this.selectedLanguage =this.languages.filter(l=>l.code===this.locale)[0];
}
} }
public isUserAdmin() { public isUserAdmin() {
var admin = false; var admin = false;
...@@ -145,11 +85,6 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{ ...@@ -145,11 +85,6 @@ export class HeaderMenuComponent implements OnInit,OnDestroy{
this.router.navigate(['/home']); this.router.navigate(['/home']);
this.messageService.add({severity:"success", detail:"Goodbye!"}) this.messageService.add({severity:"success", detail:"Goodbye!"})
} }
public reloadTranslate(event:any):void{
window.location.href= "/toolbox/"+this.selectedLanguage?.code;
}
} }
......
.imageSizeHome{ .imageSizeHome{
max-width: 270px; max-width: 100%;
max-height: 120px; max-height: 120px;
display: block; display: block;
margin-left: auto; margin-left: auto;
......
<p-messages [(value)]="disclaimer" [enableService]="false"></p-messages> <p-messages [(value)]="disclaimer" [enableService]="false"></p-messages>
<div class="grid pt-6 pl-6"> <div class="grid pt-6 pl-6">
<div class="col-3"> <div class="col-3">
<p class="text-xl">Sectors</p> <form #searchForm="ngForm" (ngSubmit)="searchResource()">
<p-multiSelect [selectionLimit]="1" defaultLabel="Select sector" [options]="sectors" [(ngModel)]="selectedSectors" optionLabel="name"></p-multiSelect> <p class="text-xl">Sectors</p>
<p class="text-xl">Country of origin</p> <p-multiSelect [selectionLimit]="1" defaultLabel="Select sector" [options]="sectors" name="sector" [(ngModel)]="searchModel.sector" optionLabel="name"></p-multiSelect>
<p-multiSelect [selectionLimit]="1" defaultLabel="Select region" [options]="regions" [(ngModel)]="selectedRegions" optionLabel="name"></p-multiSelect> <p class="text-xl">Country of origin</p>
<div class="field"> <p-multiSelect [selectionLimit]="1" defaultLabel="Select region" [options]="regions" name="region" [(ngModel)]="searchModel.region" optionLabel="name"></p-multiSelect>
<p class="text-xl">Pest type</p> <!-- <div class="field">
<p-dropdown autoWidth="false" [style]="{'width':'100%'}" placeholder="Select pest type" [options]="pestType" [(ngModel)]="selectedPestType" optionLabel="name" ></p-dropdown> <p class="text-xl">Pest type</p>
</div> <p-dropdown autoWidth="false" [style]="{'width':'100%'}" placeholder="Select pest type" [options]="pestType" name="pestType"[(ngModel)]="searchModel.pestType" optionLabel="name" ></p-dropdown>
<p class="text-xl">Project</p> </div>-->
<input id="project" type="text" pInputText [(ngModel)]="selectedProjects" placeholder="Add project"> <p class="text-xl">Project</p>
<input id="project" type="text" pInputText name="project" [(ngModel)]="searchModel.project" placeholder="Add project">
<p class="text-xl">Resource types</p> <p class="text-xl">Resource types</p>
<p-multiSelect placeholder="Select resource type" [selectionLimit]="1"[(ngModel)]="selectedTypes" [options]="contentTypes" optionLabel="name" <p-multiSelect placeholder="Select resource type" [selectionLimit]="1" name="resourceType" [(ngModel)]="searchModel.resourceType" [options]="contentTypes" optionLabel="name">
></p-multiSelect> </p-multiSelect>
<div class="button-right pt-3" *ngIf="!more"> <div class="button-right pt-3" *ngIf="!more">
<button pButton type="button" pTooltip="More filters..." icon="pi pi-plus" class="p-button-text p-button-sm p-button-rounded p-button-outlined " (click)="toggleFilters()"></button> <button pButton type="button" pTooltip="More filters..." icon="pi pi-plus" class="p-button-text p-button-sm p-button-rounded p-button-outlined " (click)="toggleFilters()"></button>
</div> </div>
<div class="button-right pt-3" *ngIf="more"> <div class="button-right pt-3" *ngIf="more">
<button pButton type="button" icon="pi pi-minus" pTooltip="Less filters..." <button pButton type="button" icon="pi pi-minus" pTooltip="Less filters..."
class="p-button-text p-button-sm p-button-rounded p-button-outlined " (click)="toggleFilters()"></button> class="p-button-text p-button-sm p-button-rounded p-button-outlined " (click)="toggleFilters()"></button>
</div> </div>
<div *ngIf="more"> <div *ngIf="more">
<p class="text-xl">Specific pest</p> <p class="text-xl">Specific pest</p>
<p-multiSelect defaultLabel="Select pests" [selectionLimit]="1" [options]="pests" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="selectedPests"> <p-multiSelect defaultLabel="Select pests" [selectionLimit]="1" [options]="pests" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="searchModel.pest" name="pest">
<ng-template let-pest pTemplate="item"> <ng-template let-pest pTemplate="item">
<div>{{pest.commonName}} <i *ngIf="pest.latinName !=undefined"> <div>{{pest.commonName}} <i *ngIf="pest.latinName !=undefined">
({{pest.latinName}}, {{pest.eppo}})</i></div> ({{pest.latinName}}, {{pest.eppo}})</i></div>
</ng-template> </ng-template>
</p-multiSelect> </p-multiSelect>
<p class="text-xl">Specific crop</p> <p class="text-xl">Specific crop</p>
<p-multiSelect defaultLabel="Select crops" [selectionLimit]="1" [options]="crops" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="selectedCrops"> <p-multiSelect defaultLabel="Select crops" [selectionLimit]="1" [options]="crops" optionLabel="commonName" filterBy="commonName,latinName,eppo" [(ngModel)]="searchModel.crop" name="crop">
<ng-template let-crop pTemplate="item"> <ng-template let-crop pTemplate="item">
<div>{{crop.commonName}} <i *ngIf="crop.latinName !=undefined"> <div>{{crop.commonName}} <i *ngIf="crop.latinName !=undefined">
({{crop.latinName}}, {{crop.eppo}})</i></div> ({{crop.latinName}}, {{crop.eppo}})</i></div>
</ng-template> </ng-template>
</p-multiSelect> </p-multiSelect>
<p class="text-xl">Languages</p> <p class="text-xl">Languages</p>
<p-multiSelect defaultLabel="Select language" [selectionLimit]="1" [options]="languages" [(ngModel)]="selectedLanguages" optionLabel="name"></p-multiSelect> <p-multiSelect defaultLabel="Select language" [selectionLimit]="1" [options]="languages" name="language" [(ngModel)]="searchModel.language" optionLabel="name"></p-multiSelect>
<!--<h3>Arbitrary text search</h3> <!--<h3>Arbitrary text search</h3>
<input type="text" pInputText [(ngModel)]="searchTerm"/>--> <input type="text" pInputText [(ngModel)]="searchTerm"/>-->
</div> </div>
<div class="pt-3 button-center"> <div class="pt-3 button-center">
<p-button label="Search" icon="pi pi-search" [loading]="false"></p-button> <p-button type="submit" label="Search" icon="pi pi-search" [loading]="false"></p-button>
</div> </div>
</form>
</div> </div>
<div class="col-9"> <div class="col-9">
<p-card> <p-card>
<div class="button-right"> <p-dataView [value]="resources" [lazy]="true" (onLazyLoad)="onPageChange($event)" (onPage)="onPageChange($event)" [totalRecords]="totalElements" [paginator]="true" [rowsPerPageOptions]=[10,50,100] [rows]="10" layout="grid">
<button pButton type="button" routerLink="/resource/add" icon="pi pi-plus" class="p-button-lg p-button-raised p-button-rounded"></button>
</div>
<p-dataView [value]="resources" [paginator]="true" [rows]="6" layout="grid">
<ng-template let-resource pTemplate="gridItem"> <ng-template let-resource pTemplate="gridItem">
<div class="card col-12 md:col-4 flex flex-column p-3 mt-3 justify-content-between" routerLink="/resource/{{resource.idResource}}"> <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"> <div class="pb-1 align-self-end">
<p-tag *ngIf="resource.resourceType" [rounded]=true value="{{resource.resourceType.name}}"> <p-tag *ngIf="resource.resourceType" [rounded]=true value="{{resource.resourceType.name}}">
</p-tag> </p-tag>
</div> </div>
<div class=""> <div class="">
<img [src]="imagePath+'/'+resource.idResource" class="imageSizeHome"> <img [src]="imagePath+'/'+resource.idResource" class="imageSizeHome"/>
<p class="text-center">{{resource.resourceName}}</p> <p class="text-center">{{resource.resourceName}}</p>
</div> </div>
<div class="align-self-center"> <div class="align-self-center">
<button pButton type="button" routerLink="/resource/{{resource.idResource}}" icon="pi pi-forward" class="p-button-outlined mr-4" pTooltip="See more..."></button> <button pButton type="button" routerLink="/resource/{{resource.idResource}}" icon="pi pi-forward" class="p-button-outlined mr-4" pTooltip="See more..."></button>
<button pButton type="button" icon="pi pi-share-alt" class="p-button-outlined" pTooltip="Share"></button> <!--<button pButton type="button" icon="pi pi-share-alt" class="p-button-outlined" pTooltip="Share"></button>-->
</div> </div>
</div> </div>
</ng-template> </ng-template>
<ng-template let-item pTemplate="paginatordropdownitem">
{{item.value}} - per page
</ng-template>
</p-dataView> </p-dataView>
</p-card> </p-card>
</div> </div>
......
import { Component, OnInit } from '@angular/core'; import {Component, OnDestroy, OnInit} from '@angular/core';
import {Crop, Keyword, Language, Pest, Project, Region, Resource, ResourceType, Sector} from "../../model/resource"; import {
Crop,
Keyword,
Language,
PageableResource,
Pest,
Project,
Region,
Resource,
ResourceType,
Sector
} from "../../model/resource";
import {ResourceService} from "../../service/resource.service"; import {ResourceService} from "../../service/resource.service";
import {Message} from "primeng/api"; import {Message} from "primeng/api";
import {environment} from "../../../environments/environment"; import {environment} from "../../../environments/environment";
import {SearchModel} from "../../model/search-model";
import {NavigationEnd, Router} from "@angular/router";
@Component({ @Component({
selector: 'app-home', selector: 'app-home',
templateUrl: './home.component.html', templateUrl: './home.component.html',
styleUrls: ['./home.component.css'] styleUrls: ['./home.component.css']
}) })
export class HomeComponent implements OnInit { export class HomeComponent implements OnInit{
resources: Resource[] = []; resources: Resource[] = [];
pageableResponse?: PageableResource;
pageSize = 10;
currentPage = 0;
totalElements: number = 0;
elements?: Resource[] = [];
sectors: Sector[] = []; sectors: Sector[] = [];
regions: Region[] = []; regions: Region[] = [];
projects: Project[] = []; projects: Project[] = [];
...@@ -32,8 +50,11 @@ export class HomeComponent implements OnInit { ...@@ -32,8 +50,11 @@ export class HomeComponent implements OnInit {
searchTerm: string = ""; searchTerm: string = "";
more= false; more= false;
imagePath = environment.baseUrl+"/resource/image"; imagePath = environment.baseUrl+"/resource/image";
searchModel:SearchModel={};
constructor(private resourceService:ResourceService) { } constructor(private resourceService:ResourceService, private router:Router) {
this.pageableResponse = {totalElements:0}
}
ngOnInit(): void { ngOnInit(): void {
this.resourceService.getAllProjects().subscribe((projects: Project[]) => { this.resourceService.getAllProjects().subscribe((projects: Project[]) => {
...@@ -50,8 +71,12 @@ export class HomeComponent implements OnInit { ...@@ -50,8 +71,12 @@ export class HomeComponent implements OnInit {
this.pests = pests;}); this.pests = pests;});
this.resourceService.getAllCrops().subscribe((crops: Crop[]) => { this.resourceService.getAllCrops().subscribe((crops: Crop[]) => {
this.crops = crops;}); this.crops = crops;});
this.resourceService.getAllResources().subscribe((resources: Resource[]) => { this.resourceService.getAllResources().subscribe((resources: PageableResource) => {
this.resources = resources;}); // @ts-ignore
this.resources = resources.content;
// @ts-ignore
this.totalElements = resources.totalElements;
});
this.disclaimer = [{severity:"info", summary:"Disclaimer", detail:"This IPMWORKS Resource Toolbox is a repository for IPM resource developed by the EU IPMWORKS project (101000339). The cooperating partners have no economic responsibility whatsoever for losses due to using this service."}]; this.disclaimer = [{severity:"info", summary:"Disclaimer", detail:"This IPMWORKS Resource Toolbox is a repository for IPM resource developed by the EU IPMWORKS project (101000339). The cooperating partners have no economic responsibility whatsoever for losses due to using this service."}];
} }
...@@ -59,4 +84,21 @@ export class HomeComponent implements OnInit { ...@@ -59,4 +84,21 @@ export class HomeComponent implements OnInit {
//kada se zatvore dodatni filteri isprazniti ako je nesto bilo selektovano u tim filterima //kada se zatvore dodatni filteri isprazniti ako je nesto bilo selektovano u tim filterima
this.more = !this.more; this.more = !this.more;
} }
public searchResource(){
this.resourceService.searchResource(this.searchModel).subscribe((resources: Resource[]) => {
this.resources = resources;});
}
onPageChange(event:any) {
var pNum = event.first / event.rows
this.resourceService.getAllResources(pNum, event.rows,)
.subscribe(ret => this.populate(ret));
}
populate(ret: PageableResource) {
this.pageableResponse = ret;
// @ts-ignore
this.resources = this.pageableResponse?.content;
// @ts-ignore
this.totalElements = this.pageableResponse.totalElements;
}
} }
...@@ -4,27 +4,18 @@ ...@@ -4,27 +4,18 @@
<div class="field"> <div class="field">
<span class="p-float-label"> <span class="p-float-label">
<input type="email" id="username" pInputText formControlName="username"> <input type="email" id="username" pInputText formControlName="username">
<label for="username" i18n="@@{username}">Username</label> <label for="username">Username</label>
</span> </span>
</div> </div>
<div class="field"> <div class="field">
<span class="p-float-label"> <span class="p-float-label">
<input type="password" id="password" pInputText formControlName="password"> <input type="password" id="password" pInputText formControlName="password">
<label for="username" i18n="@@{password}">Password</label> <label for="username">Password</label>
</span> </span>
</div> </div>
<div class="field flex justify-content-center pt-4"> <div class="field flex justify-content-center pt-4">
<p-button class="pr-4" type="submit" (click)="signIn()" i18n="@@{login}">Login</p-button> <p-button class="" type="submit" (click)="signIn()">Login</p-button>
<p-button i18n-label="@@{forgot_password}" label="Forgot password?" (click)="displayDialog()" styleClass="p-button-link"></p-button>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
<p-dialog [(visible)]="display" [breakpoints]="{'960px': '75vw', '640px': '100vw'}" [style]="{width: '50vw'} ">
<p i18n="@@{change_pass_instr}">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" i18n="@@{send_email}"> Send email</button>
</div>
</p-dialog>
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -4,7 +4,6 @@ import {Actions, ofActionCompleted, Store} from '@ngxs/store'; ...@@ -4,7 +4,6 @@ import {Actions, ofActionCompleted, Store} from '@ngxs/store';
import {LoginAction, LogoutAction, UserState} from '../../states/user.state'; import {LoginAction, LogoutAction, UserState} from '../../states/user.state';
import {Router} from '@angular/router'; import {Router} from '@angular/router';
import {MessageService} from "primeng/api"; import {MessageService} from "primeng/api";
import {LoginService} from "../../service/login.service";
@Component({ @Component({
selector: 'app-login', selector: 'app-login',
...@@ -16,10 +15,9 @@ export class LoginComponent implements OnInit { ...@@ -16,10 +15,9 @@ export class LoginComponent implements OnInit {
username: new FormControl(), username: new FormControl(),
password: new FormControl(), password: new FormControl(),
}); });
display:boolean = false;
email:string = "";
// tslint:disable-next-line:max-line-length // tslint:disable-next-line:max-line-length
constructor(private action: Actions, private router: Router, private messageService: MessageService, private store: Store, private loginService:LoginService) { } constructor(private action: Actions, private router: Router, private messageService: MessageService, private store: Store) { }
ngOnInit() { ngOnInit() {
this.action.pipe(ofActionCompleted(LoginAction)).subscribe(res => { this.action.pipe(ofActionCompleted(LoginAction)).subscribe(res => {
if (res.result.error) { if (res.result.error) {
...@@ -40,13 +38,4 @@ export class LoginComponent implements OnInit { ...@@ -40,13 +38,4 @@ export class LoginComponent implements OnInit {
const password = this.loginForm.value.password.trim(); const password = this.loginForm.value.password.trim();
this.store.dispatch(new LoginAction(username, password)); this.store.dispatch(new LoginAction(username, password));
} }
displayDialog(){
this.display = true;
}
sendPasswordChange(){
// @ts-ignore
this.loginService.startChangingPassword(this.email).subscribe(d =>{
})
this.display = false;
}
} }
...@@ -61,7 +61,17 @@ ...@@ -61,7 +61,17 @@
</div> </div>
</p-panel> </p-panel>
</div> </div>
<div class="col-12 pt-3 button-center"> <div class="col-12 pt-3 flex justify-content-center">
<p-button label="Back to search" icon="pi pi-search" routerLink="/home" [loading]="false"></p-button> <div class="pr-2">
<p-button label="Back to search" icon="pi pi-search" routerLink="/home" [loading]="false"></p-button>
</div>
<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 *ngIf="(loggeduser| async)?.roles?.includes('ADMIN')">
<p-button label="Edit" icon="pi pi-pencil" (onClick)="showInfo()" routerLink="/resource/edit" [loading]="false"></p-button>
</div>
</div> </div>
</div> </div>
<p-toast position="bottom-center" key="bc"></p-toast>
<p-confirmDialog></p-confirmDialog>
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import {ResourceService} from "../../service/resource.service"; import {ResourceService} from "../../service/resource.service";
import {ActivatedRoute} from "@angular/router"; import {ActivatedRoute, Router} from "@angular/router";
import {environment} from "../../../environments/environment"; import {environment} from "../../../environments/environment";
import {Resource} from "../../model/resource"; import {Resource} from "../../model/resource";
import {ConfirmationService, MessageService} from "primeng/api";
import {Observable} from "rxjs";
import {User} from "../../model/user";
import {UserState} from "../../states/user.state";
import {Store} from "@ngxs/store";
@Component({ @Component({
selector: 'app-resource', selector: 'app-resource',
...@@ -14,13 +19,18 @@ export class ResourceComponent implements OnInit { ...@@ -14,13 +19,18 @@ export class ResourceComponent implements OnInit {
imagePath = environment.baseUrl+"/resource/image"; imagePath = environment.baseUrl+"/resource/image";
filePath = environment.baseUrl+"/resource/file"; filePath = environment.baseUrl+"/resource/file";
url:any; url:any;
resourceId = null;
// @ts-ignore
public loggeduser: Observable<User> = this.store.select(UserState.userDetails);
constructor(private resourceService:ResourceService, private route: ActivatedRoute) { } constructor(private resourceService:ResourceService, private route: ActivatedRoute,
private router: Router, private store:Store, private messageService:MessageService, private confirmationService: ConfirmationService) { }
ngOnInit(): void { ngOnInit(): void {
const id = this.route.snapshot.paramMap.get('id');
// @ts-ignore // @ts-ignore
this.resourceService.getResource(id).subscribe(data =>{ this.resourceId = this.route.snapshot.paramMap.get('id');
// @ts-ignore
this.resourceService.getResource(this.resourceId).subscribe(data =>{
this.resource =data; this.resource =data;
}); });
...@@ -39,13 +49,24 @@ export class ResourceComponent implements OnInit { ...@@ -39,13 +49,24 @@ export class ResourceComponent implements OnInit {
console.log(error) console.log(error)
}); });
} }
getRandomSector():string{
// @ts-ignore
var index = Math.floor(Math.random() * this.resource.sectors?.length);
// @ts-ignore
var randomSector = this.resource.sectors[index].sectorIcon
return randomSector.substring(0,randomSector.length-4)+'Sector.jpg'
}
approve(event: Event) {
this.confirmationService.confirm({
message: 'Are you sure that you want to approve resource?',
icon: 'pi pi-exclamation-triangle',
accept: () => {
// @ts-ignore
this.resourceService.approveResource(this.resourceId).subscribe(r =>{
this.messageService.add({severity:'success', detail:'Resource has been approved.'});
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!'});
}
} }
...@@ -24,6 +24,8 @@ export interface Resource { ...@@ -24,6 +24,8 @@ export interface Resource {
contactPhone?: string; contactPhone?: string;
mainURL?:string; mainURL?:string;
citation?:string; citation?:string;
creationDate?:Date;
approved?:boolean;
} }
export class Country{ export class Country{
...@@ -68,3 +70,16 @@ export class Keyword{ ...@@ -68,3 +70,16 @@ export class Keyword{
public idKeyword!: string; public idKeyword!: string;
public name!: string; public name!: string;
} }
export class PageableResource {
content?: Resource[] = [];
empty?: boolean;
first?: boolean;
last?: boolean;
number?: number = 0;
numberOfElements?: number;
pageable?: any;
size?: number = 0;
sort?: any;
totalElements: number|undefined;
totalPages?: number =0;
}
File mode changed from 100755 to 100644
import {Crop, Language, Pest, Project, Region, ResourceType, Sector} from "./resource"; import {Crop, Language, Pest, Region, ResourceType, Sector} from "./resource";
export class SearchModel { export class SearchModel {
sector?:Sector[]; sector?:Sector[];
region?: Region[]; region?: Region[];
pestType?: string ; pestType?: string ;
project?: Project ; project?: string ;
resourceType?: ResourceType[]; resourceType?: ResourceType[];
pest?: Pest[]; pest?: Pest[];
crop?: Crop[]; crop?: Crop[];
language?: Language[]; language?: Language[];
title?:string;
} }
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import {HttpClient} from "@angular/common/http"; import {HttpClient} from "@angular/common/http";
import {AppConfig} from "../../config/app.config"; import {AppConfig} from "../../config/app.config";
import {User} from "../model/user";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
...@@ -13,14 +12,4 @@ export class LoginService { ...@@ -13,14 +12,4 @@ export class LoginService {
const data = {username, password}; const data = {username, password};
return this.httpClient.post(`${AppConfig.ApiPaths.login}`, data); 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);
}
} }
...@@ -4,7 +4,19 @@ import {HttpClient} from "@angular/common/http"; ...@@ -4,7 +4,19 @@ import {HttpClient} from "@angular/common/http";
import {AppConfig} from "../../config/app.config"; import {AppConfig} from "../../config/app.config";
import {ResourceType, Language, Region, Resource, Sector, Project, Keyword, Pest, Crop} from "../model/resource"; import {
ResourceType,
Language,
Region,
Resource,
Sector,
Project,
Keyword,
Pest,
Crop,
PageableResource
} from "../model/resource";
import {SearchModel} from "../model/search-model";
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
...@@ -16,12 +28,18 @@ export class ResourceService { ...@@ -16,12 +28,18 @@ export class ResourceService {
public constructor(httpClient: HttpClient) { public constructor(httpClient: HttpClient) {
this._httpClient = httpClient; this._httpClient = httpClient;
} }
public getAllResources() { public getAllResources(pageNo: number = 0,pageSize: number = 10) {
return this._httpClient.get<Resource[]>(`${AppConfig.ApiPaths.getAllResources}`); return this._httpClient.get<PageableResource>(`${AppConfig.ApiPaths.getAllResources}?pageNumber=${pageNo}&pageSize=${pageSize}`);
}
public getResourcesForApproval() {
return this._httpClient.get<Resource []>(`${AppConfig.ApiPaths.getResourcesForApproval}`);
} }
public getResource(id:string) { public getResource(id:string) {
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.getResource}`+"/"+id); return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.getResource}`+"/"+id);
} }
public approveResource(id:string) {
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.approveResource}`+"/"+id);
}
public downloadFile(name: string) { public downloadFile(name: string) {
const httpOptions = { const httpOptions = {
responseType: 'blob' as 'json', responseType: 'blob' as 'json',
...@@ -29,9 +47,15 @@ export class ResourceService { ...@@ -29,9 +47,15 @@ export class ResourceService {
return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.getFile}`+"/"+name, httpOptions); return this._httpClient.get<Resource>(`${AppConfig.ApiPaths.getFile}`+"/"+name, httpOptions);
} }
public saveResource(resource: Resource) { public saveResource(resource: Resource) {
resource.creationDate = new Date();
resource.approved = false;
return this._httpClient.post<Resource>(`${AppConfig.ApiPaths.saveResource}`, resource); return this._httpClient.post<Resource>(`${AppConfig.ApiPaths.saveResource}`, resource);
} }
public searchResource(search: SearchModel) {
return this._httpClient.post<Resource[]>(`${AppConfig.ApiPaths.searchResource}`, search);
}
public addFiles(image:File,resourceContent:File[],idResource:any){ public addFiles(image:File,resourceContent:File[],idResource:any){
const formData: FormData = new FormData(); const formData: FormData = new FormData();
...@@ -47,7 +71,7 @@ export class ResourceService { ...@@ -47,7 +71,7 @@ export class ResourceService {
return this._httpClient.get<Sector[]>(`${AppConfig.ApiPaths.getAllSectors}`); return this._httpClient.get<Sector[]>(`${AppConfig.ApiPaths.getAllSectors}`);
} }
public getAllRegions() { public getAllRegions() {
return this._httpClient.get<Region[]>(`${AppConfig.ApiPaths.getAllRegions}`); return this._httpClient.get<Region[]>(`${AppConfig.ApiPaths.getAllCountries}`);
} }
public getAllResourceTypes() { public getAllResourceTypes() {
return this._httpClient.get<ResourceType[]>(`${AppConfig.ApiPaths.getAllResourceTypes}`); return this._httpClient.get<ResourceType[]>(`${AppConfig.ApiPaths.getAllResourceTypes}`);
......
File mode changed from 100755 to 100644
File mode changed from 100755 to 100644
...@@ -46,5 +46,12 @@ ...@@ -46,5 +46,12 @@
margin-right: -0.5rem; margin-right: -0.5rem;
margin-left: -0.5rem; margin-left: -0.5rem;
margin-top: -0.5rem; margin-top: -0.5rem;
justify-content:space-between; }
@media only screen and (max-width: 768px) {
.p-tag{
visibility: hidden;
}
}
.p-menuitem-text{
color: white !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