Merge branch 'release/1-3-2' of hardi/opt-cc into master

pull/7/head
hardi 2017-08-13 09:27:06 +02:00 committed by HardiReady
commit ae20c7ce7d
30 changed files with 287 additions and 92 deletions

View File

@ -1,18 +1,19 @@
const rootRoute = '/api'; const rootRoute = '/api';
module.exports = { module.exports = {
account: rootRoute + '/account',
auth: rootRoute + '/authenticate', auth: rootRoute + '/authenticate',
signUp: rootRoute + '/authenticate/signup',
awards: rootRoute + '/awardings', awards: rootRoute + '/awardings',
command: rootRoute + '/cmd', campaigns: rootRoute + '/campaigns',
cmdCreateSig: rootRoute + '/cmd/createSignature', cmdCreateSig: rootRoute + '/cmd/createSignature',
command: rootRoute + '/cmd',
decorations: rootRoute + '/decorations', decorations: rootRoute + '/decorations',
overview: rootRoute + '/overview', overview: rootRoute + '/overview',
ranks: rootRoute + '/ranks', ranks: rootRoute + '/ranks',
request: rootRoute + '/request',
signatures: '/signatures', signatures: '/signatures',
signUp: rootRoute + '/authenticate/signup',
squads: rootRoute + '/squads', squads: rootRoute + '/squads',
users: rootRoute + '/users', users: rootRoute + '/users',
account: rootRoute + '/account',
request: rootRoute + '/request',
wars: rootRoute + '/wars' wars: rootRoute + '/wars'
}; };

18
api/models/campaign.js Normal file
View File

@ -0,0 +1,18 @@
"use strict";
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const CampaignSchema = new Schema({
title: {
type: String,
required: true
}
}, {
collection: 'campaign',
timestamps: {createdAt: 'timestamp'}
});
// optional more indices
CampaignSchema.index({timestamp: 1});
module.exports = mongoose.model('Campaign', CampaignSchema);

View File

@ -35,6 +35,10 @@ const WarSchema = new Schema({
get: v => Math.round(v), get: v => Math.round(v),
set: v => Math.round(v), set: v => Math.round(v),
default: 0 default: 0
},
campaign: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Campaign'
} }
}, { }, {
collection: 'war', collection: 'war',

65
api/routes/campaigns.js Normal file
View File

@ -0,0 +1,65 @@
"use strict";
// modules
const express = require('express');
const logger = require('debug')('cc:campaigns');
// HTTP status codes by name
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');
const campaigns = express.Router();
// routes **********************
campaigns.route('/')
.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) => {
if (err) {
err.status = codes.wrongrequest;
err.message += ' in fields: ' + Object.getOwnPropertyNames(err.errors);
return next(err);
}
res.status(codes.created);
res.locals.items = campaign;
next();
});
})
.all(
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);
module.exports = campaigns;

View File

