Complete new service, option, and variable management interface in Admin CP
This commit is contained in:
parent
bccbb309b2
commit
d7682bb7c9
16 changed files with 698 additions and 925 deletions
|
@ -0,0 +1,170 @@
|
|||
{{-- Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com> --}}
|
||||
|
||||
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
|
||||
{{-- of this software and associated documentation files (the "Software"), to deal --}}
|
||||
{{-- in the Software without restriction, including without limitation the rights --}}
|
||||
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
|
||||
{{-- copies of the Software, and to permit persons to whom the Software is --}}
|
||||
{{-- furnished to do so, subject to the following conditions: --}}
|
||||
|
||||
{{-- The above copyright notice and this permission notice shall be included in all --}}
|
||||
{{-- copies or substantial portions of the Software. --}}
|
||||
|
||||
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
|
||||
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
|
||||
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
|
||||
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
|
||||
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
|
||||
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
|
||||
{{-- SOFTWARE. --}}
|
||||
@extends('layouts.admin')
|
||||
|
||||
@section('title')
|
||||
Services → New Option
|
||||
@endsection
|
||||
|
||||
@section('content-header')
|
||||
<h1>New Option<small>Create a new service option to assign to servers.</small></h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ route('admin.index') }}">Admin</a></li>
|
||||
<li><a href="{{ route('admin.services') }}">Services</a></li>
|
||||
<li class="active">New Service Option</li>
|
||||
</ol>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<form action="{{ route('admin.services.option.new') }}" method="POST">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Configuration</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="pServiceId" class="form-label">Associated Service</label>
|
||||
<select name="service_id" id="pServiceId">
|
||||
@foreach($services as $service)
|
||||
<option value="{{ $service->id }}">{{ $service->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pName" class="form-label">Option Name</label>
|
||||
<input type="text" id="pName" name="name" value="{{ old('name') }}" class="form-control" />
|
||||
<p class="text-muted small">A simple, human-readable name to use as an identifier for this service.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pDescription" class="form-label">Description</label>
|
||||
<textarea id="pDescription" name="description" class="form-control" rows="8">{{ old('description') }}</textarea>
|
||||
<p class="text-muted small">A description of this service that will be displayed throughout the panel as needed.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="pTag" class="form-label">Option Tag</label>
|
||||
<input type="text" id="pTag" name="tag" value="{{ old('tag') }}" class="form-control" />
|
||||
<p class="text-muted small">This should be a unique identifer for this service option that is not used for any other service options.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pDockerImage" class="form-label">Docker Image</label>
|
||||
<input type="text" id="pDockerImage" name="docker_image" value="{{ old('docker_image') }}" placeholder="quay.io/pterodactyl/service" class="form-control" />
|
||||
<p class="text-muted small">The default docker image that should be used for new servers under this service option. This can be left blank to use the parent service's defined image, and can also be changed per-server.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pStartup" class="form-label">Startup Command</label>
|
||||
<textarea id="pStartup" name="startup" class="form-control" rows="4">{{ old('startup') }}</textarea>
|
||||
<p class="text-muted small">The default statup command that should be used for new servers under this service option. This can be left blank to use the parent service's startup, and can also be changed per-server.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">Process Management</h3>
|
||||
</div>
|
||||
<div class="box-body">
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="alert alert-warning">
|
||||
<p>All fields are required unless you select a seperate option from the 'Copy Settings From' dropdown, in which case fields may be left blank to use the values from that option.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="pConfigFrom" class="form-label">Copy Settings From</label>
|
||||
<select name="config_from" id="pConfigFrom" class="form-control">
|
||||
<option value="0">None</option>
|
||||
</select>
|
||||
<p class="text-muted small">If you would like to default to settings from another option select the option from the menu above.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pConfigStop" class="form-label">Stop Command</label>
|
||||
<input type="text" id="pConfigStop" name="config_stop" class="form-control" value="{{ old('config_stop') }}" />
|
||||
<p class="text-muted small">The command that should be sent to server processes to stop them gracefully. If you need to send a <code>SIGINT</code> you should enter <code>^C</code> here.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pConfigLogs" class="form-label">Log Configuration</label>
|
||||
<textarea data-action="handle-tabs" id="pConfigLogs" name="config_logs" class="form-control" rows="6">{{ old('config_logs') }}</textarea>
|
||||
<p class="text-muted small">This should be a JSON representation of where log files are stored, and wether or not the daemon should be creating custom logs.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="pConfigFiles" class="form-label">Configuration Files</label>
|
||||
<textarea data-action="handle-tabs" id="pConfigFiles" name="config_files" class="form-control" rows="6">{{ old('config_files') }}</textarea>
|
||||
<p class="text-muted small">This should be a JSON representation of configuration files to modify and what parts should be changed.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="pConfigStartup" class="form-label">Start Configuration</label>
|
||||
<textarea data-action="handle-tabs" id="pConfigStartup" name="config_startup" class="form-control" rows="6">{{ old('config_startup') }}</textarea>
|
||||
<p class="text-muted small">This should be a JSON representation of what values the daemon should be looking for when booting a server to determine completion.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{!! csrf_field() !!}
|
||||
<button type="submit" class="btn btn-success btn-sm pull-right">Create Service</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@endsection
|
||||
|
||||
@section('footer-scripts')
|
||||
@parent
|
||||
{!! Theme::js('vendor/lodash/lodash.js') !!}
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
$('#pServiceId').select2().change();
|
||||
$('#pConfigFrom').select2();
|
||||
});
|
||||
$('#pServiceId').on('change', function (event) {
|
||||
$('#pConfigFrom').html('<option value="0">None</option>').select2({
|
||||
data: $.map(_.get(Pterodactyl.services, $(this).val() + '.options', []), function (item) {
|
||||
return {
|
||||
id: item.id,
|
||||
text: item.name,
|
||||
};
|
||||
}),
|
||||
});
|
||||
});
|
||||
$('textarea[data-action="handle-tabs"]').on('keydown', function(event) {
|
||||
if (event.keyCode === 9) {
|
||||
event.preventDefault();
|
||||
|
||||
var curPos = $(this)[0].selectionStart;
|
||||
var prepend = $(this).val().substr(0, curPos);
|
||||
var append = $(this).val().substr(curPos);
|
||||
|
||||
$(this).val(prepend + ' ' + append);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@endsection
|
|
@ -0,0 +1,114 @@
|
|||
{{-- Copyright (c) 2015 - 2017 Dane Everitt <dane@daneeveritt.com> --}}
|
||||
|
||||
{{-- Permission is hereby granted, free of charge, to any person obtaining a copy --}}
|
||||
{{-- of this software and associated documentation files (the "Software"), to deal --}}
|
||||
{{-- in the Software without restriction, including without limitation the rights --}}
|
||||
{{-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell --}}
|
||||
{{-- copies of the Software, and to permit persons to whom the Software is --}}
|
||||
{{-- furnished to do so, subject to the following conditions: --}}
|
||||
|
||||
{{-- The above copyright notice and this permission notice shall be included in all --}}
|
||||
{{-- copies or substantial portions of the Software. --}}
|
||||
|
||||
{{-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR --}}
|
||||
{{-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, --}}
|
||||
{{-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE --}}
|
||||
{{-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER --}}
|
||||
{{-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, --}}
|
||||
{{-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE --}}
|
||||
{{-- SOFTWARE. --}}
|
||||
@extends('layouts.admin')
|
||||
|
||||
@section('title')
|
||||
Service Options → {{ $option->name }} → Variables
|
||||
@endsection
|
||||
|
||||
@section('content-header')
|
||||
<h1>{{ $option->name }}<small>Managing variables for this service option.</small></h1>
|
||||
<ol class="breadcrumb">
|
||||
<li><a href="{{ route('admin.index') }}">Admin</a></li>
|
||||
<li><a href="{{ route('admin.services') }}">Services</a></li>
|
||||
<li><a href="{{ route('admin.services.view', $option->service->id) }}">{{ $option->service->name }}</a></li>
|
||||
<li><a href="{{ route('admin.services.option.view', $option->id) }}">{{ $option->name }}</a></li>
|
||||
<li class="active">Variables</li>
|
||||
</ol>
|
||||
@endsection
|
||||
|
||||
@section('content')
|
||||
<div class="row">
|
||||
<div class="col-xs-12">
|
||||
<div class="nav-tabs-custom nav-tabs-floating">
|
||||
<ul class="nav nav-tabs">
|
||||
<li><a href="{{ route('admin.services.option.view', $option->id) }}">Configuration</a></li>
|
||||
<li class="active"><a href="{{ route('admin.services.option.variables', $option->id) }}">Variables</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@foreach($option->variables as $variable)
|
||||
<div class="col-sm-6">
|
||||
<div class="box">
|
||||
<div class="box-header with-border">
|
||||
<h3 class="box-title">{{ $variable->name }}</h3>
|
||||
</div>
|
||||
<form action="{{ route('admin.services.option.variables.edit', ['id' => $option->id, 'variable' => $variable->id]) }}" method="POST">
|
||||
<div class="box-body">
|
||||
<div class="form-group">
|
||||
<label class="form-label">Name</label>
|
||||
<input type="text" name="name" value="{{ $variable->name }}" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Description</label>
|
||||
<textarea name="description" class="form-control" rows="3">{{ $variable->description }}</textarea>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-group col-md-6">
|
||||
<label class="form-label">Environment Variable</label>
|
||||
<input type="text" name="env_variable" value="{{ $variable->env_variable }}" class="form-control" />
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label class="form-label">Default Value</label>
|
||||
<input type="text" name="default_value" value="{{ $variable->default_value }}" class="form-control" />
|
||||
</div>
|
||||
<div class="col-xs-12">
|
||||
<p class="text-muted small">This variable can be accessed in the statup command by using <code>{{ $variable->env_variable }}</code>.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Permissions</label>
|
||||
<select name="options[]" class="pOptions form-control" multiple>
|
||||
<option value="user_viewable" {{ (! $variable->user_viewable) ?: 'selected' }}>Users Can View</option>
|
||||
<option value="user_editable" {{ (! $variable->user_editable) ?: 'selected' }}>Users Can Edit</option>
|
||||
<option value="required" {{ (! $variable->required) ?: 'selected' }}>Field Is Required</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="form-label">Input Rules</label>
|
||||
<input type="text" name="rules" class="form-control" value="{{ $variable->rules }}" />
|
||||
<p class="text-muted small">These rules are defined using standard Laravel Framework validation rules.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{!! csrf_field() !!}
|
||||
<button class="btn btn-sm btn-danger pull-left muted muted-hover" data-action="delete" name="action" value="delete" type="submit"><i class="fa fa-trash-o"></i></button>
|
||||
<button class="btn btn-sm btn-primary pull-right" name="action" value="save" type="submit">Save</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('footer-scripts')
|
||||
@parent
|
||||
<script>
|
||||
$('.pOptions').select2();
|
||||
$('[data-action="delete"]').on('mouseenter', function (event) {
|
||||
$(this).find('i').html(' Delete Variable');
|
||||
}).on('mouseleave', function (event) {
|
||||
$(this).find('i').html('');
|
||||
});
|
||||
</script>
|
||||
@endsection
|
|
@ -39,7 +39,7 @@
|
|||
<div class="nav-tabs-custom nav-tabs-floating">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a href="{{ route('admin.services.option.view', $option->id) }}">Configuration</a></li>
|
||||
<li><a href="{{ route('admin.services.option.view.variables', $option->id) }}">Variables</a></li>
|
||||
<li><a href="{{ route('admin.services.option.variables', $option->id) }}">Variables</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -131,12 +131,16 @@
|
|||
<label for="pConfigStartup" class="form-label">Start Configuration</label>
|
||||
<textarea data-action="handle-tabs" id="pConfigStartup" name="config_startup" class="form-control" rows="6">{{ ! is_null($option->config_startup) ? json_encode(json_decode($option->config_startup), JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) : '' }}</textarea>
|
||||
<p class="text-muted small">This should be a JSON representation of what values the daemon should be looking for when booting a server to determine completion.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-footer">
|
||||
{!! csrf_field() !!}
|
||||
<button type="submit" class="btn btn-primary btn-sm pull-right">Edit Service</button>
|
||||
<button id="deleteButton" type="submit" name="action" value="delete" class="btn btn-danger btn-sm muted muted-hover">
|
||||
<i class="fa fa-trash-o"></i>
|
||||
</button>
|
||||
<button type="submit" name="action" value="edit" class="btn btn-primary btn-sm pull-right">Edit Service</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -147,6 +151,12 @@
|
|||
@section('footer-scripts')
|
||||
@parent
|
||||
<script>
|
||||
$('#pConfigFrom').select2();
|
||||
$('#deleteButton').on('mouseenter', function (event) {
|
||||
$(this).find('i').html(' Delete Option');
|
||||
}).on('mouseleave', function (event) {
|
||||
$(this).find('i').html('');
|
||||
});
|
||||
$('textarea[data-action="handle-tabs"]').on('keydown', function(event) {
|
||||
if (event.keyCode === 9) {
|
||||
event.preventDefault();
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
</div>
|
||||
<div class="box-footer">
|
||||
{!! csrf_field() !!}
|
||||
<button id="deleteButton" type="input" name="action" value="delete" class="btn btn-sm btn-danger muted muted-hover"><i class="fa fa-trash-o"></i></button>
|
||||
<button type="input" class="btn btn-primary btn-sm pull-right">Edit Service</button>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -111,3 +112,14 @@
|
|||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
|
||||
@section('footer-scripts')
|
||||
@parent
|
||||
<script>
|
||||
$('#deleteButton').on('mouseenter', function (event) {
|
||||
$(this).find('i').html(' Delete Service');
|
||||
}).on('mouseleave', function (event) {
|
||||
$(this).find('i').html('');
|
||||
});
|
||||
</script>
|
||||
@endsection
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue