505 lines
18 KiB
PHP
505 lines
18 KiB
PHP
<!-- $o=System::class -->
|
|
@use(Carbon\Carbon)
|
|
@use(Carbon\CarbonInterface)
|
|
@use(Illuminate\Support\Facades\Gate)
|
|
@use(App\Classes\FTN\Packet)
|
|
@use(App\Models\Mailer)
|
|
@use(App\Models\User)
|
|
|
|
<div class="row">
|
|
<div class="col-xl-9 col-12">
|
|
<div class="row pt-0">
|
|
@can('admin')
|
|
<div class="col-12">
|
|
<h4 class="mb-0 pb-2">System Users</h4>
|
|
|
|
<div class="row pt-0">
|
|
<!-- Users -->
|
|
<div class="col-6">
|
|
<label for="users" class="form-label">Owners</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-people-fill"></i></span>
|
|
<select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]">
|
|
<option value=""> </option>
|
|
@foreach (User::select(['id','name','email'])->orderBy('name')->active()->get() as $uo)
|
|
<option value="{{ $uo->id }}" @selected(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))>{{ $uo->name }} <small>({{ $uo->email }})</small></option>
|
|
@endforeach
|
|
</select>
|
|
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('users')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endcan
|
|
</div>
|
|
|
|
<div class="row @can('admin')pt-4 @else pt-0 @endcannot">
|
|
<div class="col-12">
|
|
<h4 class="mb-0 pb-2">System Details</h4>
|
|
|
|
<div class="row pt-0">
|
|
<!-- Name -->
|
|
<div class="col-7">
|
|
<label for="name" class="form-label">BBS Name</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-pc"></i></span>
|
|
<input type="text" class="form-control @error('name') is-invalid @enderror" id="name" placeholder="Name" name="name" value="{{ old('name',$o->name) }}" required @cannot($action,$o)readonly @endcannot autofocus autocomplete="off" data-1p-ignore>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('name')
|
|
{{ $message }}
|
|
@else
|
|
A name is required.
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- ZeroTier ID -->
|
|
@can('admin',$o)
|
|
<div class="col-5">
|
|
<label for="zt_id" class="form-label">ZeroTier ID</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-shield-lock-fill"></i></span>
|
|
<input type="text" class="form-control @error('zt_id') is-invalid @enderror" id="zt_id" placeholder="ZeroTier" name="zt_id" value="{{ old('zt_id',$o->zt_id) }}" @cannot($action,$o)readonly @endcannot>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('zt_id')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
@endcan
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Sysop -->
|
|
<div class="col-6">
|
|
<label for="sysop" class="form-label">Sysop</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-person-fill"></i></span>
|
|
<input type="text" class="form-control @error('sysop') is-invalid @enderror" id="sysop" placeholder="Sysop" name="sysop" value="{{ old('sysop',$o->sysop) }}" required @cannot('admin',$o)readonly @endcannot autocomplete="name">
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('sysop')
|
|
{{ $message }}
|
|
@else
|
|
A Sysop's name is required.
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Location -->
|
|
<div class="col-6">
|
|
<label for="location" class="form-label">Location</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-globe"></i></span>
|
|
<input type="text" class="form-control @error('location') is-invalid @enderror" id="location" placeholder="Location" name="location" value="{{ old('location',$o->location) }}" required @cannot($action,$o)readonly @endcannot>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('location')
|
|
{{ $message }}
|
|
@else
|
|
System location is required.
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Address -->
|
|
<div class="col-6">
|
|
<label for="address" class="form-label">Mailer Internet Hostname</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-globe"></i></span>
|
|
<input type="text" class="w-75 form-control @error('address') is-invalid @enderror" id="address" placeholder="FQDN" name="address" value="{{ old('address',$o->address) }}" @cannot($action,$o)readonly @endcannot data-1p-ignore>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('address')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Phone -->
|
|
<div class="col-4">
|
|
<label for="phone" class="form-label">Mailer Modem Phone Number</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-telephone-fill"></i></span>
|
|
<input type="text" class="form-control @error('phone') is-invalid @enderror" id="phone" placeholder="Phone" name="phone" value="{{ old('phone',$o->phone) }}" @cannot($action,$o)readonly @endcannot>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('phone')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row pt-4">
|
|
<!-- Mailer Details -->
|
|
<div class="col-12">
|
|
<h4 class="mb-0 pb-2">Mailer Details</h4>
|
|
|
|
<!-- Mailer Ports -->
|
|
<div class="row pt-0">
|
|
<div class="col-3">
|
|
@foreach (Mailer::all() as $mo)
|
|
@php($x=$o->mailers->find($mo))
|
|
<div class="row pt-0">
|
|
<div class="col-12">
|
|
<label for="mailer_port_{{ $mo->id }}" class="form-label w-100">{{ $mo->name }} <span class="float-end text-warning">{{ $x?->pivot->last_poll }}</span></label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-modem-fill"></i></span>
|
|
<input type="text" class="form-control text-end @error('mailer_details.'.$mo->id.'.port') is-invalid @enderror" id="mailer_port_{{ $mo->id }}" placeholder="Port" name="mailer_details[{{ $mo->id }}][port]" value="{{ old('mailer_details.'.$mo->id.'.port',$x?->pivot->port) }}" @cannot($action,$o)readonly @endcannot>
|
|
<div class="input-group-text">
|
|
<input type="checkbox" class="form-control-input" name="mailer_details[{{ $mo->id }}][active]" value="1" title="Active" @if(old('mailer_details.'.$mo->id.'.active',$x?->pivot->active))checked @endif @cannot($action,$o)disabled @endcannot>
|
|
</div>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('mailer_details.'.$mo->id.'.port')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endforeach
|
|
</div>
|
|
|
|
<!-- Mail Packet -->
|
|
<div class="col-4">
|
|
<x-form.select name="pkt_type" icon="bi-ui-radios" label="Mail Packet" feedback="Set a packet type" :value="$o->pkt_type ?: config('fido.packet_default')" :options="collect(Packet::PACKET_TYPES)->map(fn($item,$key)=>['id'=>$key,'value'=>$key])" required="true" :disabled="Gate::denies('update_nn',$o)"/>
|
|
</div>
|
|
|
|
<!-- Packet Msgs -->
|
|
<div class="col-2">
|
|
<label for="pkt_msgs" class="form-label w-100">Packet Msgs</label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-hash"></i></span>
|
|
<input type="text" class="form-control text-end @error('pkt_msgs') is-invalid @enderror" id="pkt_msgs" placeholder="{{ $setup->msgs_pkt }}" name="pkt_msgs" value="{{ old('pkt_msgs',$o->getRawOriginal('pkt_msgs')) }}" @cannot($action,$o)readonly @endcannot>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('pkt_msgs')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row pt-4">
|
|
<!-- BBS Details -->
|
|
<div class="col-12">
|
|
<h4 class="mb-0 pb-2">BBS Details</h4>
|
|
|
|
<div class="row pt-0">
|
|
<div class="col-4">
|
|
<x-form.select name="method" icon="bi-wifi" label="Connection Method" :value="$o->method" :options="collect([['id'=>23,'value'=>'Telnet'],['id'=>22,'value'=>'SSH'],['id'=>519,'value'=>'Rlogin']])" :disabled="Gate::denies('update_nn',$o)"/>
|
|
</div>
|
|
|
|
<div class="col-3">
|
|
<label for="method" class="form-label">Port</label>
|
|
<div class="input-group">
|
|
<span class="input-group-text"><i class="bi bi-wifi"></i></span>
|
|
<input type="text" class="form-control text-end @error('port') is-invalid @enderror" id="port" placeholder="Port" name="port" value="{{ old('port',$o->port) }}" @cannot($action,$o)readonly @endcannot>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-xl-3 col-12">
|
|
<div class="row">
|
|
<!-- Active -->
|
|
<div class="col-6">
|
|
@can($action,$o)
|
|
<span class="label form-label">Active</span>
|
|
<div class="input-group">
|
|
<div class="btn-group" role="group">
|
|
<input type="radio" class="btn-check" name="active" id="active_yes" value="1" required @if(old('active',$o->active))checked @endif>
|
|
<label class="btn btn-outline-success" for="active_yes">Yes</label>
|
|
|
|
<input type="radio" class="btn-check btn-danger" name="active" id="active_no" value="0" required @if(! old('active',$o->active))checked @endif>
|
|
<label class="btn btn-outline-danger" for="active_no">No</label>
|
|
</div>
|
|
</div>
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Hold -->
|
|
<div class="col-6">
|
|
@can('admin',$o)
|
|
<span class="label form-label">Hold Mail <i class="bi bi-info-circle" title="Dont give the node any mail regardless of poll mode"></i></span>
|
|
<div class="input-group">
|
|
<div class="btn-group" role="group">
|
|
<input type="radio" class="btn-check" name="hold" id="hold_yes" value="1" required @if(old('hold',$o->hold))checked @endif>
|
|
<label class="btn btn-outline-warning" for="hold_yes">Yes</label>
|
|
|
|
<input type="radio" class="btn-check btn-danger" name="hold" id="hold_no" value="0" required @if(! old('hold',$o->hold))checked @endif>
|
|
<label class="btn btn-outline-success" for="hold_no">No</label>
|
|
</div>
|
|
</div>
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<!-- Poll Mode -->
|
|
<div class="col-12">
|
|
@can($action,$o)
|
|
<span class="label form-label">Poll Mode <i class="bi bi-info-circle" title="Poll node when mail available, poll on a schedule or hold mail for collection"></i></span>
|
|
<div class="input-group has-validation">
|
|
<div class="btn-group @error('pollmode') is-invalid @enderror" role="group">
|
|
<input type="radio" class="btn-check" name="pollmode" id="poll_crash" value="2" @if((int)old('pollmode',($o->pollmode === TRUE) ? 2 : 0) === 2)checked @endif>
|
|
<label class="btn btn-outline-success" for="poll_crash">Crash</label>
|
|
|
|
<input type="radio" class="btn-check btn-danger" name="pollmode" id="poll_normal" value="1" @if((int)old('pollmode',($o->pollmode === FALSE) ? 1 : 0) === 1)checked @endif>
|
|
<label class="btn btn-outline-secondary" for="poll_normal">Normal</label>
|
|
|
|
<input type="radio" class="btn-check btn-danger" name="pollmode" id="poll_hold" value="0" @if((int)old('pollmode',is_null($o->pollmode) ? 0 : 1) === 0)checked @endif>
|
|
<label class="btn btn-outline-warning" for="poll_hold">Hold</label>
|
|
</div>
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('pollmode')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
@endcan
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
<div class="row p-0">
|
|
@if($o->exists)
|
|
@can('update_nn',$o)
|
|
<div class="col-6">
|
|
<label for="autohold" class="form-label">Auto Hold</label>
|
|
<div class="input-group">
|
|
<button id="autohold" @class(['btn','btn-warning'=>$o->autohold,'btn-outline-success'=>(! $o->autohold)])><i @class(['bi-toggle-on'=>$o->autohold,'bi-toggle-off'=>(! $o->autohold)])></i></button>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- @todo This is only relevant for uplinks, so hide it if this system isnt an uplink -->
|
|
<div class="col-6 @if((old('pollmode') === "0") || is_null($o->pollmode))d-none @endif" id="heartbeat_option">
|
|
<label for="heartbeat" class="form-label">Heartbeat <i class="bi bi-info-circle" title="Attempt contact after last seen"></i></label>
|
|
<div class="input-group has-validation">
|
|
<span class="input-group-text"><i class="bi bi-hourglass-bottom"></i></span>
|
|
<input type="text" class="form-control text-end @error('heartbeat') is-invalid @enderror" id="heartbeat" placeholder="Hrs" name="heartbeat" value="{{ old('heartbeat',$o->heartbeat) }}">
|
|
<span class="invalid-feedback" role="alert">
|
|
@error('heartbeat')
|
|
{{ $message }}
|
|
@enderror
|
|
</span>
|
|
</div>
|
|
</div>
|
|
@endcan
|
|
@endif
|
|
</div>
|
|
|
|
@if(! is_null($o->pollmode))
|
|
<div class="row">
|
|
<div class="col-12 bg-secondary rounded p-2 small">
|
|
@if($job=$o->poll())
|
|
<div class="row p-0">
|
|
<div class="col-4 text-dark">
|
|
@if($job->attempts)Last: @else Scheduled: @endif
|
|
</div>
|
|
<div class="col-8">
|
|
<strong class="highlight">{{ $job->created_at }}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-4 text-dark">
|
|
Attempts:
|
|
</div>
|
|
<div class="col-8">
|
|
<strong class="highlight">{{ $job->attempts ?: 0 }}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
@if($job->attempts)
|
|
<div class="row">
|
|
<div class="col-4 text-dark">
|
|
Next:
|
|
</div>
|
|
<div class="col-8">
|
|
<strong class="highlight">{{ $job->available_at->diffForHumans(now(),$job->available_at->isFuture() ? CarbonInterface::DIFF_ABSOLUTE : CarbonInterface::DIFF_RELATIVE_TO_NOW) }}</strong>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
|
|
@else
|
|
<div class="row p-0">
|
|
<div class="col-4 text-dark">
|
|
Last Poll:
|
|
</div>
|
|
<div class="col-8">
|
|
<strong class="highlight">{{ ($x=$o->logs()->where('originate',TRUE)->orderBy('created_at','DESC')->limit(1)->single())?->created_at ?: 'Never' }}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="row">
|
|
<div class="col-4 text-dark">
|
|
Method:
|
|
</div>
|
|
<div class="col-8">
|
|
<strong class="highlight">{{ $x ? $x->mailer->name : '-' }}</strong>
|
|
</div>
|
|
</div>
|
|
|
|
@if($o->heartbeat)
|
|
<div class="row">
|
|
<div class="col-4 text-dark">
|
|
Next Heartbeat:
|
|
</div>
|
|
<div class="col-8">
|
|
|
|
<strong class="highlight">{{ $x ? $x->created_at->addHours($o->heartbeat) : Carbon::now() }}</strong>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
@endif
|
|
|
|
<div class="row">
|
|
<div class="col-4 text-dark">
|
|
Status:
|
|
</div>
|
|
<div class="col-8">
|
|
<strong class="highlight">
|
|
@if($job) Queued
|
|
@elseif ($o->autohold)Auto Hold
|
|
@else
|
|
@switch($o->pollmode)
|
|
@case(TRUE) Crash @break;
|
|
@case(FALSE) Normal @break;
|
|
@default Hold
|
|
@endswitch
|
|
@endif
|
|
</strong>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
@can('admin')
|
|
<div class="row">
|
|
<!-- Notes -->
|
|
<div class="col-12">
|
|
<label for="notes" class="form-label">Notes</label>
|
|
<textarea class="form-control" rows=3 id="notes" name="notes" placeholder="Notes...">{{ old('notes',$o->notes) }}</textarea>
|
|
</div>
|
|
</div>
|
|
@endcan
|
|
|
|
<div class="row">
|
|
<div class="col-12">
|
|
@if($o->exists)
|
|
@can($action,$o)
|
|
<a href="{{ url('system') }}" class="btn btn-danger">Cancel</a>
|
|
<button type="submit" name="submit" class="btn btn-success float-end">@if($o->exists)Save @else Add @endif</button>
|
|
@else
|
|
<input type="hidden" name="system_id" value="{{ $o->id }}">
|
|
<span><small><strong>NOTE:</strong> You'll be able to update these details after registration is completed.</small></span>
|
|
@endcan
|
|
@else
|
|
<button type="submit" class="btn btn-success float-end" name="submit" value="create">Register</button>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
@section('page-scripts')
|
|
<script type="text/javascript">
|
|
$(document).ready(function() {
|
|
$('#users').select2({
|
|
theme: 'bootstrap-5',
|
|
dropdownAutoWidth: true,
|
|
width: 'style',
|
|
allowClear: true,
|
|
placeholder: '',
|
|
@cannot('admin')disabled: true @endcannot
|
|
/*multiple: true*/
|
|
});
|
|
|
|
$('#poll_normal').on('click',function() {
|
|
$('#heartbeat_option').removeClass('d-none');
|
|
})
|
|
$('#poll_crash').on('click',function() {
|
|
$('#heartbeat_option').removeClass('d-none');
|
|
})
|
|
$('#poll_hold').on('click',function() {
|
|
$('#heartbeat_option').addClass('d-none');
|
|
})
|
|
@if($o->exists)
|
|
$("#autohold").on('click',function(item) {
|
|
var that = $(this)
|
|
var icon = that.find('i');
|
|
|
|
if (icon.hasClass('bi-toggle-on')) {
|
|
$.ajax({
|
|
url: '/system/api/autohold/off',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data : {id: {{ $o->id }}},
|
|
beforeSend: function() {
|
|
icon.addClass('spinner-grow spinner-grow-sm')
|
|
},
|
|
complete: function() {
|
|
icon.removeClass('spinner-grow spinner-grow-sm')
|
|
},
|
|
success: function(data) {
|
|
icon.removeClass('bi-toggle-on')
|
|
.addClass('bi-toggle-off')
|
|
|
|
that.removeClass('btn-warning')
|
|
.addClass('btn-outline-success')
|
|
},
|
|
cache: false
|
|
});
|
|
|
|
} else {
|
|
$.ajax({
|
|
url: '/system/api/autohold/on',
|
|
type: 'POST',
|
|
dataType: 'json',
|
|
data : {id: {{ $o->id }}},
|
|
beforeSend: function() {
|
|
icon.addClass('spinner-grow spinner-grow-sm')
|
|
},
|
|
complete: function() {
|
|
icon.removeClass('spinner-grow spinner-grow-sm')
|
|
},
|
|
success: function(data) {
|
|
icon.removeClass('bi-toggle-off')
|
|
.addClass('bi-toggle-on');
|
|
|
|
that.removeClass('btn-outline-success')
|
|
.addClass('btn-warning')
|
|
},
|
|
cache: false
|
|
});
|
|
}
|
|
|
|
return false;
|
|
})
|
|
@endif
|
|
})
|
|
</script>
|
|
@append |