@ -18,6 +18,7 @@ const checkMT = require('../middleware/permission-check').checkMT;
const routerHandling = require('../middleware/router-handling'); const routerHandling = require('../middleware/router-handling');
// Mongoose Model using mongoDB // Mongoose Model using mongoDB
const CampaignModel = require('../models/campaign');
const WarModel = require('../models/war'); const WarModel = require('../models/war');
const PlayerModel = require('../models/player'); const PlayerModel = require('../models/player');
@ -26,20 +27,37 @@ const wars = express.Router();
// routes ********************** // routes **********************
wars.route('/') wars.route('/')
.get((req, res, next) => { .get((req, res, next) => {
const filter = {}; let result = [];
WarModel.find(filter, {}, {sort: {date: 'desc'}}, (err, items) => { CampaignModel.find({}, {}, {sort: {timestamp: 'desc'}}, (err, campaigns) => {
if (err) { if (err) {
err.status = codes.servererror; err.status = codes.servererror;
return next(err); return next(err);
} }
if (items) { if (campaigns) {
res.locals.items = items; WarModel.find({}, {}, {sort: {date: 'desc'}}, (err, wars) => {
} else { if (err) {
res.locals.items = []; err.status = codes.servererror;
return next(err);
}
if (wars) {
campaigns.forEach(campaign => {
let entry = {_id: campaign._id, title: campaign.title, wars: []};
wars.forEach((war) => {
if (String(campaign._id) === String(war.campaign)) {
entry.wars.push(war);
}
});
result.push(entry);
});
res.locals.items = result;
} }
res.locals.processed = true; res.locals.processed = true;
next(); next();
}); }
)
;
}
})
}) })
.post(apiAuthenticationMiddleware, checkMT, upload.single('log'), (req, res, next) => { .post(apiAuthenticationMiddleware, checkMT, upload.single('log'), (req, res, next) => {
@ -64,7 +82,6 @@ wars.route('/')
if (err) { if (err) {
return next(err); return next(err);
} }
//TODO: combine run and clean in one script, so log file gets touched only once
exec(__dirname + '/../war-parser/run.sh ' + folderName + ' ' + war._id, (error, stdout) => { exec(__dirname + '/../war-parser/run.sh ' + folderName + ' ' + war._id, (error, stdout) => {
if (error) { if (error) {
return next(error); return next(error);
@ -75,7 +92,9 @@ wars.route('/')
} }
let obj = JSON.parse(`${stdout}`); let obj = JSON.parse(`${stdout}`);
for (let i = 0; i < obj.length; i++) { for (let i = 0; i < obj.length; i++) {
if (obj[i].fraction === 'BLUFOR') { if (!obj[i].fraction) {
obj.splice(i, 1);
} else if (obj[i].fraction === 'BLUFOR') {
war.playersBlufor++; war.playersBlufor++;
} else { } else {
war.playersOpfor++; war.playersOpfor++;

View File

@ -32,6 +32,7 @@ const awardingRouter = require('./routes/awardings');
const requestRouter = require('./routes/request'); const requestRouter = require('./routes/request');
const signatureRouter = require('./routes/signatures'); const signatureRouter = require('./routes/signatures');
const commandRouter = require('./routes/command'); const commandRouter = require('./routes/command');
const campaignRouter = require('./routes/campaigns');
const warRouter = require('./routes/wars'); const warRouter = require('./routes/wars');
// Configuration *********************************** // Configuration ***********************************
@ -79,6 +80,7 @@ app.use(urls.decorations, decorationRouter);
app.use(urls.request, requestRouter); app.use(urls.request, requestRouter);
app.use(urls.awards, awardingRouter); app.use(urls.awards, awardingRouter);
app.use(urls.wars, warRouter); app.use(urls.wars, warRouter);
app.use(urls.campaigns,campaignRouter);
app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter); app.use(urls.command, apiAuthenticationMiddleware, checkAdmin, commandRouter);
app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter); app.use(urls.account, apiAuthenticationMiddleware, checkAdmin, accountRouter);

View File

@ -15,11 +15,11 @@
"start-e2e": "npm run deploy-static && npm run e2e --prefix ./api", "start-e2e": "npm run deploy-static && npm run e2e --prefix ./api",
"test-e2e": "npm run e2e --prefix ./static" "test-e2e": "npm run e2e --prefix ./static"
}, },
"dependencies": {
"uglify-js": "^3.0.26"
},
"devDependencies": { "devDependencies": {
"concurrently": "^3.4.0", "concurrently": "^3.4.0",
"wait-on": "^2.0.2" "wait-on": "^2.0.2"
},
"dependencies": {
"uglify-js": "^3.0.26"
} }
} }

View File

@ -523,12 +523,6 @@
"integrity": "sha1-dMt3+2BS7a/yqJhN2v2I1BnyXKw=", "integrity": "sha1-dMt3+2BS7a/yqJhN2v2I1BnyXKw=",
"dev": true "dev": true
}, },
"@types/socket.io-client": {
"version": "1.4.29",
"resolved": "https://registry.npmjs.org/@types/socket.io-client/-/socket.io-client-1.4.29.tgz",
"integrity": "sha1-+HQwcM7pMXXjbgtqd6ivc+WMyzI=",
"dev": true
},
"abbrev": { "abbrev": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.0.tgz",
@ -4865,6 +4859,11 @@
"minimist": "0.0.8" "minimist": "0.0.8"
} }
}, },
"moment": {
"version": "2.18.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz",
"integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8="
},
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
@ -4894,6 +4893,14 @@
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz",
"integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk="
}, },
"ngx-bootstrap": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/ngx-bootstrap/-/ngx-bootstrap-1.8.1.tgz",
"integrity": "sha512-f6l1HmyQPY72bvprKd0yt1WkrEFzynbps8+OvEp4KE0beg/UYPoBXAmPyv7sOtn7grOTBUJJcMO147LEqKjW0Q==",
"requires": {
"moment": "2.18.1"
}
},
"ngx-clipboard": { "ngx-clipboard": {
"version": "8.0.2", "version": "8.0.2",
"resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-8.0.2.tgz", "resolved": "https://registry.npmjs.org/ngx-clipboard/-/ngx-clipboard-8.0.2.tgz",

View File

@ -30,6 +30,7 @@
"jquery": "^3.1.0", "jquery": "^3.1.0",
"jquery-ui": "^1.12.0", "jquery-ui": "^1.12.0",
"jquery-ui-bundle": "^1.11.4", "jquery-ui-bundle": "^1.11.4",
"ngx-bootstrap": "^1.8.1",
"ngx-clipboard": "^8.0.2", "ngx-clipboard": "^8.0.2",
"rxjs": "^5.2.0", "rxjs": "^5.2.0",
"ts-helpers": "^1.1.1", "ts-helpers": "^1.1.1",

View File

@ -35,10 +35,11 @@ import {WarService} from "./services/war-service/war.service";
import {DataTableModule} from "angular2-datatable"; import {DataTableModule} from "angular2-datatable";
import {NgxChartsModule} from "@swimlane/ngx-charts"; import {NgxChartsModule} from "@swimlane/ngx-charts";
import {BrowserAnimationsModule} from "@angular/platform-browser/animations"; import {BrowserAnimationsModule} from "@angular/platform-browser/animations";
import {AccordionModule} from "ngx-bootstrap";
@NgModule({ @NgModule({
imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule, ClipboardModule, DataTableModule, imports: [BrowserModule, FormsModule, ReactiveFormsModule, appRouting, HttpModule, ClipboardModule, DataTableModule,
BrowserAnimationsModule, NgxChartsModule], BrowserAnimationsModule, NgxChartsModule, AccordionModule.forRoot()],
providers: [ providers: [
HttpClient, HttpClient,
LoginService, LoginService,

View File

@ -1,7 +1,7 @@
<div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()"> <div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()">
<div class="row"> <div class="row">
<div class="col-xs-9"> <div class="col-xs-8">
<span> <span>
<a>{{decoration.name}}</a> <a>{{decoration.name}}</a>
</span> </span>
@ -12,7 +12,7 @@
<small> - Sortierung: {{decoration.sortingNumber}}</small> <small> - Sortierung: {{decoration.sortingNumber}}</small>
</div> </div>
<div class="col-xs-3"> <div class="col-xs-4">
<img src="{{imageSrc}}" <img src="{{imageSrc}}"
[style.max-height]="imgStyle.height" [style.max-height]="imgStyle.height"
[style.max-width]="imgStyle.width" [style.max-width]="imgStyle.width"

View File

@ -11,7 +11,7 @@ export interface User {
_id?: string; _id?: string;
boardUserId?: number; boardUserId?: number;
username?: string; username?: string;
squad?: any; //Squad or string squad?: any; //Squad or id-string
rank?: Rank; rank?: Rank;
awards?: Award[]; awards?: Award[];
} }
@ -28,6 +28,11 @@ export interface Player {
respawn?: number; respawn?: number;
flagTouch?: number; flagTouch?: number;
} }
export interface Campaign {
_id?: string;
title?: string;
wars?: War[];
}
export interface War { export interface War {
_id?: string; _id?: string;
title?: string; title?: string;
@ -36,7 +41,8 @@ export interface War {
ptOpfor?: number; ptOpfor?: number;
playersBlufor?: number; playersBlufor?: number;
playersOpfor?: number; playersOpfor?: number;
players: Player[]; players?: Player[];
campaign?: string;
} }
export interface Squad { export interface Squad {

View File

@ -1,7 +1,7 @@
<div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()"> <div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()">
<div class="row"> <div class="row">
<div class="col-xs-9"> <div class="col-xs-8">
<span> <span>
<a>{{rank.name}}</a> <a>{{rank.name}}</a>
</span> </span>
@ -11,7 +11,7 @@
<small> - Stufe {{rank.level}}</small> <small> - Stufe {{rank.level}}</small>
</div> </div>
<div class="col-xs-3"> <div class="col-xs-4">
<img src="{{imageSrc}}" 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> <span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash"></span>
</div> </div>

View File

@ -1,16 +1,18 @@
import {Injectable} from "@angular/core"; import {Injectable} from "@angular/core";
import {War} from "../../models/model-interfaces"; import {Campaign, 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) {
} }
getAllWars() { getAllCampaigns() {
return this.http.get(this.config.apiWarPath) return this.http.get(this.config.apiWarPath)
.map(res => res.json()) .map(res => res.json())
} }

View File

@ -1,7 +1,7 @@
<div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()"> <div class="fade-in list-entry" [ngClass]="{selected : selected}" (click)="select()">
<div class="row"> <div class="row">
<div class="col-xs-9"> <div class="col-xs-8">
<span> <span>
<a>{{squad.name}}</a> <a>{{squad.name}}</a>
</span> </span>
@ -10,7 +10,7 @@
<small *ngIf="squad.fraction == 'BLUFOR'">NATO</small> <small *ngIf="squad.fraction == 'BLUFOR'">NATO</small>
</div> </div>
<div class="col-xs-3"> <div class="col-xs-4">
<img src="{{imageSrc}}" height="50px" class="squad-list-preview"> <img src="{{imageSrc}}" height="50px" class="squad-list-preview">
<span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash"></span> <span (click)="delete(); $event.stopPropagation()" title="Löschen" class="glyphicon glyphicon-trash trash"></span>
</div> </div>

View File

@ -1,9 +1,3 @@
h3 {
width: 920px;
margin-left: 5%;
}
.chart-container { .chart-container {
width: 1200px; width: 1200px;
margin-left: 5%;
} }

View File

@ -1,3 +1,5 @@
<h2>{{title}}</h2>
<h3>Punkte</h3> <h3>Punkte</h3>
<div class="chart-container"> <div class="chart-container">

View File

@ -1,14 +1,20 @@
import {Component} from "@angular/core"; import {Component} from "@angular/core";
import {WarService} from "../../services/war-service/war.service"; 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({ @Component({
selector: 'stats-overview', selector: 'stats-overview',
templateUrl: './stats-overview.component.html', templateUrl: './stats-overview.component.html',
styleUrls: ['./stats-overview.component.css'] styleUrls: ['./stats-overview.component.css'],
inputs: ['campaigns']
}) })
export class StatisticOverviewComponent { export class StatisticOverviewComponent {
title = "";
pointData: any[] = []; pointData: any[] = [];
playerData: any[] = []; playerData: any[] = [];
@ -16,12 +22,40 @@ export class StatisticOverviewComponent {
domain: ['#0000FF', '#B22222'] domain: ['#0000FF', '#B22222']
}; };
constructor(private warService: WarService) { constructor(private route: ActivatedRoute,
private warService: WarService) {
} }
ngOnInit() { ngOnInit() {
this.warService.getAllWars().subscribe(items => { this.route.params
this.initChart(items); .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);
}
}) })
} }

View File

@ -1,9 +0,0 @@
#left {
width: 320px;
float: left;
padding-right: 10px;
}
#right {
overflow: hidden
}

View File

@ -17,7 +17,7 @@ export const statsRoutes: Routes = [{
] ]
}, },
{ {
path: 'overview', path: 'overview/:id',
component: StatisticOverviewComponent, component: StatisticOverviewComponent,
outlet: 'right' outlet: 'right'
}, },

