Consistency and SQL Query optimisations - focused around the UI

This commit is contained in:
Deon George 2024-11-04 09:05:27 +11:00
parent f03533b62a
commit 3aeeed1686
21 changed files with 362 additions and 332 deletions

View File

@ -1290,7 +1290,7 @@ final class Binkp extends BaseProtocol
Log::info(sprintf('%s:- SECURE',self::LOGKEY)); Log::info(sprintf('%s:- SECURE',self::LOGKEY));
// @todo Since we have connected, if the node was marked down/hold reset that // @todo Since we have connected, if the node was marked down/hold reset that
// Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations())); // Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
} }
return $this->binkp_hsdone(); return $this->binkp_hsdone();
@ -1389,7 +1389,7 @@ final class Binkp extends BaseProtocol
$this->msgs(self::BPM_OK,sprintf('%ssecure',$have_pwd ? '' : 'non-')); $this->msgs(self::BPM_OK,sprintf('%ssecure',$have_pwd ? '' : 'non-'));
// @todo Since we have connected, if the node was marked down/hold reset that // @todo Since we have connected, if the node was marked down/hold reset that
// Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations())); // Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
} else { } else {
$this->msgs(self::OK,'non-secure'); $this->msgs(self::OK,'non-secure');

View File

@ -1062,7 +1062,7 @@ final class EMSI extends BaseProtocol implements CRCInterface,ZmodemInterface
} }
// @todo Since we have connected, if the node was marked down/hold reset that // @todo Since we have connected, if the node was marked down/hold reset that
// Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations())); // Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
// @todo Lock Node AKAs // @todo Lock Node AKAs

View File

@ -115,7 +115,7 @@ class DomainController extends Controller
if (! $o->public && ! Gate::check('admin',$o)) if (! $o->public && ! Gate::check('admin',$o))
abort(404); abort(404);
$o->load(['zones.system','zones.domain','zones.addresses.nodes_hub','zones.addresses']); $o->load(['zones.system','zones.domain','zones.addresses.nodes_hub','zones.addresses.echomail_from']);
return view('domain.view') return view('domain.view')
->with('o',$o); ->with('o',$o);

View File

@ -66,7 +66,17 @@ class SystemController extends Controller
->with('saved',TRUE); ->with('saved',TRUE);
} }
$o->load(['addresses.zone.domain','addresses.system','sessions.domain','sessions.systems']); $o->loadMissing([
'zcs',
// For 'ftn' to work
'addresses.zone:id,zone_id,domain_id,active',
'addresses.zone.domain:id,name,active',
// For 'role'
'addresses.system:id,address',
// For system addedit
'sessions.domain:id,name,active',
'sessions.systems:id',
]);
return view('system.addedit') return view('system.addedit')
->with('action',$o->exists ? 'update_nn' : 'create') ->with('action',$o->exists ? 'update_nn' : 'create')
@ -611,31 +621,12 @@ class SystemController extends Controller
*/ */
public function register(SystemRegisterRequest $request) public function register(SystemRegisterRequest $request)
{ {
// Step 1, show the user a form to select an existing defined system
if ($request->isMethod('GET'))
return view('user.system.register');
if ($request->action === 'register' && $request->name && is_numeric($request->name)) if ($request->action === 'register' && $request->name && is_numeric($request->name))
return view('user.system.widget.register_confirm') return view('user.system.widget.register_confirm')
->with('o',System::findOrFail($request->name)); ->with('o',System::findOrFail($request->name));
$o = System::findOrNew(is_numeric($request->system_id) ? $request->system_id : NULL); $o = System::findOrNew(is_numeric($request->system_id) ? $request->system_id : NULL);
// If the system exists, and we are 'register', we'll start the address claim process
if ($o->exists && $request->action === 'Link') {
$validate = Setup::findOrFail(config('app.id'))->system->inMyZones($o->addresses);
// If we have addresses, we'll trigger the routed netmail
if ($validate->count()) {
Notification::route('netmail',$x=$validate->first())->notify(new AddressLink(Auth::user()));
AddressPoll::dispatch($x)->delay(15);
}
return view('user.system.widget.register_send')
->with('validate',$validate)
->with('o',$o);
}
// If the system doesnt exist, we'll create it // If the system doesnt exist, we'll create it
if (! $o->exist) { if (! $o->exist) {
$o->sysop = Auth::user()->name; $o->sysop = Auth::user()->name;

View File

@ -104,8 +104,8 @@ class AddressIdle implements ShouldQueue
} }
// Netmail Alert (to othernet network address) // Netmail Alert (to othernet network address)
if ($ao->system->uncommon()->count()) { if ($ao->system->aka_unknown()->count()) {
Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeDelistedNetmail($ao->withoutRelations())); Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeDelistedNetmail($ao->withoutRelations()));
$contact = TRUE; $contact = TRUE;
} }
@ -140,8 +140,8 @@ class AddressIdle implements ShouldQueue
} }
// Netmail Alert (to othernet network address) // Netmail Alert (to othernet network address)
if ($ao->system->uncommon()->count()) { if ($ao->system->aka_unknown()->count()) {
Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations())); Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedDownNetmail($ao->withoutRelations()));
$contact = TRUE; $contact = TRUE;
} }
@ -188,8 +188,8 @@ class AddressIdle implements ShouldQueue
} }
// Netmail Alert (to othernet network address) // Netmail Alert (to othernet network address)
if ($ao->system->uncommon()->count()) { if ($ao->system->aka_unknown()->count()) {
Notification::route('netmail',$ao->system->uncommon()->first()->withoutRelations())->notify(new NodeMarkedHoldNetmail($ao->withoutRelations())); Notification::route('netmail',$ao->system->aka_unknown()->first()->withoutRelations())->notify(new NodeMarkedHoldNetmail($ao->withoutRelations()));
$contact = TRUE; $contact = TRUE;
} }
@ -214,21 +214,9 @@ class AddressIdle implements ShouldQueue
$age = Carbon::now()->subDays($days)->endOfDay(); $age = Carbon::now()->subDays($days)->endOfDay();
return Address::select([ return Address::FTN()
'addresses.id', ->ActiveFTN()
'system_id', ->addSelect(['addresses.updated_at'])
'zone_id',
'region_id',
'host_id',
'node_id',
'point_id',
'addresses.active',
'hub_id',
'role',
'addresses.updated_at',
])
->activeFTN()
->where('systems.active',TRUE)
->where(fn($query)=>$query->where('point_id',0)->orWhereNull('point_id')) ->where(fn($query)=>$query->where('point_id',0)->orWhereNull('point_id'))
->whereIn('addresses.id',our_nodes($do)->pluck('id')) ->whereIn('addresses.id',our_nodes($do)->pluck('id'))
->when($ao,fn($query)=>$query->where('addresses.id',$ao->id)) ->when($ao,fn($query)=>$query->where('addresses.id',$ao->id))
@ -236,9 +224,7 @@ class AddressIdle implements ShouldQueue
->whereRaw(sprintf('((role IS NULL) OR (role=0) OR ((role & %d) > 0))',$flags)) ->whereRaw(sprintf('((role IS NULL) OR (role=0) OR ((role & %d) > 0))',$flags))
->whereRaw(sprintf('((role IS NULL) OR ((role & %d) = 0))',Address::NODE_KEEP)) ->whereRaw(sprintf('((role IS NULL) OR ((role & %d) = 0))',Address::NODE_KEEP))
->join('systems',['systems.id'=>'addresses.system_id']) ->join('systems',['systems.id'=>'addresses.system_id'])
->ftnOrder() //->with(['system','zone.domain'])
->with(['system','zone.domain'])
->dontCache()
->get(); ->get();
} }
} }

