Initial Commit of Files

PufferPanel v0.9 (Laravel) is now Pterodactyl 1.0
This commit is contained in:
Dane Everitt 2015-12-06 13:58:49 -05:00
commit 1489f7a694
154 changed files with 10159 additions and 0 deletions

View file

@ -0,0 +1,2 @@
// @import "node_modules/bootstrap-sass/assets/stylesheets/bootstrap";

View file

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Authentication Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used during authentication for various
| messages that we need to display to the user. You are free to modify
| these language lines according to your application's requirements.
|
*/
'failed' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
'errorencountered' => 'There was an error encountered while attempting to process this request.',
'resetpassword' => 'Reset Password',
'remeberme' => 'Remeber Me',
];

View file

@ -0,0 +1,43 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Base Pterodactyl Language
|--------------------------------------------------------------------------
|
| These base strings are used throughout the front-end of Pterodactyl but
| not on pages that are used when viewing a server. Those keys are in server.php
|
*/
'failed' => 'These credentials do not match our records.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
'view_as_admin' => 'You are viewing this server listing as an admin. As such, all servers installed on the system are displayed. Any servers that you are set as the owner of are marked with a blue dot to the left of their name.',
'server_name' => 'Server Name',
'no_servers' => 'You do not currently have any servers listed on your account.',
'form_error' => 'The following errors were encountered while trying to process this request.',
'password_req' => 'Passwords must meet the following requirements: at least one uppercase character, one lowercase character, one digit, and be at least 8 characters in length.',
'account' => [
'totp_header' => 'Two-Factor Authentication',
'totp_qr' => 'TOTP QR Code',
'totp_enable_help' => 'It appears that you do not have Two-Factor authentication enabled. This method of authentication adds an additional barrier preventing unauthorized entry to your account. If you enable it you will be required to input a code generated on your phone or other TOTP supporting device before finishing your login.',
'totp_apps' => 'You must have a TOTP supporting application (e.g Google Authenticator, DUO Mobile, Authy) to use this option.',
'totp_enable' => 'Enable Two-Factor Authentication',
'totp_disable' => 'Disable Two Factor Authentication',
'totp_token' => 'TOTP Token',
'totp_disable_help' => 'In order to disable TOTP on this account you will need to provide a valid TOTP token. Once validated TOTP protection on this account will be disabled.',
'totp_checkpoint_help' => 'Please verify your TOTP settings by scanning the QR Code to the right with your phone\'s authenticator application, and then enter the 6 number code generated by the application in the box below. Press the enter key when finished.',
'totp_enabled' => 'Your account has been enabled with TOTP verification. Please click the close button on this box to finish.',
'totp_enabled_error' => 'The TOTP token provided was unable to be verified. Please try again.',
'update_email' => 'Update Email',
'new_email' => 'New Email',
'new_password' => 'New Password',
'update_pass' => 'Update Password'
]
];

View file

@ -0,0 +1,30 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Previous',
'next' => 'Next &raquo;',
'sidebar' => [
'account_controls' => 'Account Controls',
'account_settings' => 'Account Settings',
'account_security' => 'Account Security',
'server_controls' => 'Server Controls',
'servers' => 'Your Servers',
'overview' => 'Server Overview',
'files' => 'File Manager',
'subusers' => 'Manage Sub-Users',
'manage' => 'Manage Server',
],
];

View file

@ -0,0 +1,22 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reminder Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Passwords must be at least six characters and match the confirmation.',
'reset' => 'Your password has been reset!',
'sent' => 'We have e-mailed your password reset link!',
'token' => 'This password reset token is invalid.',
'user' => "We can't find a user with that e-mail address.",
];

View file

@ -0,0 +1,35 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pterodactyl Language Strings for /server/{server} Routes
|--------------------------------------------------------------------------
*/
'ajax' => [
'socket_error' => 'We were unable to connect to the main Socket.IO server, there may be network issues currently. <br /><br />If this is your first time seeing this message it may be because you need to accept this server\'s SSL certificate. Please click this notification and accept the certificate.',
'socket_status' => 'This server\'s power status has changed to',
'socket_status_crashed' => 'This server has been detected as CRASHED.',
],
'index' => [
'memory_use' => 'Memory Usage',
'cpu_use' => 'CPU Usage',
'xaxis' => 'Time (2s Increments)',
'server_info' => 'Server Information',
'connection' => 'Default Connection',
'mem_limit' => 'Memory Limit',
'disk_space' => 'Disk Space',
'control' => 'Control Server',
'info_use' => 'Information & Usage',
'command' => 'Enter Console Command',
],
'files' => [
'loading' => 'Loading file listing, this might take a few seconds...',
'yaml_notice' => 'You are currently editing a YAML file. These files do not accept tabs, they must use spaces. We\'ve gone ahead and made it so that hitting tab will insert :dropdown spaces.',
'back' => 'Back to File Manager',
'saved' => 'File has successfully been saved.',
],
];

View file

@ -0,0 +1,30 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Standalone Pterodactyl Language Strings
|--------------------------------------------------------------------------
*/
'login' => 'Login',
'password' => 'Password',
'email' => 'Email',
'whoops' => 'Whoops',
'location' => 'Location',
'node' => 'Node',
'connection' => 'Connection',
'language' => 'Language',
'close' => 'Close',
'start' => 'Start',
'stop' => 'Stop',
'restart' => 'Restart',
'save' => 'Save',
'enabled' => 'Enabled',
'disabled' => 'Disabled',
'submit' => 'Submit',
'current_password' => 'Current Password',
'again' => 'Again',
];

View file

@ -0,0 +1,109 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Validation Language Lines
|--------------------------------------------------------------------------
|
| The following language lines contain the default error messages used by
| the validator class. Some of these rules have multiple versions such
| as the size rules. Feel free to tweak each of these messages here.
|
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'email' => 'The :attribute must be a valid email address.',
'exists' => 'The selected :attribute is invalid.',
'filled' => 'The :attribute field is required.',
'image' => 'The :attribute must be an image.',
'in' => 'The selected :attribute is invalid.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'json' => 'The :attribute must be a valid JSON string.',
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'numeric' => 'The :attribute must be a number.',
'regex' => 'The :attribute format is invalid.',
'required' => 'The :attribute field is required.',
'required_if' => 'The :attribute field is required when :other is :value.',
'required_with' => 'The :attribute field is required when :values is present.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'url' => 'The :attribute format is invalid.',
/*
|--------------------------------------------------------------------------
| Custom Validation Language Lines
|--------------------------------------------------------------------------
|
| Here you may specify custom validation messages for attributes using the
| convention "attribute.rule" to name the lines. This makes it quick to
| specify a specific custom language line for a given attribute rule.
|
*/
'custom' => [
'attribute-name' => [
'rule-name' => 'custom-message',
],
],
/*
|--------------------------------------------------------------------------
| Custom Validation Attributes
|--------------------------------------------------------------------------
|
| The following language lines are used to swap attribute place-holders
| with something more reader friendly such as E-Mail Address instead
| of "email". This simply helps us make messages a little cleaner.
|
*/
'attributes' => [],
];

View file

@ -0,0 +1,43 @@
@extends('layouts.admin')
@section('title')
Account List
@endsection
@section('content')
<div class="col-md-9">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Accounts</li>
</ul>
<h3>All Registered Users</h3><hr />
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th>Username</th>
<th>Email</th>
<th>Account Created</th>
<th>Account Updated</th>
</tr>
</thead>
<tbody>
@foreach ($users as $user)
<tr>
<td><a href="/admin/accounts/view/{{ $user->id }}">@if($user->username !== null){{ $user->username }}@else[unregistered subuser]@endif</a> @if($user->root_admin === 1)<span class="badge">Administrator</span>@endif</td>
<td><code>{{ $user->email }}</code></td>
<td>{{ $user->created_at }}</td>
<td>{{ $user->updated_at }}</td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $users->render() !!}</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/accounts']").addClass('active');
});
</script>
@endsection

View file

@ -0,0 +1,20 @@
@extends('layouts.admin')
@section('title')
Administration
@endsection
@section('content')
<div class="col-md-9">
<ul class="breadcrumb">
<li class="active">Admin Control</li>
</ul>
<h3 class="nopad">Pterodactyl Admin Control Panel</h3><hr />
<p>Welcome to the most advanced, lightweight, and user-friendly open source game server control panel.</p>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin']").addClass('active');
});
</script>
@endsection

