Add editing/creating of ranks
parent
4c6f3dab78
commit
ec756028aa
|
@ -0,0 +1,3 @@
|
|||
.form-control {
|
||||
height: auto;
|
||||
}
|
|
@ -12,7 +12,7 @@
|
|||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<img src="resource/rank/{{rank._id}}.png" class="rank-list-preview">
|
||||
<img src="{{imageSrc}}" class="rank-list-preview">
|
||||
<span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash"></span>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
.preview-image {
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
.form-control {
|
||||
height: auto;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
<form #form="ngForm" class="overview">
|
||||
<h3 *ngIf="rank._id">Rang editieren</h3>
|
||||
<h3 *ngIf="!rank._id">Neuen Rang hinzufügen</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title">Name</label>
|
||||
<input type="text" class="form-control"
|
||||
[(ngModel)]="rank.name"
|
||||
name="title"
|
||||
id="title"
|
||||
required maxlength="50"/>
|
||||
|
||||
<show-error text="Name" path="title"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="fraction">Fraktion</label>
|
||||
<select id="fraction" name="fraction" class="form-control btn dropdown-toggle"
|
||||
required
|
||||
[(ngModel)]="rank.fraction">
|
||||
<option value="OPFOR">CSAT</option>
|
||||
<option value="BLUFOR">NATO</option>
|
||||
</select>
|
||||
<show-error text="Fraktion" path="fraction"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="level">Stufe</label>
|
||||
<input id="level" name="level" type="number" class="form-control btn dropdown-toggle"
|
||||
[(ngModel)]="rank.level">
|
||||
<show-error text="Stufe" path="level"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="logo">Bild</label>
|
||||
<input id="logo" name="logo" class="ui-button form-control" type="file"
|
||||
accept="image/png"
|
||||
#fileInput
|
||||
(change)="fileChange($event)">
|
||||
<span class="label label-bg label-danger center-block" style="font-size:small" *ngIf="showImageError">
|
||||
Bild muss im PNG Format vorliegen
|
||||
</span>
|
||||
|
||||
<img class="preview-image" src="{{imagePreviewSrc}}">
|
||||
</div>
|
||||
|
||||
<button id="cancel"
|
||||
(click)="cancel()"
|
||||
class="btn btn-default">
|
||||
Abbrechen
|
||||
</button>
|
||||
|
||||
<button id="save"
|
||||
(click)="saveRank(fileInput)"
|
||||
class="btn btn-default"
|
||||
[disabled]="!form.valid">
|
||||
Squad speichern
|
||||
</button>
|
||||
|
||||
<span *ngIf="showSuccessLabel"
|
||||
class="label label-success label-small"
|
||||
style="margin-left: inherit">
|
||||
Erfolgreich gespeichert
|
||||
</span>
|
||||
|
||||
</form>
|
|
@ -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?`);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
<div class="overview">
|
||||
<h3 style="margin-bottom: 25px">Rang-Details
|
||||
<span *ngIf="showSuccessLabel"
|
||||
class="label label-success label-small"
|
||||
style="margin-left: inherit">
|
||||
Erfolgreich gespeichert
|
||||
</span>
|
||||
</h3>
|
||||
<div *ngIf="rank">
|
||||
<div class="col-xs-12">
|
||||
|
||||
|
||||
<div class="div-table">
|
||||
<div class="div-table-row">
|
||||
<div class="div-table-col content-s">
|
||||
<label>Name:</label>
|
||||
</div>
|
||||
<div class="div-table-col content content-m">
|
||||
{{rank.name}}
|
||||
</div>
|
||||
<div class="div-table-col content-l">
|
||||
<input class="form-control" width="250px" placeholder="Neuer Name" #newNameInput>
|
||||
</div>
|
||||
<div class="div-table-col content-s">
|
||||
<a class="pull-right btn btn-sm btn-block btn-default" (click)="update('name', newNameInput)">Bestätigen</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-table-row">
|
||||
<div class="div-table-col content-s">
|
||||
<label>Fraktion:</label>
|
||||
</div>
|
||||
<div class="div-table-col fraction-opfor content-m" *ngIf="rank.fraction == 'OPFOR'">
|
||||
CSAT
|
||||
</div>
|
||||
<div class="div-table-col fraction-blufor content-m" *ngIf="rank.fraction == 'BLUFOR'">
|
||||
NATO
|
||||
</div>
|
||||
<div class="div-table-col">
|
||||
</div>
|
||||
</div>
|
||||
<div class="div-table-row">
|
||||
<div class="div-table-col content-s">
|
||||
<label>Stufe:</label>
|
||||
</div>
|
||||
<div class="div-table-col content content-m">
|
||||
{{rank.level}}
|
||||
</div>
|
||||
<div class="div-table-col">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
<div class="div-table">
|
||||
<div class="div-table-row">
|
||||
<div class="div-table-col content-s">
|
||||
<label>Bild:</label>
|
||||
</div>
|
||||
<div class="div-table-col content-m-flex">
|
||||
<img src="{{imagePreview}}">
|
||||
</div>
|
||||
<div class="div-table-col content-l">
|
||||
<label class="control-label">Neues Logo</label>
|
||||
<input class="form-control" type="file" accept="image/png" #newGraphicInput (change)="fileChange($event)">
|
||||
<span class="label label-bg label-danger center-block" style="font-size:small" *ngIf="showImageError">
|
||||
Bild muss im PNG Format vorliegen
|
||||
</span>
|
||||
</div>
|
||||
<div class="div-table-col content-s">
|
||||
<label> </label>
|
||||
<a class="pull-right btn btn-sm btn-block btn-default" (click)="updateGraphic(newGraphicInput)">Bestätigen</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -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)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -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];
|
||||
|
||||
|
|
|
@ -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
|
||||
*
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
.form-control {
|
||||
height: auto;
|
||||
}
|
Loading…
Reference in New Issue