Compare commits

..

2 Commits

Author SHA1 Message Date
HardiReady 94c5ac2261 Add Scoreboard SCV download (CC-11) 2018-04-02 13:20:44 +02:00
HardiReady 3745241d75 Add CSV download button FE 2018-04-02 11:20:04 +02:00
11 changed files with 145 additions and 873 deletions

View File

@ -18,7 +18,6 @@ So if your server is reachable at `https://cc.myserver.lan` the API endpoint is
https://cc.myserver.lan/api/ https://cc.myserver.lan/api/
``` ```
## Authentication ## Authentication
Requests to most of the API endpoints have to be authenticated using an API token which is received after successfully providing your application credentials to the API. Requests to most of the API endpoints have to be authenticated using an API token which is received after successfully providing your application credentials to the API.

View File

@ -103,53 +103,54 @@ app.use((req, res) => {
errorResponseWare(app); errorResponseWare(app);
// Start the server // Start the server
if (process.env.NODE_ENV === config.test.unit.env || process.env.NODE_ENV === config.test.dredd.env) { if (process.env.NODE_ENV === config.test.unit.env || process.env.NODE_ENV === config.test.dredd.env) {
const MongodbMemoryServer = require('mongodb-memory-server').default; const MongodbMemoryServer = require('mongodb-memory-server').default;
const mongoServer = new MongodbMemoryServer(); const mongoServer = new MongodbMemoryServer();
mongoose.Promise = Promise; mongoose.Promise = Promise;
mongoServer.getConnectionString().then((mongoUri) => { mongoServer.getConnectionString().then((mongoUri) => {
mongoose.connect(mongoUri); mongoose.connect(mongoUri);
mongoose.connection.on('error', (e) => { mongoose.connection.on('error', (e) => {
if (e.message.code === 'ETIMEDOUT') { if (e.message.code === 'ETIMEDOUT') {
error(e);
mongoose.connect(mongoUri);
}
error(e); error(e);
}); mongoose.connect(mongoUri);
}
error(e);
});
if (process.env.NODE_ENV === config.test.dredd.env) { if (process.env.NODE_ENV === config.test.dredd.env) {
const mongoPortAndDB = mongoUri.replace('mongodb://localhost:', '').split('/'); const mongoPortAndDB = mongoUri.replace('mongodb://localhost:', '').split('/');
exec(__dirname + '/apib/dredd/populate-data.sh' exec(
.concat(' -p ').concat(mongoPortAndDB[0]) __dirname + '/apib/dredd/populate-data.sh'
.concat(' -d ').concat(mongoPortAndDB[1]), (err, stdout, stderr) => { .concat(' -p ').concat(mongoPortAndDB[0])
.concat(' -d ').concat(mongoPortAndDB[1]), (err, stdout, stderr) => {
if (err) { if (err) {
error(err.message); error(err.message);
} else { } else {
logger('\x1b[32m%s\x1b[0m', stderr); logger('\x1b[32m%s\x1b[0m', stderr);
} }
}); });
} }
mongoose.connection.once('open', () => { mongoose.connection.once('open', () => {
logger(`MongoDB successfully connected to ${mongoUri}`); logger(`MongoDB successfully connected to ${mongoUri}`);
app.listen(config.test.port); app.listen(config.test.port);
logger('Listening on port ' + config.test.port); logger('Listening on port ' + config.test.port);
});
}); });
} else { });
const mongoosePromise = mongoose.connect(config.database.uri + config.database.db); } else {
mongoosePromise.then((db) => { const mongoosePromise = mongoose.connect(config.database.uri + config.database.db);
app.listen(config.port, (err) => { mongoosePromise.then((db) => {
if (err !== undefined) { app.listen(config.port, (err) => {
error('Error on startup, ', err); if (err !== undefined) {
} else { error('Error on startup, ', err);
logger('Listening on port ' + config.port); } else {
signatureCronJob.start(); logger('Listening on port ' + config.port);
backupCronJob.start(); signatureCronJob.start();
} backupCronJob.start();
}); }
}); });
});
} }
module.exports = app; module.exports = app;

795
static/package-lock.json generated
View File

@ -1183,7 +1183,6 @@
"requires": { "requires": {
"anymatch": "1.3.2", "anymatch": "1.3.2",
"async-each": "1.0.1", "async-each": "1.0.1",
"fsevents": "1.1.3",
"glob-parent": "2.0.0", "glob-parent": "2.0.0",
"inherits": "2.0.3", "inherits": "2.0.3",
"is-binary-path": "1.0.1", "is-binary-path": "1.0.1",
@ -3003,6 +3002,11 @@
"schema-utils": "0.3.0" "schema-utils": "0.3.0"
} }
}, },
"file-saver": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/file-saver/-/file-saver-1.3.8.tgz",
"integrity": "sha512-spKHSBQIxxS81N/O21WmuXA2F6wppUCsutpzenOeZzOCCJ5gEfcbqJP983IrpLXzYmXnMUa6J03SubcNPdKrlg=="
},
"filename-regex": { "filename-regex": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
@ -3188,795 +3192,6 @@
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
}, },
"fsevents": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz",
"integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==",
"optional": true,
"requires": {
"nan": "2.7.0",
"node-pre-gyp": "0.6.39"
},
"dependencies": {
"abbrev": {
"version": "1.1.0",
"bundled": true,
"optional": true
},
"ajv": {
"version": "4.11.8",
"bundled": true,
"optional": true,
"requires": {
"co": "4.6.0",
"json-stable-stringify": "1.0.1"
}
},
"ansi-regex": {
"version": "2.1.1",
"bundled": true
},
"aproba": {
"version": "1.1.1",
"bundled": true,
"optional": true
},
"are-we-there-yet": {
"version": "1.1.4",
"bundled": true,
"optional": true,
"requires": {
"delegates": "1.0.0",
"readable-stream": "2.2.9"
}
},
"asn1": {
"version": "0.2.3",
"bundled": true,
"optional": true
},
"assert-plus": {
"version": "0.2.0",
"bundled": true,
"optional": true
},
"asynckit": {
"version": "0.4.0",
"bundled": true,
"optional": true
},
"aws-sign2": {
"version": "0.6.0",
"bundled": true,
"optional": true
},
"aws4": {
"version": "1.6.0",
"bundled": true,
"optional": true
},
"balanced-match": {
"version": "0.4.2",
"bundled": true
},
"bcrypt-pbkdf": {
"version": "1.0.1",
"bundled": true,
"optional": true,
"requires": {
"tweetnacl": "0.14.5"
}
},
"block-stream": {
"version": "0.0.9",
"bundled": true,
"requires": {
"inherits": "2.0.3"
}
},
"boom": {
"version": "2.10.1",
"bundled": true,
"requires": {
"hoek": "2.16.3"
}
},
"brace-expansion": {
"version": "1.1.7",
"bundled": true,
"requires": {
"balanced-match": "0.4.2",
"concat-map": "0.0.1"
}
},
"buffer-shims": {
"version": "1.0.0",
"bundled": true
},
"caseless": {
"version": "0.12.0",
"bundled": true,
"optional": true
},
"co": {
"version": "4.6.0",
"bundled": true,
"optional": true
},
"code-point-at": {
"version": "1.1.0",
"bundled": true
},
"combined-stream": {
"version": "1.0.5",
"bundled": true,
"requires": {
"delayed-stream": "1.0.0"
}
},
"concat-map": {
"version": "0.0.1",
"bundled": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true
},
"core-util-is": {
"version": "1.0.2",
"bundled": true
},
"cryptiles": {
"version": "2.0.5",
"bundled": true,
"requires": {
"boom": "2.10.1"
}
},
"dashdash": {
"version": "1.14.1",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"debug": {
"version": "2.6.8",
"bundled": true,
"optional": true,
"requires": {
"ms": "2.0.0"
}
},
"deep-extend": {
"version": "0.4.2",
"bundled": true,
"optional": true
},
"delayed-stream": {
"version": "1.0.0",
"bundled": true
},
"delegates": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"detect-libc": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"ecc-jsbn": {
"version": "0.1.1",
"bundled": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"extend": {
"version": "3.0.1",
"bundled": true,
"optional": true
},
"extsprintf": {
"version": "1.0.2",
"bundled": true
},
"forever-agent": {
"version": "0.6.1",
"bundled": true,
"optional": true
},
"form-data": {
"version": "2.1.4",
"bundled": true,
"optional": true,
"requires": {
"asynckit": "0.4.0",
"combined-stream": "1.0.5",
"mime-types": "2.1.15"
}
},
"fs.realpath": {
"version": "1.0.0",
"bundled": true
},
"fstream": {
"version": "1.0.11",
"bundled": true,
"requires": {
"graceful-fs": "4.1.11",
"inherits": "2.0.3",
"mkdirp": "0.5.1",
"rimraf": "2.6.1"
}
},
"fstream-ignore": {
"version": "1.0.5",
"bundled": true,
"optional": true,
"requires": {
"fstream": "1.0.11",
"inherits": "2.0.3",
"minimatch": "3.0.4"
}
},
"gauge": {
"version": "2.7.4",
"bundled": true,
"optional": true,
"requires": {
"aproba": "1.1.1",
"console-control-strings": "1.1.0",
"has-unicode": "2.0.1",
"object-assign": "4.1.1",
"signal-exit": "3.0.2",
"string-width": "1.0.2",
"strip-ansi": "3.0.1",
"wide-align": "1.1.2"
}
},
"getpass": {
"version": "0.1.7",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"glob": {
"version": "7.1.2",
"bundled": true,
"requires": {
"fs.realpath": "1.0.0",
"inflight": "1.0.6",
"inherits": "2.0.3",
"minimatch": "3.0.4",
"once": "1.4.0",
"path-is-absolute": "1.0.1"
}
},
"graceful-fs": {
"version": "4.1.11",
"bundled": true
},
"har-schema": {
"version": "1.0.5",
"bundled": true,
"optional": true
},
"har-validator": {
"version": "4.2.1",
"bundled": true,
"optional": true,
"requires": {
"ajv": "4.11.8",
"har-schema": "1.0.5"
}
},
"has-unicode": {
"version": "2.0.1",
"bundled": true,
"optional": true
},
"hawk": {
"version": "3.1.3",
"bundled": true,
"requires": {
"boom": "2.10.1",
"cryptiles": "2.0.5",
"hoek": "2.16.3",
"sntp": "1.0.9"
}
},
"hoek": {
"version": "2.16.3",
"bundled": true
},
"http-signature": {
"version": "1.1.1",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "0.2.0",
"jsprim": "1.4.0",
"sshpk": "1.13.0"
}
},
"inflight": {
"version": "1.0.6",
"bundled": true,
"requires": {
"once": "1.4.0",
"wrappy": "1.0.2"
}
},
"inherits": {
"version": "2.0.3",
"bundled": true
},
"ini": {
"version": "1.3.4",
"bundled": true,
"optional": true
},
"is-fullwidth-code-point": {
"version": "1.0.0",
"bundled": true,
"requires": {
"number-is-nan": "1.0.1"
}
},
"is-typedarray": {
"version": "1.0.0",
"bundled": true,
"optional": true
},
"isarray": {
"version": "1.0.0",
"bundled": true
},
"isstream": {
"version": "0.1.2",
"bundled": true,
"optional": true
},
"jodid25519": {
"version": "1.0.2",
"bundled": true,
"optional": true,
"requires": {
"jsbn": "0.1.1"
}
},
"jsbn": {
"version": "0.1.1",
"bundled": true,
"optional": true
},
"json-schema": {
"version": "0.2.3",
"bundled": true,
"optional": true
},
"json-stable-stringify": {
"version": "1.0.1",
"bundled": true,
"optional": true,
"requires": {
"jsonify": "0.0.0"
}
},
"json-stringify-safe": {
"version": "5.0.1",
"bundled": true,
"optional": true
},
"jsonify": {
"version": "0.0.0",
"bundled": true,
"optional": true
},
"jsprim": {
"version": "1.4.0",
"bundled": true,
"optional": true,
"requires": {
"assert-plus": "1.0.0",
"extsprintf": "1.0.2",
"json-schema": "0.2.3",
"verror": "1.3.6"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"mime-db": {
"version": "1.27.0",
"bundled": true
},
"mime-types": {
"version": "2.1.15",
"bundled": true,
"requires": {
"mime-db": "1.27.0"
}
},
"minimatch": {
"version": "3.0.4",
"bundled": true,
"requires": {
"brace-expansion": "1.1.7"
}
},
"minimist": {
"version": "0.0.8",
"bundled": true
},
"mkdirp": {
"version": "0.5.1",
"bundled": true,
"requires": {
"minimist": "0.0.8"
}
},
"ms": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"node-pre-gyp": {
"version": "0.6.39",
"bundled": true,
"optional": true,
"requires": {
"detect-libc": "1.0.2",
"hawk": "3.1.3",
"mkdirp": "0.5.1",
"nopt": "4.0.1",
"npmlog": "4.1.0",
"rc": "1.2.1",
"request": "2.81.0",
"rimraf": "2.6.1",
"semver": "5.3.0",
"tar": "2.2.1",
"tar-pack": "3.4.0"
}
},
"nopt": {
"version": "4.0.1",
"bundled": true,
"optional": true,
"requires": {
"abbrev": "1.1.0",
"osenv": "0.1.4"
}
},
"npmlog": {
"version": "4.1.0",
"bundled": true,
"optional": true,
"requires": {
"are-we-there-yet": "1.1.4",
"console-control-strings": "1.1.0",
"gauge": "2.7.4",
"set-blocking": "2.0.0"
}
},
"number-is-nan": {
"version": "1.0.1",
"bundled": true
},
"oauth-sign": {
"version": "0.8.2",
"bundled": true,
"optional": true
},
"object-assign": {
"version": "4.1.1",
"bundled": true,
"optional": true
},
"once": {
"version": "1.4.0",
"bundled": true,
"requires": {
"wrappy": "1.0.2"
}
},
"os-homedir": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"os-tmpdir": {
"version": "1.0.2",
"bundled": true,
"optional": true
},
"osenv": {
"version": "0.1.4",
"bundled": true,
"optional": true,
"requires": {
"os-homedir": "1.0.2",
"os-tmpdir": "1.0.2"
}
},
"path-is-absolute": {
"version": "1.0.1",
"bundled": true
},
"performance-now": {
"version": "0.2.0",
"bundled": true,
"optional": true
},
"process-nextick-args": {
"version": "1.0.7",
"bundled": true
},
"punycode": {
"version": "1.4.1",
"bundled": true,
"optional": true
},
"qs": {
"version": "6.4.0",
"bundled": true,
"optional": true
},
"rc": {
"version": "1.2.1",
"bundled": true,
"optional": true,
"requires": {
"deep-extend": "0.4.2",
"ini": "1.3.4",
"minimist": "1.2.0",
"strip-json-comments": "2.0.1"
},
"dependencies": {
"minimist": {
"version": "1.2.0",
"bundled": true,
"optional": true
}
}
},
"readable-stream": {
"version": "2.2.9",
"bundled": true,
"requires": {
"buffer-shims": "1.0.0",
"core-util-is": "1.0.2",
"inherits": "2.0.3",
"isarray": "1.0.0",
"process-nextick-args": "1.0.7",
"string_decoder": "1.0.1",
"util-deprecate": "1.0.2"
}
},
"request": {
"version": "2.81.0",
"bundled": true,
"optional": true,
"requires": {
"aws-sign2": "0.6.0",
"aws4": "1.6.0",
"caseless": "0.12.0",
"combined-stream": "1.0.5",
"extend": "3.0.1",
"forever-agent": "0.6.1",
"form-data": "2.1.4",
"har-validator": "4.2.1",
"hawk": "3.1.3",
"http-signature": "1.1.1",
"is-typedarray": "1.0.0",
"isstream": "0.1.2",
"json-stringify-safe": "5.0.1",
"mime-types": "2.1.15",
"oauth-sign": "0.8.2",
"performance-now": "0.2.0",
"qs": "6.4.0",
"safe-buffer": "5.0.1",
"stringstream": "0.0.5",
"tough-cookie": "2.3.2",
"tunnel-agent": "0.6.0",
"uuid": "3.0.1"
}
},
"rimraf": {
"version": "2.6.1",
"bundled": true,
"requires": {
"glob": "7.1.2"
}
},
"safe-buffer": {
"version": "5.0.1",
"bundled": true
},
"semver": {
"version": "5.3.0",
"bundled": true,
"optional": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true,
"optional": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true,
"optional": true
},
"sntp": {
"version": "1.0.9",
"bundled": true,
"requires": {
"hoek": "2.16.3"
}
},
"sshpk": {
"version": "1.13.0",
"bundled": true,
"optional": true,
"requires": {
"asn1": "0.2.3",
"assert-plus": "1.0.0",
"bcrypt-pbkdf": "1.0.1",
"dashdash": "1.14.1",
"ecc-jsbn": "0.1.1",
"getpass": "0.1.7",
"jodid25519": "1.0.2",
"jsbn": "0.1.1",
"tweetnacl": "0.14.5"
},
"dependencies": {
"assert-plus": {
"version": "1.0.0",
"bundled": true,
"optional": true
}
}
},
"string-width": {
"version": "1.0.2",
"bundled": true,
"requires": {
"code-point-at": "1.1.0",
"is-fullwidth-code-point": "1.0.0",
"strip-ansi": "3.0.1"
}
},
"string_decoder": {
"version": "1.0.1",
"bundled": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"stringstream": {
"version": "0.0.5",
"bundled": true,
"optional": true
},
"strip-ansi": {
"version": "3.0.1",
"bundled": true,
"requires": {
"ansi-regex": "2.1.1"
}
},
"strip-json-comments": {
"version": "2.0.1",
"bundled": true,
"optional": true
},
"tar": {
"version": "2.2.1",
"bundled": true,
"requires": {
"block-stream": "0.0.9",
"fstream": "1.0.11",
"inherits": "2.0.3"
}
},
"tar-pack": {
"version": "3.4.0",
"bundled": true,
"optional": true,
"requires": {
"debug": "2.6.8",
"fstream": "1.0.11",
"fstream-ignore": "1.0.5",
"once": "1.4.0",
"readable-stream": "2.2.9",
"rimraf": "2.6.1",
"tar": "2.2.1",
"uid-number": "0.0.6"
}
},
"tough-cookie": {
"version": "2.3.2",
"bundled": true,
"optional": true,
"requires": {
"punycode": "1.4.1"
}
},
"tunnel-agent": {
"version": "0.6.0",
"bundled": true,
"optional": true,
"requires": {
"safe-buffer": "5.0.1"
}
},
"tweetnacl": {
"version": "0.14.5",
"bundled": true,
"optional": true
},
"uid-number": {
"version": "0.0.6",
"bundled": true,
"optional": true
},
"util-deprecate": {
"version": "1.0.2",
"bundled": true
},
"uuid": {
"version": "3.0.1",
"bundled": true,
"optional": true
},
"verror": {
"version": "1.3.6",
"bundled": true,
"optional": true,
"requires": {
"extsprintf": "1.0.2"
}
},
"wide-align": {
"version": "1.1.2",
"bundled": true,
"optional": true,
"requires": {
"string-width": "1.0.2"
}
},
"wrappy": {
"version": "1.0.2",
"bundled": true
}
}
},
"fstream": { "fstream": {
"version": "1.0.11", "version": "1.0.11",
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz",

View File

@ -30,6 +30,7 @@
"@swimlane/ngx-datatable": "^11.0.4", "@swimlane/ngx-datatable": "^11.0.4",
"bootstrap": "^3.3.7", "bootstrap": "^3.3.7",
"d3": "^4.11.0", "d3": "^4.11.0",
"file-saver": "^1.3.8",
"jquery": "^3.1.0", "jquery": "^3.1.0",
"jquery-ui": "^1.12.0", "jquery-ui": "^1.12.0",
"jquery-ui-bundle": "^1.11.4", "jquery-ui-bundle": "^1.11.4",

View File

@ -15,7 +15,7 @@ import {CSSHelpers} from '../global.helpers';
}) })
export class ArmyComponent implements OnInit, OnDestroy { export class ArmyComponent implements OnInit, OnDestroy {
army: Army[]; army: Army[] = [{}, {}];
readonly fraction = Fraction; readonly fraction = Fraction;

View File

@ -103,17 +103,19 @@ export interface Decoration {
isMedal?: boolean; isMedal?: boolean;
} }
export interface Army { export interface ArmySquad {
squads: { _id?: string;
_id, name?: string;
name, memberCount?: number;
memberCount, members?: {
members: { _id,
_id, username,
username, rank
rank };
}[], }
}[];
memberCount: number; export interface Army {
squads?: ArmySquad[];
memberCount?: number;
} }

View File

@ -10,7 +10,7 @@
[columnMode]="'force'" [columnMode]="'force'"
[scrollbarV]="true" [scrollbarV]="true"
[selectionType]="'single'"> [selectionType]="'single'">
<ngx-datatable-column name="Spieler" prop="name" [width]="210" style="padding-left:10px"> <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"> <ng-template ngx-datatable-cell-template let-row="row" let-value="value">
<span class="player-name" <span class="player-name"
[style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR"> [style.color]="row['fraction'] === 'BLUFOR' ? fraction.COLOR_BLUFOR : fraction.COLOR_OPFOR">
@ -18,18 +18,18 @@
</span> </span>
</ng-template> </ng-template>
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column name="Fraktion" prop="fraction" [width]="100"> <ngx-datatable-column name="{{tableHead[1]}}" prop="fraction" [width]="100">
<ng-template ngx-datatable-cell-template let-value="value"> <ng-template ngx-datatable-cell-template let-value="value">
{{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}} {{value === 'BLUFOR' ? fraction.BLUFOR : fraction.OPFOR}}
</ng-template> </ng-template>
</ngx-datatable-column> </ngx-datatable-column>
<ngx-datatable-column [width]="90" name="Kills" prop="kill"></ngx-datatable-column> <ngx-datatable-column [width]="90" name="{{tableHead[2]}}" prop="kill"></ngx-datatable-column>
<ngx-datatable-column [width]="104" name="FriendlyFire" prop="friendlyFire"></ngx-datatable-column> <ngx-datatable-column [width]="104" name="{{tableHead[3]}}" prop="friendlyFire"></ngx-datatable-column>
<ngx-datatable-column [width]="90" name="Fahrzeug" prop="vehicle"></ngx-datatable-column> <ngx-datatable-column [width]="90" name="{{tableHead[4]}}" prop="vehicle"></ngx-datatable-column>
<ngx-datatable-column [width]="80" name="Revive" prop="revive"></ngx-datatable-column> <ngx-datatable-column [width]="80" name="{{tableHead[5]}}" prop="revive"></ngx-datatable-column>
<ngx-datatable-column [width]="100" name="Eroberung" prop="flagTouch"></ngx-datatable-column> <ngx-datatable-column [width]="100" name="{{tableHead[6]}}" prop="flagTouch"></ngx-datatable-column>
<ngx-datatable-column [width]="70" name="Tod" prop="death"></ngx-datatable-column> <ngx-datatable-column [width]="70" name="{{tableHead[7]}}" prop="death"></ngx-datatable-column>
<ngx-datatable-column [width]="90" name="Respawn" prop="respawn"></ngx-datatable-column> <ngx-datatable-column [width]="90" name="{{tableHead[8]}}" prop="respawn"></ngx-datatable-column>
<!--<ngx-datatable-column [width]="80" name="" prop="name">--> <!--<ngx-datatable-column [width]="80" name="" prop="name">-->
<!--<ng-template ngx-datatable-cell-template let-value="value">--> <!--<ng-template ngx-datatable-cell-template let-value="value">-->
<!--<span class="btn btn-sm btn-default in-table-btn disabled">Detail</span>--> <!--<span class="btn btn-sm btn-default in-table-btn disabled">Detail</span>-->

View File

@ -2,6 +2,7 @@ import {Component, ElementRef, EventEmitter, Input, OnChanges, Output, SimpleCha
import {War} from '../../../models/model-interfaces'; import {War} from '../../../models/model-interfaces';
import {Fraction} from '../../../utils/fraction.enum'; import {Fraction} from '../../../utils/fraction.enum';
import {PlayerUtils} from '../../../utils/player-utils'; import {PlayerUtils} from '../../../utils/player-utils';
import {saveAs} from 'file-saver/FileSaver';
@Component({ @Component({
selector: 'cc-scoreboard', selector: 'cc-scoreboard',
@ -18,6 +19,8 @@ export class ScoreboardComponent implements OnChanges {
@Output() playerTabSwitch = new EventEmitter(); @Output() playerTabSwitch = new EventEmitter();
tableHead = ['Spieler', 'Fraktion', 'Kills', 'FriendlyFire', 'Fahrzeug', 'Revive', 'Eroberung', 'Tod', 'Respawn'];
isSteamUUID = PlayerUtils.isSteamUUID; isSteamUUID = PlayerUtils.isSteamUUID;
cellHeight = 40; cellHeight = 40;
@ -63,4 +66,31 @@ export class ScoreboardComponent implements OnChanges {
} }
} }
exportCSV() {
let csvOut = '';
for (let i = 0; i < this.tableHead.length; i++) {
csvOut += this.tableHead[i];
if (i !== this.tableHead.length - 1) {
csvOut += ',';
}
}
for (let j = 0; j < this.war.players.length; j++) {
const player = this.war.players[j];
csvOut += '\r\n';
csvOut += '"' + player.name + '",';
csvOut += player.fraction + ',';
csvOut += player.kill + ',';
csvOut += player.friendlyFire + ',';
csvOut += player.vehicle + ',';
csvOut += player.revive + ',';
csvOut += player.flagTouch + ',';
csvOut += player.death + ',';
csvOut += player.respawn;
}
const blob = new Blob([csvOut], {type: 'text/plain'});
saveAs(blob, this.war.title.toLowerCase().replace(' ', '_').concat('.csv'));
}
} }

View File

@ -10,6 +10,16 @@
margin-bottom: 10px; margin-bottom: 10px;
} }
form.tab-control {
padding: 10px;
}
span.tab-control {
margin: 4px 67px;
padding: 4px 16px;
}
.war-header { .war-header {
border-bottom: thin solid lightgrey; border-bottom: thin solid lightgrey;
} }
@ -34,6 +44,10 @@
color: #f5f5f5; color: #f5f5f5;
} }
.nav-tabs > li:last-child {
margin-left: 70px;
}
.nav-link { .nav-link {
cursor: pointer !important; cursor: pointer !important;
color: #FFF !important; color: #FFF !important;

View File

@ -24,29 +24,9 @@
</div> </div>
<div class="pull-left " style="padding-left: 100px; padding-top:15px"> <div class="pull-left " style="padding-left: 100px; padding-top:15px">
<a class="btn btn-default" style="margin: 20px" target="_blank" href="resource/logs/{{war._id}}/clean.log">Logfile <a class="btn btn-default" style="margin: 20px" target="_blank" href="resource/logs/{{war._id}}/clean.log">
anzeigen</a> Logfile anzeigen
<form class="form-group" *ngIf="tab === 0"> </a>
<label class="radio-inline">
<input type="radio" name="fractSelect"
[checked]="(fractionFilterSelected == undefined) ? 'true' : 'false'"
[(ngModel)]="fractionFilterSelected"
(change)="filterPlayersByFraction()">Alle
</label>
<label class="radio-inline">
<input type="radio" name="fractSelect" value="BLUFOR"
[(ngModel)]="fractionFilterSelected"
#fractRadioBufor
(change)="filterPlayersByFraction(fractRadioBufor.value)">{{fraction.BLUFOR}}
</label>
<label class="radio-inline">
<input type="radio" name="fractSelect" value="OPFOR"
[(ngModel)]="fractionFilterSelected"
#fractRadioOpfor
(change)="filterPlayersByFraction(fractRadioOpfor.value)">{{fraction.OPFOR}}
</label>
<br>
</form>
</div> </div>
</div> </div>
@ -60,12 +40,40 @@
<li class="nav-item" [ngClass]="{active :tab === 2, deactivated :tab !== 2} "> <li class="nav-item" [ngClass]="{active :tab === 2, deactivated :tab !== 2} ">
<a class="nav-link"><img src="../../../assets/player-stats-btn.png"> Player</a> <a class="nav-link"><img src="../../../assets/player-stats-btn.png"> Player</a>
</li> </li>
<li>
<div *ngIf="tab === 0">
<form class="pull-left tab-control">
<label class="radio-inline">
<input type="radio" name="fractSelect"
[checked]="(fractionFilterSelected == undefined) ? 'true' : 'false'"
[(ngModel)]="fractionFilterSelected"
(change)="filterPlayersByFraction()">Alle
</label>
<label class="radio-inline">
<input type="radio" name="fractSelect" value="BLUFOR"
[(ngModel)]="fractionFilterSelected"
#fractRadioBufor
(change)="filterPlayersByFraction(fractRadioBufor.value)">{{fraction.BLUFOR}}
</label>
<label class="radio-inline">
<input type="radio" name="fractSelect" value="OPFOR"
[(ngModel)]="fractionFilterSelected"
#fractRadioOpfor
(change)="filterPlayersByFraction(fractRadioOpfor.value)">{{fraction.OPFOR}}
</label>
</form>
<span class="btn btn-default pull-left tab-control" (click)="scoreBoardComponent.exportCSV()">
Download CSV
</span>
</div>
</li>
</ul> </ul>
<!--Sub-Components (=TABS)--> <!--Sub-Components (=TABS)-->
<div *ngIf="war"> <div *ngIf="war">
<cc-scoreboard <cc-scoreboard
*ngIf="tab === 0" *ngIf="tab === 0"
#scoreboard
[war]="war" [war]="war"
[fractionFilterSelected]="fractionFilterSelected" [fractionFilterSelected]="fractionFilterSelected"
(playerTabSwitch)="switchToPlayerTab($event)"> (playerTabSwitch)="switchToPlayerTab($event)">

View File

@ -1,10 +1,11 @@
import {Component, OnInit} from '@angular/core'; import {Component, EventEmitter, OnInit, Output, 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";
@Component({ @Component({
@ -18,6 +19,8 @@ export class WarDetailComponent implements OnInit {
war: War; war: War;
@ViewChild('scoreboard') scoreBoardComponent: ScoreboardComponent;
logData; logData;
singlePlayerView: number; singlePlayerView: number;
@ -81,5 +84,4 @@ export class WarDetailComponent implements OnInit {
filterPlayersByFraction(fraction?: string) { filterPlayersByFraction(fraction?: string) {
this.fractionFilterSelected = fraction; this.fractionFilterSelected = fraction;
} }
} }