Merge branch 'task/add-delete-campaign-funct' of hardi/opt-cc into master

pull/10/head
hardi 2017-09-14 12:05:29 +02:00 committed by HardiReady
commit 17b31df9a6
18 changed files with 194 additions and 45 deletions

View File

@ -13,6 +13,8 @@ const checkMT = require('../middleware/permission-check').checkMT;
// Mongoose Model using mongoDB // Mongoose Model using mongoDB
const CampaignModel = require('../models/campaign'); const CampaignModel = require('../models/campaign');
const WarModel = require('../models/war');
const campaigns = express.Router(); const campaigns = express.Router();
@ -54,6 +56,25 @@ campaigns.route('/:id')
return next(); return next();
}); });
}) })
.delete((req, res, next) => {
CampaignModel.findByIdAndRemove(req.params.id, (err, item) => {
if (err) {
err.status = codes.wrongrequest;
return next(err);
}
else if (!item) {
err = new Error("item not found");
err.status = codes.notfound;
return next(err);
}
WarModel.find({campaign: req.params.id}).remove().exec();
res.locals.processed = true;
next();
})
})
.all( .all(
routerHandling.httpMethodNotAllowed routerHandling.httpMethodNotAllowed
); );

View File

@ -1,6 +1,6 @@
{ {
"name": "opt-cc", "name": "opt-cc",
"version": "1.4.3", "version": "1.4.4",
"license": "MIT", "license": "MIT",
"private": true, "private": true,
"scripts": { "scripts": {

View File

@ -14,6 +14,7 @@ export class AppConfig {
public readonly apiRequestAwardPath = this.apiUrl + '/request/award'; public readonly apiRequestAwardPath = this.apiUrl + '/request/award';
public readonly apiPromotionPath = this.apiUrl + '/request/promotion'; public readonly apiPromotionPath = this.apiUrl + '/request/promotion';
public readonly apiWarPath = this.apiUrl + '/wars'; public readonly apiWarPath = this.apiUrl + '/wars';
public readonly apiCampaignPath = this.apiUrl + '/campaigns';
} }

View File

@ -0,0 +1,31 @@
import {Injectable} from "@angular/core";
import {Campaign} from "../../models/model-interfaces";
import {AppConfig} from "../../app.config";
import {HttpClient} from "../http-client";
@Injectable()
export class CampaignService {
campaigns: Campaign[];
constructor(private http: HttpClient,
private config: AppConfig) {
}
getAllCampaigns() {
return this.http.get(this.config.apiWarPath)
.map(res => res.json())
}
submitCampaign(campaign: Campaign) {
return this.http.post(this.config.apiCampaignPath, campaign)
.map(res => res.json())
}
deleteCampaign(id: string) {
return this.http.delete(this.config.apiCampaignPath + '/' + id)
.map(res => res.json())
}
}

View File

@ -1,22 +1,15 @@
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {Campaign, War} from "../../models/model-interfaces"; import {War} from "../../models/model-interfaces";
import {AppConfig} from "../../app.config"; import {AppConfig} from "../../app.config";
import {HttpClient} from "../http-client"; import {HttpClient} from "../http-client";
@Injectable() @Injectable()
export class WarService { export class WarService {
campaigns: Campaign[];
constructor(private http: HttpClient, constructor(private http: HttpClient,
private config: AppConfig) { private config: AppConfig) {
} }
getAllCampaigns() {
return this.http.get(this.config.apiWarPath)
.map(res => res.json())
}
getWar(warId: string) { getWar(warId: string) {
return this.http.get(this.config.apiWarPath + '/' + warId) return this.http.get(this.config.apiWarPath + '/' + warId)
.map(res => res.json()) .map(res => res.json())

View File

@ -0,0 +1,8 @@
.overview {
position: fixed;
width: 25%;
min-width: 300px;
padding-left: 50px;
padding-top: 70px;
margin-left: 10px;
}

View File

@ -0,0 +1,33 @@
<form #form="ngForm" class="overview">
<h3>Kampagne hinzufügen</h3>
<div class="form-group">
<label for="title">Titel</label>
<input type="text" class="form-control"
[(ngModel)]="campaign.title"
name="title"
id="title"
required maxlength="50"/>
<show-error text="Name" path="title"></show-error>
</div>
<button id="cancel"
(click)="cancel()"
class="btn btn-default">
Abbrechen
</button>
<button id="save"
(click)="saveCampaign()"
class="btn btn-default"
[disabled]="!form.valid">
Bestätigen
</button>
<span *ngIf="showErrorLabel"
class="center-block label label-danger" style="font-size: medium; padding: 2px; margin-top: 2px">
{{error}}
</span>
</form>

View File

@ -0,0 +1,44 @@
import {Component, ViewChild} from "@angular/core";
import {ActivatedRoute, Router} from "@angular/router";
import {NgForm} from "@angular/forms";
import {Campaign} from "../../models/model-interfaces";
import {CampaignService} from "../../services/campaign-service/campaign.service";
@Component({
selector: 'campaign-submit',
templateUrl: './campaign-submit.component.html',
styleUrls: ['./campaign-submit.component.css']
})
export class CampaignSubmitComponent {
campaign: Campaign = {};
showErrorLabel = false;
error;
@ViewChild(NgForm) form: NgForm;
constructor(private route: ActivatedRoute,
private router: Router,
private campaignService: CampaignService) {
}
saveCampaign() {
this.campaignService.submitCampaign(this.campaign)
.subscribe(campaign => {
this.router.navigate(['../overview/' + campaign._id], {relativeTo: this.route});
},
error => {
this.error = error._body.error.message;
this.showErrorLabel = true;
});
}
cancel() {
this.router.navigate(['..'], {relativeTo: this.route});
return false;
}
}

View File

@ -1,7 +1,7 @@
import {Component} from "@angular/core"; import {Component} from "@angular/core";
import {WarService} from "../../services/war-service/war.service";
import {ActivatedRoute} from "@angular/router"; import {ActivatedRoute} from "@angular/router";
import {CarouselConfig} from "ngx-bootstrap"; import {CarouselConfig} from "ngx-bootstrap";
import {CampaignService} from "../../services/campaign-service/campaign.service";
@Component({ @Component({
@ -26,7 +26,7 @@ export class StatisticOverviewComponent {
}; };
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private warService: WarService) { private campaignService: CampaignService) {
} }
ngOnInit() { ngOnInit() {
@ -34,10 +34,10 @@ export class StatisticOverviewComponent {
.map(params => params['id']) .map(params => params['id'])
.subscribe((id) => { .subscribe((id) => {
this.id = id; this.id = id;
if (this.warService.campaigns) { if (this.campaignService.campaigns) {
this.initWars(this.warService.campaigns); this.initWars(this.campaignService.campaigns);
} else { } else {
this.warService.getAllCampaigns().subscribe(campaigns => { this.campaignService.getAllCampaigns().subscribe(campaigns => {
this.initWars(campaigns); this.initWars(campaigns);
}) })
} }

View File

@ -5,13 +5,14 @@ import {statsRouterModule, statsRoutingComponents} from "./stats.routing";
import {WarService} from "../services/war-service/war.service"; import {WarService} from "../services/war-service/war.service";
import {LineChartModule, PieChartModule} from "@swimlane/ngx-charts"; import {LineChartModule, PieChartModule} from "@swimlane/ngx-charts";
import {AccordionModule, CarouselModule} from "ngx-bootstrap"; import {AccordionModule, CarouselModule} from "ngx-bootstrap";
import {CampaignService} from "../services/campaign-service/campaign.service";
import {NgxDatatableModule} from "@swimlane/ngx-datatable"; import {NgxDatatableModule} from "@swimlane/ngx-datatable";
@NgModule({ @NgModule({
declarations: statsRoutingComponents, declarations: statsRoutingComponents,
imports: [CommonModule, SharedModule, statsRouterModule, LineChartModule, PieChartModule, imports: [CommonModule, SharedModule, statsRouterModule, LineChartModule, PieChartModule,
AccordionModule.forRoot(), CarouselModule.forRoot(), NgxDatatableModule], AccordionModule.forRoot(), CarouselModule.forRoot(), NgxDatatableModule],
providers: [WarService] providers: [WarService, CampaignService]
}) })
export class StatsModule { export class StatsModule {
static routes = statsRouterModule; static routes = statsRouterModule;

View File

@ -6,6 +6,7 @@ import {WarListComponent} from "./war-list/war-list.component";
import {StatisticOverviewComponent} from "./overview/stats-overview.component"; import {StatisticOverviewComponent} from "./overview/stats-overview.component";
import {WarItemComponent} from "./war-list/war-item.component"; import {WarItemComponent} from "./war-list/war-item.component";
import {ModuleWithProviders} from "@angular/core"; import {ModuleWithProviders} from "@angular/core";
import {CampaignSubmitComponent} from "./campaign-submit/campaign-submit.component";
export const statsRoutes: Routes = [{ export const statsRoutes: Routes = [{
@ -22,6 +23,11 @@ export const statsRoutes: Routes = [{
component: StatisticOverviewComponent, component: StatisticOverviewComponent,
outlet: 'right' outlet: 'right'
}, },
{
path: 'new-campaign',
component: CampaignSubmitComponent,
outlet: 'right'
},
{ {
path: 'new', path: 'new',
component: WarSubmitComponent, component: WarSubmitComponent,
@ -35,6 +41,6 @@ export const statsRoutes: Routes = [{
export const statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes); export const statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes);
export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, WarListComponent, export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, CampaignSubmitComponent,
WarSubmitComponent, WarDetailComponent, WarItemComponent]; WarListComponent, WarSubmitComponent, WarDetailComponent, WarItemComponent];

View File

@ -2,6 +2,7 @@
position: fixed; position: fixed;
overflow-y: scroll; overflow-y: scroll;
overflow-x: hidden; overflow-x: hidden;
border-left: thin solid lightgrey;
bottom: 20px; bottom: 20px;
width: 100%; width: 100%;
padding-left: 50px; padding-left: 50px;

View File

@ -3,7 +3,8 @@
} }
:host /deep/ .card-header { :host /deep/ .card-header {
background-color: slategray; background-color: rgba(34, 34, 34, 0.80);
cursor: pointer;
padding: 15px; padding: 15px;
color: white; color: white;
font-weight: 600; font-weight: 600;

View File

@ -1,15 +1,23 @@
<div class="war-list"> <div class="war-list">
<div class="input-group search-bar" style="margin-bottom:12px" *ngIf="loginService.hasPermission(3)"> <div class="input-group search-bar" style="margin-bottom:12px; width:100%;" *ngIf="loginService.hasPermission(3)">
<a class="pull-left btn btn-success" (click)="selectNewWar()"> <a class="pull-left btn btn-success" (click)="selectNewWar()">
Schlacht hinzufügen Schlacht hinzufügen
</a> </a>
<a class="pull-right btn btn-success" (click)="selectNewCampaign()">
Kampagne hinzufügen
</a>
</div> </div>
<accordion *ngFor="let campaign of campaigns; let isFirstRow=first"> <accordion *ngFor="let campaign of campaigns; let isFirstRow=first">
<accordion-group [isOpen]="isFirstRow"> <accordion-group [isOpen]="isFirstRow">
<div accordion-heading (click)="selectOverview(campaign._id)"> <div accordion-heading>
{{campaign.title}} {{campaign.title}}
<span class="pull-right"></span> <span class="pull-right"></span>
<span (click)="deleteCampaign(campaign); $event.stopPropagation()" title="Löschen"
style="color: whitesmoke; padding-top: 0; padding-right: 20px;"
class="glyphicon glyphicon-trash trash pull-right"
*ngIf="loginService.hasPermission(3)">
</span>
</div> </div>
<div class="fade-in list-entry" style="margin-top: -16px; margin-bottom: 10px;" <div class="fade-in list-entry" style="margin-top: -16px; margin-bottom: 10px;"

View File

@ -3,6 +3,7 @@ import {ActivatedRoute, Router} from "@angular/router";
import {Campaign, War} from "../../models/model-interfaces"; import {Campaign, War} from "../../models/model-interfaces";
import {WarService} from "../../services/war-service/war.service"; import {WarService} from "../../services/war-service/war.service";
import {LoginService} from "../../services/login-service/login-service"; import {LoginService} from "../../services/login-service/login-service";
import {CampaignService} from "../../services/campaign-service/campaign.service";
@Component({ @Component({
selector: 'war-list', selector: 'war-list',
@ -16,19 +17,25 @@ export class WarListComponent implements OnInit {
campaigns: Campaign[] = []; campaigns: Campaign[] = [];
constructor(private warService: WarService, constructor(private warService: WarService,
private campaignService: CampaignService,
private loginService: LoginService, private loginService: LoginService,
private router: Router, private router: Router,
private route: ActivatedRoute) { private route: ActivatedRoute) {
} }
ngOnInit() { ngOnInit() {
this.warService.getAllCampaigns().subscribe((items) => { this.campaignService.getAllCampaigns().subscribe((items) => {
this.warService.campaigns = items; this.campaignService.campaigns = items;
this.campaigns = items; this.campaigns = items;
this.selectOverview(this.campaigns[0]._id); this.selectOverview(this.campaigns[0]._id);
}); });
} }
selectNewCampaign() {
this.selectedWarId = null;
this.router.navigate([{outlets: {'right': ['new-campaign']}}], {relativeTo: this.route});
}
selectNewWar() { selectNewWar() {
this.selectedWarId = null; this.selectedWarId = null;
this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route}); this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route});
@ -60,4 +67,17 @@ export class WarListComponent implements OnInit {
} }
} }
deleteCampaign(campaign) {
if (confirm('Soll die Kampagne ' + campaign.title + ' wirklich gelöscht werden?')) {
this.campaignService.deleteCampaign(campaign._id)
.subscribe((res) => {
console.log(res)
if (this.selectedWarId === campaign._id) {
this.selectOverview('all');
}
this.campaigns.splice(this.campaigns.indexOf(campaign), 1);
})
}
}
} }

View File

@ -6,24 +6,3 @@
padding-top: 70px; padding-top: 70px;
margin-left: 10px; margin-left: 10px;
} }
.load-arrow {
background: url(../../../assets/loading.png) no-repeat;
display: block;
width: 120px;
height: 120px;
}
/* Loading Animation */
.glyphicon-refresh-animate {
animation: spin 1.5s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -49,7 +49,7 @@
id="campaign" id="campaign"
[(ngModel)]="war.campaign" [(ngModel)]="war.campaign"
required> required>
<option *ngFor="let campaign of warService.campaigns" [ngValue]="campaign._id"> <option *ngFor="let campaign of campaignService.campaigns" [ngValue]="campaign._id">
{{campaign.title}} {{campaign.title}}
</option> </option>
</select> </select>

View File

@ -3,6 +3,7 @@ import {ActivatedRoute, Router} from "@angular/router";
import {NgForm} from "@angular/forms"; import {NgForm} from "@angular/forms";
import {WarService} from "../../services/war-service/war.service"; import {WarService} from "../../services/war-service/war.service";
import {War} from "../../models/model-interfaces"; import {War} from "../../models/model-interfaces";
import {CampaignService} from "../../services/campaign-service/campaign.service";
@Component({ @Component({
@ -28,7 +29,8 @@ export class WarSubmitComponent {
constructor(private route: ActivatedRoute, constructor(private route: ActivatedRoute,
private router: Router, private router: Router,
private warService: WarService) { private warService: WarService,
private campaignService: CampaignService) {
} }
fileChange(event) { fileChange(event) {