Merge branch 'release/v1.7.4' of hardi/opt-cc into master
|
@ -1,2 +1,3 @@
|
|||
{"_id":{"$oid":"5abd55ea9e30a76bfef747d6"},"title":"Ein Kessel Buntes","timestamp":{"$date":"2018-03-29T21:08:58.123Z"},"updatedAt":{"$date":"2018-03-29T21:08:58.123Z"},"__v":0}
|
||||
{"_id":{"$oid":"5abd58989e30a76bfef747e6"},"title":"This Is The End","timestamp":{"$date":"2018-03-29T21:20:24.558Z"},"updatedAt":{"$date":"2018-03-29T21:20:24.558Z"},"__v":0}
|
||||
{"_id":{"$oid":"5abd55ea9e32a76afef777d6"},"title":"Placeholder","timestamp":{"$date":"2018-03-30T21:08:58.123Z"},"updatedAt":{"$date":"2018-03-30T21:08:58.123Z"},"__v":0}
|
||||
|
|
|
@ -1,2 +1,3 @@
|
|||
{"_id":{"$oid":"5abf65d83fc5fa349ffd5cbb"},"playersBlufor":4,"playersOpfor":4,"budgetBlufor":4535500,"budgetOpfor":4221250,"endBudgetBlufor":997000,"endBudgetOpfor":512000,"title":"Battle #1","campaign":{"$oid":"5abd55ea9e30a76bfef747d6"},"date":{"$date":"2018-03-19T23:00:00.000Z"},"endDate":{"$date":"2018-03-20T01:30:00.000Z"},"ptBlufor":34,"ptOpfor":25,"timestamp":{"$date":"2018-03-31T10:41:28.451Z"},"updatedAt":{"$date":"2018-03-31T10:41:28.451Z"},"__v":0}
|
||||
{"_id":{"$oid":"5abf65ae3fc5fa349ffd5ca3"},"playersBlufor":4,"playersOpfor":4,"budgetBlufor":4535500,"budgetOpfor":4221250,"endBudgetBlufor":997000,"endBudgetOpfor":512000,"title":"Test Battle #0","campaign":{"$oid":"5abd55ea9e30a76bfef747d6"},"date":{"$date":"2018-03-19T23:00:00.000Z"},"endDate":{"$date":"2018-03-20T01:30:00.000Z"},"ptBlufor":34,"ptOpfor":25,"timestamp":{"$date":"2018-03-31T10:40:46.695Z"},"updatedAt":{"$date":"2018-03-31T10:40:46.695Z"},"__v":0}
|
||||
{"_id":{"$oid":"5abf65ae2df5fa349ffd5ca3"},"playersBlufor":20,"playersOpfor":20,"budgetBlufor":4535500,"budgetOpfor":4535500,"endBudgetBlufor":0,"endBudgetOpfor":20000,"title":"Test Battle XY","campaign":{"$oid":"5abd55ea9e30a76bfef747d6"},"date":{"$date":"2018-03-02T23:00:00.000Z"},"endDate":{"$date":"2018-03-02T01:30:00.000Z"},"ptBlufor":34,"ptOpfor":25,"timestamp":{"$date":"2018-03-02T10:40:46.695Z"},"updatedAt":{"$date":"2018-03-02T10:40:46.695Z"},"__v":0}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
###-------------------------------------------------------------###
|
||||
###------------------- HOW TO USE THIS FILE --------------------###
|
||||
###-------------------------------------------------------------###
|
||||
### 1. start express server with `npm run start-test` ###
|
||||
### 1. start express server with `npm run start-api-test` ###
|
||||
### 2. import data by executing script: `./populate-data.sh` ###
|
||||
### 3. change data in app as you need for tests ###
|
||||
### 4. export data state with: `./populate-data.sh -m save` ###
|
||||
|
|
|
@ -24,6 +24,25 @@ Create a new campaign
|
|||
|
||||
+ Attributes (Campaign, fixed-type)
|
||||
|
||||
### Update Campaign [PATCH /campaigns/{id}]
|
||||
|
||||
Update a campaign, identified by its id
|
||||
|
||||
**Permission: 3**
|
||||
|
||||
+ Parameters
|
||||
+ id: `5abd55ea9e32a76afef777d6` (string, required) - unique id of campaign
|
||||
|
||||
+ Request (application/json)
|
||||
|
||||
+ Attributes
|
||||
+ _id: `5abd55ea9e32a76afef777d6` (string, required) - unique id of campaign
|
||||
+ title: `Operation Pandora` (string, optional) - display name of the campaign
|
||||
|
||||
+ Response 200 (application/json; charset=utf-8)
|
||||
|
||||
+ Attributes (Campaign, fixed-type)
|
||||
|
||||
### Delete Campaign [DELETE /campaigns/{id}]
|
||||
|
||||
Delete a campaign
|
||||
|
|
|
@ -76,6 +76,35 @@ Create a new war
|
|||
|
||||
+ Attributes (War, fixed-type)
|
||||
|
||||
### Update War [PATCH /wars/{id}]
|
||||
|
||||
Update a war, identified by its id
|
||||
|
||||
**Permission: 3**
|
||||
|
||||
+ Parameters
|
||||
+ id: `5abf65ae2df5fa349ffd5ca3` (string, required) - unique id of campaign
|
||||
|
||||
+ Request (application/json)
|
||||
|
||||
+ Attributes
|
||||
+ _id: `5abf65ae2df5fa349ffd5ca3` (string, required) - unique id of war
|
||||
+ title: `Final Touchdown` (string, optional) - display name of the war
|
||||
+ date: `2017-05-11T20:00:00.471Z` (string, optional) - starting date
|
||||
+ endDate: `2017-05-12T00:30:32.471Z` (string, optional) - end date
|
||||
+ ptBlufor: 5 (number, optional) - points Blufor
|
||||
+ ptOpfor: 5 (number, optional) - points Opfor
|
||||
+ playersBlufor: 20 (number, optional) - number of players Blufor
|
||||
+ playersOpfor: 20 (number, optional) - number of players Opfor
|
||||
+ budgetBlufor: 3000000 (number, optional) - start budget Blufor
|
||||
+ budgetOpfor: 3000000 (number, optional) - start budget Opfor
|
||||
+ endBudgetBlufor: 10000 (number, optional) - end budget Blufor
|
||||
+ endBudgetOpfor: 12000 (number, optional) - end budget Opfor
|
||||
|
||||
+ Response 200 (application/json; charset=utf-8)
|
||||
|
||||
+ Attributes (War, fixed-type)
|
||||
|
||||
### Delete War [DELETE /wars/{id}]
|
||||
|
||||
Delete a war
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
'use strict';
|
||||
|
||||
// HTTP status codes by name
|
||||
const codes = require('./http-codes');
|
||||
|
||||
const genericGetById = (req, res, next, modelClass) => {
|
||||
modelClass.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();
|
||||
});
|
||||
};
|
||||
|
||||
const genericPatch = (req, res, next, modelClass) => {
|
||||
if (!req.body || (req.body._id && req.body._id !== req.params.id)) {
|
||||
// little bit different as in PUT. :id does not need to be in data, but if the _id and url id must match
|
||||
const err = new Error('id of PATCH resource and send JSON body are not equal ' + req.params.id + ' ' +
|
||||
req.body._id);
|
||||
err.status = codes.notfound;
|
||||
next(err);
|
||||
return; // prevent node to process this function further after next() has finished.
|
||||
}
|
||||
|
||||
req.body.updatedAt = new Date();
|
||||
req.body.$inc = {__v: 1};
|
||||
if (req.body.hasOwnProperty('__v')) {
|
||||
delete req.body.__v;
|
||||
}
|
||||
|
||||
// PATCH is easier with mongoose than PUT. You simply update by all data that comes from outside. no need to
|
||||
// reset attributes that are missing.
|
||||
modelClass.findByIdAndUpdate(req.params.id, req.body, {new: true}, (err, item) => {
|
||||
if (err) {
|
||||
err.status = codes.wrongrequest;
|
||||
} else if (!item) {
|
||||
err = new Error('item not found');
|
||||
err.status = codes.notfound;
|
||||
} else {
|
||||
res.locals.items = item;
|
||||
}
|
||||
next(err);
|
||||
});
|
||||
};
|
||||
|
||||
exports.genericGetById = genericGetById;
|
||||
exports.genericPatch = genericPatch;
|
|
@ -16,12 +16,14 @@ const idValidator = require('../middleware/validators').idValidator;
|
|||
const CampaignModel = require('../models/campaign');
|
||||
const WarModel = require('../models/war');
|
||||
|
||||
// util
|
||||
const genericGetById = require('./_generic').genericGetById;
|
||||
const genericPatch = require('./_generic').genericPatch;
|
||||
|
||||
const campaigns = new 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
|
||||
|
@ -43,18 +45,11 @@ campaigns.route('/')
|
|||
|
||||
campaigns.route('/:id')
|
||||
.get(idValidator, (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();
|
||||
});
|
||||
return genericGetById(req, res, next, CampaignModel);
|
||||
})
|
||||
|
||||
.patch(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||
return genericPatch(req, res, next, CampaignModel);
|
||||
})
|
||||
|
||||
.delete((req, res, next) => {
|
||||
|
|
|
@ -21,6 +21,9 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca
|
|||
const DecorationModel = require('../models/decoration');
|
||||
const AwardingsModel = require('../models/awarding');
|
||||
|
||||
// util
|
||||
const genericGetById = require('./_generic').genericGetById;
|
||||
|
||||
const decoration = new express.Router();
|
||||
|
||||
// routes **********************
|
||||
|
@ -81,18 +84,7 @@ decoration.route('/')
|
|||
|
||||
decoration.route('/:id')
|
||||
.get(idValidator, (req, res, next) => {
|
||||
DecorationModel.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;
|
||||
next();
|
||||
});
|
||||
return genericGetById(req, res, next, DecorationModel);
|
||||
})
|
||||
|
||||
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
||||
|
|
|
@ -20,6 +20,9 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca
|
|||
// Mongoose Model using mongoDB
|
||||
const RankModel = require('../models/rank');
|
||||
|
||||
// util
|
||||
const genericGetById = require('./_generic').genericGetById;
|
||||
|
||||
const ranks = new express.Router();
|
||||
|
||||
// routes **********************
|
||||
|
@ -73,18 +76,7 @@ ranks.route('/')
|
|||
|
||||
ranks.route('/:id')
|
||||
.get(idValidator, (req, res, next) => {
|
||||
RankModel.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;
|
||||
next();
|
||||
});
|
||||
return genericGetById(req, res, next, RankModel);
|
||||
})
|
||||
|
||||
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
||||
|
|
|
@ -20,6 +20,9 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca
|
|||
// Mongoose Model using mongoDB
|
||||
const SquadModel = require('../models/squad');
|
||||
|
||||
// util
|
||||
const genericGetById = require('./_generic').genericGetById;
|
||||
|
||||
const squads = new express.Router();
|
||||
|
||||
// routes **********************
|
||||
|
@ -77,18 +80,7 @@ squads.route('/')
|
|||
|
||||
squads.route('/:id')
|
||||
.get(idValidator, (req, res, next) => {
|
||||
SquadModel.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;
|
||||
next();
|
||||
});
|
||||
return genericGetById(req, res, next, SquadModel);
|
||||
})
|
||||
|
||||
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
||||
|
|
|
@ -35,6 +35,9 @@ const LogFlagModel = require('../models/logs/flag');
|
|||
const LogBudgetModel = require('../models/logs/budget');
|
||||
const LogPointsModel = require('../models/logs/points');
|
||||
|
||||
// util
|
||||
const genericPatch = require('./_generic').genericPatch;
|
||||
|
||||
const wars = new express.Router();
|
||||
|
||||
// routes **********************
|
||||
|
@ -168,6 +171,10 @@ wars.route('/:id')
|
|||
});
|
||||
})
|
||||
|
||||
.patch(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||
return genericPatch(req, res, next, WarModel);
|
||||
})
|
||||
|
||||
.delete(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||
WarModel.findByIdAndRemove(req.params.id, (err, item) => {
|
||||
if (err) {
|
||||
|
|
|
@ -106,6 +106,12 @@ const parseWarLog = (lineArray, war) => {
|
|||
stats.war['endBudgetBlufor'] = transformMoneyString(budg[9]);
|
||||
stats.war['endBudgetOpfor'] = transformMoneyString(budg[12].slice(0, -2));
|
||||
stats.war.endDate = getFullTimeDate(war.date, budg[5]);
|
||||
} else if (line.includes('Respawn von ')) {
|
||||
/**
|
||||
* RESPAWN
|
||||
*/
|
||||
const playerName = line.substring(line.lastIndexOf('Respawn von ') + 12, line.lastIndexOf('"'));
|
||||
stats.respawn.push(getRespawnEntry(budg, playerName, war._id, war.date));
|
||||
} else {
|
||||
stats.budget.push(getBudgetEntry(budg, war._id, war.date));
|
||||
}
|
||||
|
@ -140,13 +146,6 @@ const parseWarLog = (lineArray, war) => {
|
|||
} else {
|
||||
stats.points.push(getPointsEntry(pt, line, war._id, war.date));
|
||||
}
|
||||
} else if (line.includes('(Respawn)')) {
|
||||
/**
|
||||
* RESPAWN
|
||||
*/
|
||||
const resp = line.split(WHITESPACE);
|
||||
const playerName = line.substring(line.lastIndexOf('Spieler:') + 9, line.lastIndexOf('- Kosten') - 1);
|
||||
stats.respawn.push(getRespawnEntry(resp, playerName, war._id, war.date));
|
||||
} else if (line.includes('(Revive)')) {
|
||||
/**
|
||||
* REVIVE
|
||||
|
|
|
@ -137,48 +137,7 @@ let addDecorationsAndSave = (userId, loadedImage, res, next) => {
|
|||
return next(err);
|
||||
}
|
||||
if (awardings.length > 0) {
|
||||
// TODO: simplify this sorting hell
|
||||
awardings.sort((a1, a2) => {
|
||||
if (!a1.decorationId.isMedal && !a2.decorationId.isMedal) {
|
||||
if (a1.decorationId.fraction === a2.decorationId.fraction) {
|
||||
if (a1.date !== a2.date) {
|
||||
if (a1.date < a2.date) {
|
||||
return -1;
|
||||
}
|
||||
if (a1.date > a2.date) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (a1.decorationId.fraction === 'GLOBAL' && a2.decorationId.fraction !== 'GLOBAL') {
|
||||
return -1;
|
||||
}
|
||||
if (a2.decorationId.fraction === 'GLOBAL' && a1.decorationId.fraction !== 'GLOBAL') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a1.decorationId.isMedal !== a2.decorationId.isMedal) {
|
||||
if (a1.decorationId.isMedal && !a2.decorationId.isMedal) {
|
||||
return 1;
|
||||
}
|
||||
if (!a1.decorationId.isMedal && a2.decorationId.isMedal) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (a1.decorationId.isMedal && a2.decorationId.isMedal) {
|
||||
if (a1.date !== a2.date) {
|
||||
if (a1.date < a2.date) {
|
||||
return -1;
|
||||
}
|
||||
if (a1.date > a2.date) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
awardings.sort((a1, a2) => sortAwardingsForSignature(a1, a2));
|
||||
|
||||
// use synchronized call to keep correct order of decorations
|
||||
async.eachSeries(awardings, (award, callback) => {
|
||||
|
@ -262,5 +221,47 @@ let saveJimpImageAndCompress = (image, userId, res, next) => {
|
|||
}, 3000);
|
||||
};
|
||||
|
||||
const sortAwardingsForSignature = (a1, a2) => {
|
||||
if (!a1.decorationId.isMedal && !a2.decorationId.isMedal) {
|
||||
if (a1.decorationId.fraction === a2.decorationId.fraction) {
|
||||
if (a1.date !== a2.date) {
|
||||
if (a1.date < a2.date) {
|
||||
return -1;
|
||||
}
|
||||
if (a1.date > a2.date) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
} else {
|
||||
if (a1.decorationId.fraction === 'GLOBAL' && a2.decorationId.fraction !== 'GLOBAL') {
|
||||
return -1;
|
||||
}
|
||||
if (a2.decorationId.fraction === 'GLOBAL' && a1.decorationId.fraction !== 'GLOBAL') {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (a1.decorationId.isMedal !== a2.decorationId.isMedal) {
|
||||
if (a1.decorationId.isMedal && !a2.decorationId.isMedal) {
|
||||
return 1;
|
||||
}
|
||||
if (!a1.decorationId.isMedal && a2.decorationId.isMedal) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (a1.decorationId.isMedal && a2.decorationId.isMedal) {
|
||||
if (a1.date !== a2.date) {
|
||||
if (a1.date < a2.date) {
|
||||
return -1;
|
||||
}
|
||||
if (a1.date > a2.date) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
module.exports = createSignature;
|
||||
|
|
|
@ -39,7 +39,6 @@ const timeStringToDecimal = (timeString) => {
|
|||
return hour + (sek / 3600);
|
||||
};
|
||||
|
||||
|
||||
const decimalToTimeString = (decimal) => {
|
||||
const hours = parseInt(decimal.toString().split('.')[0]);
|
||||
const minutesFloat = ((decimal % 1) * 3600) / 60;
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
<option name="RIGHT_MARGIN" value="120" />
|
||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
||||
<option name="SPACE_WITHIN_BRACKETS" value="true" />
|
||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||
|
@ -21,4 +22,4 @@
|
|||
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
||||
<option name="WRAP_COMMENTS" value="true" />
|
||||
</codeStyleSettings>
|
||||
</code_scheme>
|
||||
</code_scheme>
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "opt-cc",
|
||||
"version": "1.7.3",
|
||||
"version": "1.7.4",
|
||||
"author": "Florian Hartwich <hardi@noarch.de>",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {LoginComponent} from './login/index';
|
||||
import {NotFoundComponent} from './common/not-found/not-found.component';
|
||||
import {LoginGuardAdmin, LoginGuardHL} from './login/login.guard';
|
||||
import {NotFoundComponent} from './common/not-found';
|
||||
import {LoginComponent, LoginGuardAdmin, LoginGuardHL, LoginGuardMT} from './login';
|
||||
import {armyRoutes, armyRoutingComponents} from './army/army.routing';
|
||||
import {SignupComponent} from './login/signup.component';
|
||||
import {RouteConfig} from './app.config';
|
||||
|
@ -72,4 +71,4 @@ export const appRouting = RouterModule.forRoot(appRoutes);
|
|||
|
||||
export const routingComponents = [...armyRoutingComponents, LoginComponent, SignupComponent, NotFoundComponent];
|
||||
|
||||
export const routingProviders = [LoginGuardHL, LoginGuardAdmin];
|
||||
export const routingProviders = [LoginGuardHL, LoginGuardMT, LoginGuardAdmin];
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
<p>Dieses Formular nur ausfüllen wenn du einer <b>HL</b> angehörst oder <b>SQL</b> bist. Dabei den Nutzernamen aus
|
||||
dem OPT Forum verwenden!
|
||||
Im Forum eine Nachricht an <a href="https://opt-dev.de/dashboard/index.php?conversation-add/&userID=9"
|
||||
Im Forum eine Nachricht an <a href="https://operation-pandora.com/dashboard/index.php?conversation-add/&userID=9"
|
||||
target="_blank">HardiReady</a>
|
||||
senden, in welcher der 'geheime Text' steht, den du bei der Registrierung nutzt.<br>
|
||||
Dabei kann es sich um irgend eine willkürliche Zeichenfolge oder einen Satz handeln - dient nur dem Abgleich.
|
||||
|
|
|
@ -18,8 +18,13 @@ export class CampaignService {
|
|||
}
|
||||
|
||||
submitCampaign(campaign: Campaign) {
|
||||
return this.http.post(this.config.apiCampaignPath, campaign)
|
||||
.map(res => res.json());
|
||||
if (campaign._id) {
|
||||
return this.http.patch(this.config.apiCampaignPath + '/' + campaign._id, campaign)
|
||||
.map(res => res.json());
|
||||
} else {
|
||||
return this.http.post(this.config.apiCampaignPath, campaign)
|
||||
.map(res => res.json());
|
||||
}
|
||||
}
|
||||
|
||||
deleteCampaign(id: string) {
|
||||
|
@ -27,5 +32,9 @@ export class CampaignService {
|
|||
.map(res => res.json());
|
||||
}
|
||||
|
||||
getCampaign(id: string) {
|
||||
return this.http.get(this.config.apiCampaignPath + '/' + id)
|
||||
.map(res => res.json());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,5 +38,9 @@ export class WarService {
|
|||
.map(res => res.json());
|
||||
}
|
||||
|
||||
updateWar(war: War) {
|
||||
return this.http.patch(this.config.apiWarPath + '/' + war._id, war)
|
||||
.map(res => res.json());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,224 +0,0 @@
|
|||
<div class="fade-in player-campaign-detail-container" xmlns="http://www.w3.org/1999/html">
|
||||
<h2 class="pull-left">Kampagnendetails - {{campaignPlayer.name}}</h2>
|
||||
<h2 class="pull-right">{{campaignPlayer.campaign.title}} Kampagne</h2>
|
||||
|
||||
<span class="btn btn-default btn-back" (click)="navigateBack()">< Zurück</span>
|
||||
|
||||
<div class="sum-container">
|
||||
<div class="gauge-container pull-left">
|
||||
<ngx-charts-linear-gauge
|
||||
[view]="[200, 100]"
|
||||
[scheme]="colorScheme"
|
||||
[value]="kdRatio"
|
||||
[previousValue]="1"
|
||||
[max]="maxKd"
|
||||
[min]="0"
|
||||
[units]="'Kill/Death'">
|
||||
</ngx-charts-linear-gauge>
|
||||
<span style="height: 150px; display: block;"></span>
|
||||
<ngx-charts-linear-gauge
|
||||
[view]="[200, 100]"
|
||||
[scheme]="colorScheme"
|
||||
[value]="respawnDeathRatio"
|
||||
[previousValue]="0.5"
|
||||
[max]="maxRespawnDeathRatio"
|
||||
[min]="0"
|
||||
[units]="'Respawn/Death'">
|
||||
</ngx-charts-linear-gauge>
|
||||
</div>
|
||||
|
||||
<div class="sum-bar-container pull-left">
|
||||
<ngx-charts-bar-horizontal
|
||||
[scheme]="colorSchemeBar"
|
||||
[results]="sumData"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel">
|
||||
</ngx-charts-bar-horizontal>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="charts-parent">
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="killData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="killRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisKill"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="friendlyFireData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="friendlyFireRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisFriendlyFire"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="deathData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="deathRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisDeath"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="respawnData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="respawnRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisRespawn"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="reviveData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="reviveRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisRevive"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="captureData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="captureRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisCapture"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="vehicleLightData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="killRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisVehicleLight"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="vehicleHeavyData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="killRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisVehicleHeavy"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
|
||||
<div class="chart-container">
|
||||
<ngx-charts-line-chart
|
||||
[results]="vehicleAirData"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="killRefLines"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="yAxisVehicleAir"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -1,223 +0,0 @@
|
|||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {CampaignPlayer} from '../../models/model-interfaces';
|
||||
import {PlayerService} from '../../services/logs/player.service';
|
||||
import {ChartUtils} from '../../utils/chart-utils';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'campaign-player-detail',
|
||||
templateUrl: './campaign-player-detail.component.html',
|
||||
styleUrls: ['./campaign-player-detail.component.css', '../../style/list-entry.css',
|
||||
'../../style/hide-scrollbar.css', '../../style/overview.css']
|
||||
})
|
||||
export class CampaignPlayerDetailComponent implements OnInit {
|
||||
|
||||
@Input() campaignId: string;
|
||||
|
||||
@Input() playerName: string;
|
||||
|
||||
@Output() switchTab = new EventEmitter();
|
||||
|
||||
campaignPlayer: CampaignPlayer = {campaign: {}, players: []};
|
||||
|
||||
sumData: any[] = [];
|
||||
killData: any[] = [];
|
||||
friendlyFireData: any[] = [];
|
||||
vehicleLightData: any[] = [];
|
||||
vehicleHeavyData: any[] = [];
|
||||
vehicleAirData: any[] = [];
|
||||
deathData: any[] = [];
|
||||
respawnData: any[] = [];
|
||||
reviveData: any[] = [];
|
||||
captureData: any[] = [];
|
||||
|
||||
yAxisKill = 'Kills';
|
||||
yAxisFriendlyFire = 'FriendlyFire';
|
||||
yAxisVehicleLight = 'Fahrzeug (Light)';
|
||||
yAxisVehicleHeavy = 'Fahrzeug (Heavy)';
|
||||
yAxisVehicleAir = 'Fahrzeug (Air)';
|
||||
yAxisDeath = 'Tode';
|
||||
yAxisRespawn = 'Respawn';
|
||||
yAxisRevive = 'Revive';
|
||||
yAxisCapture = 'Eroberungen';
|
||||
avgLabel = 'Durchschnitt';
|
||||
|
||||
colorScheme = {
|
||||
domain: ['#00ce12']
|
||||
};
|
||||
colorSchemeBar = {
|
||||
domain: [
|
||||
'#2d5a00', '#455600', '#00561f', '#3f3b00', '#003c19', '#083c00'
|
||||
]
|
||||
};
|
||||
showRefLines = true;
|
||||
showRefLabels = true;
|
||||
killRefLines = [];
|
||||
vehicleLightRefLines = [];
|
||||
vehicleHeavyRefLines = [];
|
||||
vehicleAirRefLines = [];
|
||||
deathRefLines = [];
|
||||
captureRefLines = [];
|
||||
friendlyFireRefLines = [];
|
||||
reviveRefLines = [];
|
||||
respawnRefLines = [];
|
||||
|
||||
gradient = false;
|
||||
xAxis = true;
|
||||
yAxis = true;
|
||||
legend = false;
|
||||
showXAxisLabel = true;
|
||||
showYAxisLabel = true;
|
||||
autoscale = false;
|
||||
timeline = false;
|
||||
roundDomains = true;
|
||||
|
||||
totalKills;
|
||||
totalFriendlyFire;
|
||||
totalVehicleLight;
|
||||
totalVehicleHeavy;
|
||||
totalVehicleAir;
|
||||
totalDeath;
|
||||
totalRespawn;
|
||||
totalRevive;
|
||||
totalCapture;
|
||||
|
||||
kdRatio = 0;
|
||||
maxKd = 1.7;
|
||||
|
||||
respawnDeathRatio = 0;
|
||||
maxRespawnDeathRatio = 1;
|
||||
|
||||
|
||||
constructor(private playerService: PlayerService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.playerService.getCampaignPlayer(this.campaignId, encodeURIComponent(this.playerName))
|
||||
.subscribe(campaignPlayer => {
|
||||
this.campaignPlayer = campaignPlayer;
|
||||
this.killData = this.assignData(this.yAxisKill, 'kill');
|
||||
this.friendlyFireData = this.assignData(this.yAxisFriendlyFire, 'friendlyFire');
|
||||
this.deathData = this.assignData(this.yAxisDeath, 'death');
|
||||
this.respawnData = this.assignData(this.yAxisRespawn, 'respawn');
|
||||
this.reviveData = this.assignData(this.yAxisRevive, 'revive');
|
||||
this.captureData = this.assignData(this.yAxisCapture, 'flagTouch');
|
||||
this.vehicleLightData = this.assignData(this.yAxisVehicleLight, 'vehicleLight');
|
||||
this.vehicleHeavyData = this.assignData(this.yAxisVehicleHeavy, 'vehicleHeavy');
|
||||
this.vehicleAirData = this.assignData(this.yAxisVehicleAir, 'vehicleAir');
|
||||
|
||||
const totalDeathDiv = this.totalDeath === 0 ? 1 : this.totalDeath;
|
||||
this.kdRatio = parseFloat((this.totalKills / totalDeathDiv).toFixed(2));
|
||||
if (this.kdRatio > 1) {
|
||||
this.maxKd = this.kdRatio * 1.7;
|
||||
}
|
||||
|
||||
this.respawnDeathRatio = parseFloat((this.totalRespawn / totalDeathDiv).toFixed(2));
|
||||
|
||||
this.sumData = [
|
||||
{
|
||||
name: this.yAxisKill,
|
||||
value: this.totalKills
|
||||
},
|
||||
{
|
||||
name: this.yAxisFriendlyFire,
|
||||
value: this.totalFriendlyFire
|
||||
},
|
||||
{
|
||||
name: this.yAxisDeath,
|
||||
value: this.totalDeath
|
||||
},
|
||||
{
|
||||
name: this.yAxisRespawn,
|
||||
value: this.totalRespawn
|
||||
},
|
||||
{
|
||||
name: this.yAxisRevive,
|
||||
value: this.totalRevive
|
||||
},
|
||||
{
|
||||
name: this.yAxisCapture,
|
||||
value: this.totalCapture
|
||||
},
|
||||
{
|
||||
name: this.yAxisVehicleLight,
|
||||
value: this.totalVehicleLight
|
||||
},
|
||||
{
|
||||
name: this.yAxisVehicleHeavy,
|
||||
value: this.totalVehicleHeavy
|
||||
},
|
||||
{
|
||||
name: this.yAxisVehicleAir,
|
||||
value: this.totalVehicleAir
|
||||
},
|
||||
];
|
||||
|
||||
Object.assign(this, [this.sumData, this.killData, this.friendlyFireData, this.vehicleLightData,
|
||||
this.vehicleHeavyData, this.vehicleAirData, this.deathData, this.respawnData, this.reviveData,
|
||||
this.captureData]);
|
||||
});
|
||||
}
|
||||
|
||||
private assignData(label, field) {
|
||||
const killObj = {
|
||||
name: label,
|
||||
series: []
|
||||
};
|
||||
const playerLength = this.campaignPlayer.players.length;
|
||||
let total = 0;
|
||||
for (let i = 0; i < playerLength; i++) {
|
||||
const warDateString = ChartUtils.getShortDateString(this.campaignPlayer.players[i].warId.date);
|
||||
const value = this.campaignPlayer.players[i][field];
|
||||
killObj.series.push({
|
||||
name: warDateString,
|
||||
value: value
|
||||
});
|
||||
total += value;
|
||||
}
|
||||
switch (field) {
|
||||
case 'kill':
|
||||
this.killRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalKills = total;
|
||||
break;
|
||||
case 'friendlyFire':
|
||||
this.friendlyFireRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalFriendlyFire = total;
|
||||
break;
|
||||
case 'death':
|
||||
this.deathRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalDeath = total;
|
||||
break;
|
||||
case 'respawn':
|
||||
this.respawnRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalRespawn = total;
|
||||
break;
|
||||
case 'revive':
|
||||
this.reviveRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalRevive = total;
|
||||
break;
|
||||
case 'flagTouch':
|
||||
this.captureRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalCapture = total;
|
||||
break;
|
||||
case 'vehicleLight':
|
||||
this.vehicleLightRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalVehicleLight = total;
|
||||
break;
|
||||
case 'vehicleHeavy':
|
||||
this.vehicleHeavyRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalVehicleHeavy = total;
|
||||
break;
|
||||
case 'vehicleAir':
|
||||
this.vehicleAirRefLines.push({value: total / playerLength, name: this.avgLabel});
|
||||
this.totalVehicleAir = total;
|
||||
break;
|
||||
}
|
||||
return [killObj];
|
||||
}
|
||||
|
||||
navigateBack() {
|
||||
this.switchTab.emit(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
<div class="fade-in player-campaign-detail-container" xmlns="http://www.w3.org/1999/html">
|
||||
<h2 class="pull-left">Kampagnendetails - {{campaignPlayer.name}}</h2>
|
||||
<h2 class="pull-right">{{campaignPlayer.campaign.title}} Kampagne</h2>
|
||||
|
||||
<span class="btn btn-default btn-back" (click)="navigateBack()">< Zurück</span>
|
||||
|
||||
<div class="sum-container">
|
||||
<div class="gauge-container pull-left">
|
||||
<ngx-charts-linear-gauge
|
||||
[view]="[200, 100]"
|
||||
[scheme]="colorScheme"
|
||||
[value]="kdRatio"
|
||||
[previousValue]="1"
|
||||
[max]="maxKd"
|
||||
[min]="0"
|
||||
[units]="'Kill/Death'">
|
||||
</ngx-charts-linear-gauge>
|
||||
<span style="height: 150px; display: block;"></span>
|
||||
<ngx-charts-linear-gauge
|
||||
[view]="[200, 100]"
|
||||
[scheme]="colorScheme"
|
||||
[value]="respawnDeathRatio"
|
||||
[previousValue]="0.5"
|
||||
[max]="maxRespawnDeathRatio"
|
||||
[min]="0"
|
||||
[units]="'Respawn/Death'">
|
||||
</ngx-charts-linear-gauge>
|
||||
</div>
|
||||
|
||||
<div class="sum-bar-container pull-left">
|
||||
<ngx-charts-bar-horizontal
|
||||
[scheme]="colorSchemeBar"
|
||||
[results]="sumData"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel">
|
||||
</ngx-charts-bar-horizontal>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="charts-parent">
|
||||
<div class="chart-container" *ngFor="let category of graphData">
|
||||
<ngx-charts-line-chart
|
||||
[results]="category.data"
|
||||
[showRefLines]="showRefLines"
|
||||
[showRefLabels]="showRefLabels"
|
||||
[referenceLines]="category.refLine"
|
||||
[scheme]="colorScheme"
|
||||
[gradient]="gradient"
|
||||
[xAxis]="xAxis"
|
||||
[yAxis]="yAxis"
|
||||
[legend]="legend"
|
||||
[showXAxisLabel]="showXAxisLabel"
|
||||
[showYAxisLabel]="showYAxisLabel"
|
||||
[yAxisLabel]="category.label"
|
||||
[autoScale]="autoscale"
|
||||
[timeline]="timeline"
|
||||
[roundDomains]="roundDomains">
|
||||
</ngx-charts-line-chart>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,117 @@
|
|||
import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {CampaignPlayer} from '../../../models/model-interfaces';
|
||||
import {PlayerService} from '../../../services/logs/player.service';
|
||||
import {ChartUtils} from '../../../utils/chart-utils';
|
||||
import {PlayerUtils} from '../../../utils/player-utils';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'campaign-player-detail',
|
||||
templateUrl: './campaign-player-detail.component.html',
|
||||
styleUrls: ['./campaign-player-detail.component.css', '../../../style/list-entry.css',
|
||||
'../../../style/hide-scrollbar.css', '../../../style/overview.css']
|
||||
})
|
||||
export class CampaignPlayerDetailComponent implements OnInit {
|
||||
|
||||
@Input() campaignId: string;
|
||||
|
||||
@Input() playerName: string;
|
||||
|
||||
@Output() switchTab = new EventEmitter();
|
||||
|
||||
campaignPlayer: CampaignPlayer = {campaign: {}, players: []};
|
||||
|
||||
graphData: any[] = [];
|
||||
sumData: any[] = [];
|
||||
|
||||
avgLabel = 'Durchschnitt';
|
||||
|
||||
colorScheme = {
|
||||
domain: ['#00ce12']
|
||||
};
|
||||
colorSchemeBar = {
|
||||
domain: [
|
||||
'#2d5a00', '#455600', '#00561f', '#3f3b00', '#003c19', '#083c00'
|
||||
]
|
||||
};
|
||||
showRefLines = true;
|
||||
showRefLabels = true;
|
||||
gradient = false;
|
||||
xAxis = true;
|
||||
yAxis = true;
|
||||
legend = false;
|
||||
showXAxisLabel = true;
|
||||
showYAxisLabel = true;
|
||||
autoscale = false;
|
||||
timeline = false;
|
||||
roundDomains = true;
|
||||
|
||||
kdRatio = 0;
|
||||
maxKd = 1.7;
|
||||
|
||||
respawnDeathRatio = 0;
|
||||
maxRespawnDeathRatio = 1;
|
||||
|
||||
playerAttributeNameMap = PlayerUtils.attributeDisplayNames.slice(2, PlayerUtils.attributeDisplayNames.length);
|
||||
|
||||
constructor(private playerService: PlayerService) {
|
||||
}
|
||||
|
||||
ngOnInit() {
|
||||
this.playerService.getCampaignPlayer(this.campaignId, encodeURIComponent(this.playerName))
|
||||
.subscribe(campaignPlayer => {
|
||||
this.campaignPlayer = campaignPlayer;
|
||||
|
||||
for (let i = 0; i < this.playerAttributeNameMap.length; i++) {
|
||||
const attr = this.playerAttributeNameMap[i];
|
||||
this.graphData.push({key: attr.prop, label: attr.head});
|
||||
}
|
||||
|
||||
this.initDataArray();
|
||||
|
||||
const totalDeathDiv = this.graphData[7].total === 0 ? 1 : this.graphData[7].total;
|
||||
this.kdRatio = parseFloat((this.graphData[0].total / totalDeathDiv).toFixed(2));
|
||||
if (this.kdRatio > 1) {
|
||||
this.maxKd = this.kdRatio * 1.7;
|
||||
}
|
||||
|
||||
this.respawnDeathRatio = parseFloat((this.graphData[8].total / totalDeathDiv).toFixed(2));
|
||||
|
||||
// we can not directly push to target array, since only full reference changes trigger the refresh of data
|
||||
const tmpSumData = [];
|
||||
this.graphData.forEach(dataSet => {
|
||||
tmpSumData.push({name: dataSet.label, value: dataSet.total});
|
||||
});
|
||||
this.sumData = tmpSumData;
|
||||
});
|
||||
}
|
||||
|
||||
private initDataArray() {
|
||||
this.graphData.forEach(dataSet => {
|
||||
const killObj = {
|
||||
name: dataSet.label,
|
||||
series: []
|
||||
};
|
||||
const playerLength = this.campaignPlayer.players.length;
|
||||
let total = 0;
|
||||
for (let i = 0; i < playerLength; i++) {
|
||||
const warDateString = ChartUtils.getShortDateString(this.campaignPlayer.players[i].warId.date);
|
||||
const value = this.campaignPlayer.players[i][dataSet.key];
|
||||
killObj.series.push({
|
||||
name: warDateString,
|
||||
value: value
|
||||
});
|
||||
total += value;
|
||||
}
|
||||
|
||||
dataSet.data = [killObj];
|
||||
dataSet.refLine = [{value: total / playerLength, name: this.avgLabel}];
|
||||
dataSet.total = total;
|
||||
});
|
||||
}
|
||||
|
||||
navigateBack() {
|
||||
this.switchTab.emit(0);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
<form #form="ngForm" class="overview">
|
||||
<h3>Kampagne hinzufügen</h3>
|
||||
<h3 *ngIf="campaign._id">Kampagne editieren</h3>
|
||||
<h3 *ngIf="!campaign._id">Neue Kampagne hinzufügen</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title">Titel</label>
|
|
@ -1,14 +1,15 @@
|
|||
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/logs/campaign.service';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
import {Campaign} from '../../../models/model-interfaces';
|
||||
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'campaign-submit',
|
||||
templateUrl: './campaign-submit.component.html',
|
||||
styleUrls: ['./campaign-submit.component.css', '../../style/entry-form.css', '../../style/overview.css']
|
||||
styleUrls: ['./campaign-submit.component.css', '../../../style/entry-form.css', '../../../style/overview.css']
|
||||
})
|
||||
export class CampaignSubmitComponent {
|
||||
|
||||
|
@ -18,17 +19,30 @@ export class CampaignSubmitComponent {
|
|||
|
||||
error;
|
||||
|
||||
subscription: Subscription;
|
||||
|
||||
@ViewChild(NgForm) form: NgForm;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private campaignService: CampaignService) {
|
||||
this.subscription = this.route.params
|
||||
.map(params => params['id'])
|
||||
.filter(id => id !== undefined)
|
||||
.flatMap(id => this.campaignService.getCampaign(id))
|
||||
.subscribe(campaign => {
|
||||
this.campaign = campaign;
|
||||
});
|
||||
}
|
||||
|
||||
saveCampaign() {
|
||||
this.campaignService.submitCampaign(this.campaign)
|
||||
.subscribe(campaign => {
|
||||
this.router.navigate(['../overview/' + campaign._id], {relativeTo: this.route});
|
||||
let redirectSuccessUrl = '../overview/';
|
||||
if (this.campaign._id) {
|
||||
redirectSuccessUrl = '../' + redirectSuccessUrl;
|
||||
}
|
||||
this.router.navigate([redirectSuccessUrl + campaign._id], {relativeTo: this.route});
|
||||
},
|
||||
error => {
|
||||
this.error = error._body.error.message;
|
||||
|
@ -40,5 +54,4 @@ export class CampaignSubmitComponent {
|
|||
this.router.navigate(['..'], {relativeTo: this.route});
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -57,6 +57,10 @@ ngx-datatable {
|
|||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
:host /deep/ .ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* Table Scrollbar BEGIN */
|
||||
|
||||
:host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar {
|
|
@ -0,0 +1,56 @@
|
|||
<div class="highscore-container fade-in">
|
||||
<h2>{{title}} ⟶ Highscore</h2>
|
||||
|
||||
<div class="input-group search-field">
|
||||
<input id="search-tasks"
|
||||
placeholder="Spielername (mehrere mit '&' trennen)"
|
||||
type="text" #query class="form-control"
|
||||
(keyup.enter)="filterPlayers()"
|
||||
[formControl]="searchTerm">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button"
|
||||
(click)="filterPlayers()">
|
||||
Filter
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div *ngFor="let attributeMap of playerAttributeDisplayNames">
|
||||
<ngx-datatable
|
||||
[rows]="players[attributeMap.prop]"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<ngx-datatable-column [width]="valueColWidth" prop="{{attributeMap.prop}}">
|
||||
<ng-template ngx-datatable-header-template let-sort="sortFn">
|
||||
<span class="datatable-header-cell-wrapper">
|
||||
<span class="datatable-header-cell-label text-truncate" title="{{attributeMap.head}}" (click)="sort()">
|
||||
<img src="../../../../assets/scoreboard/{{attributeMap.prop}}.png" alt="{{attributeMap.head}}">
|
||||
</span>
|
||||
</span>
|
||||
</ng-template>
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span style="padding-left: 7px;">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,17 +1,18 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {PlayerService} from '../../services/logs/player.service';
|
||||
import {CampaignService} from '../../services/logs/campaign.service';
|
||||
import {Fraction} from '../../utils/fraction.enum';
|
||||
import {PlayerService} from '../../../services/logs/player.service';
|
||||
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||
import {Fraction} from '../../../utils/fraction.enum';
|
||||
import {FormControl} from '@angular/forms';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {Player} from '../../models/model-interfaces';
|
||||
import {Player} from '../../../models/model-interfaces';
|
||||
import {PlayerUtils} from '../../../utils/player-utils';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'stats-highscore',
|
||||
templateUrl: './highscore.component.html',
|
||||
styleUrls: ['./highscore.component.css', '../../style/list-entry.css', '../../style/overview.css']
|
||||
styleUrls: ['./highscore.component.css', '../../../style/list-entry.css', '../../../style/overview.css']
|
||||
})
|
||||
export class StatisticHighScoreComponent implements OnInit {
|
||||
|
||||
|
@ -27,13 +28,15 @@ export class StatisticHighScoreComponent implements OnInit {
|
|||
|
||||
playersStored = {};
|
||||
|
||||
playerAttributeDisplayNames = PlayerUtils.attributeDisplayNames.slice(2, PlayerUtils.attributeDisplayNames.length);
|
||||
|
||||
cellHeight = 40;
|
||||
|
||||
numberColWidth = 60;
|
||||
|
||||
nameColWidth = 210;
|
||||
|
||||
valueColWidth = 110;
|
||||
valueColWidth = 55;
|
||||
|
||||
emptyMessage = {emptyMessage: 'Keine Einträge'};
|
||||
|
||||
|
@ -84,17 +87,11 @@ export class StatisticHighScoreComponent implements OnInit {
|
|||
if (!this.searchTerm.value || this.searchTerm.value === '') {
|
||||
this.players = this.playersStored;
|
||||
} else {
|
||||
this.players = {
|
||||
kill: this.filterPlayerAttribute('kill'),
|
||||
friendlyFire: this.filterPlayerAttribute('friendlyFire'),
|
||||
vehicleLight: this.filterPlayerAttribute('vehicleLight'),
|
||||
vehicleHeavy: this.filterPlayerAttribute('vehicleLight'),
|
||||
vehicleAir: this.filterPlayerAttribute('vehicleLight'),
|
||||
death: this.filterPlayerAttribute('death'),
|
||||
respawn: this.filterPlayerAttribute('respawn'),
|
||||
revive: this.filterPlayerAttribute('revive'),
|
||||
flagTouch: this.filterPlayerAttribute('flagTouch')
|
||||
};
|
||||
this.players = {};
|
||||
for (let i = 0; i < this.playerAttributeDisplayNames.length; i++) {
|
||||
const attributeProperty = this.playerAttributeDisplayNames[i].prop;
|
||||
this.players[attributeProperty] = this.filterPlayerAttribute(attributeProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,14 +1,14 @@
|
|||
import {Component, Input, OnInit} from '@angular/core';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {CampaignService} from '../../services/logs/campaign.service';
|
||||
import {ChartUtils} from '../../utils/chart-utils';
|
||||
import {Fraction} from '../../utils/fraction.enum';
|
||||
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||
import {ChartUtils} from '../../../utils/chart-utils';
|
||||
import {Fraction} from '../../../utils/fraction.enum';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'stats-overview',
|
||||
templateUrl: './stats-overview.component.html',
|
||||
styleUrls: ['./stats-overview.component.css', '../../style/list-entry.css', '../../style/overview.css']
|
||||
styleUrls: ['./stats-overview.component.css', '../../../style/list-entry.css', '../../../style/overview.css']
|
||||
})
|
||||
export class StatisticOverviewComponent implements OnInit {
|
||||
|
|
@ -1,208 +0,0 @@
|
|||
<div class="highscore-container fade-in">
|
||||
<h2>{{title}} ⟶ Highscore</h2>
|
||||
|
||||
<div class="input-group search-field">
|
||||
<input id="search-tasks"
|
||||
placeholder="Spielername (mehrere mit '&' trennen)"
|
||||
type="text" #query class="form-control"
|
||||
(keyup.enter)="filterPlayers()"
|
||||
[formControl]="searchTerm">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" type="button"
|
||||
(click)="filterPlayers()">
|
||||
Filter
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.kill"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Kills" prop="kill"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.friendlyFire"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="FriendlyFire" prop="friendlyFire"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.death"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Tode" prop="death"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.respawn"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Respawn" prop="respawn"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.revive"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Revive" prop="revive"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.flagTouch"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Eroberung" prop="flagTouch"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.vehicleLight"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Fzg (Light)" prop="vehicleLight"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.vehicleHeavy"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Fzg (Heavy)" prop="vehicleHeavy"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
<ngx-datatable
|
||||
[rows]="players.vehicleAir"
|
||||
[messages]="emptyMessage"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column [width]="numberColWidth" name="#" prop="num"></ngx-datatable-column>
|
||||
<ngx-datatable-column name="Spieler" prop="name" [width]="nameColWidth" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="valueColWidth" name="Fzg (Air)" prop="vehicleAir"></ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
|
||||
</div>
|
||||
|
|
@ -1,16 +1,18 @@
|
|||
import {RouterModule, Routes} from '@angular/router';
|
||||
import {StatisticComponent} from './stats.component';
|
||||
import {WarListComponent} from './war-list/war-list.component';
|
||||
import {StatisticOverviewComponent} from './overview/stats-overview.component';
|
||||
import {WarItemComponent} from './war-list/war-item.component';
|
||||
import {WarListComponent} from './war/war-list/war-list.component';
|
||||
import {StatisticOverviewComponent} from './campaign/overview/stats-overview.component';
|
||||
import {WarItemComponent} from './war/war-list/war-item.component';
|
||||
import {ModuleWithProviders} from '@angular/core';
|
||||
import {CampaignSubmitComponent} from './campaign-submit/campaign-submit.component';
|
||||
import {CampaignPlayerDetailComponent} from './campaign-player-detail/campaign-player-detail.component';
|
||||
import {WarDetailComponent} from './war-detail/war-detail.component';
|
||||
import {ScoreboardComponent} from './war-detail/scoreboard/scoreboard.component';
|
||||
import {WarSubmitComponent} from './war-submit/war-submit.component';
|
||||
import {FractionStatsComponent} from './war-detail/fraction-stats/fraction-stats.component';
|
||||
import {StatisticHighScoreComponent} from './highscore/highscore.component';
|
||||
import {CampaignSubmitComponent} from './campaign/campaign-submit/campaign-submit.component';
|
||||
import {CampaignPlayerDetailComponent} from './campaign/campaign-player-detail/campaign-player-detail.component';
|
||||
import {ScoreboardComponent} from './war/scoreboard/scoreboard.component';
|
||||
import {WarSubmitComponent} from './war/war-submit/war-submit.component';
|
||||
import {FractionStatsComponent} from './war/fraction-stats/fraction-stats.component';
|
||||
import {StatisticHighScoreComponent} from './campaign/highscore/highscore.component';
|
||||
import {WarHeaderComponent} from './war/war-header/war-header.component';
|
||||
import {WarEditComponent} from './war/war-edit/war-edit.component';
|
||||
import {LoginGuardMT} from '../login';
|
||||
|
||||
|
||||
export const statsRoutes: Routes = [{
|
||||
|
@ -32,30 +34,44 @@ export const statsRoutes: Routes = [{
|
|||
component: StatisticHighScoreComponent,
|
||||
outlet: 'right'
|
||||
},
|
||||
{
|
||||
path: 'new-campaign',
|
||||
component: CampaignSubmitComponent,
|
||||
outlet: 'right'
|
||||
},
|
||||
{
|
||||
path: 'new',
|
||||
component: WarSubmitComponent,
|
||||
outlet: 'right'
|
||||
},
|
||||
{
|
||||
path: 'war/:id',
|
||||
component: WarDetailComponent,
|
||||
component: WarHeaderComponent,
|
||||
outlet: 'right'
|
||||
},
|
||||
{
|
||||
path: 'campaign-player/:id/:playerName',
|
||||
component: CampaignPlayerDetailComponent,
|
||||
outlet: 'right'
|
||||
},
|
||||
{
|
||||
path: 'campaign',
|
||||
component: CampaignSubmitComponent,
|
||||
outlet: 'right',
|
||||
canActivate: [LoginGuardMT]
|
||||
},
|
||||
{
|
||||
path: 'campaign/:id',
|
||||
component: CampaignSubmitComponent,
|
||||
outlet: 'right',
|
||||
canActivate: [LoginGuardMT]
|
||||
},
|
||||
{
|
||||
path: 'submit-war',
|
||||
component: WarSubmitComponent,
|
||||
outlet: 'right',
|
||||
canActivate: [LoginGuardMT]
|
||||
},
|
||||
{
|
||||
path: 'submit-war/:id',
|
||||
component: WarEditComponent,
|
||||
outlet: 'right',
|
||||
canActivate: [LoginGuardMT]
|
||||
}];
|
||||
|
||||
export const statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes);
|
||||
|
||||
export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, StatisticHighScoreComponent,
|
||||
CampaignSubmitComponent, WarListComponent, WarSubmitComponent, WarDetailComponent, ScoreboardComponent,
|
||||
FractionStatsComponent, CampaignPlayerDetailComponent, WarItemComponent];
|
||||
CampaignSubmitComponent, WarListComponent, WarSubmitComponent, WarEditComponent, WarHeaderComponent,
|
||||
ScoreboardComponent, FractionStatsComponent, CampaignPlayerDetailComponent, WarItemComponent];
|
||||
|
||||
|
|
|
@ -1,49 +0,0 @@
|
|||
<div class="fade-in" style="overflow-x: auto" xmlns="http://www.w3.org/1999/html">
|
||||
<ngx-datatable
|
||||
[rows]="rows"
|
||||
[sorts]="[{prop: 'kill', dir: 'desc'}]"
|
||||
[reorderable]="reorderable"
|
||||
[messages]="{emptyMessage: 'Loading...'}"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column name="{{tableHead[0]}}" prop="name" [width]="210" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="{{tableHead[1]}}" prop="fraction" [width]="100">
|
||||
<ng-template ngx-datatable-cell-template let-value="value">
|
||||
{{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[2]}}" prop="kill"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[3]}}" prop="friendlyFire"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[4]}}" prop="vehicleLight"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[5]}}" prop="vehicleHeavy"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[6]}}" prop="vehicleAir"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[7]}}" prop="revive"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[8]}}" prop="flagTouch"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[9]}}" prop="death"></ngx-datatable-column>
|
||||
<ngx-datatable-column [width]="70" name="{{tableHead[10]}}" prop="respawn"></ngx-datatable-column>
|
||||
<!--<ngx-datatable-column [width]="80" name="" prop="name">-->
|
||||
<!--<ng-template ngx-datatable-cell-template let-value="value">-->
|
||||
<!--<span class="btn btn-sm btn-default in-table-btn disabled">Detail</span>-->
|
||||
<!--</ng-template>-->
|
||||
<!--</ngx-datatable-column>-->
|
||||
<ngx-datatable-column [width]="80">
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<span class="btn btn-sm btn-default in-table-btn"
|
||||
(click)="selectPlayerDetail(1, isSteamUUID(row['steamUUID']) ? row['steamUUID'] : row['name'])">
|
||||
Gesamt
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
</div>
|
|
@ -45,9 +45,9 @@ export class FractionStatsComponent implements OnInit, OnChanges {
|
|||
|
||||
labelPoints = 'Punkte';
|
||||
labelBudget = 'Budget';
|
||||
labelKill = 'Kills';
|
||||
labelFriendlyFire = 'FriendlyFire';
|
||||
labelVehicle = 'Fahrzeug-Kills';
|
||||
labelKill = 'Abschüsse';
|
||||
labelFriendlyFire = 'Friendly Fire';
|
||||
labelVehicle = 'Fahrzeug Abschüsse';
|
||||
labelTransport = 'Lufttransport';
|
||||
labelRevive = 'Revive';
|
||||
labelStabilize = 'Stabilisiert';
|
|
@ -5,7 +5,7 @@
|
|||
/* ########### DATATABLE ########### */
|
||||
|
||||
ngx-datatable {
|
||||
width: 1040px;
|
||||
width: 940px;
|
||||
margin: auto;
|
||||
height: 68vh;
|
||||
}
|
||||
|
@ -43,6 +43,10 @@ ngx-datatable {
|
|||
background-color: #f7f7f7;
|
||||
}
|
||||
|
||||
:host /deep/ .ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
/* Table Scrollbar BEGIN */
|
||||
:host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar {
|
||||
width: 12px;
|
|
@ -0,0 +1,47 @@
|
|||
<div class="fade-in" style="overflow-x: auto" xmlns="http://www.w3.org/1999/html">
|
||||
<ngx-datatable
|
||||
[rows]="rows"
|
||||
[sorts]="[{prop: 'kill', dir: 'desc'}]"
|
||||
[reorderable]="reorderable"
|
||||
[messages]="{emptyMessage: 'Loading...'}"
|
||||
[headerHeight]="cellHeight"
|
||||
[rowHeight]="cellHeight"
|
||||
[cssClasses]='customClasses'
|
||||
[columnMode]="'force'"
|
||||
[scrollbarV]="true"
|
||||
[selectionType]="'single'">
|
||||
<ngx-datatable-column name="{{tableHead[0].head}}" prop="name" [width]="210" style="padding-left:10px">
|
||||
<ng-template ngx-datatable-cell-template let-row="row" let-value="value">
|
||||
<span class="player-name"
|
||||
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
|
||||
{{value}}
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
<ngx-datatable-column name="{{tableHead[1].head}}" prop="fraction" [width]="90">
|
||||
<ng-template ngx-datatable-cell-template let-value="value">
|
||||
{{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}}
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
|
||||
<div *ngFor="let column of tableHead.slice(2, tableHead.length) ">
|
||||
<ngx-datatable-column [width]="columnWidth" prop="{{column.prop}}">
|
||||
<ng-template ngx-datatable-header-template let-sort="sortFn">
|
||||
<span class="datatable-header-cell-wrapper">
|
||||
<span class="datatable-header-cell-label text-truncate" title="{{column.head}}" (click)="sort()">
|
||||
<img src="../../../../assets/scoreboard/{{column.prop}}.png" alt="{{column.head}}">
|
||||
</span>
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
</div>
|
||||
<ngx-datatable-column [width]="80">
|
||||
<ng-template ngx-datatable-cell-template let-row="row">
|
||||
<span class="btn btn-sm btn-default in-table-btn"
|
||||
(click)="selectPlayerDetail(1, isSteamUUID(row['steamUUID']) ? row['steamUUID'] : row['name'])">
|
||||
Gesamt
|
||||
</span>
|
||||
</ng-template>
|
||||
</ngx-datatable-column>
|
||||
</ngx-datatable>
|
||||
</div>
|
|
@ -19,13 +19,14 @@ export class ScoreboardComponent implements OnChanges {
|
|||
|
||||
@Output() playerTabSwitch = new EventEmitter();
|
||||
|
||||
tableHead = ['Spieler', 'Fraktion', 'Kills', 'FF', 'Fzg(L)', 'Fzg(H)', 'Fzg(A)',
|
||||
'Revive', 'Flagge', 'Tod', 'Respawn'];
|
||||
tableHead = PlayerUtils.attributeDisplayNames;
|
||||
|
||||
isSteamUUID = PlayerUtils.isSteamUUID;
|
||||
|
||||
cellHeight = 40;
|
||||
|
||||
columnWidth = 65;
|
||||
|
||||
rows = [];
|
||||
|
||||
reorderable = false;
|
|
@ -0,0 +1,85 @@
|
|||
<form #form="ngForm" class="overview">
|
||||
<h3>Schlacht bearbeiten</h3>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title">Titel</label>
|
||||
<input type="text" class="form-control"
|
||||
[(ngModel)]="war.title"
|
||||
name="title"
|
||||
id="title"
|
||||
required maxlength="50"/>
|
||||
<show-error displayName="Name" controlPath="title"></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 campaignService.campaigns" [ngValue]="campaign._id">
|
||||
{{campaign.title}}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ptBlufor">Punkte NATO</label>
|
||||
<input type="number" class="form-control"
|
||||
[(ngModel)]="war.ptBlufor"
|
||||
name="ptBlufor"
|
||||
id="ptBlufor"
|
||||
required min="0"/>
|
||||
<show-error displayName="Name" controlPath="ptBlufor"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="ptOpfor">Punkte CSAT</label>
|
||||
<input type="number" class="form-control"
|
||||
[(ngModel)]="war.ptOpfor"
|
||||
name="ptOpfor"
|
||||
id="ptOpfor"
|
||||
required min="0"/>
|
||||
<show-error displayName="Name" controlPath="ptOpfor"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="endBudgetBlufor">Endbudget NATO</label>
|
||||
<input type="number" class="form-control"
|
||||
[(ngModel)]="war.endBudgetBlufor"
|
||||
name="endBudgetBlufor"
|
||||
id="endBudgetBlufor"
|
||||
required/>
|
||||
<show-error displayName="Name" controlPath="endBudgetBlufor"></show-error>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="endBudgetOpfor">Endbudget CSAT</label>
|
||||
<input type="number" class="form-control"
|
||||
[(ngModel)]="war.endBudgetOpfor"
|
||||
name="endBudgetOpfor"
|
||||
id="endBudgetOpfor"
|
||||
required/>
|
||||
<show-error displayName="Name" controlPath="endBudgetOpfor"></show-error>
|
||||
</div>
|
||||
|
||||
<button id="cancel"
|
||||
(click)="cancel()"
|
||||
class="btn btn-default">
|
||||
Abbrechen
|
||||
</button>
|
||||
|
||||
<button id="save"
|
||||
(click)="updateWar()"
|
||||
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>
|
|
@ -0,0 +1,56 @@
|
|||
import {Component, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {NgForm} from '@angular/forms';
|
||||
import {WarService} from '../../../services/logs/war.service';
|
||||
import {War} from '../../../models/model-interfaces';
|
||||
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||
import {Subscription} from 'rxjs/Subscription';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'war-edit',
|
||||
templateUrl: './war-edit.component.html',
|
||||
styleUrls: ['./war-edit.component.css', '../../../style/load-indicator.css',
|
||||
'../../../style/entry-form.css', '../../../style/overview.css']
|
||||
})
|
||||
export class WarEditComponent {
|
||||
|
||||
war: War = {players: []};
|
||||
|
||||
subscription: Subscription;
|
||||
|
||||
showErrorLabel = false;
|
||||
|
||||
error;
|
||||
|
||||
@ViewChild(NgForm) form: NgForm;
|
||||
|
||||
constructor(private route: ActivatedRoute,
|
||||
private router: Router,
|
||||
private warService: WarService,
|
||||
public campaignService: CampaignService) {
|
||||
this.subscription = this.route.params
|
||||
.map(params => params['id'])
|
||||
.filter(id => id !== undefined)
|
||||
.flatMap(id => this.warService.getWar(id))
|
||||
.subscribe(war => {
|
||||
this.war = war;
|
||||
});
|
||||
}
|
||||
|
||||
updateWar() {
|
||||
this.warService.updateWar(this.war)
|
||||
.subscribe(war => {
|
||||
this.router.navigate(['../../war/' + war._id], {relativeTo: this.route});
|
||||
},
|
||||
error => {
|
||||
this.error = error._body.error.message;
|
||||
this.showErrorLabel = true;
|
||||
});
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.router.navigate(['..'], {relativeTo: this.route});
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ span.tab-control {
|
|||
}
|
||||
|
||||
.nav-tabs {
|
||||
width: 980px;
|
||||
width: 920px;
|
||||
margin: auto;
|
||||
clear: both;
|
||||
border-bottom: 0;
|
|
@ -1,19 +1,19 @@
|
|||
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute} from '@angular/router';
|
||||
import {WarService} from '../../services/logs/war.service';
|
||||
import {War} from '../../models/model-interfaces';
|
||||
import {ChartUtils} from '../../utils/chart-utils';
|
||||
import {Fraction} from '../../utils/fraction.enum';
|
||||
import {LogsService} from '../../services/logs/logs.service';
|
||||
import {ScoreboardComponent} from './scoreboard/scoreboard.component';
|
||||
import {WarService} from '../../../services/logs/war.service';
|
||||
import {War} from '../../../models/model-interfaces';
|
||||
import {ChartUtils} from '../../../utils/chart-utils';
|
||||
import {Fraction} from '../../../utils/fraction.enum';
|
||||
import {LogsService} from '../../../services/logs/logs.service';
|
||||
import {ScoreboardComponent} from '../scoreboard/scoreboard.component';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'war-detail',
|
||||
templateUrl: './war-detail.component.html',
|
||||
styleUrls: ['./war-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css']
|
||||
templateUrl: './war-header.component.html',
|
||||
styleUrls: ['./war-header.component.css', '../../../style/list-entry.css', '../../../style/hide-scrollbar.css']
|
||||
})
|
||||
export class WarDetailComponent implements OnInit {
|
||||
export class WarHeaderComponent implements OnInit {
|
||||
|
||||
readonly fraction = Fraction;
|
||||
|
|
@ -13,6 +13,10 @@
|
|||
<span (click)="delete(); $event.stopPropagation()"
|
||||
title="Löschen"
|
||||
class="glyphicon glyphicon-trash trash"></span>
|
||||
<span (click)="edit(); $event.stopPropagation()"
|
||||
style="padding-right: 10px;"
|
||||
title="Bearbeiten"
|
||||
class="glyphicon glyphicon-edit trash"></span>
|
||||
</div>
|
||||
|
||||
</div>
|
|
@ -1,11 +1,11 @@
|
|||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||
import {War} from '../../models/model-interfaces';
|
||||
import {LoginService} from '../../services/app-user-service/login-service';
|
||||
import {War} from '../../../models/model-interfaces';
|
||||
import {LoginService} from '../../../services/app-user-service/login-service';
|
||||
|
||||
@Component({
|
||||
selector: 'pjm-war-item',
|
||||
templateUrl: './war-item.component.html',
|
||||
styleUrls: ['./war-item.component.css', '../../style/list-entry.css'],
|
||||
styleUrls: ['./war-item.component.css', '../../../style/list-entry.css'],
|
||||
changeDetection: ChangeDetectionStrategy.OnPush
|
||||
})
|
||||
export class WarItemComponent implements OnInit {
|
||||
|
@ -16,6 +16,8 @@ export class WarItemComponent implements OnInit {
|
|||
|
||||
@Output() warSelected = new EventEmitter();
|
||||
|
||||
@Output() warEdit = new EventEmitter();
|
||||
|
||||
@Output() warDelete = new EventEmitter();
|
||||
|
||||
constructor(public loginService: LoginService) {
|
||||
|
@ -28,6 +30,10 @@ export class WarItemComponent implements OnInit {
|
|||
this.warSelected.emit(this.war._id);
|
||||
}
|
||||
|
||||
edit() {
|
||||
this.warEdit.emit(this.war._id);
|
||||
}
|
||||
|
||||
delete() {
|
||||
this.warDelete.emit(this.war);
|
||||
}
|
|
@ -11,13 +11,18 @@
|
|||
<accordion *ngFor="let campaign of campaigns; let isFirstRow=first">
|
||||
<accordion-group [isOpen]="isFirstRow">
|
||||
<div accordion-heading>
|
||||
{{campaign.title}}
|
||||
<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"
|
||||
<span (click)="editCampaign(campaign); $event.stopPropagation()" title="Bearbeiten"
|
||||
style="color: whitesmoke; padding-top: 0; padding-right: 10px;"
|
||||
class="glyphicon glyphicon-edit trash pull-left"
|
||||
*ngIf="loginService.hasPermission(3)">
|
||||
</span>
|
||||
<span (click)="deleteCampaign(campaign); $event.stopPropagation()" title="Löschen"
|
||||
style="color: whitesmoke; padding-top: 0; padding-right: 10px;"
|
||||
class="glyphicon glyphicon-trash trash pull-left"
|
||||
*ngIf="loginService.hasPermission(3)">
|
||||
</span>
|
||||
{{campaign.title}}
|
||||
<span class="pull-right">▼</span>
|
||||
</div>
|
||||
|
||||
<div class="fade-in list-entry top-list-entry"
|
||||
|
@ -42,6 +47,7 @@
|
|||
<div *ngFor="let war of campaign.wars">
|
||||
<pjm-war-item
|
||||
[war]="war"
|
||||
(warEdit)="editWar($event)"
|
||||
(warDelete)="deleteWar(war)"
|
||||
(warSelected)="selectWar($event)"
|
||||
[selected]="war._id == selectedWarId">
|
|
@ -1,15 +1,15 @@
|
|||
import {Component, OnInit} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {Campaign, War} from '../../models/model-interfaces';
|
||||
import {WarService} from '../../services/logs/war.service';
|
||||
import {LoginService} from '../../services/app-user-service/login-service';
|
||||
import {CampaignService} from '../../services/logs/campaign.service';
|
||||
import {RouteConfig} from '../../app.config';
|
||||
import {Campaign, War} from '../../../models/model-interfaces';
|
||||
import {WarService} from '../../../services/logs/war.service';
|
||||
import {LoginService} from '../../../services/app-user-service/login-service';
|
||||
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||
import {RouteConfig} from '../../../app.config';
|
||||
|
||||
@Component({
|
||||
selector: 'war-list',
|
||||
templateUrl: './war-list.component.html',
|
||||
styleUrls: ['./war-list.component.css', '../../style/list-entry.css', '../../style/select-list.css']
|
||||
styleUrls: ['./war-list.component.css', '../../../style/list-entry.css', '../../../style/select-list.css']
|
||||
})
|
||||
export class WarListComponent implements OnInit {
|
||||
|
||||
|
@ -46,12 +46,7 @@ export class WarListComponent implements OnInit {
|
|||
|
||||
selectNewCampaign() {
|
||||
this.selectedWarId = null;
|
||||
this.router.navigate([{outlets: {'right': ['new-campaign']}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
selectNewWar() {
|
||||
this.selectedWarId = null;
|
||||
this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route});
|
||||
this.router.navigate([{outlets: {'right': ['campaign']}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
selectWar(warId) {
|
||||
|
@ -75,6 +70,16 @@ export class WarListComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
selectNewWar() {
|
||||
this.selectedWarId = null;
|
||||
this.router.navigate([{outlets: {'right': ['submit-war']}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
editWar(warId) {
|
||||
this.selectedWarId = warId;
|
||||
this.router.navigate([{outlets: {'right': ['submit-war', warId]}}], {relativeTo: this.route});
|
||||
}
|
||||
|
||||
deleteWar(war: War) {
|
||||
if (confirm('Soll die Schlacht ' + war.title + ' wirklich gelöscht werden?')) {
|
||||
this.warService.deleteWar(war._id)
|
||||
|
@ -82,7 +87,9 @@ export class WarListComponent implements OnInit {
|
|||
if (this.selectedWarId === war._id) {
|
||||
this.selectOverview('all');
|
||||
}
|
||||
this.campaigns.splice(this.campaigns.indexOf(war), 1);
|
||||
this.campaigns.forEach(campaign => {
|
||||
campaign.wars.splice(campaign.wars.indexOf(war), 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -99,4 +106,7 @@ export class WarListComponent implements OnInit {
|
|||
}
|
||||
}
|
||||
|
||||
editCampaign(selectCampaign) {
|
||||
this.router.navigate([{outlets: {'right': ['campaign', selectCampaign._id]}}], {relativeTo: this.route});
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@
|
|||
<label for="log">Logfile</label>
|
||||
<input id="log" name="log" class="ui-button form-control" type="file"
|
||||
(change)="fileChange($event)">
|
||||
<span class="label label-bg label-danger center-block" style="font-size:small" *ngIf="showImageError">
|
||||
<span class="label label-bg label-danger center-block" style="font-size:small" *ngIf="showFileError">
|
||||
Logfile muss im Format RPT, LOG oder TXT vorliegen
|
||||
</span>
|
||||
</div>
|
|
@ -1,16 +1,16 @@
|
|||
import {Component, ViewChild} from '@angular/core';
|
||||
import {ActivatedRoute, Router} from '@angular/router';
|
||||
import {NgForm} from '@angular/forms';
|
||||
import {WarService} from '../../services/logs/war.service';
|
||||
import {War} from '../../models/model-interfaces';
|
||||
import {CampaignService} from '../../services/logs/campaign.service';
|
||||
import {WarService} from '../../../services/logs/war.service';
|
||||
import {War} from '../../../models/model-interfaces';
|
||||
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'war-submit',
|
||||
templateUrl: './war-submit.component.html',
|
||||
styleUrls: ['./war-submit.component.css', '../../style/load-indicator.css',
|
||||
'../../style/entry-form.css', '../../style/overview.css']
|
||||
styleUrls: ['./war-submit.component.css', '../../../style/load-indicator.css',
|
||||
'../../../style/entry-form.css', '../../../style/overview.css']
|
||||
})
|
||||
export class WarSubmitComponent {
|
||||
|
||||
|
@ -18,7 +18,9 @@ export class WarSubmitComponent {
|
|||
|
||||
fileList: FileList;
|
||||
|
||||
showImageError = false;
|
||||
readonly validExtensions = ['.rpt', '.log', '.txt'];
|
||||
|
||||
showFileError = false;
|
||||
|
||||
showErrorLabel = false;
|
||||
|
||||
|
@ -35,14 +37,13 @@ export class WarSubmitComponent {
|
|||
}
|
||||
|
||||
fileChange(event) {
|
||||
if (!event.target.files[0].name.endsWith('.rpt')
|
||||
&& !event.target.files[0].name.endsWith('.log')
|
||||
&& !event.target.files[0].name.endsWith('.txt')) {
|
||||
this.showImageError = true;
|
||||
this.fileList = undefined;
|
||||
} else {
|
||||
this.showImageError = false;
|
||||
if (this.validExtensions.filter(ext => event.target.files[0] &&
|
||||
event.target.files[0].name.endsWith(ext)).length === 1) {
|
||||
this.showFileError = false;
|
||||
this.fileList = event.target.files;
|
||||
} else {
|
||||
this.showFileError = true;
|
||||
this.fileList = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,5 +70,4 @@ export class WarSubmitComponent {
|
|||
this.router.navigate(['..'], {relativeTo: this.route});
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,19 @@
|
|||
export class PlayerUtils {
|
||||
|
||||
public static readonly attributeDisplayNames = [
|
||||
{prop: 'name', head: 'Spieler'},
|
||||
{prop: 'fraction', head: 'Fraktion'},
|
||||
{prop: 'kill', head: 'Abschüsse'},
|
||||
{prop: 'friendlyFire', head: 'Friendly Fire'},
|
||||
{prop: 'revive', head: 'Revive'},
|
||||
{prop: 'flagTouch', head: 'Eroberungen'},
|
||||
{prop: 'vehicleLight', head: 'Fahrzeug (leicht)'},
|
||||
{prop: 'vehicleHeavy', head: 'Fahrzeug (schwer)'},
|
||||
{prop: 'vehicleAir', head: 'Fahrzeug (Luft)'},
|
||||
{prop: 'death', head: 'Tode'},
|
||||
{prop: 'respawn', head: 'Respawn'}
|
||||
];
|
||||
|
||||
public static isSteamUUID(input: string): boolean {
|
||||
const steamUIDPattern = new RegExp('[0-9]{17}');
|
||||
return steamUIDPattern.test(input);
|
||||
|
|
After Width: | Height: | Size: 659 B |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 678 B |
After Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 716 B |
After Width: | Height: | Size: 567 B |
After Width: | Height: | Size: 498 B |
After Width: | Height: | Size: 546 B |