View file

@ -0,0 +1,45 @@
@extends('layouts.admin')
@section('title')
Server List
@endsection
@section('content')
<div class="col-md-9">
<ul class="breadcrumb">
<li><a href="/admin">Admin Control</a></li>
<li class="active">Servers</li>
</ul>
<h3>All Servers</h3><hr />
<table class="table table-bordered table-hover">
<thead>
<tr>
<th>Server Name</th>
<th>Owner</th>
<th>Node</th>
<th>Default Connection</th>
<th>SFTP Username</th>
</tr>
</thead>
<tbody>
@foreach ($servers as $server)
<tr class="dynUpdate @if($server->active !== 1)active @endif" id="{{ $server->uuidShort }}">
<td><a href="/admin/servers/view/{{ $server->id }}">{{ $server->name }}</td>
<td><a href="/admin/users/view/{{ $server->owner }}">{{ $server->a_ownerEmail }}</a></td>
<td><a href="/admin/nodes/view/{{ $server->node }}">{{ $server->a_nodeName }}</a></td>
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
<td><code>{{ $server->username }}</code></td>
</tr>
@endforeach
</tbody>
</table>
<div class="row">
<div class="col-md-12 text-center">{!! $servers->render() !!}</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find("a[href='/admin/servers']").addClass('active');
});
</script>
@endsection

View file

@ -0,0 +1,105 @@
@extends('layouts.master')
@section('title', 'Login')
@section('right-nav')
@endsection
@section('sidebar')
@endsection
@section('content')
<div class="col-md-6">
<form action="/auth/login" method="POST" id="login-form">
<legend>{{ trans('strings.login') }}</legend>
<fieldset>
@if (count($errors) > 0)
<div class="alert alert-danger">
<strong>{{ trans('strings.whoops') }}!</strong> {{ trans('auth.errorencountered') }}<br><br>
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="form-group">
<label for="email" class="control-label">{{ trans('strings.email') }}</label>
<div>
<input type="text" class="form-control" name="email" id="email" value="{{ old('email') }}" placeholder="{{ trans('strings.email') }}" />
</div>
</div>
<div class="form-group">
<label for="login-password" class="control-label">{{ trans('strings.password') }}</label>
<div>
<input type="password" class="form-control" name="password" id="password" placeholder="{{ trans('strings.password') }}" />
</div>
</div>
<div class="form-group">
<div>
<label><input type="checkbox" name="remember" /> {{ trans('auth.remeberme') }}</label>
</div>
</div>
<div class="form-group">
<div>
{!! csrf_field() !!}
<input type="submit" class="btn btn-primary btn-sm" value="{{ trans('strings.login') }}" />
<button class="btn btn-default btn-sm" onclick="window.location='/auth/password';return false;">{{ trans('auth.resetpassword') }}</button>
</div>
</div>
</fieldset>
</form>
</div>
<div class="modal fade" id="openTOTP" tabindex="-1" role="dialog">
<div class="modal-dialog" style="width:400px;">
<form action="/auth/login" method="POST" id="totp-form">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Two-Factor Authentication Checkpoint</h4>
</div>
<div class="modal-body" id="modal_insert_content">
<div class="form-group">
<label for="totp_token" class="control-label">Two-Factor Authentication Token</label>
<div>
<input class="form-control" type="text" placeholder="000111" name="totp_token" id="totp_token" />
</div>
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-default btn-sm" value="Continue" />
</div>
</div>
</form>
</div>
</div>
<div class="col-md-3"></div>
<script type="text/javascript">
$(document).ready(function(){
// $("#login-form").submit(function(event){
// var check_email = $("#email").val();
// $.ajax({
// type: "POST",
// url: "/auth/login/totp",
// async: false,
// data: { check: check_email },
// success: function(data){
// if(data == 'true'){
// $("#openTOTP").modal('show');
// $('#openTOTP').on('shown.bs.modal', function(){
// $("#totp_token").focus();
// })
// event.preventDefault();
// }else{
// $(this).submit();
// }
// }
// });
// });
// $("#totp-form").submit(function(){
// $('#login-form :input').not(':submit').clone().hide().appendTo('#totp-form');
// return true;
// });
});
</script>
@endsection

View file

@ -0,0 +1,90 @@
@extends('layouts.master')
@section('title', 'Your Account')
@section('sidebar-server')
@endsection
@section('content')
<div class="col-md-9">
@if (count($errors) > 0)
<div class="alert alert-danger alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ trans('base.form_error') }}
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
<div class="row">
<div class="col-md-6">
<h3 class="nopad">{{ trans('base.account.update_pass') }}</h3><hr />
<form action="/account/password" method="post">
<div class="form-group">
<label for="current_password" class="control-label">{{ trans('strings.current_password') }}</label>
<div>
<input type="password" class="form-control" name="current_password" />
</div>
</div>
<div class="form-group">
<label for="new_password" class="control-label">{{ trans('base.account.new_password') }}</label>
<div>
<input type="password" class="form-control" name="new_password" />
<p class="text-muted"><small>{{ trans('base.password_req') }}</small></p>
</div>
</div>
<div class="form-group">
<label for="new_password_again" class="control-label">{{ trans('base.account.new_password') }} {{ trans('strings.again') }}</label>
<div>
<input type="password" class="form-control" name="new_password_confirmation" />
</div>
</div>
<div class="form-group">
<div>
{!! csrf_field() !!}
<input type="submit" class="btn btn-primary btn-sm" value="{{ trans('base.account.update_pass') }}" />
</div>
</div>
</form>
</div>
<div class="col-md-6">
<h3 class="nopad">{{ trans('base.account.update_email') }}</h3><hr />
<form action="/account/email" method="post">
<div class="form-group">
<label for="new_email" class="control-label">{{ trans('base.account.new_email') }}</label>
<div>
<input type="text" class="form-control" name="new_email" />
</div>
</div>
<div class="form-group">
<label for="password" class="control-label">{{ trans('strings.current_password') }}</label>
<div>
<input type="password" class="form-control" name="password" />
</div>
</div>
<div class="form-group">
<div>
{!! csrf_field() !!}
<input type="submit" class="btn btn-primary btn-sm" value="{{ trans('base.account.update_email') }}" />
</div>
</div>
</form>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find('a[href=\'/account\']').addClass('active');
});
</script>
@endsection

View file

@ -0,0 +1,98 @@
@extends('layouts.master')
@section('title', 'Your Servers')
@section('sidebar-server')
@endsection
@section('content')
<div class="col-md-9">
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
@if (Auth::user()->root_admin == 1)
<div class="alert alert-info">{{ trans('base.view_as_admin') }}</div>
@endif
@if (!$servers->isEmpty())
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
@if (Auth::user()->root_admin == 1)
<th></th>
@endif
<th>{{ trans('base.server_name') }}</th>
<th>{{ trans('strings.location') }}</th>
<th>{{ trans('strings.node') }}</th>
<th>{{ trans('strings.connection') }}</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach ($servers as $server)
<tr class="dynUpdate" id="{{ $server->uuidShort }}">
@if (Auth::user()->root_admin == 1)
<td style="width:26px;">
@if ($server->owner === Auth::user()->id)
<i class="fa fa-circle" style="color:#008cba;"></i>
@else
<i class="fa fa-circle" style="color:#ddd;"></i>
@endif
</td>
@endif
<td><a href="/server/{{ $server->uuidShort }}">{{ $server->name }}</a></td>
<td>{{ $server->location }}</td>
<td>{{ $server->nodeName }}</td>
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
<td style="width:26px;"><i class="fa fa-circle-o-notch fa-spinner fa-spin applyUpdate"></i></td>
</tr>
@endforeach
</tbody>
</table>
@else
<div class="alert alert-info">{{ trans('base.no_servers') }}</div>
@endif
</div>
<script>
$(window).load(function () {
$('#sidebar_links').find('a[href=\'/\']').addClass('active');
function updateServerStatus () {
$('.dynUpdate').each(function (index, data) {
var element = $(this);
var serverShortUUID = $(this).attr('id');
var updateElement = $(this).find('.applyUpdate');
updateElement.removeClass('fa-check-circle fa-times-circle').css({ color: '#000' });
updateElement.addClass('fa-circle-o-notch fa-spinner fa-spin');
$.ajax({
type: 'GET',
url: '/server/' + serverShortUUID + '/ajax/status',
timeout: 10000
}).done(function (data) {
var selector = (data == 'true') ? 'fa-check-circle' : 'fa-times-circle';
var selectorColor = (data == 'true') ? 'rgb(83, 179, 12)' : 'rgb(227, 50, 0)';
updateElement.removeClass('fa-circle-o-notch fa-spinner fa-spin');
updateElement.addClass(selector).css({ color: selectorColor });
}).fail(function (jqXHR) {
updateElement.removeClass('fa-circle-o-notch fa-spinner fa-spin');
updateElement.addClass('fa-question-circle').css({ color: 'rgb(227, 50, 0)' });
});
});
}
updateServerStatus();
setInterval(updateServerStatus, 30000);
});
</script>
@endsection

