Merge pull request #4 from alexfriesen/gh-pages

PlayerInfo, Console & Connection improved
This commit is contained in:
Garry Newman
2016-06-02 15:50:40 +01:00
10 changed files with 321 additions and 113 deletions
+31 -37
View File
@@ -1,57 +1,51 @@
<div ng-controller="ConnectionController" class="row"> <div ng-controller="ConnectionController" class="row">
<div class="col-md-offset-4 col-md-6 panel" style="margin-top: 128px"> <div class="col-md-offset-4 col-md-6 panel jumbotron" style="margin-top: 128px">
<h2>Connect</h2> <h2>Connect</h2>
<div class="alert alert-danger" ng-show="LastErrorMessage != null">{{LastErrorMessage}}</div> <div class="alert alert-danger" ng-show="LastErrorMessage != null">{{LastErrorMessage}}</div>
<p>Enter the address (including rcon port) and the rcon password below to connect.</p> <p>Enter the address (including rcon port) and the rcon password below to connect.</p>
<form ng-submit="Connect()"> <form ng-submit="Connect()">
<div class="md-inline-form"> <div class="md-inline-form">
<div class="md-block" flex-gt-xs>
<label>Address</label>
<input required minlength=5 ng-model="Address" name="Address" class="form-control">
</div>
<div class="md-block" flex-gt-xs>
<label>Password</label>
<input required minlength=2 type="password" ng-model="Password" name="Password" class="form-control">
</div>
<div class="right">
<input type="checkbox" ng-model="SaveConnection">
Save Connection
</div>
<br /> <br />
<div class="center">
<button class="btn btn-primary" ng-click="Connect()">Connect</button>
</div>
<br />
<div class="md-block form-group" flex-gt-xs>
<label for="conncetion-adress">Address</label>
<input required minlength=5 ng-model="Address" name="Address" class="form-control" placeholder="xxx.xxx.xxx.xxx:28016" id="conncetion-adress">
</div> </div>
</form> <div class="md-block form-group" flex-gt-xs>
</div> <label for="conncetion-password">Password</label>
<input required minlength=2 type="password" ng-model="Password" name="Password" class="form-control" id="conncetion-password">
</div>
<div class="col-md-offset-4 col-md-6 panel" style="margin-top: 64px"> <div class="checkbox right">
<label>
<input type="checkbox" ng-model="SaveConnection"> Save Connection
</label>
</div>
<button type="submit" class="btn btn-primary btn-block" ng-click="Connect()">Connect</button>
</div>
</form>
</div>
<div class="col-md-offset-4 col-md-6 panel jumbotron">
<div ng-show="PreviousConnects.length > 0"> <div ng-show="PreviousConnects.length > 0">
<h2>Saved Connections</h2> <h2>Saved Connections</h2>
<ul ng-repeat="c in PreviousConnects"> <ul ng-repeat="c in PreviousConnects | orderBy:array:true | limitTo:connectionsLimit">
<li><a ng-click="ConnectTo( c )" href="#">{{c.Address}}</a></li> <li><a ng-click="ConnectTo( c )" href="#/{{c.Address}}/info">{{c.Address}}</a> - {{c.date | date:'short'}}</li>
</ul> </ul>
<div ng-show="PreviousConnects.length > connectionsLimit || connectionsLimit === undefined">
<button type="submit" class="btn btn-primary btn-block" ng-click="toggleConnectionsLimit()">Show {{(connectionsLimit === undefined) ? 'less' : 'more'}}</button>
</div>
</div> </div>
</div> </div>
</div>
</div> </div>
+4 -4
View File
@@ -1,11 +1,11 @@
<div ng-controller="ConsoleController" id="ConsoleController"> <div ng-controller="ConsoleController" id="ConsoleController">
<div id="vertical-container" style="height: 600px" class="Output scrollable"><div ng-repeat="line in Output" ng-class="line.Class">{{line.Message}}</div></div> <div id="vertical-container" style="height: 600px" class="Output scrollable">
<div ng-repeat="line in Output" ng-class="line.Class">{{line.Message}}</div>
</div>
<form ng-submit="SubmitCommand()" class="md-inline-form"> <form ng-submit="SubmitCommand()" class="md-inline-form">
<div> <input type="text" class="form-control" ng-model="Command" ng-keyup="KeyUp($event)" />
<input class="form-control" ng-model="Command" style="width: 100%">
</div>
</form> </form>
</div> </div>
+41 -3
View File
@@ -1,9 +1,47 @@
<div ng-controller="PlayerInfoController" flex layout="column" id="PlayerInfoController"> <div ng-controller="PlayerInfoController" flex layout="column" id="PlayerInfoController">
Info about player {{userid}} <div class="row">
<p>View <a href="#/{{address}}/player/{{userid}}/xp">XP info for this player</a></p> <div class="col-lg-12">
Show info about this player here
<h2 class="center">
Player: {{getUsername()}}
<div class="btn-group pull-right">
<button ng-click="refresh()" class="btn btn-default" type="button"><i class="glyphicon glyphicon-refresh"></i></button>
</div>
</h2>
<div class="btn-group btn-group-lg btn-group-justified">
<div class="btn-group">
<a href="#/{{address}}/player/{{userid}}/xp" class="btn btn-default">
<span class="glyphicon glyphicon-education"></span>
XP Info
</a>
</div>
<div class="btn-group">
<a href="http://www.steamcommunity.com/profiles/{{userid}}" target="_blank" class="btn btn-default">
<span class="glyphicon glyphicon-info-sign"></span>
Steam Profile
</a>
</div>
</div>
</div>
<div class="col-lg-12">
<h2 class="center">
Info
</h2>
<div class="alert alert-warning" ng-show="!info">
This Player is currently not connected to this server!
</div>
</div>
<div class="col-sm-4" ng-repeat="(key, value) in info">
<p>{{key}}: <span class="badge">{{value}}</span></p>
</div>
</div>
</div> </div>
+17 -1
View File
@@ -33,8 +33,24 @@
<span class="glyphicon glyphicon-cog"></span> <span class="caret"></span> <span class="glyphicon glyphicon-cog"></span> <span class="caret"></span>
</button> </button>
<ul class="dropdown-menu"> <ul class="dropdown-menu">
<li>
<a href="#/{{address}}/player/{{line.SteamID}}/xp">
<span class="glyphicon glyphicon-education"></span>
XP Info
</a>
</li>
<li> <li>
<a href ng-click="KickPlayer(line.SteamID)">Kick</a> <a href="http://www.steamcommunity.com/profiles/{{line.SteamID}}" target="_blank">
<span class="glyphicon glyphicon-info-sign"></span>
Steam Profile
</a>
</li>
<li class="divider"></li>
<li>
<a href ng-click="KickPlayer(line.SteamID)">
<span class="glyphicon glyphicon-trash"></span>
Kick
</a>
</li> </li>
</ul> </ul>
</div> </div>
+18 -40
View File
@@ -12,64 +12,42 @@
</h2> </h2>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Map: {{info.Map}}</p>
<p>Map: {{info.Map}}</p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Max Players: {{info.MaxPlayers}}</p>
<p>Max Players: {{info.MaxPlayers}}</p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>GameTime: {{info.GameTime}}</p>
<p>GameTime: {{info.GameTime}}</p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Framerate: <span class="badge">{{info.Framerate}}</span></p>
<p>Framerate: <span class="badge">{{info.Framerate}}</span></p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>EntityCount: <span class="badge">{{info.EntityCount}}</span></p>
<p>EntityCount: <span class="badge">{{info.EntityCount}}</span></p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Uptime: <span class="badge">{{info.Uptime}}</span></p>
<p>Uptime: <span class="badge">{{info.Uptime}}s</span></p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Players: <span class="badge">{{info.Players}}</span></p>
<p>Players: <span class="badge">{{info.Players}}</span></p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Joining: <span class="badge">{{info.Joining}}</span></p>
<p>Joining: <span class="badge">{{info.Joining}}</span></p>
</div>
</div> </div>
<div class="col-lg-4"> <div class="col-sm-4">
<div class="container"> <p>Queued: <span class="badge">{{info.Queued}}</span></p>
<p>Queued: <span class="badge">{{info.Queued}}</span></p>
</div>
</div> </div>
</div> </div>
<div class="right row">
</div>
</div> </div>
+54 -6
View File
@@ -7,11 +7,51 @@ function ConnectionController( $scope, rconService, $routeParams, $timeout, $loc
$scope.Password = ""; $scope.Password = "";
$scope.SaveConnection = true; $scope.SaveConnection = true;
if ( localStorage.previousConnections != null ) $scope.connectionsLimit = 5;
$scope.PreviousConnects = angular.fromJson( localStorage.previousConnections );
if ( $scope.PreviousConnects == null ) function _loadFromLocalStorage() {
$scope.PreviousConnects = new Array(); var connections = [];
// load and parse from local storage
if ( localStorage && localStorage.previousConnections ) {
connections = angular.fromJson( localStorage.previousConnections );
}
// double check
if ( !connections ) {
connections = [];
}
return connections;
}
function _addWithoutDuplicates(connections, connection) {
// prepare new array
var filteredConnections = [];
for(var i in connections) {
if(connections[i].Address !== connection.Address && connections[i].Password !== connection.Password) {
// add old connection info to our new array
filteredConnections.push(connections[i]);
}
}
// add new connection
filteredConnections.push(connection);
return filteredConnections;
}
$scope.toggleConnectionsLimit = function ()
{
// toggle limit between undefined and 5
// undefined sets limit to max
if($scope.connectionsLimit === undefined) {
$scope.connectionsLimit = 5;
} else {
$scope.connectionsLimit = undefined;
}
}
$scope.Connect = function () $scope.Connect = function ()
{ {
@@ -42,11 +82,19 @@ function ConnectionController( $scope, rconService, $routeParams, $timeout, $loc
{ {
if ( $scope.SaveConnection ) if ( $scope.SaveConnection )
{ {
$scope.PreviousConnects.push( { Address: $scope.Address, Password: $scope.Password } ); // new connection to add
var connection = { Address: $scope.Address, Password: $scope.Password, date: new Date() };
// remove old entries and add our new connection info
var connections = _addWithoutDuplicates(_loadFromLocalStorage(), connection);
// push to scope and save data
$scope.PreviousConnects = connections;
localStorage.previousConnections = angular.toJson( $scope.PreviousConnects ); localStorage.previousConnections = angular.toJson( $scope.PreviousConnects );
} }
} ); } );
$scope.PreviousConnects = _loadFromLocalStorage();
// //
// If a server address is passed in.. try to connect if we have a saved entry // If a server address is passed in.. try to connect if we have a saved entry
@@ -83,5 +131,5 @@ function ConnectionController( $scope, rconService, $routeParams, $timeout, $loc
} }
}, 20 ); }, 20 );
}
}
+103 -15
View File
@@ -3,38 +3,114 @@ app.controller( 'ConsoleController', ConsoleController );
function ConsoleController( $scope, rconService, $timeout ) function ConsoleController( $scope, rconService, $timeout )
{ {
$scope.Output = new Array(); $scope.Output = [];
$scope.commandHistory = [];
$scope.commandHistoryIndex = 0;
$scope.KeyUp = function (event)
{
switch(event.keyCode) {
// Arrow Key Up
case 38:
// rotate through commandHistory
$scope.commandHistoryIndex--;
if($scope.commandHistoryIndex < 0) {
$scope.commandHistoryIndex = $scope.commandHistory.length;
}
// set command from history
if($scope.commandHistory[$scope.commandHistoryIndex]) {
$scope.Command = $scope.commandHistory[$scope.commandHistoryIndex];
}
break;
// Arrow Key Down
case 40:
// rotate through commandHistory
$scope.commandHistoryIndex++;
if($scope.commandHistoryIndex >= $scope.commandHistory.length) {
$scope.commandHistoryIndex = 0;
}
// set command from history
if($scope.commandHistory[$scope.commandHistoryIndex]) {
$scope.Command = $scope.commandHistory[$scope.commandHistoryIndex];
}
break;
default:
// reset command history index
$scope.commandHistoryIndex = $scope.commandHistory.length;
break;
}
}
$scope.SubmitCommand = function () $scope.SubmitCommand = function ()
{ {
$scope.OnMessage( { Message: $scope.Command, Type: 'Command' } ) $scope.OnMessage( { Message: $scope.Command, Type: 'Command' } );
$scope.commandHistory.push($scope.Command);
rconService.Command( $scope.Command, 1 ); rconService.Command( $scope.Command, 1 );
$scope.Command = ""; $scope.Command = "";
$scope.commandHistoryIndex = 0;
} }
$scope.$on( "OnMessage", function ( event, msg ) { $scope.OnMessage( msg ); } ); $scope.$on( "OnMessage", function ( event, msg ) { $scope.OnMessage( msg ); } );
$scope.OnMessage = function( msg ) $scope.OnMessage = function( msg )
{ {
if ( msg.Message.startsWith( "[rcon] " ) ) return; if ( msg.Message.startsWith( "[rcon] " ) ) {
if ( msg.Type != "Generic" && msg.Type != "Log" && msg.Type != "Error" && msg.Type != "Warning" )
{
console.log( msg );
return; return;
} }
msg.Class = msg.Type; switch(msg.Type) {
$scope.Output.push( msg ); case 'Generic':
case 'Log':
case 'Error':
case 'Warning':
$scope.addOutput(msg);
break;
$timeout( $scope.ScrollToBottom, 50 ); default:
console.log( msg );
return;
}
} }
$scope.ScrollToBottom = function() $scope.ScrollToBottom = function()
{ {
// TODO - don't scroll if we're not at the bottom ! var element = $( "#ConsoleController .Output" );
$( "#ConsoleController .Output" ).scrollTop( $( "#ConsoleController .Output" )[0].scrollHeight );
$timeout( function() {
element.scrollTop( element.prop('scrollHeight') );
}, 50 );
}
$scope.isOnBottom = function()
{
// get jquery element
var element = $( "#ConsoleController .Output" );
// height of the element
var height = element.height();
// scroll position from top position
var scrollTop = element.scrollTop();
// full height of the element
var scrollHeight = element.prop('scrollHeight');
if((scrollTop + height) > (scrollHeight - 10)) {
return true;
}
return false;
} }
// //
@@ -43,15 +119,27 @@ function ConsoleController( $scope, rconService, $timeout )
// //
$scope.GetHistory = function () $scope.GetHistory = function ()
{ {
console.log( "GetHistory" );
rconService.Request( "console.tail 128", $scope, function ( msg ) rconService.Request( "console.tail 128", $scope, function ( msg )
{ {
var messages = JSON.parse( msg.Message ); var messages = JSON.parse( msg.Message );
messages.forEach( function ( x ) { $scope.OnMessage( x ); } ); messages.forEach( function ( msg ) {
$scope.OnMessage( msg );
});
$scope.ScrollToBottom();
} ); } );
} }
$scope.addOutput = function (msg)
{
msg.Class = msg.Type;
$scope.Output.push( msg );
if($scope.isOnBottom()) {
$scope.ScrollToBottom();
}
}
rconService.InstallService( $scope, $scope.GetHistory ) rconService.InstallService( $scope, $scope.GetHistory )
} }
+35
View File
@@ -4,4 +4,39 @@ app.controller( 'PlayerInfoController', PlayerInfoController );
function PlayerInfoController( $scope, rconService, $routeParams ) function PlayerInfoController( $scope, rconService, $routeParams )
{ {
$scope.userid = $routeParams.userid; $scope.userid = $routeParams.userid;
$scope.info = null;
$scope.refresh = function ()
{
rconService.getPlayers($scope, function(players) {
for(var i in players) {
if(players[i].SteamID === $scope.userid){
// set player data
$scope.info = players[i];
return;
}
}
// player not found
// reset data to null
$scope.info = null;
});
}
$scope.getUsername = function ()
{
// try to find players name in info
if($scope.info && $scope.info.DisplayName) {
return $scope.info.DisplayName;
}
// otherwise show the id
return $scope.userid;
}
rconService.InstallService( $scope, $scope.refresh )
} }
+3 -3
View File
@@ -3,14 +3,14 @@ app.controller( 'PlayerListController', PlayerListController );
function PlayerListController( $scope, rconService, $interval ) function PlayerListController( $scope, rconService, $interval )
{ {
$scope.Output = new Array(); $scope.Output = [];
$scope.OrderBy = '-ConnectedSeconds'; $scope.OrderBy = '-ConnectedSeconds';
$scope.Refresh = function () $scope.Refresh = function ()
{ {
rconService.Request( "playerlist", $scope, function ( msg ) rconService.getPlayers($scope, function ( players )
{ {
$scope.Players = JSON.parse( msg.Message ); $scope.Players = players;
}); });
} }
+14 -3
View File
@@ -1,9 +1,9 @@
function RconService() function RconService()
{ {
var s = {}; var s = {
Callbacks: {}
s.Callbacks = {}; };
s.Connect = function ( addr, pass ) s.Connect = function ( addr, pass )
{ {
@@ -102,5 +102,16 @@ function RconService()
} }
} }
s.getPlayers = function(scope, success) {
this.Request( "playerlist", scope, function ( response )
{
var players = JSON.parse( response.Message );
if(typeof success === 'function') {
success.call(scope, players);
}
});
}
return s; return s;
} }