View File

@ -1,6 +1,6 @@
<div class="overview" xmlns="http://www.w3.org/1999/html"> <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> <h2>{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}</h2>
<h3 class="pull-left"> <h3 class="pull-left">
<h4>Endpunktestand:</h4> <h4>Endpunktestand:</h4>
@ -9,7 +9,7 @@
<span class="text-opfor" style="font-weight: bold; margin-left: 10px;">{{war.ptOpfor}} CSAT</span> <span class="text-opfor" style="font-weight: bold; margin-left: 10px;">{{war.ptOpfor}} CSAT</span>
</h3> </h3>
<h3 class="pull-left" style="padding-left: 6%;"> <h3 class="pull-left">
<h4>Teilnehmer:</h4> <h4>Teilnehmer:</h4>
<ngx-charts-pie-chart <ngx-charts-pie-chart
[view]="[150, 150]" [view]="[150, 150]"
@ -23,7 +23,7 @@
</ngx-charts-pie-chart> </ngx-charts-pie-chart>
</h3> </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 <a class="btn btn-default" style="margin: 20px" target="_blank" href="resource/logs/{{war._id}}/clean.log">Logfile
anzeigen</a> anzeigen</a>
<form class="form-group"> <form class="form-group">
@ -50,7 +50,7 @@
</div> </div>
</div> </div>
<div class="pull-left" style="margin-left: 2%"> <div class="pull-left" >
<div class="table-container scoreboard-table-container"> <div class="table-container scoreboard-table-container">
<table class="table table-hover" [mfData]="players" #mf="mfDataTable" [(mfSortBy)]="sortBy" <table class="table table-hover" [mfData]="players" #mf="mfDataTable" [(mfSortBy)]="sortBy"
[(mfSortOrder)]="sortOrder"> [(mfSortOrder)]="sortOrder">

