Merge branch 'release/v1.5.1' of hardi/opt-cc into master

pull/13/head v1.5.1
hardi 2017-10-07 11:13:52 +02:00 committed by HardiReady
commit 51a203861b
40 changed files with 324 additions and 376 deletions

View File

@ -11,20 +11,20 @@
"e2e": "NODE_ENV=test node server.js"
},
"dependencies": {
"async": "^2.4.0",
"async": "^2.5.0",
"bcryptjs": "^2.4.3",
"body-parser": "~1.13.2",
"cors": "^2.8.3",
"cron": "^1.2.1",
"cors": "^2.8.4",
"cron": "^1.3.0",
"debug": "~2.2.0",
"express": "^4.16.1",
"imagemin": "^5.2.2",
"imagemin-pngquant": "^5.0.0",
"jimp": "^0.2.27",
"jsonwebtoken": "^7.4.0",
"jsonwebtoken": "^7.4.3",
"lodash": "^4.17.4",
"mkdirp": "^0.5.1",
"mongoose": "^4.11.4",
"mongoose": "^4.12.0",
"morgan": "~1.6.1",
"multer": "^1.3.0",
"node-sha1": "^1.0.1",
@ -34,7 +34,7 @@
"devDependencies": {
"chai": "^3.5.0",
"chai-http": "^3.0.0",
"mocha": "^3.3.0",
"nodemon": "^1.11.0"
"mocha": "^3.5.3",
"nodemon": "^1.12.1"
}
}

View File

