clrghouz/resources/views/system/addedit.blade.php

704 lines
25 KiB
PHP

<!-- $o=System::class -->
@use(App\Models\Address)
@use(App\Models\Echomail)
@use(App\Models\File)
@use(App\Models\Netmail)
@extends('layouts.app')
@section('htmlheader_title')
@can('update_nn',$o) @if($o->exists) Update @else Add @endif @endcan System
@endsection
@section('content')
@if($o->exists)
<h1>
{{ $o->name }}@if($o->setup)<sup class="success">*</sup>@endif
@if($o->setup)<small class="success float-end">* This Host</small>@endif
<span style="top: 0.25em;position: relative;">@includeWhen(session()->has('saved'),'widgets.saved')</span>
</h1>
@endif
@if($o->zcs->count())
<p>This system is the ZC for the following zones: <strong class="highlight">{!! $o->zcs->sortBy('zone_id')->map(function($item) { return sprintf('%d@%s',$item->zone_id,$item->domain->name); })->join('</strong>, <strong class="highlight">') !!} </strong></p>
@endif
@include('widgets.error')
<div class="accordion" id="accordion_homepage">
@if ($o->exists)
<!-- System -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button" id="system" data-bs-toggle="collapse" data-bs-target="#collapse_system" aria-expanded="true" aria-controls="collapse_system">System</span>
</h3>
<div id="collapse_system" class="accordion-collapse collapse {{ (! $flash=session()->pull('accordion')) ? 'show' : '' }}" aria-labelledby="system" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@include('system.widget.form-system')
</div>
</div>
</div>
<!-- Addresses -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="addresses" data-bs-toggle="collapse" data-bs-target="#collapse_addresses" aria-expanded="false" aria-controls="collapse_addresses">System AKAs</span>
</h3>
<div id="collapse_addresses" class="accordion-collapse collapse {{ ($flash=='address') ? 'show' : '' }}" aria-labelledby="addresses" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
<div class="row">
<div class="col-12">
<p>FidoNet addresses are constructed in the format <strong class="highlight">zone</strong>:<strong class="highlight">net</strong>/<strong class="highlight">node</strong>.<strong class="highlight">point</strong><span>@</span><strong class="highlight">domain</strong>.</p>
<div class="accordion accordion-flush" id="accordion_ftnaddress">
<h4 class="accordion-header">
<span class="accordion-button collapsed" id="ftnaddress" data-bs-toggle="collapse" data-bs-target="#collapse_ftnaddresses" aria-expanded="false" aria-controls="collapse_addresses">Fidonet Addressing</span>
</h4>
<div id="collapse_ftnaddresses" class="accordion-collapse collapse" aria-labelledby="ftnaddress" data-bs-parent="#accordion_ftnaddress">
<div class="accordion-body">
<p>FidoNet system are also assigned some roles, and in some cases, those roles have a particular address format:</p>
<table class="table monotable">
<thead>
<tr>
<th>Role</th>
<th>Address Format</th>
</tr>
</thead>
<tbody>
<tr>
<td>Zone <small>(optional)</small></td>
<td>
<strong class="highlight">ZONE</strong>:0/0.0, where the net, node and point values are zero. Zones normally have 1 or more Regions and/or Hosts.<br><br>
<small>(Systems that do not configure other systems with a zone, assume that that other system is in the same zone as the system being configured.)</small>
</td>
</tr>
<tr>
<td>Region <small>(optional)</small></td>
<td>
zone:<strong class="highlight">REGION</strong>/0.0, where the zone indicates which zone the region is in. The node and point values are zero. Regions normally have 1 or more Hosts.<br><br>
<small>Fidonet software normally doesnt configure the region address per-se. It is used by the mailer to receive packets destined to it by routing, in transition to the final destination. The region number must be unique with a zone.</small>
</td>
</tr>
<tr>
<td>Host <small>(mandatory)</small></td>
<td>
zone:<strong class="highlight">HOST</strong>/0.0, where the zone indicates which zone the host is in. The node and point values are zero. The Host system is normally configured with an additional address, where the NET address is the same and the NODE number that is greater than zero. Hosts may may zero or more Hubs and 1 or more Nodes.<br><br>
<small>The host number must be unique within a zone, which implies that it cannot be the same as a region, if regions are used.</small>
</td>
</tr>
<tr>
<td>Hub <small>(optional)</small></td>
<td>
zone:net/<strong class="highlight">NODE</strong>.0, where the zone/net indicates which zone/net the hub is in. The system(s) in the nodelist below a Hub are fed from that hub from a routing perspective.<br><br>
<small>The node is unique within the net and point is zero.</small>
</td>
</tr>
<tr>
<td>Node <small>(required)</small></td>
<td>
zone:net/<strong class="highlight">NODE</strong>.0, where the zone/net indicates which zone/net the node is in.<br><br>
<small>The node is unique within the net and point is zero.</small>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
@if($o->addresses->count())
<p>This system has the following addresses assigned to it:</p>
<table class="table monotable">
<thead>
<tr>
<th>Address</th>
<th>Active</th>
<th>Security</th>
<th colspan="2">Role</th>
</tr>
</thead>
<tbody>
@foreach ($o->addresses->sortBy(function($item) { return sprintf('%04x%04x%04x%04x%04x',$item->zone->zone_id,$item->region_id,$item->host_id,$item->node_id,$item->point_id); }) as $oo)
<tr>
<td @if($oo->trashed()) class="trashed" @elseif (! $oo->active) class="inactive" @endif>{{ $oo->ftn }}<span class="float-end"><data value="{{ $oo->id }}:{{ $oo->validated ? 1 : 0 }}" class="validated"><i title="@if($oo->validated)Mail flowing @else Mail held @endif" @class(['bi','bi-activity'=>$oo->validated,'bi-radioactive'=>(! $oo->validated)])></i></data></span></td>
<td>{{ $oo->active ? 'YES' : 'NO' }}</td>
<td class="text-end">{{ $oo->security }}</td>
<td>{{ $oo->role_name }}</td>
<td class="nowrap actions">
@can('admin',$oo)
@if(! $oo->active_domain)
<!-- No options -->
<a href="javascript:;" title="Net Disabled"><i class="bi bi-slash-square"></i></a>
@elseif($oo->trashed())
<a href="{{ url('system/address/rec',[$oo->id]) }}" title="Restore Address"><i class="bi bi-bandaid"></i></a>
<a href="{{ url('system/address/pur',[$oo->id]) }}" title="Purge Address" class="purge"><i class="bi bi-scissors"></i></a>
@else
<a href="{{ url('system/address/mod',[$oo->id]) }}" data-id="{{ $oo->id }}" title="Modify Address" class="modaddress" aria-readonly="true"><i class="bi bi-pencil-square"></i></a>
<a href="{{ url('system/address/sus',[$oo->id]) }}" title="@if($oo->active)Pause @else Activate @endif Address"><i class="bi @if($oo->active)bi-pause-circle @else bi-play-circle @endif"></i></a>
<a href="{{ url('system/address/mov',[$o->id,$oo->id]) }}" title="Move Address to another System"><i class="bi bi-arrow-right-square"></i></a>
<a href="{{ url('system/address/del',[$oo->id]) }}" title="Delete Address"><i class="bi bi-trash"></i></a>
@if ((Address::NODE_HC|Address::NODE_NN) & $oo->role_id)
<a href="{{ url('system/address/pro',[$oo->id]) }}" title="Promote Address"><i class="bi bi-arrow-up-square"></i></a>
@endif
@if ((Address::NODE_NC|Address::NODE_HC) & $oo->role_id)
<a href="{{ url('system/address/dem',[$oo->id]) }}" title="Demote Address"><i class="bi bi-arrow-down-square"></i></a>
@endif
@endif
@endcan
</td>
</tr>
@endforeach
</tbody>
</table>
@endif
</div>
</div>
@error('address')
<div class="row pb-5">
<div class="col-12">
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
{!! $message !!}
</span>
</div>
</div>
@enderror
@can('admin',$o)
<div class="row pb-2">
<div class="col-12">
@include('system.widget.form-address')
</div>
</div>
@else
You'll need to ask an admin to assign addresses.
@endcan
</div>
</div>
</div>
@if(! $o->setup)
<!-- Authentication -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="authentication" data-bs-toggle="collapse" data-bs-target="#collapse_auth" aria-expanded="false" aria-controls="collapse_auth">System Authentication</span>
</h3>
<div id="collapse_auth" class="accordion-collapse collapse {{ ($flash=='session') ? 'show' : '' }}" aria-labelledby="authentication" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@if ($o->sessions->count())
<table class="table monotable">
<thead>
<tr>
<th colspan="2">&nbsp;</th>
<th colspan="4" class="text-center">Passwords</th>
<th>&nbsp;</th>
</tr>
<tr>
<th>Zone</th>
<th style="min-width: 1%;">Default</th>
<th>Session</th>
<th>Packet</th>
<th>TIC</th>
<th>Areafix</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
@foreach ($o->sessions->sortBy('zone_id') as $oo)
<tr>
<td>{{ $oo->zone_id }}<span>@</span>{{ $oo->domain->name }}</td>
<td style="text-align: center;">
@if(($x=$oo->systems->where('pivot.default',TRUE))->count() && ($x->first()->id !== $o->id))
<i class="bi bi-dash-square"></i>
@else
@can('admin')
<span class="default" itemid="{{ $oo->id }}"><i class="bi bi-{{ $x->count() ? 'check-square' : 'square' }}"></i></span>
@endcan
@endif
</td>
<td>{{ $oo->pivot->sespass }}</td>
<td>{{ $oo->pivot->pktpass }}</td>
<td>{{ $oo->pivot->ticpass }}</td>
<td>{{ $oo->pivot->fixpass }}</td>
<td style="width: 70px;">
{{--
<a href="{{ url('system/session/mod',[$oo->id]) }}" title="Modify Details" class="modify"><i class="bi bi-pen"></i></a>
--}}
<a href="{{ url('system/session/del',[$o->id,$oo->id]) }}" title="Delete Details" class="purge"><i class="bi bi-trash"></i></a>
<a href="{{ url('system/areafix',[$o->id,$oo->id]) }}" title="Areafix/Filefix"><i class="bi bi-envelope-paper"></i></a>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<p>No session details exist</p>
@endif
@can('update_nn',$o)
@include('system.widget.form-session')
@endcan
</div>
</div>
</div>
<!-- Echoareas -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="echoarea" data-bs-toggle="collapse" data-bs-target="#collapse_echoarea" aria-expanded="false" aria-controls="collapse_echoarea">Echo Area Subscription</span>
</h3>
<div id="collapse_echoarea" class="accordion-collapse collapse {{ ($flash=='echoarea') ? 'show' : '' }}" aria-labelledby="echoarea" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@if ($o->sessions->count())
<p>This system can subscribe to the following echoareas:</p>
@include('system.widget.form-echoarea')
@else
<p>No session details exist for this system, so Echoareas are unavailable.</p>
@endif
</div>
</div>
</div>
<!-- Fileareas -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="filearea" data-bs-toggle="collapse" data-bs-target="#collapse_filearea" aria-expanded="false" aria-controls="collapse_filearea">File Area Subscription</span>
</h3>
<div id="collapse_filearea" class="accordion-collapse collapse {{ ($flash=='filearea') ? 'show' : '' }}" aria-labelledby="filearea" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@if ($o->sessions->count())
<p>This system can subscribe to the following fileareas:</p>
@include('system.widget.form-filearea')
@else
<p>No session details exist for this system, so Fileareas are unavailable.</p>
@endif
</div>
</div>
</div>
<!-- Routing -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="routing" data-bs-toggle="collapse" data-bs-target="#collapse_routing" aria-expanded="false" aria-controls="collapse_routing">Mail Routing</span>
</h3>
<div id="collapse_routing" class="accordion-collapse collapse {{ ($flash=='routing') ? 'show' : '' }}" aria-labelledby="routing" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
@include('system.widget.routing')
</div>
</div>
</div>
<!-- Items Waiting -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="waiting" data-bs-toggle="collapse" data-bs-target="#collapse_mail" aria-expanded="false" aria-controls="collapse_mail">Items Waiting</span>
</h3>
<div id="collapse_mail" class="accordion-collapse collapse {{ ($flash=='mail') ? 'show' : '' }}" aria-labelledby="waiting" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
<div class="row">
<!-- Netmail -->
<div class="col-4">
Netmails are waiting for these addresses:
<table class="table monotable">
<thead>
<tr>
<th>Address</th>
<th>Netmail</th>
</tr>
</thead>
<tbody>
@foreach ($o->addresses->sortBy('zone.zone_id') as $ao)
<tr>
<td>{{ $ao->ftn }}</td>
<td>{{ $ao->netmailWaiting()->count() }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<!-- Echomail -->
<div class="col-4">
Echomail waiting for these addresses:
<table class="table monotable">
<thead>
<tr>
<th>Address</th>
<th>Echomail</th>
</tr>
</thead>
<tbody>
@foreach ($o->addresses->sortBy('zone.zone_id') as $ao)
<tr>
<td>{{ $ao->ftn }}</td>
<td>{{ $ao->echomailWaiting()->count() }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<!-- Files -->
<div class="col-4">
Files waiting for these addresses:
<table class="table monotable">
<thead>
<tr>
<th>Address</th>
<th>Files</th>
</tr>
</thead>
<tbody>
@foreach ($o->addresses->sortBy('zone.zone_id') as $ao)
<tr>
<td>{{ $ao->ftn }}</td>
<td>{{ $ao->filesWaiting()->count() }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
<!-- Last Packets and Files -->
<div class="accordion-item">
<h3 class="accordion-header">
<span class="accordion-button collapsed" id="last" data-bs-toggle="collapse" data-bs-target="#collapse_transfers" aria-expanded="false" aria-controls="collapse_mail">Packets and Files Sent</span>
</h3>
<div id="collapse_transfers" class="accordion-collapse collapse {{ ($flash=='transfers') ? 'show' : '' }}" aria-labelledby="last" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
<div class="row">
<div class="col-4">
The last Netmails sent (to you):
@if(($x=Netmail::select(['sent_pkt','sent_at',DB::raw('count(sent_pkt) AS count')])
->whereIn('sent_id',$o->addresses->pluck('id'))
->whereNotNull('sent_at')
->groupBy(['sent_pkt','sent_at'])
->orderBy('sent_at','DESC')
->limit(10)
->get())->count())
<table class="table monotable">
<thead>
<tr>
<th>Packet</th>
<th>Sent</th>
<th class="text-end">Count</th>
</tr>
</thead>
<tbody>
@foreach ($x as $oo)
<tr>
<td class="packet">{{ $oo->sent_pkt }}</td>
<td>{{ $oo->sent_at }}</td>
<td class="text-end">{{ $oo->count }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<strong class="highlight">None</strong>
@endif
</div>
<div class="col-4">
The last Echomails sent (to you):
@if(($x=Echomail::select(['sent_pkt','sent_at',DB::raw('count(sent_pkt) AS count')])
->join('echomail_seenby',['echomail_seenby.echomail_id'=>'echomails.id'])
->whereNotNull('sent_at')
->whereIn('address_id',$o->addresses->pluck('id'))
->groupBy(['sent_pkt','sent_at'])
->orderBy('sent_at','DESC')
->limit(10)
->get())->count())
<table class="table monotable">
<thead>
<tr>
<th>Packet</th>
<th>Sent</th>
<th class="text-end">Count</th>
</tr>
</thead>
<tbody>
@foreach ($x as $oo)
<tr>
<td class="packet">{{ $oo->sent_pkt }}</td>
<td>{{ $oo->sent_at }}</td>
<td class="text-end">{{ $oo->count }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<strong class="highlight">None</strong>
@endif
</div>
<div class="col-4">
The last Files sent (to you):
@if(($x=File::select(['sent_at',DB::raw('count(sent_at) AS count')])
->join('file_seenby',['file_seenby.file_id'=>'files.id'])
->whereNotNull('sent_at')
->whereIn('address_id',$o->addresses->pluck('id'))
->groupBy(['sent_at'])
->orderBy('sent_at','DESC')
->limit(10)
->get())->count())
<table class="table monotable">
<thead>
<tr>
<th>Session</th>
<th class="text-end">Count</th>
</tr>
</thead>
<tbody>
@foreach ($x as $oo)
<tr>
<td class="files">{{ $oo->sent_at }}</td>
<td class="text-end">{{ $oo->count }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<strong class="highlight">None</strong>
@endif
</div>
</div>
<div class="row pt-2">
<div class="col-4">
The last Netmails received (you sent):
@if(($x=Netmail::select(['recv_pkt','recv_at',DB::raw('count(recv_pkt) AS count')])
->join('netmail_path',['netmail_path.netmail_id'=>'netmails.id'])
->whereIn('address_id',$o->addresses->pluck('id'))
->groupBy(['recv_pkt','recv_at'])
->orderBy('recv_at','DESC')
->limit(10)
->get())->count())
<table class="table monotable">
<thead>
<tr>
<th>Packet</th>
<th>Received</th>
<th class="text-end">Count</th>
</tr>
</thead>
<tbody>
@foreach ($x as $oo)
<tr>
<td @class(['packet'=>$oo->recv_pkt])>{{ $oo->recv_pkt ?: '-' }}</td>
<td>{{ $oo->recv_at ?: '-' }}</td>
<td class="text-end">{{ $oo->count }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<strong class="highlight">None</strong>
@endif
</div>
<div class="col-4">
The last Echomails received (you sent):
@if(($x=Echomail::select(['recv_pkt','recv_at',DB::raw('count(recv_pkt) AS count')])
->join('echomail_path',['echomail_path.echomail_id'=>'echomails.id'])
->whereNotNull('recv_pkt')
->whereIn('address_id',$o->addresses->pluck('id'))
->groupBy(['recv_pkt','recv_at'])
->orderBy('recv_at','DESC')
->limit(10)
->get())->count())
<table class="table monotable">
<thead>
<tr>
<th>Packet</th>
<th>Received</th>
<th class="text-end">Count</th>
</tr>
</thead>
<tbody>
@foreach ($x as $oo)
<tr>
<td class="packet">{{ $oo->recv_pkt }}</td>
<td>{{ $oo->recv_at }}</td>
<td class="text-end">{{ $oo->count }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<strong class="highlight">None</strong>
@endif
</div>
<div class="col-4">
The last Files received (from you):
@if(($x=File::select(['created_at',DB::raw('count(created_at) AS count')])
->whereIn('fftn_id',$o->addresses->pluck('id'))
->groupBy(['created_at'])
->orderBy('created_at','DESC')
->limit(10)
->get())->count())
<table class="table monotable">
<thead>
<tr>
<th>Session</th>
<th class="text-end">Count</th>
</tr>
</thead>
<tbody>
@foreach ($x as $oo)
<tr>
<td class="files">{{ $oo->created_at }}</td>
<td class="text-end">{{ $oo->count }}</td>
</tr>
@endforeach
</tbody>
</table>
@else
<strong class="highlight">None</strong>
@endif
</div>
</div>
</div>
</div>
</div>
@endif
@else
@include('system.widget.form-system')
@endif
</div>
@include('widgets.modal_packet')
@include('widgets.modal_files')
@include('widgets.modal_purge')
@endsection
@section('page-css')
<style>
span.btn.btn-danger a {
color: white
}
</style>
@endsection
@section('page-scripts')
<script type="text/javascript">
$(document).ready(function () {
@can('admin')
$('.default').click(function () {
var item = this;
icon = $(item).find('i');
$.ajax({
type: 'POST',
data: {sid: {{$o->id}}, _token: '{{csrf_token()}}', set: (icon.hasClass('bi-square') ? 1 : 0)},
beforeSend: function () {
$(item).find('i').addClass('spinner-grow spinner-grow-sm');
},
success: function () {
if (icon.hasClass('bi-square')) {
icon.removeClass('bi-square');
icon.addClass('bi-check-square');
} else {
icon.removeClass('bi-check-square');
icon.addClass('bi-square');
}
$(item).find('i').removeClass('spinner-grow spinner-grow-sm');
},
error: function (e) {
$(item).find('i').removeClass('spinner-grow spinner-grow-sm');
if (e.status != 412)
alert('That didnt work? Please try again....');
},
url: '{{ url('zone/api/default') }}/' + item.attributes.itemid.nodeValue,
cache: false
})
});
@endcan
$('data.validated').on('click',function(item) {
that = $(this);
var values = item.delegateTarget.value.split(':');
var icon = that.find('i');
if (values[1] === '1') {
$.ajax({
url: '/address/api/validated/off',
type: 'POST',
dataType: 'json',
data : {id: values[0]},
beforeSend: function() {
that.addClass('spinner-grow spinner-grow-sm')
},
complete: function() {
that.removeClass('spinner-grow spinner-grow-sm')
},
success: function(data) {
icon.removeClass('bi-activity')
.addClass('bi-radioactive');
that.attr('value',values[0]+':'+0);
},
cache: false
});
} else {
$.ajax({
url: '/address/api/validated/on',
type: 'POST',
dataType: 'json',
data : {id: values[0]},
beforeSend: function() {
that.addClass('spinner-grow spinner-grow-sm')
},
complete: function() {
that.removeClass('spinner-grow spinner-grow-sm')
},
success: function(data) {
icon.removeClass('bi-radioactive')
.addClass('bi-activity');
that.attr('value',values[0]+':'+1);
},
cache: false
});
}
});
});
</script>
@append