Start of echomail subscribing

This commit is contained in:
Deon George 2021-08-25 22:13:49 +10:00
parent 97384ce3a0
commit 8306f4c3a3
8 changed files with 403 additions and 186 deletions

View File

@ -2,10 +2,11 @@
namespace App\Http\Controllers; namespace App\Http\Controllers;
use Carbon\Carbon;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Support\Arr; use Illuminate\Support\Arr;
use App\Models\{Address,System,SystemZone,Zone}; use App\Models\{Address,Echoarea,System,SystemZone,Zone};
use App\Rules\{FidoInteger,TwoByteInteger}; use App\Rules\{FidoInteger,TwoByteInteger};
class SystemController extends Controller class SystemController extends Controller
@ -27,7 +28,7 @@ class SystemController extends Controller
{ {
// @todo This should be admin of the zone // @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_address',TRUE); session()->flash('accordion','address');
$request->validate([ $request->validate([
'action' => 'required|in:region,host,node', 'action' => 'required|in:region,host,node',
@ -222,7 +223,7 @@ class SystemController extends Controller
{ {
// @todo This should be admin of the zone // @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_session',TRUE); session()->flash('accordion','session');
$validate = $request->validate([ $validate = $request->validate([
'zone_id' => 'required|exists:zones,id', 'zone_id' => 'required|exists:zones,id',
@ -293,7 +294,7 @@ class SystemController extends Controller
{ {
// @todo This should be admin of the zone // @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_address',TRUE); session()->flash('accordion','address');
$sid = $o->system_id; $sid = $o->system_id;
$o->active = FALSE; $o->active = FALSE;
@ -313,13 +314,46 @@ class SystemController extends Controller
public function del_session(System $o,Zone $zo) public function del_session(System $o,Zone $zo)
{ {
$this->authorize('admin',$zo); $this->authorize('admin',$zo);
session()->flash('add_session',TRUE); session()->flash('accordion','session');
$o->sessions()->detach($zo); $o->sessions()->detach($zo);
return redirect()->to(sprintf('ftn/system/addedit/%d',$o->id)); return redirect()->to(sprintf('ftn/system/addedit/%d',$o->id));
} }
/**
* Update the systems echoareas
*
* @param Request $request
* @param System $o
*/
public function echoareas(Request $request,System $o)
{
$ao = $o->addresses->filter(function($item) use ($request) { return $item->zone->domain_id == $request->domain_id; })->first();
if (($request->method() == 'POST') && $request->post()) {
session()->flash('accordion','echoarea');
// Ensure we have session details for this address.
if (! $ao->session('sespass'))
return redirect()->back()->withErrors('System doesnt belong to this network');
$ao->echoareas()->syncWithPivotValues($request->id,['subscribed'=>Carbon::now()]);
return redirect()->back()->with('success','Echoareas updated');;
}
$eo = Echoarea::active()
->where('domain_id',$request->domain_id)
->orderBy('name')
->get();
return view('system.widget.echoarea')
->with('o',$o)
->with('ao',$ao)
->with('echoareas',$eo);
}
/** /**
* Move address to another system * Move address to another system
* *
@ -331,6 +365,8 @@ class SystemController extends Controller
*/ */
public function mov_address(Request $request,System $so,Address $o) public function mov_address(Request $request,System $so,Address $o)
{ {
session()->flash('accordion','address');
// Quick check that this address belongs to this system // Quick check that this address belongs to this system
if ($so->addresses->search(function($item) use ($o) { return $item->id == $o->id; }) === FALSE) if ($so->addresses->search(function($item) use ($o) { return $item->id == $o->id; }) === FALSE)
abort(404); abort(404);
@ -378,7 +414,7 @@ class SystemController extends Controller
{ {
// @todo This should be admin of the zone // @todo This should be admin of the zone
$this->authorize('admin',$o); $this->authorize('admin',$o);
session()->flash('add_address',TRUE); session()->flash('accordion','address');
$o->active = (! $o->active); $o->active = (! $o->active);
$o->save(); $o->save();

View File

@ -109,6 +109,12 @@ class Address extends Model
->with(['zone.domain']); ->with(['zone.domain']);
} }
public function echoareas()
{
return $this->belongsToMany(Echoarea::class)
->withPivot(['subscribed']);
}
/** /**
* Who we send this systems mail to. * Who we send this systems mail to.
* *

View File

@ -72,6 +72,14 @@ class System extends Model
/* METHODS */ /* METHODS */
public function echoareas()
{
return Echoarea::select('echoareas.*')
->join('address_echoarea',['address_echoarea.echoarea_id'=>'echoareas.id'])
->join('addresses',['addresses.id'=>'address_echoarea.address_id'])
->where('addresses.system_id',$this->id);
}
/** /**
* Return the system's address in the same zone * Return the system's address in the same zone
* *

View File

@ -0,0 +1 @@
/*! checkboxes.js v1.2.2 | (c) 2013 - 2018 Rubens Mariuzzo | http://github.com/rmariuzzo/checkboxes.js/LICENSE */"use strict";function _classCallCheck(a,b){if(!(a instanceof b))throw new TypeError("Cannot call a class as a function")}var _createClass=function(){function a(a,b){for(var c=0;c<b.length;c++){var d=b[c];d.enumerable=d.enumerable||!1,d.configurable=!0,"value"in d&&(d.writable=!0),Object.defineProperty(a,d.key,d)}}return function(b,c,d){return c&&a(b.prototype,c),d&&a(b,d),b}}();!function(a){var b=function(){function b(a){_classCallCheck(this,b),this.$context=a}return _createClass(b,[{key:"check",value:function(){this.$context.find(":checkbox").filter(":not(:disabled)").filter(":visible").prop("checked",!0).trigger("change")}},{key:"uncheck",value:function(){this.$context.find(":checkbox:visible").filter(":not(:disabled)").prop("checked",!1).trigger("change")}},{key:"toggle",value:function(){this.$context.find(":checkbox:visible").filter(":not(:disabled)").each(function(b,c){var d=a(c);d.prop("checked",!d.is(":checked"))}).trigger("change")}},{key:"max",value:function(a){if(a>0){var b=this;this.$context.on("click.checkboxes.max",":checkbox",function(){b.$context.find(":checked").length===a?b.$context.find(":checkbox:not(:checked)").prop("disabled",!0):b.$context.find(":checkbox:not(:checked)").prop("disabled",!1)})}else this.$context.off("click.checkboxes.max")}},{key:"range",value:function(b){if(b){var c=this;this.$context.on("click.checkboxes.range",":checkbox",function(b){var d=a(b.target);if(b.shiftKey&&c.$last){var e=c.$context.find(":checkbox:visible"),f=e.index(c.$last),g=e.index(d),h=Math.min(f,g),i=Math.max(f,g)+1;e.slice(h,i).filter(":not(:disabled)").prop("checked",d.prop("checked")).trigger("change")}c.$last=d})}else this.$context.off("click.checkboxes.range")}}]),b}(),c=a.fn.checkboxes;a.fn.checkboxes=function(c){var d=Array.prototype.slice.call(arguments,1);return this.each(function(e,f){var g=a(f),h=g.data("checkboxes");h||g.data("checkboxes",h=new b(g)),"string"==typeof c&&h[c]&&h[c].apply(h,d)})},a.fn.checkboxes.Constructor=b,a.fn.checkboxes.noConflict=function(){return a.fn.checkboxes=c,this};var d=function(b){var c=a(b.target),d=c.attr("href"),e=a(c.data("context")||d&&d.replace(/.*(?=#[^\s]+$)/,"")),f=c.data("action");e&&f&&(c.is(":checkbox")||b.preventDefault(),e.checkboxes(f))},e=function(){a("[data-toggle^=checkboxes]").each(function(){var b=a(this),c=b.data();delete c.toggle;for(var d in c)b.checkboxes(d,c[d])})};a(document).on("click.checkboxes.data-api","[data-toggle^=checkboxes]",d),a(document).on("ready.checkboxes.data-api",e)}(window.jQuery);

View File

@ -24,79 +24,18 @@ use App\Http\Controllers\DomainController as DC;
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header" id="system" data-bs-toggle="collapse" data-bs-target="#collapse_system" aria-expanded="true" aria-controls="collapse_system">System</h3> <h3 class="accordion-header" id="system" data-bs-toggle="collapse" data-bs-target="#collapse_system" aria-expanded="true" aria-controls="collapse_system">System</h3>
<div id="collapse_system" class="accordion-collapse collapse {{ ((! session()->has('add_address')) && (! session()->has('add_session'))) ? 'show' : '' }}" aria-labelledby="system" data-bs-parent="#accordion_homepage"> <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"> <div class="accordion-body">
@include('system.form-system') @include('system.form-system')
</div> </div>
</div> </div>
</div> </div>
@if(! $o->setup)
<!-- Authentication -->
<div class="accordion-item">
<h3 class="accordion-header" id="authentication" data-bs-toggle="collapse" data-bs-target="#collapse_auth" aria-expanded="false" aria-controls="collapse_auth">System Authentication</h3>
<div id="collapse_auth" class="accordion-collapse collapse {{ session()->has('add_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
<span class="default" itemid="{{$oo->id}}"><i class="bi bi-{{ $x->count() ? 'check-square' : 'square' }}"></i></span>
@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('ftn/system/modsession',[$oo->id]) }}" title="Modify Details" class="modify"><i class="bi bi-pen-fill"></i></a>
--}}
<a href="{{ url('ftn/system/delsession',[$o->id,$oo->id]) }}" title="Delete Details" class="delete"><i class="bi bi-trash-fill"></i></a>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<p>No session details exist</p>
@endif
@include('system.form-session')
</div>
</div>
</div>
@endif
<!-- Addresses --> <!-- Addresses -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header" id="addresses" data-bs-toggle="collapse" data-bs-target="#collapse_addresses" aria-expanded="false" aria-controls="collapse_addresses">System AKAs</h3> <h3 class="accordion-header" id="addresses" data-bs-toggle="collapse" data-bs-target="#collapse_addresses" aria-expanded="false" aria-controls="collapse_addresses">System AKAs</h3>
<div id="collapse_addresses" class="accordion-collapse collapse {{ session()->has('add_address') ? 'show' : '' }}" aria-labelledby="addresses" data-bs-parent="#accordion_homepage"> <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="accordion-body">
<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> <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>
@ -196,17 +135,89 @@ use App\Http\Controllers\DomainController as DC;
@include('system.form-address') @include('system.form-address')
@else @else
This system does not currently belong to any Fido networks. You'll need to ask an admin to assign addresses. You'll need to ask an admin to assign addresses.
@endcan @endcan
</div> </div>
</div> </div>
</div> </div>
@if(! $o->setup)
<!-- Authentication -->
<div class="accordion-item">
<h3 class="accordion-header" id="authentication" data-bs-toggle="collapse" data-bs-target="#collapse_auth" aria-expanded="false" aria-controls="collapse_auth">System Authentication</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
<span class="default" itemid="{{$oo->id}}"><i class="bi bi-{{ $x->count() ? 'check-square' : 'square' }}"></i></span>
@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('ftn/system/modsession',[$oo->id]) }}" title="Modify Details" class="modify"><i class="bi bi-pen-fill"></i></a>
--}}
<a href="{{ url('ftn/system/delsession',[$o->id,$oo->id]) }}" title="Delete Details" class="delete"><i class="bi bi-trash-fill"></i></a>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<p>No session details exist</p>
@endif
@include('system.form-session')
</div>
</div>
</div>
<!-- Echoareas -->
<div class="accordion-item">
<h3 class="accordion-header" id="echoarea" data-bs-toggle="collapse" data-bs-target="#collapse_echoarea" aria-expanded="false" aria-controls="collapse_echoarea">Echo Area Subscription</h3>
<div id="collapse_echoarea" class="accordion-collapse collapse {{ ($flash=='echoarea') ? 'show' : '' }}" aria-labelledby="echoarea" data-bs-parent="#accordion_homepage">
<div class="accordion-body">
<p>This system can subscribe to the following echoareas:</p>
@include('system.form-echoarea')
</div>
</div>
</div>
<!-- Routing --> <!-- Routing -->
<div class="accordion-item"> <div class="accordion-item">
<h3 class="accordion-header" id="routing" data-bs-toggle="collapse" data-bs-target="#collapse_routing" aria-expanded="false" aria-controls="collapse_routing">Mail Routing</h3> <h3 class="accordion-header" id="routing" data-bs-toggle="collapse" data-bs-target="#collapse_routing" aria-expanded="false" aria-controls="collapse_routing">Mail Routing</h3>
<div id="collapse_routing" class="accordion-collapse collapse {{ (session()->has('add_address')) ? 'show' : '' }}" aria-labelledby="addresses" data-bs-parent="#accordion_homepage"> <div id="collapse_routing" class="accordion-collapse collapse {{ ($flash=='routing') ? 'show' : '' }}" aria-labelledby="addresses" data-bs-parent="#accordion_homepage">
<div class="accordion-body"> <div class="accordion-body">
<div class="row"> <div class="row">
<!-- Zone mail sent to --> <!-- Zone mail sent to -->
@ -277,6 +288,7 @@ use App\Http\Controllers\DomainController as DC;
</div> </div>
</div> </div>
</div> </div>
@endif
@else @else
@include('system.form-system') @include('system.form-system')
@endif @endif

View File

@ -0,0 +1,108 @@
@if(($x=\App\Models\Domain::active()
->select('domains.*')
->join('zones',['zones.domain_id'=>'domains.id'])
->whereIn('zone_id',$o->sessions->pluck('zone_id'))
->get())->count())
<form class="row g-0 needs-validation" method="post" action="{{ url('ftn/system/echoarea',$o->id) }}" novalidate>
@csrf
<div class="row pt-0">
<div class="col-12">
<div class="greyframe titledbox shadow0xb0">
<div class="row">
<!-- Select Domain -->
<div class="col-3">
<label for="domain_id" class="form-label">Network</label>
<div class="input-group has-validation">
<span class="input-group-text"><i class="bi bi-hash"></i></span>
<select class="form-select @error('domain_id') is-invalid @enderror" id="domain_id" name="domain_id" required>
<option></option>
@foreach($x as $do)
<option value="{{ $do->id }}" @if(old('domain_id') == $do->id)selected @endif>{{ $do->id }} <small>({{ $do->name }})</small></option>
@endforeach
</select>
<span class="invalid-feedback" role="alert">
@error('domain_id')
{{ $message }}
@enderror
</span>
</div>
</div>
<div class="offset-2 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>
<div class="row">
<div class="col-12 d-none" id="echoarea-select"></div>
</div>
</div>
</div>
</div>
</form>
@endif
@section('page-scripts')
<script type="text/javascript" src="{{ asset('plugin/checkboxes/jquery.checkboxes-1.2.2.min.js') }}"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#domain_id').on('change',function() {
if (! $(this).val()) {
$('#echoarea-summary').removeClass('d-none');
$('#echoarea-select').addClass('d-none');
return;
}
if ($('#echoarea-select').hasClass('d-none')) {
$('#echoarea-select').removeClass('d-none');
$('#echoarea-summary').addClass('d-none');
}
var item = this;
icon = $(item).parent().find('i');
$.ajax({
type: 'GET',
data: {domain_id: $(item).val()},
beforeSend: function() {
icon.addClass('spinner-grow spinner-grow-sm');
},
success: function(data) {
icon.removeClass('spinner-grow spinner-grow-sm');
$('#echoarea-select').empty().append(data);
$('#echoareas').checkboxes('range',true);
//eval(document.getElementById('echoarea-javascript').innerHTML);
},
error: function(e) {
icon.removeClass('spinner-grow spinner-grow-sm');
if (e.status != 412)
alert('That didnt work? Please try again....');
},
url: '{{ url('ftn/system/echoarea',[$o->id]) }}',
cache: false
})
});
})
</script>
@append

View File

@ -0,0 +1,44 @@
<div class="row">
<div class="col-12">
<table class="table monotable" id="echoareas">
<thead>
<tr>
<th>Subscribed</th>
<th>Echoarea</th>
<th>Description</th>
</tr>
</thead>
<tbody>
@foreach ($echoareas as $oo)
<tr>
<td><input type="checkbox" name="id[]" value="{{ $oo->id }}" @if($ao->echoareas->search(function($item) use ($oo) { return $item->id == $oo->id; }) !== FALSE)checked @endif></td>
<td>{{ $oo->name }}</td>
<td>{{ $oo->description }}</td>
</tr>
@endforeach
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-2">
<a href="{{ url('ftn/system') }}" class="btn btn-danger">Cancel</a>
</div>
<span class="col-6 mt-auto mx-auto text-center align-bottom">
@if($errors->count())
<span class="btn btn-sm btn-danger" role="alert">
There were errors with the submission.
@dump($errors)
</span>
@endif
</span>
@can('admin',$o)
<div class="col-2">
<button type="submit" name="submit" class="btn btn-success float-end">Add</button>
</div>
@endcan
</div>

View File

@ -65,6 +65,8 @@ Route::middleware(['verified','activeuser'])->group(function () {
Route::get('ftn/system/delsession/{o}/{zo}',[SystemController::class,'del_session']) Route::get('ftn/system/delsession/{o}/{zo}',[SystemController::class,'del_session'])
->where('o','[0-9]+') ->where('o','[0-9]+')
->where('zo','[0-9]+'); ->where('zo','[0-9]+');
Route::match(['get','post'],'ftn/system/echoarea/{o}',[SystemController::class,'echoareas'])
->where('o','[0-9]+');
Route::match(['get','post'],'ftn/system/movaddress/{so}/{o}',[SystemController::class,'mov_address']) Route::match(['get','post'],'ftn/system/movaddress/{so}/{o}',[SystemController::class,'mov_address'])
->where('so','[0-9]+') ->where('so','[0-9]+')
->where('o','[0-9]+'); ->where('o','[0-9]+');