Compare commits

...

27 Commits

Author SHA1 Message Date
snyk-bot
af9cba4a5f fix: package.json & package-lock.json to reduce vulnerabilities
The following vulnerabilities are fixed with an upgrade:
- https://snyk.io/vuln/SNYK-JS-ANSIHTML-1296849
2022-03-13 18:17:55 +00:00
B.Fatih KOZ
00bf18c225 Fix Cron Deleting Paused Pireps (#1434) 2022-03-07 09:55:30 -05:00
Toni Vicente
b81dd97822 Changed es directory es by es-es (#1421)
This structure will allow for other variants derived from the Spanish of Spain.

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2022-02-28 13:34:01 -05:00
B.Fatih KOZ
7a40a9d128 Add DRAFT state in conditional check (#1422)
Add DRAFT state in conditional check
2022-02-28 09:52:57 -05:00
B.Fatih KOZ
9d368e8efa Allow bids on same flight by multiple users
Dash out unnecessary check, let multiple users to bid on same flight according to settings.
2022-02-25 14:40:53 -05:00
Toni Vicente
219a7cf6f9 fixed incorrect translation & Make TOC only readeable (#1408)
* fixed incorrect translation

Bloque de combustible -> Combustible en calzos

* Make TOC only redeable

make toc only readable for the user
2022-02-22 09:35:21 -05:00
Nabeel Shahzad
54bc5ccb30 Update example cron path to point to bin/cron 2022-02-21 10:36:54 -05:00
Nabeel Shahzad
648659aea5 Check if PIREP doesn't exist before cancelling 2022-02-16 19:13:47 -05:00
B.Fatih KOZ
08f82f8a2e Admin and Discord Notification Improvements (#1407)
* Backend changes

Sorting for : Airlines, Subfleets, Type Ratings and exported Flights

Blade : Added WYSIWYG editor to flight remarks/notes field

Notifications :

Mails > Added enabled/disabled settings for mails. Discord > Dashed out PirepPreFiled, re-enabled PirepStatusChanged with reduced messages

* Update PirepStatusChanged.php

* Update NotificationEventsHandler.php

* in_array fix

* Fix Discord Notifications

* Discord Notifications

Removed the pirep url from message as it is mostly private at phpvms side.

Also removed the Flight Ident from fields 'cause it is being used in the title.

Added the user avatar as thumbnail, and pirep filed message uses the airline logo as the main image.

Even though the outgoing pirep status messages are reduced, it is still possible to enable/disable them from admin settings.

Pirep Filed is always being sent (if the webhook is defined)

* StyleFix
2022-02-14 16:24:22 -05:00
Nabeel Shahzad
60cec870f6 Add aircraft ident to API response 2022-02-14 12:53:12 -05:00
Nabeel S
78fd8367a1 Add separate cron runner that doesn't use proc_open (#1405)
* Add alternative to using the artisan schedule runner

* StyleCI fixes

* Add additional cron time periods

* Style fixes

* Typo

* Update the web cron to use the new system

* Write out JSON for which tasks were run

* Rename cron.php to just cron
2022-02-11 16:24:06 -05:00
B.Fatih KOZ
607ea6f5e5 Add Notes to Users (#1406)
* Fix migration

Add Notes

* Migration to add mediumtext field
* Model update
* Admin blade update

* Hide notes by default

* Fix fields layout
2022-02-11 15:58:16 -05:00
Nabeel Shahzad
9e080d544a Fix Discord webhook URLs 2022-02-09 13:20:57 -05:00
Nabeel S
cb38f2ad90 Refactor broadcast notifications (#1402)
* Refactor broadcast notifications

* StyleCI fixes

* Fix the planned_distance accidental changes
2022-02-08 15:07:02 -05:00
Nabeel S
6cfbd91328 Update package versions (#1399)
* Update dependencies

* Symfony components downgrade

* Restrict symfony versions with meta package

* Downgrade valuestore

* Symfony versions

* More downgrades

* Package versions

* Package versions
2022-02-08 11:12:39 -05:00
B.Fatih KOZ
9253d39848 Custom Code for Pilot IDents (#1398)
* Custom Code for Pilot IDents

Adds a new setting to customize the ident or to use a fixed icao code in a multi airline environment.

If settings is null/empty, airline icao will be used as like before.

* StyleFix
2022-02-07 17:47:57 -05:00
arthurpar06
737b2f137f Fix French translations (#1394)
Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2022-02-07 16:15:25 -05:00
B.Fatih KOZ
c518175244 Update User Model (#1396)
Current GDPR compliant Private Name attribute is not compatible with multi byte strings, and when encountered it fails and returns an empty string for the name_private attribute.

`substr($last_name, 0, 1)` or just `$last_name[0]` is not multi byte compatible, therefore only solution is to use `mb_substr`.

It also supports encoding definitions like `mb_substr($last_name, 0, 1, 'UTF-8')`

Co-authored-by: Nabeel S <nabeelio@users.noreply.github.com>
2022-02-07 16:10:58 -05:00
B.Fatih KOZ
08624042f2 Make name and e-mail based searches with like for easier administration. (#1397)
* Update UserRepository.php

Make `name` and `e-mail` based searches with `like` for easier administration and search.

* Update search.blade.php

Remove old dashed out code

* Update index.blade.php

Add proper state selections
2022-02-07 16:02:17 -05:00
B.Fatih KOZ
94735103aa French Translation (#1392)
Author: Jacques M.
( Jbaltazar67 from phpVMS Forum/Discord )
2022-02-04 15:39:10 -05:00
Nabeel Shahzad
e4782c40f3 Fix tests 2022-02-04 15:03:05 -05:00
Nabeel Shahzad
670cb5d811 Check for bid existing or not 2022-02-04 14:21:59 -05:00
Nabeel Shahzad
88ffee16be Remove PII from debug info for user 2022-02-04 14:17:07 -05:00
Nabeel Shahzad
cc5a6db427 Nullable return type 2022-02-04 14:15:42 -05:00
Nabeel Shahzad
74a1b4d753 Add subfleet data when single bid is retrieved 2022-02-04 14:13:40 -05:00
Nabeel S
8a94d8db7b Add LGA flight 2022-01-29 14:49:38 -05:00
Nabeel S
c2cc067329 ICAO typo for sample data 2022-01-28 16:35:24 -05:00
110 changed files with 2821 additions and 1113 deletions

View File

@@ -15,7 +15,10 @@ declare -a remove_files=(
.idea
.travis
docker
node_modules
vendor/willdurand/geocoder/tests
_ide_helper.php
.env
.dockerignore
.dpl
.editorconfig
@@ -38,9 +41,8 @@ declare -a remove_files=(
phpvms.iml
Procfile
phpstan.neon
node_modules
symfony.lock
composer.phar
vendor/willdurand/geocoder/tests
)
for file in "${remove_files[@]}"; do

View File

@@ -22,7 +22,11 @@ class ProcessQueue extends Command
'--stop-when-empty' => null,
]);
Log::info(Artisan::output());
$jobOutput = trim(Artisan::output());
if (!empty($jobOutput)) {
Log::info($jobOutput);
}
///** @var App\Support\WorkCommand $queueWorker */
//$queueWorker = new App\Support\WorkCommand(app('queue.worker'), app('cache.store'));

90
app/Console/Cron.php Normal file
View File

@@ -0,0 +1,90 @@
<?php
/**
* This runs any of the cron tasks that are set to run according to the Laravel schedule
*/
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Contracts\Command;
use Illuminate\Console\Scheduling\Schedule;
class Cron
{
/** @var Schedule */
private $scheduler;
/**
* @var string[] The cron tasks which get called/run
*/
private $cronTasks = [
JobQueue::class,
FiveMinute::class,
FifteenMinute::class,
ThirtyMinute::class,
Hourly::class,
Nightly::class,
Weekly::class,
Monthly::class,
];
/**
* @var array Stores the instantiated cron tasks
*/
private $cronRunners = [];
/**
* @param Schedule $scheduler
*/
public function __construct(Schedule $scheduler)
{
$this->scheduler = $scheduler;
foreach ($this->cronTasks as $task) {
/** @var Command $cronTask */
$cronTask = app($task);
$signature = $cronTask->getSignature();
if (empty($signature)) {
continue;
}
$this->cronRunners[$signature] = $cronTask;
}
}
/**
* Try to figure out which commands are supposed to run right now
*
* @return array string of tasks that were run
*/
public function run(): array
{
$events = $this->scheduler->dueEvents(app());
if (empty($events)) {
return [];
}
$run = [];
/** @var \Illuminate\Console\Scheduling\Event $event */
foreach ($events as $event) {
foreach ($this->cronRunners as $signature => $task) {
if (!str_contains($event->command, $signature)) {
continue;
}
$task->callEvent();
$run[] = $signature;
}
}
return $run;
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFifteenMinute;
/**
* The actual cron tasks are in app/Cron
*/
class FifteenMinute extends CronCommand
{
protected $signature = 'cron:fifteen';
protected $description = 'Run the 15 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFifteenMinute());
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronFiveMinute;
/**
* This just calls the CronNightly event, so all of the
* listeners, etc can just be called to run those tasks
*
* The actual cron tasks are in app/Cron
*/
class FiveMinute extends CronCommand
{
protected $signature = 'cron:five';
protected $description = 'Run the 5 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronFiveMinute());
}
}

View File

@@ -2,14 +2,14 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronHourly;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class Hourly extends Command
class Hourly extends CronCommand
{
protected $signature = 'cron:hourly';
protected $description = 'Run the hourly cron tasks';
@@ -17,7 +17,11 @@ class Hourly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronHourly());
}
}

View File

@@ -2,14 +2,14 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use Illuminate\Support\Facades\Artisan;
/**
* This just calls the CronHourly event, so all of the
* listeners, etc can just be called to run those tasks
*/
class JobQueue extends Command
class JobQueue extends CronCommand
{
protected $signature = 'cron:queue';
protected $description = 'Run the cron queue tasks';
@@ -17,9 +17,16 @@ class JobQueue extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
Artisan::call('queue:cron');
$this->callEvent();
$this->info(Artisan::output());
$queueOutput = trim(Artisan::output());
if (!empty($queueOutput)) {
$this->info($queueOutput);
}
}
public function callEvent()
{
Artisan::call('queue:cron');
}
}

View File

@@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronMonthly;
/**
@@ -11,7 +11,7 @@ use App\Events\CronMonthly;
*
* The actual cron tasks are in app/Cron
*/
class Monthly extends Command
class Monthly extends CronCommand
{
protected $signature = 'cron:monthly';
protected $description = 'Run the monthly cron tasks';
@@ -19,7 +19,11 @@ class Monthly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronMonthly());
}
}

View File

@@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronNightly;
/**
@@ -11,7 +11,7 @@ use App\Events\CronNightly;
*
* The actual cron tasks are in app/Cron
*/
class Nightly extends Command
class Nightly extends CronCommand
{
protected $signature = 'cron:nightly';
protected $description = 'Run the nightly cron tasks';
@@ -19,7 +19,11 @@ class Nightly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronNightly());
}
}

View File

@@ -0,0 +1,26 @@
<?php
namespace App\Console\Cron;
use App\Contracts\CronCommand;
use App\Events\CronThirtyMinute;
/**
* The actual cron tasks are in app/Cron
*/
class ThirtyMinute extends CronCommand
{
protected $signature = 'cron:thirty';
protected $description = 'Run the 30 minute cron tasks';
protected $schedule;
public function handle(): void
{
$this->callEvent();
}
public function callEvent()
{
event(new CronThirtyMinute());
}
}

View File

@@ -2,7 +2,7 @@
namespace App\Console\Cron;
use App\Contracts\Command;
use App\Contracts\CronCommand;
use App\Events\CronWeekly;
/**
@@ -11,7 +11,7 @@ use App\Events\CronWeekly;
*
* The actual cron tasks are in app/Cron
*/
class Weekly extends Command
class Weekly extends CronCommand
{
protected $signature = 'cron:weekly';
protected $description = 'Run the weekly cron tasks';
@@ -19,7 +19,11 @@ class Weekly extends Command
public function handle(): void
{
$this->redirectLoggingToFile('cron');
$this->callEvent();
}
public function callEvent()
{
event(new CronWeekly());
}
}

View File

@@ -2,10 +2,13 @@
namespace App\Console;
use App\Console\Cron\FifteenMinute;
use App\Console\Cron\FiveMinute;
use App\Console\Cron\Hourly;
use App\Console\Cron\JobQueue;
use App\Console\Cron\Monthly;
use App\Console\Cron\Nightly;
use App\Console\Cron\ThirtyMinute;
use App\Console\Cron\Weekly;
use App\Services\CronService;
use Illuminate\Console\Scheduling\Schedule;
@@ -33,10 +36,16 @@ class Kernel extends ConsoleKernel
->withoutOverlapping();
}
/*
* NOTE: IF MORE TASKS ARE ADDED, THEY ALSO MUST BE ADDED TO THE CRON.PHP
*/
$schedule->command(FiveMinute::class)->everyFiveMinutes();
$schedule->command(FifteenMinute::class)->everyFifteenMinutes();
$schedule->command(ThirtyMinute::class)->everyThirtyMinutes();
$schedule->command(Nightly::class)->dailyAt('01:00');
$schedule->command(Hourly::class)->hourly();
$schedule->command(Weekly::class)->weeklyOn(0);
$schedule->command(Monthly::class)->monthlyOn(1);
$schedule->command(Hourly::class)->hourly();
// When spatie-backups runs
/*if (config('backup.backup.enabled', false) === true) {

View File

@@ -29,6 +29,16 @@ abstract class Command extends \Illuminate\Console\Command
}*/
}
/**
* Return the signature of the command
*
* @return string
*/
public function getSignature(): string
{
return $this->signature;
}
/**
* Splice the logger and replace the active handlers with the handlers from the
* a stack in config/logging.php

View File

@@ -87,16 +87,17 @@ abstract class Controller extends \Illuminate\Routing\Controller
*
* @return \Illuminate\Http\JsonResponse
*/
public function message($message, $count = null)
public function message($message, $count = null, $attrs = [])
{
$attrs = [
$ret = [
'message' => $message,
'attrs' => $attrs,
];
if ($count !== null) {
$attrs['count'] = $count;
$ret['count'] = $count;
}
return response()->json($attrs);
return response()->json($ret);
}
}

View File

@@ -0,0 +1,20 @@
<?php
namespace App\Contracts;
abstract class CronCommand extends Command
{
/**
* @return mixed
*/
abstract public function callEvent();
/**
* Adjust the logging depending on where we're running from
*/
public function __construct()
{
parent::__construct();
$this->redirectLoggingToFile('cron');
}
}

View File

@@ -2,7 +2,6 @@
namespace App\Contracts;
use App\Notifications\Channels\Discord\DiscordMessage;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -26,24 +25,4 @@ class Notification extends \Illuminate\Notifications\Notification implements Sho
$this->channels = $notif_config[$klass];*/
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
*
* @return array
*/
/*public function via($notifiable)
{
return $this->channels;
}*/
/**
* @return DiscordMessage|null
*/
public function toDiscordChannel($notifiable): ?DiscordMessage
{
return null;
}
}

View File

@@ -20,7 +20,7 @@ class ClearExpiredSimbrief extends Listener
}
/**
* @param \App\Events\CronNightly $event
* @param CronHourly $event
*/
public function handle(CronHourly $event): void
{

View File

@@ -6,6 +6,7 @@ use App\Contracts\Listener;
use App\Events\CronHourly;
use App\Events\PirepCancelled;
use App\Models\Enums\PirepState;
use App\Models\Enums\PirepStatus;
use App\Models\Pirep;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;
@@ -31,6 +32,7 @@ class RemoveExpiredLiveFlights extends Listener
$date = Carbon::now('UTC')->subHours(setting('acars.live_time'));
$pireps = Pirep::where('updated_at', '<', $date)
->where('state', PirepState::IN_PROGRESS)
->where('status', '<>', PirepStatus::PAUSED)
->get();
foreach ($pireps as $pirep) {

View File

@@ -0,0 +1,15 @@
<?php
use App\Contracts\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class UpdateUsersAddNotes extends Migration
{
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->mediumText('notes')->nullable()->after('remember_token');
});
}
}

View File

@@ -34,9 +34,9 @@ airports:
lon: -97.6698889
hub: 1
ground_handling_cost: 100
- id: KPHN
- id: KHPN
iata: HPN
icao: KPHN
icao: KHPN
name: Westchester County Airport
location: White Plains
country: United States
@@ -45,6 +45,17 @@ airports:
lon: -73.7076
hub: 1
ground_handling_cost: 100
- id: KLGA
iata: LGA
icao: KLGA
name: La Guardia Airport
location: New York, New York, USA
country: United States
timezone: America/New_York
lat: 40.7772
lon: -73.8726
hub: 1
ground_handling_cost: 250
- id: KJFK
iata: JFK
icao: KJFK
@@ -575,6 +586,21 @@ flights:
visible: 1
created_at: now
updated_at: now
- id: flightid_4
airline_id: 1
flight_number: 100
dpt_airport_id: KHPN
arr_airport_id: KLGA
route: DCT CMK V374 DENNA V44 BELTT/N0346F140 V44 DPK DCT
distance: 75
level: 110
dpt_time: 6PM CST
arr_time: 11PM EST
flight_time: 240
flight_type: J
load_factor: 100
created_at: NOW
updated_at: NOW
flight_fields:
- name: Departure Terminal

View File

@@ -333,6 +333,13 @@
options: ''
type: int
description: 'The length of a pilot''s ID'
- key: pilots.id_code
name: 'Pilot ID Code'
group: pilots
value: ''
options: ''
type: text
description: 'Fixed ICAO code for pilot IDs'
- key: pilots.auto_accept
name: 'Auto Accept New Pilot'
group: pilots
@@ -403,6 +410,41 @@
options: ''
type: text
description: The Discord Webhook URL for private notifications
- key: notifications.discord_pirep_status
name: Discord Pirep Messages (Public)
group: notifications
value: true
options: ''
type: boolean
description: Pirep status messages (Only key events are being sent)
- key: notifications.mail_pirep_admin
name: Pirep Filed (Admin)
group: notifications
value: true
options: ''
type: boolean
description: Pirep filed mails sent to admins
- key: notifications.mail_pirep_user_ack
name: Pirep Accepted (Pilot)
group: notifications
value: true
options: ''
type: boolean
description: Pirep Accepted mails sent to pilots
- key: notifications.mail_pirep_user_rej
name: Pirep Rejected (Pilot)
group: notifications
value: true
options: ''
type: boolean
description: Pirep Rejected mails sent to pilots
- key: notifications.mail_news
name: News Mails
group: notifications
value: true
options: ''
type: boolean
description: News mails sent to all members
- key: 'cron.random_id'
name: 'Cron Randomized ID'
group: 'cron'

View File

@@ -0,0 +1,9 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFifteenMinute extends Event
{
}

View File

@@ -0,0 +1,9 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronFiveMinute extends Event
{
}

View File

@@ -0,0 +1,9 @@
<?php
namespace App\Events;
use App\Contracts\Event;
class CronThirtyMinute extends Event
{
}

View File

@@ -0,0 +1,43 @@
<?php
namespace App\Exceptions;
class BidNotFound extends AbstractHttpException
{
private $bid_id;
public function __construct($bid_id)
{
$this->bid_id = $bid_id;
parent::__construct(
404,
'The bid '.$bid_id.' was not found'
);
}
/**
* Return the RFC 7807 error type (without the URL root)
*/
public function getErrorType(): string
{
return 'bid-not-found';
}
/**
* Get the detailed error string
*/
public function getErrorDetails(): string
{
return $this->getMessage();
}
/**
* Return an array with the error details, merged with the RFC7807 response
*/
public function getErrorMetadata(): array
{
return [
'bid_id' => $this->bid_id,
];
}
}

View File

@@ -38,7 +38,7 @@ class AirlinesController extends Controller
public function index(Request $request)
{
$this->airlineRepo->pushCriteria(new RequestCriteria($request));
$airlines = $this->airlineRepo->all();
$airlines = $this->airlineRepo->orderby('name', 'asc')->get();
return view('admin.airlines.index', [
'airlines' => $airlines,

View File

@@ -308,7 +308,7 @@ class FlightController extends Controller
$where['airline_id'] = $airline_id;
$file_name = 'flights-'.$airline_id.'.csv';
}
$flights = $this->flightRepo->where($where)->get();
$flights = $this->flightRepo->where($where)->orderBy('airline_id')->orderBy('flight_number')->orderBy('route_code')->orderBy('route_leg')->get();
$path = $exporter->exportFlights($flights);
return response()->download($path, $file_name, ['content-type' => 'text/csv'])->deleteFileAfterSend(true);

View File

@@ -83,7 +83,7 @@ class SubfleetController extends Controller
public function index(Request $request)
{
$this->subfleetRepo->with(['airline'])->pushCriteria(new RequestCriteria($request));
$subfleets = $this->subfleetRepo->all();
$subfleets = $this->subfleetRepo->orderby('name', 'asc')->get();
return view('admin.subfleets.index', [
'subfleets' => $subfleets,

View File

@@ -32,7 +32,7 @@ class TypeRatingController extends Controller
public function index(Request $request)
{
$this->typeratingRepo->pushCriteria(new RequestCriteria($request));
$typeratings = $this->typeratingRepo->all();
$typeratings = $this->typeratingRepo->orderby('type', 'asc')->get();
return view('admin.typeratings.index', [
'typeratings' => $typeratings,
@@ -50,7 +50,6 @@ class TypeRatingController extends Controller
$model = $this->typeratingRepo->create($input);
Flash::success('Type Rating saved successfully.');
// Cache::forget(config('cache.keys.RANKS_PILOT_LIST.key'));
return redirect(route('admin.typeratings.edit', [$model->id]));
}

View File

@@ -2,10 +2,10 @@
namespace App\Http\Controllers\Api;
use App\Console\Cron;
use App\Contracts\Controller;
use App\Exceptions\CronInvalid;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Artisan;
class MaintenanceController extends Controller
{
@@ -24,12 +24,12 @@ class MaintenanceController extends Controller
throw new CronInvalid();
}
$output = '';
Artisan::call('schedule:run');
$output .= trim(Artisan::output());
$cron = app(Cron::class);
$run = $cron->run();
return response([
'content' => $output,
return response()->json([
'count' => count($run),
'tasks' => $run,
]);
}
}

View File

@@ -334,16 +334,18 @@ class PirepController extends Controller
*
* @throws \Prettus\Validator\Exceptions\ValidatorException
*
* @return PirepResource
* @return mixed
*/
public function cancel($pirep_id, Request $request)
{
Log::info('PIREP '.$pirep_id.' Cancel, user '.Auth::id(), $request->post());
$pirep = Pirep::find($pirep_id);
$this->pirepSvc->cancel($pirep);
if (!empty($pirep)) {
$this->pirepSvc->cancel($pirep);
}
return new PirepResource($pirep);
return $this->message('PIREP '.$pirep_id.' cancelled');
}
/**

View File

@@ -3,6 +3,7 @@
namespace App\Http\Controllers\Api;
use App\Contracts\Controller;
use App\Exceptions\BidNotFound;
use App\Exceptions\Unauthorized;
use App\Exceptions\UserNotFound;
use App\Http\Resources\Bid as BidResource;
@@ -160,6 +161,10 @@ class UserController extends Controller
// Return the current bid
$bid = $this->bidSvc->getBid($user, $bid_id);
if ($bid === null) {
throw new BidNotFound($bid_id);
}
if ($bid->user_id !== $user->id) {
throw new Unauthorized(new \Exception('Bid not not belong to authenticated user'));
}

View File

@@ -4,6 +4,16 @@ namespace App\Http\Resources;
use App\Contracts\Resource;
/**
* @mixin \App\Models\Aircraft
*/
class Aircraft extends Resource
{
public function toArray($request)
{
$res = parent::toArray($request);
$res['ident'] = $this->ident;
return $res;
}
}

View File

@@ -10,6 +10,8 @@ use Carbon\Carbon;
* @property string flight_id
* @property Carbon created_at
* @property Carbon updated_at
* @property Flight flight
* @property User user
*/
class Bid extends Model
{

View File

@@ -24,6 +24,7 @@ use Illuminate\Support\Collection;
* @property Collection subfleets
* @property int days
* @property int distance
* @property int planned_distance
* @property int flight_time
* @property string route
* @property string dpt_time

View File

@@ -88,6 +88,7 @@ class User extends Authenticatable
'toc_accepted',
'opt_in',
'last_ip',
'notes',
'created_at',
'updated_at',
];
@@ -97,10 +98,14 @@ class User extends Authenticatable
*/
protected $hidden = [
'api_key',
'email',
'name',
'discord_id',
'discord_private_channel_id',
'password',
'last_ip',
'remember_token',
'notes',
];
protected $casts = [
@@ -128,8 +133,9 @@ class User extends Authenticatable
public function getIdentAttribute(): string
{
$length = setting('pilots.id_length');
$ident_code = filled(setting('pilots.id_code')) ? setting('pilots.id_code') : optional($this->airline)->icao;
return optional($this->airline)->icao.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT);
return $ident_code.str_pad($this->pilot_id, $length, '0', STR_PAD_LEFT);
}
/**
@@ -148,7 +154,7 @@ class User extends Authenticatable
$first_name = $name_parts[0];
$last_name = $name_parts[$count - 1];
return $first_name.' '.$last_name[0];
return $first_name.' '.mb_substr($last_name, 0, 1);
}
/**

View File

@@ -11,14 +11,16 @@ use Carbon\Carbon;
*/
class DiscordMessage
{
const COLOR_SUCCESS = '#0B6623';
const COLOR_WARNING = '#FD6A02';
const COLOR_ERROR = '#ED2939';
const COLOR_SUCCESS = '0B6623';
const COLOR_WARNING = 'FD6A02';
const COLOR_ERROR = 'ED2939';
public $webhook_url;
protected $title;
protected $url;
protected $thumbnail = [];
protected $image = [];
protected $description;
protected $timestamp;
protected $footer;
@@ -26,30 +28,43 @@ class DiscordMessage
protected $author = [];
protected $fields = [];
/**
* Supply the webhook URL that this should be going to
*/
// Supply the webhook URL that this should be going to
public function webhook(string $url): self
{
$this->webhook_url = $url;
return $this;
}
/**
* Title of the notification
*/
// Title of the embed
public function title(string $title): self
{
$this->title = $title;
return $this;
}
// URL of the Title
public function url(string $url): self
{
$this->url = $url;
return $this;
}
// Thumbnail image (placed right side of embed)
// ['url' => '']
public function thumbnail(array $thumbnail): self
{
$this->thumbnail = $thumbnail;
return $this;
}
// Main image (placed bottom of embed)
// ['url' => '']
public function image(array $image): self
{
$this->image = $image;
return $this;
}
/**
* @param array|string $descriptionLines
*/
@@ -63,22 +78,15 @@ class DiscordMessage
return $this;
}
/**
* Set the author information:
* [
* 'name' => '',
* 'url' => '',
* 'icon_url' => '',
*/
// Author details
// ['name' => '', 'url' => '', 'icon_url' => '']
public function author(array $author): self
{
$this->author = $author;
return $this;
}
/**
* Set the fields
*/
// Fields
public function fields(array $fields): self
{
$this->fields = [];
@@ -99,32 +107,45 @@ class DiscordMessage
return $this;
}
// Fixed Success Color
public function success(): self
{
$this->color = static::COLOR_SUCCESS;
$this->color = hexdec('0B6623'); // static::COLOR_SUCCESS;
return $this;
}
// Fixed Warning
public function warning(): self
{
$this->color = static::COLOR_WARNING;
$this->color = hexdec('FD6A02'); // static::COLOR_WARNING;
return $this;
}
// Fixed Error
public function error(): self
{
$this->color = static::COLOR_ERROR;
$this->color = hexdec('ED2939'); // static::COLOR_ERROR;
return $this;
}
// Custom Color
public function color(string $embed_color): self
{
$this->color = hexdec($embed_color);
return $this;
}
public function toArray(): array
{
$embeds = [
'type' => 'rich',
'color' => $this->color,
'title' => $this->title,
'url' => $this->url,
'type' => 'rich',
'thumbnail' => $this->thumbnail,
'description' => $this->description,
'author' => $this->author,
'image' => $this->image,
'timestamp' => Carbon::now('UTC'),
];

View File

@@ -20,14 +20,23 @@ class DiscordWebhook
public function send($notifiable, Notification $notification)
{
$message = $notification->toDiscordChannel($notifiable);
if ($message === null || empty($message->webhook_url)) {
Log::debug('Discord notifications not configured, skipping');
if ($message === null) {
//Log::debug('Discord notifications not configured, skipping');
return;
}
$webhook_url = $message->webhook_url;
if (empty($webhook_url)) {
$webhook_url = setting('notifications.discord_private_webhook_url');
if (empty($webhook_url)) {
//Log::debug('Discord notifications not configured, skipping');
return;
}
}
try {
$data = $message->toArray();
$this->httpClient->post($message->webhook_url, $data);
$this->httpClient->post($webhook_url, $data);
} catch (RequestException $e) {
$request = Psr7\Message::toString($e->getRequest());
$response = Psr7\Message::toString($e->getResponse());

View File

@@ -4,8 +4,6 @@ namespace App\Notifications\Messages;
use App\Contracts\Notification;
use App\Models\User;
use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Notifications\Channels\MailChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
@@ -32,32 +30,21 @@ class AdminUserRegistered extends Notification implements ShouldQueue
);
}
/**
* @param $notifiable
*
* @return string[]
*/
public function via($notifiable)
{
return ['mail', DiscordWebhook::class];
return ['mail'];
}
/**
* Send a Discord notification
* @param $notifiable
*
* @param User $pirep
* @param mixed $user
*
* @return DiscordMessage|null
* @return array
*/
public function toDiscordChannel($user): ?DiscordMessage
{
if (empty(setting('notifications.discord_private_webhook_url'))) {
return null;
}
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_private_webhook_url'))
->success()
->title('New User Registered: '.$user->ident)
->fields([]);
}
public function toArray($notifiable)
{
return [

View File

@@ -0,0 +1,58 @@
<?php
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\News;
use App\Notifications\Channels\Discord\DiscordMessage;
use Illuminate\Contracts\Queue\ShouldQueue;
class NewsAdded extends Notification implements ShouldQueue
{
private $news;
public function __construct(News $news)
{
parent::__construct();
$this->news = $news;
}
public function via($notifiable)
{
return ['discord_webhook'];
}
/**
* @param News $news
*
* @return DiscordMessage|null
*/
public function toDiscordChannel($news): ?DiscordMessage
{
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->success()
->title('News: '.$news->subject)
->author([
'name' => $news->user->ident.' - '.$news->user->name_private,
'url' => '',
'icon_url' => $news->user->resolveAvatarUrl(),
])
->description($news->body);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'news_id' => $this->news->id,
];
}
}

View File

@@ -1,22 +1,18 @@
<?php
namespace App\Notifications\Messages;
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\Pirep;
use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Notifications\Channels\MailChannel;
use App\Support\Units\Distance;
use App\Support\Units\Time;
use Illuminate\Contracts\Queue\ShouldQueue;
use PhpUnitsOfMeasure\Exception\NonNumericValue;
use PhpUnitsOfMeasure\Exception\NonStringUnitName;
class PirepSubmitted extends Notification implements ShouldQueue
class PirepFiled extends Notification implements ShouldQueue
{
use MailChannel;
private $pirep;
/**
@@ -29,17 +25,11 @@ class PirepSubmitted extends Notification implements ShouldQueue
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'New PIREP Submitted',
'notifications.mail.admin.pirep.submitted',
['pirep' => $this->pirep]
);
}
public function via($notifiable)
{
return ['mail', DiscordWebhook::class];
return ['discord_webhook'];
}
/**
@@ -51,42 +41,40 @@ class PirepSubmitted extends Notification implements ShouldQueue
*/
public function toDiscordChannel($pirep): ?DiscordMessage
{
if (empty(setting('notifications.discord_public_webhook_url'))) {
return null;
}
$title = 'Flight '.$pirep->ident.' Filed';
$fields = [
'Flight' => $pirep->ident,
'Departure Airport' => $pirep->dpt_airport_id,
'Arrival Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time (Planned)' => Time::minutesToTimeString($pirep->planned_flight_time),
'Dep.Airport' => $pirep->dpt_airport_id,
'Arr.Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
];
if ($pirep->planned_distance) {
if ($pirep->distance) {
try {
$planned_distance = new Distance(
$pirep->planned_distance,
$distance = new Distance(
$pirep->distance,
config('phpvms.internal_units.distance')
);
$pd = $planned_distance[$planned_distance->unit].' '.$planned_distance->unit;
$fields['Distance (Planned)'] = $pd;
$pd = $distance[$distance->unit].' '.$distance->unit;
$fields['Distance'] = $pd;
} catch (NonNumericValue|NonStringUnitName $e) {
}
}
// User avatar, somehow $pirep->user->resolveAvatarUrl() is not being accepted by Discord as thumbnail
$user_avatar = !empty($pirep->user->avatar) ? $pirep->user->avatar->url : $pirep->user->gravatar(256);
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->success()
->title($title)
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
->url(route('frontend.pireps.show', [$pirep->id]))
->thumbnail(['url' => $user_avatar])
->image(['url' => $pirep->airline->logo])
->author([
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
'icon_url' => $pirep->user->resolveAvatarUrl(),
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
])
->fields($fields);
}

View File

@@ -1,6 +1,6 @@
<?php
namespace App\Notifications\Messages;
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\Pirep;

View File

@@ -1,6 +1,6 @@
<?php
namespace App\Notifications\Messages;
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\Enums\PirepStatus;
@@ -78,13 +78,11 @@ class PirepStatusChanged extends Notification implements ShouldQueue
}
$title = 'Flight '.$pirep->ident.' '.self::$verbs[$pirep->status];
$fields = [
'Flight' => $pirep->ident,
'Departure Airport' => $pirep->dpt_airport_id,
'Arrival Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
'Dep.Airport' => $pirep->dpt_airport_id,
'Arr.Airport' => $pirep->arr_airport_id,
'Equipment' => $pirep->aircraft->ident,
'Flight Time' => Time::minutesToTimeString($pirep->flight_time),
];
// Show the distance, but include the planned distance if it's been set
@@ -111,16 +109,29 @@ class PirepStatusChanged extends Notification implements ShouldQueue
}
}
// User avatar, somehow $pirep->user->resolveAvatarUrl() is not being accepted by Discord as thumbnail
$user_avatar = !empty($pirep->user->avatar) ? $pirep->user->avatar->url : $pirep->user->gravatar(256);
// Proper coloring for the messages
// Pirep Filed > success, normals > warning, non-normals > error
$danger_types = [
PirepStatus::GRND_RTRN,
PirepStatus::DIVERTED,
PirepStatus::CANCELLED,
PirepStatus::PAUSED,
PirepStatus::EMERG_DESCENT,
];
$color = in_array($pirep->status, $danger_types, true) ? 'ED2939' : 'FD6A02';
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_public_webhook_url'))
->success()
->color($color)
->title($title)
->description($pirep->user->discord_id ? 'Flight by <@'.$pirep->user->discord_id.'>' : '')
->url(route('frontend.pireps.show', [$pirep->id]))
->thumbnail(['url' => $user_avatar])
->author([
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
'icon_url' => $pirep->user->resolveAvatarUrl(),
'name' => $pirep->user->ident.' - '.$pirep->user->name_private,
'url' => route('frontend.profile.show', [$pirep->user_id]),
])
->fields($fields);
}

View File

@@ -0,0 +1,74 @@
<?php
namespace App\Notifications\Messages\Broadcast;
use App\Contracts\Notification;
use App\Models\User;
use App\Notifications\Channels\Discord\DiscordMessage;
use App\Notifications\Channels\MailChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
/**
* Send a message to a Discord channel that a user was registered
*/
class UserRegistered extends Notification implements ShouldQueue
{
use MailChannel;
private $user;
/**
* Create a new notification instance.
*
* @param \App\Models\User $user
*/
public function __construct(User $user)
{
parent::__construct();
$this->user = $user;
}
/**
* @param $notifiable
*
* @return string[]
*/
public function via($notifiable)
{
return ['discord_webhook'];
}
/**
* Send a Discord notification
*
* @param $notifiable
*
* @return DiscordMessage|null
*/
public function toDiscordChannel($notifiable): ?DiscordMessage
{
$dm = new DiscordMessage();
return $dm->webhook(setting('notifications.discord_private_webhook_url'))
->success()
->title('New User Registered: '.$this->user->ident)
->author([
'name' => $this->user->ident.' - '.$this->user->name_private,
'url' => '',
'icon_url' => $this->user->resolveAvatarUrl(),
])
->fields([]);
}
/**
* @param $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'user_id' => $this->user->id,
];
}
}

View File

@@ -0,0 +1,53 @@
<?php
namespace App\Notifications\Messages;
use App\Contracts\Notification;
use App\Models\Pirep;
use App\Notifications\Channels\MailChannel;
use Illuminate\Contracts\Queue\ShouldQueue;
class PirepFiled extends Notification implements ShouldQueue
{
use MailChannel;
private $pirep;
/**
* Create a new notification instance.
*
* @param \App\Models\Pirep $pirep
*/
public function __construct(Pirep $pirep)
{
parent::__construct();
$this->pirep = $pirep;
$this->setMailable(
'New PIREP Submitted',
'notifications.mail.admin.pirep.submitted',
['pirep' => $this->pirep]
);
}
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
*
* @return array
*/
public function toArray($notifiable)
{
return [
'pirep_id' => $this->pirep->id,
'user_id' => $this->pirep->user_id,
];
}
}

View File

@@ -11,6 +11,7 @@ use App\Events\PirepRejected;
use App\Events\PirepStatusChange;
use App\Events\UserRegistered;
use App\Events\UserStateChanged;
use App\Models\Enums\PirepStatus;
use App\Models\Enums\UserState;
use App\Models\User;
use App\Notifications\Messages\UserRejected;
@@ -134,10 +135,10 @@ class NotificationEventsHandler extends Listener
*/
$this->notifyAdmins(new Messages\AdminUserRegistered($event->user));
/**
* Discord and other notifications
/*
* Broadcast notifications
*/
Notification::send([$event->user], new Messages\AdminUserRegistered($event->user));
Notification::send([$event->user], new Messages\Broadcast\UserRegistered($event->user));
}
/**
@@ -161,21 +162,42 @@ class NotificationEventsHandler extends Listener
}
/**
* Prefile notification
* Prefile notification. Disabled intentionally, No need to send it to Discord
*/
public function onPirepPrefile(PirepPrefiled $event): void
{
Log::info('NotificationEvents::onPirepPrefile: '.$event->pirep->id.' prefiled');
Notification::send([$event->pirep], new Messages\PirepPrefiled($event->pirep));
/*
* Broadcast notifications
*/
// Notification::send([$event->pirep], new Messages\Broadcast\PirepPrefiled($event->pirep));
}
/**
* Status Change notification
* Status Change notification.
* Reduced the messages (Boarding, Pushback, TakeOff, Landing and non-normals only)
* If needed array can be tied to a setting at admin side for further customization
*/
public function onPirepStatusChange(PirepStatusChange $event): void
{
Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' prefiled');
Notification::send([$event->pirep], new Messages\PirepStatusChanged($event->pirep));
Log::info('NotificationEvents::onPirepStatusChange: '.$event->pirep->id.' status changed');
$message_types = [
PirepStatus::BOARDING,
PirepStatus::PUSHBACK_TOW,
PirepStatus::GRND_RTRN,
PirepStatus::TAKEOFF,
PirepStatus::LANDED,
PirepStatus::DIVERTED,
PirepStatus::CANCELLED,
PirepStatus::PAUSED,
PirepStatus::EMERG_DESCENT,
];
if (setting('notifications.discord_pirep_status', true) && in_array($event->pirep->status, $message_types, true)) {
Notification::send([$event->pirep], new Messages\Broadcast\PirepStatusChanged($event->pirep));
}
}
/**
@@ -186,8 +208,14 @@ class NotificationEventsHandler extends Listener
public function onPirepFile(PirepFiled $event): void
{
Log::info('NotificationEvents::onPirepFile: '.$event->pirep->id.' filed');
$this->notifyAdmins(new Messages\PirepSubmitted($event->pirep));
Notification::send([$event->pirep], new Messages\PirepSubmitted($event->pirep));
if (setting('notifications.mail_pirep_admin', true)) {
$this->notifyAdmins(new Messages\PirepFiled($event->pirep));
}
/*
* Broadcast notifications
*/
Notification::send([$event->pirep], new Messages\Broadcast\PirepFiled($event->pirep));
}
/**
@@ -197,8 +225,10 @@ class NotificationEventsHandler extends Listener
*/
public function onPirepAccepted(PirepAccepted $event): void
{
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
$this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
if (setting('notifications.mail_pirep_user_ack', true)) {
Log::info('NotificationEvents::onPirepAccepted: '.$event->pirep->id.' accepted');
$this->notifyUser($event->pirep->user, new Messages\PirepAccepted($event->pirep));
}
}
/**
@@ -208,8 +238,10 @@ class NotificationEventsHandler extends Listener
*/
public function onPirepRejected(PirepRejected $event): void
{
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
$this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
if (setting('notifications.mail_pirep_user_rej', true)) {
Log::info('NotificationEvents::onPirepRejected: '.$event->pirep->id.' rejected');
$this->notifyUser($event->pirep->user, new Messages\PirepRejected($event->pirep));
}
}
/**
@@ -220,7 +252,13 @@ class NotificationEventsHandler extends Listener
public function onNewsAdded(NewsAdded $event): void
{
Log::info('NotificationEvents::onNewsAdded');
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
Notification::send([$event->news], new Messages\NewsAdded($event->news));
if (setting('notifications.mail_news', true)) {
$this->notifyAllUsers(new Messages\NewsAdded($event->news));
}
/*
* Broadcast notifications
*/
Notification::send([$event->news], new Messages\Broadcast\NewsAdded($event->news));
}
}

View File

@@ -2,10 +2,12 @@
namespace App\Providers;
use App\Notifications\Channels\Discord\DiscordWebhook;
use App\Services\ModuleService;
use App\Support\ThemeViewFinder;
use App\Support\Utils;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
@@ -15,8 +17,13 @@ class AppServiceProvider extends ServiceProvider
public function boot(): void
{
Schema::defaultStringLength(191);
Paginator::useBootstrap();
View::share('moduleSvc', app(ModuleService::class));
Notification::extend('discord_webhook', function ($app) {
return app(DiscordWebhook::class);
});
}
/**

View File

@@ -12,9 +12,12 @@ use App\Cron\Nightly\PilotLeave;
use App\Cron\Nightly\RecalculateBalances;
use App\Cron\Nightly\RecalculateStats;
use App\Cron\Nightly\SetActiveFlights;
use App\Events\CronFifteenMinute;
use App\Events\CronFiveMinute;
use App\Events\CronHourly;
use App\Events\CronMonthly;
use App\Events\CronNightly;
use App\Events\CronThirtyMinute;
use App\Events\CronWeekly;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -24,6 +27,15 @@ use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvi
class CronServiceProvider extends ServiceProvider
{
protected $listen = [
CronFiveMinute::class => [],
CronFifteenMinute::class => [],
CronThirtyMinute::class => [],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
CronNightly::class => [
ApplyExpenses::class,
RecalculateBalances::class,
@@ -32,19 +44,10 @@ class CronServiceProvider extends ServiceProvider
RecalculateStats::class,
NewVersionCheck::class,
],
CronWeekly::class => [
],
CronMonthly::class => [
\App\Cron\Monthly\ApplyExpenses::class,
],
CronHourly::class => [
DeletePireps::class,
RemoveExpiredBids::class,
RemoveExpiredLiveFlights::class,
ClearExpiredSimbrief::class,
],
];
}

View File

@@ -90,11 +90,11 @@ class UserRepository extends Repository
}
if ($request->filled('name')) {
$where['name'] = $request->name;
$where[] = ['name', 'LIKE', '%'.$request->name.'%'];
}
if ($request->filled('email')) {
$where['email'] = $request->email;
$where[] = ['email', 'LIKE', '%'.$request->email.'%'];
}
if ($request->filled('state')) {

View File

@@ -33,7 +33,7 @@ class BidService extends Service
*
* @return \App\Models\Bid|\Illuminate\Database\Eloquent\Model|object|null
*/
public function getBid(User $user, $bid_id): Bid
public function getBid(User $user, $bid_id): ?Bid
{
$with = [
'flight',
@@ -48,7 +48,18 @@ class BidService extends Service
'flight.subfleets.fares',
];
return Bid::with($with)->where(['id' => $bid_id])->first();
/** @var Bid $bid */
$bid = Bid::with($with)->where(['id' => $bid_id])->first();
if ($bid === null) {
return null;
}
// Reconcile the aircraft for this bid
// TODO: Only do this if there isn't a Simbrief attached?
$bid->flight = $this->flightSvc->filterSubfleets($user, $bid->flight);
$bid->flight = $this->fareSvc->getReconciledFaresForFlight($bid->flight);
return $bid;
}
/**
@@ -127,8 +138,10 @@ class BidService extends Service
throw new BidExistsForFlight($flight);
}
// This is already controlled above at line 114 with user bid count,
// To prevent or allow multiple bids. Should not be here at all
if (setting('bids.allow_multiple_bids') === false) {
throw new BidExistsForFlight($flight);
// throw new BidExistsForFlight($flight);
}
} else {
/* @noinspection NestedPositiveIfStatementsInspection */

View File

@@ -39,8 +39,7 @@ class CronService extends Service
$path = [
$php_exec,
base_path('artisan'),
'schedule:run',
base_path('bin/cron'),
];
return implode(' ', $path);

View File

@@ -243,7 +243,7 @@ class PirepService extends Service
// Copy some fields over from Flight if we have it
if ($pirep->flight) {
$pirep->planned_distance = $pirep->flight->distance;
$pirep->planned_distance = $pirep->flight->planned_distance;
$pirep->planned_flight_time = $pirep->flight->flight_time;
}
@@ -336,7 +336,7 @@ class PirepService extends Service
// Copy some fields over from Flight if we have it
if ($pirep->flight) {
$pirep->planned_distance = $pirep->flight->distance;
$pirep->distance = $pirep->flight->distance;
$pirep->planned_flight_time = $pirep->flight->flight_time;
}
@@ -485,8 +485,8 @@ class PirepService extends Service
$default_state = $pirep->state;
}
// If pirep is still at PENDING state decide the default behavior by looking at rank settings
if ($pirep->state === PirepState::PENDING) {
// If pirep is still at PENDING or DRAFT state decide the default behavior by looking at rank settings
if ($pirep->state === PirepState::PENDING || $pirep->state === PirepState::DRAFT) {
if ($pirep->source === PirepSource::ACARS && $pirep->user->rank->auto_approve_acars) {
$default_state = PirepState::ACCEPTED;
} elseif ($pirep->source === PirepSource::MANUAL && $pirep->user->rank->auto_approve_manual) {

35
bin/cron Executable file
View File

@@ -0,0 +1,35 @@
#!/usr/bin/env php
<?php
/**
* THIS CRON FILE IS A BACKUP METHOD IF YOUR SERVER DOES NOT HAVE PROC_OPEN ENABLED
* YOU SHOULD TRY USING THE DEFAULT INSTRUCTIONS OF USING ARTISAN SCHEDULE:RUN
*/
define('LARAVEL_START', microtime(true));
use App\Console\Cron;
use App\Console\Kernel;
require __DIR__.'/../vendor/autoload.php';
/** @var Application $app */
$app = require_once __DIR__.'/../bootstrap/app.php';
/** @var Kernel $kernel */
$kernel = $app->make(Kernel::class);
// Run a null artisan thing just so Laravel internals can be setup properly
$status = $kernel->handle(
$input = new Symfony\Component\Console\Input\ArrayInput([
'command' => 'version',
]),
new Symfony\Component\Console\Output\NullOutput()
);
/** @var Cron $cron */
$cron = app(Cron::class);
$run = $cron->run();
echo json_encode([
'count' => count($run),
'tasks' => $run,
]);

View File

@@ -15,15 +15,21 @@
"ext-bcmath": "*",
"ext-pdo": "*",
"ext-intl": "*",
"cache/adapter-common": "1.2.0",
"cache/array-adapter": "1.1.0",
"cache/hierarchical-cache": "1.1.0",
"symfony/flex": "^1.0",
"symfony/polyfill-intl-icu": "*",
"symfony/polyfill-intl-idn": "*",
"symfony/polyfill-mbstring": "*",
"symfony/polyfill-php74": "*",
"symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*",
"symfony/deprecation-contracts": "^v2.5.0",
"symfony/event-dispatcher-contracts": "^2",
"symfony/property-info": "^5.4",
"symfony/string": "^5.4",
"symfony/translation": "^5.4",
"psr/container": "1.1.1",
"composer/composer": "~2.0",
"composer/installers": "~1.0",
@@ -46,21 +52,21 @@
"laravel/helpers": "^1.4",
"laravelcollective/html": "~6.2.0",
"jeremykendall/php-domain-parser": "~5.7.2",
"league/commonmark": "~1.6",
"league/commonmark": "~1.6.0",
"league/csv": "9.7.*",
"league/geotools": "0.8.*",
"league/iso3166": "^3.0.0",
"markrogoyski/math-php": "^1.10",
"markrogoyski/math-php": "^1.11.0",
"myclabs/deep-copy": "~1.10.0",
"nabeel/vacentral": "~2.0",
"nwidart/laravel-modules": "^8.2",
"nwidart/laravel-modules": "^8.2.0",
"php-units-of-measure/php-units-of-measure": "~2.1.0",
"phpvms/sample-module": "^1.0",
"pragmarx/version": ">=v1.2.3",
"prettus/l5-repository": "~2.7.0",
"santigarcor/laratrust": "~6.3",
"santigarcor/laratrust": "~6.3.0",
"semver/semver": "~1.1.0",
"spatie/valuestore": "~1.2",
"spatie/valuestore": "~1.2.0",
"symfony/polyfill-iconv": "~1.22.0",
"tivie/php-os-detector": "~1.1.0",
"vlucas/phpdotenv": "^5.3.0",
@@ -114,7 +120,7 @@
"module-dir": "modules",
"symfony": {
"require": "^5.4"
}
}
},
"scripts": {
"pre-package-uninstall": [

1287
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,8 +3,8 @@
use App\Notifications\Messages\AdminUserRegistered;
use App\Notifications\Messages\NewsAdded;
use App\Notifications\Messages\PirepAccepted;
use App\Notifications\Messages\PirepFiled;
use App\Notifications\Messages\PirepRejected;
use App\Notifications\Messages\PirepSubmitted;
use App\Notifications\Messages\UserPending;
use App\Notifications\Messages\UserRegistered;
use App\Notifications\Messages\UserRejected;
@@ -18,7 +18,7 @@ return [
NewsAdded::class => ['mail'],
PirepAccepted::class => ['mail'],
PirepRejected::class => ['mail'],
PirepSubmitted::class => ['mail'],
PirepFiled::class => ['mail'],
UserPending::class => ['mail'],
UserRegistered::class => ['mail'],
UserRejected::class => ['mail'],

610
package-lock.json generated
View File

@@ -1,5 +1,5 @@
{
"name": "phpvms",
"name": "npm-proj-1647195469379-0.2625236740756156F6TT9D",
"lockfileVersion": 2,
"requires": true,
"packages": {
@@ -22,7 +22,7 @@
"jquery": "^3.5.1",
"jquery-pjax": "~2.0",
"js-yaml": "^3.14.0",
"laravel-mix": "^6.0.25",
"laravel-mix": "^6.0.30",
"leaflet": "^1.3.4",
"leaflet-ajax": "2.1.0",
"leaflet-providers": "1.0.*",
@@ -1752,9 +1752,9 @@
}
},
"node_modules/@types/http-proxy": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz",
"integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==",
"version": "1.17.8",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
"integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
"dependencies": {
"@types/node": "*"
}
@@ -1801,9 +1801,9 @@
}
},
"node_modules/@types/json-schema": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz",
"integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg=="
"version": "7.0.9",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
},
"node_modules/@types/minimatch": {
"version": "3.0.5",
@@ -2039,6 +2039,42 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"dependencies": {
"ajv": "^8.0.0"
},
"peerDependencies": {
"ajv": "^8.0.0"
},
"peerDependenciesMeta": {
"ajv": {
"optional": true
}
}
},
"node_modules/ajv-formats/node_modules/ajv": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
"integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ajv-formats/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -2082,10 +2118,10 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ansi-html": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
"integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4=",
"node_modules/ansi-html-community": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
"integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
"engines": [
"node >= 0.8.0"
],
@@ -4009,6 +4045,14 @@
"node": ">= 10"
}
},
"node_modules/define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
"engines": {
"node": ">=8"
}
},
"node_modules/define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@@ -6168,6 +6212,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"dependencies": {
"has-symbols": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -7162,11 +7220,12 @@
}
},
"node_modules/is-arguments": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
"integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"dependencies": {
"call-bind": "^1.0.0"
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
@@ -7738,11 +7797,6 @@
"node": ">=8"
}
},
"node_modules/killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
"integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg=="
},
"node_modules/kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -7778,9 +7832,9 @@
}
},
"node_modules/laravel-mix": {
"version": "6.0.25",
"resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-6.0.25.tgz",
"integrity": "sha512-SDpLGUnXJ8g0rvtiLljSTJSR6awj86M2Jd3MhbtT32TCgwXdtajVLF7Mv2blsPLixGHtynwZgi+UFlYQbquPLg==",
"version": "6.0.30",
"resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-6.0.30.tgz",
"integrity": "sha512-Y5EjdPVEqVMgnglzJvDuDEpUa2EouutS4ySrukZkBWh2EPPYM1iszu8TItvQ2J08N5BPIrYWh8McUbTwq6tcrQ==",
"dependencies": {
"@babel/core": "^7.14.5",
"@babel/plugin-proposal-object-rest-spread": "^7.14.5",
@@ -7827,7 +7881,7 @@
"vue-style-loader": "^4.1.3",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "4.0.0-beta.3",
"webpack-dev-server": "4.1.1",
"webpack-merge": "^5.8.0",
"webpack-notifier": "^1.13.0",
"webpackbar": "^5.0.0-3",
@@ -7878,9 +7932,9 @@
}
},
"node_modules/laravel-mix/node_modules/ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==",
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
@@ -7981,18 +8035,26 @@
}
},
"node_modules/laravel-mix/node_modules/http-proxy-middleware": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz",
"integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz",
"integrity": "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==",
"dependencies": {
"@types/http-proxy": "^1.17.5",
"@types/http-proxy": "^1.17.8",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
"micromatch": "^4.0.2"
},
"engines": {
"node": ">=8.0.0"
"node": ">=12.0.0"
},
"peerDependencies": {
"@types/express": "^4.17.13"
},
"peerDependenciesMeta": {
"@types/express": {
"optional": true
}
}
},
"node_modules/laravel-mix/node_modules/import-local": {
@@ -8058,15 +8120,16 @@
}
},
"node_modules/laravel-mix/node_modules/open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
"integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
"dependencies": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
"define-lazy-prop": "^2.0.0",
"is-docker": "^2.1.1",
"is-wsl": "^2.2.0"
},
"engines": {
"node": ">=8"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -8175,11 +8238,11 @@
}
},
"node_modules/laravel-mix/node_modules/strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.0"
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
@@ -8251,37 +8314,35 @@
}
},
"node_modules/laravel-mix/node_modules/webpack-dev-server": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.0.0-beta.3.tgz",
"integrity": "sha512-Ud7ieH15No/KiSdRuzk+2k+S4gSCR/N7m4hJhesDbKQEZy3P+NPXTXfsimNOZvbVX2TRuIEFB+VdLZFn8DwGwg==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.1.1.tgz",
"integrity": "sha512-Kl1mnCEw8Cy1Kw173gCxLIB242LfPKEOj9WoKhKz/MbryZTNrILzOJTk8kiczw/YUEPzn3gcltCQv6hDsLudRg==",
"dependencies": {
"ansi-html": "^0.0.7",
"ansi-html-community": "^0.0.8",
"bonjour": "^3.5.0",
"chokidar": "^3.5.1",
"colorette": "^1.2.2",
"compression": "^1.7.4",
"connect-history-api-fallback": "^1.6.0",
"del": "^6.0.0",
"express": "^4.17.1",
"find-cache-dir": "^3.3.1",
"graceful-fs": "^4.2.6",
"html-entities": "^2.3.2",
"http-proxy-middleware": "^1.3.1",
"http-proxy-middleware": "^2.0.0",
"internal-ip": "^6.2.0",
"ipaddr.js": "^2.0.0",
"is-absolute-url": "^3.0.3",
"killable": "^1.0.1",
"open": "^7.4.2",
"ipaddr.js": "^2.0.1",
"open": "^8.0.9",
"p-retry": "^4.5.0",
"portfinder": "^1.0.28",
"schema-utils": "^3.0.0",
"schema-utils": "^3.1.0",
"selfsigned": "^1.10.11",
"serve-index": "^1.9.1",
"sockjs": "^0.3.21",
"spdy": "^4.0.2",
"strip-ansi": "^6.0.0",
"strip-ansi": "^7.0.0",
"url": "^0.11.0",
"webpack-dev-middleware": "^4.1.0",
"ws": "^7.4.5"
"webpack-dev-middleware": "^5.0.0",
"ws": "^8.1.0"
},
"bin": {
"webpack-dev-server": "bin/webpack-dev-server.js"
@@ -8290,7 +8351,7 @@
"node": ">= 12.13.0"
},
"peerDependencies": {
"webpack": "^4.0.0 || ^5.0.0"
"webpack": "^4.37.0 || ^5.0.0"
},
"peerDependenciesMeta": {
"webpack-cli": {
@@ -8298,12 +8359,37 @@
}
}
},
"node_modules/laravel-mix/node_modules/ws": {
"version": "7.5.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
"node_modules/laravel-mix/node_modules/webpack-dev-server/node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"engines": {
"node": ">=8.3.0"
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/laravel-mix/node_modules/webpack-dev-server/node_modules/strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/laravel-mix/node_modules/ws": {
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
@@ -8521,17 +8607,6 @@
"semver": "bin/semver.js"
}
},
"node_modules/map-age-cleaner": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
"dependencies": {
"p-defer": "^1.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -8601,33 +8676,10 @@
"node": ">= 0.6"
}
},
"node_modules/mem": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz",
"integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==",
"dependencies": {
"map-age-cleaner": "^0.1.3",
"mimic-fn": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/mem?sponsor=1"
}
},
"node_modules/mem/node_modules/mimic-fn": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
"integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/memfs": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.2.2.tgz",
"integrity": "sha512-RE0CwmIM3CEvpcdK3rZ19BC4E6hv9kADkMN5rPduRak58cNArWLi/9jFLsa4rhsjfVxMP3v0jO7FHXq7SvFY5Q==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
"integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
"dependencies": {
"fs-monkey": "1.0.3"
},
@@ -9555,14 +9607,6 @@
"node": ">=0.10.0"
}
},
"node_modules/p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww=",
"engines": {
"node": ">=4"
}
},
"node_modules/p-event": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz",
@@ -11332,6 +11376,14 @@
"node": ">=0.10.0"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -11656,9 +11708,9 @@
"integrity": "sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw=="
},
"node_modules/selfsigned": {
"version": "1.10.11",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
"integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
"version": "1.10.14",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz",
"integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==",
"dependencies": {
"node-forge": "^0.10.0"
}
@@ -13653,19 +13705,18 @@
}
},
"node_modules/webpack-dev-middleware": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz",
"integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz",
"integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==",
"dependencies": {
"colorette": "^1.2.2",
"mem": "^8.1.1",
"memfs": "^3.2.2",
"mime-types": "^2.1.30",
"colorette": "^2.0.10",
"memfs": "^3.4.1",
"mime-types": "^2.1.31",
"range-parser": "^1.2.1",
"schema-utils": "^3.0.0"
"schema-utils": "^4.0.0"
},
"engines": {
"node": ">= v10.23.3"
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
@@ -13675,17 +13726,54 @@
"webpack": "^4.0.0 || ^5.0.0"
}
},
"node_modules/webpack-dev-middleware/node_modules/schema-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
"node_modules/webpack-dev-middleware/node_modules/ajv": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
"integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
"dependencies": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dependencies": {
"fast-deep-equal": "^3.1.3"
},
"peerDependencies": {
"ajv": "^8.8.2"
}
},
"node_modules/webpack-dev-middleware/node_modules/colorette": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
"integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g=="
},
"node_modules/webpack-dev-middleware/node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/webpack-dev-middleware/node_modules/schema-utils": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
"integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
"dependencies": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.8.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.0.0"
},
"engines": {
"node": ">= 10.13.0"
"node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
@@ -15421,9 +15509,9 @@
}
},
"@types/http-proxy": {
"version": "1.17.7",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz",
"integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==",
"version": "1.17.8",
"resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.8.tgz",
"integrity": "sha512-5kPLG5BKpWYkw/LVOGWpiq3nEVqxiN32rTgI53Sk12/xHFQ2rG3ehI9IO+O3W2QoKeyB92dJkoka8SUm6BX1pA==",
"requires": {
"@types/node": "*"
}
@@ -15470,9 +15558,9 @@
}
},
"@types/json-schema": {
"version": "7.0.8",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.8.tgz",
"integrity": "sha512-YSBPTLTVm2e2OoQIDYx8HaeWJ5tTToLH67kXR7zYNGupXMEHa2++G8k+DczX2cFVgalypqtyZIcU19AFcmOpmg=="
"version": "7.0.9",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
"integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ=="
},
"@types/minimatch": {
"version": "3.0.5",
@@ -15687,6 +15775,32 @@
"uri-js": "^4.2.2"
}
},
"ajv-formats": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
"integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
"requires": {
"ajv": "^8.0.0"
},
"dependencies": {
"ajv": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
"integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
"requires": {
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
}
}
},
"ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
@@ -15718,10 +15832,10 @@
}
}
},
"ansi-html": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.7.tgz",
"integrity": "sha1-gTWEAhliqenm/QOflA0S9WynhZ4="
"ansi-html-community": {
"version": "0.0.8",
"resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
"integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw=="
},
"ansi-regex": {
"version": "4.1.0",
@@ -17210,6 +17324,11 @@
"execa": "^5.0.0"
}
},
"define-lazy-prop": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
"integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og=="
},
"define-properties": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
@@ -18881,6 +19000,14 @@
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
},
"has-tostringtag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
"requires": {
"has-symbols": "^1.0.2"
}
},
"has-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
@@ -19637,11 +19764,12 @@
}
},
"is-arguments": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.0.tgz",
"integrity": "sha512-1Ij4lOMPl/xB5kBDn7I+b2ttPMKa8szhEIrXDuXQD/oe3HJLTLhqhgGspwgyGd6MOywBUqVvYicF72lkgDnIHg==",
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
"integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
"requires": {
"call-bind": "^1.0.0"
"call-bind": "^1.0.2",
"has-tostringtag": "^1.0.0"
}
},
"is-arrayish": {
@@ -20041,11 +20169,6 @@
"resolved": "https://registry.npmjs.org/junk/-/junk-3.1.0.tgz",
"integrity": "sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ=="
},
"killable": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
"integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg=="
},
"kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
@@ -20075,9 +20198,9 @@
}
},
"laravel-mix": {
"version": "6.0.25",
"resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-6.0.25.tgz",
"integrity": "sha512-SDpLGUnXJ8g0rvtiLljSTJSR6awj86M2Jd3MhbtT32TCgwXdtajVLF7Mv2blsPLixGHtynwZgi+UFlYQbquPLg==",
"version": "6.0.30",
"resolved": "https://registry.npmjs.org/laravel-mix/-/laravel-mix-6.0.30.tgz",
"integrity": "sha512-Y5EjdPVEqVMgnglzJvDuDEpUa2EouutS4ySrukZkBWh2EPPYM1iszu8TItvQ2J08N5BPIrYWh8McUbTwq6tcrQ==",
"requires": {
"@babel/core": "^7.14.5",
"@babel/plugin-proposal-object-rest-spread": "^7.14.5",
@@ -20124,7 +20247,7 @@
"vue-style-loader": "^4.1.3",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.2",
"webpack-dev-server": "4.0.0-beta.3",
"webpack-dev-server": "4.1.1",
"webpack-merge": "^5.8.0",
"webpack-notifier": "^1.13.0",
"webpackbar": "^5.0.0-3",
@@ -20152,9 +20275,9 @@
"requires": {}
},
"ansi-regex": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ=="
},
"ansi-styles": {
"version": "4.3.0",
@@ -20222,11 +20345,11 @@
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="
},
"http-proxy-middleware": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz",
"integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==",
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.3.tgz",
"integrity": "sha512-1bloEwnrHMnCoO/Gcwbz7eSVvW50KPES01PecpagI+YLNLci4AcuKJrujW4Mc3sBLpFxMSlsLNHS5Nl/lvrTPA==",
"requires": {
"@types/http-proxy": "^1.17.5",
"@types/http-proxy": "^1.17.8",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
@@ -20275,12 +20398,13 @@
}
},
"open": {
"version": "7.4.2",
"resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
"integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
"version": "8.4.0",
"resolved": "https://registry.npmjs.org/open/-/open-8.4.0.tgz",
"integrity": "sha512-XgFPPM+B28FtCCgSb9I+s9szOC1vZRSwgWsRUA5ylIxRTgKozqjOCrVOqGsYABPYK5qnfqClxZTFBa8PKt2v6Q==",
"requires": {
"is-docker": "^2.0.0",
"is-wsl": "^2.1.1"
"define-lazy-prop": "^2.0.0",
"is-docker": "^2.1.1",
"is-wsl": "^2.2.0"
}
},
"p-limit": {
@@ -20349,11 +20473,11 @@
}
},
"strip-ansi": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"requires": {
"ansi-regex": "^5.0.0"
"ansi-regex": "^5.0.1"
}
},
"supports-color": {
@@ -20393,43 +20517,56 @@
}
},
"webpack-dev-server": {
"version": "4.0.0-beta.3",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.0.0-beta.3.tgz",
"integrity": "sha512-Ud7ieH15No/KiSdRuzk+2k+S4gSCR/N7m4hJhesDbKQEZy3P+NPXTXfsimNOZvbVX2TRuIEFB+VdLZFn8DwGwg==",
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.1.1.tgz",
"integrity": "sha512-Kl1mnCEw8Cy1Kw173gCxLIB242LfPKEOj9WoKhKz/MbryZTNrILzOJTk8kiczw/YUEPzn3gcltCQv6hDsLudRg==",
"requires": {
"ansi-html": "^0.0.7",
"ansi-html-community": "^0.0.8",
"bonjour": "^3.5.0",
"chokidar": "^3.5.1",
"colorette": "^1.2.2",
"compression": "^1.7.4",
"connect-history-api-fallback": "^1.6.0",
"del": "^6.0.0",
"express": "^4.17.1",
"find-cache-dir": "^3.3.1",
"graceful-fs": "^4.2.6",
"html-entities": "^2.3.2",
"http-proxy-middleware": "^1.3.1",
"http-proxy-middleware": "^2.0.0",
"internal-ip": "^6.2.0",
"ipaddr.js": "^2.0.0",
"is-absolute-url": "^3.0.3",
"killable": "^1.0.1",
"open": "^7.4.2",
"ipaddr.js": "^2.0.1",
"open": "^8.0.9",
"p-retry": "^4.5.0",
"portfinder": "^1.0.28",
"schema-utils": "^3.0.0",
"schema-utils": "^3.1.0",
"selfsigned": "^1.10.11",
"serve-index": "^1.9.1",
"sockjs": "^0.3.21",
"spdy": "^4.0.2",
"strip-ansi": "^6.0.0",
"strip-ansi": "^7.0.0",
"url": "^0.11.0",
"webpack-dev-middleware": "^4.1.0",
"ws": "^7.4.5"
"webpack-dev-middleware": "^5.0.0",
"ws": "^8.1.0"
},
"dependencies": {
"ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA=="
},
"strip-ansi": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.0.1.tgz",
"integrity": "sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw==",
"requires": {
"ansi-regex": "^6.0.1"
}
}
}
},
"ws": {
"version": "7.5.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
"version": "8.5.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz",
"integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==",
"requires": {}
}
}
@@ -20605,14 +20742,6 @@
}
}
},
"map-age-cleaner": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
"requires": {
"p-defer": "^1.0.0"
}
},
"map-cache": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
@@ -20667,26 +20796,10 @@
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
},
"mem": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz",
"integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==",
"requires": {
"map-age-cleaner": "^0.1.3",
"mimic-fn": "^3.1.0"
},
"dependencies": {
"mimic-fn": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz",
"integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ=="
}
}
},
"memfs": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.2.2.tgz",
"integrity": "sha512-RE0CwmIM3CEvpcdK3rZ19BC4E6hv9kADkMN5rPduRak58cNArWLi/9jFLsa4rhsjfVxMP3v0jO7FHXq7SvFY5Q==",
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/memfs/-/memfs-3.4.1.tgz",
"integrity": "sha512-1c9VPVvW5P7I85c35zAdEr1TD5+F11IToIHIlrVIcflfnzPkJa0ZoYEoEdYDP8KgPFoSZ/opDrUsAoZWym3mtw==",
"requires": {
"fs-monkey": "1.0.3"
}
@@ -21405,11 +21518,6 @@
"integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=",
"dev": true
},
"p-defer": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
},
"p-event": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/p-event/-/p-event-4.2.0.tgz",
@@ -22695,6 +22803,11 @@
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
},
"require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
},
"require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -22924,9 +23037,9 @@
"integrity": "sha512-1JeB87s6oN/TDxQQYCvS5EFoQyvV6eYMZZ0AeA4tdFDYWN3BAGZ8npr17UBFddU0lgAt3H0yjX3X6/ekOj1yjw=="
},
"selfsigned": {
"version": "1.10.11",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
"integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
"version": "1.10.14",
"resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.14.tgz",
"integrity": "sha512-lkjaiAye+wBZDCBsu5BGi0XiLRxeUlsGod5ZP924CRSEoGuZAw/f7y9RKu28rwTfiHVhdavhB0qH0INV6P1lEA==",
"requires": {
"node-forge": "^0.10.0"
}
@@ -24577,26 +24690,55 @@
}
},
"webpack-dev-middleware": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-4.3.0.tgz",
"integrity": "sha512-PjwyVY95/bhBh6VUqt6z4THplYcsvQ8YNNBTBM873xLVmw8FLeALn0qurHbs9EmcfhzQis/eoqypSnZeuUz26w==",
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.1.tgz",
"integrity": "sha512-81EujCKkyles2wphtdrnPg/QqegC/AtqNH//mQkBYSMqwFVCQrxM6ktB2O/SPlZy7LqeEfTbV3cZARGQz6umhg==",
"requires": {
"colorette": "^1.2.2",
"mem": "^8.1.1",
"memfs": "^3.2.2",
"mime-types": "^2.1.30",
"colorette": "^2.0.10",
"memfs": "^3.4.1",
"mime-types": "^2.1.31",
"range-parser": "^1.2.1",
"schema-utils": "^3.0.0"
"schema-utils": "^4.0.0"
},
"dependencies": {
"schema-utils": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.1.1.tgz",
"integrity": "sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw==",
"ajv": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.10.0.tgz",
"integrity": "sha512-bzqAEZOjkrUMl2afH8dknrq5KEk2SrwdBROR+vH1EKVQTqaUbJVPdc/gEdggTMM0Se+s+Ja4ju4TlNcStKl2Hw==",
"requires": {
"@types/json-schema": "^7.0.8",
"ajv": "^6.12.5",
"ajv-keywords": "^3.5.2"
"fast-deep-equal": "^3.1.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2",
"uri-js": "^4.2.2"
}
},
"ajv-keywords": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
"integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"requires": {
"fast-deep-equal": "^3.1.3"
}
},
"colorette": {
"version": "2.0.16",
"resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.16.tgz",
"integrity": "sha512-hUewv7oMjCp+wkBv5Rm0v87eJhq4woh5rSR+42YSQJKecCqgIqNkZ6lAlQms/BwHPJA5NKMRlpxPRv0n8HQW6g=="
},
"json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"schema-utils": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.0.0.tgz",
"integrity": "sha512-1edyXKgh6XnJsJSQ8mKWXnN/BVaIbFMLpouRUrXgVq7WYne5kw3MW7UPhO44uRXQSIpTSXoJbmrR2X0w9kUTyg==",
"requires": {
"@types/json-schema": "^7.0.9",
"ajv": "^8.8.0",
"ajv-formats": "^2.1.1",
"ajv-keywords": "^5.0.0"
}
}
}

View File

@@ -27,7 +27,7 @@
"jquery": "^3.5.1",
"jquery-pjax": "~2.0",
"js-yaml": "^3.14.0",
"laravel-mix": "^6.0.25",
"laravel-mix": "^6.0.30",
"leaflet": "^1.3.4",
"leaflet-ajax": "2.1.0",
"leaflet-providers": "1.0.*",

View File

@@ -22,7 +22,7 @@ return [
'fieldsreadonly' => 'Una vez que se ha enviado un PIREP, ciertos campos pasan al modo de solo lectura.',
'flightinformations' => 'Información de vuelo',
'flightident' => 'Vuelo Número/Código/Etapa',
'block_fuel' => 'Bloque de Combustible',
'block_fuel' => 'Combustible en calzos',
'fuel_used' => 'Combustible Usado',
'codeoptional' => 'Código (opcional)',
'legoptional' => 'Etapa (opcional)',

View File

@@ -0,0 +1,12 @@
<?php
return [
'status' => [
'active' => 'Actif',
'maintenance' => 'Maintenance',
'stored' => 'Stocké',
'retired' => 'Retiré',
'scrapped' => 'Démantelé',
'written' => 'Désaffecté',
],
];

View File

@@ -0,0 +1,9 @@
<?php
return [
'ident' => 'Identification',
'home' => 'Aéroport d\'Attache',
'current' => 'Aéroport Actuel',
'departure' => 'Aéroport de Départ',
'arrival' => 'Aéroport d\'Arrivée',
];

View File

@@ -0,0 +1,24 @@
<?php
return [
'failed' => 'Ces informations d\'identification ne correspondent pas.',
'throttle' => 'Trop de tentatives de connexion. Veuillez réessayer dans :seconds secondes.',
'password' => 'Mot de Passe',
'createaccount' => 'Créer un Compte',
'forgotpassword' => 'Mot de Passe Oublié',
'fullname' => 'Nom Complet',
'emailaddress' => 'Adresse Email',
'fillcaptcha' => 'Remplissez le captcha',
'tocaccept' => 'En vous inscrivant, vous accezptez les Conditions Générales d\'Utilisations.',
'register' => 'S\'inscrire',
'registrationpending' => 'Inscription en attente',
'pendingmessage' => 'Votre inscription est en attente d\'approbation. Veuillez vérifier vos emails!',
'registrationsubmitted' => 'Inscription Soumise',
'registrationconfirmation' => 'Confirmation d\'inscription',
'confirmationmessage' => 'Votre demande a été soumise. Elle nécessite l\'approbation d\'un administrateur. Une fois qu\'un administrateur aura examiné votre demande, vous recevrez un email de confirmation.',
'registrationdenied' => 'Inscription Refusée',
'deniedmessage' => 'Votre inscription a été refusée. Veuillez contacter un administrateur.',
'accountsuspended' => 'Compte suspendu',
'suspendedmessage' => 'Votre compte a été suspendu. Veuillez contacter un administrateur.',
'transferhours' => 'Heures transférées',
];

View File

@@ -0,0 +1,62 @@
<?php
return [
'dashboard' => 'Tableau de bord',
'administration' => 'Administration',
'flight' => 'Vol|Vols',
'livemap' => 'Carte des vols',
'pilot' => 'Pilote|Pilotes',
'pirep' => 'PIREP|PIREPs',
'newestpilots' => 'Nouveaux Pilotes',
'profile' => 'Profil',
'email' => 'Email',
'pilot_id' => 'Pilote ID',
'register' => 'S\'inscrire',
'login' => 'Se connecter',
'logout' => 'Se déconnecter',
'timezone' => 'Fuseau horraire',
'country' => 'Pays',
'download' => 'Téléchargement|Téléchargements',
'from' => 'Depuis',
'to' => 'Vers',
'state' => 'Etat',
'status' => 'Statut',
'departure' => 'Départ',
'arrival' => 'Arrivée',
'aircraft' => 'Avion',
'airline' => 'Compagnie',
'subfleet' => 'Sous-Flotte',
'distance' => 'Distance',
'fuel' => 'Carburant',
'metar' => 'METAR',
'hour' => 'Heure|Heures',
'minute' => 'Minute|Minutes',
'note' => 'Note|Notes',
'field' => 'Champ|Champs',
'name' => 'Nom',
'value' => 'Valeur|Valeurs',
'remark' => 'Remarque|Remarques',
'find' => 'Rechercher',
'reset' => 'Réinitialiser',
'submit' => 'Envoyer',
'edit' => 'Editer',
'close' => 'Fermer',
'whoops' => 'Whoops',
'hello' => 'Bonjour',
'regards' => 'Cordialement',
'rightsreserved' => 'Tous droits réservés',
'active' => 'Actif',
'inactive' => 'Inactif',
'yes' => 'Oui',
'no' => 'Non',
'or' => 'ou',
'days' => [
'mon' => 'Lundi',
'tues' => 'Mardi',
'wed' => 'Mercredi',
'thurs' => 'Jeudi',
'fri' => 'Vendredi',
'sat' => 'Samedi',
'sun' => 'Dimanche',
],
];

View File

@@ -0,0 +1,11 @@
<?php
return [
'totalhours' => 'Heures Totales',
'yourbalance' => 'Votre Solde',
'yourlastreport' => 'Votre dernier Rapport',
'noreportsyet' => 'Aucun Rapport',
'fileonenow' => 'Créez en un maintenant',
'weatherat' => 'Météo à :ICAO',
'recentreports' => 'Rapports Récents',
];

View File

@@ -0,0 +1,5 @@
<?php
return [
'none' => 'Aucun téléchargement!',
];

View File

@@ -0,0 +1,5 @@
<?php
return [
'buttontroubles' => 'Si vous avez des difficultés à cliquer sur le bouton ":actiontext", copiez et collez cette URL ci-dessous dans votre navigateur web:',
];

View File

@@ -0,0 +1,16 @@
<?php
return [
401 => [
'title' => 'Accès Non Autorisé',
'message' => 'Embarrassant, vous n\'êtes pas autorisé à accéder à cette page ou à exécuter cette fonction. Cliquez <a href=":link">ici</a> pour revenir à la page d\'accueil.',
],
404 => [
'title' => 'Page Non Trouvée',
'message' => 'Embarrassant, la page demandée n\'existe pas. Cliquez <a href=":link">ici</a> pour revenir à la page accueil.',
],
503 => [
'title' => 'Erreur Interne',
'message' => 'Une Erreur s\'est Produite',
],
];

View File

@@ -0,0 +1,9 @@
<?php
return [
'type' => [
'flight' => 'Vol',
'daily' => 'Quotidien',
'monthly' => 'Mensuel',
],
];

View File

@@ -0,0 +1,42 @@
<?php
return [
'flightnumber' => 'Numéro de Vol',
'flighttime' => 'Temps de Vol',
'flighttype' => 'Type de Vol',
'flighthours' => 'Heures de Vol',
'code' => 'Code',
'callsign' => 'Callsign',
'route' => 'Route',
'mybid' => 'Mes réservations',
'search' => 'Rechercher',
'addremovebid' => 'Ajouter/Supprimer une Réservation',
'bidremoved' => 'Votre réservation a été supprimée.',
'bidadded' => 'Votre réservation a été ajoutée.',
'dep' => 'Dép',
'arr' => 'Arr',
'level' => 'Niveau',
'alternateairport' => 'Aéroport Alternatif',
'inbound' => 'Vols à l\'arrivée',
'outbound' => 'Vols au départ',
'none' => 'Auncun vols trouvé.',
'departuretime' => 'Heure de Départ',
'arrivaltime' => 'Heure d\'Arrivée',
'type' => [
'pass_scheduled' => 'Passager (Prévu)',
'pass_addtl' => 'Passager (Additionnel)',
'charter_pass_only' => 'Passager (Charter)',
'charter_special' => 'Passager (Charter Spécial)',
'cargo_scheduled' => 'Cargo (Prévu)',
'addtl_cargo_mail' => 'Cargo (Additionnel)',
'charter_cargo' => 'Cargo (Charter)',
'mail_service' => 'Service Postal',
'special_vip' => 'Vol VIP',
'ambulance' => 'Ambulance',
'training_flight' => 'Entrainement',
'military' => 'Militaire',
'positioning' => 'Repositionement',
'technical_test' => 'Test Technique',
'technical_stop' => 'Arrêt Technique',
],
];

View File

@@ -0,0 +1,8 @@
<?php
return [
'welcome' => [
'title' => 'Bienvenue!',
'message' => 'Bienvenue chez :appname',
],
];

View File

@@ -0,0 +1,245 @@
<?php
return [
/*
*
* Shared translations.
*
*/
'title' => 'phpVMS Installateur',
'next' => 'Etape suivante',
'back' => 'Etape Précédente',
'finish' => 'Installation',
'forms' => [
'errorTitle' => 'Les erreurs suivantes se sont produites:',
],
/*
*
* Home page translations.
*
*/
'welcome' => [
'templateTitle' => 'Bienvenue',
'title' => 'phpVMS Installateur',
'message' => 'Assistant installation.',
'next' => 'Vérifier les exigences',
],
/*
*
* Requirements page translations.
*
*/
'requirements' => [
'templateTitle' => 'Step 1 | Exigences du serveur',
'title' => 'Exigences du serveur',
'next' => 'Vérifier les permissions',
],
/*
*
* Permissions page translations.
*
*/
'permissions' => [
'templateTitle' => 'Step 2 | Permissions',
'title' => 'Permissions',
'next' => 'Configurer environnement',
],
/*
*
* Environment page translations.
*
*/
'environment' => [
'menu' => [
'templateTitle' => 'Step 3 | Paramétrage environnement',
'title' => 'Paramétrage environnement',
'desc' => 'Veuillez choisir comment vous voulez configurer le fichier <code>.env</code> application.',
'wizard-button' => 'Configuration assistant de formulaire',
'classic-button' => 'Éditeur de texte classique',
],
'wizard' => [
'templateTitle' => 'Step 3 | Paramètres environnement | Assistant guide',
'title' => 'Guide <code>.env</code> Assistant',
'tabs' => [
'environment' => 'Environnement',
'database' => 'Database',
'application' => 'Application',
],
'form' => [
'name_required' => 'Un nom environnement est requis.',
'app_name_label' => 'App Nom',
'app_name_placeholder' => 'App Nom',
'app_environment_label' => 'App Environnement',
'app_environment_label_local' => 'Local',
'app_environment_label_developement' => 'Développement',
'app_environment_label_qa' => 'Qa',
'app_environment_label_production' => 'Production',
'app_environment_label_other' => 'Autre',
'app_environment_placeholder_other' => 'Entrez votre environnement...',
'app_debug_label' => 'App Debug',
'app_debug_label_true' => 'True',
'app_debug_label_false' => 'False',
'app_log_level_label' => 'App Log Level',
'app_log_level_label_debug' => 'debug',
'app_log_level_label_info' => 'info',
'app_log_level_label_notice' => 'notice',
'app_log_level_label_warning' => 'warning',
'app_log_level_label_error' => 'error',
'app_log_level_label_critical' => 'critical',
'app_log_level_label_alert' => 'alert',
'app_log_level_label_emergency' => 'emergency',
'app_url_label' => 'App Url',
'app_url_placeholder' => 'App Url',
'db_connection_label' => 'Connexion à la base de données',
'db_connection_label_mysql' => 'mysql',
'db_connection_label_sqlite' => 'sqlite',
'db_connection_label_pgsql' => 'pgsql',
'db_connection_label_sqlsrv' => 'sqlsrv',
'db_host_label' => 'Database Host',
'db_host_placeholder' => 'Database Host',
'db_port_label' => 'Database Port',
'db_port_placeholder' => 'Database Port',
'db_name_label' => 'Database Name',
'db_name_placeholder' => 'Database Name',
'db_username_label' => 'Database User Name',
'db_username_placeholder' => 'Database User Name',
'db_password_label' => 'Database Password',
'db_password_placeholder' => 'Database Password',
'app_tabs' => [
'more_info' => 'More Info',
'broadcasting_title' => 'Broadcasting, Caching, Session, &amp; Queue',
'broadcasting_label' => 'Broadcast Driver',
'broadcasting_placeholder' => 'Broadcast Driver',
'cache_label' => 'Cache Driver',
'cache_placeholder' => 'Cache Driver',
'session_label' => 'Session Driver',
'session_placeholder' => 'Session Driver',
'queue_label' => 'Queue Driver',
'queue_placeholder' => 'Queue Driver',
'redis_label' => 'Redis Driver',
'redis_host' => 'Redis Host',
'redis_password' => 'Redis Password',
'redis_port' => 'Redis Port',
'mail_label' => 'Mail',
'mail_driver_label' => 'Mail Driver',
'mail_driver_placeholder' => 'Mail Driver',
'mail_host_label' => 'Mail Host',
'mail_host_placeholder' => 'Mail Host',
'mail_port_label' => 'Mail Port',
'mail_port_placeholder' => 'Mail Port',
'mail_username_label' => 'Mail Username',
'mail_username_placeholder' => 'Mail Username',
'mail_password_label' => 'Mail Password',
'mail_password_placeholder' => 'Mail Password',
'mail_encryption_label' => 'Mail Encryption',
'mail_encryption_placeholder' => 'Mail Encryption',
'pusher_label' => 'Pusher',
'pusher_app_id_label' => 'Pusher App Id',
'pusher_app_id_palceholder' => 'Pusher App Id',
'pusher_app_key_label' => 'Pusher App Key',
'pusher_app_key_palceholder' => 'Pusher App Key',
'pusher_app_secret_label' => 'Pusher App Secret',
'pusher_app_secret_palceholder' => 'Pusher App Secret',
],
'buttons' => [
'setup_database' => 'Configuration de la base de données',
'setup_application' => 'Configuration application',
'install' => 'Installation',
],
],
],
'classic' => [
'templateTitle' => 'Step 3 | Paramètres environnement | Éditeur classique',
'title' => 'Éditeur environnement classique',
'save' => 'Savegarde .env',
'back' => 'Utiliser assistant de formulaire',
'install' => 'Savegarder et Installer',
],
'success' => 'Les paramètres de votre fichier .env ont été enregistrés.',
'errors' => 'Impossible enregistrer le fichier .env, veuillez le créer manuellement.',
],
'install' => 'Installation',
/*
*
* Installed Log translations.
*
*/
'installed' => [
'success_log_message' => 'Laravel Installer a été installé avec succès sur ',
],
/*
*
* Final page translations.
*
*/
'final' => [
'title' => 'Installation terminée',
'templateTitle' => 'Installation terminée',
'finished' => 'Cette application a été installée avec succès.',
'migration' => 'Migration &amp; Sortie de la console amorçage:',
'console' => 'Sortie de la console application:',
'log' => 'Entrée du journal installation :',
'env' => 'Final .env File:',
'exit' => 'Cliquez ici pour sortir',
],
/*
*
* Update specific translations
*
*/
'updater' => [
/*
*
* Shared translations.
*
*/
'title' => 'Laravel Updater',
/*
*
* Welcome page translations for update feature.
*
*/
'welcome' => [
'title' => 'Bienvenue dans assistant de mise à jour',
'message' => 'Bienvenue dans assistant de mise à jour.',
],
/*
*
* Welcome page translations for update feature.
*
*/
'overview' => [
'title' => 'Vue ensemble',
'message' => 'Il y a 1 mise à jour.|Il y a :number de mises à jour.',
'install_updates' => 'Installer les mises à jour',
],
/*
*
* Final page translations.
*
*/
'final' => [
'title' => 'Terminé',
'finished' => 'La base de données application a été mise à jour avec succès.',
'exit' => 'Cliquez ici pour quitter',
],
'log' => [
'success_message' => 'Laravel Installer a été mis à jour avec succès sur ',
],
],
];

View File

@@ -0,0 +1,18 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Pagination Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are used by the paginator library to build
| the simple pagination links. You are free to change them to anything
| you want to customize your views to better match your application.
|
*/
'previous' => '&laquo; Précédent',
'next' => 'Suivant &raquo;',
];