View file

@ -0,0 +1,155 @@
@extends('layouts.master')
@section('title', 'Account TOTP Settings')
@section('sidebar-server')
@endsection
@section('content')
<div class="col-md-9">
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
<h3 style="margin-top:0;">{{ trans('base.account.totp_header') }} <small>@if (Auth::user()->use_totp === 1){{ trans('strings.enabled') }}@else{{ trans('strings.disabled') }}@endif</small></h3><hr />
@if (Auth::user()->use_totp === 1)
<div class="panel panel-default">
<div class="panel-heading">{{ trans('base.account.totp_disable') }}</div>
<div class="panel-body">
<p>{{ trans('base.account.totp_disable_help') }}</p>
<br />
<form action="/account/totp" method="post">
<div class="form-group">
<div class="input-group">
<span class="input-group-addon">{{ trans('base.account.totp_token') }}</span>
<input type="text" name="token" class="form-control">
<span class="input-group-btn">
{!! csrf_field() !!}
{{ method_field('DELETE') }}
<button class="btn btn-danger btn-sm" type="submit">{{ trans('base.account.totp_disable') }}</button>
</span>
</div>
</div>
</form>
</div>
</div>
@else
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">{{ trans('base.account.totp_header') }}</h3>
</div>
<div class="panel-body">
<p>{{ trans('base.account.totp_enable_help') }}</p>
<div class="alert alert-info" style="margin-bottom: 0;">{{ trans('base.account.totp_apps') }}</div>
</div>
</div>
<form action="#" id="do_totp" method="post">
<div class="form-group">
<div>
{!! csrf_field() !!}
<input type="submit" id="enable_totp" class="btn btn-success btn-sm" name="enable_totp" value="{{ trans('base.account.totp_enable') }}" />
</div>
</div>
</form>
@endif
<div class="modal fade" id="openTOTP" tabindex="-1" role="dialog" aria-labelledby="openTOTP" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form action="#" method="post" id="totp_token_verify">
<div class="modal-header">
<h4 class="modal-title">{{ trans('base.account.totp_qr') }}</h4>
</div>
<div class="modal-body" id="modal_insert_content">
<div class="row">
<div class="col-md-12" id="notice_box_totp" style="display:none;"></div>
</div>
<div class="row">
<div class="col-md-6">
<center><span id="hide_img_load"><i class="fa fa-spinner fa-spin"></i> Loading QR Code...</span><img src="" id="qr_image_insert" style="display:none;"/><br /><code id="totp_secret_insert"></code></center>
</div>
<div class="col-md-6">
<div class="alert alert-info">{{ trans('base.account.totp_checkpoint_help') }}</div>
<div class="form-group">
<label class="control-label" for="totp_token">TOTP Token</label>
{!! csrf_field() !!}
<input class="form-control" type="text" id="totp_token" />
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary btn-sm" id="submit_action">{{ trans('strings.submit') }}</button>
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal" id="close_reload">{{ trans('strings.close') }}</button>
</div>
</form>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('#sidebar_links').find('a[href=\'/account/totp\']').addClass('active');
$('#close_reload').click(function () {
location.reload();
});
$('#do_totp').submit(function (event) {
event.preventDefault();
$.ajax({
type: 'PUT',
url: '/account/totp',
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' }
}).done(function (data) {
var image = new Image();
image.src = data.qrImage;
$(image).load(function () {
$('#hide_img_load').slideUp(function () {
$('#qr_image_insert').attr('src', image.src).slideDown();
});
});
$('#totp_secret_insert').html(data.secret);
$('#openTOTP').modal('show');
}).fail(function (jqXHR) {
alert('An error occured while attempting to perform this action. Please try again.');
console.log(jqXHR);
});
});
$('#totp_token_verify').submit(function (event) {
event.preventDefault();
$('#submit_action').html('<i class="fa fa-spinner fa-spin"></i> {{ trans('strings.submit') }}').addClass('disabled');
$.ajax({
type: 'POST',
url:'/account/totp',
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
data: {
token: $('#totp_token').val()
}
}).done(function (data) {
$('#notice_box_totp').hide();
if (data === 'true') {
$('#notice_box_totp').html('<div class="alert alert-success">{{ trans('base.account.totp_enabled') }}</div>').slideDown();
} else {
$('#notice_box_totp').html('<div class="alert alert-danger">{{ trans('base.account.totp_enabled_error') }}</div>').slideDown();
}
}).fail(function (jqXHR) {
alert('An error occured while attempting to perform this action. Please try again.');
console.log(jqXHR);
}).always(function () {
$('#submit_action').html('{{ trans('strings.submit') }}').removeClass('disabled');
});
});
});
</script>
@endsection

View file

@ -0,0 +1,18 @@
@extends('layouts.master')
@section('title', '403: Forbidden')
@section('content')
<div class="col-md-9">
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">HTTP 403: Access Denied</h3>
</div>
<div class="panel-body">
<p style="margin-bottom:0;">You do not have permission to access that function. Please contact your server administrator to request permission.</p>
</div>
</div>
<p style="text-align:center;"><img src="{{ asset('images/403.jpg') }}" /></p>
<p style="text-align:center;"><a href="{{ URL::previous() }}">Take me back</a> or <a href="/">go home</a>.</p>
</div>
@endsection

View file

@ -0,0 +1,16 @@
@extends('layouts.master')
@section('title', '404: Not Found')
@section('right-nav')
@endsection
@section('sidebar')
@endsection
@section('content')
<h1 style="text-align:center;">404 - File Not Found</h1>
<p style="text-align:center;"><img src="{{ asset('images/404.jpg') }}" /></p>
<p style="text-align:center;"><a href="{{ URL::previous() }}">Take me back</a> or <a href="/">go home</a>.</p>
@endsection

View file

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html>
<head>
<title>Be right back.</title>
<link href="https://fonts.googleapis.com/css?family=Lato:100" rel="stylesheet" type="text/css">
<style>
html, body {
height: 100%;
}
body {
margin: 0;
padding: 0;
width: 100%;
color: #B0BEC5;
display: table;
font-weight: 100;
font-family: 'Lato';
}
.container {
text-align: center;
display: table-cell;
vertical-align: middle;
}
.content {
text-align: center;
display: inline-block;
}
.title {
font-size: 72px;
margin-bottom: 40px;
}
</style>
</head>
<body>
<div class="container">
<div class="content">
<div class="title">Be right back.</div>
</div>
</div>
</body>
</html>

View file