View File

@ -395,16 +395,14 @@ class Address extends Model
* *
* @param $query * @param $query
* @return mixed * @return mixed
* @note zones and domains needs to be joined in the base call, or use FTN()
*/ */
public function scopeActiveFTN($query) public function scopeActiveFTN($query)
{ {
return $query->select($this->getTable().'.*') return $query
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->where('zones.active',TRUE) ->where('zones.active',TRUE)
->where('domains.active',TRUE) ->where('domains.active',TRUE)
->active() ->active();
->FTNorder();
} }
/** /**
@ -416,13 +414,21 @@ class Address extends Model
public function scopeFTN($query) public function scopeFTN($query)
{ {
return $query return $query
->select(['id','addresses.zone_id','host_id','node_id','point_id','system_id']) ->select(['addresses.id','region_id','host_id','node_id','point_id','addresses.zone_id','addresses.active','role','security','addresses.system_id','addresses.active','validated'])
->join('zones',['zones.id'=>'addresses.zone_id'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->orderBy('region_id')
->orderBy('host_id')
->orderBy('node_id')
->orderBy('point_id')
->with([ ->with([
'zone:zones.id,domain_id,zone_id', 'zone:zones.id,domain_id,zone_id,active',
'zone.domain:domains.id,name', 'zone.domain:domains.id,name,active,public',
]); ]);
} }
/** @deprecated use FTN() */
public function scopeFTNOrder($query) public function scopeFTNOrder($query)
{ {
return $query return $query

View File

@ -48,35 +48,39 @@ class System extends Model
$uo = Auth::user(); $uo = Auth::user();
return $query return $query
->when($uo && ! $uo->isAdmin(),function($query) use ($uo) { ->when(
return $query->whereIn('id',$uo->systems->pluck('id')) $uo && ! $uo->isAdmin(),
->orWhere($this->getTable().'.active',TRUE); fn($query)=>
},function($query) { $query->where($this->getTable().'.active',TRUE); }) $query
->whereIn('id',$uo->systems->pluck('id'))
->orWhere($this->getTable().'.active',TRUE),
fn($query)=>$query->where($this->getTable().'.active',TRUE))
->orderBy('name'); ->orderBy('name');
} }
/* RELATIONS */ /* RELATIONS */
/**
* All addresses assigned to a system, including addresses pending deletion
* @return mixed
*/
public function addresses() public function addresses()
{ {
return $this->hasMany(Address::class) return $this->hasMany(Address::class)
->withTrashed() ->FTN()
->FTNorder(); ->withTrashed();
} }
/**
* System addresses that are active
*
* @return mixed
*/
public function akas() public function akas()
{ {
return $this->hasMany(Address::class) return $this->hasMany(Address::class)
->select('addresses.*') ->FTN()
->join('zones',['zones.id'=>'addresses.zone_id']) ->ActiveFTN();
->join('domains',['domains.id'=>'zones.domain_id'])
->where('addresses.active',TRUE)
->where('zones.active',TRUE)
->where('domains.active',TRUE)
->orderBy('domains.name')
->with(['zone.domain'])
->FTNorder()
->orderBy('role','ASC');
} }
public function mailers() public function mailers()
@ -136,7 +140,14 @@ class System extends Model
*/ */
public function zcs() public function zcs()
{ {
return $this->hasMany(Zone::class); return $this->hasMany(Zone::class)
->select(['zones.id','zone_id','domain_id','system_id','zones.active'])
->join('domains',['domains.id'=>'zones.domain_id'])
->orderBy('domains.name')
->orderBy('zone_id')
->with([
'domain:id,name,active',
]);
} }
/** /**
@ -189,6 +200,58 @@ class System extends Model
/* METHODS */ /* METHODS */
/**
* Return the ACTIVE addresses that are common with our addresses
*
* @return Collection
* @throws \Exception
*/
public function aka_common(): Collection
{
$our = our_address()->pluck('zone.domain_id')->unique();
// Return our akas, filter with our_addresses()
return $this->akas->filter(fn($item)=>$our->contains($item->zone->domain_id));
}
/**
* Return the ACTIVE addresses that we auth with
*
* @return Collection
* @throws \Exception
*/
public function aka_known(): Collection
{
return $this->aka_common()
->filter(fn($item)=>$this->sessions->contains($item->zone_id));
}
/**
* Return the ACTIVE addresses in the same networks as us, but dont auth here
*
* @return Collection
* @throws \Exception
*/
public function aka_unknown(): Collection
{
return $this->aka_common()
->filter(fn($item)=>! $this->sessions->contains($item->zone_id));
}
/**
* Return the AKAs that are in networks not common with us
*
* @return Collection
* @throws \Exception
*/
public function aka_uncommon(): Collection
{
$our = our_address()->pluck('zone.domain_id')->unique();
// Return our akas, filter with our_addresses()
return $this->akas->filter(fn($item)=>! $our->contains($item->zone->domain_id));
}
public function echoareas() public function echoareas()
{ {
return Echoarea::select('echoareas.*') return Echoarea::select('echoareas.*')
@ -250,28 +313,13 @@ class System extends Model
: $akas; : $akas;
} }
/**
* Parse the addresses and return which ones are in my zones
*
* @param \Illuminate\Database\Eloquent\Collection $addresses
* @param int $type
* @return Collection
*/
public function inMyZones(Collection $addresses,int $type=(Address::NODE_HC|Address::NODE_NN|Address::NODE_POINT)): Collection
{
$myzones = $this->addresses->pluck('zone_id')->unique();
return $addresses->filter(function($item) use ($myzones,$type) {
return ($item->role & $type) && ($myzones->search($item->zone_id) !== FALSE);
});
}
/** /**
* Return the packet that this system uses * Return the packet that this system uses
* *
* @param Address $ao * @param Address $ao
* @param string|null $password * @param string|null $password
* @return Packet * @return Packet
* @throws \Exception
*/ */
public function packet(Address $ao,string $password=NULL): Packet public function packet(Address $ao,string $password=NULL): Packet
{ {
@ -289,22 +337,7 @@ class System extends Model
{ {
return Job::where('queue',AddressPoll::QUEUE) return Job::where('queue',AddressPoll::QUEUE)
->get() ->get()
->where(function($item) { ->where(fn($item)=>$this->akas->pluck('id')->contains($item->command->address->id))
return $this->akas->pluck('id')->search($item->command->address->id) !== FALSE; })
->last(); ->last();
} }
/**
* Return other addresses that are not collected here, but are on the same network as us.
*
* @return \Illuminate\Database\Eloquent\Collection
* @throws \Exception
*/
public function uncommon(): Collection
{
$our = our_address();
return $this->akas
->filter(fn($item)=>(($x=$item->parent()) && (! $our->contains($x)) && ($our->pluck('zone.domain_id')->contains($item->zone->domain_id))));
}
} }

