Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
pterodactyl
GitHub Repository: pterodactyl/panel
Path: blob/1.0-develop/resources/views/admin/nodes/view/allocation.blade.php
7461 views
1
@extends('layouts.admin')
2
3
@section('title')
4
{{ $node->name }}: Allocations
5
@endsection
6
7
@section('content-header')
8
<h1>{{ $node->name }}<small>Control allocations available for servers on this node.</small></h1>
9
<ol class="breadcrumb">
10
<li><a href="{{ route('admin.index') }}">Admin</a></li>
11
<li><a href="{{ route('admin.nodes') }}">Nodes</a></li>
12
<li><a href="{{ route('admin.nodes.view', $node->id) }}">{{ $node->name }}</a></li>
13
<li class="active">Allocations</li>
14
</ol>
15
@endsection
16
17
@section('content')
18
<div class="row">
19
<div class="col-xs-12">
20
<div class="nav-tabs-custom nav-tabs-floating">
21
<ul class="nav nav-tabs">
22
<li><a href="{{ route('admin.nodes.view', $node->id) }}">About</a></li>
23
<li><a href="{{ route('admin.nodes.view.settings', $node->id) }}">Settings</a></li>
24
<li><a href="{{ route('admin.nodes.view.configuration', $node->id) }}">Configuration</a></li>
25
<li class="active"><a href="{{ route('admin.nodes.view.allocation', $node->id) }}">Allocation</a></li>
26
<li><a href="{{ route('admin.nodes.view.servers', $node->id) }}">Servers</a></li>
27
</ul>
28
</div>
29
</div>
30
</div>
31
<div class="row">
32
<div class="col-sm-8">
33
<div class="box box-primary">
34
<div class="box-header with-border">
35
<h3 class="box-title">Existing Allocations</h3>
36
</div>
37
<div class="box-body table-responsive no-padding" style="overflow-x: visible">
38
<table class="table table-hover" style="margin-bottom:0;">
39
<tr>
40
<th>
41
<input type="checkbox" class="select-all-files hidden-xs" data-action="selectAll">
42
</th>
43
<th>IP Address <i class="fa fa-fw fa-minus-square" style="font-weight:normal;color:#d9534f;cursor:pointer;" data-toggle="modal" data-target="#allocationModal"></i></th>
44
<th>IP Alias</th>
45
<th>Port</th>
46
<th>Assigned To</th>
47
<th>
48
<div class="btn-group hidden-xs">
49
<button type="button" id="mass_actions" class="btn btn-sm btn-default dropdown-toggle disabled"
50
data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Mass Actions <span class="caret"></span>
51
</button>
52
<ul class="dropdown-menu dropdown-massactions">
53
<li><a href="#" id="selective-deletion" data-action="selective-deletion">Delete <i class="fa fa-fw fa-trash-o"></i></a></li>
54
</ul>
55
</div>
56
</th>
57
</tr>
58
@foreach($node->allocations as $allocation)
59
<tr>
60
<td class="middle min-size" data-identifier="type">
61
@if(is_null($allocation->server_id))
62
<input type="checkbox" class="select-file hidden-xs" data-action="addSelection">
63
@else
64
<input disabled="disabled" type="checkbox" class="select-file hidden-xs" data-action="addSelection">
65
@endif
66
</td>
67
<td class="col-sm-3 middle" data-identifier="ip">{{ $allocation->ip }}</td>
68
<td class="col-sm-3 middle">
69
<input class="form-control input-sm" type="text" value="{{ $allocation->ip_alias }}" data-action="set-alias" data-id="{{ $allocation->id }}" placeholder="none" />
70
<span class="input-loader"><i class="fa fa-refresh fa-spin fa-fw"></i></span>
71
</td>
72
<td class="col-sm-2 middle" data-identifier="port">{{ $allocation->port }}</td>
73
<td class="col-sm-3 middle">
74
@if(! is_null($allocation->server))
75
<a href="{{ route('admin.servers.view', $allocation->server_id) }}">{{ $allocation->server->name }}</a>
76
@endif
77
</td>
78
<td class="col-sm-1 middle">
79
@if(is_null($allocation->server_id))
80
<button data-action="deallocate" data-id="{{ $allocation->id }}" class="btn btn-sm btn-danger"><i class="fa fa-trash-o"></i></button>
81
@endif
82
</td>
83
</tr>
84
@endforeach
85
</table>
86
</div>
87
@if($node->allocations->hasPages())
88
<div class="box-footer text-center">
89
{{ $node->allocations->render() }}
90
</div>
91
@endif
92
</div>
93
</div>
94
<div class="col-sm-4">
95
<form action="{{ route('admin.nodes.view.allocation', $node->id) }}" method="POST">
96
<div class="box box-success">
97
<div class="box-header with-border">
98
<h3 class="box-title">Assign New Allocations</h3>
99
</div>
100
<div class="box-body">
101
<div class="form-group">
102
<label for="pAllocationIP" class="control-label">IP Address</label>
103
<div>
104
<select class="form-control" name="allocation_ip" id="pAllocationIP" multiple>
105
@foreach($allocations as $allocation)
106
<option value="{{ $allocation->ip }}">{{ $allocation->ip }}</option>
107
@endforeach
108
</select>
109
<p class="text-muted small">Enter an IP address to assign ports to here.</p>
110
</div>
111
</div>
112
<div class="form-group">
113
<label for="pAllocationIP" class="control-label">IP Alias</label>
114
<div>
115
<input type="text" id="pAllocationAlias" class="form-control" name="allocation_alias" placeholder="alias" />
116
<p class="text-muted small">If you would like to assign a default alias to these allocations enter it here.</p>
117
</div>
118
</div>
119
<div class="form-group">
120
<label for="pAllocationPorts" class="control-label">Ports</label>
121
<div>
122
<select class="form-control" name="allocation_ports[]" id="pAllocationPorts" multiple></select>
123
<p class="text-muted small">Enter individual ports or port ranges here separated by commas or spaces.</p>
124
</div>
125
</div>
126
</div>
127
<div class="box-footer">
128
{!! csrf_field() !!}
129
<button type="submit" class="btn btn-success btn-sm pull-right">Submit</button>
130
</div>
131
</div>
132
</form>
133
</div>
134
</div>
135
<div class="modal fade" id="allocationModal" tabindex="-1" role="dialog">
136
<div class="modal-dialog" role="document">
137
<div class="modal-content">
138
<div class="modal-header">
139
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
140
<h4 class="modal-title">Delete Allocations for IP Block</h4>
141
</div>
142
<form action="{{ route('admin.nodes.view.allocation.removeBlock', $node->id) }}" method="POST">
143
<div class="modal-body">
144
<div class="row">
145
<div class="col-md-12">
146
<select class="form-control" name="ip">
147
@foreach($allocations as $allocation)
148
<option value="{{ $allocation->ip }}">{{ $allocation->ip }}</option>
149
@endforeach
150
</select>
151
</div>
152
</div>
153
</div>
154
<div class="modal-footer">
155
{{{ csrf_field() }}}
156
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
157
<button type="submit" class="btn btn-danger">Delete Allocations</button>
158
</div>
159
</form>
160
</div>
161
</div>
162
</div>
163
@endsection
164
165
@section('footer-scripts')
166
@parent
167
<script>
168
$('[data-action="addSelection"]').on('click', function () {
169
updateMassActions();
170
});
171
172
$('[data-action="selectAll"]').on('click', function () {
173
$('input.select-file').not(':disabled').prop('checked', function (i, val) {
174
return !val;
175
});
176
177
updateMassActions();
178
});
179
180
$('[data-action="selective-deletion"]').on('mousedown', function () {
181
deleteSelected();
182
});
183
184
$('#pAllocationIP').select2({
185
tags: true,
186
maximumSelectionLength: 1,
187
selectOnClose: true,
188
tokenSeparators: [',', ' '],
189
});
190
191
$('#pAllocationPorts').select2({
192
tags: true,
193
selectOnClose: true,
194
tokenSeparators: [',', ' '],
195
});
196
197
$('button[data-action="deallocate"]').click(function (event) {
198
event.preventDefault();
199
var element = $(this);
200
var allocation = $(this).data('id');
201
swal({
202
title: '',
203
text: 'Are you sure you want to delete this allocation?',
204
type: 'warning',
205
showCancelButton: true,
206
allowOutsideClick: true,
207
closeOnConfirm: false,
208
confirmButtonText: 'Delete',
209
confirmButtonColor: '#d9534f',
210
showLoaderOnConfirm: true
211
}, function () {
212
$.ajax({
213
method: 'DELETE',
214
url: '/admin/nodes/view/' + {{ $node->id }} + '/allocation/remove/' + allocation,
215
headers: { 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content') },
216
}).done(function (data) {
217
element.parent().parent().addClass('warning').delay(100).fadeOut();
218
swal({ type: 'success', title: 'Port Deleted!' });
219
}).fail(function (jqXHR) {
220
console.error(jqXHR);
221
swal({
222
title: 'Whoops!',
223
text: jqXHR.responseJSON.error,
224
type: 'error'
225
});
226
});
227
});
228
});
229
230
var typingTimer;
231
$('input[data-action="set-alias"]').keyup(function () {
232
clearTimeout(typingTimer);
233
$(this).parent().removeClass('has-error has-success');
234
typingTimer = setTimeout(sendAlias, 250, $(this));
235
});
236
237
var fadeTimers = [];
238
function sendAlias(element) {
239
element.parent().find('.input-loader').show();
240
clearTimeout(fadeTimers[element.data('id')]);
241
$.ajax({
242
method: 'POST',
243
url: '/admin/nodes/view/' + {{ $node->id }} + '/allocation/alias',
244
headers: { 'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content') },
245
data: {
246
alias: element.val(),
247
allocation_id: element.data('id'),
248
}
249
}).done(function () {
250
element.parent().addClass('has-success');
251
}).fail(function (jqXHR) {
252
console.error(jqXHR);
253
element.parent().addClass('has-error');
254
}).always(function () {
255
element.parent().find('.input-loader').hide();
256
fadeTimers[element.data('id')] = setTimeout(clearHighlight, 2500, element);
257
});
258
}
259
260
function clearHighlight(element) {
261
element.parent().removeClass('has-error has-success');
262
}
263
264
function updateMassActions() {
265
if ($('input.select-file:checked').length > 0) {
266
$('#mass_actions').removeClass('disabled');
267
} else {
268
$('#mass_actions').addClass('disabled');
269
}
270
}
271
272
function deleteSelected() {
273
var selectedIds = [];
274
var selectedItems = [];
275
var selectedItemsElements = [];
276
277
$('input.select-file:checked').each(function () {
278
var $parent = $($(this).closest('tr'));
279
var id = $parent.find('[data-action="deallocate"]').data('id');
280
var $ip = $parent.find('td[data-identifier="ip"]');
281
var $port = $parent.find('td[data-identifier="port"]');
282
var block = `${$ip.text()}:${$port.text()}`;
283
284
selectedIds.push({
285
id: id
286
});
287
selectedItems.push(block);
288
selectedItemsElements.push($parent);
289
});
290
291
if (selectedItems.length !== 0) {
292
var formattedItems = "";
293
var i = 0;
294
$.each(selectedItems, function (key, value) {
295
formattedItems += ("<code>" + value + "</code>, ");
296
i++;
297
return i < 5;
298
});
299
300
formattedItems = formattedItems.slice(0, -2);
301
if (selectedItems.length > 5) {
302
formattedItems += ', and ' + (selectedItems.length - 5) + ' other(s)';
303
}
304
305
swal({
306
type: 'warning',
307
title: '',
308
text: 'Are you sure you want to delete the following allocations: ' + formattedItems + '?',
309
html: true,
310
showCancelButton: true,
311
showConfirmButton: true,
312
closeOnConfirm: false,
313
showLoaderOnConfirm: true
314
}, function () {
315
$.ajax({
316
method: 'DELETE',
317
url: '/admin/nodes/view/' + {{ $node->id }} + '/allocations',
318
headers: {'X-CSRF-TOKEN': $('meta[name="_token"]').attr('content')},
319
data: JSON.stringify({
320
allocations: selectedIds
321
}),
322
contentType: 'application/json',
323
processData: false
324
}).done(function () {
325
$('#file_listing input:checked').each(function () {
326
$(this).prop('checked', false);
327
});
328
329
$.each(selectedItemsElements, function () {
330
$(this).addClass('warning').delay(200).fadeOut();
331
});
332
333
swal({
334
type: 'success',
335
title: 'Allocations Deleted'
336
});
337
}).fail(function (jqXHR) {
338
console.error(jqXHR);
339
swal({
340
type: 'error',
341
title: 'Whoops!',
342
html: true,
343
text: 'An error occurred while attempting to delete these allocations. Please try again.',
344
});
345
});
346
});
347
} else {
348
swal({
349
type: 'warning',
350
title: '',
351
text: 'Please select allocation(s) to delete.',
352
});
353
}
354
}
355
</script>
356
@endsection
357
358