@ -0,0 +1,106 @@
<!DOCTYPE html>
<html lang="en">
<head>
@section('scripts')
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex">
<link rel="stylesheet" href="{{ asset('css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ asset('css/Pterodactyl.css') }}">
<link rel="stylesheet" href="{{ asset('css/animate.css') }}">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="{{ asset('js/admin.min.js') }}"></script>
@show
<title>Pterodactyl - @yield('title')</title>
</head>
<body>
<div class="container">
<div class="navbar navbar-default">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Pterodactyl - Laravel</a>
</div>
<div class="navbar-collapse collapse navbar-responsive-collapse">
@section('right-nav')
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ trans('strings.language') }}<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/language/de">Deutsch</a></li>
<li><a href="/language/en">English</a></li>
<li><a href="/language/es">Espa&ntilde;ol</a></li>
<li><a href="/language/fr">Fran&ccedil;ais</a></li>
<li><a href="/language/it">Italiano</a></li>
<li><a href="/language/pl">Polski</a></li>
<li><a href="/language/pt">Portugu&ecirc;s</a></li>
<li><a href="/language/ru">&#1088;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;</a></li>
<li><a href="/language/se">Svenska</a></li>
<li><a href="/language/zh">&#20013;&#22269;&#30340;的</a></li>
</ul>
</li>
<li class="hidden-xs"><a href="/"><i class="fa fa-server"></i></a></li>
<li class="hidden-xs"><a href="/auth/logout"><i class="fa fa-power-off"></i></a></li>
</ul>
@show
</div>
</div>
<!-- Add Back Mobile Support -->
<div class="row">
<div class="col-md-3 hidden-xs hidden-sm" id="sidebar_links">
@section('sidebar')
<div class="list-group">
<a href="/admin" id="sidenav_admin-index" class="list-group-item">Admin Index</a>
</div>
<div class="list-group">
<a href="#" class="list-group-item list-group-item-heading"><strong>Settings</strong></a>
<a href="/admin/settings/global" class="list-group-item">Global Settings</a>
<a href="/admin/settings/urls" class="list-group-item">URL Settings</a>
<a href="/admin/settings/email" class="list-group-item">Email Settings</a>
<a href="/admin/settings/captcha" class="list-group-item">Captcha Settings</a>
</div>
<div class="list-group">
<a href="#" class="list-group-item list-group-item-heading"><strong>Account Management</strong></a>
<a href="/admin/accounts" class="list-group-item">Find Account</a>
<a href="/admin/accounts/new" class="list-group-item">New Account</a>
</div>
<div class="list-group">
<a href="#" class="list-group-item list-group-item-heading"><strong>Server Management</strong></a>
<a href="/admin/servers" class="list-group-item">Find Server</a>
<a href="/admin/servers/new" class="list-group-item">New Server</a>
</div>
<div class="list-group">
<a href="#" class="list-group-item list-group-item-heading"><strong>Node Management</strong></a>
<a href="/admin/node" class="list-group-item">List Nodes</a>
<a href="/admin/node/new" class="list-group-item">Add Node</a>
<a href="/admin/node/locations" class="list-group-item">Manage Locations</a>
<a href="/admin/node/plugins" class="list-group-item">Manage Plugins</a>
</div>
@show
</div>
@yield('content')
</div>
<div class="footer">
<div class="row">
<div class="col-md-12">
Copyright &copy; 2012 - {{ date('Y') }} <a href="https://github.com/Pterodactyl-IO/Panel" target="_blank">Pterodactyl Software &amp; Design</a>.<br />
Pterodactyl is licensed under a <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPLv3</a> license. <!-- Please do not remove this license notice. -->
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
// Remeber Active Tab and Navigate to it on Reload
for(var queryParameters={},queryString=location.search.substring(1),re=/([^&=]+)=([^&]*)/g,m;m=re.exec(queryString);)queryParameters[decodeURIComponent(m[1])]=decodeURIComponent(m[2]);$("a[data-toggle='tab']").click(function(){queryParameters.tab=$(this).attr("href").substring(1),window.history.pushState(null,null,location.pathname+"?"+$.param(queryParameters))});
if($.urlParam('tab') != null){$('.nav.nav-tabs a[href="#' + $.urlParam('tab') + '"]').tab('show');}
});
</script>
</body>
</html>

View file

@ -0,0 +1,224 @@
<!DOCTYPE html>
<html lang="en">
<head>
@section('scripts')
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="robots" content="noindex">
<link rel="stylesheet" href="{{ asset('css/bootstrap.css') }}">
<link rel="stylesheet" href="{{ asset('css/Pterodactyl.css') }}">
<link rel="stylesheet" href="{{ asset('css/animate.css') }}">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.2/js/bootstrap.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.7/socket.io.min.js"></script>
<script src="{{ asset('js/admin.min.js') }}"></script>
<script src="{{ asset('js/bootstrap-notify.min.js') }}"></script>
<script>
$(document).ready(function () {
$.notifyDefaults({
placement: {
from: 'bottom',
align: 'right'
},
newest_on_top: true,
delay: 2000,
animate: {
enter: 'animated fadeInUp',
exit: 'animated fadeOutDown'
}
});
});
</script>
@section('server-socket')
@if (isset($server->name) && isset($node->name))
<script>
var socket;
var notifySocketError = false;
$(window).load(function () {
// Main Socket Object
socket = io('https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/{{ $server->uuid }}', {
'query': 'token={{ $server->daemonSecret }}'
});
// Socket Failed to Connect
socket.io.on('connect_error', function (err) {
$('#applyUpdate').removeClass('fa-circle-o-notch fa-spinner fa-spin').addClass('fa-question-circle').css({ color: '#FF9900' });
if(typeof notifySocketError !== 'object') {
notifySocketError = $.notify({
message: '{{ trans('server.ajax.socket_error') }}',
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}',
target: '_blank'
}, {
type: 'danger',
delay: 0
});
}
});
// Connected to Socket Successfully
socket.on('connect', function () {
if (notifySocketError !== false) {
notifySocketError.close();
notifySocketError = false;
}
});
// Socket Sends Server Status on Connect
socket.on('initial_status', function (data) {
var color = '#E33200';
var selector = 'fa-times-circle';
if (data.status === 1) {
color = '#53B30C';
selector = 'fa-check-circle';
}
$('#applyUpdate').removeClass('fa-circle-o-notch fa-spinner fa-spin fa-check-circle fa-times-circle').addClass(selector).css({ color: color });
});
// Socket Recieves New Status from Scales
socket.on('status', function(data) {
if(data.status !== 'crashed') {
var newStatus, selector = 'fa-times-circle';
var color = '#E33200';
switch (data.status) {
case 0:
newStatus = 'OFF';
break;
case 1:
newStatus = 'ON';
color = "#53B30C";
selector = "fa-check-circle";
break;
case 2:
newStatus = 'STOPPING';
break;
case 3:
newStatus = 'STARTING';
break;
}
$('#applyUpdate').removeClass('fa-circle-o-notch fa-spinner fa-spin fa-check-circle fa-times-circle').addClass(selector).css({ color: color });
$.notify({
message: '{{ trans('server.ajax.socket_status') }} <strong>' + newStatus + '</strong>.'
}, {
type: 'info'
});
} else {
$.notify({
message: '{{ trans('server.ajax.socket_status_crashed') }}'
}, {
delay: 5000,
type: 'danger'
});
}
});
});
</script>
@endif
@show
@show
<title>Pterodactyl - @yield('title')</title>
</head>
<body>
<div class="container">
<div class="navbar navbar-default">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-responsive-collapse">
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Pterodactyl</a>
</div>
<div class="navbar-collapse collapse navbar-responsive-collapse">
@section('server-name')
@if (isset($server->name) && isset($node->name))
<ul class="nav navbar-nav">
<li class="active" id="{{ $server->name }}"><a href="/server/{{ $server->id }}/index"><i id="applyUpdate" class="fa fa-circle-o-notch fa-spinner fa-spin spin-light"></i> {{ $server->name }}</a></li>
</ul>
@endif
@show
@section('right-nav')
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">{{ trans('strings.language') }}<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="/language/de">Deutsch</a></li>
<li><a href="/language/en">English</a></li>
<li><a href="/language/es">Espa&ntilde;ol</a></li>
<li><a href="/language/fr">Fran&ccedil;ais</a></li>
<li><a href="/language/it">Italiano</a></li>
<li><a href="/language/pl">Polski</a></li>
<li><a href="/language/pt">Portugu&ecirc;s</a></li>
<li><a href="/language/ru">&#1088;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;</a></li>
<li><a href="/language/se">Svenska</a></li>
<li><a href="/language/zh">&#20013;&#22269;&#30340;的</a></li>
</ul>
</li>
@if (null !== Auth::user() && Auth::user()->root_admin == 1)
<li class="hidden-xs"><a href="/admin/"><i class="fa fa-cogs"></i></a></li>
@endif
<li class="hidden-xs"><a href="/auth/logout"><i class="fa fa-power-off"></i></a></li>
</ul>
@show
</div>
</div>
<!-- Add Back Mobile Support -->
<div class="row">
<div class="col-md-3 hidden-xs hidden-sm" id="sidebar_links">
@section('sidebar')
<div class="list-group">
<a href="#" class="list-group-item list-group-item-heading"><strong>{{ trans('pagination.sidebar.account_controls') }}</strong></a>
<a href="/account" class="list-group-item">{{ trans('pagination.sidebar.account_settings') }}</a>
<a href="/account/totp" class="list-group-item">{{ trans('pagination.sidebar.account_security') }}</a>
<a href="/" class="list-group-item">{{ trans('pagination.sidebar.servers') }}</a>
</div>
@section('sidebar-server')
@if (isset($server->name) && isset($node->name))
<div class="list-group">
<a href="#" class="list-group-item list-group-item-heading"><strong>{{ trans('pagination.sidebar.server_controls') }}</strong></a>
<a href="/server/{{ $server->uuidShort }}/" class="list-group-item server-index">{{ trans('pagination.sidebar.overview') }}</a>
<a href="/server/{{ $server->uuidShort }}/files" class="list-group-item server-files">{{ trans('pagination.sidebar.files') }}</a>
<a href="/server/{{ $server->uuidShort }}/users" class="list-group-item server-users">{{ trans('pagination.sidebar.subusers') }}</a>
<a href="/server/{{ $server->uuidShort }}/settings" class="list-group-item server-settings">{{ trans('pagination.sidebar.manage') }}</a>
</div>
@endif
@show
@show
</div>
@yield('content')
</div>
<div class="footer">
<div class="row">
<div class="col-md-12">
Copyright &copy; 2012 - {{ date('Y') }} <a href="https://github.com/Pterodactyl-IO/Panel" target="_blank">Pterodactyl Software &amp; Design</a>.<br />
Pterodactyl is licensed under a <a href="http://www.gnu.org/licenses/gpl-3.0.en.html" target="_blank">GPLv3</a> license. <!-- Please do not remove this license notice. -->
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
// Remeber Active Tab and Navigate to it on Reload
for(var queryParameters={},queryString=location.search.substring(1),re=/([^&=]+)=([^&]*)/g,m;m=re.exec(queryString);)queryParameters[decodeURIComponent(m[1])]=decodeURIComponent(m[2]);$("a[data-toggle='tab']").click(function(){queryParameters.tab=$(this).attr("href").substring(1),window.history.pushState(null,null,location.pathname+"?"+$.param(queryParameters))});
if($.urlParam('tab') != null){$('.nav.nav-tabs a[href="#' + $.urlParam('tab') + '"]').tab('show');}
});
</script>
</body>
</html>

View file

@ -0,0 +1,194 @@
@extends('layouts.master')
@section('title')
Add File to: {{ $server->name }}
@endsection
@section('scripts')
@parent
<script src="{{ asset('js/binaryjs.js') }}"></script>
@endsection
@section('content')
<div class="col-md-9">
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
<ul class="nav nav-tabs" id="config_tabs">
<li class="active"><a href="#create" data-toggle="tab">Create File</a></li>
@can('upload-files', $server)<li><a href="#upload" data-toggle="tab">Upload Files</a></li>@endcan
</ul>
<div class="tab-content">
<div class="tab-pane active" id="create">
<div id="write_status" style="display:none;width: 100%; margin: 10px 0 5px;"></div>
<form method="post" id="new_file">
<h4>/home/container/{{ $directory }} <input type="text" id="file_name" class="filename" value="newfile.txt" /></h4>
<div class="form-group">
<div>
<textarea name="file_contents" id="fileContents" style="border: 1px solid #dddddd;" class="form-control console"></textarea>
</div>
</div>
<div class="form-group">
<div>
<button class="btn btn-primary btn-sm" id="create_file">{{ trans('strings.save') }}</button>
<button class="btn btn-default btn-sm" onclick="window.location='/server/{{ $server->uuidShort }}/files?dir=/{{ $directory }}';return false;">{{ trans('server.files.back') }}</button>
</div>
</div>
</form>
</div>
@can('upload-files', $server)
<div class="tab-pane" id="upload">
<h4>/home/container/&nbsp;&nbsp;<input type="text" id="u_file_name" value="{{ $directory }}" style='outline: none;width:450px;background: transparent;margin-left:-5px;padding:0;border: 0px;font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;font-weight: 250;line-height: 1.1;color: inherit;font-size: 19px;'/></h4>
<div class="alert alert-warning">Please edit the path location above <strong>before you upload files</strong>. They will automatically be placed in the directory you specify above. Simply click next to <code>/home/container/</code> and begin typing. You can change this each time you upload a new file without having to press anything else.</div>
<div class="alert alert-danger" id="upload_error" style="display: none;"></div>
<input type="file" id="fileinput" name="fileUpload[]" multiple="" style="display:none;"/>
<div id="uploader_box" class="well well-sm" style="cursor:pointer;">
<center><h2 style="margin-bottom: 25px;">Connecting...</h2></center>
</div>
<span id="file_progress"></span>
</div>
@endcan
</div>
</div>
<script>
$(window).load(function () {
$('.server-files').addClass('active');
var newFilePath;
var newFileContents;
@can('upload-files', $server)
var client = new BinaryClient('wss://{{ $node->fqdn }}:{{ $node->daemonListen }}/upload/', {
chunkSize: 40960
});
// Wait for connection to BinaryJS server
client.on('open', function() {
var box = $('#uploader_box');
box.on('dragenter', doNothing);
box.on('dragover', doNothing);
box.html('<center><h2 style="margin-bottom:25px;">Drag or Click to Upload</h2></center>');
box.on('click', function () {
$('#fileinput').click();
});
box.on('drop', function (e, files) {
if (typeof files !== 'undefined') {
e.originalEvent = {
dataTransfer: {
files: files.currentTarget.files
}
};
}
e.preventDefault();
$.each(e.originalEvent.dataTransfer.files, function(index, value) {
var file = e.originalEvent.dataTransfer.files[index];
var identifier = Math.random().toString(36).slice(2);
$('#file_progress').append('<div class="well well-sm" id="file-upload-' + identifier +'"> \
<div class="row"> \
<div class="col-md-12"> \
<h6>Uploading ' + file.name + '</h6> \
<span class="prog-bar-text-' + identifier +'" style="font-size: 10px;position: absolute;margin: 3px 0 0 15px;">Waiting...</span> \
<div class="progress progress-striped active"> \
<div class="progress-bar progress-bar-info prog-bar-' + identifier +'" style="width: 0%"></div> \
</div> \
</div> \
</div> \
</div>');
// Add to list of uploaded files
var stream = client.send(file, {
token: "{{ $server->daemonSecret }}",
server: "{{ $server->uuid }}",
path: $("#u_file_name").val(),
name: file.name,
size: file.size
});
var tx = 0;
stream.on('data', function(data) {
if(data.error) {
$("#upload_error").html(data.error).show();
$("#file-upload-" + identifier).hide();
} else {
tx += data.rx;
if(tx >= 0.999) {
$('.prog-bar-text-' + identifier).text('Upload Complete');
$('.prog-bar-' + identifier).css('width', '100%').parent().removeClass('active').removeClass('progress-striped');
} else {
$('.prog-bar-text-' + identifier).text(Math.round(tx * 100) + '%');
$('.prog-bar-' + identifier).css('width', tx * 100 + '%');
}
}
});
stream.on('close', function(data) {
$("#upload_error").html("The BinaryJS data stream was closed by the server. Please refresh the page and try again.").show();
$("#file-upload-" + identifier).hide();
});
stream.on('error', function(data) {
console.error("An error was encountered with the BinaryJS upload stream.");
});
});
});
});
// listen for a file being chosen
$('#fileinput').change(function (event) {
$('#uploader_box').trigger('drop', [event, event.currentTarget]);
$('#fileinput').val('');
});
// Deal with DOM quirks
function doNothing (e){
e.preventDefault();
e.stopPropagation();
}
@endcan
$('textarea').keydown(function (e) {
if (e.keyCode === 9) {
var start = this.selectionStart;
var end = this.selectionEnd;
var value = $(this).val();
$(this).val(value.substring(0, start) + '\t' + value.substring(end));
this.selectionStart = this.selectionEnd = start + 1;
e.preventDefault();
}
});
$("#create_file").click(function(e) {
e.preventDefault();
$("#create_file").append(' <i class="fa fa-spinner fa fa-spin"></i>').addClass("disabled");
$.ajax({
type: 'POST',
url: '/server/{{ $server->uuidShort }}/ajax/files/save',
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
data: {
file: '{{ $directory }}' + $('#file_name').val(),
contents: $('#fileContents').val()
}
}).done(function (data) {
window.location.replace('/server/{{ $server->uuidShort }}/files/edit/{{ $directory }}' + $('#file_name').val());
}).fail(function (jqXHR) {
$('#write_status').html('<div class="alert alert-danger">' + jqXHR.responseText + '</div>').show();
$('#create_file').html('{{ trans('strings.save') }}').removeClass('disabled');
});
});
});
</script>
@endsection

View file

@ -0,0 +1,99 @@
@extends('layouts.master')
@section('title')
Managing Files for: {{ $server->name }}
@endsection
@section('content')
<div class="col-md-9">
<span id="save_status" style="display:none;width: 100%;"></span>
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
<h3 class="nopad"><small>Editing File: /home/container/{{ $file }}</small></h3>
<form method="post" id="editing_file">
<div class="form-group">
<div>
@if (in_array($extension, ['yaml', 'yml']))
<div class="alert alert-info">
{!! trans('server.files.yaml_notice', [
'dropdown' => '<select id="space_yaml">
<option value="2">2</option>
<option value="4" selected="selected">4</option>
<option value="8">8</option>
</select>'
]) !!}
</div>
@endif
<textarea name="file_contents" id="fileContent" style="border: 1px solid #dddddd;height:500px;" class="form-control console">{{ $contents }}</textarea>
</div>
</div>
@can('save-files', $server)
<div class="form-group">
<div>
<input type="hidden" name="file" value="{{ $file }}" />
{!! csrf_field() !!}
<button class="btn btn-primary btn-sm" id="save_file">{{ trans('strings.save') }}</button>
<button class="btn btn-default btn-sm" onclick="window.location='/server/{{ $server->uuidShort }}/files?dir={{ urlencode($directory) }}';return false;">{{ trans('server.files.back') }}</button>
</div>
</div>
@endcan
</form>
</div>
<script>
$(document).ready(function () {
$('.server-files').addClass('active');
$('textarea').keydown(function (e) {
if (e.keyCode === 9) {
var start = this.selectionStart;
var end = this.selectionEnd;
var value = $(this).val();
var joinYML = '\t';
var yamlSpaces = 1;
@if (in_array($extension, ['yaml', 'yml']))
yamlSpaces = parseInt($("#space_yaml").val());
joinYML = Array(yamlSpaces + 1).join(" ");
@endif
$(this).val(value.substring(0, start) + joinYML + value.substring(end));
this.selectionStart = this.selectionEnd = start + yamlSpaces;
e.preventDefault();
}
});
@can('save-files', $server)
$('#save_file').click(function (e) {
e.preventDefault();
var fileName = $('input[name="file"]').val();
var fileContents = $('#fileContent').val();
$('#save_file').append(' <i class="fa fa-spinner fa fa-spin"></i>').addClass('disabled');
$.ajax({
type: 'POST',
url: '/server/{{ $server->uuidShort }}/ajax/files/save',
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
data: {
file: fileName,
contents: fileContents
}
}).done(function (data) {
$('#save_status').html('<div class="alert alert-success">{{ trans('server.files.saved') }}</div>').slideDown();
}).fail(function (jqXHR) {
$('#save_status').html('<div class="alert alert-danger">' + jqXHR.responseText + '</div>').slideDown();
}).always(function () {
$('#save_file').html('{{ trans('strings.save') }}').removeClass('disabled');
});
});
@endcan
});
</script>
@endsection

View file

@ -0,0 +1,150 @@
@extends('layouts.master')
@section('title')
Managing Files for: {{ $server->name }}
@endsection
@section('content')
<div class="col-md-9">
<div class="row" id="internal_alert">
<div class="col-md-12">
<div class="alert alert-info">
<i class="fa fa-spinner fa-spin"></i> {{ trans('server.files.loading') }}
</div>
</div>
</div>
<div class="row">
<div class="col-md-12">
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
<div class="files_loading_box"><i class="fa fa-refresh fa-spin" id="position_me"></i></div>
</div>
</div>
<div class="row">
<div class="col-md-12" id="load_files"></div>
<div class="col-md-12">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">File Path Information</h3>
</div>
<div class="panel-body">
When configuring any file paths in your server plugins or settings you should use <code>/home/container</code> as your base path. While your SFTP client sees the files as <code>/public</code> this is not true for the server process.
</div>
</div>
</div>
</div>
</div>
<script>
$(document).ready(function () {
$('.server-files').addClass('active');
});
$(window).load(function(){
var doneLoad = false;
// Show Loading Animation
function handleLoader (show) {
// Hide animation if no files displayed.
if ($('#load_files').height() < 5) { return; }
// Show Animation
if (show === true){
var height = $('#load_files').height();
var width = $('.files_loading_box').width();
var center_height = (height / 2) - 30;
var center_width = (width / 2) - 30;
$('#position_me').css({
'top': center_height,
'left': center_width,
'font-size': '60px'
});
$(".files_loading_box").css('height', (height + 5)).fadeIn();
} else {
$('.files_loading_box').fadeOut(100);
}
}
function reloadActions () {
reloadActionClick();
reloadActionDelete();
}
// Handle folder clicking to load new contents
function reloadActionClick () {
$('a.load_new').click(function (e) {
e.preventDefault();
window.history.pushState(null, null, $(this).attr('href'));
loadDirectoryContents($.urlParam('dir', $(this).attr('href')));
});
}
// Handle Deleting Files
function reloadActionDelete () {
$('a.delete_file').click(function (e) {
e.preventDefault();
var clicked = $(this);
var deleteItemPath = $(this).attr('href');
if (!confirm('Are you sure you want to delete /home/container/' + deleteItemPath + '? There is no reversing this action.')) {
return;
}
$.ajax({
type: 'DELETE',
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/file/' + deleteItemPath,
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
}
}).done(function (data) {
clicked.parent().parent().parent().parent().fadeOut();
}).fail(function (jqXHR) {
$("#internal_alert").html('<div class="alert alert-danger">An error occured while attempting to delete <code>/home/container/' + deleteItemPath + '</code>. Please try again.</div>').show();
console.log(jqXHR);
});
});
}
// Handle Loading Contents
function loadDirectoryContents (dir) {
handleLoader(true);
var outputContent;
var urlDirectory = (dir === null) ? '/' : dir;
$.ajax({
type: 'POST',
url: '/server/{{ $server->uuidShort }}/ajax/files/directory-list',
headers: { 'X-CSRF-Token': '{{ csrf_token() }}' },
data: { directory: urlDirectory }
}).done(function (data) {
handleLoader(false);
$("#load_files").slideUp(function () {
$("#load_files").html(data).slideDown();
$('[data-toggle="tooltip"]').tooltip();
$('#internal_alert').slideUp();
// Run Actions Again
reloadActions();
});
}).fail(function (jqXHR) {
$("#internal_alert").html('<div class="alert alert-danger">An error occured while attempting to process this request. Please try again.</div>').show();
console.log(jqXHR);
});
}
// Load on Initial Page Load
loadDirectoryContents($.urlParam('dir'));
});
</script>
@endsection

View file

