Minor optimisations when editing and viewing domains

This commit is contained in:
Deon George 2024-11-05 00:28:34 +11:00
parent dc2e84386f
commit 60ea0afc98
6 changed files with 91 additions and 73 deletions

View File

@ -186,7 +186,7 @@ class AddressIdle implements ShouldQueue
} }
if ($result->count()) if ($result->count())
Notification::route('echomail',$this->do->nodestatusarea)->notify(new AbsentNodes($result)); Notification::route('echomail',$this->do->nodestatus_echoarea)->notify(new AbsentNodes($result));
} }
private function old(Domain $do,int $days,int $flags=0,Address $ao=NULL): Collection private function old(Domain $do,int $days,int $flags=0,Address $ao=NULL): Collection

View File

@ -11,9 +11,16 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Cache; use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB; use Illuminate\Support\Facades\DB;
use App\Casts\CompressedStringOrNull; use App\Models\Casts\CompressedStringOrNull;
use App\Traits\{QueryCacheableConfig,ScopeActive}; use App\Traits\{QueryCacheableConfig,ScopeActive};
/**
* This represents an FTN Domain.
*
* We are either a member of the domain (because we have an AKA in it) or NOT.
*
* The assumption is, if we are a member of the domain, we receive/send mail to an uplink and possibly downlinks
*/
class Domain extends Model class Domain extends Model
{ {
use HasFactory,QueryCacheableConfig,ScopeActive; use HasFactory,QueryCacheableConfig,ScopeActive;
@ -28,14 +35,16 @@ class Domain extends Model
/* SCOPES */ /* SCOPES */
/** /**
* Only query active records * A domain is public (visible), if the user is an admin or, the domain is marked public)
*/ */
public function scopePublic($query) public function scopePublic($query)
{ {
$user = Auth::user(); $user = Auth::user();
return $query return $query
->when(((! $user) || (! $user->isAdmin())),function($query) { return $query->where('public',TRUE)->active(); }); ->active()
->when((! $user) || (! $user->isAdmin()),
fn($query)=>$query->where('public',TRUE));
} }
/* RELATIONS */ /* RELATIONS */
@ -43,13 +52,13 @@ class Domain extends Model
public function echoareas() public function echoareas()
{ {
return $this->hasMany(Echoarea::class) return $this->hasMany(Echoarea::class)
->orderBY('name'); ->orderBy('name');
} }
public function fileareas() public function fileareas()
{ {
return $this->hasMany(Filearea::class) return $this->hasMany(Filearea::class)
->orderBY('name'); ->orderBy('name');
} }
public function nodelist_filearea() public function nodelist_filearea()
@ -57,7 +66,7 @@ class Domain extends Model
return $this->belongsTo(Filearea::class); return $this->belongsTo(Filearea::class);
} }
public function nodestatusarea() public function nodestatus_echoarea()
{ {
return $this->belongsTo(Echoarea::class,'nodestatus_id'); return $this->belongsTo(Echoarea::class,'nodestatus_id');
} }
@ -65,29 +74,37 @@ class Domain extends Model
public function zones() public function zones()
{ {
return $this->hasMany(Zone::class) return $this->hasMany(Zone::class)
->select(['id','zone_id','domain_id','active']); ->select(['id','zone_id','domain_id','active'])
->orderBy('zone_id');
} }
/* ATTRIBUTES */ /* ATTRIBUTES */
/**
* We can accept applications if we have an address in the domain
*
* @return bool
* @throws \Exception
*/
public function getCanAcceptAppAttribute(): bool public function getCanAcceptAppAttribute(): bool
{ {
return ($x=our_address($this)) return $this->isManaged()
&& $x->count()
&& $this->active
&& $this->accept_app && $this->accept_app
&& Auth::id() && Auth::id();
&& $this->userHasSystemsNotInNet(Auth::user())->count();
} }
public function getHomePageAttribute(?string $value): string public function getHomePageAttribute(?string $value): string
{ {
//0xFD2FB528
return $this->castAttribute('homepage',$value) ?: 'No available information at the moment.'; return $this->castAttribute('homepage',$value) ?: 'No available information at the moment.';
} }
/* METHODS */ /* METHODS */
/**
* Show count of messages by day/week/month/all stats for each echoarea in this domain
*
* @return Collection
*/
public function echoarea_stats(): Collection public function echoarea_stats(): Collection
{ {
return Cache::remember(md5(sprintf('%d-%s',$this->id,__METHOD__)),self::CACHE_TIME,function() { return Cache::remember(md5(sprintf('%d-%s',$this->id,__METHOD__)),self::CACHE_TIME,function() {
@ -110,6 +127,12 @@ class Domain extends Model
}); });
} }
/**
* Show daily total of messages by echoarea in this domain
*
* @param Collection|NULL $systems
* @return Collection
*/
public function echoarea_total_daily(Collection $systems=NULL): Collection public function echoarea_total_daily(Collection $systems=NULL): Collection
{ {
return Cache::remember(md5(sprintf('%d-%s',$this->id,$systems?->pluck('id')->join(','))),self::CACHE_TIME,function() use ($systems) { return Cache::remember(md5(sprintf('%d-%s',$this->id,$systems?->pluck('id')->join(','))),self::CACHE_TIME,function() use ($systems) {
@ -120,7 +143,7 @@ class Domain extends Model
->join('echomails',['echomails.echoarea_id'=>'echoareas.id']) ->join('echomails',['echomails.echoarea_id'=>'echoareas.id'])
->where('domains.id',$this->id) ->where('domains.id',$this->id)
->where('echomails.datetime','>=',Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth()) ->where('echomails.datetime','>=',Carbon::now()->subMonths(self::STATS_MONTHS)->startOfMonth())
->when($systems?->count(),function($query) use ($systems) { return $query->whereIn('echomails.fftn_id',$systems->pluck('addresses')->flatten()->pluck('id')); }) ->when($systems?->count(),fn($query)=>$query->whereIn('echomails.fftn_id',$systems->pluck('addresses')->flatten()->pluck('id')))
->groupBy(['echoareas.name','echoareas.show','date']) ->groupBy(['echoareas.name','echoareas.show','date'])
->orderBy('echoareas.name') ->orderBy('echoareas.name')
->orderBy('date') ->orderBy('date')
@ -128,6 +151,9 @@ class Domain extends Model
}); });
} }
/**
* Show count of files by week/month/all status for each filearea in this domain
*/
public function filearea_stats() public function filearea_stats()
{ {
return Cache::remember(md5(sprintf('%d-%s',$this->id,__METHOD__)),self::CACHE_TIME,function() { return Cache::remember(md5(sprintf('%d-%s',$this->id,__METHOD__)),self::CACHE_TIME,function() {
@ -157,28 +183,6 @@ class Domain extends Model
*/ */
public function isManaged(): bool public function isManaged(): bool
{ {
return ($x=our_address()) return our_address($this)->count() > 0;
&& $x->pluck('zone.domain')
->pluck('id')
->contains($this->id);
}
/**
* Work out which of the users systems are not in this domain
*
* @param User $o
* @return Collection
*/
public function userHasSystemsNotInNet(User $o): Collection
{
$o->load('systems.akas.zone');
$result = collect();
foreach ($o->systems->filter(function($item) { return $item->active; }) as $so) {
if (! $so->akas->pluck('zone')->unique('domain_id')->pluck('domain_id')->contains($this->id))
$result->push($so);
}
return $result;
} }
} }

View File

@ -115,9 +115,10 @@ class System extends Model
public function sessions() public function sessions()
{ {
return $this->belongsToMany(Zone::class) return $this->belongsToMany(Zone::class)
->select(['id','zones.zone_id','domain_id','active']) ->select(['zones.id','zones.zone_id','domain_id','zones.active'])
->join('domains',['domains.id'=>'zones.domain_id'])
->withPivot(['sespass','pktpass','ticpass','fixpass','zt_ipv4','zt_ipv6','default']) ->withPivot(['sespass','pktpass','ticpass','fixpass','zt_ipv4','zt_ipv6','default'])
->dontCache(); ->orderBy('domains.name');
} }
/** /**
@ -301,6 +302,13 @@ class System extends Model
} }
} }
public function inDomain(Domain $o): bool
{
return $this->addresses
->filter(fn($item)=>$item->zone->domain_id === $o->id)
->count() > 0;
}
/** /**
* Return the system's address in the same zone * Return the system's address in the same zone
* This function can filter based on the address type needed. * This function can filter based on the address type needed.

View File

@ -1,14 +1,12 @@
@use(App\Models\Echoarea)
<!-- $o=Domain::class --> <!-- $o=Domain::class -->
@extends('layouts.app') @extends('layouts.app')
@section('htmlheader_title') @section('htmlheader_title')
@if($o->exists) Update @else Add @endif Domain @if($o->exists) Update @else Add @endif Domain
@endsection @endsection
@php
use App\Models\Echoarea;
@endphp
@section('content') @section('content')
<form class="needs-validation" method="post" novalidate> <form class="needs-validation" method="post" novalidate>
@csrf @csrf
@ -107,16 +105,18 @@ use App\Models\Echoarea;
</div> </div>
<div class="col-2"> <div class="col-2">
<label class="form-label">Applications</label> @if ($o->isManaged())
<div class="input-group"> <label class="form-label">Applications</label>
<div class="btn-group" role="group"> <div class="input-group">
<input type="radio" class="btn-check" name="accept_app" id="accept_app_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('accept_app',$o->accept_app))checked @endif> <div class="btn-group" role="group">
<label class="btn btn-outline-success" for="accept_app_yes">Yes</label> <input type="radio" class="btn-check" name="accept_app" id="accept_app_yes" value="1" required @cannot('admin',$o)disabled @endcannot @if(old('accept_app',$o->accept_app))checked @endif>
<label class="btn btn-outline-success" for="accept_app_yes">Yes</label>
<input type="radio" class="btn-check btn-danger" name="accept_app" id="accept_app_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('accept_app',$o->accept_app))checked @endif> <input type="radio" class="btn-check btn-danger" name="accept_app" id="accept_app_no" value="0" required @cannot('admin',$o)disabled @endcannot @if(! old('accept_app',$o->accept_app))checked @endif>
<label class="btn btn-outline-danger" for="accept_app_no">No</label> <label class="btn btn-outline-danger" for="accept_app_no">No</label>
</div>
</div> </div>
</div> @endif
</div> </div>
@if ($o->nodelist_filename) @if ($o->nodelist_filename)
@ -136,22 +136,24 @@ use App\Models\Echoarea;
<div class="col-8"> <div class="col-8">
</div> </div>
<div class="col-4"> <div class="col-4">
<label for="nodestatus_id" class="form-label">Echoarea Node Status</label> @if ($o->isManaged())
<div class="input-group has-validation"> <label for="nodestatus_id" class="form-label">Echoarea Node Status</label>
<span class="input-group-text"><i class="bi bi-journal-text"></i></span> <div class="input-group has-validation">
<select style="width: 80%;" class="form-select @error('nodestatus_id') is-invalid @enderror" id="nodestatus_id" name="nodestatus_id" @cannot('admin',$o)disabled @endcannot> <span class="input-group-text"><i class="bi bi-journal-text"></i></span>
<option value="">&nbsp;</option> <select style="width: 80%;" class="form-select @error('nodestatus_id') is-invalid @enderror" id="nodestatus_id" name="nodestatus_id" @cannot('admin',$o)disabled @endcannot>
@foreach (Echoarea::active()->where('domain_id',$o->id)->orderBy('description')->cursor() as $oo) <option value="">&nbsp;</option>
<option value="{{ $oo->id }}" @if(old('nodestatus_id',$o->nodestatus_id)==$oo->id)selected @endif>{{ $oo->description }}</option> @foreach (Echoarea::active()->where('domain_id',$o->id)->orderBy('description')->cursor() as $oo)
@endforeach <option value="{{ $oo->id }}" @if(old('nodestatus_id',$o->nodestatus_id)==$oo->id)selected @endif>{{ $oo->description }}</option>
</select> @endforeach
<span class="invalid-feedback" role="alert"> </select>
@error('nodestatus_id') <span class="invalid-feedback" role="alert">
{{ $message }} @error('nodestatus_id')
@enderror {{ $message }}
</span> @enderror
<span class="input-helper">Add a <a href="{{ url('echoarea/addedit') }}">NEW Echoarea</a>. This echoarea is used to send node status messages.</span> </span>
</div> <span class="input-helper">Add a <a href="{{ url('echoarea/addedit') }}">NEW Echoarea</a>. This echoarea is used to send node status messages.</span>
</div>
@endif
</div> </div>
</div> </div>

View File

@ -1,3 +1,4 @@
@use(App\Models\Address)
@use(Illuminate\Mail\Markdown) @use(Illuminate\Mail\Markdown)
<!-- $o=Domain::class --> <!-- $o=Domain::class -->
@ -176,7 +177,7 @@
</div> </div>
<!-- Sign up --> <!-- Sign up -->
@if ($o->can_accept_app) @if ($o->can_accept_app && ($x=Auth::user()->systems->filter(fn($item)=>$item->address && (! $item->inDomain($o))))->count())
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header"> <h3 class="accordion-header">
<span class="accordion-button collapsed" id="signup" data-bs-toggle="collapse" data-bs-target="#collapse_signup" aria-expanded="false" aria-controls="collapse_signup">Join Network</span> <span class="accordion-button collapsed" id="signup" data-bs-toggle="collapse" data-bs-target="#collapse_signup" aria-expanded="false" aria-controls="collapse_signup">Join Network</span>
@ -184,7 +185,10 @@
<div id="collapse_signup" class="accordion-collapse collapse" aria-labelledby="signup" data-bs-parent="#accordion_homepage"> <div id="collapse_signup" class="accordion-collapse collapse" aria-labelledby="signup" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<p>Your system(s) <strong class="highlight">{!! $o->userHasSystemsNotInNet(Auth::user())->pluck('name')->join('</strong>, <strong class="highlight">') !!}</strong> can join this network.</p> <p>Your system(s) <strong class="highlight">{!! $x->pluck('name')->sort()->join('</strong>, <strong class="highlight">') !!}</strong> can join this network.</p>
@if (($x=Auth::user()->systems->filter(fn($item)=>(! $item->address) && (! $item->inDomain($o))))->count())
<p><small>Your other systems(s) <strong class="highlight">{!! $x->pluck('name')->sort()->join('</strong>, <strong class="highlight">') !!}</strong> cant use this process, because they are missing network details.</small></p>
@endif
<p> <p>
If you want to join it/them to this network, make sure: If you want to join it/them to this network, make sure:
</p> </p>
@ -206,7 +210,7 @@
<li>Enjoy!</li> <li>Enjoy!</li>
</ul> </ul>
<button class="btn btn-success">Lets Do It</button> <button class="btn btn-success">Lets Do It</button> <small><-- NOT READY YET</small>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,8 +1,8 @@
<!-- $o=System::class -->
@use(App\Models\Address) @use(App\Models\Address)
@use(App\Models\Echomail) @use(App\Models\Echomail)
@use(App\Models\File) @use(App\Models\File)
@use(App\Models\Netmail) @use(App\Models\Netmail)
<!-- $o=System::class -->
@extends('layouts.app') @extends('layouts.app')
@ -212,7 +212,7 @@
</thead> </thead>
<tbody> <tbody>
@foreach ($o->sessions->sortBy('zone_id') as $oo) @foreach ($o->sessions as $oo)
<tr> <tr>
<td>{{ $oo->zone_id }}<span>@</span>{{ $oo->domain->name }}</td> <td>{{ $oo->zone_id }}<span>@</span>{{ $oo->domain->name }}</td>
<td style="text-align: center;"> <td style="text-align: center;">