View File

@ -6,3 +6,10 @@
.rank-list { .rank-list {
width: 100%; width: 100%;
} }
:host /deep/ .card-header {
background-color: slategray;
padding: 15px;
color: white;
font-weight: 600;
}

View File

@ -5,20 +5,44 @@
</a> </a>
</div> </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="row">
<div class="col-xs-9"> <div class="col-xs-9">
<span style="margin:auto"> <span style="margin:auto">
<a>Zusammenfassung</a> <a>Gesamtübersicht</a>
</span> </span>
</div> </div>
</div> </div>
</div> </div>
<pjm-war-item *ngFor="let war of wars" <accordion *ngFor="let campaign of campaigns">
<accordion-group>
<div accordion-heading (click)="selectOverview(campaign._id)">
{{campaign.title}}
<span class="pull-right"></span>
</div>
<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" [war]="war"
(warDelete)="deleteWar(war)" (warDelete)="deleteWar(war)"
(warSelected)="selectWar($event)" (warSelected)="selectWar($event)"
[selected]="war._id == selectedWarId"> [selected]="war._id == selectedWarId">
</pjm-war-item> </pjm-war-item>
</div> </div>
</accordion-group>
</accordion>
</div>

View File

@ -1,6 +1,6 @@
import {Component, OnInit} from "@angular/core"; import {Component, OnInit} from "@angular/core";
import {ActivatedRoute, Router} from "@angular/router"; 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 {WarService} from "../../services/war-service/war.service";
import {LoginService} from "../../services/login-service/login-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 { export class WarListComponent implements OnInit {
selectedWarId: string | number = '0'; selectedWarId: string | number = 'all';
wars: War[] = []; campaigns: Campaign[] = [];
constructor(private warService: WarService, constructor(private warService: WarService,
private loginService: LoginService, private loginService: LoginService,
@ -22,9 +22,10 @@ export class WarListComponent implements OnInit {
} }
ngOnInit() { ngOnInit() {
this.warService.getAllWars().subscribe((items) => { this.warService.getAllCampaigns().subscribe((items) => {
this.wars = items; this.warService.campaigns = items;
this.router.navigate([{outlets: {'right': ['overview']}}], {relativeTo: this.route}); this.campaigns = items;
this.router.navigate([{outlets: {'right': ['overview', 'all']}}], {relativeTo: this.route});
}); });
} }
@ -33,14 +34,18 @@ export class WarListComponent implements OnInit {
this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route}); this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route});
} }
selectWar(warId: string | number) { selectWar(warId) {
if (this.selectedWarId != warId) {
this.selectedWarId = warId; this.selectedWarId = warId;
this.router.navigate([{outlets: {'right': ['war', warId]}}], {relativeTo: this.route}); this.router.navigate([{outlets: {'right': ['war', warId]}}], {relativeTo: this.route});
} }
}
selectOverview() { selectOverview(overviewId) {
this.selectedWarId = '0'; if (this.selectedWarId != overviewId) {
this.router.navigate([{outlets: {'right': ['overview']}}], {relativeTo: this.route}); this.selectedWarId = overviewId;
this.router.navigate([{outlets: {'right': ['overview', overviewId]}}], {relativeTo: this.route});
}
} }
deleteWar(war: War) { deleteWar(war: War) {
@ -48,10 +53,11 @@ export class WarListComponent implements OnInit {
this.warService.deleteWar(war._id) this.warService.deleteWar(war._id)
.subscribe((res) => { .subscribe((res) => {
if (this.selectedWarId === war._id) { 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);
}) })
} }
} }
} }