@ -0,0 +1,86 @@
<h4 class="nopad">/home/container{{ $directory['header'] }} &nbsp;<small><a href="/server/{{ $server->uuidShort }}/files/add/@if($directory['header'] !== '')?dir={{ $directory['header'] }}@endif" class="text-muted"><i class="fa fa-plus" data-toggle="tooltip" data-placement="top" title="Add New File(s)"></i></a></small></h4>
<table class="table table-striped table-bordered table-hover">
<thead>
<tr>
<th style="width:2%;text-align:center;"></th>
<th style="width:45%">File Name</th>
<th style="width:15%">Size</th>
<th style="width:20%">Last Modified</th>
<th style="width:20%;text-align:center;">Options</th>
</tr>
</thead>
<tbody>
@if (isset($directory['first']) && $directory['first'] === true)
<tr>
<td><i class="fa fa-folder-open" style="margin-left: 0.859px;"></i></td>
<td><a href="/server/{{ $server->uuidShort }}/files" class="load_new">&larr;</a></a></td>
<td></td>
<td></td>
<td></td>
</tr>
@endif
@if (isset($directory['show']) && $directory['show'] === true)
<tr>
<td><i class="fa fa-folder-open" style="margin-left: 0.859px;"></i></td>
<td><a href="/server/{{ $server->uuidShort }}/files?dir={{ $directory['link'] }}" class="load_new">&larr; {{ $directory['link_show'] }}</a></a></td>
<td></td>
<td></td>
<td></td>
</tr>
@endif
@foreach ($folders as $folder)
<tr>
<td><i class="fa fa-folder-open" style="margin-left: 0.859px;"></i></td>
<td><a href="/server/{{ $server->uuidShort }}/files?dir=/@if($folder['directory'] !== ''){{ $folder['directory'] }}/@endif{{ $folder['entry'] }}" class="load_new">{{ $folder['entry'] }}</a></td>
<td>{{ $folder['size'] }}</td>
<td>{{ date('m/d/y H:i:s', $folder['date']) }}</td>
<td style="text-align:center;">
<div class="row" style="text-align:center;">
<div class="col-md-3 hidden-xs hidden-sm"></div>
<div class="col-md-3 hidden-xs hidden-sm">
</div>
<div class="col-md-3">
@can('delete-file', $server)
<a href="@if($folder['directory'] !== ''){{ $folder['directory'] }}/@endif{{ $folder['entry'] }}" class="delete_file"><span class="badge label-danger"><i class="fa fa-trash-o"></i></span></a>
@endcan
</div>
</div>
</td>
</tr>
@endforeach
@foreach ($files as $file)
<tr>
<td><i class="fa fa-file-text" style="margin-left: 2px;"></i></td>
<td>
@if(in_array($file['extension'], $extensions))
@can('edit-file', $server)
<a href="/server/{{ $server->uuidShort }}/files/edit/@if($file['directory'] !== ''){{ $file['directory'] }}/@endif{{ $file['entry'] }}" class="edit_file">{{ $file['entry'] }}</a>
@else
{{ $file['entry'] }}
@endcan
@else
{{ $file['entry'] }}
@endif
</td>
<td>{{ $file['size'] }}</td>
<td>{{ date('m/d/y H:i:s', $file['date']) }}</td>
<td style="text-align:center;">
<div class="row" style="text-align:center;">
<div class="col-md-3 hidden-xs hidden-sm">
</div>
<div class="col-md-3 hidden-xs hidden-sm">
@can('download-file', $server)
<a href="/server/{{ $server->uuidShort }}/files/download/@if($file['directory'] !== ''){{ $file['directory'] }}/@endif{{ $file['entry'] }}"><span class="badge"><i class="fa fa-download"></i></span></a>
@endcan
</div>
<div class="col-md-3">
@can('delete-file', $server)
<a href="@if($file['directory'] !== ''){{ $file['directory'] }}/@endif{{ $file['entry'] }}" class="delete_file"><span class="badge label-danger"><i class="fa fa-trash-o"></i></span>
@endcan
</div>
</div>
</td>
</tr>
@endforeach
</tbody>
</table>

View file

