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":"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":"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":"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":"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 --------------------###
|
###------------------- 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` ###
|
### 2. import data by executing script: `./populate-data.sh` ###
|
||||||
### 3. change data in app as you need for tests ###
|
### 3. change data in app as you need for tests ###
|
||||||
### 4. export data state with: `./populate-data.sh -m save` ###
|
### 4. export data state with: `./populate-data.sh -m save` ###
|
||||||
|
|
|
@ -24,6 +24,25 @@ Create a new campaign
|
||||||
|
|
||||||
+ Attributes (Campaign, fixed-type)
|
+ 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 Campaign [DELETE /campaigns/{id}]
|
||||||
|
|
||||||
Delete a campaign
|
Delete a campaign
|
||||||
|
|
|
@ -76,6 +76,35 @@ Create a new war
|
||||||
|
|
||||||
+ Attributes (War, fixed-type)
|
+ 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 War [DELETE /wars/{id}]
|
||||||
|
|
||||||
Delete a war
|
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 CampaignModel = require('../models/campaign');
|
||||||
const WarModel = require('../models/war');
|
const WarModel = require('../models/war');
|
||||||
|
|
||||||
|
// util
|
||||||
|
const genericGetById = require('./_generic').genericGetById;
|
||||||
|
const genericPatch = require('./_generic').genericPatch;
|
||||||
|
|
||||||
const campaigns = new express.Router();
|
const campaigns = new express.Router();
|
||||||
|
|
||||||
// routes **********************
|
// routes **********************
|
||||||
campaigns.route('/')
|
campaigns.route('/')
|
||||||
|
|
||||||
.post(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
.post(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||||
const campaign = new CampaignModel(req.body);
|
const campaign = new CampaignModel(req.body);
|
||||||
// timestamp and default are set automatically by Mongoose Schema Validation
|
// timestamp and default are set automatically by Mongoose Schema Validation
|
||||||
|
@ -43,18 +45,11 @@ campaigns.route('/')
|
||||||
|
|
||||||
campaigns.route('/:id')
|
campaigns.route('/:id')
|
||||||
.get(idValidator, (req, res, next) => {
|
.get(idValidator, (req, res, next) => {
|
||||||
CampaignModel.findById(req.params.id, (err, item) => {
|
return genericGetById(req, res, next, CampaignModel);
|
||||||
if (err) {
|
})
|
||||||
err.status = codes.servererror;
|
|
||||||
return next(err);
|
.patch(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||||
} else if (!item) {
|
return genericPatch(req, res, next, CampaignModel);
|
||||||
err = new Error('item not found');
|
|
||||||
err.status = codes.notfound;
|
|
||||||
return next(err);
|
|
||||||
}
|
|
||||||
res.locals.items = item;
|
|
||||||
return next();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.delete((req, res, next) => {
|
.delete((req, res, next) => {
|
||||||
|
|
|
@ -21,6 +21,9 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca
|
||||||
const DecorationModel = require('../models/decoration');
|
const DecorationModel = require('../models/decoration');
|
||||||
const AwardingsModel = require('../models/awarding');
|
const AwardingsModel = require('../models/awarding');
|
||||||
|
|
||||||
|
// util
|
||||||
|
const genericGetById = require('./_generic').genericGetById;
|
||||||
|
|
||||||
const decoration = new express.Router();
|
const decoration = new express.Router();
|
||||||
|
|
||||||
// routes **********************
|
// routes **********************
|
||||||
|
@ -81,18 +84,7 @@ decoration.route('/')
|
||||||
|
|
||||||
decoration.route('/:id')
|
decoration.route('/:id')
|
||||||
.get(idValidator, (req, res, next) => {
|
.get(idValidator, (req, res, next) => {
|
||||||
DecorationModel.findById(req.params.id, (err, item) => {
|
return genericGetById(req, res, next, DecorationModel);
|
||||||
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();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
||||||
|
|
|
@ -20,6 +20,9 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca
|
||||||
// Mongoose Model using mongoDB
|
// Mongoose Model using mongoDB
|
||||||
const RankModel = require('../models/rank');
|
const RankModel = require('../models/rank');
|
||||||
|
|
||||||
|
// util
|
||||||
|
const genericGetById = require('./_generic').genericGetById;
|
||||||
|
|
||||||
const ranks = new express.Router();
|
const ranks = new express.Router();
|
||||||
|
|
||||||
// routes **********************
|
// routes **********************
|
||||||
|
@ -73,18 +76,7 @@ ranks.route('/')
|
||||||
|
|
||||||
ranks.route('/:id')
|
ranks.route('/:id')
|
||||||
.get(idValidator, (req, res, next) => {
|
.get(idValidator, (req, res, next) => {
|
||||||
RankModel.findById(req.params.id, (err, item) => {
|
return genericGetById(req, res, next, RankModel);
|
||||||
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();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
||||||
|
|
|
@ -20,6 +20,9 @@ const resourceLocation = require('../middleware/resource-location').resourceLoca
|
||||||
// Mongoose Model using mongoDB
|
// Mongoose Model using mongoDB
|
||||||
const SquadModel = require('../models/squad');
|
const SquadModel = require('../models/squad');
|
||||||
|
|
||||||
|
// util
|
||||||
|
const genericGetById = require('./_generic').genericGetById;
|
||||||
|
|
||||||
const squads = new express.Router();
|
const squads = new express.Router();
|
||||||
|
|
||||||
// routes **********************
|
// routes **********************
|
||||||
|
@ -77,18 +80,7 @@ squads.route('/')
|
||||||
|
|
||||||
squads.route('/:id')
|
squads.route('/:id')
|
||||||
.get(idValidator, (req, res, next) => {
|
.get(idValidator, (req, res, next) => {
|
||||||
SquadModel.findById(req.params.id, (err, item) => {
|
return genericGetById(req, res, next, SquadModel);
|
||||||
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();
|
|
||||||
});
|
|
||||||
})
|
})
|
||||||
|
|
||||||
.patch(apiAuthenticationMiddleware, checkHl, upload.single('image'), (req, res, next) => {
|
.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 LogBudgetModel = require('../models/logs/budget');
|
||||||
const LogPointsModel = require('../models/logs/points');
|
const LogPointsModel = require('../models/logs/points');
|
||||||
|
|
||||||
|
// util
|
||||||
|
const genericPatch = require('./_generic').genericPatch;
|
||||||
|
|
||||||
const wars = new express.Router();
|
const wars = new express.Router();
|
||||||
|
|
||||||
// routes **********************
|
// 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) => {
|
.delete(apiAuthenticationMiddleware, checkMT, (req, res, next) => {
|
||||||
WarModel.findByIdAndRemove(req.params.id, (err, item) => {
|
WarModel.findByIdAndRemove(req.params.id, (err, item) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
|
|
|
@ -106,6 +106,12 @@ const parseWarLog = (lineArray, war) => {
|
||||||
stats.war['endBudgetBlufor'] = transformMoneyString(budg[9]);
|
stats.war['endBudgetBlufor'] = transformMoneyString(budg[9]);
|
||||||
stats.war['endBudgetOpfor'] = transformMoneyString(budg[12].slice(0, -2));
|
stats.war['endBudgetOpfor'] = transformMoneyString(budg[12].slice(0, -2));
|
||||||
stats.war.endDate = getFullTimeDate(war.date, budg[5]);
|
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 {
|
} else {
|
||||||
stats.budget.push(getBudgetEntry(budg, war._id, war.date));
|
stats.budget.push(getBudgetEntry(budg, war._id, war.date));
|
||||||
}
|
}
|
||||||
|
@ -140,13 +146,6 @@ const parseWarLog = (lineArray, war) => {
|
||||||
} else {
|
} else {
|
||||||
stats.points.push(getPointsEntry(pt, line, war._id, war.date));
|
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)')) {
|
} else if (line.includes('(Revive)')) {
|
||||||
/**
|
/**
|
||||||
* REVIVE
|
* REVIVE
|
||||||
|
|
|
@ -137,48 +137,7 @@ let addDecorationsAndSave = (userId, loadedImage, res, next) => {
|
||||||
return next(err);
|
return next(err);
|
||||||
}
|
}
|
||||||
if (awardings.length > 0) {
|
if (awardings.length > 0) {
|
||||||
// TODO: simplify this sorting hell
|
awardings.sort((a1, a2) => sortAwardingsForSignature(a1, a2));
|
||||||
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;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// use synchronized call to keep correct order of decorations
|
// use synchronized call to keep correct order of decorations
|
||||||
async.eachSeries(awardings, (award, callback) => {
|
async.eachSeries(awardings, (award, callback) => {
|
||||||
|
@ -262,5 +221,47 @@ let saveJimpImageAndCompress = (image, userId, res, next) => {
|
||||||
}, 3000);
|
}, 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;
|
module.exports = createSignature;
|
||||||
|
|
|
@ -39,7 +39,6 @@ const timeStringToDecimal = (timeString) => {
|
||||||
return hour + (sek / 3600);
|
return hour + (sek / 3600);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const decimalToTimeString = (decimal) => {
|
const decimalToTimeString = (decimal) => {
|
||||||
const hours = parseInt(decimal.toString().split('.')[0]);
|
const hours = parseInt(decimal.toString().split('.')[0]);
|
||||||
const minutesFloat = ((decimal % 1) * 3600) / 60;
|
const minutesFloat = ((decimal % 1) * 3600) / 60;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
<option name="RIGHT_MARGIN" value="120" />
|
<option name="RIGHT_MARGIN" value="120" />
|
||||||
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
<option name="KEEP_FIRST_COLUMN_COMMENT" value="false" />
|
||||||
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
||||||
|
<option name="SPACE_WITHIN_BRACKETS" value="true" />
|
||||||
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
<option name="CALL_PARAMETERS_WRAP" value="1" />
|
||||||
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
<option name="METHOD_PARAMETERS_WRAP" value="1" />
|
||||||
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
<option name="EXTENDS_KEYWORD_WRAP" value="1" />
|
||||||
|
@ -21,4 +22,4 @@
|
||||||
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
<option name="ALIGN_MULTILINE_CHAINED_METHODS" value="true" />
|
||||||
<option name="WRAP_COMMENTS" value="true" />
|
<option name="WRAP_COMMENTS" value="true" />
|
||||||
</codeStyleSettings>
|
</codeStyleSettings>
|
||||||
</code_scheme>
|
</code_scheme>
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "opt-cc",
|
"name": "opt-cc",
|
||||||
"version": "1.7.3",
|
"version": "1.7.4",
|
||||||
"author": "Florian Hartwich <hardi@noarch.de>",
|
"author": "Florian Hartwich <hardi@noarch.de>",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import {RouterModule, Routes} from '@angular/router';
|
import {RouterModule, Routes} from '@angular/router';
|
||||||
import {LoginComponent} from './login/index';
|
import {NotFoundComponent} from './common/not-found';
|
||||||
import {NotFoundComponent} from './common/not-found/not-found.component';
|
import {LoginComponent, LoginGuardAdmin, LoginGuardHL, LoginGuardMT} from './login';
|
||||||
import {LoginGuardAdmin, LoginGuardHL} from './login/login.guard';
|
|
||||||
import {armyRoutes, armyRoutingComponents} from './army/army.routing';
|
import {armyRoutes, armyRoutingComponents} from './army/army.routing';
|
||||||
import {SignupComponent} from './login/signup.component';
|
import {SignupComponent} from './login/signup.component';
|
||||||
import {RouteConfig} from './app.config';
|
import {RouteConfig} from './app.config';
|
||||||
|
@ -72,4 +71,4 @@ export const appRouting = RouterModule.forRoot(appRoutes);
|
||||||
|
|
||||||
export const routingComponents = [...armyRoutingComponents, LoginComponent, SignupComponent, NotFoundComponent];
|
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
|
<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!
|
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>
|
target="_blank">HardiReady</a>
|
||||||
senden, in welcher der 'geheime Text' steht, den du bei der Registrierung nutzt.<br>
|
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.
|
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) {
|
submitCampaign(campaign: Campaign) {
|
||||||
return this.http.post(this.config.apiCampaignPath, campaign)
|
if (campaign._id) {
|
||||||
.map(res => res.json());
|
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) {
|
deleteCampaign(id: string) {
|
||||||
|
@ -27,5 +32,9 @@ export class CampaignService {
|
||||||
.map(res => res.json());
|
.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());
|
.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">
|
<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">
|
<div class="form-group">
|
||||||
<label for="title">Titel</label>
|
<label for="title">Titel</label>
|
|
@ -1,14 +1,15 @@
|
||||||
import {Component, ViewChild} from '@angular/core';
|
import {Component, ViewChild} from '@angular/core';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {NgForm} from '@angular/forms';
|
import {NgForm} from '@angular/forms';
|
||||||
import {Campaign} from '../../models/model-interfaces';
|
import {Subscription} from 'rxjs/Subscription';
|
||||||
import {CampaignService} from '../../services/logs/campaign.service';
|
import {Campaign} from '../../../models/model-interfaces';
|
||||||
|
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'campaign-submit',
|
selector: 'campaign-submit',
|
||||||
templateUrl: './campaign-submit.component.html',
|
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 {
|
export class CampaignSubmitComponent {
|
||||||
|
|
||||||
|
@ -18,17 +19,30 @@ export class CampaignSubmitComponent {
|
||||||
|
|
||||||
error;
|
error;
|
||||||
|
|
||||||
|
subscription: Subscription;
|
||||||
|
|
||||||
@ViewChild(NgForm) form: NgForm;
|
@ViewChild(NgForm) form: NgForm;
|
||||||
|
|
||||||
constructor(private route: ActivatedRoute,
|
constructor(private route: ActivatedRoute,
|
||||||
private router: Router,
|
private router: Router,
|
||||||
private campaignService: CampaignService) {
|
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() {
|
saveCampaign() {
|
||||||
this.campaignService.submitCampaign(this.campaign)
|
this.campaignService.submitCampaign(this.campaign)
|
||||||
.subscribe(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 => {
|
error => {
|
||||||
this.error = error._body.error.message;
|
this.error = error._body.error.message;
|
||||||
|
@ -40,5 +54,4 @@ export class CampaignSubmitComponent {
|
||||||
this.router.navigate(['..'], {relativeTo: this.route});
|
this.router.navigate(['..'], {relativeTo: this.route});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -57,6 +57,10 @@ ngx-datatable {
|
||||||
background-color: #f7f7f7;
|
background-color: #f7f7f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host /deep/ .ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
/* Table Scrollbar BEGIN */
|
/* Table Scrollbar BEGIN */
|
||||||
|
|
||||||
:host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar {
|
: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 {Component, Input, OnInit} from '@angular/core';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
import {PlayerService} from '../../services/logs/player.service';
|
import {PlayerService} from '../../../services/logs/player.service';
|
||||||
import {CampaignService} from '../../services/logs/campaign.service';
|
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||||
import {Fraction} from '../../utils/fraction.enum';
|
import {Fraction} from '../../../utils/fraction.enum';
|
||||||
import {FormControl} from '@angular/forms';
|
import {FormControl} from '@angular/forms';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import {Player} from '../../models/model-interfaces';
|
import {Player} from '../../../models/model-interfaces';
|
||||||
|
import {PlayerUtils} from '../../../utils/player-utils';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stats-highscore',
|
selector: 'stats-highscore',
|
||||||
templateUrl: './highscore.component.html',
|
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 {
|
export class StatisticHighScoreComponent implements OnInit {
|
||||||
|
|
||||||
|
@ -27,13 +28,15 @@ export class StatisticHighScoreComponent implements OnInit {
|
||||||
|
|
||||||
playersStored = {};
|
playersStored = {};
|
||||||
|
|
||||||
|
playerAttributeDisplayNames = PlayerUtils.attributeDisplayNames.slice(2, PlayerUtils.attributeDisplayNames.length);
|
||||||
|
|
||||||
cellHeight = 40;
|
cellHeight = 40;
|
||||||
|
|
||||||
numberColWidth = 60;
|
numberColWidth = 60;
|
||||||
|
|
||||||
nameColWidth = 210;
|
nameColWidth = 210;
|
||||||
|
|
||||||
valueColWidth = 110;
|
valueColWidth = 55;
|
||||||
|
|
||||||
emptyMessage = {emptyMessage: 'Keine Einträge'};
|
emptyMessage = {emptyMessage: 'Keine Einträge'};
|
||||||
|
|
||||||
|
@ -84,17 +87,11 @@ export class StatisticHighScoreComponent implements OnInit {
|
||||||
if (!this.searchTerm.value || this.searchTerm.value === '') {
|
if (!this.searchTerm.value || this.searchTerm.value === '') {
|
||||||
this.players = this.playersStored;
|
this.players = this.playersStored;
|
||||||
} else {
|
} else {
|
||||||
this.players = {
|
this.players = {};
|
||||||
kill: this.filterPlayerAttribute('kill'),
|
for (let i = 0; i < this.playerAttributeDisplayNames.length; i++) {
|
||||||
friendlyFire: this.filterPlayerAttribute('friendlyFire'),
|
const attributeProperty = this.playerAttributeDisplayNames[i].prop;
|
||||||
vehicleLight: this.filterPlayerAttribute('vehicleLight'),
|
this.players[attributeProperty] = this.filterPlayerAttribute(attributeProperty);
|
||||||
vehicleHeavy: this.filterPlayerAttribute('vehicleLight'),
|
}
|
||||||
vehicleAir: this.filterPlayerAttribute('vehicleLight'),
|
|
||||||
death: this.filterPlayerAttribute('death'),
|
|
||||||
respawn: this.filterPlayerAttribute('respawn'),
|
|
||||||
revive: this.filterPlayerAttribute('revive'),
|
|
||||||
flagTouch: this.filterPlayerAttribute('flagTouch')
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import {Component, Input, OnInit} from '@angular/core';
|
import {Component, Input, OnInit} from '@angular/core';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
import {CampaignService} from '../../services/logs/campaign.service';
|
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||||
import {ChartUtils} from '../../utils/chart-utils';
|
import {ChartUtils} from '../../../utils/chart-utils';
|
||||||
import {Fraction} from '../../utils/fraction.enum';
|
import {Fraction} from '../../../utils/fraction.enum';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'stats-overview',
|
selector: 'stats-overview',
|
||||||
templateUrl: './stats-overview.component.html',
|
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 {
|
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 {RouterModule, Routes} from '@angular/router';
|
||||||
import {StatisticComponent} from './stats.component';
|
import {StatisticComponent} from './stats.component';
|
||||||
import {WarListComponent} from './war-list/war-list.component';
|
import {WarListComponent} from './war/war-list/war-list.component';
|
||||||
import {StatisticOverviewComponent} from './overview/stats-overview.component';
|
import {StatisticOverviewComponent} from './campaign/overview/stats-overview.component';
|
||||||
import {WarItemComponent} from './war-list/war-item.component';
|
import {WarItemComponent} from './war/war-list/war-item.component';
|
||||||
import {ModuleWithProviders} from '@angular/core';
|
import {ModuleWithProviders} from '@angular/core';
|
||||||
import {CampaignSubmitComponent} from './campaign-submit/campaign-submit.component';
|
import {CampaignSubmitComponent} from './campaign/campaign-submit/campaign-submit.component';
|
||||||
import {CampaignPlayerDetailComponent} from './campaign-player-detail/campaign-player-detail.component';
|
import {CampaignPlayerDetailComponent} from './campaign/campaign-player-detail/campaign-player-detail.component';
|
||||||
import {WarDetailComponent} from './war-detail/war-detail.component';
|
import {ScoreboardComponent} from './war/scoreboard/scoreboard.component';
|
||||||
import {ScoreboardComponent} from './war-detail/scoreboard/scoreboard.component';
|
import {WarSubmitComponent} from './war/war-submit/war-submit.component';
|
||||||
import {WarSubmitComponent} from './war-submit/war-submit.component';
|
import {FractionStatsComponent} from './war/fraction-stats/fraction-stats.component';
|
||||||
import {FractionStatsComponent} from './war-detail/fraction-stats/fraction-stats.component';
|
import {StatisticHighScoreComponent} from './campaign/highscore/highscore.component';
|
||||||
import {StatisticHighScoreComponent} from './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 = [{
|
export const statsRoutes: Routes = [{
|
||||||
|
@ -32,30 +34,44 @@ export const statsRoutes: Routes = [{
|
||||||
component: StatisticHighScoreComponent,
|
component: StatisticHighScoreComponent,
|
||||||
outlet: 'right'
|
outlet: 'right'
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: 'new-campaign',
|
|
||||||
component: CampaignSubmitComponent,
|
|
||||||
outlet: 'right'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: 'new',
|
|
||||||
component: WarSubmitComponent,
|
|
||||||
outlet: 'right'
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: 'war/:id',
|
path: 'war/:id',
|
||||||
component: WarDetailComponent,
|
component: WarHeaderComponent,
|
||||||
outlet: 'right'
|
outlet: 'right'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'campaign-player/:id/:playerName',
|
path: 'campaign-player/:id/:playerName',
|
||||||
component: CampaignPlayerDetailComponent,
|
component: CampaignPlayerDetailComponent,
|
||||||
outlet: 'right'
|
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 statsRouterModule: ModuleWithProviders = RouterModule.forChild(statsRoutes);
|
||||||
|
|
||||||
export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, StatisticHighScoreComponent,
|
export const statsRoutingComponents = [StatisticComponent, StatisticOverviewComponent, StatisticHighScoreComponent,
|
||||||
CampaignSubmitComponent, WarListComponent, WarSubmitComponent, WarDetailComponent, ScoreboardComponent,
|
CampaignSubmitComponent, WarListComponent, WarSubmitComponent, WarEditComponent, WarHeaderComponent,
|
||||||
FractionStatsComponent, CampaignPlayerDetailComponent, WarItemComponent];
|
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';
|
labelPoints = 'Punkte';
|
||||||
labelBudget = 'Budget';
|
labelBudget = 'Budget';
|
||||||
labelKill = 'Kills';
|
labelKill = 'Abschüsse';
|
||||||
labelFriendlyFire = 'FriendlyFire';
|
labelFriendlyFire = 'Friendly Fire';
|
||||||
labelVehicle = 'Fahrzeug-Kills';
|
labelVehicle = 'Fahrzeug Abschüsse';
|
||||||
labelTransport = 'Lufttransport';
|
labelTransport = 'Lufttransport';
|
||||||
labelRevive = 'Revive';
|
labelRevive = 'Revive';
|
||||||
labelStabilize = 'Stabilisiert';
|
labelStabilize = 'Stabilisiert';
|
|
@ -5,7 +5,7 @@
|
||||||
/* ########### DATATABLE ########### */
|
/* ########### DATATABLE ########### */
|
||||||
|
|
||||||
ngx-datatable {
|
ngx-datatable {
|
||||||
width: 1040px;
|
width: 940px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
height: 68vh;
|
height: 68vh;
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,10 @@ ngx-datatable {
|
||||||
background-color: #f7f7f7;
|
background-color: #f7f7f7;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:host /deep/ .ngx-datatable.fixed-header .datatable-header .datatable-header-inner .datatable-header-cell {
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
/* Table Scrollbar BEGIN */
|
/* Table Scrollbar BEGIN */
|
||||||
:host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar {
|
:host /deep/ .ngx-datatable.scroll-vertical .datatable-body::-webkit-scrollbar {
|
||||||
width: 12px;
|
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();
|
@Output() playerTabSwitch = new EventEmitter();
|
||||||
|
|
||||||
tableHead = ['Spieler', 'Fraktion', 'Kills', 'FF', 'Fzg(L)', 'Fzg(H)', 'Fzg(A)',
|
tableHead = PlayerUtils.attributeDisplayNames;
|
||||||
'Revive', 'Flagge', 'Tod', 'Respawn'];
|
|
||||||
|
|
||||||
isSteamUUID = PlayerUtils.isSteamUUID;
|
isSteamUUID = PlayerUtils.isSteamUUID;
|
||||||
|
|
||||||
cellHeight = 40;
|
cellHeight = 40;
|
||||||
|
|
||||||
|
columnWidth = 65;
|
||||||
|
|
||||||
rows = [];
|
rows = [];
|
||||||
|
|
||||||
reorderable = false;
|
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 {
|
.nav-tabs {
|
||||||
width: 980px;
|
width: 920px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
clear: both;
|
clear: both;
|
||||||
border-bottom: 0;
|
border-bottom: 0;
|
|
@ -1,19 +1,19 @@
|
||||||
import {Component, OnInit, ViewChild} from '@angular/core';
|
import {Component, OnInit, ViewChild} from '@angular/core';
|
||||||
import {ActivatedRoute} from '@angular/router';
|
import {ActivatedRoute} from '@angular/router';
|
||||||
import {WarService} from '../../services/logs/war.service';
|
import {WarService} from '../../../services/logs/war.service';
|
||||||
import {War} from '../../models/model-interfaces';
|
import {War} from '../../../models/model-interfaces';
|
||||||
import {ChartUtils} from '../../utils/chart-utils';
|
import {ChartUtils} from '../../../utils/chart-utils';
|
||||||
import {Fraction} from '../../utils/fraction.enum';
|
import {Fraction} from '../../../utils/fraction.enum';
|
||||||
import {LogsService} from '../../services/logs/logs.service';
|
import {LogsService} from '../../../services/logs/logs.service';
|
||||||
import {ScoreboardComponent} from './scoreboard/scoreboard.component';
|
import {ScoreboardComponent} from '../scoreboard/scoreboard.component';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'war-detail',
|
selector: 'war-detail',
|
||||||
templateUrl: './war-detail.component.html',
|
templateUrl: './war-header.component.html',
|
||||||
styleUrls: ['./war-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css']
|
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;
|
readonly fraction = Fraction;
|
||||||
|
|
|
@ -13,6 +13,10 @@
|
||||||
<span (click)="delete(); $event.stopPropagation()"
|
<span (click)="delete(); $event.stopPropagation()"
|
||||||
title="Löschen"
|
title="Löschen"
|
||||||
class="glyphicon glyphicon-trash trash"></span>
|
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>
|
||||||
|
|
||||||
</div>
|
</div>
|
|
@ -1,11 +1,11 @@
|
||||||
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
import {ChangeDetectionStrategy, Component, EventEmitter, Input, OnInit, Output} from '@angular/core';
|
||||||
import {War} from '../../models/model-interfaces';
|
import {War} from '../../../models/model-interfaces';
|
||||||
import {LoginService} from '../../services/app-user-service/login-service';
|
import {LoginService} from '../../../services/app-user-service/login-service';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'pjm-war-item',
|
selector: 'pjm-war-item',
|
||||||
templateUrl: './war-item.component.html',
|
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
|
changeDetection: ChangeDetectionStrategy.OnPush
|
||||||
})
|
})
|
||||||
export class WarItemComponent implements OnInit {
|
export class WarItemComponent implements OnInit {
|
||||||
|
@ -16,6 +16,8 @@ export class WarItemComponent implements OnInit {
|
||||||
|
|
||||||
@Output() warSelected = new EventEmitter();
|
@Output() warSelected = new EventEmitter();
|
||||||
|
|
||||||
|
@Output() warEdit = new EventEmitter();
|
||||||
|
|
||||||
@Output() warDelete = new EventEmitter();
|
@Output() warDelete = new EventEmitter();
|
||||||
|
|
||||||
constructor(public loginService: LoginService) {
|
constructor(public loginService: LoginService) {
|
||||||
|
@ -28,6 +30,10 @@ export class WarItemComponent implements OnInit {
|
||||||
this.warSelected.emit(this.war._id);
|
this.warSelected.emit(this.war._id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
edit() {
|
||||||
|
this.warEdit.emit(this.war._id);
|
||||||
|
}
|
||||||
|
|
||||||
delete() {
|
delete() {
|
||||||
this.warDelete.emit(this.war);
|
this.warDelete.emit(this.war);
|
||||||
}
|
}
|
|
@ -11,13 +11,18 @@
|
||||||
<accordion *ngFor="let campaign of campaigns; let isFirstRow=first">
|
<accordion *ngFor="let campaign of campaigns; let isFirstRow=first">
|
||||||
<accordion-group [isOpen]="isFirstRow">
|
<accordion-group [isOpen]="isFirstRow">
|
||||||
<div accordion-heading>
|
<div accordion-heading>
|
||||||
{{campaign.title}}
|
<span (click)="editCampaign(campaign); $event.stopPropagation()" title="Bearbeiten"
|
||||||
<span class="pull-right">▼</span>
|
style="color: whitesmoke; padding-top: 0; padding-right: 10px;"
|
||||||
<span (click)="deleteCampaign(campaign); $event.stopPropagation()" title="Löschen"
|
class="glyphicon glyphicon-edit trash pull-left"
|
||||||
style="color: whitesmoke; padding-top: 0; padding-right: 20px;"
|
|
||||||
class="glyphicon glyphicon-trash trash pull-right"
|
|
||||||
*ngIf="loginService.hasPermission(3)">
|
*ngIf="loginService.hasPermission(3)">
|
||||||
</span>
|
</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>
|
||||||
|
|
||||||
<div class="fade-in list-entry top-list-entry"
|
<div class="fade-in list-entry top-list-entry"
|
||||||
|
@ -42,6 +47,7 @@
|
||||||
<div *ngFor="let war of campaign.wars">
|
<div *ngFor="let war of campaign.wars">
|
||||||
<pjm-war-item
|
<pjm-war-item
|
||||||
[war]="war"
|
[war]="war"
|
||||||
|
(warEdit)="editWar($event)"
|
||||||
(warDelete)="deleteWar(war)"
|
(warDelete)="deleteWar(war)"
|
||||||
(warSelected)="selectWar($event)"
|
(warSelected)="selectWar($event)"
|
||||||
[selected]="war._id == selectedWarId">
|
[selected]="war._id == selectedWarId">
|
|
@ -1,15 +1,15 @@
|
||||||
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 {Campaign, War} from '../../models/model-interfaces';
|
import {Campaign, War} from '../../../models/model-interfaces';
|
||||||
import {WarService} from '../../services/logs/war.service';
|
import {WarService} from '../../../services/logs/war.service';
|
||||||
import {LoginService} from '../../services/app-user-service/login-service';
|
import {LoginService} from '../../../services/app-user-service/login-service';
|
||||||
import {CampaignService} from '../../services/logs/campaign.service';
|
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||||
import {RouteConfig} from '../../app.config';
|
import {RouteConfig} from '../../../app.config';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'war-list',
|
selector: 'war-list',
|
||||||
templateUrl: './war-list.component.html',
|
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 {
|
export class WarListComponent implements OnInit {
|
||||||
|
|
||||||
|
@ -46,12 +46,7 @@ export class WarListComponent implements OnInit {
|
||||||
|
|
||||||
selectNewCampaign() {
|
selectNewCampaign() {
|
||||||
this.selectedWarId = null;
|
this.selectedWarId = null;
|
||||||
this.router.navigate([{outlets: {'right': ['new-campaign']}}], {relativeTo: this.route});
|
this.router.navigate([{outlets: {'right': ['campaign']}}], {relativeTo: this.route});
|
||||||
}
|
|
||||||
|
|
||||||
selectNewWar() {
|
|
||||||
this.selectedWarId = null;
|
|
||||||
this.router.navigate([{outlets: {'right': ['new']}}], {relativeTo: this.route});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
selectWar(warId) {
|
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) {
|
deleteWar(war: War) {
|
||||||
if (confirm('Soll die Schlacht ' + war.title + ' wirklich gelöscht werden?')) {
|
if (confirm('Soll die Schlacht ' + war.title + ' wirklich gelöscht werden?')) {
|
||||||
this.warService.deleteWar(war._id)
|
this.warService.deleteWar(war._id)
|
||||||
|
@ -82,7 +87,9 @@ export class WarListComponent implements OnInit {
|
||||||
if (this.selectedWarId === war._id) {
|
if (this.selectedWarId === war._id) {
|
||||||
this.selectOverview('all');
|
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>
|
<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"
|
||||||
(change)="fileChange($event)">
|
(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
|
Logfile muss im Format RPT, LOG oder TXT vorliegen
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
|
@ -1,16 +1,16 @@
|
||||||
import {Component, ViewChild} from '@angular/core';
|
import {Component, ViewChild} from '@angular/core';
|
||||||
import {ActivatedRoute, Router} from '@angular/router';
|
import {ActivatedRoute, Router} from '@angular/router';
|
||||||
import {NgForm} from '@angular/forms';
|
import {NgForm} from '@angular/forms';
|
||||||
import {WarService} from '../../services/logs/war.service';
|
import {WarService} from '../../../services/logs/war.service';
|
||||||
import {War} from '../../models/model-interfaces';
|
import {War} from '../../../models/model-interfaces';
|
||||||
import {CampaignService} from '../../services/logs/campaign.service';
|
import {CampaignService} from '../../../services/logs/campaign.service';
|
||||||
|
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'war-submit',
|
selector: 'war-submit',
|
||||||
templateUrl: './war-submit.component.html',
|
templateUrl: './war-submit.component.html',
|
||||||
styleUrls: ['./war-submit.component.css', '../../style/load-indicator.css',
|
styleUrls: ['./war-submit.component.css', '../../../style/load-indicator.css',
|
||||||
'../../style/entry-form.css', '../../style/overview.css']
|
'../../../style/entry-form.css', '../../../style/overview.css']
|
||||||
})
|
})
|
||||||
export class WarSubmitComponent {
|
export class WarSubmitComponent {
|
||||||
|
|
||||||
|
@ -18,7 +18,9 @@ export class WarSubmitComponent {
|
||||||
|
|
||||||
fileList: FileList;
|
fileList: FileList;
|
||||||
|
|
||||||
showImageError = false;
|
readonly validExtensions = ['.rpt', '.log', '.txt'];
|
||||||
|
|
||||||
|
showFileError = false;
|
||||||
|
|
||||||
showErrorLabel = false;
|
showErrorLabel = false;
|
||||||
|
|
||||||
|
@ -35,14 +37,13 @@ export class WarSubmitComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
fileChange(event) {
|
fileChange(event) {
|
||||||
if (!event.target.files[0].name.endsWith('.rpt')
|
if (this.validExtensions.filter(ext => event.target.files[0] &&
|
||||||
&& !event.target.files[0].name.endsWith('.log')
|
event.target.files[0].name.endsWith(ext)).length === 1) {
|
||||||
&& !event.target.files[0].name.endsWith('.txt')) {
|
this.showFileError = false;
|
||||||
this.showImageError = true;
|
|
||||||
this.fileList = undefined;
|
|
||||||
} else {
|
|
||||||
this.showImageError = false;
|
|
||||||
this.fileList = event.target.files;
|
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});
|
this.router.navigate(['..'], {relativeTo: this.route});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,5 +1,19 @@
|
||||||
export class PlayerUtils {
|
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 {
|
public static isSteamUUID(input: string): boolean {
|
||||||
const steamUIDPattern = new RegExp('[0-9]{17}');
|
const steamUIDPattern = new RegExp('[0-9]{17}');
|
||||||
return steamUIDPattern.test(input);
|
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 |