US03: Make it possible to update a hourse through the web UI
This commit is contained in:
parent
1eaaf27bac
commit
034837ce1b
@ -3,6 +3,7 @@ import { Routes, RouterModule } from '@angular/router';
|
|||||||
import { OwnerComponent } from './component/owner/owner.component';
|
import { OwnerComponent } from './component/owner/owner.component';
|
||||||
import { HorseComponent } from './component/horse/horse.component';
|
import { HorseComponent } from './component/horse/horse.component';
|
||||||
import { AddHorseComponent } from './component/add-horse/add-horse.component';
|
import { AddHorseComponent } from './component/add-horse/add-horse.component';
|
||||||
|
import { UpdateHorseComponent } from './component/update-horse/update-horse.component';
|
||||||
|
|
||||||
|
|
||||||
const routes: Routes = [
|
const routes: Routes = [
|
||||||
@ -10,6 +11,7 @@ const routes: Routes = [
|
|||||||
{path: 'owner', component: OwnerComponent},
|
{path: 'owner', component: OwnerComponent},
|
||||||
{path: 'horse', component: HorseComponent},
|
{path: 'horse', component: HorseComponent},
|
||||||
{path: 'horse/add', component: AddHorseComponent},
|
{path: 'horse/add', component: AddHorseComponent},
|
||||||
|
{path: 'horse/:id/edit', component: UpdateHorseComponent},
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -9,6 +9,7 @@ import {HeaderComponent} from './component/header/header.component';
|
|||||||
import {OwnerComponent} from './component/owner/owner.component';
|
import {OwnerComponent} from './component/owner/owner.component';
|
||||||
import { HorseComponent } from './component/horse/horse.component';
|
import { HorseComponent } from './component/horse/horse.component';
|
||||||
import { AddHorseComponent } from './component/add-horse/add-horse.component';
|
import { AddHorseComponent } from './component/add-horse/add-horse.component';
|
||||||
|
import { UpdateHorseComponent } from './component/update-horse/update-horse.component';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
@ -16,7 +17,8 @@ import { AddHorseComponent } from './component/add-horse/add-horse.component';
|
|||||||
HeaderComponent,
|
HeaderComponent,
|
||||||
OwnerComponent,
|
OwnerComponent,
|
||||||
HorseComponent,
|
HorseComponent,
|
||||||
AddHorseComponent
|
AddHorseComponent,
|
||||||
|
UpdateHorseComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
BrowserModule,
|
BrowserModule,
|
||||||
|
@ -0,0 +1,61 @@
|
|||||||
|
<div *ngIf="error" class="alert alert-danger alert-dismissible fade show" role="alert">
|
||||||
|
<strong>Error! </strong> {{ errorMessage }}
|
||||||
|
<button type="button" (click)="vanishError()" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="success" class="alert alert-success alert-dismissible fade show" role="alert">
|
||||||
|
<p><strong>Success! </strong> Horse {{ success }} has been successfully added. </p>
|
||||||
|
<button type="button" (click)="vanishAlert()" class="close" data-dismiss="alert" aria-label="Close">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="container">
|
||||||
|
<h1>Add new horse</h1>
|
||||||
|
<form (ngSubmit)="updateHorse()" #horseForm="ngForm">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Name</label>
|
||||||
|
<input type="text" class="form-control" name="name" [(ngModel)]="horse.name" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="description">Description</label>
|
||||||
|
<textarea class="form-control" name="description" [(ngModel)]="horse.description"></textarea>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="score">Score</label>
|
||||||
|
<select class="form-control" name="score" [(ngModel)]="horse.score" required>
|
||||||
|
<option value="1">1</option>
|
||||||
|
<option value="2">2</option>
|
||||||
|
<option value="3">3</option>
|
||||||
|
<option value="4">4</option>
|
||||||
|
<option value="5">5</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="race">Race</label>
|
||||||
|
<select class="form-control" name="race" [(ngModel)]="horse.race" required>
|
||||||
|
<option value="ARABIAN">Arabian</option>
|
||||||
|
<option value="MORGAN">Morgan</option>
|
||||||
|
<option value="PAINT">Paint</option>
|
||||||
|
<option value="APPALOOSA">Appaloosa</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="birthday">Birthday</label>
|
||||||
|
<input type="date" class="form-control" name="birthday" [(ngModel)]="horse.birthday" required pattern="\d{4}-\d{2}-\d{2}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="image">Image</label>
|
||||||
|
<input type="file" class="form-control-file" name="image" id="image" (change)="handleImageInput($event.target.files)" required>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button type="submit" class="btn btn-success" [disabled]="!horseForm.form.valid" (submit)="updateHorse()">Submit</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
@ -0,0 +1,132 @@
|
|||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { ActivatedRoute, Params} from '@angular/router';
|
||||||
|
import { Horse } from '../../dto/horse';
|
||||||
|
import { HorseService } from '../../service/horse.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-update-horse',
|
||||||
|
templateUrl: './update-horse.component.html',
|
||||||
|
styleUrls: ['./update-horse.component.scss']
|
||||||
|
})
|
||||||
|
export class UpdateHorseComponent implements OnInit {
|
||||||
|
error = false;
|
||||||
|
success: string;
|
||||||
|
errorMessage = '';
|
||||||
|
horse: Horse = new Horse(null, null, null, null, null, null, null, null);
|
||||||
|
imageToUpload: File = null;
|
||||||
|
|
||||||
|
constructor(private horseService: HorseService, private route: ActivatedRoute) { }
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
// Extract id from url
|
||||||
|
const horseId: string = this.route.snapshot.paramMap.get('id');
|
||||||
|
|
||||||
|
// Get current value of the horse and save it
|
||||||
|
this.horseService.getHorseById(parseInt(horseId, 10)).subscribe(
|
||||||
|
(horse: Horse) => {
|
||||||
|
this.horse = horse;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.defaultServiceErrorHandling(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be called on a click on the success alert close button
|
||||||
|
*/
|
||||||
|
public vanishAlert() {
|
||||||
|
this.success = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will be called on a click on the error alert close button
|
||||||
|
*/
|
||||||
|
public vanishError() {
|
||||||
|
this.errorMessage = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the input on the image input.
|
||||||
|
* Inspired from:
|
||||||
|
* https://stackoverflow.com/questions/47936183/angular-file-upload
|
||||||
|
* @param files
|
||||||
|
*/
|
||||||
|
public handleImageInput(files: FileList) {
|
||||||
|
var imageFile: File = files.item(0);
|
||||||
|
|
||||||
|
// Generate a random bytes name to avoid conflicts
|
||||||
|
var fileExt: string = imageFile.name.split('.').pop();
|
||||||
|
var newFileName: string = this.generateHex(20) + '.' + fileExt;
|
||||||
|
this.horse.imagePath = newFileName;
|
||||||
|
|
||||||
|
// Upload the file
|
||||||
|
this.uploadFile(imageFile, newFileName)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a horse and loads it
|
||||||
|
* @param horse
|
||||||
|
*/
|
||||||
|
public updateHorse() {
|
||||||
|
console.log("PUT horse to API")
|
||||||
|
console.log(this.horse);
|
||||||
|
// TODO: Make it possible for the horse to be added with an owner
|
||||||
|
this.horseService.updateHorse(this.horse).subscribe(
|
||||||
|
(result: Horse) => {
|
||||||
|
this.success = result.name;
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
this.defaultServiceErrorHandling(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uploads the file to the backend with the specified file name
|
||||||
|
* @param file
|
||||||
|
* @param newFileName
|
||||||
|
*/
|
||||||
|
private uploadFile(file: File, newFileName: string){
|
||||||
|
this.horseService.postFile(file, newFileName).subscribe(
|
||||||
|
() => {
|
||||||
|
console.log("Image successfully uploaded");
|
||||||
|
}, error => {
|
||||||
|
this.defaultServiceErrorHandling(error)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a random hex with the specified length
|
||||||
|
* Inspired from:
|
||||||
|
* https://stackoverflow.com/a/27747377
|
||||||
|
* @param len
|
||||||
|
*/
|
||||||
|
private generateHex(len: number): string {
|
||||||
|
var arr = new Uint8Array((len) / 2)
|
||||||
|
window.crypto.getRandomValues(arr)
|
||||||
|
return Array.from(arr, this.dec2hex).join('')
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a decimal to its hex value
|
||||||
|
* @param dec
|
||||||
|
*/
|
||||||
|
private dec2hex(dec: number): string {
|
||||||
|
return ('0' + dec.toString(16)).substr(-2)
|
||||||
|
}
|
||||||
|
|
||||||
|
private defaultServiceErrorHandling(error: any) {
|
||||||
|
console.log(error);
|
||||||
|
this.error = true;
|
||||||
|
if (error.status === 0) {
|
||||||
|
// If status is 0, the backend is probably down
|
||||||
|
this.errorMessage = 'The backend seems not to be reachable';
|
||||||
|
} else if (error.error.message === 'No message available') {
|
||||||
|
// If no detailed error message is provided, fall back to the simple error name
|
||||||
|
this.errorMessage = error.error.error;
|
||||||
|
} else {
|
||||||
|
this.errorMessage = error.error.message;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,11 @@ export class HorseService {
|
|||||||
return this.httpClient.post<Horse>(this.messageBaseUri, horse);
|
return this.httpClient.post<Horse>(this.messageBaseUri, horse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateHorse(horse: Horse): Observable<Horse> {
|
||||||
|
console.log('Update horse with id ' + horse.id + ': '+ JSON.stringify(horse));
|
||||||
|
return this.httpClient.put<Horse>(this.messageBaseUri + '/' + horse.id, horse);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user