Commit 8f1bce23 authored by Janik Münzenberger's avatar Janik Münzenberger
Browse files
parents cb0267b4 d5aa7a25
......@@ -25,6 +25,7 @@
"resources": {
"files": [
"/assets/img/*.jpg",
"/assets/img/*.webp",
"/assets/icons/*.png"
]
}
......@@ -35,7 +36,7 @@
"urls": ["/plants/*", "/diseases/*"],
"cacheConfig": {
"strategy": "freshness",
"maxAge": "3d",
"maxAge": "7d",
"timeout": "3s"
}
},{
......@@ -46,5 +47,13 @@
"maxAge": "3d",
"timeout": "2s"
}
},{
"name": "gardeners-api",
"urls": ["/gardeners"],
"cacheConfig": {
"strategy": "freshness",
"maxAge": "7d",
"timeout": "2s"
}
}]
}
......@@ -6,28 +6,16 @@ import {NotificationService} from './services/notification.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
styleUrls: ['./app.component.css'],
})
export class AppComponent {
readonly VAPID_PUBLIC_KEY = 'BNaGf2POUom9qpnI45OSE8gmzjeqdvk-4HoV7Is-3RjPeCWMtgcukwEVPp0K2xMdfmSrGCS2be5rFIYX2qRwoEc';
constructor(translate: TranslateService) {
constructor(translate: TranslateService,
private notificationService: NotificationService) {
translate.setDefaultLang('en');
translate.use('en');
// this.subscribeToNotifications();
}
subscribeToNotifications() {
this.swPush.requestSubscription({
serverPublicKey: this.VAPID_PUBLIC_KEY
})
.then(sub => {
this.notificationservice.addPushSubscriber(sub).subscribe();
console.log(sub);
})
.catch(err => console.error('Could not subscribe to notifications', err));
}
}
<form [formGroup]="emailForm">
<div class="alert alert-success" *ngIf="sent" role="alert"><i class="fas fa-check mr-2"></i>{{"EMAIL.SUCCESS" | translate}}</div>
<div class="alert alert-danger" *ngIf="!sent && error" role="alert">{{"EMAIL.FAILED" | translate}}</div>
<form [formGroup]="emailForm" *ngIf="!sent">
<div class="form-group row">
<label for="email_sender" class="col-sm-2 col-form-label">{{"EMAIL.SENDER" | translate}}:</label>
<div class="col-sm-10">
<input type="email" class="form-control" formControlName="email_sender" id="email_sender" placeholder="Sender email" required>
<input type="email" autocomplete="email" class="form-control" formControlName="email_sender" id="email_sender" placeholder="Sender email" required>
</div>
</div>
<div class="form-group row">
<label for="email_receiver" class="col-sm-2 col-form-label">{{"EMAIL.RECEIVER" | translate}}:</label>
<div class="col-sm-10">
<select *ngIf="receivers" type="email" class="form-control" formControlName="email_receiver" id="email_receiver" placeholder="Receiver email" required>
<option *ngFor="let recv of receivers" [value]="recv.email">{{recv.name}}</option>
<select *ngIf="receivers" type="email" autocomplete="email" class="form-control" formControlName="email_receiver" id="email_receiver" placeholder="Receiver email" required>
<option *ngFor="let recv of receivers" [value]="recv?.email">{{recv?.name}}</option>
</select>
<input *ngIf="!receivers || receivers.length == 0" type="email" class="form-control" formControlName="email_receiver" id="email_receiver" placeholder="Receiver email">
<input *ngIf="!receivers || receivers.length === 0" type="email" autocomplete="email" class="form-control" formControlName="email_receiver" id="email_receiver" placeholder="Receiver email">
</div>
</div>
<div class="form-group row">
......
......@@ -15,6 +15,9 @@ export class EmailComponent implements OnInit {
@Input() receivers: {email: string, name: string}[];
@Input() message: string = "";
emailForm: FormGroup;
sent: boolean = false;
error: boolean = false;
constructor(private emailService: EmailService,
private userService: UserService) { }
......@@ -35,11 +38,15 @@ export class EmailComponent implements OnInit {
let email: IEmail = {
sender: this.emailForm.get('email_sender').value,
receiver: this.emailForm.get('email_receiver').value,
text: this.emailForm.get('email_message').value + "\n\n" + this.message
subject: "Krankheitsanalyse von " + this.emailForm.get('email_sender').value,
message: this.emailForm.get('email_message').value + "\n\n" + this.message
};
this.emailService.sendEmail(email)
.then(x => console.log("sucessfully sent"))
.catch(err => console.log(err));
.then(x => this.sent = true)
.catch(err => {
console.log(err);
this.error = true;
});
}
}
}
......@@ -22,7 +22,7 @@
<li class="nav-item" data-toggle="collapse" data-target=".navbar-collapse.show"><a class="nav-link" routerLink="/login">{{"TITLES.LOGIN" | translate }}</a></li>
</ng-template>
<li *ngIf="authservice.isAuthentificated()" style="cursor: pointer;" class="nav-item" (click)="logout()"><a class="nav-link">{{"TITLES.LOGOUT" | translate }}</a></li>
<li data-toggle="collapse" data-target=".navbar-collapse.show"><app-language-switch></app-language-switch></li>
<li><app-language-switch></app-language-switch></li>
</ul>
</div><!-- /.navbar-collapse -->
......
......@@ -23,7 +23,7 @@ export class HeaderComponent implements OnInit {
this.snackBar.open('Logout', 'succeed', {
duration: 2000,
});
this.route.navigate(['/login']);
this.route.navigate(['/login'], {queryParams: {logout: true}});
}
......
<select class="p-2" name="language" [(ngModel)]="current" (change)="change()">
<select class="p-2 no-collapse" name="language" [(ngModel)]="current" (change)="change()">
<option
*ngFor="let lang of languages"
[value]="lang"
......
......@@ -2,5 +2,5 @@ export interface IEmail {
sender: string,
receiver: string,
subject?: string,
text: string
message: string
}
\ No newline at end of file
......@@ -6,12 +6,12 @@
<form #analysisForm="ngForm" class="row col-md-6 col-sm-12 mx-auto justify-content-center flex-column" (ngSubmit)="onSubmit()">
<div class="form-group">
<label for="crop_id">{{"ANALYSIS.SELECT_A_CROP" | translate}}</label>
<select id="crop_id" name="crop_id" class="custom-select mb-3" ngModel>
<option *ngFor="let plant of plants" [value]="plant._id">{{plant.name}}</option>
<select id="crop_id" name="crop_id" class="custom-select mb-3" [(ngModel)]="selected">
<option *ngFor="let plant of plants" [value]="plant._id" >{{plant.name}}</option>
</select>
</div>
<div class="custom-file mb-3">
<input type='file' (change)="onSelectFile($event)" accept="image/*" class="inputfile col-md-3" id="image_file" name="image_file"
<input autocomplete="photo" type='file' (change)="onSelectFile($event)" accept="image/*" class="inputfile col-md-3" id="image_file" name="image_file"
#image ngModel>
<label class="custom-file-label" for="image_file">{{"ANALYSIS.SELECT_IMAGE" | translate}}</label>
</div>
......@@ -21,14 +21,16 @@
<div *ngIf="showImage == true" class="form-group mt-2">
<label for="notification_email" class="col-form-label">{{"ANALYSIS.TO_EMAIL" | translate}}:</label>
<input type="email" id="notification_email" name="notification_email" class="form-control" [(ngModel)]="notification_email">
<input type="email" autocomplete="email" id="notification_email" name="notification_email" class="form-control" [(ngModel)]="notification_email">
</div>
<div *ngIf="showImage == true" class="mt-3 mx-auto">
<button type="button" type="submit" class="btn btn-primary btn-lg">{{"ANALYSIS.ANALYSE" | translate}}</button>
</div>
</form>
<div class="col-md-8 alert alert-danger mx-auto" style="display: none;" #error>
{{"ANALYSIS.NO_RESULT" | translate}}
</div>
<div class="cover" #loader>
<div class="loader"></div>
<h3>{{"ANALYSIS.PROGRESS" | translate}}</h3>
<h3 class="mx-4 text-center">{{"ANALYSIS.PROGRESS" | translate}}</h3>
</div>
......@@ -3,7 +3,7 @@ import { PlantService } from '../../services/plant.service';
import { IPlant } from '../../model/IPlant';
import { FormGroup, FormControl, Validators, NgForm } from '@angular/forms';
import { AnalysisService } from '../../services/analysis.service';
import { Router } from '@angular/router';
import { Router, ActivatedRoute } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import { UserService } from '../../services/user.service';
......@@ -19,14 +19,18 @@ export class AnalyseComponent implements OnInit {
notification_email: string = "";
plants: IPlant[] = [];
selected: number;
@ViewChild(NgForm) analysisForm:NgForm;
@ViewChild('image') image;
@ViewChild('loader') loader;
@ViewChild('error') error:ElementRef;
constructor(private pService: PlantService,
private aService: AnalysisService,
public userService: UserService,
private router: Router) {
private router: Router,
private route: ActivatedRoute) {
}
......@@ -37,7 +41,14 @@ export class AnalyseComponent implements OnInit {
}
getPlants(){
this.pService.getAllPlants().then(plants => this.plants = plants);
this.pService.getAllPlants().then(plants => {
this.plants = plants;
this.route.queryParams.subscribe(params => {
let preselect = params["plant"];
if(preselect) this.selected = +preselect;
else this.selected = plants[0]._id;
})
});
}
......@@ -46,11 +57,11 @@ export class AnalyseComponent implements OnInit {
onSubmit(){
let element = this.image.nativeElement;
if(element.files && element.files[0]){
if(this.selected && element.files && element.files[0]){
this.startAnalysis();
const formData = new FormData();
formData.append('image_file', element.files[0]);
formData.append('crop_id', this.analysisForm.value.crop_id);
formData.append('crop_id', this.selected.toString());
formData.append('notification_email', this.notification_email);
this.aService.startAnalysis(formData)
.then(res => {
......@@ -59,6 +70,7 @@ export class AnalyseComponent implements OnInit {
})
.catch(err => {
this.stopAnalysis();
this.error.nativeElement.style.display = 'block';
console.error(err);
});
}
......@@ -78,4 +90,5 @@ export class AnalyseComponent implements OnInit {
}
}
}
......@@ -10,9 +10,6 @@ export class ListmapComponent implements OnInit {
constructor(public mapservice: MapService) { }
ngOnInit() {
console.log(this.mapservice.data);
}
ngOnInit() {}
}
......@@ -6,8 +6,7 @@
<agm-marker
[latitude]="mapservice.lat"
[longitude]="mapservice.lng"
[iconUrl]= "'../../assets/icons/icons8-map-pin-50.png'"
(markerClick)="test()" >
[iconUrl]= "'../../assets/icons/icons8-map-pin-50.png'">
<agm-info-window>
<h4><strong>{{"GARDENERS.HERE" | translate}}</strong></h4>
......@@ -17,8 +16,7 @@
<agm-marker *ngFor="let m of mapservice.data"
[latitude]="m.latitude"
[longitude]="m.longitude"
(markerClick)="test()" >
[longitude]="m.longitude">
<agm-info-window>
<h4><strong> {{m.name}}!</strong></h4>
......
......@@ -10,19 +10,10 @@ import {MapService} from '../../../services/map.service';
})
export class MapComponent implements OnInit {
title = 'My first AGM project';
lat: number;
lng: number;
zoom = 11;
constructor( public mapservice: MapService) {
}
ngOnInit() {
}
test() {
console.log(this.lat);
}
ngOnInit() {}
}
......@@ -3,17 +3,29 @@
<i class="fas fa-sign-in-alt"></i> {{"TITLES.LOGIN" | translate}}</h1>
<hr>
<div class="alert alert-success" *ngIf="logout && !logoutReason">{{"LOGOUT.SUCCESS" | translate}}</div>
<div class="alert alert-success" *ngIf="logout && logoutReason === 'update'">{{"LOGOUT.UPDATE" | translate}}</div>
<div class="alert alert-success" *ngIf="logout && logoutReason === 'delete'">{{"LOGOUT.DELETE" | translate}}</div>
<div class="alert alert-success" *ngIf="logoutReason === 'registered'">{{"LOGOUT.REGISTERED" | translate}}</div>
<div class="alert alert-danger" *ngIf="logout && logoutReason === 'timeout'">{{"LOGOUT.TIMEOUT" | translate}}</div>
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="form-group row">
<label for="inputEmail3" class="col-sm-2 col-form-label">{{"AUTH.EMAIL" | translate}}:</label>
<div class="col-sm-10">
<input type="email" class="form-control" formControlName="email" id="inputEmail3" [placeholder]="'AUTH.EMAIL' | translate">
<input type="email" class="form-control"
autocomplete="email"
formControlName="email" id="inputEmail3"
[placeholder]="'AUTH.EMAIL' | translate">
</div>
</div>
<div class="form-group row">
<label for="inputPassword3" class="col-sm-2 col-form-label">{{"AUTH.PASSWORD" | translate}}:</label>
<div class="col-sm-10">
<input type="password" class="form-control" formControlName="password" id="inputPassword3" [placeholder]="'AUTH.PASSWORD' | translate">
<input type="password" class="form-control"
autocomplete="current-password"
formControlName="password" id="inputPassword3"
[placeholder]="'AUTH.PASSWORD' | translate">
</div>
</div>
<div class="form-group row">
......
import {Component, OnInit} from '@angular/core';
import {Router} from '@angular/router';
import {Router, ActivatedRoute} from '@angular/router';
import {MatSnackBar} from '@angular/material';
import {AuthService} from '../../services/auth.service';
import {FormControl, FormGroup, Validators} from '@angular/forms';
......@@ -14,7 +14,13 @@ export class LoginComponent implements OnInit {
errorResponse: string;
error: boolean = false;
constructor(private authservice: AuthService, public snackBar: MatSnackBar, private route: Router) {
logout: boolean = false;
logoutReason: string;
constructor(private authservice: AuthService,
public snackBar: MatSnackBar,
private router: Router,
private route: ActivatedRoute) {
}
ngOnInit() {
......@@ -25,6 +31,11 @@ export class LoginComponent implements OnInit {
'loggedIn': new FormControl(null)
}
);
this.route.queryParams.subscribe(params => {
this.logout = 'true' === params["logout"];
this.logoutReason = params["reason"];
})
}
onSubmit() {
......@@ -33,15 +44,13 @@ export class LoginComponent implements OnInit {
this.snackBar.open('Login', 'succeed', {
duration: 3000,
});
this.route.navigate(['/profile']);
this.router.navigate(['/profile']);
}).catch(err => {
this.snackBar.open('Login', 'failed', {
duration: 3000,
});
this.error = true;
this.errorResponse = err.error.error.message;
console.log(err);
});
}
......
......@@ -37,6 +37,6 @@ export class PlantdetailsComponent implements OnInit, OnDestroy {
}
onShowAnalyse() {
this.router.navigate(['/result']);
this.router.navigate(['/analyse'], {queryParams: {plant: this.plant._id}});
}
}
<h2 class="col-md-12">{{"TITLES.PROFILE" | translate}}</h2>
<hr>
<div *ngIf="errorMessage" class="col-md-12 alert alert-danger" role="alert">
{{errorMessage | translate}}!
</div>
<div class="col-md-12">
<h3 class="mt-5">{{"PROFILE.INFORMATION" | translate}}</h3>
<h3 class="mt-3">{{"PROFILE.INFORMATION" | translate}}</h3>
<form (ngSubmit)="updateProfile()">
<div class="form-group row">
<label for="name" class="col-sm-2 col-form-label">{{"PROFILE.NAME" | translate}}:</label>
<div class="col-sm-10">
<input type="name" readonly class="form-control-plaintext" id="name" [value]="user.name">
<input type="name" autocomplete="name" readonly class="form-control-plaintext" id="name" [value]="user.name">
</div>
</div>
<div class="form-group row">
<label for="email" class="col-sm-2 col-form-label">{{"PROFILE.EMAIL" | translate}}:</label>
<div class="col-sm-10">
<input type="email" readonly class="form-control-plaintext" id="email" [value]="user.email">
<input type="email" autocomplete="email" readonly class="form-control-plaintext" id="email" [value]="user.email">
</div>
</div>
<div class="form-group row">
<label for="passwordOld" class="col-sm-2 col-form-label">{{"PROFILE.OLD_PASSWORD" | translate}}:</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="passwordOld" name="password" [placeholder]="'PROFILE.OLD_PASSWORD' | translate" [(ngModel)]="update.password">
<input type="password" autocomplete="current-password" class="form-control" id="passwordOld" name="password" [placeholder]="'PROFILE.OLD_PASSWORD' | translate" [(ngModel)]="update.password">
</div>
</div>
<div class="form-group row">
<label for="passwordNew" class="col-sm-2 col-form-label">{{"PROFILE.NEW_PASSWORD" | translate}}:</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="passwordNew" name="new_password" [placeholder]="'PROFILE.NEW_PASSWORD' | translate" [(ngModel)]="update.new_password">
<input type="password" autocomplete="new-password" class="form-control" id="passwordNew" name="new_password" [placeholder]="'PROFILE.NEW_PASSWORD' | translate" [(ngModel)]="update.new_password">
</div>
</div>
<div class="form-group row">
<div class="col-sm-offset-2 col-sm-10">
<div class="d-flex col-md-12 align-items-center flex-wrap">
<button type="submit" class="btn btn-success mr-3">{{"PROFILE.UPDATE_PROFILE" | translate}}</button>
<button type="button" class="btn btn-danger" data-toggle="modal" data-target="#confirm_dialog">{{"PROFILE.DELETE_PROFILE" | translate}}</button>
<small class="ml-auto w-100 py-2">{{"PROFILE.MEMBER_SINCE" | translate}} {{user?.created_at | date: 'shortDate'}}</small>
</div>
</div>
</form>
......@@ -55,6 +58,7 @@
</tr>
</tbody>
</table>
<h5 class="pl-2" *ngIf="history.length <= 0">{{"PROFILE.NO_ANALYSIS" | translate}}</h5>
</div>
<div class="modal" id="confirm_dialog" tabindex="-1" role="dialog" aria-hidden="true">
......@@ -67,8 +71,8 @@
</button>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger">{{"PROFILE.DELETE_PROFILE" | translate}}</button>
<button type="button" (click)="deleteProfile()" class="btn btn-secondary" data-dismiss="modal">{{"CONTROLS.CANCEL" | translate}}</button>
<button type="button" (click)="deleteProfile()" class="btn btn-danger" data-dismiss="modal">{{"PROFILE.DELETE_PROFILE" | translate}}</button>
<button type="button" class="btn btn-secondary" data-dismiss="modal">{{"CONTROLS.CANCEL" | translate}}</button>
</div>
</div>
</div>
......
......@@ -6,6 +6,7 @@ import { IJob } from '../../model/IJob';
import { UserDataService } from '../../services/user-data.service';
import { Router } from '@angular/router';
import { AuthService } from '../../services/auth.service';
import { TranslateService } from '@ngx-translate/core';
@Component({
selector: 'app-profile',
......@@ -15,6 +16,7 @@ import { AuthService } from '../../services/auth.service';
})
export class ProfileComponent implements OnInit {
errorMessage: string;
user: IUser;
history: IJob[] = [];
......@@ -43,22 +45,30 @@ export class ProfileComponent implements OnInit {
this.userDataService.updateUser(this.update)
.then(user => {
this.user = user;
this.errorMessage = null;
this.userService.setUser(user);
this.authService.logout();
this.router.navigate(["/login"]);
this.router.navigate(["/login"], {queryParams: {logout: true, reason: 'update'}});
}).catch(err => {
this.authService.logout();
this.router.navigate(["/login"]);
this.errorMessage = err.error.message || 'PROFILE.UPDATE_FAILED';
});
}else{
console.log("No valid password");
this.errorMessage = "AUTH.NO_VALID_PASSWORD";
}
}
deleteProfile(){
this.userDataService.removeUser()
.then(() => {
this.router.navigate(["/login"]);
}).catch(err => console.error(err));
if(typeof this.update.password === 'string' && this.update.password.length >= 8){
this.userDataService.removeUser(this.update)
.then(()=>{
this.errorMessage = null;
this.authService.logout();
this.router.navigate(["/login"], {queryParams: {logout: true, reason: 'delete'}});
}).catch(err => {
this.errorMessage = err.error.message || 'PROFILE.DELETE_FAILED';
});
}else{
this.errorMessage = "AUTH.NO_VALID_PASSWORD";
}
}
}
......@@ -7,7 +7,7 @@
<div class="form-group row">
<label for="name" class="col-sm-2 col-form-label">Name:</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="name" formControlName="name" [placeholder]="'AUTH.ENTER_NAME' | translate">
<input type="text" class="form-control" id="name" autocomplete="name" formControlName="name" [placeholder]="'AUTH.ENTER_NAME' | translate">
<span *ngIf="!registerForm.get('name').valid && registerForm.get('name').touched" class="help-block">
{{"AUTH.NO_VALID_NAME" | translate}}
</span>
......@@ -16,7 +16,7 @@
<div class="form-group row">
<label for="inputEmail3" class="col-sm-2 col-form-label">{{"AUTH.EMAIL" | translate}}</label>
<div class="col-sm-10">
<input type="email" class="form-control" id="inputEmail3" formControlName="email" [placeholder]="'AUTH.ENTER_EMAIL' | translate">
<input type="email" class="form-control" autocomplete="email" id="inputEmail3" formControlName="email" [placeholder]="'AUTH.ENTER_EMAIL' | translate">
<span *ngIf="!registerForm.get('email').valid && registerForm.get('email').touched" class="help-block">
{{"AUTH.NO_VALID_EMAIL" | translate}}
</span>
......@@ -25,7 +25,7 @@
<div class="form-group row">
<label for="inputPassword3" class="col-sm-2 col-form-label">Password:</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="inputPassword3" formControlName="password" [placeholder]="'AUTH.ENTER_PASSWORD' | translate">
<input type="password" class="form-control" autocomplete="new-password" id="inputPassword3" formControlName="password" [placeholder]="'AUTH.ENTER_PASSWORD' | translate">
<span *ngIf="!registerForm.get('password').valid && registerForm.get('password').touched" class="help-block">
{{'AUTH.NO_VALID_PASSWORD' | translate}}
</span>
......
......@@ -31,7 +31,7 @@ export class RegisterComponent implements OnInit {
this.authservice.register(this.registerForm.value)
.then(message => {
this.registerForm.reset();
this.route.navigate(['/login']);
this.route.navigate(['/login'], {queryParams: {reason: 'registered'}});
}).catch(err => {
this.snackBar.open('Registration', 'failed', {
duration: 3000,
......
Supports Markdown
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