@ -1,6 +1,6 @@
{
"name": "opt-cc",
"version": "1.5.0",
"version": "1.5.1",
"license": "MIT",
"private": true,
"scripts": {
@ -16,7 +16,7 @@
"test-e2e": "npm run e2e --prefix ./static"
},
"dependencies": {
"uglify-js": "^3.0.26"
"uglify-js": "^3.1.3"
},
"devDependencies": {
"concurrently": "^3.4.0",

View File

@ -11,37 +11,37 @@
"e2e": "ng e2e --serve=false"
},
"dependencies": {
"@angular/animations": "^4.3.2",
"@angular/cli": "^1.4.0-rc.2",
"@angular/common": "^4.3.2",
"@angular/compiler": "^4.3.2",
"@angular/compiler-cli": "^4.3.2",
"@angular/core": "^4.3.2",
"@angular/forms": "^4.3.2",
"@angular/http": "^4.3.2",
"@angular/platform-browser": "^4.3.2",
"@angular/platform-browser-dynamic": "^4.3.2",
"@angular/router": "^4.3.2",
"@angular/animations": "^4.4.4",
"@angular/cli": "^1.4.5",
"@angular/common": "^4.4.4",
"@angular/compiler": "^4.4.4",
"@angular/compiler-cli": "^4.4.4",
"@angular/core": "^4.4.4",
"@angular/forms": "^4.4.4",
"@angular/http": "^4.4.4",
"@angular/platform-browser": "^4.4.4",
"@angular/platform-browser-dynamic": "^4.4.4",
"@angular/router": "^4.4.4",
"@swimlane/ngx-charts": "^6.0.2",
"@swimlane/ngx-datatable": "^10.2.3",
"bootstrap": "^3.3.7",
"core-js": "^2.4.1",
"d3": "^4.10.0",
"d3": "^4.11.0",
"jquery": "^3.1.0",
"jquery-ui": "^1.12.0",
"jquery-ui-bundle": "^1.11.4",
"ngx-bootstrap": "^1.8.1",
"ngx-clipboard": "^8.0.2",
"ngx-bootstrap": "^1.9.3",
"ngx-clipboard": "^8.1.0",
"ngx-cookie-service": "^1.0.9",
"rxjs": "^5.2.0",
"ts-helpers": "^1.1.1",
"typescript": "^2.3.2",
"webpack": "^3.5.5",
"zone.js": "^0.8.5"
"typescript": "^2.3.4",
"webpack": "^3.6.0",
"zone.js": "^0.8.18"
},
"devDependencies": {
"@types/jasmine": "2.5.38",
"@types/node": "~6.0.60",
"@types/node": "^6.0.89",
"codelyzer": "~2.0.0-beta.1",
"jasmine-core": "^2.5.2",
"jasmine-spec-reporter": "^3.2.0",

View File

@ -86,7 +86,7 @@
</nav>
</div>
<div class="content">
<div>
<span *ngIf="loading" class="load-indicator load-arrow glyphicon-refresh-animate"></span>
<div id="left">
<router-outlet></router-outlet>

View File

@ -1,7 +1,7 @@
import {RouterModule, Routes} from "@angular/router";
import {LoginComponent} from "./login/index";
import {NotFoundComponent} from "./common/not-found/not-found.component";
import {LoginGuardAdmin, LoginGuardHL, LoginGuardMT, LoginGuardSQL} from "./login/login.guard";
import {LoginGuardAdmin, LoginGuardHL} from "./login/login.guard";
import {armyRoutes, armyRoutingComponents} from "./army/army.routing";
import {SignupComponent} from "./login/signup.component";
import {RouteConfig} from "./app.config";

View File

@ -1,4 +1,4 @@
<div style="width: 1100px; margin:auto; position: relative;left: -1%;">
<div style="width: 1100px; margin:auto; position: relative;">
<h1>Übersicht über alle Spieler, Squads und Armeen</h1>
<div class="pull-left" style="width: 45%;">

View File

@ -1,8 +0,0 @@
.search-bar {
padding-top: 20px;
padding-bottom: 20px;
}
.decoration-list {
width: 100%;
}

View File

@ -1,7 +1,5 @@
<div class="decoration-list">
<h2>Übersicht</h2>
<div class="input-group search-bar" style="padding-bottom: 5px; width:100%">
<form class="pull-left form-group">
<div class="select-list">
<div class="input-group list-header pull-left">
<label class="radio-inline">
<input type="radio" name="fractSelect"
[checked]="(fractionRadioSelect == undefined) ? 'true' : 'false'"
@ -27,14 +25,12 @@
#fractRadioGlobal
(change)="filterSquadsByFraction(query.value, fractRadioGlobal.value)">Global
</label>
</form>
<a class="pull-right btn btn-success" (click)="openNewSquadForm()">
Neue Auszeichnung hinzufügen
Auszeichnung hinzufügen
</a>
</div>
<div class="input-group search-bar" style="padding-top: 0;">
<div class="input-group list-header">
<input id="search-tasks"
type="text" #query class="form-control"
(keyup.enter)="findSquads(query.value)"

View File

@ -10,7 +10,7 @@ import {DecorationService} from "../../services/decoration-service/decoration.se
@Component({
selector: 'decoration-list',
templateUrl: './decoration-list.component.html',
styleUrls: ['./decoration-list.component.css']
styleUrls: ['./decoration-list.component.css', '../../style/select-list.css']
})
export class DecorationListComponent implements OnInit {

View File

@ -1,6 +1,5 @@
import {Injectable} from '@angular/core';
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {CookieService} from "ngx-cookie-service";
import {LoginService} from "../services/login-service/login-service";
@Injectable()

View File

@ -1,8 +0,0 @@
.search-bar {
padding-top: 20px;
padding-bottom: 20px;
}
.rank-list {
width: 100%;
}

View File

@ -1,7 +1,6 @@
<div class="rank-list">
<h2>Übersicht</h2>
<div class="input-group search-bar" style="padding-bottom: 5px; width:100%">
<form class="pull-left form-group">
<div class="select-list">
<div class="input-group list-header">
<form class="pull-left">
<label class="radio-inline">
<input type="radio" name="fractSelect"
[checked]="(fractionRadioSelect == undefined) ? 'true' : 'false'"
@ -22,11 +21,11 @@
</label>
</form>
<a class="pull-right btn btn-success" (click)="openNewRankForm()">
Neuen Rang hinzufügen
Rang hinzufügen
</a>
</div>
<div class="input-group search-bar" style="padding-top: 0;">
<div class="input-group list-header">
<input id="search-tasks"
type="text" #query class="form-control"
(keyup.enter)="findRanks(query.value)"

View File

@ -10,7 +10,7 @@ import {RankService} from "../../services/rank-service/rank.service";
@Component({
selector: 'rank-list',
templateUrl: './rank-list.component.html',
styleUrls: ['./rank-list.component.css']
styleUrls: ['./rank-list.component.css', '../../style/select-list.css']
})
export class RankListComponent implements OnInit {

View File

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

View File

@ -8,8 +8,6 @@ import {ConfirmAwardComponent} from "./confirm-award/confirm-award.component";
import {ConfirmPromotionComponent} from "./confirm-promotion/confirm-promotion.component";
import {RequestAwardComponent} from "./award/req-award.component";
import {RequestPromotionComponent} from "./promotion/req-promotion.component";
import {UserService} from "../services/user-service/user.service";
import {UserStore} from "../services/stores/user.store";
@NgModule({
declarations: [RequestComponent, RequestPromotionComponent, RequestAwardComponent, ConfirmPromotionComponent,

View File

@ -1,7 +1,5 @@
<div class="squad-list">
<h2>Übersicht</h2>
<div class="input-group search-bar" style="padding-bottom: 5px; width:100%">
<form class="pull-left form-group">
<div class="select-list">
<div class="input-group list-header pull-left">
<label class="radio-inline">
<input type="radio" name="fractSelect"
[checked]="(fractionRadioSelect == undefined) ? 'true' : 'false'"
@ -20,9 +18,8 @@
#fractRadioOpfor
(change)="filterSquadsByFraction(query.value, fractRadioOpfor.value)">CSAT
</label>
</form>
<a class="pull-right btn btn-success" (click)="openNewSquadForm()">
Neues Squad hinzufügen
Squad hinzufügen
</a>
</div>

View File

@ -10,7 +10,7 @@ import {SquadService} from "../../services/squad-service/squad.service";
@Component({
selector: 'squad-list',
templateUrl: './squad-list.component.html',
styleUrls: ['./squad-list.component.css']
styleUrls: ['./squad-list.component.css', '../../style/select-list.css']
})
export class SquadListComponent implements OnInit {

View File

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

View File

@ -4,10 +4,7 @@
overflow-x: hidden;
border-left: thin solid lightgrey;
bottom: 20px;
width: 80%;
padding-left: 20px;
padding-right: 5%;
padding-top: 70px;
padding: 70px 1% 0 1%;
height: 100vh;
}

View File

@ -1,5 +1,4 @@
<div class="overview fade-in" xmlns="http://www.w3.org/1999/html">
<h2 class="pull-left">Spielerstatistik - {{campaignPlayer.name}}</h2>
<h2 class="pull-right">{{campaignPlayer.campaign.title}} Kampagne</h2>
@ -163,5 +162,4 @@
</ngx-charts-line-chart>
</div>
</div>
</div>

View File

@ -9,7 +9,7 @@ import {Location} from '@angular/common';
@Component({
selector: 'campaign-player-detail',
templateUrl: './campaign-player-detail.component.html',
styleUrls: ['./campaign-player-detail.component.css', '../../style/list-entry.css']
styleUrls: ['./campaign-player-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css']
})
export class CampaignPlayerDetailComponent {

View File

@ -3,7 +3,7 @@
min-width: 880px;
height: 650px;
margin: auto;
padding-left: 6%;
padding-left: 5%;
}
:host /deep/ .carousel-indicators {

View File

@ -1,71 +1,32 @@
<div class="slide-chart-container" style="height: 150px;">
<h2 style="margin-bottom: 20px">{{title}}</h2>
<div class="btn btn-default" [style.background]="activeSlideIndex === 2 ? '#d9edf7':'white'"
(click)="goToSlide(2)" *ngIf="id != 'all'">Gesamtpunktzahl
<div class="btn btn-default" [style.background]="isActiveSlide(0)"
(click)="goToSlide(0)" *ngIf="id != 'all'">Gesamtpunktzahl
</div>
<div class="btn btn-default" [style.background]="activeSlideIndex === 0 ? '#d9edf7':'white'"
(click)="goToSlide(0)">Punkte je Schlacht
<div class="btn btn-default" [style.background]="isActiveSlide(1)"
(click)="goToSlide(1)">Punkte je Schlacht
</div>
<div class="btn btn-default" [style.background]="isActiveSlide(2)"
(click)="goToSlide(2)">Spielerzahlen
</div>
</div>
<div class="fade-in">
<div class="slide-chart-container">
<ngx-charts-line-chart
[scheme]="colorScheme"
[results]="currentData"
[gradient]="gradient"
[xAxis]="xAxis"
[yAxis]="yAxis"
[legend]="legend"
[legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[yAxisLabel]="yAxisLabel"
[autoScale]="autoscale"
[timeline]="timeline">
</ngx-charts-line-chart>
</div>
<div class="btn btn-default" [style.background]="activeSlideIndex === 1 ? '#d9edf7':'white'"
(click)="goToSlide(1)">Spielerzahlen
</div>
<carousel class="fade-in" [(activeSlide)]="activeSlideIndex">
<slide *ngIf="id != 'all'">
<div class="slide-chart-container">
<h3>Gesamtpunktzahl</h3>
<ngx-charts-line-chart
[scheme]="colorScheme"
[results]="pointSumData"
[gradient]="gradient"
[xAxis]="xAxis"
[yAxis]="yAxis"
[legend]="legend"
[legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[yAxisLabel]="'Gesamtpunkte'"
[autoScale]="autoscale"
[timeline]="timeline">
</ngx-charts-line-chart>
</div>
</slide>
<slide>
<div class="slide-chart-container">
<h3>Punkte je Schlacht</h3>
<ngx-charts-line-chart
[scheme]="colorScheme"
[results]="pointData"
[gradient]="gradient"
[xAxis]="xAxis"
[yAxis]="yAxis"
[legend]="legend"
[legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[yAxisLabel]="'Punkte'"
[autoScale]="autoscale"
[timeline]="timeline">>
</ngx-charts-line-chart>
</div>
</slide>
<slide>
<div class="slide-chart-container">
<h3>Spielerzahlen</h3>
<ngx-charts-line-chart
[scheme]="colorScheme"
[results]="playerData"
[gradient]="gradient"
[xAxis]="xAxis"
[yAxis]="yAxis"
[legend]="legend"
[legendTitle]="legendTitle"
[showXAxisLabel]="showXAxisLabel"
[showYAxisLabel]="showYAxisLabel"
[yAxisLabel]="'Anzahl Spieler'"
[autoScale]="autoscale"
[timeline]="timeline">
</ngx-charts-line-chart>
</div>
</slide>
</carousel>

View File

@ -16,11 +16,12 @@ export class StatisticOverviewComponent {
id = "";
title = "";
activeSlideIndex: number = 0;
pointData: any[] = [];
pointSumData: any[] = [];
playerData: any[] = [];
currentData: any[] = [];
activeSlideIndex;
colorScheme = {
domain: ['#0000FF', '#B22222']
@ -33,9 +34,11 @@ export class StatisticOverviewComponent {
legendTitle = '';
showXAxisLabel = true;
showYAxisLabel = true;
yAxisLabel = "";
autoscale = true;
timeline = false;
constructor(private route: ActivatedRoute,
private campaignService: CampaignService) {
}
@ -63,10 +66,7 @@ export class StatisticOverviewComponent {
if (this.id === 'all') {
this.title = "Gesamtübersicht";
} else {
this.title = campaign.title
setTimeout(() => {
this.activeSlideIndex = 2;
}, 10)
this.title = campaign.title;
}
wars = wars.concat(campaign.wars);
itemsProcessed++;
@ -77,7 +77,22 @@ export class StatisticOverviewComponent {
}
goToSlide(index: number) {
switch (index) {
case 0:
this.currentData = this.pointSumData;
this.yAxisLabel = "Gesamtpunkte";
break;
case 1:
this.currentData = this.pointData;
this.yAxisLabel = "Punkte";
break;
case 2:
this.currentData = this.playerData;
this.yAxisLabel = "Anzahl Spieler";
break;
}
this.activeSlideIndex = index;
}
initChart(wars: any[]) {
@ -130,7 +145,16 @@ export class StatisticOverviewComponent {
this.pointData = pointsObj;
this.pointSumData = pointsSumObj;
this.playerData = playersObj;
Object.assign(this, [this.pointData, this.pointSumData, this.playerData]);
if (this.id != 'all') {
this.goToSlide(0);
} else {
this.goToSlide(1);
}
Object.assign(this, this.currentData);
}
isActiveSlide(index) {
return this.activeSlideIndex === index ? '#d9edf7':'white'
}
}

View File

@ -1,13 +1,26 @@
.vertical-spacer {
height: 100vh;
float: left;
width: 4%;
}
@media screen and (min-width: 1500px) {
.vertical-spacer {
width: 15%;
}
}
@media screen and (min-width: 2000px) {
.vertical-spacer {
width: 20%;
}
}
.overview {
position: fixed;
overflow-y: scroll;
overflow-x: hidden;
border-left: thin solid lightgrey;
bottom: 20px;
width: 100%;
padding-left: 50px;
padding-top: 70px;
margin-left: 10px;
height: 100vh;
}

View File

@ -1,6 +1,8 @@
<div class="overview fade-in" xmlns="http://www.w3.org/1999/html">
<div style="min-height: 263px;">
<div class=vertical-spacer>
</div>
<div style="overflow:hidden">
<div style="width: 920px;min-height: 263px;">
<h2>{{war.title}} - vom {{war.date | date: 'dd.MM.yyyy'}}</h2>
<h3 class="pull-left" style="width: 250px">
<h4>Endpunktestand:</h4>
@ -80,5 +82,6 @@
<ngx-datatable-column [width]="100" name="Tod" prop="death"></ngx-datatable-column>
<ngx-datatable-column [width]="100" name="Respawn" prop="respawn"></ngx-datatable-column>
</ngx-datatable>
</div>
</div>

View File

@ -7,7 +7,7 @@ import {War} from "../../models/model-interfaces";
@Component({
selector: 'war-detail',
templateUrl: './war-detail.component.html',
styleUrls: ['./war-detail.component.css', '../../style/list-entry.css']
styleUrls: ['./war-detail.component.css', '../../style/list-entry.css', '../../style/hide-scrollbar.css']
})
export class WarDetailComponent {

View File

@ -3,7 +3,7 @@
<div class="row">
<div class="col-xs-9">
<span>
<a>{{war.title}}</a>
<a style="font-size: 22px;">{{war.title}}</a>
</span>
<br>
<small>vom {{war.date | date: 'dd.MM.yyyy'}}</small>

View File

@ -1,7 +1,3 @@
.war-list {
padding-top: 30px;
}
:host /deep/ .card-header {
background-color: rgba(34, 34, 34, 0.80);
cursor: pointer;

View File

@ -1,5 +1,5 @@
<div class="war-list">
<div class="input-group search-bar" style="margin-bottom:12px; width:100%;" *ngIf="loginService.hasPermission(3)">
<div class="select-list">
<div class="input-group list-header" *ngIf="loginService.hasPermission(3)">
<a class="pull-left btn btn-success" (click)="selectNewWar()">
Schlacht hinzufügen
</a>
@ -25,7 +25,7 @@
<div class="row">
<div class="col-xs-9">
<span style="margin:auto">
<a>Kampagnenübersicht</a>
<a style="font-size: 22px;">Kampagnenübersicht</a>
</span>
</div>
</div>
@ -47,7 +47,7 @@
<div class="row">
<div class="col-xs-9">
<span style="margin:auto">
<a>Gesamtübersicht</a>
<a style="font-size: 22px;">Gesamtübersicht</a>
</span>
</div>
</div>

View File

@ -4,11 +4,12 @@ import {Campaign, War} from "../../models/model-interfaces";
import {WarService} from "../../services/war-service/war.service";
import {LoginService} from "../../services/login-service/login-service";
import {CampaignService} from "../../services/campaign-service/campaign.service";
import {RouteConfig} from "../../app.config";
@Component({
selector: 'war-list',
templateUrl: './war-list.component.html',
styleUrls: ['./war-list.component.css', '../../style/list-entry.css']
styleUrls: ['./war-list.component.css', '../../style/list-entry.css', '../../style/select-list.css']
})
export class WarListComponent implements OnInit {
@ -25,9 +26,19 @@ export class WarListComponent implements OnInit {
ngOnInit() {
this.campaignService.getAllCampaigns().subscribe((items) => {
const subPathWar = 'war/';
const subPathOverview = 'overview/';
this.campaignService.campaigns = items;
this.campaigns = items;
const url = this.router.url;
if (url.endsWith(RouteConfig.statsPath)) {
this.selectOverview(this.campaigns[0]._id);
} else if (url.indexOf(subPathWar) !== -1) {
this.selectedWarId = url.substring(url.lastIndexOf(subPathWar) + subPathWar.length, url.lastIndexOf(")"));
} else if (url.indexOf(subPathOverview) !== -1) {
this.selectedWarId = url.substring(url.lastIndexOf(subPathOverview) + subPathOverview.length, url.lastIndexOf(")"));
}
});
}

View File

@ -0,0 +1,9 @@
::-webkit-scrollbar {
/*width: 0px; !* remove scrollbar space *!*/
background: transparent; /* just make scrollbar invisible */
}
/* show position indicator in red */
::-webkit-scrollbar-thumb {
background: rgb(234, 234, 234);
}

View File

@ -4,6 +4,7 @@
left: 50%;
transform: translate(-50%, -50%);
width: 50%;
z-index: 1;
}
.load-arrow {

View File

@ -0,0 +1,8 @@
.select-list {
padding: 20px 2% 0 5%;
}
.list-header {
width: 100%;
padding-bottom: 20px;
}

View File

@ -1,18 +0,0 @@
.search-bar {
padding-top: 20px;
padding-bottom: 20px;
}
.user-list {
width: 100%;
}
.fraction-blufor {
color: mediumblue;
font-weight: bold;
}
.fraction-opfor {
color: red;
font-weight: bold;
}

View File

@ -1,7 +1,5 @@
<div class="user-list">
<h2>Übersicht</h2>
<div class="input-group search-bar" style="padding-bottom: 5px; width:100%">
<form class="pull-left form-group">
<div class="select-list">
<div class="input-group list-header pull-left">
<label class="radio-inline">
<input type="radio" name="fractSelect"
[checked]="(fractionRadioSelect == undefined) ? 'true' : 'false'"
@ -27,13 +25,12 @@
#fractRadioUnassigned
(change)="filterUsersByFraction(query.value, fractRadioUnassigned.value)">Ohne Squad
</label>
</form>
<a class="pull-right btn btn-success" (click)="openNewUserForm()">
Neuen Teilnehmer hinzufügen
Teilnehmer hinzufügen
</a>
</div>
<div class="input-group search-bar" style="padding-top: 0;">
<div class="input-group list-header">
<input id="search-tasks"
type="text" #query class="form-control"
(keyup.enter)="findUsers(query.value)"

View File

@ -10,7 +10,7 @@ import {User} from "../../models/model-interfaces";
@Component({
selector: 'squad-list',
templateUrl: './user-list.component.html',
styleUrls: ['./user-list.component.css']
styleUrls: ['./user-list.component.css', '../../style/select-list.css']
})
export class UserListComponent implements OnInit {

View File

@ -1,7 +1,5 @@
import {NgModule} from '@angular/core';
import {routes, usersRoutingComponents} from './users.routing';
import {UserStore} from "../services/stores/user.store";
import {UserService} from "../services/user-service/user.service";
import {CommonModule} from "@angular/common";
import {SharedModule} from "../shared.module";

View File

@ -1,7 +1,5 @@
body {
padding-left: 20px;
padding-top: 50px;
}
.tabs-container {
@ -44,11 +42,8 @@ form {
min-width: 350px;
max-width: 450px;
float: left;
padding-right: 10px;
}
#right {
overflow: hidden;
padding-left: 4%;
}