View File

@@ -0,0 +1,21 @@
<?php
return [
/*
|--------------------------------------------------------------------------
| Password Reset Language Lines
|--------------------------------------------------------------------------
|
| The following language lines are the default lines which match reasons
| that are given by the password broker for a password update attempt
| has failed, such as for an invalid token or invalid new password.
|
*/
'password' => 'Les mots de passe doivent comporter au moins six caractères et correspondre à la confirmation.',
'reset' => 'Votre mot de passe a été réinitialisé!',
'sent' => 'Nous vous avons envoyé par email votre lien de réinitialisation de mot de passe!',
'token' => 'Ce jeton de réinitialisation de mot de passe est invalide.',
'user' => 'Nous ne trouvons pas d\'utilisateurs avec cette adresse email.',
'confirm' => 'Confirmer votre mot de passe.',
];

View File

@@ -0,0 +1,72 @@
<?php
return [
'newflightreport' => 'Nouveau Rapport de vol',
'editflightreport' => 'Editer le Rapport de vol',
'savepirep' => 'Sauvegarder le PIREP',
'submitpirep' => 'Envoyer le PIREP',
'fileflightreport' => 'Remplir un Nouveau Rapport',
'filenewpirep' => 'Remplir un Nouveau PIREP',
'newpirep' => 'Nouveau PIREP',
'pilotreport' => 'Rapport des Pilotes|Rapports des Pilotes',
'arrived' => 'Arrivé',
'source' => 'Source',
'flightlog' => 'Carnet de vol',
'filedroute' => 'Route Déposée',
'filedon' => 'Déposé le',
'fare' => 'Tarif|Tarifs',
'class' => 'Classe',
'count' => 'Comte',
'flighttime' => 'Temps de vol',
'flightlevel' => 'Niveau de vol',
'fieldsreadonly' => 'Une fois qu\'un PIREP est envoyé, certains champs passent en lecture seul.',
'flightinformations' => 'Informations du vol',
'flightident' => 'Numéro/Code/Etape du vol',
'block_fuel' => 'Carburant emporté',
'fuel_used' => 'Carburant utilisé',
'codeoptional' => 'Code (optionnel)',
'legoptional' => 'Etape (optionnel)',
'deparrinformations' => 'Information sur le Départ/l\'Arrivée',
'aircraftinformations' => 'Information sur l\'Avion',
'dateflown' => 'Date du vol',
'deletepirep' => 'Supprimer le PIREP',
'submitted' => 'Envoyé',
'source_types' => [
'manual' => 'Manuel',
'acars' => 'ACARS',
],
'state' => [
'accepted' => 'Accepté',
'pending' => 'En attente de validation',
'rejected' => 'Rejeté',
'in_progress' => 'En Cours',
'cancelled' => 'Annulé',
'deleted' => 'Supprimé',
'draft' => 'Brouillon',
'paused' => 'En Pause',
],
'status' => [
'initialized' => 'Initié',
'scheduled' => 'Planifé',
'boarding' => 'Embarquement',
'ready_start' => 'Prêt pour le démarrage',
'push_tow' => 'Repoussage/Remorquage',
'departed' => 'Parti',
'ready_deice' => 'Prêt pour le dégivrage',
'deicing' => 'Dégivrage en cours',
'ground_ret' => 'Retour au sol',
'taxi' => 'Roulage',
'takeoff' => 'Décolalge',
'initial_clb' => 'Montée initiale',
'enroute' => 'En Route',
'diverted' => 'Dérouté',
'approach' => 'Approche',
'final_appr' => 'Approche Finale',
'landing' => 'Atterrissage',
'landed' => 'Atterrit',
'arrived' => 'Arrivé',
'cancelled' => 'Annulé',
'emerg_decent' => 'Descente d\'Urgence',
'paused' => 'En pause',
],
];

