From ec756028aa2b582ebc914f1b952ce138344a5dff Mon Sep 17 00:00:00 2001 From: Florian Hartwich Date: Mon, 15 May 2017 15:32:36 +0200 Subject: [PATCH] Add editing/creating of ranks --- .../new-decoration.component.css | 3 + .../ranks/rank-list/rank-item.component.html | 2 +- .../ranks/rank-list/rank-item.component.ts | 5 + .../ranks/rank-list/rank-list.component.ts | 3 +- .../app/ranks/rank-new/new-rank.component.css | 7 ++ .../ranks/rank-new/new-rank.component.html | 66 +++++++++++ .../app/ranks/rank-new/new-rank.component.ts | 105 ++++++++++++++++++ .../rank-overview/rank-overview.component.css | 0 .../rank-overview.component.html | 79 ------------- .../rank-overview/rank-overview.component.ts | 86 -------------- static/src/app/ranks/ranks.routing.ts | 13 ++- .../app/services/rank-service/rank.service.ts | 54 ++++++++- .../squads/new-squad/new-squad.component.css | 3 + 13 files changed, 252 insertions(+), 174 deletions(-) create mode 100644 static/src/app/ranks/rank-new/new-rank.component.css create mode 100644 static/src/app/ranks/rank-new/new-rank.component.html create mode 100644 static/src/app/ranks/rank-new/new-rank.component.ts delete mode 100644 static/src/app/ranks/rank-overview/rank-overview.component.css delete mode 100644 static/src/app/ranks/rank-overview/rank-overview.component.html delete mode 100644 static/src/app/ranks/rank-overview/rank-overview.component.ts diff --git a/static/src/app/decorations/new-decoration/new-decoration.component.css b/static/src/app/decorations/new-decoration/new-decoration.component.css index e69de29..c77d09c 100644 --- a/static/src/app/decorations/new-decoration/new-decoration.component.css +++ b/static/src/app/decorations/new-decoration/new-decoration.component.css @@ -0,0 +1,3 @@ +.form-control { + height: auto; +} diff --git a/static/src/app/ranks/rank-list/rank-item.component.html b/static/src/app/ranks/rank-list/rank-item.component.html index e960ace..a1c9d8a 100644 --- a/static/src/app/ranks/rank-list/rank-item.component.html +++ b/static/src/app/ranks/rank-list/rank-item.component.html @@ -12,7 +12,7 @@
- +
diff --git a/static/src/app/ranks/rank-list/rank-item.component.ts b/static/src/app/ranks/rank-list/rank-item.component.ts index e602091..6e39a6d 100644 --- a/static/src/app/ranks/rank-list/rank-item.component.ts +++ b/static/src/app/ranks/rank-list/rank-item.component.ts @@ -14,6 +14,7 @@ export class RankItemComponent { selected: boolean; rank: Rank; + imageSrc; rankSelected = new EventEmitter(); rankDelete = new EventEmitter(); @@ -22,6 +23,10 @@ export class RankItemComponent { } + ngOnInit() { + this.imageSrc = 'resource/rank/' + this.rank._id + '.png?' + Date.now(); + } + select() { this.rankSelected.emit(this.rank._id) } diff --git a/static/src/app/ranks/rank-list/rank-list.component.ts b/static/src/app/ranks/rank-list/rank-list.component.ts index e6a2d1b..579883c 100644 --- a/static/src/app/ranks/rank-list/rank-list.component.ts +++ b/static/src/app/ranks/rank-list/rank-list.component.ts @@ -48,12 +48,13 @@ export class RankListComponent implements OnInit { } openNewRankForm() { + this.selectedRankId = null; this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route}); } selectRank(rankId: string | number) { this.selectedRankId = rankId; - this.router.navigate([{outlets: {'right': ['overview', rankId]}}], {relativeTo: this.route}); + this.router.navigate([{outlets: {'right': ['new', rankId]}}], {relativeTo: this.route}); } filterRanksByFraction(query = '', fractionFilter) { diff --git a/static/src/app/ranks/rank-new/new-rank.component.css b/static/src/app/ranks/rank-new/new-rank.component.css new file mode 100644 index 0000000..0523e4c --- /dev/null +++ b/static/src/app/ranks/rank-new/new-rank.component.css @@ -0,0 +1,7 @@ +.preview-image { + margin: 10px; +} + +.form-control { + height: auto; +} diff --git a/static/src/app/ranks/rank-new/new-rank.component.html b/static/src/app/ranks/rank-new/new-rank.component.html new file mode 100644 index 0000000..93ac334 --- /dev/null +++ b/static/src/app/ranks/rank-new/new-rank.component.html @@ -0,0 +1,66 @@ +
+

Rang editieren

+

Neuen Rang hinzufügen

+ +
+ + + + +
+ +
+ + + +
+ +
+ + + +
+ +
+ + + + Bild muss im PNG Format vorliegen + + + +
+ + + + + + + Erfolgreich gespeichert + + +
diff --git a/static/src/app/ranks/rank-new/new-rank.component.ts b/static/src/app/ranks/rank-new/new-rank.component.ts new file mode 100644 index 0000000..649e720 --- /dev/null +++ b/static/src/app/ranks/rank-new/new-rank.component.ts @@ -0,0 +1,105 @@ +import {Component, ViewChild} from "@angular/core"; +import {ActivatedRoute, Router} from "@angular/router"; +import {NgForm} from "@angular/forms"; +import {Rank} from "../../models/model-interfaces"; +import {RankService} from "../../services/rank-service/rank.service"; +import {Subscription} from "rxjs/Subscription"; + + +@Component({ + templateUrl: './new-rank.component.html', + styleUrls: ['./new-rank.component.css', '../../style/new-entry-form.css'] +}) +export class CreateRankComponent { + + subscription: Subscription; + + rank: Rank = {name: '', fraction: '', level: 0}; + + fileList: FileList; + + saved = false; + + showImageError = false; + + imagePreviewSrc; + + showSuccessLabel = false; + + @ViewChild(NgForm) form: NgForm; + + constructor(private route: ActivatedRoute, + private router: Router, + private rankService : RankService) { + } + + ngOnInit() { + this.subscription = this.route.params + .map(params => params['id']) + .filter(id => id != undefined) + .flatMap(id => this.rankService.getRank(id)) + .subscribe(rank => { + this.rank = rank; + this.imagePreviewSrc = 'resource/rank/' + this.rank._id + '.png?' + Date.now(); + }); + } + + ngOnDestroy() { + this.subscription.unsubscribe(); + } + + fileChange(event) { + if (!event.target.files[0].name.endsWith('.png')) { + this.showImageError = true; + this.fileList = undefined; + } else { + this.showImageError = false; + this.fileList = event.target.files; + } + } + + saveRank(fileInput) { + let file: File; + if (!this.rank._id) { + if (this.fileList) { + file = this.fileList[0]; + this.rankService.submitRank(this.rank, file) + .subscribe(rank => { + this.saved = true; + this.router.navigate(['..'], {relativeTo: this.route}); + }) + } else { + return window.alert(`Bild ist ein Pflichtfeld`); + } + } else { + if (this.fileList) { + file = this.fileList[0]; + } + delete this.rank['__v']; + this.rankService.submitRank(this.rank, file) + .subscribe(rank => { + setTimeout(() => { + this.imagePreviewSrc = 'resource/rank/' + this.rank._id + '.png?' + Date.now(); + }, 300); + fileInput.value = ''; + this.showSuccessLabel = true; + setTimeout(() => { + this.showSuccessLabel = false; + }, 2000) + }) + } + } + + cancel() { + this.router.navigate([this.rank._id ? '../..' : '..'], {relativeTo: this.route}); + return false; + } + + canDeactivate(): boolean { + if (this.saved || !this.form.dirty) { + return true; + } + return window.confirm(`Ihr Formular besitzt ungespeicherte Änderungen, möchten Sie die Seite wirklich verlassen?`); + } + +} diff --git a/static/src/app/ranks/rank-overview/rank-overview.component.css b/static/src/app/ranks/rank-overview/rank-overview.component.css deleted file mode 100644 index e69de29..0000000 diff --git a/static/src/app/ranks/rank-overview/rank-overview.component.html b/static/src/app/ranks/rank-overview/rank-overview.component.html deleted file mode 100644 index 90ddbec..0000000 --- a/static/src/app/ranks/rank-overview/rank-overview.component.html +++ /dev/null @@ -1,79 +0,0 @@ -
-

Rang-Details - - Erfolgreich gespeichert - -

-
-
- - -
-
-
- -
-
- {{rank.name}} -
-
- -
- -
-
-
- -
-
- CSAT -
-
- NATO -
-
-
-
-
-
- -
-
- {{rank.level}} -
-
-
-
-
- -
-
-
-
- -
-
- -
-
- - - - Bild muss im PNG Format vorliegen - -
-
- - Bestätigen -
-
-
- - -
-
-
diff --git a/static/src/app/ranks/rank-overview/rank-overview.component.ts b/static/src/app/ranks/rank-overview/rank-overview.component.ts deleted file mode 100644 index 080c7a0..0000000 --- a/static/src/app/ranks/rank-overview/rank-overview.component.ts +++ /dev/null @@ -1,86 +0,0 @@ -import {Component} from "@angular/core"; -import {ActivatedRoute} from "@angular/router"; -import {Rank} from "../../models/model-interfaces"; -import {RankService} from "../../services/rank-service/rank.service"; - - -@Component({ - templateUrl: './rank-overview.component.html', - styleUrls: ['./rank-overview.component.css', '../../style/overview.css'], -}) -export class RankOverviewComponent { - - showSuccessLabel = false; - - showImageError = false; - - rank: Rank; - - fileList: FileList; - - imagePreview; - - constructor(private route: ActivatedRoute, - private rankService: RankService) { - } - - ngOnInit() { - this.route.params.subscribe((params) => { - this.rankService.getRank(params['id']).subscribe(rank => { - this.rank = rank; - this.imagePreview = 'resource/rank/' + rank._id + '.png?' + Date.now(); - }) - }) - } - - /** - * register change on file input and save to local fileList - * @param event - */ - fileChange(event) { - if (!event.target.files[0].name.endsWith('.png')) { - this.showImageError = true; - this.fileList = undefined; - } else { - this.showImageError = false; - this.fileList = event.target.files; - } - } - - - update(attrName, inputField) { - const inputValue = inputField.value; - if (inputValue.length > 0 && this.rank[attrName] !== inputValue) { - const updateObject = {_id: this.rank._id}; - updateObject[attrName] = inputValue; - this.rankService.updateRank(updateObject) - .subscribe(rank => { - this.rank = rank; - inputField.value = ''; - this.showSuccessLabel = true; - setTimeout(() => { - this.showSuccessLabel = false; - }, 2000) - }) - } - } - - updateGraphic(fileInput) { - if (this.fileList && this.fileList.length > 0) { - let file: File = this.fileList[0]; - this.rankService.updateRankGraphic(this.rank._id, file) - .subscribe((res) => { - setTimeout(() => { - this.imagePreview = 'resource/rank/' + this.rank._id + '.png?' + Date.now(); - }, 300); - fileInput.value = ''; - this.showSuccessLabel = true; - setTimeout(() => { - this.showSuccessLabel = false; - }, 2000) - }) - } - } - - -} diff --git a/static/src/app/ranks/ranks.routing.ts b/static/src/app/ranks/ranks.routing.ts index 245f1bf..9a5fd13 100644 --- a/static/src/app/ranks/ranks.routing.ts +++ b/static/src/app/ranks/ranks.routing.ts @@ -1,7 +1,7 @@ import {Routes} from "@angular/router"; import {RankComponent} from "./ranks.component"; import {RankListComponent} from "./rank-list/rank-list.component"; -import {RankOverviewComponent} from "./rank-overview/rank-overview.component"; +import {CreateRankComponent} from "./rank-new/new-rank.component"; export const ranksRoutes: Routes = [{ @@ -14,10 +14,15 @@ export const ranksRoutes: Routes = [{ ] }, { - path: 'overview/:id', - component: RankOverviewComponent, + path: 'new', + component: CreateRankComponent, + outlet: 'right' + }, + { + path: 'new/:id', + component: CreateRankComponent, outlet: 'right' }]; -export const ranksRoutingComponents = [RankComponent, RankListComponent, RankOverviewComponent]; +export const ranksRoutingComponents = [RankComponent, RankListComponent, CreateRankComponent]; diff --git a/static/src/app/services/rank-service/rank.service.ts b/static/src/app/services/rank-service/rank.service.ts index fe84522..335a5bc 100644 --- a/static/src/app/services/rank-service/rank.service.ts +++ b/static/src/app/services/rank-service/rank.service.ts @@ -3,7 +3,7 @@ import {Decoration, Rank} from "../../models/model-interfaces"; import {RequestMethod, RequestOptions, URLSearchParams} from "@angular/http"; import {Observable} from "rxjs/Observable"; import {LOAD} from "../stores/decoration.store"; -import {EDIT, RankStore, REMOVE} from "../stores/rank.store"; +import {ADD, EDIT, RankStore, REMOVE} from "../stores/rank.store"; import {AppConfig} from "../../app.config"; import {HttpClient} from "../http-client"; @@ -29,8 +29,8 @@ export class RankService { this.http.get(this.config.apiUrl + this.config.apiRankPath, searchParams) .map(res => res.json()) - .do((squads) => { - this.rankStore.dispatch({type: LOAD, data: squads}); + .do((ranks) => { + this.rankStore.dispatch({type: LOAD, data: ranks}); }).subscribe(_ => { }); @@ -42,6 +42,54 @@ export class RankService { .map(res => res.json()); } + /** + * For creating new data with POST or + * update existing with patch PATCH + */ + submitRank(rank: Rank, imageFile?) { + let requestUrl = this.config.apiUrl + this.config.apiRankPath; + let requestMethod: RequestMethod; + let accessType; + let body; + + if (rank._id) { + requestUrl += rank._id; + requestMethod = RequestMethod.Patch; + accessType = EDIT; + } else { + requestMethod = RequestMethod.Post; + accessType = ADD; + } + + if (imageFile) { + body = new FormData(); + Object.keys(rank).map((objectKey) => { + if (rank[objectKey] !== undefined) { + body.append(objectKey, rank[objectKey]); + } + }); + + body.append('image', imageFile, imageFile.name); + } else { + body = rank; + } + + const options = new RequestOptions({ + body: body, + method: requestMethod + }); + + return this.http.request(requestUrl, options) + .map(res => res.json()) + .do(savedRank => { + const action = {type: accessType, data: savedRank}; + // leave some time to save image file before accessing it through listview + setTimeout(() => { + this.rankStore.dispatch(action); + }, 300); + }); + } + /** * send PATCH request to update db entry * diff --git a/static/src/app/squads/new-squad/new-squad.component.css b/static/src/app/squads/new-squad/new-squad.component.css index e69de29..c77d09c 100644 --- a/static/src/app/squads/new-squad/new-squad.component.css +++ b/static/src/app/squads/new-squad/new-squad.component.css @@ -0,0 +1,3 @@ +.form-control { + height: auto; +}