@ -0,0 +1,395 @@
@extends('layouts.master')
@section('title')
Viewing Server: {{ $server->name }}
@endsection
@section('scripts')
@parent
<script src="{{ asset('js/chartjs/chart.core.js') }}"></script>
<script src="{{ asset('js/chartjs/chart.bar.js') }}"></script>
@endsection
@section('content')
<div class="col-md-9">
@foreach (Alert::getMessages() as $type => $messages)
@foreach ($messages as $message)
<div class="alert alert-{{ $type }} alert-dismissable" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
{{ $message }}
</div>
@endforeach
@endforeach
<ul class="nav nav-tabs" id="config_tabs">
<li class="active"><a href="#stats" data-toggle="tab">{{ trans('server.index.info_use') }}</a></li>
<li id="triggerConsoleView"><a href="#console" data-toggle="tab">{{ trans('server.index.control') }}</a></li>
</ul><br />
<div class="tab-content">
<div class="tab-pane active" id="stats">
<div class="row">
<div class="col-md-6">
<h3 class="nopad">{{ trans('server.index.memory_use') }}</h3><hr />
<div class="row centered">
<canvas id="memoryChart" width="280" height="150" style="margin-left:20px;"></canvas>
<p style="text-align:center;margin-top:-15px;" class="text-muted"><small>{{ trans('server.index.xaxis') }}</small></p>
<p class="graph-yaxis hidden-xs hidden-sm text-muted" style="margin-top:-50px !important;"><small>{{ trans('server.index.memory_use') }} (Mb)</small></p>
<p class="graph-yaxis hidden-lg hidden-md text-muted" style="margin-top:-65px !important;margin-left: 100px !important;"><small>{{ trans('server.index.memory_use') }} (Mb)</small></p>
</div>
</div>
<div class="col-md-6">
<h3 class="nopad">{{ trans('server.index.cpu_use') }}</h3><hr />
<div class="row centered">
<canvas id="cpuChart" width="280" height="150" style="margin-left:20px;"></canvas>
<p style="text-align:center;margin-top:-15px;" class="text-muted"><small>{{ trans('server.index.xaxis') }}</small></p>
<p class="graph-yaxis hidden-sm hidden-xs text-muted" style="margin-top:-65px !important;"><small>{{ trans('server.index.cpu_use') }} (%)</small></p>
<p class="graph-yaxis hidden-lg hidden-md text-muted" style="margin-top:-65px !important;margin-left: 100px !important;"><small>{{ trans('server.index.cpu_use') }} (%)</small></p>
</div>
</div>
</div>
<div class="row">
<div class="col-md-12" id="stats_players">
<h3 class="nopad">Active Players</h3><hr />
<div id="players_notice" class="alert alert-info">
<i class="fa fa-spinner fa-spin"></i> Waiting for response from server...
</div>
<span id="toggle_players" style="display:none;">
<p class="text-muted">No players are online.</p>
</span>
</div>
<div class="col-md-12">
<h3>{{ trans('server.index.server_info') }}</h3><hr />
<table class="table table-striped table-bordered table-hover">
<tbody>
<tr>
<td><strong>{{ trans('server.index.connection') }}</strong></td>
<td><code>{{ $server->ip }}:{{ $server->port }}</code></td>
</tr>
<tr>
<td><strong>{{ trans('strings.node') }}</strong></td>
<td>{{ $node->name }}</td>
</tr>
<tr>
<td><strong>{{ trans('server.index.mem_limit') }}</strong></td>
<td>{{ $server->memory }} MB</td>
</tr>
<tr>
<td><strong>{{ trans('server.index.disk_space') }}</strong></td>
<td>{{ $server->disk }} MB</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="tab-pane" id="console">
<div class="row">
<div class="col-md-12">
<textarea id="live_console" class="form-control console" readonly="readonly">Loading Previous Content...</textarea>
</div>
<div class="col-md-6">
<hr />
<form action="#" method="post" id="console_command">
<fieldset>
<div class="input-group">
<input type="text" class="form-control" name="command" id="ccmd" placeholder="{{ trans('server.index.command') }}" />
<span class="input-group-btn">
<button id="sending_command" class="btn btn-primary btn-sm">&rarr;</button>
</span>
</div>
</fieldset>
</form>
<div class="alert alert-danger" id="sc_resp" style="display:none;margin-top: 15px;"></div>
</div>
<div class="col-md-6" style="text-align:center;">
<hr />
<button class="btn btn-success btn-sm start disabled" id="server_start">Start</button>
<button class="btn btn-primary btn-sm restart disabled" id="server_restart">Restart</button>
<button class="btn btn-danger btn-sm stop disabled" id="server_stop">Stop</button>
<button class="btn btn-danger btn-sm stop disabled" id="kill_proc"><i class="fa fa-ban" data-toggle="tooltip" data-placement="top" title="Kill Running Process"></i></button>
<button class="btn btn-primary btn-sm" data-toggle="modal" data-target="#pauseConsole" id="pause_console"><small><i class="fa fa-pause fa-fw"></i></small></button>
<div id="pw_resp" style="display:none;margin-top: 15px;"></div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="pauseConsole" tabindex="-1" role="dialog" aria-labelledby="PauseConsole" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="PauseConsole">{{ trans('server.index.scrollstop') }}</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-md-12">
<textarea id="paused_console" class="form-control console" readonly="readonly"></textarea>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ trans('strings.close') }}</button>
</div>
</div>
</div>
</div>
<script>
$(window).load(function () {
$('[data-toggle="tooltip"]').tooltip();
// Socket Recieves New Server Stats
socket.on('stats', function (data) {
var currentTime = new Date();
memoryChart.addData([parseInt(data.data.memory / (1024 * 1024))], '');
memoryChart.removeData();
if({{ $server->cpu }} > 0) { cpuChart.addData([(data.data.cpu / {{ $server->cpu }}) * 100], ''); }else{ cpuChart.addData([data.data.cpu], ''); }
cpuChart.removeData();
});
// Socket Recieves New Query
socket.on('query', function (data){
if($('#players_notice').is(':visible')){
$('#players_notice').hide();
$('#toggle_players').show();
}
if(data['data'].players != undefined && data['data'].players.length !== 0){
$('#toggle_players').html('');
$.each(data['data'].players, function(id, d) {
$('#toggle_players').append('<code>' + d.name + '</code>,');
});
}else{
$('#toggle_players').html('<p class=\'text-muted\'>No players are currently online.</p>');
}
});
// New Console Data Recieved
socket.on('console', function (data) {
$('#live_console').val($('#live_console').val() + data.line);
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
});
// Update Listings on Initial Status
socket.on('initial_status', function (data) {
if (data.status !== 0) {
$.ajax({
type: 'GET',
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
},
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/log/750',
timeout: 10000
}).done(function(data) {
$('#live_console').val(data);
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
}).fail(function(jqXHR, textStatus, errorThrown) {
$('#pw_resp').attr('class', 'alert alert-danger').html('Unable to load initial server log.').fadeIn().delay(5000).fadeOut();
});
} else {
$('#live_console').val('');
}
updateServerPowerControls(data.status);
updatePlayerListVisibility(data.status);
});
// Update Listings on Status
socket.on('status', function (data) {
updateServerPowerControls(data.status);
updatePlayerListVisibility(data.status);
});
// Scroll to the top of the Console when switching to that tab.
$('#triggerConsoleView').click(function () {
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
});
if($('triggerConsoleView').is(':visible')) {
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
}
$('a[data-toggle=\'tab\']').on('shown.bs.tab', function (e) {
$('#live_console').scrollTop($('#live_console')[0].scrollHeight);
});
// Load Paused Console with Live Console Data
$('#pause_console').click(function(){
$('#paused_console').val($('#live_console').val());
});
// -----------------+
// Charting Methods |
// -----------------+
var ctx = $('#memoryChart').get(0).getContext('2d');
var cty = $('#cpuChart').get(0).getContext('2d');
var memoryChartData = {labels:["","","","","","","","","","","","","","","","","","","",""],datasets:[{fillColor:"#ccc",strokeColor:"rgba(0,0,0,0)",highlightFill:"#666",data:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}]};
var cpuChartData = {labels:["","","","","","","","","","","","","","","","","","","",""],datasets:[{fillColor:"#ccc",strokeColor:"rgba(0,0,0,0)",highlightFill:"#666",data:[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}]};
var memoryChart= new Chart(ctx).Bar(memoryChartData,{animation:!1,showScale:!0,barShowStroke:!1,scaleOverride:!1,tooltipTemplate:"<%= value %> Mb",barValueSpacing:1,barStrokeWidth:1,scaleShowGridLines:!1});
var cpuChart = new Chart(cty).Bar(cpuChartData,{animation:!1,showScale:!0,barShowStroke:!1,scaleOverride:!1,tooltipTemplate:"<%= value %> %",barValueSpacing:1,barStrokeWidth:1,scaleShowGridLines:!1});
function updatePlayerListVisibility(data) {
// Server is On or Starting
if(data == 1 || data == 3) {
$('#stats_players').show();
} else {
$('#stats_players').hide();
}
}
@can('command', $server)
// Send Command to Server
$('#console_command').submit(function (event) {
event.preventDefault();
var ccmd = $('#ccmd').val();
if (ccmd == '') {
return;
}
$('#sending_command').html('<i class=\'fa fa-refresh fa-spin\'></i>').addClass('disabled');
$.ajax({
type: 'POST',
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
},
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/console',
timeout: 10000,
data: { command: ccmd }
}).fail(function (jqXHR) {
$('#sc_resp').html('Unable to process your request. Please try again.').fadeIn().delay(5000).fadeOut();
}).always(function () {
$('#sending_command').html('&rarr;').removeClass('disabled');
$('#ccmd').val('');
});
});
@endcan
@can('power', $server)
var can_run = true;
function updateServerPowerControls (data) {
// Server is On or Starting
if(data == 1 || data == 3) {
$('#server_start').addClass('disabled');
$('#server_stop, #server_restart').removeClass('disabled');
} else {
$('#server_start').removeClass('disabled');
$('#server_stop, #server_restart').addClass('disabled');
}
if(data !== 0) {
$('#kill_proc').removeClass('disabled');
} else {
$('#kill_proc').addClass('disabled');
}
}
// Kill Server Process Button
$('#kill_proc').click(function (e){
e.preventDefault();
var killConfirm = confirm('WARNING: This operation will not save your server data gracefully. You should only use this if your server is failing to respond to stops.');
if(killConfirm) {
$.ajax({
type: 'GET',
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
},
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/power/kill',
timeout: 10000
}).done(function(data) {
$('#pw_resp').attr('class', 'alert alert-success').html('Server has been killed successfully.').fadeIn().delay(5000).fadeOut();
}).fail(function(jqXHR, textStatus, errorThrown) {
$('#pw_resp').attr('class', 'alert alert-danger').html('Unable to process your request. Please try again. ('+ errorThrown +')').fadeIn().delay(5000).fadeOut();
});
}
});
$('#server_stop').click(function (e){
e.preventDefault();
if(can_run) {
can_run = false;
$(this).append(' <i class=\'fa fa-refresh fa-spin\'></i>').toggleClass('disabled');
$.ajax({
type: 'GET',
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
},
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/power/off',
timeout: 10000
}).done(function(data) {
$('#pw_resp').attr('class', 'alert alert-success').html('Server is now stopping...').fadeIn().delay(5000).fadeOut();
$('#server_stop').removeClass('disabled').html('Stop');
can_run = true;
return false;
}).fail(function(jqXHR, textStatus, errorThrown) {
$('#pw_resp').attr('class', 'alert alert-danger').html('Unable to process your request. Please try again. ('+ errorThrown +')').fadeIn().delay(5000).fadeOut();
$('#server_stop').removeClass('disabled').html('Stop');
can_run = true;
});
}
});
$('#server_restart').click(function(e){
e.preventDefault();
if(can_run) {
can_run = false;
$(this).append(' <i class=\'fa fa-refresh fa-spin\'></i>').toggleClass('disabled');
$.ajax({
type: 'GET',
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
},
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/power/restart',
timeout: 10000
}).done(function(data) {
$('#pw_resp').attr('class', 'alert alert-success').html('Server is now restarting...').fadeIn().delay(5000).fadeOut();
$('#server_restart').removeClass('disabled').html('Restart');
can_run = true;
return false;
}).fail(function(jqXHR, textStatus, errorThrown) {
$('#pw_resp').attr('class', 'alert alert-danger').html('Unable to process your request. Please try again. ('+ errorThrown +')').fadeIn().delay(5000).fadeOut();
$('#server_restart').removeClass('disabled').html('Restart');
can_run = true;
});
}
});
$('#server_start').click(function(e){
e.preventDefault();
start_server();
});
function start_server() {
if(can_run === true){
can_run = false;
$('#server_start').append(' <i class=\'fa fa-refresh fa-spin\'></i>').toggleClass('disabled');
$.ajax({
type: 'GET',
headers: {
'X-Access-Token': '{{ $server->daemonSecret }}',
'X-Access-Server': '{{ $server->uuid }}'
},
url: 'https://{{ $node->fqdn }}:{{ $node->daemonListen }}/server/power/on',
timeout: 10000
}).done(function(data) {
$('#live_console').val('Server is starting...\n');
$('#pw_resp').attr('class', 'alert alert-success').html('Server is now starting...').fadeIn().delay(5000).fadeOut();
$('#server_start').toggleClass('disabled');
$('#server_start').html('Start');
can_run = true;
}).fail(function(jqXHR, textStatus, errorThrown) {
$('#pw_resp').attr('class', 'alert alert-danger').html('Unable to process your request. Please try again. ('+ errorThrown +')').fadeIn().delay(5000).fadeOut();
$('#server_start').removeClass('disabled');
$('#server_start').html('Start');
can_run = true;
});
}
}
@endcan
});
$(document).ready(function () {
$('.server-index').addClass('active');
});
</script>
@endsection

0
resources/views/vendor/.gitkeep vendored Normal file
View file