View File

@@ -0,0 +1,20 @@
<?php
return [
'avatarresize' => 'Cette avatar sera redimensionné en :width x :height pixels',
'newapikey' => 'Nouvelle clé d\'API',
'your-profile' => 'Mon Profil',
'your-awards' => 'Mes Distinctions',
'apikey' => 'Clé d\'API',
'apikey-show' => 'Afficher la clé',
'dontshare' => 'Ne pas partager!',
'changepassword' => 'Changer le mot de passe',
'newpassword' => 'Nouveau mot de passe',
'avatar' => 'Avatar',
'updateprofile' => 'Modifier le Profil',
'editprofile' => 'Editer le Profil',
'edityourprofile' => 'Editer mon Profil',
'transferhours' => 'Heures Transférées',
'opt-in' => 'Opt-In',
'opt-in-descrip' => 'Oui, incluez-moi dans les emails non administratifs.',
];

View File

@@ -0,0 +1,5 @@
<?php
return [
'title' => 'Conditions Générales d\'Utilisations',
];

View File

@@ -0,0 +1,13 @@
<?php
return [
'location' => 'Localisation',
'state' => [
'pending' => 'En attente',
'active' => 'Actif',
'rejected' => 'Rejeté',
'on_leave' => 'En vacances',
'suspended' => 'Suspendu',
'deleted' => 'Supprimé',
],
];

