Compare commits
3 Commits
8319b79e1f
...
a7412af2ef
Author | SHA1 | Date |
---|---|---|
Florian Hartwich | a7412af2ef | |
Florian Hartwich | b86f5394d6 | |
Florian Hartwich | 7890ef76fb |
|
@ -8,6 +8,8 @@ const logger = require('debug')('cc:campaigns');
|
|||
const codes = require('./http-codes');
|
||||
|
||||
const routerHandling = require('../middleware/router-handling');
|
||||
const apiAuthenticationMiddleware = require('../middleware/auth-middleware');
|
||||
const checkMT = require('../middleware/permission-check').checkMT;
|
||||
|
||||
// Mongoose Model using mongoDB
|
||||
const CampaignModel = require('../models/campaign');
|
||||
|
@ -17,7 +19,7 @@ const campaigns = express.Router();
|
|||
// routes **********************
|
||||
campaigns.route('/')
|
||||
|
||||
.post((req, res, next) => {
|
||||
.post(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||
const campaign = new CampaignModel(req.body);
|
||||
// timestamp and default are set automatically by Mongoose Schema Validation
|
||||
campaign.save((err) => {
|
||||
|
@ -36,6 +38,26 @@ campaigns.route('/')
|
|||
routerHandling.httpMethodNotAllowed
|
||||
);
|
||||
|
||||
campaigns.route('/:id')
|
||||
.get((req, res, next) => {
|
||||
CampaignModel.findById(req.params.id, (err, item) => {
|
||||
if (err) {
|
||||
err.status = codes.servererror;
|
||||
return next(err);
|
||||
}
|
||||
else if (!item) {
|
||||
err = new Error("item not found");
|
||||
err.status = codes.notfound;
|
||||
return next(err);
|
||||
}
|
||||
res.locals.items = item;
|
||||
return next();
|
||||
});
|
||||
})
|
||||
.all(
|
||||
routerHandling.httpMethodNotAllowed
|
||||
);
|
||||
|
||||
// this middleware function can be used, if you like or remove it
|
||||
// it looks for object(s) in res.locals.items and if they exist, they are send to the client as json
|
||||
campaigns.use(routerHandling.emptyResponse);
|
||||
|
|
|
@ -41,7 +41,7 @@ wars.route('/')
|
|||
}
|
||||
if (wars) {
|
||||
campaigns.forEach(campaign => {
|
||||
let entry = {title: campaign.title, wars: []};
|
||||
let entry = {_id: campaign._id, title: campaign.title, wars: []};
|
||||
wars.forEach((war) => {
|
||||
if (String(campaign._id) === String(war.campaign)) {
|
||||
entry.wars.push(war);
|
||||
|
|
|
@ -15,7 +15,6 @@ const urls = require('./config/api-url');
|
|||
const restAPIchecks = require('./middleware/request-checks.js');
|
||||
const errorResponseWare = require('./middleware/error-response');
|
||||
const apiAuthenticationMiddleware = require('./middleware/auth-middleware');
|
||||
const checkMT = require('./middleware/permission-check').checkMT;
|
||||
const checkAdmin = require('./middleware/permission-check').checkAdmin;
|
||||
const signatureCronJob = require('./cron-job/cron').cronJobSignature;
|
||||
const backupCronJob = require('./cron-job/cron').cronJobBackup;
|
||||
|
@ -81,7 +80,7 @@ app.use(urls.decorations, decorationRouter);
|
|||
app.use(urls.request, requestRouter);
|
||||
app.use(urls.awards, awardingRouter);
|
||||
app.use(urls.wars, warRouter);
|
||||
app.use(urls.campaigns, apiAuthenticationMiddleware, checkMT, campaignRouter);
|
||||
app.use(urls.campaigns,campaignRouter);
|
||||
app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
|
||||
app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter);
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<div class="col-xs-8">
|
||||
<span>
|
||||
<a>{{decoration.name}}</a>
|
||||
</span>
|
||||
|
@ -12,7 +12,7 @@
|
|||
<small> - Sortierung: {{decoration.sortingNumber}}</small>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<div class="col-xs-4">
|
||||
<img src="{{imageSrc}}"
|
||||
[style.max-height]="imgStyle.height"
|
||||
[style.max-width]="imgStyle.width"
|
||||
|
|
|
@ -11,7 +11,7 @@ export interface User {
|
|||
_id?: string;
|
||||
boardUserId?: number;
|
||||
username?: string;
|
||||
squad?: any; //Squad or string
|
||||
squad?: any; //Squad or id-string
|
||||
rank?: Rank;
|
||||
awards?: Award[];
|
||||
}
|
||||
|
@ -28,6 +28,11 @@ export interface Player {
|
|||
respawn?: number;
|
||||
flagTouch?: number;
|
||||
}
|
||||
export interface Campaign {
|
||||
_id?: string;
|
||||
title?: string;
|
||||
wars?: War[];
|
||||
}
|
||||
export interface War {
|
||||
_id?: string;
|
||||
title?: string;
|
||||
|
@ -36,7 +41,8 @@ export interface War {
|
|||
ptOpfor?: number;
|
||||
playersBlufor?: number;
|
||||
playersOpfor?: number;
|
||||
players: Player[];
|
||||
players?: Player[];
|
||||
campaign?: string;
|
||||
}
|
||||
|
||||
export interface Squad {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<div class="col-xs-8">
|
||||
<span>
|
||||
<a>{{rank.name}}</a>
|
||||
</span>
|
||||
|
@ -11,7 +11,7 @@
|
|||
<small> - Stufe {{rank.level}}</small>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<div class="col-xs-4">
|
||||
<img src="{{imageSrc}}" class="rank-list-preview">
|
||||
<span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash"></span>
|
||||
</div>
|
||||
|
|
|
@ -1,16 +1,18 @@
|
|||
import {Injectable} from "@angular/core";
|
||||
import {War} from "../../models/model-interfaces";
|
||||
import {Campaign, War} from "../../models/model-interfaces";
|
||||
import {AppConfig} from "../../app.config";
|
||||
import {HttpClient} from "../http-client";
|
||||
|
||||
@Injectable()
|
||||
export class WarService {
|
||||
|
||||
campaigns :Campaign[];
|
||||
|
||||
constructor(private http: HttpClient,
|
||||
private config: AppConfig) {
|
||||
}
|
||||
|
||||
getAllWars() {
|
||||
getAllCampaigns() {
|
||||
return this.http.get(this.config.apiWarPath)
|
||||
.map(res => res.json())
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<div class="col-xs-8">
|
||||
<span>
|
||||
<a>{{squad.name}}</a>
|
||||
</span>
|
||||
|
@ -10,7 +10,7 @@
|
|||
<small *ngIf="squad.fraction == 'BLUFOR'">NATO</small>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-3">
|
||||
<div class="col-xs-4">
|
||||
<img src="{{imageSrc}}" height="50px" class="squad-list-preview">
|
||||
<span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash"></span>
|
||||
</div>
|
||||
|
|
|
@ -1,9 +1,3 @@
|
|||
h3 {
|
||||
width: 920px;
|
||||
margin-left: 5%;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
width: 1200px;
|
||||
margin-left: 5%;
|
||||
}
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
<h2>{{title}}</h2>
|
||||
|
||||
<h3>Punkte</h3>
|
||||
|
||||
<div class="chart-container">
|
||||
|
|
|
@ -1,14 +1,20 @@
|
|||
import {Component} from "@angular/core";
|
||||
import {WarService} from "../../services/war-service/war.service";
|
||||
import {Campaign, War} from "../../models/model-interfaces";
|
||||
import {WarListComponent} from "../war-list/war-list.component";
|
||||
import {ActivatedRoute} from "@angular/router";
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'stats-overview',
|
||||
templateUrl: './stats-overview.component.html',
|
||||
styleUrls: ['./stats-overview.component.css']
|
||||
styleUrls: ['./stats-overview.component.css'],
|
||||
inputs: ['campaigns']
|
||||
})
|
||||
export class StatisticOverviewComponent {
|
||||
|
||||
title = "";
|
||||
|
||||
pointData: any[] = [];
|
||||
playerData: any[] = [];
|
||||
|
||||
|
@ -16,12 +22,40 @@ export class StatisticOverviewComponent {
|
|||
domain: ['#0000FF', '#B22222']
|
||||
};
|
||||
|
||||
constructor(private warService: WarService) {
|
||||
constructor(private route: ActivatedRoute,
|
||||
private warService: WarService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.warService.getAllWars().subscribe(items => {
|
||||
this.initChart(items);
|
||||
this.route.params
|
||||
.map(params => params['id'])
|
||||
.subscribe((id) => {
|
||||
if (this.warService.campaigns) {
|
||||
this.initWars(this.warService.campaigns, id);
|
||||
} else {
|
||||
this.warService.getAllCampaigns().subscribe(campaigns => {
|
||||
this.initWars(campaigns, id);
|
||||
})
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
initWars(campaigns, id) {
|
||||
|
||||
let wars = [];
|
||||
let itemsProcessed = 0;
|
||||
campaigns = campaigns.filter(campaign => id === 'all' || campaign._id === id);
|
||||
campaigns.forEach(campaign => {
|
||||
if (id === 'all') {
|
||||
this.title = "Gesamtübersicht"
|
||||
} else {
|
||||
this.title = campaign.title
|
||||
}
|
||||
wars = wars.concat(campaign.wars);
|
||||
itemsProcessed++;
|
||||
if (itemsProcessed === campaigns.length) {
|
||||
this.initChart(wars);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
#left {
|
||||
width: 320px;
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#right {
|
||||
overflow: hidden
|
||||
}
|
|
@ -17,7 +17,7 @@ export const statsRoutes: Routes = [{
|
|||
]
|
||||
},
|
||||
{
|
||||
path: 'overview',
|
||||
path: 'overview/:id',
|
||||
component: StatisticOverviewComponent,
|
||||
outlet: 'right'
|
||||
},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<div class="overview" xmlns="http://www.w3.org/1999/html">
|
||||
|
||||
<div style="margin-left: 2%; min-height: 263px;">
|
||||
<div style="min-height: 263px;">
|
||||
<h2>{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}</h2>
|
||||
<h3 class="pull-left">
|
||||
<h4>Endpunktestand:</h4>
|
||||
|
@ -9,7 +9,7 @@
|
|||
<span class="text-opfor" style="font-weight: bold; margin-left: 10px;">{{war.ptOpfor}} CSAT</span>
|
||||
</h3>
|
||||
|
||||
<h3 class="pull-left" style="padding-left: 6%;">
|
||||
<h3 class="pull-left">
|
||||
<h4>Teilnehmer:</h4>
|
||||
<ngx-charts-pie-chart
|
||||
[view]="[150, 150]"
|
||||
|
@ -23,7 +23,7 @@
|
|||
</ngx-charts-pie-chart>
|
||||
</h3>
|
||||
|
||||
<div style="margin-left: 600px; margin-top:1%">
|
||||
<div style="margin-top:1%">
|
||||
<a class="btn btn-default" style="margin: 20px" target="_blank" href="resource/logs/{{war._id}}/clean.log">Logfile
|
||||
anzeigen</a>
|
||||
<form class="form-group">
|
||||
|
@ -50,7 +50,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="pull-left" style="margin-left: 2%">
|
||||
<div class="pull-left" >
|
||||
<div class="table-container scoreboard-table-container">
|
||||
<table class="table table-hover" [mfData]="players" #mf="mfDataTable" [(mfSortBy)]="sortBy"
|
||||
[(mfSortOrder)]="sortOrder">
|
||||
|
|
|
@ -6,3 +6,10 @@
|
|||
.rank-list {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
:host /deep/ .card-header {
|
||||
background-color: slategray;
|
||||
padding: 15px;
|
||||
color: white;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
|
|
@ -5,23 +5,36 @@
|
|||
</a>
|
||||
</div>
|
||||
|
||||
<div class="fade-in list-entry" style="margin-top: 30px; margin-bottom: 30px;"
|
||||
[ngClass]="{selected : selectedWarId == '0'}" (click)="selectOverview()">
|
||||
<div class="fade-in list-entry" style="margin-top: 20px; margin-bottom: 20px;"
|
||||
[ngClass]="{selected : selectedWarId == 'all'}" (click)="selectOverview('all')">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<span style="margin:auto">
|
||||
<a>Zusammenfassung</a>
|
||||
<a>Gesamtübersicht</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<accordion [closeOthers]="oneAtATime">
|
||||
<accordion-group #group>
|
||||
<div accordion-heading>
|
||||
Return to Hell in a Bowl
|
||||
<accordion *ngFor="let campaign of campaigns">
|
||||
<accordion-group>
|
||||
<div accordion-heading (click)="selectOverview(campaign._id)">
|
||||
{{campaign.title}}
|
||||
<span class="pull-right">▼</span>
|
||||
</div>
|
||||
<div *ngFor="let war of wars">
|
||||
|
||||
<div class="fade-in list-entry" style="margin-top: -16px; margin-bottom: 10px;"
|
||||
[ngClass]="{selected : selectedWarId == campaign._id}" (click)="selectOverview(campaign._id)">
|
||||
<div class="row">
|
||||
<div class="col-xs-9">
|
||||
<span style="margin:auto">
|
||||
<a>Kampagnenübersicht</a>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let war of campaign.wars">
|
||||
<pjm-war-item
|
||||
[war]="war"
|
||||
(warDelete)="deleteWar(war)"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {Component, OnInit} from "@angular/core";
|
||||
import {ActivatedRoute, Router} from "@angular/router";
|
||||
import {War} from "../../models/model-interfaces";
|
||||
import {Campaign, War} from "../../models/model-interfaces";
|
||||
import {WarService} from "../../services/war-service/war.service";
|
||||
import {LoginService} from "../../services/login-service/login-service";
|
||||
|
||||
|
@ -11,9 +11,9 @@ import {LoginService} from "../../services/login-service/login-service";
|
|||
})
|
||||
export class WarListComponent implements OnInit {
|
||||
|
||||
selectedWarId: string | number = '0';
|
||||
selectedWarId: string | number = 'all';
|
||||
|
||||
wars: War[] = [];
|
||||
campaigns: Campaign[] = [];
|
||||
|
||||
public oneAtATime: boolean = true;
|
||||
|
||||
|
@ -24,9 +24,10 @@ export class WarListComponent implements OnInit {
|
|||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.warService.getAllWars().subscribe((items) => {
|
||||
this.wars = items;
|
||||
this.router.navigate([{outlets: {'right': ['overview']}}], {relativeTo: this.route});
|
||||
this.warService.getAllCampaigns().subscribe((items) => {
|
||||
this.warService.campaigns = items;
|
||||
this.campaigns = items;
|
||||
this.router.navigate([{outlets: {'right': ['overview', 'all']}}], {relativeTo: this.route});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -35,14 +36,18 @@ export class WarListComponent implements OnInit {
|
|||
this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
selectWar(warId: string | number) {
|
||||
this.selectedWarId = warId;
|
||||
this.router.navigate([{outlets: {'right': ['war', warId]}}], {relativeTo: this.route});
|
||||
selectWar(warId) {
|
||||
if (this.selectedWarId != warId) {
|
||||
this.selectedWarId = warId;
|
||||
this.router.navigate([{outlets: {'right': ['war', warId]}}], {relativeTo: this.route});
|
||||
}
|
||||
}
|
||||
|
||||
selectOverview() {
|
||||
this.selectedWarId = '0';
|
||||
this.router.navigate([{outlets: {'right': ['overview']}}], {relativeTo: this.route});
|
||||
selectOverview(overviewId) {
|
||||
if (this.selectedWarId != overviewId) {
|
||||
this.selectedWarId = overviewId;
|
||||
this.router.navigate([{outlets: {'right': ['overview', overviewId]}}], {relativeTo: this.route});
|
||||
}
|
||||
}
|
||||
|
||||
deleteWar(war: War) {
|
||||
|
@ -50,14 +55,11 @@ export class WarListComponent implements OnInit {
|
|||
this.warService.deleteWar(war._id)
|
||||
.subscribe((res) => {
|
||||
if (this.selectedWarId === war._id) {
|
||||
this.selectOverview();
|
||||
this.selectOverview('all');
|
||||
}
|
||||
this.wars.splice(this.wars.indexOf(war), 1);
|
||||
this.campaigns.splice(this.campaigns.indexOf(war), 1);
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
open(event) {
|
||||
console.log(event);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,19 @@
|
|||
<show-error text="Punkte CSAT" path="ptopf"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="campaign">Kampagne</label>
|
||||
<select class="form-control"
|
||||
name="campaign"
|
||||
id="campaign"
|
||||
[(ngModel)]="war.campaign"
|
||||
required>
|
||||
<option *ngFor="let campaign of warService.campaigns" [ngValue]="campaign._id">
|
||||
{{campaign.title}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="log">Logfile</label>
|
||||
<input id="log" name="log" class="ui-button form-control" type="file"
|
||||
|
|
|
@ -13,6 +13,7 @@ label {
|
|||
.overview {
|
||||
position: fixed;
|
||||
width: 25%;
|
||||
min-width: 500px;
|
||||
border-left: thin solid lightgrey;
|
||||
padding-left: 50px;
|
||||
padding-top: 20px;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<div class="fade-in user-list-entry" [ngClass]="{selected : selected}" (click)="select()">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-sm-9">
|
||||
<div class="col-sm-8">
|
||||
<span>
|
||||
<a>{{user.username}}</a>
|
||||
</span>
|
||||
|
@ -11,7 +11,7 @@
|
|||
<small *ngIf="!user.squad">ohne Squad/Fraktion</small>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-3">
|
||||
<div class="col-sm-4">
|
||||
<span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash pull-right"></span>
|
||||
<span (click)="award(); $event.stopPropagation()" title="Auszeichnungen" class="icon-award pull-right"></span>
|
||||
</div>
|
||||
|
|
|
@ -41,17 +41,13 @@ form {
|
|||
|
||||
#left {
|
||||
width: 20%;
|
||||
min-width: 280px;
|
||||
min-width: 350px;
|
||||
max-width: 450px;
|
||||
float: left;
|
||||
padding-right: 10px;
|
||||
|
||||
}
|
||||
#right {
|
||||
overflow: hidden
|
||||
}
|
||||
|
||||
.chat-button {
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 10px;
|
||||
overflow: hidden;
|
||||
padding-left: 4%;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue