diff --git a/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php b/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php index 22f7a618..57f72cb5 100644 --- a/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php +++ b/app/Database/migrations/2017_06_28_195426_create_pirep_tables.php @@ -84,6 +84,7 @@ class CreatePirepTables extends Migration Schema::create('pirep_fields', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name', 50); + $table->string('slug', 50)->nullable(); $table->boolean('required')->default(false); }); diff --git a/app/Database/seeds/sample.yml b/app/Database/seeds/sample.yml index 3bacfc32..d4984898 100644 --- a/app/Database/seeds/sample.yml +++ b/app/Database/seeds/sample.yml @@ -405,7 +405,12 @@ pireps: pirep_fields: - id: 1 + name: departure gate + slug: departure_gate + required: 1 + - id: 2 name: arrival gate + slug: arrival_gate required: 0 pirep_field_values: diff --git a/app/Http/Controllers/Admin/PirepFieldController.php b/app/Http/Controllers/Admin/PirepFieldController.php index 75f7a1a0..0e388997 100644 --- a/app/Http/Controllers/Admin/PirepFieldController.php +++ b/app/Http/Controllers/Admin/PirepFieldController.php @@ -22,9 +22,9 @@ class PirepFieldController extends BaseController /** * Display a listing of the PirepField. - * * @param Request $request * @return Response + * @throws \Prettus\Repository\Exceptions\RepositoryException */ public function index(Request $request) { @@ -38,7 +38,6 @@ class PirepFieldController extends BaseController /** * Show the form for creating a new PirepField. - * * @return Response */ public function create() @@ -48,9 +47,7 @@ class PirepFieldController extends BaseController /** * Store a newly created PirepField in storage. - * * @param CreatePirepFieldRequest $request - * * @return Response * @throws \Prettus\Validator\Exceptions\ValidatorException */ @@ -67,9 +64,7 @@ class PirepFieldController extends BaseController /** * Display the specified PirepField. - * * @param int $id - * * @return Response */ public function show($id) @@ -88,9 +83,7 @@ class PirepFieldController extends BaseController /** * Show the form for editing the specified PirepField. - * * @param int $id - * * @return Response */ public function edit($id) @@ -130,9 +123,7 @@ class PirepFieldController extends BaseController /** * Remove the specified PirepField from storage. - * * @param int $id - * * @return Response */ public function destroy($id) diff --git a/app/Http/Controllers/Api/PirepController.php b/app/Http/Controllers/Api/PirepController.php index 4f369fbf..48e8e97f 100644 --- a/app/Http/Controllers/Api/PirepController.php +++ b/app/Http/Controllers/Api/PirepController.php @@ -2,7 +2,6 @@ namespace App\Http\Controllers\Api; -use App\Rules\Minutes; use Log; use Auth; use Illuminate\Database\Eloquent\ModelNotFoundException; @@ -78,8 +77,8 @@ class PirepController extends RestController 'flight_number' => 'required', 'route_code' => 'nullable', 'route_leg' => 'nullable', - 'flight_time' => ['nullable', new Minutes], - 'planned_flight_time' => ['nullable', new Minutes], + 'flight_time' => ['nullable', 'integer'], + 'planned_flight_time' => ['nullable', 'integer'], 'level' => 'required|integer', 'route' => 'nullable', 'notes' => 'nullable', @@ -133,7 +132,7 @@ class PirepController extends RestController $file_rules = [ # actual flight time is required - 'flight_time' => ['required', new Minutes], + 'flight_time' => ['required', 'integer'], 'flight_number' => 'nullable', 'dpt_airport_id' => 'nullable', 'arr_airport_id' => 'nullable', @@ -142,7 +141,7 @@ class PirepController extends RestController 'flight_id' => 'nullable', 'route_code' => 'nullable', 'route_leg' => 'nullable', - 'planned_flight_time' => ['nullable', new Minutes], + 'planned_flight_time' => ['nullable', 'integer'], 'level' => 'nullable', 'route' => 'nullable', 'notes' => 'nullable', diff --git a/app/Http/Controllers/Frontend/PirepController.php b/app/Http/Controllers/Frontend/PirepController.php index 10a775c8..8b9f3b2d 100644 --- a/app/Http/Controllers/Frontend/PirepController.php +++ b/app/Http/Controllers/Frontend/PirepController.php @@ -2,7 +2,9 @@ namespace App\Http\Controllers\Frontend; +use Log; use App\Facades\Utils; +use App\Http\Requests\CreatePirepRequest; use Illuminate\Support\Facades\Auth; use Illuminate\Http\Request; @@ -61,11 +63,15 @@ class PirepController extends Controller * @param null $user * @return array */ - public function aircraftList($user=null) + public function aircraftList($user=null, $add_blank=false) { $aircraft = []; $subfleets = $this->userSvc->getAllowableSubfleets($user); + if($add_blank) { + $aircraft[''] = ''; + } + foreach ($subfleets as $subfleet) { $tmp = []; foreach ($subfleet->aircraft as $ac) { @@ -107,49 +113,56 @@ class PirepController extends Controller $user = Auth::user(); return $this->view('pireps.create', [ - 'aircraft' => $this->aircraftList($user), - 'airports' => $this->airportRepo->selectBoxList(), - 'airlines' => $this->airlineRepo->selectBoxList(), - 'pirepfields' => $this->pirepFieldRepo->all(), - 'fieldvalues' => [], + 'airlines' => $this->airlineRepo->selectBoxList(true), + 'aircraft' => $this->aircraftList($user, true), + 'airports' => $this->airportRepo->selectBoxList(true), + 'pirep_fields' => $this->pirepFieldRepo->all(), + 'field_values' => [], ]); } - public function store(Request $request) + /** + * + * @param CreatePirepRequest $request + * @return \Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector + */ + public function store(CreatePirepRequest $request) { - $pirep_fields = $request->all(); - // Create the main PIREP - $pirep = new Pirep($pirep_fields); + $pirep = new Pirep($request->all()); + $pirep->user_id = Auth::user()->id; + + # Make sure this isn't a duplicate + $dupe_pirep = $this->pirepSvc->findDuplicate($pirep); + if ($dupe_pirep !== false) { + flash()->error('This PIREP has already been filed.'); + return redirect(route('frontend.pireps.create'))->withInput(); + } // Any special fields - $pirep->pilot()->associate(Auth::user()); $pirep->flight_time = ((int) Utils::hoursToMinutes($request['hours'])) + ((int) $request['minutes']); // The custom fields from the form $custom_fields = []; - foreach($pirep_fields as $field_name => $field_val) - { - if (strpos($field_name, 'field_') === false) { + $pirep_fields = $this->pirepFieldRepo->all(); + foreach ($pirep_fields as $field) { + if(!$request->filled($field->slug)) { continue; } - $field_id = explode('field_', $field_name)[1]; - $cfield = PirepField::find($field_id); - $custom_fields[] = [ - 'name' => $cfield->name, - 'value' => $field_val, + 'name' => $field->name, + 'value' => $request->input($field->slug), 'source' => PirepSource::MANUAL ]; } + Log::info('PIREP Custom Fields', $custom_fields); $pirep = $this->pirepSvc->create($pirep, $custom_fields); $this->pirepSvc->saveRoute($pirep); - //Flash::success('PIREP submitted successfully!'); - return redirect(route('frontend.pireps.index')); + return redirect(route('frontend.pireps.show', ['id' => $pirep->id])); } public function show($id) diff --git a/app/Http/Requests/CreatePirepRequest.php b/app/Http/Requests/CreatePirepRequest.php index 6f39d0aa..d91705c0 100644 --- a/app/Http/Requests/CreatePirepRequest.php +++ b/app/Http/Requests/CreatePirepRequest.php @@ -2,13 +2,14 @@ namespace App\Http\Requests; -use App\Models\Pirep; +use Log; use Illuminate\Foundation\Http\FormRequest; +use App\Models\Pirep; +use App\Repositories\PirepFieldRepository; class CreatePirepRequest extends FormRequest { - /** * Determine if the user is authorized to make this request. * @@ -26,6 +27,21 @@ class CreatePirepRequest extends FormRequest */ public function rules() { - return Pirep::$rules; + $field_rules = Pirep::$rules; + + $field_rules['hours'] = 'nullable|integer'; + $field_rules['minutes'] = 'required|integer'; + + # Add the validation rules for the custom fields + $pirepFieldRepo = app(PirepFieldRepository::class); + + $custom_fields = $pirepFieldRepo->all(); + foreach ($custom_fields as $field) { + $field_rules[$field->slug] = $field->required ? 'required' : 'nullable'; + } + + Log::debug('createPirepFormRequest::rules', $field_rules); + + return $field_rules; } } diff --git a/app/Models/Pirep.php b/app/Models/Pirep.php index ee5bbb99..a1d20fd4 100644 --- a/app/Models/Pirep.php +++ b/app/Models/Pirep.php @@ -57,11 +57,13 @@ class Pirep extends BaseModel ]; public static $rules = [ - 'flight_number' => 'required', - 'dpt_airport_id' => 'required', - 'arr_airport_id' => 'required', - 'notes' => 'nullable', - 'route' => 'nullable', + 'airline_id' => 'required|exists:airlines,id', + 'aircraft_id' => 'required|exists:aircraft,id', + 'flight_number' => 'required', + 'dpt_airport_id' => 'required', + 'arr_airport_id' => 'required', + 'notes' => 'nullable', + 'route' => 'nullable', ]; /** @@ -71,12 +73,14 @@ class Pirep extends BaseModel public function getIdentAttribute() { $flight_id = $this->airline->code; - if(!empty($this->flight_number)) { - $flight_id .= $this->flight_number; - } else { - if ($this->flight_id) { - $flight_id .= $this->flight->flight_number; - } + $flight_id .= $this->flight_number; + + if(filled($this->route_code)) { + $flight_id .= '/C'.$this->route_code; + } + + if(filled($this->route_leg)) { + $flight_id .= '/L'.$this->route_leg; } return $flight_id; diff --git a/app/Models/PirepField.php b/app/Models/PirepField.php index 24cbc877..138f9de9 100644 --- a/app/Models/PirepField.php +++ b/app/Models/PirepField.php @@ -14,6 +14,7 @@ class PirepField extends BaseModel public $fillable = [ 'name', + 'slug', 'required', ]; @@ -24,4 +25,30 @@ class PirepField extends BaseModel public static $rules = [ 'name' => 'required', ]; + + /** + * Create/update the field slug + */ + protected static function boot() + { + parent::boot(); + + /** + * On creation + */ + static::creating(function (PirepField $model) { + if (!empty($model->slug)) { + $model->slug = str_slug($model->name); + } + }); + + /** + * When updating + */ + static::updating(function(PirepField $model) { + if (!empty($model->slug)) { + $model->slug = str_slug($model->name); + } + }); + } } diff --git a/app/Repositories/AirlineRepository.php b/app/Repositories/AirlineRepository.php index f073287b..99740db7 100644 --- a/app/Repositories/AirlineRepository.php +++ b/app/Repositories/AirlineRepository.php @@ -31,7 +31,7 @@ class AirlineRepository extends BaseRepository implements CacheableInterface $items = $this->all(); if($add_blank) { - $retval[] = ''; + $retval[''] = ''; } foreach ($items as $i) { diff --git a/app/Rules/Minutes.php b/app/Rules/Minutes.php deleted file mode 100644 index 12585bb5..00000000 --- a/app/Rules/Minutes.php +++ /dev/null @@ -1,25 +0,0 @@ - $pirep->flight_number, ]; - if(!empty($pirep->route_code)) { + if(filled($pirep->route_code)) { $where['route_code'] = $pirep->route_code; } - if(!empty($pirep->route_leg)) { + if(filled($pirep->route_leg)) { $where['route_leg'] = $pirep->route_leg; } diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index 28c6677f..bfde114b 100755 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -2,16 +2,9 @@ return [ - /* - |-------------------------------------------------------------------------- - | Validation Language Lines - |-------------------------------------------------------------------------- - | - | The following language lines contain the default error messages used by - | the validator class. Some of these rules have multiple versions such - | as the size rules. Feel free to tweak each of these messages here. - | - */ + /** + * Validation Language Lines + */ 'accepted' => 'The :attribute must be accepted.', 'active_url' => 'The :attribute is not a valid URL.', @@ -39,7 +32,7 @@ return [ 'email' => 'The :attribute must be a valid email address.', 'exists' => 'The selected :attribute is invalid.', 'file' => 'The :attribute must be a file.', - 'filled' => 'The :attribute field is required.', + 'filled' => 'The ":attribute" is required.', 'image' => 'The :attribute must be an image.', 'in' => 'The selected :attribute is invalid.', 'in_array' => 'The :attribute field does not exist in :other.', @@ -63,7 +56,7 @@ return [ 'numeric' => 'The :attribute must be a number.', 'present' => 'The :attribute field must be present.', 'regex' => 'The :attribute format is invalid.', - 'required' => 'The :attribute field is required.', + 'required' => 'The ":attribute" field is required.', 'required_if' => 'The :attribute field is required when :other is :value.', 'required_unless' => 'The :attribute field is required unless :other is in :values.', 'required_with' => 'The :attribute field is required when :values is present.', @@ -82,33 +75,38 @@ return [ 'unique' => 'The :attribute has already been taken.', 'url' => 'The :attribute format is invalid.', - /* - |-------------------------------------------------------------------------- - | Custom Validation Language Lines - |-------------------------------------------------------------------------- - | - | Here you may specify custom validation messages for attributes using the - | convention "attribute.rule" to name the lines. This makes it quick to - | specify a specific custom language line for a given attribute rule. - | - */ + /** + * Custom Validation Language Lines + */ 'custom' => [ - 'attribute-name' => [ - 'rule-name' => 'custom-message', + 'airline_id' => [ + 'required' => 'An airline is required', + 'exists' => 'The airline doesn\'t exist', + ], + 'aircraft_id' => [ + 'required' => 'An aircraft is required', + 'exists' => 'The aircraft doesn\'t exist', + ], + 'arr_airport_id' => [ + 'required' => 'An arrival airport is required', + ], + 'dpt_airport_id' => [ + 'required' => 'A departure airport is required', + ], + 'flight_time' => [ + 'required' => 'Flight time, in minutes, is required', + 'integer' => 'Flight time, in minutes, is required', + ], + 'planned_flight_time' => [ + 'required' => 'Flight time, in minutes, is required', + 'integer' => 'Flight time, in minutes, is required', ], ], - /* - |-------------------------------------------------------------------------- - | Custom Validation Attributes - |-------------------------------------------------------------------------- - | - | The following language lines are used to swap attribute place-holders - | with something more reader friendly such as E-Mail Address instead - | of "email". This simply helps us make messages a little cleaner. - | - */ + /** + * Custom Validation Attributes + */ 'attributes' => [], diff --git a/resources/views/admin/pirepfields/table.blade.php b/resources/views/admin/pirepfields/table.blade.php index 201989ad..aa8c25ab 100644 --- a/resources/views/admin/pirepfields/table.blade.php +++ b/resources/views/admin/pirepfields/table.blade.php @@ -1,4 +1,12 @@
+ +
+

+    + PIREP fields are only shown for manual PIREPs. +

+
+ diff --git a/resources/views/admin/pireps/field_values.blade.php b/resources/views/admin/pireps/field_values.blade.php index e73e2430..2e1a25d4 100644 --- a/resources/views/admin/pireps/field_values.blade.php +++ b/resources/views/admin/pireps/field_values.blade.php @@ -13,7 +13,7 @@ - + @@ -23,6 +24,9 @@ {!! Form::text('route_code', null, ['placeholder' => 'Code (optional)', 'class' => 'form-control']) !!} {!! Form::text('route_leg', null, ['placeholder' => 'Leg (optional)', 'class' => 'form-control']) !!} +

{{ $errors->first('flight_number') }}

+

{{ $errors->first('route_code') }}

+

{{ $errors->first('route_leg') }}

@@ -32,6 +36,7 @@
{!! Form::select('aircraft_id', $aircraft, null, ['class' => 'custom-select select2']) !!}
+

{{ $errors->first('aircraft_id') }}

@@ -41,6 +46,7 @@
{!! Form::select('dpt_airport_id', $airports, null, ['class' => 'custom-select select2']) !!}
+

{{ $errors->first('dpt_airport_id') }}

@@ -50,6 +56,7 @@
{!! Form::select('arr_airport_id', $airports, null, ['class' => 'custom-select select2']) !!}
+

{{ $errors->first('arr_airport_id') }}

@@ -60,46 +67,50 @@ {!! Form::number('hours', null, ['class' => 'form-control', 'placeholder' => 'hours']) !!} {!! Form::number('minutes', null, ['class' => 'form-control', 'placeholder' => 'minutes']) !!} +

{{ $errors->first('hours') }}

+

{{ $errors->first('minutes') }}

+ {{-- + Write out the custom fields, and label if they're required + --}} + @foreach($pirep_fields as $field) + + + + + @endforeach + - {{-- - Write out the custom fields, and label if they're required - --}} - @foreach($pirepfields as $field) - - - - - @endforeach - diff --git a/resources/views/layouts/default/pireps/pirep_card.blade.php b/resources/views/layouts/default/pireps/pirep_card.blade.php index 71cd8db3..c3d5c24c 100644 --- a/resources/views/layouts/default/pireps/pirep_card.blade.php +++ b/resources/views/layouts/default/pireps/pirep_card.blade.php @@ -4,12 +4,7 @@
- {!! $pirep->airline->code !!} - @if($pirep->flight_id) - {!! $pirep->flight->flight_number !!} - @else - {!! $pirep->flight_number !!} - @endif + {!! $pirep->ident !!}
diff --git a/resources/views/layouts/default/pireps/show.blade.php b/resources/views/layouts/default/pireps/show.blade.php index 3097dcc2..c29807ab 100644 --- a/resources/views/layouts/default/pireps/show.blade.php +++ b/resources/views/layouts/default/pireps/show.blade.php @@ -77,16 +77,14 @@

fields

Name {!! $field->value !!} {!! $field->source !!}{!! PirepSource::label($field->source) !!} {!! Form::open(['url' => '/admin/pireps/'.$pirep->id.'/fields', 'method' => 'delete', diff --git a/resources/views/admin/pireps/pirep_card.blade.php b/resources/views/admin/pireps/pirep_card.blade.php index 1a5beb4b..40bf3b1e 100644 --- a/resources/views/admin/pireps/pirep_card.blade.php +++ b/resources/views/admin/pireps/pirep_card.blade.php @@ -5,7 +5,7 @@
+ href="{!! route('admin.pireps.edit', [$pirep->id]) !!}"> {!! $pirep->ident !!}
diff --git a/resources/views/layouts/default/pireps/fields.blade.php b/resources/views/layouts/default/pireps/fields.blade.php index dba49541..3d8a9438 100644 --- a/resources/views/layouts/default/pireps/fields.blade.php +++ b/resources/views/layouts/default/pireps/fields.blade.php @@ -12,6 +12,7 @@
{!! Form::select('airline_id', $airlines, null, ['class' => 'custom-select select2']) !!}
+

{{ $errors->first('airline_id') }}

+ {!! $field->name !!} + @if($field->required === true) + * + @endif + +
+ {!! Form::text($field->slug, null, [ + 'class' => 'form-control' + ]) !!} +
+

{{ $errors->first($field->slug) }}

+
Route
{!! Form::textarea('route', null, ['class' => 'form-control', 'placeholder' => 'Route']) !!}
+

{{ $errors->first('route') }}

- {!! $field->name !!} - required - -
- - {!! Form::text('field_'.$field->id, null, [ - 'class' => 'form-control' - ]) !!} -
-

Notes

{!! Form::textarea('notes', null, ['class' => 'form-control', 'placeholder' => 'Notes']) !!}
+

{{ $errors->first('notes') }}

- - - + + @foreach($pirep->fields as $field) - @endforeach diff --git a/tests/AcarsTest.php b/tests/AcarsTest.php index 5ae3c017..2a04ef4c 100644 --- a/tests/AcarsTest.php +++ b/tests/AcarsTest.php @@ -55,7 +55,7 @@ class AcarsTest extends TestCase } /** - * Post a PIREP into a PREFILE state and post ACARS + * Test some prefile error conditions */ public function testPrefileErrors() { @@ -65,6 +65,9 @@ class AcarsTest extends TestCase $airline = factory(App\Models\Airline::class)->create(); $aircraft = factory(App\Models\Aircraft::class)->create(); + /** + * INVALID AIRLINE_ID FIELD + */ $uri = '/api/pireps/prefile'; $pirep = [ '_airline_id' => $airline->id,
NameValueSourceNameValue
{!! $field->name !!} {!! $field->value !!}{!! $field->source !!}