View File

@ -75,19 +75,14 @@ class User extends Authenticatable implements MustVerifyEmail
/* GENERAL METHODS */ /* GENERAL METHODS */
public function addresses(Domain $o=NULL): Collection public function addresses(): Collection
{ {
return Address::select('addresses.*') return Address::select('addresses.*')
->join('systems',['systems.id'=>'addresses.system_id']) ->join('systems',['systems.id'=>'addresses.system_id'])
->join('system_user',['system_user.system_id'=>'systems.id']) ->join('system_user',['system_user.system_id'=>'systems.id'])
->when(! is_null($o),function($query) use ($o) {
return $query
->join('zones',['zones.id'=>'addresses.zone_id'])
->where('zones.domain_id',$o->id);
})
->where('system_user.user_id',$this->id) ->where('system_user.user_id',$this->id)
->activeFTN() ->ActiveFTN()
->with(['zone.domain']) ->FTN()
->get(); ->get();
} }

View File

@ -46,9 +46,9 @@ class NodeMarkedDown extends Netmails //implements ShouldQueue
->addText(sprintf("Your system has been marked **DOWN**, because it hasnt polled **%s** with address %s since **%s** (%d days).\r",$this->ao->zone->domain->name,$this->ao->ftn4d,$this->ao->system->last_seen?->format('Y-m-d') ?: 'Not seen',$this->ao->system->last_seen?->diffInDays($now))) ->addText(sprintf("Your system has been marked **DOWN**, because it hasnt polled **%s** with address %s since **%s** (%d days).\r",$this->ao->zone->domain->name,$this->ao->ftn4d,$this->ao->system->last_seen?->format('Y-m-d') ?: 'Not seen',$this->ao->system->last_seen?->diffInDays($now)))
->addText("\r") ->addText("\r")
->addText("You have (waiting for collection):\r") ->addText("You have (waiting for collection):\r")
->addText(sprintf('* %s Netmails',number_format($this->ao->netmailWaiting()->count()))) ->addText(sprintf("* %s Netmails\r",number_format($this->ao->netmailWaiting()->count())))
->addText(sprintf('* %s Echomails',number_format($this->ao->echomailWaiting()->count()))) ->addText(sprintf("* %s Echomails\r",number_format($this->ao->echomailWaiting()->count())))
->addText(sprintf('* %s Files',number_format($this->ao->filesWaiting()->count()))) ->addText(sprintf("* %s Files\r",number_format($this->ao->filesWaiting()->count())))
->addText("\r") ->addText("\r")
->addText(sprintf("Your system will automatically be **DE-LISTED** if your system hasnt polled to collected your mail/file(s) by **%s**\r\r",$now->addDays(7)->format('Y-m-d'))) ->addText(sprintf("Your system will automatically be **DE-LISTED** if your system hasnt polled to collected your mail/file(s) by **%s**\r\r",$now->addDays(7)->format('Y-m-d')))
->addText("If you think you've received this netmail by mistake or need help, please let me know.\r"); ->addText("If you think you've received this netmail by mistake or need help, please let me know.\r");

View File

@ -47,9 +47,9 @@ class NodeMarkedHold extends Netmails //implements ShouldQueue
->addText(sprintf("Your system has been marked **HOLD**, because it hasnt polled **%s** with address %s since **%s** (%d days).\r",$this->ao->zone->domain->name,$this->ao->ftn4d,$this->ao->system->last_seen?->format('Y-m-d') ?: 'Not seen',$this->ao->system->last_seen?->diffInDays($now))) ->addText(sprintf("Your system has been marked **HOLD**, because it hasnt polled **%s** with address %s since **%s** (%d days).\r",$this->ao->zone->domain->name,$this->ao->ftn4d,$this->ao->system->last_seen?->format('Y-m-d') ?: 'Not seen',$this->ao->system->last_seen?->diffInDays($now)))
->addText("\r") ->addText("\r")
->addText("You have (waiting for collection):\r") ->addText("You have (waiting for collection):\r")
->addText(sprintf('* %s Netmails',number_format($this->ao->netmailWaiting()->count()))) ->addText(sprintf("* %s Netmails\r",number_format($this->ao->netmailWaiting()->count())))
->addText(sprintf('* %s Echomails',number_format($this->ao->echomailWaiting()->count()))) ->addText(sprintf("* %s Echomails\r",number_format($this->ao->echomailWaiting()->count())))
->addText(sprintf('* %s Files',number_format($this->ao->filesWaiting()->count()))) ->addText(sprintf("* %s Files\r",number_format($this->ao->filesWaiting()->count())))
->addText("\r") ->addText("\r")
->addText(sprintf("To clear this status, all you need to do make sure your system polls and collects mail by **%s**\r\r",($this->ao->system->last_seen ?: Carbon::now())->addDays(config('fido.idle.down'))->format('Y-m-d'))) ->addText(sprintf("To clear this status, all you need to do make sure your system polls and collects mail by **%s**\r\r",($this->ao->system->last_seen ?: Carbon::now())->addDays(config('fido.idle.down'))->format('Y-m-d')))
->addText("If you think you've received this netmail by mistake or need help, please let me know.\r"); ->addText("If you think you've received this netmail by mistake or need help, please let me know.\r");

View File

@ -114,6 +114,7 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
// We are requesting a list of addresses for a Domain, or a specific Address, and we have more than 1 // We are requesting a list of addresses for a Domain, or a specific Address, and we have more than 1
switch (get_class($o)) { switch (get_class($o)) {
// Looking for addresses in the same domain, and if fido.strict, addresses that have a higher role (ie: uplink)
case Address::class: case Address::class:
$filter = $so->system->akas $filter = $so->system->akas
->filter(fn($item)=>$item->zone->domain_id === $o->zone->domain_id) ->filter(fn($item)=>$item->zone->domain_id === $o->zone->domain_id)
@ -125,6 +126,7 @@ function our_address(Domain|Address $o=NULL): Collection|Address|NULL
return $filter->count() ? $filter->last()->unsetRelation('nodes_hub') : NULL; return $filter->count() ? $filter->last()->unsetRelation('nodes_hub') : NULL;
// Addresses in this domain
case Domain::class: case Domain::class:
return $so->system->akas return $so->system->akas
->filter(fn($item)=>$item->zone->domain_id === $o->id) ->filter(fn($item)=>$item->zone->domain_id === $o->id)

View File

@ -28,9 +28,7 @@ $user->load(['systems.akas.zone.domain.echoareas','systems.akas.echoareas']);
@foreach($user @foreach($user
->addresses() ->addresses()
->diff(our_address()) ->diff(our_address())
->filter(fn($item)=>($item->point_id === 0)) ->filter(fn($item)=>($item->point_id === 0) && ($item->zone->domain->isManaged()))
->filter(function($item) { return $item->zone->domain->active && $item->zone->domain->public && $item->zone->domain->isManaged(); })
->sortBy('zone.domain.name')
->groupBy('zone.domain.name') as $list) ->groupBy('zone.domain.name') as $list)
<!-- {{ $x=$list->first()->domain->name }} --> <!-- {{ $x=$list->first()->domain->name }} -->
<div class="accordion-item"> <div class="accordion-item">

View File

@ -1,5 +1,5 @@
<!-- $o=Domain::class -->
@use(Illuminate\Mail\Markdown) @use(Illuminate\Mail\Markdown)
<!-- $o=Domain::class -->
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@ -137,12 +137,13 @@
<div id="collapse_systems" class="accordion-collapse collapse" aria-labelledby="systems" data-bs-parent="#accordion_homepage"> <div id="collapse_systems" class="accordion-collapse collapse" aria-labelledby="systems" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<p>The following systems are members of this network.</p> <p>The following systems are members of this network.</p>
<table class="table monotable" id="system"> <table class="table monotable w-100" id="system">
<thead> <thead>
<tr> <tr>
<th>System</th> <th>System</th>
<th>Sysop</th> <th>Sysop</th>
<th>Location</th> <th>Location</th>
<th>Region</th>
<th>Address</th> <th>Address</th>
<th>Last Echomail</th> <th>Last Echomail</th>
</tr> </tr>
@ -155,6 +156,7 @@
<td><a href="{{ url('system/addedit',[$ao->system_id]) }}">{{ $ao->system->full_name($ao) }}</a> @auth<span class="float-end"><small>@if($ao->is_hosted)<sup>{{ $ao->is_default ? '**' : '*' }}</sup>@elseif($ao->system->setup)<sup class="success">+</sup>@endif[{{ $ao->system_id }}]</small></span>@endauth</td> <td><a href="{{ url('system/addedit',[$ao->system_id]) }}">{{ $ao->system->full_name($ao) }}</a> @auth<span class="float-end"><small>@if($ao->is_hosted)<sup>{{ $ao->is_default ? '**' : '*' }}</sup>@elseif($ao->system->setup)<sup class="success">+</sup>@endif[{{ $ao->system_id }}]</small></span>@endauth</td>
<td>{{ $ao->system->sysop }}</td> <td>{{ $ao->system->sysop }}</td>
<td>{{ $ao->system->location }}</td> <td>{{ $ao->system->location }}</td>
<td>{{ $ao->region_id }}</td>
<td>{{ $ao->ftn4d }}</td> <td>{{ $ao->ftn4d }}</td>
<td>{{ $ao->echomail_from->count() ? $ao->echomail_from->first()->datetime->format('Y-m-d H:i') : '-' }}</td> <td>{{ $ao->echomail_from->count() ? $ao->echomail_from->first()->datetime->format('Y-m-d H:i') : '-' }}</td>
</tr> </tr>
@ -279,6 +281,18 @@
searching: true, searching: true,
ordering: true, ordering: true,
order: [], order: [],
rowGroup: {
dataSrc: [3],
startRender: function(rows,group) {
return 'Region '+group;
}
},
columnDefs: [
{
targets: [3],
visible: false,
},
],
conditionalPaging: { conditionalPaging: {
style: 'fade', style: 'fade',
speed: 500 // optional speed: 500 // optional

View File

@ -20,7 +20,7 @@
@endif @endif
@if($o->zcs->count()) @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> <p>This system is the ZC for the following zones: <strong class="highlight">{!! $o->zcs->map(fn($item)=>sprintf('%d@%s',$item->zone_id,$item->domain->name))->join('</strong>, <strong class="highlight">') !!} </strong></p>
@endif @endif
@include('widgets.error') @include('widgets.error')
@ -123,7 +123,7 @@
</thead> </thead>
<tbody> <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) @foreach ($o->addresses as $oo)
<tr> <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 @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>{{ $oo->active ? 'YES' : 'NO' }}</td>
@ -156,7 +156,6 @@
</tbody> </tbody>
</table> </table>
@endif @endif
</div> </div>
</div> </div>
@ -321,7 +320,7 @@
</thead> </thead>
<tbody> <tbody>
@foreach ($o->addresses->sortBy('zone.zone_id') as $ao) @foreach ($o->aka_common() as $ao)
<tr> <tr>
<td>{{ $ao->ftn }}</td> <td>{{ $ao->ftn }}</td>
<td>{{ $ao->netmailWaiting()->count() }}</td> <td>{{ $ao->netmailWaiting()->count() }}</td>
@ -343,7 +342,7 @@
</thead> </thead>
<tbody> <tbody>
@foreach ($o->addresses->sortBy('zone.zone_id') as $ao) @foreach ($o->aka_common() as $ao)
<tr> <tr>
<td>{{ $ao->ftn }}</td> <td>{{ $ao->ftn }}</td>
<td>{{ $ao->echomailWaiting()->count() }}</td> <td>{{ $ao->echomailWaiting()->count() }}</td>
@ -365,7 +364,7 @@
</thead> </thead>
<tbody> <tbody>
@foreach ($o->addresses->sortBy('zone.zone_id') as $ao) @foreach ($o->aka_common() as $ao)
<tr> <tr>
<td>{{ $ao->ftn }}</td> <td>{{ $ao->ftn }}</td>
<td>{{ $ao->filesWaiting()->count() }}</td> <td>{{ $ao->filesWaiting()->count() }}</td>

View File

@ -1,91 +1,84 @@
@if(($x=\App\Models\Zone::active() <form class="needs-validation" method="post" action="{{ url('system/echoarea',$o->id) }}" novalidate>
->whereIn('id',$o->sessions->pluck('pivot.zone_id')) @csrf
->orderBy('zone_id')
->with(['domain'])
->get())->count())
<form class="needs-validation" method="post" action="{{ url('system/echoarea',$o->id) }}" novalidate> <div class="row pt-0">
@csrf <div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<div class="row pt-0"> <div class="row">
<div class="col-12"> <!-- Select Domain -->
<div class="greyframe titledbox shadow0xb0"> <div class="col-3">
<div class="row"> <label for="echoarea_domain_id" class="form-label">Network</label>
<!-- Select Domain --> <div class="input-group has-validation">
<div class="col-3"> <span class="input-group-text"><i class="bi bi-hash"></i></span>
<label for="echoarea_domain_id" class="form-label">Network</label> <select class="form-select @error('domain_id') is-invalid @enderror" id="echoarea_domain_id" name="domain_id" required>
<div class="input-group has-validation"> <option></option>
<span class="input-group-text"><i class="bi bi-hash"></i></span> @foreach($o->sessions as $zo)
<select class="form-select @error('domain_id') is-invalid @enderror" id="echoarea_domain_id" name="domain_id" required> <option value="{{ $zo->domain_id }}" @if(old('domain_id') == $zo->domain_id)selected @endif>{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
<option></option>
@foreach($x as $zo)
<option value="{{ $zo->domain_id }}" @if(old('domain_id') == $zo->domain_id)selected @endif>{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('domain_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Select Address -->
<div class="col-3">
<div class="d-none" id="echoarea_address-select">
<label for="echoarea_address_id" class="form-label">Address</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select" id="echoarea_address_id" name="address_id" required>
<option></option>
</select>
</div>
</div>
</div>
<!-- Summary of Addresses -->
<div class="offset-3 col-3" id="echoarea-summary">
<table class="table monotable">
<thead>
<tr>
<th>Network</th>
<th class="text-end">Areas</th>
</tr>
</thead>
<tbody>
@foreach ($o->echoareas()->with(['domain'])->get()->groupBy('domain_id') as $oo)
<tr>
<td>{{ $oo->first()->domain->name }}</td>
<td class="text-end">{{ $oo->count() }}</td>
</tr>
@endforeach @endforeach
</tbody> </select>
</table> <span class="invalid-feedback" role="alert">
</div> @error('domain_id')
</div> {{ $message }}
@enderror
@if($errors->count())
<div class="row">
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
There were errors with the submission.
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</span> </span>
</div> </div>
@endif
<div class="row">
<div class="col-12 d-none" id="echoarea-select"></div>
</div> </div>
<!-- Select Address -->
<div class="col-3">
<div class="d-none" id="echoarea_address-select">
<label for="echoarea_address_id" class="form-label">Address</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select" id="echoarea_address_id" name="address_id" required>
<option></option>
</select>
</div>
</div>
</div>
<!-- Summary of Addresses -->
<div class="offset-3 col-3" id="echoarea-summary">
<table class="table monotable">
<thead>
<tr>
<th>Network</th>
<th class="text-end">Areas</th>
</tr>
</thead>
<tbody>
@foreach ($o->echoareas()->with(['domain'])->get()->groupBy('domain_id') as $oo)
<tr>
<td>{{ $oo->first()->domain->name }}</td>
<td class="text-end">{{ $oo->count() }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@if($errors->count())
<div class="row">
<span class="btn btn-sm btn-danger" role="alert" style="text-align: left;">
There were errors with the submission.
<ul>
@foreach ($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</span>
</div>
@endif
<div class="row">
<div class="col-12 d-none" id="echoarea-select"></div>
</div> </div>
</div> </div>
</div> </div>
</form> </div>
@endif </form>
@section('page-scripts') @section('page-scripts')
<script type="text/javascript" src="{{ asset('plugin/checkboxes/jquery.checkboxes-1.2.2.min.js') }}"></script> <script type="text/javascript" src="{{ asset('plugin/checkboxes/jquery.checkboxes-1.2.2.min.js') }}"></script>

View File

@ -1,78 +1,71 @@
@if(($x=\App\Models\Zone::active() <form class="needs-validation" method="post" action="{{ url('system/filearea',$o->id) }}" novalidate>
->whereIn('id',$o->sessions->pluck('pivot.zone_id')) @csrf
->orderBy('zone_id')
->with(['domain'])
->get())->count())
<form class="needs-validation" method="post" action="{{ url('system/filearea',$o->id) }}" novalidate> <div class="row pt-0">
@csrf <div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<div class="row pt-0"> <div class="row">
<div class="col-12"> <!-- Select Domain -->
<div class="greyframe titledbox shadow0xb0"> <div class="col-3">
<div class="row"> <label for="domain_id" class="form-label">Network</label>
<!-- Select Domain --> <div class="input-group has-validation">
<div class="col-3"> <span class="input-group-text"><i class="bi bi-hash"></i></span>
<label for="domain_id" class="form-label">Network</label> <select class="form-select @error('domain_id') is-invalid @enderror" id="filearea_domain_id" name="domain_id" required>
<div class="input-group has-validation"> <option></option>
<span class="input-group-text"><i class="bi bi-hash"></i></span> @foreach($o->sessions as $zo)
<select class="form-select @error('domain_id') is-invalid @enderror" id="filearea_domain_id" name="domain_id" required> <option value="{{ $zo->domain_id }}" @if(old('domain_id') == $zo->domain_id)selected @endif>{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
<option></option>
@foreach($x as $zo)
<option value="{{ $zo->domain_id }}" @if(old('domain_id') == $zo->domain_id)selected @endif>{{ $zo->zone_id }} <small>({{ $zo->domain->name }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('domain_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<!-- Select Address -->
<div class="col-3">
<div class="d-none" id="filearea_address-select">
<label for="filearea_address_id" class="form-label">Address</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select" id="filearea_address_id" name="address_id" required>
<option></option>
</select>
</div>
</div>
</div>
<!-- Summary of Addresses -->
<div class="offset-3 col-3" id="filearea-summary">
<table class="table monotable">
<thead>
<tr>
<th>Network</th>
<th class="text-end">Areas</th>
</tr>
</thead>
<tbody>
@foreach ($o->fileareas()->with(['domain'])->get()->groupBy('domain_id') as $oo)
<tr>
<td>{{ $oo->first()->domain->name }}</td>
<td class="text-end">{{ $oo->count() }}</td>
</tr>
@endforeach @endforeach
</tbody> </select>
</table> <span class="invalid-feedback" role="alert">
@error('domain_id')
{{ $message }}
@enderror
</span>
</div> </div>
</div> </div>
<div class="row"> <!-- Select Address -->
<div class="col-12 d-none" id="filearea-select"></div> <div class="col-3">
<div class="d-none" id="filearea_address-select">
<label for="filearea_address_id" class="form-label">Address</label>
<div class="input-group">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select" id="filearea_address_id" name="address_id" required>
<option></option>
</select>
</div>
</div>
</div> </div>
<!-- Summary of Addresses -->
<div class="offset-3 col-3" id="filearea-summary">
<table class="table monotable">
<thead>
<tr>
<th>Network</th>
<th class="text-end">Areas</th>
</tr>
</thead>
<tbody>
@foreach ($o->fileareas()->with(['domain'])->get()->groupBy('domain_id') as $oo)
<tr>
<td>{{ $oo->first()->domain->name }}</td>
<td class="text-end">{{ $oo->count() }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-12 d-none" id="filearea-select"></div>
</div> </div>
</div> </div>
</div> </div>
</form> </div>
@endif </form>
@section('page-scripts') @section('page-scripts')
<script type="text/javascript" src="{{ asset('plugin/checkboxes/jquery.checkboxes-1.2.2.min.js') }}"></script> <script type="text/javascript" src="{{ asset('plugin/checkboxes/jquery.checkboxes-1.2.2.min.js') }}"></script>

View File

@ -6,7 +6,7 @@
<div class="row pt-0"> <div class="row pt-0">
<div class="col-12"> <div class="col-12">
<div class="greyframe titledbox shadow0xb0"> <div class="greyframe titledbox shadow0xb0">
<h2 class="cap">@can($action,$o) @if($o->exists) Update @else Add @endif @endif System</h2> <h2 class="cap">@can($action,$o) @if($o->exists) Update @else Add @endif @endcan System</h2>
@include('system.widget.system') @include('system.widget.system')
</div> </div>

View File

@ -1,15 +1,9 @@
@php @use(App\Models\Address)
use App\Models\{Address,Zone}; <!-- $o=System::class -->
@endphp
<div class="row"> <div class="row">
<!-- Zone mail sent to --> <!-- Zone mail sent to, because we dont have session details for these addresses -->
<div class="col-6"> <div class="col-6">
@if(! $o->setup && ($x=Zone::active() @if($o->aka_unknown()->count())
->whereIn('id',$o->zones->pluck('id'))
->whereNotIn('id',$o->sessions->pluck('id'))
->get())->count())
<h4>This host's mail is sent to:</h4> <h4>This host's mail is sent to:</h4>
<table class="table monotable"> <table class="table monotable">
<thead> <thead>
@ -20,19 +14,17 @@
</thead> </thead>
<tbody> <tbody>
@foreach($x as $zo) @foreach($o->aka_unknown() as $ao)
@foreach ($o->match($zo,Address::NODE_ALL) as $oo) <tr>
<tr> <td>{{ $ao->ftn }}</td>
<td>{{ $oo->ftn }}</td> <td>
<td> @if ($xx=$ao->uplink())
@if ($x=$oo->uplink()) {{ $xx->ftn4d }}
{{ $x->ftn4d }} @else
@else None
None @endif
@endif </td>
</td> </tr>
</tr>
@endforeach
@endforeach @endforeach
</tbody> </tbody>
</table> </table>
@ -41,28 +33,62 @@
<!-- Systems this host collects for --> <!-- Systems this host collects for -->
<div class="col-6"> <div class="col-6">
@if($o->sessions->count()) <div class="row">
<h4>This host collects mail for the following systems:</h4> <div class="col-12">
@if($o->sessions->count())
<h4>This host collects mail for the following systems:</h4>
<table class="table monotable"> <table class="table monotable">
<thead> <thead>
<tr>
<th>AKA</th>
<th>For Systems(s)</th>
</tr>
</thead>
<tbody>
@foreach ($o->sessions->sortBy('zone_id') as $zo)
@foreach ($o->match($zo,Address::NODE_ALL) as $oo)
<tr> <tr>
<td>{{ $oo->ftn }}</td> <th>AKA</th>
<td>{!! (($x=$oo->downlinks()) && $x->count()) ? $x->pluck('ftn')->join('<br>') : 'None' !!}</td> <th>Incl Systems(s)</th>
</tr> </tr>
@endforeach </thead>
@endforeach
</tbody> <tbody>
</table> @foreach ($o->sessions->sortBy('zone_id') as $zo)
@if($zo->pivot->default)
<tr>
<td>{!! $o->akas->filter(fn($item)=>$item->zone->domain_id === $zo->domain_id)->pluck('ftn')->join('<br>') !!}</td>
<td>All <small>(not otherwise routed)</small></td>
</tr>
@else
@foreach ($o->match($zo,Address::NODE_ALL) as $oo)
<tr>
<td>{{ $oo->ftn }}</td>
<td>{!! (($x=$oo->downlinks()) && $x->count()) ? $x->pluck('ftn')->join('<br>') : 'None' !!}</td>
</tr>
@endforeach
@endif
@endforeach
</tbody>
</table>
@endif
</div>
</div>
@if($o->aka_uncommon()->count())
<div class="row">
<div class="rol-12">
<h4>This host's mail not known here:</h4>
<table class="table monotable">
<thead>
<tr>
<th>AKA</th>
</tr>
</thead>
<tbody>
@foreach($o->aka_uncommon() as $ao)
<tr>
<td>{{ $ao->ftn }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
@endif @endif
</div> </div>
</div> </div>

View File

@ -1,8 +1,6 @@
@php @use(App\Classes\FTN\Packet)
use App\Classes\FTN\Packet; @use(App\Models\Mailer)
use App\Models\{Mailer,User}; @use(App\Models\User)
@endphp
<!-- $o=System::class --> <!-- $o=System::class -->
<div class="row"> <div class="row">
<div class="col-xl-9 col-12"> <div class="col-xl-9 col-12">
@ -20,7 +18,7 @@ use App\Models\{Mailer,User};
<select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]"> <select style="width: 80%;" class="form-select @error('users') is-invalid @enderror" id="users" name="users[]">
<option value="">&nbsp;</option> <option value="">&nbsp;</option>
@foreach (User::orderBy('name')->active()->get() as $uo) @foreach (User::orderBy('name')->active()->get() as $uo)
<option value="{{ $uo->id }}" @if(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))selected @endif>{{ $uo->name }} <small>({{ $uo->email }})</small></option> <option value="{{ $uo->id }}" @selected(in_array($uo->id,old('users',$o->users->pluck('id')->toArray())))>{{ $uo->name }} <small>({{ $uo->email }})</small></option>
@endforeach @endforeach
</select> </select>
@ -325,8 +323,6 @@ use App\Models\{Mailer,User};
</div> </div>
</div> </div>
@endcan @endcan
</div> </div>
@if(! is_null($o->pollmode)) @if(! is_null($o->pollmode))
@ -438,9 +434,6 @@ use App\Models\{Mailer,User};
@else @else
<input type="hidden" name="system_id" value="{{ $o->id }}"> <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> <span><small><strong>NOTE:</strong> You'll be able to update these details after registration is completed.</small></span>
{{--
<button type="submit" class="btn btn-success float-end" name="submit" value="register">Register</button>
--}}
@endcan @endcan
@else @else
<button type="submit" class="btn btn-success float-end" name="submit" value="create">Register</button> <button type="submit" class="btn btn-success float-end" name="submit" value="create">Register</button>

View File

@ -29,7 +29,7 @@ use App\Models\System;
@foreach (System::select(['systems.id','systems.name']) @foreach (System::select(['systems.id','systems.name'])
->active() ->active()
->where('id','<>',$setup->system_id) ->where('id','<>',$setup->system_id)
->whereRaw('id NOT IN (SELECT system_id FROM system_user)') ->whereRaw('id NOT IN (SELECT system_id FROM "system_user")')
->cursor() as $oo) ->cursor() as $oo)
<option value="{{ $oo->id }}" @if(old('id')===$oo->id)selected @endif>{{ $oo->name }}</option> <option value="{{ $oo->id }}" @if(old('id')===$oo->id)selected @endif>{{ $oo->name }}</option>
@endforeach @endforeach

View File

@ -133,7 +133,8 @@ Route::middleware(['auth','verified','activeuser'])->group(function () {
->where('o','[0-9]+') ->where('o','[0-9]+')
->where('packet','[0-9a-zA-Z]+'); ->where('packet','[0-9a-zA-Z]+');
Route::match(['get','post'],'user/system/register',[SystemController::class,'register']); Route::view('user/system/register','user.system.register');
Route::post('user/system/register',[SystemController::class,'register']);
Route::match(['post'],'user/system/link',[SystemController::class,'system_link']); Route::match(['post'],'user/system/link',[SystemController::class,'system_link']);
/* ZONE PATHS */ /* ZONE PATHS */