View File

@@ -0,0 +1,119 @@
<?php
return [
/*
* Validation Language Lines
*/
'accepted' => 'The :attribute must be accepted.',
'active_url' => 'The :attribute is not a valid URL.',
'after' => 'The :attribute must be a date after :date.',
'alpha' => 'The :attribute may only contain letters.',
'alpha_dash' => 'The :attribute may only contain letters, numbers, and dashes.',
'alpha_num' => 'The :attribute may only contain letters and numbers.',
'array' => 'The :attribute must be an array.',
'before' => 'The :attribute must be a date before :date.',
'between' => [
'numeric' => 'The :attribute must be between :min and :max.',
'file' => 'The :attribute must be between :min and :max kilobytes.',
'string' => 'The :attribute must be between :min and :max characters.',
'array' => 'The :attribute must have between :min and :max items.',
],
'boolean' => 'The :attribute field must be true or false.',
'confirmed' => 'The :attribute confirmation does not match.',
'date' => 'The :attribute is not a valid date.',
'date_format' => 'The :attribute does not match the format :format.',
'different' => 'The :attribute and :other must be different.',
'digits' => 'The :attribute must be :digits digits.',
'digits_between' => 'The :attribute must be between :min and :max digits.',
'dimensions' => 'The :attribute has invalid image dimensions.',
'distinct' => 'The :attribute field has a duplicate value.',
'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" 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.',
'integer' => 'The :attribute must be an integer.',
'ip' => 'The :attribute must be a valid IP address.',
'json' => 'The :attribute must be a valid JSON string.',
'max' => [
'numeric' => 'The :attribute may not be greater than :max.',
'file' => 'The :attribute may not be greater than :max kilobytes.',
'string' => 'The :attribute may not be greater than :max characters.',
'array' => 'The :attribute may not have more than :max items.',
],
'mimes' => 'The :attribute must be a file of type: :values.',
'min' => [
'numeric' => 'The :attribute must be at least :min.',
'file' => 'The :attribute must be at least :min kilobytes.',
'string' => 'The :attribute must be at least :min characters.',
'array' => 'The :attribute must have at least :min items.',
],
'not_in' => 'The selected :attribute is invalid.',
'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_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.',
'required_with_all' => 'The :attribute field is required when :values is present.',
'required_without' => 'The :attribute field is required when :values is not present.',
'required_without_all' => 'The :attribute field is required when none of :values are present.',
'same' => 'The :attribute and :other must match.',
'size' => [
'numeric' => 'The :attribute must be :size.',
'file' => 'The :attribute must be :size kilobytes.',
'string' => 'The :attribute must be :size characters.',
'array' => 'The :attribute must contain :size items.',
],
'string' => 'The :attribute must be a string.',
'timezone' => 'The :attribute must be a valid zone.',
'unique' => 'The :attribute has already been taken.',
'url' => 'The :attribute format is invalid.',
/*
* Custom Validation Language Lines
*/
'custom' => [
'airline_id' => [
'required' => 'Une Compagnie est requise',
'exists' => 'Cette compagnie existe pas',
],
'aircraft_id' => [
'required' => 'Un Avion est requis',
'exists' => 'Cet Avion existe pas',
],
'arr_airport_id' => [
'required' => 'Un Aéroprt arrivée est requis',
],
'dpt_airport_id' => [
'required' => 'Un Aéroprt de départ est requis',
],
'flight_time' => [
'required' => 'Le temps de vol, en minutes, est requis',
'integer' => 'Le temps de vol, en minutes, est requis',
],
'planned_flight_time' => [
'required' => 'Le temps de vol, en minutes, est requis',
'integer' => 'Le temps de vol, en minutes, est requis',
],
'source_name' => [
'required' => 'La source de PIREP est requise',
],
'g-recaptcha-response' => [
'required' => 'Veuillez vérifier que vous êtes pas un robot.',
'captcha' => 'Erreur Captcha ! Essayez à nouveau plus tard ou contactez un administrateur du site.',
],
],
/*
* Custom Validation Attributes
*/
'attributes' => [],
];