View File

@ -42,6 +42,19 @@
<show-error text="Punkte CSAT" path="ptopf"></show-error> <show-error text="Punkte CSAT" path="ptopf"></show-error>
</div> </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"> <div class="form-group">
<label for="log">Logfile</label> <label for="log">Logfile</label>
<input id="log" name="log" class="ui-button form-control" type="file" <input id="log" name="log" class="ui-button form-control" type="file"

View File

@ -13,6 +13,7 @@ label {
.overview { .overview {
position: fixed; position: fixed;
width: 25%; width: 25%;
min-width: 500px;
border-left: thin solid lightgrey; border-left: thin solid lightgrey;
padding-left: 50px; padding-left: 50px;
padding-top: 20px; padding-top: 20px;

View File

@ -1,7 +1,6 @@
div.list-entry, a.list-entry, div.list-entry, a.list-entry,
div.user-list-entry, a.user-list-entry { div.user-list-entry, a.user-list-entry {
padding: 8px; padding: 8px;
width: 475px;
border-radius: 2px; border-radius: 2px;
border: lightgrey solid 1px; border: lightgrey solid 1px;
cursor: cell; cursor: cell;

View File

@ -1,7 +1,7 @@
<div class="fade-in user-list-entry" [ngClass]="{selected : selected}" (click)="select()"> <div class="fade-in user-list-entry" [ngClass]="{selected : selected}" (click)="select()">
<div class="row"> <div class="row">
<div class="col-sm-9"> <div class="col-sm-8">
<span> <span>
<a>{{user.username}}</a> <a>{{user.username}}</a>
</span> </span>
@ -11,7 +11,7 @@
<small *ngIf="!user.squad">ohne Squad/Fraktion</small> <small *ngIf="!user.squad">ohne Squad/Fraktion</small>
</div> </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)="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> <span (click)="award(); $event.stopPropagation()" title="Auszeichnungen" class="icon-award pull-right"></span>
</div> </div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -40,16 +40,14 @@ form {
} }
#left { #left {
width:480px; width: 20%;
min-width: 350px;
max-width: 450px;
float: left; float: left;
padding-right: 10px; padding-right: 10px;
} }
#right { #right {
overflow: hidden overflow: hidden;
} padding-left: 4%;
.chat-button {
position: absolute;
bottom: 0px;
right: 10px;
} }