View File

@@ -0,0 +1,34 @@
<?php
return [
'latestnews' => [
'news' => 'Actualités',
'nonewsfound' => 'Aucune actualité trouvée',
],
'livemap' => [
'groundspeed' => 'Vitesse Sol',
'altitude' => 'Altitude',
'heading' => 'Cap',
'distance' => 'Distance',
'noflights' => 'Il n\'y a pas de vols.',
'gs' => 'GS',
],
'weather' => [
'nometar' => 'METAR/TAF n\'ont pas pu être récupérés',
'conditions' => 'Conditions',
'visibility' => 'Visibilité',
'temp' => 'Température',
'humidity' => 'Humidité',
'dewpoint' => 'Point de rosée',
'barometer' => 'Baromètre',
'clouds' => 'Nuages',
'wind' => 'Vent',
'remarks' => 'Remarques',
'guststo' => 'Rafales à',
'updated' => 'Mis à jour il y a ',
'hrago' => 'heure|heures',
'minago' => 'minute|minutes',
],
];

View File

@@ -174,7 +174,6 @@
</div>
</div>
<div class="row">
<div class="col-12">
<div class="form-container">
@@ -260,8 +259,9 @@
<div class="row">
<div class="form-group col-sm-12">
{{ Form::textarea('notes', null, [
'class' => 'form-control input-text',
'style' => 'padding: 10px',
'id' => 'editor',
'class' => 'editor',
'style' => 'padding: 5px',
]) }}
<p class="text-danger">{{ $errors->first('notes') }}</p>
</div>
@@ -288,3 +288,10 @@
</div>
</div>
</div>
@section('scripts')
@parent
<script src="{{ public_asset('assets/vendor/ckeditor4/ckeditor.js') }}"></script>
<script>
$(document).ready(function () { CKEDITOR.replace('editor'); });
</script>
@endsection

View File

@@ -5,19 +5,16 @@
{{ Form::number('pilot_id', null, ['class' => 'form-control']) }}
<p class="text-danger">{{ $errors->first('pilot_id') }}</p>
</div>
<div class="form-group col-sm-3">
{{ Form::label('name', 'Name:') }}
{{ Form::text('name', null, ['class' => 'form-control', 'autocomplete' => 'off']) }}
<p class="text-danger">{{ $errors->first('name') }}</p>
</div>
<div class="form-group col-sm-3">
{{ Form::label('email', 'Email:') }}
{{ Form::text('email', null, ['class' => 'form-control', 'autocomplete' => 'off']) }}
<p class="text-danger">{{ $errors->first('email') }}</p>
</div>
<div class="form-group col-sm-3">
{{ Form::label('password', 'Password:') }}
{{ Form::password('password', ['class' => 'form-control', 'autocomplete' => 'off']) }}
@@ -52,7 +49,6 @@
{{ Form::select('curr_airport_id', $airports, null , ['class' => 'form-control select2']) }}
<p class="text-danger">{{ $errors->first('curr_airport_id') }}</p>
</div>
</div>
<div class="row">
@@ -60,12 +56,10 @@
{{ Form::label('airline_id', 'Airline:') }}
{{ Form::select('airline_id', $airlines, null, ['class' => 'form-control select2', 'placeholder' => 'Select Airline']) }}
</div>
<div class="form-group col-sm-4">
{{ Form::label('rank_id', 'Rank:') }}
{{ Form::select('rank_id', $ranks, null, ['class' => 'form-control select2', 'placeholder' => 'Select Rank']) }}
</div>
<div class="form-group col-sm-4">
{{ Form::label('roles', 'Roles:') }}
{{ Form::select('roles[]', $roles, $user->roles->pluck('id'),
@@ -74,17 +68,21 @@
</div>
<div class="row">
<div class="form-group col-sm-6">
<div class="form-group col-md-4">
{{ Form::label('state', 'State:') }}
<label class="checkbox-inline">
{{ Form::select('state', UserState::labels(), null, ['class' => 'form-control select2']) }}
</label>
{{-- <label class="checkbox-inline"> --}}
{{ Form::select('state', UserState::labels(), null, ['class' => 'form-control select2', 'style' => 'width: 100%;']) }}
{{-- </label> --}}
</div>
<div class="form-group col-md-8">
{{ Form::label('notes', 'Management Notes:') }}
{{ Form::textarea('notes', null, ['class' => 'form-control', 'rows' => 4, 'autocomplete' => 'off']) }}
</div>
</div>
<!-- Submit Field -->
<div class="form-group col-sm-6 text-right">
{{--<a href="{{ route('admin.users.regen_apikey', [$user->id]) }}" class="btn btn-warning"
onclick="return confirm('Are you sure? This will reset this user\'s API key.')">new api key</a>--}}
<div class="row">
<div class="form-group col-sm-12 text-right">
{{-- <a href="{{ route('admin.users.regen_apikey', [$user->id]) }}" class="btn btn-warning" onclick="return confirm('Are you sure? This will reset this user\'s API key.')">New API Key</a> --}}
&nbsp;
{{ Form::button('Save', ['type' => 'submit', 'class' => 'btn btn-success']) }}
<a href="{{ route('admin.users.index') }}" class="btn btn-default">Cancel</a>
@@ -95,10 +93,8 @@
<div class="form-group col-sm-12">
<table class="table table-hover">
<tr>
<td colspan="2">
<h5>User Details</h5>
</td>
</tr>
<td colspan="2"><h5>User Details</h5></td>
</tr>
<tr>
<td>Total Flights</td>
<td>{{ $user->flights }}</td>
@@ -127,14 +123,10 @@
<td>@lang('profile.opt-in')</td>
<td>{{ $user->opt_in ? __('common.yes') : __('common.no') }}</td>
</tr>
@if($user->fields)
<tr>
<td colspan="2">
<h5>Custom Fields</h5>
</td>
<td colspan="2"><h5>Custom Fields</h5></td>
</tr>
{{-- Custom Fields --}}
@foreach($user->fields as $field)
<tr>
@@ -145,4 +137,4 @@
@endif
</table>
</div>
</div>
</div>

Some files were not shown because too many files have changed in this diff Show More