diff --git a/.env.example b/.env.example
index 1b5466fe..296fbba7 100644
--- a/.env.example
+++ b/.env.example
@@ -23,6 +23,7 @@ DB_LOWER_STRING_LENGTH=false
BROADCAST_DRIVER=log
CACHE_DRIVER=file
+FILESYSTEM_DISK=local
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_CONNECTION=sync
@@ -91,3 +92,5 @@ IGNITION_EDITOR=vscode
IGNITION_THEME=auto
IGNITION_REMOTE_SITES_PATH=
IGNITION_LOCAL_SITES_PATH=
+
+FILAMENT_FILESYSTEM_DRIVER=public
diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php
index 0652bdb0..0dd4afc8 100644
--- a/app/Console/Kernel.php
+++ b/app/Console/Kernel.php
@@ -29,6 +29,8 @@ protected function schedule(Schedule $schedule)
$schedule->command('activitylog:clean')->daily();
+ $schedule->command('model:prune');
+
if (config('telescope.enabled')) {
$schedule->command('telescope:prune')->daily();
}
diff --git a/app/Events/FileCreated.php b/app/Events/FileCreated.php
new file mode 100644
index 00000000..015cb333
--- /dev/null
+++ b/app/Events/FileCreated.php
@@ -0,0 +1,39 @@
+ $record->icao,
+ 'IATA' => $record->iata,
+ ];
+ }
+
+ public static function form(Form $form): Form
+ {
+ return $form
+ ->schema([
+ Forms\Components\TextInput::make('icao')
+ ->label('ICAO')
+ ->required()
+ ->unique()
+ ->maxLength(255),
+ Forms\Components\TextInput::make('iata')
+ ->label('IATA')
+ ->required()
+ ->unique()
+ ->maxLength(255),
+ Forms\Components\TextInput::make('name')
+ ->required()
+ ->maxLength(255),
+ Forms\Components\TextInput::make('latitude'),
+ Forms\Components\TextInput::make('longitude'),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('icao')->label('ICAO')->sortable(),
+ Tables\Columns\TextColumn::make('iata')->label('IATA')->sortable(),
+ Tables\Columns\TextColumn::make('name')->sortable(),
+ ])
+ ->defaultSort('icao')
+ ->filters([
+ //
+ ])
+ ->pushHeaderActions([
+ ButtonAction::make('delete-unused-airports')
+ ->action(function () {
+ Airport::whereDoesntHave('flightsDep')
+ ->whereDoesntHave('flightsArr')
+ ->whereDoesntHave('eventDep')
+ ->whereDoesntHave('eventArr')
+ ->delete();
+ })
+ ->requiresConfirmation()
+ ->color('danger')
+ ->icon('heroicon-o-trash')
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ RelationManagers\LinksRelationManager::class,
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListAirports::route('/'),
+ 'create' => Pages\CreateAirport::route('/create'),
+ 'edit' => Pages\EditAirport::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/AirportResource/Pages/CreateAirport.php b/app/Filament/Resources/AirportResource/Pages/CreateAirport.php
new file mode 100644
index 00000000..416f41cc
--- /dev/null
+++ b/app/Filament/Resources/AirportResource/Pages/CreateAirport.php
@@ -0,0 +1,11 @@
+schema([
+ Forms\Components\Select::make('airportLinkType_id')
+ ->label('Type')
+ ->required()
+ ->options(AirportLinkType::all(['id', 'name'])->pluck('name', 'id')),
+ Forms\Components\TextInput::make('name')
+ ->helperText('If left empty, type will be used as name')
+ ->minLength(5)
+ ->maxLength(255),
+ Forms\Components\TextInput::make('url')
+ ->required()
+ ->url()
+ ->maxLength(255),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('type.name')->sortable(),
+ Tables\Columns\TextColumn::make('name')->sortable(),
+ Tables\Columns\TextColumn::make('url')->sortable(),
+ ])
+ ->filters([
+ //
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/EventResource.php b/app/Filament/Resources/EventResource.php
new file mode 100644
index 00000000..ce15e09f
--- /dev/null
+++ b/app/Filament/Resources/EventResource.php
@@ -0,0 +1,130 @@
+ $record->type->name,
+ 'Date' => $record->startEvent->format('M j, Y')
+ ];
+ }
+
+ protected static function getGlobalSearchEloquentQuery(): Builder
+ {
+ return parent::getGlobalSearchEloquentQuery()
+ ->orderBy('startEvent')
+ ->with(['type']);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('name'),
+ Tables\Columns\TextColumn::make('type.name'),
+ Tables\Columns\TextColumn::make('startEvent')
+ ->dateTime('M j, Y Hi\z')->sortable(),
+ ])->defaultSort('startEvent')
+ ->filters([
+ Filter::make('active')->query(fn (Builder $query): Builder => $query->where('endEvent', '>', now()))->default(),
+ Filter::make('expired')->query(fn (Builder $query): Builder => $query->where('endEvent', '<', now())),
+ SelectFilter::make('event_type_id')
+ ->label('Type')
+ ->options(ModelsEventType::all(['id', 'name'])->pluck('name', 'id')),
+ ])
+ ->prependActions([
+ ButtonAction::make('import-bookings')
+ ->url(fn (Event $record): string => route('filament.resources.events.import-bookings', $record))
+ ->icon('heroicon-o-upload')
+ ->visible(fn (Event $record): bool => auth()->user()->can('update', $record)),
+ ButtonAction::make('assign-routes')
+ ->url(fn (Event $record): string => route('filament.resources.events.assign-routes', $record))
+ ->icon('heroicon-o-upload')
+ ->visible(fn (Event $record): bool => auth()->user()->can('update', $record) && $record->event_type_id == EventType::MULTIFLIGHTS()->value),
+ ButtonAction::make('send-email')
+ ->url(fn (Event $record): string => route('filament.resources.events.send-email', $record))
+ ->icon('heroicon-o-mail'),
+ ButtonAction::make('export')
+ ->action(function (Event $record): BinaryFileResponse {
+ activity()
+ ->by(auth()->user())
+ ->on($record)
+ ->log('Export triggered');
+
+ return (new BookingsExport($record, false))->download('bookings.csv');
+ })
+ ->icon('heroicon-o-download')
+ ->modalButton('Start export')
+ ->requiresConfirmation()
+ ->hidden(fn (Event $record): bool => $record->event_type_id == EventType::MULTIFLIGHTS()->value),
+ ButtonAction::make('export_multiflights')
+ ->label('Export')
+ ->action(function (Event $record, array $data): BinaryFileResponse {
+ activity()
+ ->by(auth()->user())
+ ->on($record)
+ ->log('Export triggered');
+
+ return (new BookingsExport($record, $data['with_emails']))->download('bookings.csv');
+ })
+ ->icon('heroicon-o-download')
+ ->modalButton('Start export')
+ ->form([
+ Toggle::make('with_emails')
+ ->default(false)
+ ])
+ ->visible(fn (Event $record): bool => $record->event_type_id == EventType::MULTIFLIGHTS()->value),
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ RelationManagers\BookingsRelationManager::class,
+ RelationManagers\LinksRelationManager::class,
+ RelationManagers\FaqsRelationManager::class,
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListEvents::route('/'),
+ 'create' => Pages\CreateEvent::route('/create'),
+ 'view' => Pages\ViewEvent::route('/{record}'),
+ 'edit' => Pages\EditEvent::route('/{record}/edit'),
+ 'import-bookings' => Pages\ImportBookings::route('{record}/import-bookings'),
+ 'assign-routes' => Pages\AssignRoutes::route('{record}/assign-routes'),
+ 'send-email' => Pages\SendEmail::route('{record}/send-email')
+ ];
+ }
+}
diff --git a/app/Filament/Resources/EventResource/Pages/AssignRoutes.php b/app/Filament/Resources/EventResource/Pages/AssignRoutes.php
new file mode 100644
index 00000000..034485f4
--- /dev/null
+++ b/app/Filament/Resources/EventResource/Pages/AssignRoutes.php
@@ -0,0 +1,62 @@
+event = $record;
+ $this->form->fill();
+ }
+
+ protected function getFormSchema(): array
+ {
+ return [
+ FileUpload::make('file')
+ ->helperText('Headers in **bold** are mandatory **From ** | **To ** | **Route** | Notes')
+ ->required()
+ ->directory('imports')
+ ->visibility('private'),
+ ];
+ }
+
+ protected function getFormModel(): Model|string|null
+ {
+ return $this->event;
+ }
+
+ public function submit(): void
+ {
+ activity()
+ ->by(auth()->user())
+ ->on($this->event)
+ ->log('Import triggered');
+
+ $this->event->files()->create([
+ 'path' => $this->form->getState()['file'],
+ 'disk' => config('filament.default_filesystem_disk'),
+ 'type' => FlightRouteAssign::class,
+ ]);
+
+ $this->notify('success', 'Import triggered', true);
+ $this->redirectRoute('filament.resources.events.index');
+ }
+}
diff --git a/app/Filament/Resources/EventResource/Pages/CreateEvent.php b/app/Filament/Resources/EventResource/Pages/CreateEvent.php
new file mode 100644
index 00000000..c1031e9e
--- /dev/null
+++ b/app/Filament/Resources/EventResource/Pages/CreateEvent.php
@@ -0,0 +1,11 @@
+event = $record;
+ $this->form->fill();
+ }
+
+ protected function getFormSchema(): array
+ {
+ $helperText = 'Headers in **bold** are mandatory ';
+ switch ($this->event->event_type_id) {
+ case EventType::MULTIFLIGHTS()->value:
+ $helperText .= '**CTOT 1 ** - **Airport 1 ** - **CTOT 2 ** - **Airport 2 ** - **Airport 3 **';
+ break;
+ default:
+ $helperText .= 'Call Sign | **Origin ** | **Destination ** | CTOT | ETA | Aircraft Type | Route | Notes | Track | FL ';
+ }
+ return [
+ FileUpload::make('file')
+ ->helperText($helperText)
+ ->required()
+ ->directory('imports')
+ ->visibility('private'),
+ ];
+ }
+
+ protected function getFormModel(): Model|string|null
+ {
+ return $this->event;
+ }
+
+ public function submit(): void
+ {
+ activity()
+ ->by(auth()->user())
+ ->on($this->event)
+ ->log('Import triggered');
+
+ $this->event->files()->create([
+ 'path' => $this->form->getState()['file'],
+ 'disk' => config('filament.default_filesystem_disk'),
+ 'type' => BookingsImport::class,
+ ]);
+
+ $this->notify('success', 'Import triggered', true);
+ $this->redirectRoute('filament.resources.events.index');
+ }
+}
diff --git a/app/Filament/Resources/EventResource/Pages/ListEvents.php b/app/Filament/Resources/EventResource/Pages/ListEvents.php
new file mode 100644
index 00000000..1c98cbcb
--- /dev/null
+++ b/app/Filament/Resources/EventResource/Pages/ListEvents.php
@@ -0,0 +1,11 @@
+event = $record;
+ $this->finalInformationEmailForm->fill();
+ $this->emailForm->fill();
+ }
+
+ protected function getFinalInformationEmailSchema(): array
+ {
+ return [
+ Toggle::make('test_mode_final')
+ ->label('Test mode')
+ ->helperText('Send a random **Final Information E-mail** to yourself'),
+ Toggle::make('force_send')
+ ->helperText('Send to all particpants, even though they already received it (and no edit was made)'),
+
+ ];
+ }
+
+ protected function getEmailSchema(): array
+ {
+ return [
+ TextInput::make('subject')
+ ->prefix($this->event->name . ':'),
+ RichEditor::make('message')
+ ->helperText('Salutation and closing are already included')
+ ->disableToolbarButtons([
+ 'attachFiles',
+ 'codeBlock',
+ ]),
+ Toggle::make('test_mode')
+ ->helperText('Send a random **E-mail** to yourself'),
+ ];
+ }
+
+ protected function getForms(): array
+ {
+ return [
+ 'finalInformationEmailForm' => $this->makeForm()
+ ->schema($this->getFinalInformationEmailSchema())
+ ->model($this->event),
+ 'emailForm' => $this->makeForm()
+ ->schema($this->getEmailSchema())
+ ->model($this->event),
+ ];
+ }
+
+ public function sendFinalInformationEmail(): void
+ {
+ $state = $this->finalInformationEmailForm->getState();
+
+ $bookings = $this->event->bookings()
+ ->with(['user', 'flights'])
+ ->where('status', BookingStatus::BOOKED)
+ ->get();
+
+ if ($state['test_mode_final']) {
+ EventFinalInformation::dispatch($bookings->random(), auth()->user());
+ $this->notify('primary', 'Email has been sent to yourself');
+ return;
+ }
+
+ $count = $bookings->count();
+ $countSkipped = 0;
+ foreach ($bookings as $booking) {
+ if (!$booking->has_received_final_information_email || $state['force_send']) {
+ EventFinalInformation::dispatch($booking);
+ } else {
+ $count--;
+ $countSkipped++;
+ }
+ }
+
+ $message = "Final Information has been sent to {$count} people!";
+ if ($countSkipped != 0) {
+ $message .= " However, {$countSkipped} where skipped, because they already received one";
+ }
+
+ activity()
+ ->by(auth()->user())
+ ->on($this->event)
+ ->withProperties([
+ 'count' => $count,
+ 'countSkipped', $countSkipped
+ ])
+ ->log('Final Information E-mail');
+
+ $this->notify('success', $message, true);
+ $this->redirectRoute('filament.resources.events.index');
+ }
+
+ public function sendEmail(): void
+ {
+ $state = $this->emailForm->getState();
+
+ if ($state['test_mode']) {
+ EventBulkEmail::dispatch($this->event, $state, collect([auth()->user()]));
+ $this->notify('primary', 'Email has been sent to yourself');
+ return;
+ }
+
+ $users = User::whereHas('bookings', function (Builder $query) {
+ $query->where('event_id', $this->event->id);
+ $query->where('status', BookingStatus::BOOKED);
+ })->get();
+
+ EventBulkEmail::dispatch($this->event, $state, $users);
+ $this->notify('success', "Bulk E-mail has been sent to {$users->count()} people!", true);
+ $this->redirectRoute('filament.resources.events.index');
+ }
+}
diff --git a/app/Filament/Resources/EventResource/Pages/ViewEvent.php b/app/Filament/Resources/EventResource/Pages/ViewEvent.php
new file mode 100644
index 00000000..9d8040f9
--- /dev/null
+++ b/app/Filament/Resources/EventResource/Pages/ViewEvent.php
@@ -0,0 +1,11 @@
+ownerRecord->event_type_id == EventType::MULTIFLIGHTS) {
+ return false;
+ }
+
+ return parent::canCreate();
+ }
+
+ public static function form(Form $form): Form
+ {
+ return $form
+ ->schema([
+ Forms\Components\Toggle::make('is_editable')
+ ->columnSpan('full')
+ ->label('Editable?')
+ ->helperText("Choose if you want the booking to be editable (Callsign and Aircraft Code only) by users. This is useful when using 'import only', but want to add extra slots")
+ ->required(),
+ Forms\Components\TextInput::make('callsign')
+ ->maxLength(7),
+ Forms\Components\TextInput::make('acType')
+ ->label('Aircraft code')
+ ->maxLength(4),
+ Forms\Components\HasManyRepeater::make('flights')
+ ->relationship('flights')
+ ->label(__('Flight'))
+ ->columnSpan('full')
+ ->columns(2)
+ ->disableItemCreation()
+ ->disableItemDeletion()
+ ->disableItemMovement()
+ ->schema([
+ Forms\Components\Select::make('dep')
+ ->label('Departure airport')
+ ->required()
+ ->searchable()
+ ->getSearchResultsUsing(fn (string $query) => Airport::where('icao', 'like', "%{$query}%")
+ ->orWhere('iata', 'like', "%{$query}%")->orWhere('name', 'like', "%{$query}%")
+ ->limit(50)->get()->mapWithKeys(fn (Airport $airport) => [$airport->id => "$airport->icao | $airport->iata | $airport->name"]))
+ ->getOptionLabelUsing(function (?string $value) {
+ $airport = Airport::find($value);
+ return $airport ? "{$airport?->icao} | {$airport?->iata} | {$airport?->name}" : '';
+ }),
+ Forms\Components\Select::make('arr')
+ ->label('Arrival airport')
+ ->required()
+ ->searchable()
+ ->getSearchResultsUsing(fn (string $query) => Airport::where('icao', 'like', "%{$query}%")
+ ->orWhere('iata', 'like', "%{$query}%")->orWhere('name', 'like', "%{$query}%")
+ ->limit(50)->get()->mapWithKeys(fn (Airport $airport) => [$airport->id => "$airport->icao | $airport->iata | $airport->name"]))
+ ->getOptionLabelUsing(function (?string $value) {
+ $airport = Airport::find($value);
+ return $airport ? "{$airport?->icao} | {$airport?->iata} | {$airport?->name}" : '';
+ }),
+ Forms\Components\TimePicker::make('ctot')->label('CTOT (UTC)')->withoutSeconds(),
+ Forms\Components\TimePicker::make('eta')->label('ETA (UTC)')->withoutSeconds(),
+ Forms\Components\TextInput::make('oceanicFL')
+ ->label('Cruise FL')
+ ->prefix('FL')
+ ->numeric()
+ ->step(10)
+ ->minLength(0)
+ ->maxLength(660),
+ Forms\Components\Textarea::make('route')->columnSpan('full'),
+ Forms\Components\Textarea::make('notes')->columnSpan('full'),
+ ])
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('firstFlight.ctot')->label('CTOT')->time('Hi\z'),
+ Tables\Columns\TextColumn::make('firstFlight.eta')->label('ETA')->time('Hi\z'),
+ Tables\Columns\TextColumn::make('firstFlight.airportDep.icao')->label('DEP'),
+ Tables\Columns\TextColumn::make('firstFlight.airportArr.icao')->label('ARR'),
+ Tables\Columns\TextColumn::make('callsign'),
+ Tables\Columns\TextColumn::make('acType')->label('Aircraft type'),
+ Tables\Columns\BadgeColumn::make('status')
+ ->enum([
+ BookingStatus::UNASSIGNED()->value => 'Unassigned',
+ BookingStatus::RESERVED()->value => 'Reserved',
+ BookingStatus::BOOKED()->value => 'Booked',
+ ])
+ ->colors([
+ 'warning' => BookingStatus::RESERVED()->value,
+ 'success' => BookingStatus::BOOKED()->value,
+ ]),
+ Tables\Columns\TextColumn::make('user.pic')->label('PIC'),
+ ])
+ ->filters([
+ //
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/EventResource/RelationManagers/FaqsRelationManager.php b/app/Filament/Resources/EventResource/RelationManagers/FaqsRelationManager.php
new file mode 100644
index 00000000..3257dd76
--- /dev/null
+++ b/app/Filament/Resources/EventResource/RelationManagers/FaqsRelationManager.php
@@ -0,0 +1,45 @@
+columns(1)
+ ->schema([
+ Forms\Components\Toggle::make('is_online')
+ ->label('Show online?')
+ ->default(true)
+ ->required(),
+ Forms\Components\TextInput::make('question')
+ ->required()
+ ->maxLength(255),
+ Forms\Components\RichEditor::make('answer')
+ ->required(),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('question'),
+ Tables\Columns\BooleanColumn::make('is_online')->label('Show online?'),
+ ])
+ ->filters([
+ //
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/EventResource/RelationManagers/LinksRelationManager.php b/app/Filament/Resources/EventResource/RelationManagers/LinksRelationManager.php
new file mode 100644
index 00000000..13bfb06a
--- /dev/null
+++ b/app/Filament/Resources/EventResource/RelationManagers/LinksRelationManager.php
@@ -0,0 +1,48 @@
+schema([
+ Forms\Components\Select::make('event_link_type_id')
+ ->label('Type')
+ ->required()
+ ->options(AirportLinkType::all(['id', 'name'])->pluck('name', 'id')),
+ Forms\Components\TextInput::make('name')
+ ->minLength(5)
+ ->maxLength(255),
+ Forms\Components\TextInput::make('url')
+ ->required()
+ ->url()
+ ->maxLength(255),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('type.name')->sortable(),
+ Tables\Columns\TextColumn::make('name')->sortable(),
+ Tables\Columns\TextColumn::make('url')->sortable(),
+ ])
+ ->filters([
+ //
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/EventResource/Traits/EventForm.php b/app/Filament/Resources/EventResource/Traits/EventForm.php
new file mode 100644
index 00000000..ccf5c462
--- /dev/null
+++ b/app/Filament/Resources/EventResource/Traits/EventForm.php
@@ -0,0 +1,106 @@
+schema([
+ Toggle::make('is_online')
+ ->label('Show online?')
+ ->default(true)
+ ->helperText("Choose here if you want the event to be reachable by it's generated url")
+ ->required(),
+ Toggle::make('show_on_homepage')
+ ->label('Show on homepage?')
+ ->default(true)
+ ->helperText("Choose here if you want to show the event on the homepage. If turned off, the event can only be reached by the url. NOTE: If 'Show Online' is off, the event won't be shown at all")
+ ->required(),
+ Toggle::make('import_only')
+ ->label('Only import?')
+ ->helperText('If enabled, only admins can fill in details via import script')
+ ->required(),
+ Toggle::make('uses_times')
+ ->label('Show times?')
+ ->helperText('If enabled, CTOT and ETA (if set in booking) will be shown')
+ ->required(),
+ Toggle::make('multiple_bookings_allowed')
+ ->label('Multiple bookings allowed?')
+ ->helperText('If enabled, a user is allowed to book multiple flights for this event')
+ ->required(),
+ Toggle::make('is_oceanic_event')
+ ->label('Oceanic event?')
+ ->helperText('If enabled, users can fill in a SELCAL code')
+ ->required(),
+ TextInput::make('name')
+ ->required()
+ ->maxLength(255),
+ Select::make('event_type_id')
+ ->label('Event type')
+ ->options(EventType::all(['id', 'name'])->pluck('name', 'id'))
+ ->required(),
+ Select::make('dep')
+ ->label('Departure airport')
+ ->required()
+ ->searchable()
+ ->getSearchResultsUsing(fn (string $query) => Airport::where('icao', 'like', "%{$query}%")
+ ->orWhere('iata', 'like', "%{$query}%")->orWhere('name', 'like', "%{$query}%")
+ ->limit(50)->get()->mapWithKeys(fn (Airport $airport) => [$airport->id => "$airport->icao | $airport->iata | $airport->name"]))
+ ->getOptionLabelUsing(function (?string $value) {
+ $airport = Airport::find($value);
+ return $airport ? "{$airport?->icao} | {$airport?->iata} | {$airport?->name}" : '';
+ }),
+ Select::make('arr')
+ ->label('Arrival airport')
+ ->required()
+ ->searchable()
+ ->getSearchResultsUsing(fn (string $query) => Airport::where('icao', 'like', "%{$query}%")
+ ->orWhere('iata', 'like', "%{$query}%")->orWhere('name', 'like', "%{$query}%")
+ ->limit(50)->get()->mapWithKeys(fn (Airport $airport) => [$airport->id => "$airport->icao | $airport->iata | $airport->name"]))
+ ->getOptionLabelUsing(function (?string $value) {
+ $airport = Airport::find($value);
+ return $airport ? "{$airport?->icao} | {$airport?->iata} | {$airport?->name}" : '';
+ }),
+ DateTimePicker::make('startEvent')
+ ->label('Start event (UTC)')
+ ->default(now()->addDay()->startOfHour())
+ ->withoutSeconds()
+ ->required(),
+ DateTimePicker::make('endEvent')
+ ->label('End event (UTC)')
+ ->default(now()->addDay()->addHours(4)->startOfHour())
+ ->withoutSeconds()
+ ->required()
+ ->after('startEvent'),
+ DateTimePicker::make('startBooking')
+ ->label('Start booking (UTC)')
+ ->default(now()->startOfHour())
+ ->withoutSeconds()
+ ->required(),
+ DateTimePicker::make('endBooking')
+ ->label('End booking (UTC)')
+ ->default(now()->addDay()->addHours(4)->startOfHour())
+ ->withoutSeconds()
+ ->required()
+ ->after('startBooking')
+ ->beforeOrEqual('endEvent'),
+ TextInput::make('image_url')
+ ->label('Image URL')
+ ->maxLength(255)
+ ->url(),
+ RichEditor::make('description')
+ ->columnSpan('full'),
+ ]);
+ }
+}
diff --git a/app/Filament/Resources/FaqResource.php b/app/Filament/Resources/FaqResource.php
new file mode 100644
index 00000000..7420f36f
--- /dev/null
+++ b/app/Filament/Resources/FaqResource.php
@@ -0,0 +1,65 @@
+columns(1)
+ ->schema([
+ Forms\Components\Toggle::make('is_online')
+ ->label('Show online?')
+ ->default(true)
+ ->required(),
+ Forms\Components\TextInput::make('question')
+ ->required()
+ ->maxLength(255),
+ Forms\Components\RichEditor::make('answer')
+ ->required(),
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('question'),
+ Tables\Columns\BooleanColumn::make('is_online')->label('Show online?'),
+ Tables\Columns\BooleanColumn::make('events_count')->label('Linked to event(s)?')->counts('events'),
+ ])
+ ->filters([
+ //
+ ]);
+ }
+
+ public static function getRelations(): array
+ {
+ return [
+ RelationManagers\EventsRelationManager::class,
+ ];
+ }
+
+ public static function getPages(): array
+ {
+ return [
+ 'index' => Pages\ListFaqs::route('/'),
+ 'create' => Pages\CreateFaq::route('/create'),
+ 'edit' => Pages\EditFaq::route('/{record}/edit'),
+ ];
+ }
+}
diff --git a/app/Filament/Resources/FaqResource/Pages/CreateFaq.php b/app/Filament/Resources/FaqResource/Pages/CreateFaq.php
new file mode 100644
index 00000000..ef41d093
--- /dev/null
+++ b/app/Filament/Resources/FaqResource/Pages/CreateFaq.php
@@ -0,0 +1,11 @@
+schema([
+ Select::make('recordId')
+ ->label('Event')
+ ->options(Event::where('endEvent', '>', now())
+ ->orderBy('startEvent')->get()->mapWithKeys(fn (Event $event) => [$event->id => $event->name_date]))
+ ]);
+ }
+
+ public static function table(Table $table): Table
+ {
+ return $table
+ ->columns([
+ Tables\Columns\TextColumn::make('nameDate')->label('Name')
+ ])
+ ->filters([
+ //
+ ]);
+ }
+}
diff --git a/app/Http/Controllers/Airport/AirportAdminController.php b/app/Http/Controllers/Airport/AirportAdminController.php
deleted file mode 100644
index 93883bee..00000000
--- a/app/Http/Controllers/Airport/AirportAdminController.php
+++ /dev/null
@@ -1,88 +0,0 @@
-authorizeResource(AirportPolicy::class, 'airport');
- }
-
- public function index(): View
- {
- $airports = Airport::with(['flightsDep', 'flightsArr', 'eventDep', 'eventArr'])
- ->paginate(100);
- return view('airport.admin.overview', compact('airports'));
- }
-
- public function create(): View
- {
- return view('airport.admin.form', ['airport' => new Airport()]);
- }
-
- public function store(StoreAirport $request): RedirectResponse
- {
- $airport = Airport::create($request->validated());
- flashMessage('success', __('Done'), __(':airport has been added!', ['airport' => "$airport->name [$airport->icao | $airport->iata]"]));
- return to_route('admin.airports.index');
- }
-
- public function show(Airport $airport): View
- {
- return view('airport.admin.show', compact('airport'));
- }
-
- public function edit(Airport $airport): View
- {
- return view('airport.admin.form', compact('airport'));
- }
-
- public function update(UpdateAirport $request, Airport $airport): RedirectResponse
- {
- $airport->update($request->validated());
- flashMessage('success', __('Done'), __(':airport has been updated!', ['airport' => "$airport->name [$airport->icao | $airport->iata]"]));
-
- return to_route('admin.airports.index');
- }
-
- public function destroy(Airport $airport): RedirectResponse
- {
- if ($airport->flightsDep->isEmpty() && $airport->flightsArr->isEmpty()) {
- $airport->delete();
- flashMessage('success', __('Done'), __(':airport has been deleted!', ['airport' => "$airport->name [$airport->icao | $airport->iata]"]));
-
- return redirect()->back();
- } else {
- flashMessage(
- 'danger',
- __('Warning'),
- __(':airport could not be deleted! It\'s linked to another event', ['airport' => "$airport->name [$airport->icao | $airport->iata]"])
- );
- return redirect()->back();
- }
- }
-
- public function destroyUnused()
- {
- $this->authorize('destroy', Airport::class);
- Airport::whereDoesntHave('flightsDep')
- ->whereDoesntHave('flightsArr')
- ->whereDoesntHave('eventDep')
- ->whereDoesntHave('eventArr')
- ->delete();
-
- flashMessage('success', __('Done'), __('Unused airport have been deleted!'));
-
- return to_route('admin.airports.index');
- }
-}
diff --git a/app/Http/Controllers/AirportLink/AirportLinkAdminController.php b/app/Http/Controllers/AirportLink/AirportLinkAdminController.php
deleted file mode 100644
index 5dbfb6e5..00000000
--- a/app/Http/Controllers/AirportLink/AirportLinkAdminController.php
+++ /dev/null
@@ -1,73 +0,0 @@
-authorizeResource(AirportLinkPolicy::class, 'airportLink');
- }
-
- public function index(): View
- {
- $airportLinks = AirportLink::orderBy('airport_id', 'asc')
- ->with(['airport', 'type'])
- ->paginate();
- return view('airportLink.admin.overview', compact('airportLinks'));
- }
-
- public function create(): View
- {
- $airportLink = new AirportLink();
- $airportLinkTypes = AirportLinkType::all(['id', 'name'])->pluck('name', 'id');
- $airports = Airport::all(['id', 'icao', 'iata', 'name'])->keyBy('id')
- ->map(function ($airport) {
- /** @var Airport $airport */
- return "$airport->icao | $airport->name | $airport->iata";
- });
- return view('airportLink.admin.form', compact('airportLink', 'airportLinkTypes', 'airports'));
- }
-
- public function store(StoreAirportLink $request): RedirectResponse
- {
- $airportLink = AirportLink::create($request->validated());
- flashMessage(
- 'success',
- __('Done'),
- __(':Type item has been added for :airport', ['Type' => $airportLink->type->name, 'airport' => "{$airportLink->airport->name} [{$airportLink->airport->icao} | {$airportLink->airport->iata}]"])
- );
- return to_route('admin.airports.index');
- }
-
- public function edit(AirportLink $airportLink): View
- {
- $airportLinkTypes = AirportLinkType::all(['id', 'name'])->pluck('name', 'id');
-
- return view('airportLink.admin.form', compact('airportLink', 'airportLinkTypes'));
- }
-
- public function update(UpdateAirportLink $request, AirportLink $airportLink): RedirectResponse
- {
- $airportLink->update($request->validated());
- flashMessage('success', __('Done'), __('Airport Link has been updated'));
- return to_route('admin.airportLinks.index');
- }
-
- public function destroy(AirportLink $airportLink): RedirectResponse
- {
- $airportLink->delete();
- flashMessage('success', __('Airport link deleted'), __('Airport link has been deleted'));
- return back();
- }
-}
diff --git a/app/Http/Controllers/Booking/BookingAdminController.php b/app/Http/Controllers/Booking/BookingAdminController.php
index 86a10edb..c824d9fb 100644
--- a/app/Http/Controllers/Booking/BookingAdminController.php
+++ b/app/Http/Controllers/Booking/BookingAdminController.php
@@ -23,7 +23,6 @@
use App\Http\Requests\Booking\Admin\RouteAssign;
use App\Http\Requests\Booking\Admin\StoreBooking;
use App\Http\Requests\Booking\Admin\UpdateBooking;
-use App\Http\Requests\Booking\Admin\ImportBookings;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
class BookingAdminController extends AdminController
@@ -221,34 +220,6 @@ public function destroy(Booking $booking): RedirectResponse
return back();
}
- public function export(Event $event, Request $request): BinaryFileResponse
- {
- activity()
- ->by(auth()->user())
- ->on($event)
- ->log('Export triggered');
-
- return (new BookingsExport($event, $request->vacc))->download('bookings.csv');
- }
-
- public function importForm(Event $event)
- {
- return view('event.admin.import', compact('event'));
- }
-
- public function import(ImportBookings $request, Event $event): RedirectResponse
- {
- activity()
- ->by(auth()->user())
- ->on($event)
- ->log('Import triggered');
- $file = $request->file('file');
- (new BookingsImport($event))->import($file);
- Storage::delete($file->getRealPath());
- flashMessage('success', __('Flights imported'), __('Flights have been imported'));
- return to_route('bookings.event.index', $event);
- }
-
public function adminAutoAssignForm(Event $event): View
{
return view('event.admin.autoAssign', compact('event'));
diff --git a/app/Http/Controllers/Event/EventAdminController.php b/app/Http/Controllers/Event/EventAdminController.php
deleted file mode 100644
index c7739706..00000000
--- a/app/Http/Controllers/Event/EventAdminController.php
+++ /dev/null
@@ -1,208 +0,0 @@
-authorizeResource(EventPolicy::class, 'event');
- }
-
- public function index(): View
- {
- $events = Event::orderByDesc('startEvent')
- ->with('type')
- ->paginate();
- return view('event.admin.overview', compact('events'));
- }
-
- public function create(): View
- {
- $event = new Event();
- $airports = Airport::all(['id', 'icao', 'iata', 'name'])->keyBy('id')
- ->map(function ($airport) {
- /** @var Airport $airport */
- return "$airport->icao | $airport->name | $airport->iata";
- });
- $eventTypes = EventType::all()->pluck('name', 'id');
- return view('event.admin.form', compact('event', 'airports', 'eventTypes'));
- }
-
- public function store(StoreEvent $request): RedirectResponse
- {
- $event = new Event();
- $event->fill($request->only(
- 'is_online',
- 'show_on_homepage',
- 'name',
- 'event_type_id',
- 'import_only',
- 'uses_times',
- 'multiple_bookings_allowed',
- 'is_oceanic_event',
- 'dep',
- 'arr',
- 'image_url',
- 'description'
- ));
- $event->fill([
- 'startEvent' => $request->date('startEvent'),
- 'endEvent' => $request->date('endEvent'),
- 'startBooking' => $request->date('startBooking'),
- 'endBooking' => $request->date('endBooking'),
- ])->save();
-
- flashMessage('success', __('Done'), __('Event has been created!'));
- return to_route('admin.events.index');
- }
-
- public function show(Event $event): View
- {
- return view('event.admin.show', compact('event'));
- }
-
- public function edit(Event $event): View
- {
- $airports = Airport::all(['id', 'icao', 'iata', 'name'])->keyBy('id')
- ->map(function ($airport) {
- /** @var Airport $airport */
- return "$airport->icao | $airport->name | $airport->iata";
- });
- $eventTypes = EventType::all()->pluck('name', 'id');
- return view('event.admin.form', compact('event', 'airports', 'eventTypes'));
- }
-
- public function update(UpdateEvent $request, Event $event): RedirectResponse
- {
- $event->fill($request->only(
- 'is_online',
- 'show_on_homepage',
- 'name',
- 'event_type_id',
- 'import_only',
- 'uses_times',
- 'multiple_bookings_allowed',
- 'is_oceanic_event',
- 'dep',
- 'arr',
- 'image_url',
- 'description'
- ));
- $event->fill([
- 'startEvent' => $request->date('startEvent'),
- 'endEvent' => $request->date('endEvent'),
- 'startBooking' => $request->date('startBooking'),
- 'endBooking' => $request->date('endBooking'),
- ])->save();
- flashMessage('success', __('Done'), __('Event has been updated!'));
- return to_route('admin.events.index');
- }
-
- public function destroy(Event $event): RedirectResponse
- {
- if ($event->startEvent > now()) {
- $event->delete();
- flashMessage('success', __('Done'), __(':event has been deleted!', ['event' => $event->name]));
- return redirect()->back();
- } else {
- flashMessage('danger', __('Danger'), __('Event can no longer be deleted!'));
- return redirect()->back();
- }
- }
-
- public function sendEmailForm(Event $event): View
- {
- return view('event.admin.sendEmail', compact('event'));
- }
-
- public function sendEmail(SendEmail $request, Event $event): JsonResponse|RedirectResponse
- {
- if ($request->testmode) {
- event(new EventBulkEmail($event, $request->all(), collect([auth()->user()])));
- return response()->json(['success' => __('Email has been sent to yourself')]);
- } else {
- /* @var User $users */
- $users = User::whereHas('bookings', function (Builder $query) use ($event) {
- $query->where('event_id', $event->id);
- $query->where('status', BookingStatus::BOOKED);
- })->get();
- event(new EventBulkEmail($event, $request->all(), $users));
- flashMessage('success', __('Done'), __('Bulk E-mail has been sent to :count people!', ['count' => $users->count()]));
- return to_route('admin.events.index');
- }
- }
-
- public function sendFinalInformationMail(Request $request, Event $event): RedirectResponse|JsonResponse
- {
- $bookings = $event->bookings()
- ->with(['user', 'flights'])
- ->where('status', BookingStatus::BOOKED)
- ->get();
-
- if ($request->testmode) {
- event(new EventFinalInformation($bookings->random(), $request->user()));
-
- return response()->json(['success' => __('Email has been sent to yourself')]);
- } else {
- $count = $bookings->count();
- $countSkipped = 0;
- foreach ($bookings as $booking) {
- if (!$booking->has_received_final_information_email || $request->forceSend) {
- event(new EventFinalInformation($booking));
- } else {
- $count--;
- $countSkipped++;
- }
- }
- $message = __('Final Information has been sent to :count people!', ['count' => $count]);
- if ($countSkipped != 0) {
- $message .= ' ' . __('However, :count where skipped, because they already received one', ['count' => $count]);
- }
- flashMessage('success', __('Done'), $message);
- activity()
- ->by(auth()->user())
- ->on($event)
- ->withProperty('count', $count)
- ->log('Final Information E-mail');
- }
-
- return to_route('admin.events.index');
- }
-
- public function deleteAllBookings(Request $request, Event $event): RedirectResponse
- {
- activity()
- ->by(auth()->user())
- ->on($event)
- ->log('Delete all bookings');
-
- if ($event->endEvent <= now()) {
- flashMessage('danger', __('Danger'), __('Booking can no longer be deleted'));
- return back();
- }
-
- $event->bookings()->delete();
- flashMessage('success', __('Bookings deleted'), __('All bookings have been deleted'));
- return to_route('admin.events.index');
- }
-}
diff --git a/app/Http/Controllers/EventLink/EventLinkAdminController.php b/app/Http/Controllers/EventLink/EventLinkAdminController.php
deleted file mode 100644
index cc914418..00000000
--- a/app/Http/Controllers/EventLink/EventLinkAdminController.php
+++ /dev/null
@@ -1,75 +0,0 @@
-authorizeResource(EventLinkPolicy::class, 'eventLink');
- }
-
- public function index(): View
- {
- $eventLinks = EventLink::orderBy('event_id', 'asc')
- ->with(['event', 'type'])
- ->paginate();
- return view('eventLink.admin.overview', compact('eventLinks'));
- }
-
- public function create(Event $event): View
- {
- $eventLink = new EventLink();
- $eventLinkTypes = AirportLinkType::all(['id', 'name'])->pluck('name', 'id');
- $events = Event::where('endEvent', '>', now())
- ->orderBy('startEvent')
- ->get(['id', 'name', 'startEvent'])
- ->keyBy('id')
- ->map(function ($event) {
- /** @var Event $event */
- return "$event->name [{$event->startEvent->format('d-m-Y')}]";
- });
- return view('eventLink.admin.form', compact('eventLink', 'eventLinkTypes', 'events'));
- }
-
- public function store(StoreEventLink $request): RedirectResponse
- {
- $eventLink = EventLink::create($request->validated());
- flashMessage(
- 'success',
- __('Done'),
- __(':Type item has been added for :event', ['Type' => $eventLink->type->name, 'event' => $eventLink->event->name])
- );
- return to_route('admin.eventLinks.index');
- }
-
- public function edit(EventLink $eventLink): View
- {
- $eventLinkTypes = AirportLinkType::all(['id', 'name'])->pluck('name', 'id');
- return view('eventLink.admin.form', compact('eventLink', 'eventLinkTypes'));
- }
-
- public function update(UpdateEventLink $request, EventLink $eventLink): RedirectResponse
- {
- $eventLink->update($request->validated());
- flashMessage('success', __('Done'), __('Link has been updated'));
- return to_route('admin.eventLinks.index');
- }
-
- public function destroy(EventLink $eventLink): RedirectResponse
- {
- $eventLink->delete();
- flashMessage('success', __('Event link deleted'), __('Event link has been deleted'));
- return back();
- }
-}
diff --git a/app/Http/Controllers/Faq/FaqAdminController.php b/app/Http/Controllers/Faq/FaqAdminController.php
deleted file mode 100644
index b91324be..00000000
--- a/app/Http/Controllers/Faq/FaqAdminController.php
+++ /dev/null
@@ -1,74 +0,0 @@
-authorizeResource(FaqPolicy::class, 'faq');
- }
-
- public function index(): View
- {
- $faqs = Faq::withCount('events')->paginate();
- return view('faq.admin.overview', compact('faqs'));
- }
-
- public function create(): View
- {
- $faq = new Faq();
- return view('faq.admin.form', compact('faq'));
- }
-
- public function store(StoreFaq $request): RedirectResponse
- {
- $faq = Faq::create($request->validated());
- flashMessage('success', __('Done'), __('FAQ has been added!'));
- return to_route('admin.faq.edit', $faq);
- }
-
- public function edit(Faq $faq): View
- {
- $events = Event::where('endEvent', '>', now())
- ->orderBy('startEvent', 'desc')
- ->get();
-
- return view('faq.admin.form', compact('faq', 'events'));
- }
-
- public function update(UpdateFaq $request, Faq $faq): RedirectResponse
- {
- $faq->update($request->validated());
- flashMessage('success', __('Done'), __('FAQ has been updated!'));
- return to_route('admin.faq.edit', $faq);
- }
-
- public function destroy(Faq $faq): RedirectResponse
- {
- $faq->delete();
- flashMessage('success', __('Done'), 'Question has been removed!');
- return to_route(route('admin.faq.index'));
- }
-
- public function toggleEvent(Faq $faq, Event $event): RedirectResponse
- {
- if ($faq->events()->where('event_id', $event->id)->first()) {
- $faq->events()->detach($event->id);
- flashMessage('success', __('Event unlinked'), __('Event has been unlinked to this FAQ'));
- } else {
- $faq->events()->attach($event->id);
- flashMessage('success', __('Event linked'), __('Event has been linked to this FAQ'));
- }
- return back();
- }
-}
diff --git a/app/Http/Requests/Airport/Admin/StoreAirport.php b/app/Http/Requests/Airport/Admin/StoreAirport.php
deleted file mode 100644
index 986dd985..00000000
--- a/app/Http/Requests/Airport/Admin/StoreAirport.php
+++ /dev/null
@@ -1,40 +0,0 @@
- 'required:string|unique:airports|size:4',
- 'iata' => 'required:string|unique:airports,iata|size:3',
- 'name' => 'required:string',
- 'latitude' => ['required', 'regex:/^[-]?((([0-8]?[0-9])(\.(\d{1,10}))?)|(90(\.0+)?))$/'],
- 'longitude' => ['required', 'regex:/^[-]?((((1[0-7][0-9])|([0-9]?[0-9]))(\.(\d{1,10}))?)|180(\.0+)?)/'],
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'icao' => __('ICAO'),
- 'iata' => __('IATA'),
- 'name' => __('Name'),
- 'latitude' => __('Latitude'),
- 'longitude' => __('Longitude'),
- ];
- }
-}
diff --git a/app/Http/Requests/Airport/Admin/UpdateAirport.php b/app/Http/Requests/Airport/Admin/UpdateAirport.php
deleted file mode 100644
index de0ce63e..00000000
--- a/app/Http/Requests/Airport/Admin/UpdateAirport.php
+++ /dev/null
@@ -1,40 +0,0 @@
- 'required:string|between:4,4',
- 'iata' => 'required:string|between:3,3',
- 'name' => 'required:string',
- 'latitude' => ['required', 'regex:/^[-]?((([0-8]?[0-9])(\.(\d{1,10}))?)|(90(\.0+)?))$/'],
- 'longitude' => ['required', 'regex:/^[-]?((((1[0-7][0-9])|([0-9]?[0-9]))(\.(\d{1,10}))?)|180(\.0+)?)/'],
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'icao' => __('ICAO'),
- 'iata' => __('IATA'),
- 'name' => __('Name'),
- 'latitude' => __('Latitude'),
- 'longitude' => __('Longitude'),
- ];
- }
-}
diff --git a/app/Http/Requests/AirportLink/Admin/StoreAirportLink.php b/app/Http/Requests/AirportLink/Admin/StoreAirportLink.php
deleted file mode 100644
index f398b1c9..00000000
--- a/app/Http/Requests/AirportLink/Admin/StoreAirportLink.php
+++ /dev/null
@@ -1,38 +0,0 @@
- 'required|exists:airport_link_types,id',
- 'airport_id' => 'required|exists:airports,id',
- 'name' => 'nullable|string',
- 'url' => 'required|url',
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'airportLinkType_id' => __('Type'),
- 'airport_id' => __('Airport'),
- 'name' => __('Name'),
- 'url' => __('URL'),
- ];
- }
-}
diff --git a/app/Http/Requests/AirportLink/Admin/UpdateAirportLink.php b/app/Http/Requests/AirportLink/Admin/UpdateAirportLink.php
deleted file mode 100644
index 00fb647c..00000000
--- a/app/Http/Requests/AirportLink/Admin/UpdateAirportLink.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'required|exists:airport_link_types,id',
- 'name' => 'nullable|string',
- 'url' => 'required|url',
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'airportLinkType_id' => __('Type'),
- 'name' => __('Name'),
- 'url' => __('URL'),
- ];
- }
-}
diff --git a/app/Http/Requests/Event/Admin/SendEmail.php b/app/Http/Requests/Event/Admin/SendEmail.php
deleted file mode 100644
index 53ff145f..00000000
--- a/app/Http/Requests/Event/Admin/SendEmail.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'bail|required:string',
- 'message' => 'required:string',
- 'testmode' => 'boolean'
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'subject' => __('Subject'),
- 'message' => __('Message'),
- 'testmode' => __('Test mode'),
- ];
- }
-}
diff --git a/app/Http/Requests/Event/Admin/StoreEvent.php b/app/Http/Requests/Event/Admin/StoreEvent.php
deleted file mode 100644
index 0e261783..00000000
--- a/app/Http/Requests/Event/Admin/StoreEvent.php
+++ /dev/null
@@ -1,62 +0,0 @@
- 'required|boolean',
- 'show_on_homepage' => 'required|boolean',
- 'name' => 'bail|required:string',
- 'event_type_id' => 'exists:event_types,id|required',
- 'import_only' => 'required|boolean',
- 'uses_times' => 'required|boolean',
- 'multiple_bookings_allowed' => 'required|boolean',
- 'is_oceanic_event' => 'required|boolean',
- 'dep' => 'exists:airports,id|required',
- 'arr' => 'exists:airports,id|required',
- 'startEvent' => 'required|date',
- 'endEvent' => 'required|date|after_or_equal:startEvent',
- 'startBooking' => 'required|date',
- 'endBooking' => 'required|date|after_or_equal:startBooking',
- 'image_url' => 'nullable|url',
- 'description' => 'required:string',
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'is_online' => __('Show online?'),
- 'show_on_homepage' => __('Show on homepage?'),
- 'name' => __('Name'),
- 'event_type_id' => __('Event type'),
- 'import_only' => __('Only import?'),
- 'uses_times' => __('Show times?'),
- 'multiple_bookings_allowed' => __('Multiple bookings allowed?'),
- 'is_oceanic_event' => __('Oceanic event?'),
- 'dep' => __('Departure airport'),
- 'arr' => __('Arrival airport'),
- 'startEvent' => __('Start event'),
- 'endEvent' => __('End event'),
- 'startBooking' => __('Start booking'),
- 'endBooking' => __('End booking'),
- 'image_url' => __('Image URL'),
- 'description' => __('Description'),
- ];
- }
-}
diff --git a/app/Http/Requests/Event/Admin/UpdateEvent.php b/app/Http/Requests/Event/Admin/UpdateEvent.php
deleted file mode 100644
index 536aec78..00000000
--- a/app/Http/Requests/Event/Admin/UpdateEvent.php
+++ /dev/null
@@ -1,62 +0,0 @@
- 'required|boolean',
- 'show_on_homepage' => 'required|boolean',
- 'name' => 'bail|required:string',
- 'event_type_id' => 'exists:event_types,id|required',
- 'import_only' => 'required|boolean',
- 'uses_times' => 'required|boolean',
- 'multiple_bookings_allowed' => 'required|boolean',
- 'is_oceanic_event' => 'required|boolean',
- 'dep' => 'exists:airports,id|required',
- 'arr' => 'exists:airports,id|required',
- 'startEvent' => 'required|date',
- 'endEvent' => 'required|date|after_or_equal:startEvent',
- 'startBooking' => 'required|date',
- 'endBooking' => 'required|date|after_or_equal:startBooking',
- 'image_url' => 'nullable|url',
- 'description' => 'required:string',
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'is_online' => __('Show online?'),
- 'show_on_homepage' => __('Show on homepage?'),
- 'name' => __('Name'),
- 'event_type_id' => __('Event type'),
- 'import_only' => __('Only import?'),
- 'uses_times' => __('Show times?'),
- 'multiple_bookings_allowed' => __('Multiple bookings allowed?'),
- 'is_oceanic_event' => __('Oceanic event?'),
- 'dep' => __('Departure airport'),
- 'arr' => __('Arrival airport'),
- 'startEvent' => __('Start event'),
- 'endEvent' => __('End event'),
- 'startBooking' => __('Start booking'),
- 'endBooking' => __('End booking'),
- 'image_url' => __('Image URL'),
- 'description' => __('Description'),
- ];
- }
-}
diff --git a/app/Http/Requests/EventLink/Admin/StoreEventLink.php b/app/Http/Requests/EventLink/Admin/StoreEventLink.php
deleted file mode 100644
index 8adf251a..00000000
--- a/app/Http/Requests/EventLink/Admin/StoreEventLink.php
+++ /dev/null
@@ -1,38 +0,0 @@
- 'required|exists:airport_link_types,id',
- 'event_id' => 'required|exists:events,id',
- 'name' => 'nullable|string',
- 'url' => 'required|url',
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'event_link_type_id' => __('Type'),
- 'event_id' => __('Event'),
- 'name' => __('Name'),
- 'url' => __('URL'),
- ];
- }
-}
diff --git a/app/Http/Requests/EventLink/Admin/UpdateEventLink.php b/app/Http/Requests/EventLink/Admin/UpdateEventLink.php
deleted file mode 100644
index 8bcfd0d6..00000000
--- a/app/Http/Requests/EventLink/Admin/UpdateEventLink.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'required|exists:airport_link_types,id',
- 'name' => 'nullable|string',
- 'url' => 'required|url',
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'event_link_type_id' => __('Type'),
- 'name' => __('Name'),
- 'url' => __('URL'),
- ];
- }
-}
diff --git a/app/Http/Requests/Faq/Admin/StoreFaq.php b/app/Http/Requests/Faq/Admin/StoreFaq.php
deleted file mode 100644
index 16eda1da..00000000
--- a/app/Http/Requests/Faq/Admin/StoreFaq.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'required:boolean',
- 'question' => 'required:string',
- 'answer' => 'required:string'
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'is_online' => __('Is online'),
- 'question' => __('Question'),
- 'answer' => __('Answer'),
- ];
- }
-}
diff --git a/app/Http/Requests/Faq/Admin/UpdateFaq.php b/app/Http/Requests/Faq/Admin/UpdateFaq.php
deleted file mode 100644
index 24e81276..00000000
--- a/app/Http/Requests/Faq/Admin/UpdateFaq.php
+++ /dev/null
@@ -1,36 +0,0 @@
- 'required:boolean',
- 'question' => 'required:string',
- 'answer' => 'required:string'
- ];
- }
-
- /**
- * Get custom attributes for validator errors.
- *
- * @return array
- */
- public function attributes()
- {
- return [
- 'is_online' => __('Is online'),
- 'question' => __('Question'),
- 'answer' => __('Answer'),
- ];
- }
-}
diff --git a/app/Imports/BookingsImport.php b/app/Imports/BookingsImport.php
index 7b703e74..562460fd 100644
--- a/app/Imports/BookingsImport.php
+++ b/app/Imports/BookingsImport.php
@@ -6,15 +6,17 @@
use App\Models\Event;
use App\Models\Airport;
use App\Models\Booking;
+use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\ToModel;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use Maatwebsite\Excel\Concerns\Importable;
+use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
use Maatwebsite\Excel\Concerns\WithBatchInserts;
use Maatwebsite\Excel\Concerns\WithChunkReading;
-class BookingsImport implements ToModel, WithHeadingRow, WithBatchInserts, WithChunkReading, WithValidation
+class BookingsImport implements ToModel, WithHeadingRow, WithBatchInserts, WithChunkReading, WithValidation, ShouldQueue, SkipsEmptyRows
{
use Importable;
@@ -97,17 +99,17 @@ public function rules(): array
];
}
return [
- 'origin' => 'exists:airports,icao',
- 'destination' => 'exists:airports,icao',
- 'track' => 'sometimes|nullable',
- 'oceanicFL' => 'sometimes|nullable|integer:3',
- 'aircraft_type' => 'sometimes|nullable|max:4',
+ 'origin' => ['exists:airports,icao'],
+ 'destination' => ['exists:airports,icao'],
+ 'track' => ['sometimes', 'nullable'],
+ 'oceanicFL' => ['sometimes', 'nullable', 'integer:3'],
+ 'aircraft_type' => ['sometimes', 'nullable', 'max:4'],
];
}
private function getAirport($icao): int
{
- return Airport::whereIcao($icao)->first()->id;
+ return Airport::whereIcao(strtoupper($icao))->first()->id;
}
private function getTime($time)
diff --git a/app/Imports/FlightRouteAssign.php b/app/Imports/FlightRouteAssign.php
index 09e14f06..55981eae 100644
--- a/app/Imports/FlightRouteAssign.php
+++ b/app/Imports/FlightRouteAssign.php
@@ -6,11 +6,15 @@
use App\Models\Airport;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\Importable;
+use Illuminate\Contracts\Queue\ShouldQueue;
use Maatwebsite\Excel\Concerns\ToCollection;
+use Maatwebsite\Excel\Concerns\SkipsEmptyRows;
use Maatwebsite\Excel\Concerns\WithHeadingRow;
use Maatwebsite\Excel\Concerns\WithValidation;
+use Maatwebsite\Excel\Concerns\WithBatchInserts;
+use Maatwebsite\Excel\Concerns\WithChunkReading;
-class FlightRouteAssign implements ToCollection, WithHeadingRow, WithValidation
+class FlightRouteAssign implements ToCollection, WithHeadingRow, WithBatchInserts, WithChunkReading, WithValidation, ShouldQueue, SkipsEmptyRows
{
use Importable;
@@ -28,6 +32,16 @@ public function collection(Collection $rows)
}
}
+ public function batchSize(): int
+ {
+ return 250;
+ }
+
+ public function chunkSize(): int
+ {
+ return 250;
+ }
+
public function rules(): array
{
return [
diff --git a/app/Listeners/AssignRoutes.php b/app/Listeners/AssignRoutes.php
new file mode 100644
index 00000000..018e18d8
--- /dev/null
+++ b/app/Listeners/AssignRoutes.php
@@ -0,0 +1,39 @@
+file->type != FlightRouteAssign::class) {
+ return;
+ }
+
+ (new FlightRouteAssign($event->file->fileable))
+ ->queue($event->file->path, $event->file->disk);
+ }
+}
diff --git a/app/Listeners/ImportBookings.php b/app/Listeners/ImportBookings.php
new file mode 100644
index 00000000..02e307a0
--- /dev/null
+++ b/app/Listeners/ImportBookings.php
@@ -0,0 +1,40 @@
+file->type != BookingsImport::class) {
+ return;
+ }
+
+ (new BookingsImport($event->file->fileable))
+ ->queue($event->file->path, $event->file->disk);
+ }
+}
diff --git a/app/Listeners/SendEventBulkEmailNotification.php b/app/Listeners/SendEventBulkEmailNotification.php
index 1e3106f7..b02d3c18 100644
--- a/app/Listeners/SendEventBulkEmailNotification.php
+++ b/app/Listeners/SendEventBulkEmailNotification.php
@@ -27,7 +27,7 @@ public function __construct()
*/
public function handle(EventBulkEmail $event)
{
- if (isset($event->request['testmode'])) {
+ if (isset($event->request['test_mode'])) {
$log = 'Bulk E-mail test performed';
} else {
$log = 'Bulk E-mail';
diff --git a/app/Models/Airport.php b/app/Models/Airport.php
index 1ee253fc..8d389b05 100644
--- a/app/Models/Airport.php
+++ b/app/Models/Airport.php
@@ -17,6 +17,8 @@
* @property string $icao
* @property string $iata
* @property string $name
+ * @property float|null $latitude
+ * @property float|null $longitude
* @property \Illuminate\Support\Carbon|null $created_at
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Activitylog\Models\Activity[] $activities
@@ -40,6 +42,8 @@
* @method static Builder|Airport whereIata($value)
* @method static Builder|Airport whereIcao($value)
* @method static Builder|Airport whereId($value)
+ * @method static Builder|Airport whereLatitude($value)
+ * @method static Builder|Airport whereLongitude($value)
* @method static Builder|Airport whereName($value)
* @method static Builder|Airport whereUpdatedAt($value)
* @mixin \Eloquent
diff --git a/app/Models/AirportLinkType.php b/app/Models/AirportLinkType.php
index e1cb0032..1a2066a6 100644
--- a/app/Models/AirportLinkType.php
+++ b/app/Models/AirportLinkType.php
@@ -20,7 +20,7 @@
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Activitylog\Models\Activity[] $activities
* @property-read int|null $activities_count
- * @property-read AirportLink $links
+ * @property-read AirportLink|null $links
* @method static Builder|AirportLinkType newModelQuery()
* @method static Builder|AirportLinkType newQuery()
* @method static Builder|AirportLinkType query()
diff --git a/app/Models/Booking.php b/app/Models/Booking.php
index 7000ac80..a555ff6c 100644
--- a/app/Models/Booking.php
+++ b/app/Models/Booking.php
@@ -15,6 +15,7 @@
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Factories\HasFactory;
+use Illuminate\Database\Eloquent\Relations\HasOneThrough;
/**
* App\Models\Booking
@@ -33,15 +34,15 @@
* @property \Illuminate\Support\Carbon|null $updated_at
* @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Activitylog\Models\Activity[] $activities
* @property-read int|null $activities_count
- * @property-read Airport|null $airportArr
- * @property-read Airport|null $airportDep
* @property-read Event $event
+ * @property-read Flight|null $firstFlight
* @property-read \Illuminate\Database\Eloquent\Collection|Flight[] $flights
* @property-read int|null $flights_count
* @property-read string $formatted_actype
* @property-read string $formatted_callsign
* @property-read string $formatted_selcal
* @property-read bool $has_received_final_information_email
+ * @property-read Flight|null $lastFlight
* @property-write mixed $actype
* @property-read User|null $user
* @method static \Database\Factories\BookingFactory factory(...$parameters)
@@ -136,16 +137,6 @@ public function setSelcalAttribute($value): void
$this->attributes['selcal'] = !empty($value) ? strtoupper($value) : null;
}
- public function airportDep(): HasOne
- {
- return $this->hasOne(Airport::class, 'id', 'dep');
- }
-
- public function airportArr(): HasOne
- {
- return $this->hasOne(Airport::class, 'id', 'arr');
- }
-
public function event(): BelongsTo
{
return $this->belongsTo(Event::class);
@@ -161,6 +152,16 @@ public function flights(): HasMany
return $this->hasMany(Flight::class)->orderBy('order_by');
}
+ public function firstFlight(): HasOne
+ {
+ return $this->hasOne(Flight::class)->ofMany('order_by', 'min');
+ }
+
+ public function lastFlight(): HasOne
+ {
+ return $this->hasOne(Flight::class)->ofMany('order_by', 'max');
+ }
+
public function airportCtot($orderBy, $withAbbr = true): string
{
if ($flight = $this->flights->where('order_by', $orderBy)->first()) {
diff --git a/app/Models/Event.php b/app/Models/Event.php
index 6e80b688..f7cb914c 100644
--- a/app/Models/Event.php
+++ b/app/Models/Event.php
@@ -6,11 +6,13 @@
use Spatie\Activitylog\LogOptions;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;
+use Illuminate\Database\Eloquent\Casts\Attribute;
use Spatie\Activitylog\Traits\LogsActivity;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
+use Illuminate\Database\Eloquent\Relations\MorphMany;
/**
* App\Models\Event
@@ -43,6 +45,8 @@
* @property-read int|null $bookings_count
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Faq[] $faqs
* @property-read int|null $faqs_count
+ * @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\File[] $files
+ * @property-read int|null $files_count
* @property-read \Illuminate\Database\Eloquent\Collection|EventLink[] $links
* @property-read int|null $links_count
* @property-read \App\Models\EventType|null $type
@@ -150,6 +154,11 @@ public function faqs(): BelongsToMany
return $this->belongsToMany(Faq::class);
}
+ public function files(): MorphMany
+ {
+ return $this->morphMany(File::class, 'fileable');
+ }
+
public function sluggable(): array
{
return [
@@ -171,4 +180,11 @@ public function hasOrderButtons(): bool
\App\Enums\EventType::GROUPFLIGHT
]);
}
+
+ protected function nameDate(): Attribute
+ {
+ return new Attribute(
+ get: fn () => "{$this->name} [{$this->startEvent->format('M j, Y')}]",
+ );
+ }
}
diff --git a/app/Models/EventType.php b/app/Models/EventType.php
index 741d36d7..a8d9078a 100644
--- a/app/Models/EventType.php
+++ b/app/Models/EventType.php
@@ -16,7 +16,7 @@
* @property string $name
* @property-read \Illuminate\Database\Eloquent\Collection|\Spatie\Activitylog\Models\Activity[] $activities
* @property-read int|null $activities_count
- * @property-read Event $events
+ * @property-read Event|null $events
* @method static Builder|EventType newModelQuery()
* @method static Builder|EventType newQuery()
* @method static Builder|EventType query()
diff --git a/app/Models/File.php b/app/Models/File.php
new file mode 100644
index 00000000..9e568425
--- /dev/null
+++ b/app/Models/File.php
@@ -0,0 +1,64 @@
+ FileCreated::class,
+ ];
+
+ public function prunable()
+ {
+ return static::where('created_at', '<=', now()->subDay());
+ }
+
+ public function fileable(): MorphTo
+ {
+ return $this->morphTo();
+ }
+
+ protected function pruning()
+ {
+ Storage::disk($this->disk)
+ ->delete($this->path);
+ }
+}
diff --git a/app/Models/User.php b/app/Models/User.php
index add48045..db6072b8 100644
--- a/app/Models/User.php
+++ b/app/Models/User.php
@@ -6,6 +6,8 @@
use Spatie\Activitylog\LogOptions;
use Illuminate\Notifications\Notifiable;
use App\Http\Controllers\OAuthController;
+use Filament\Models\Contracts\FilamentUser;
+use Filament\Models\Contracts\HasName;
use League\OAuth2\Client\Token\AccessToken;
use Spatie\Activitylog\Traits\LogsActivity;
use Illuminate\Database\Eloquent\Relations\HasMany;
@@ -56,7 +58,7 @@
* @method static \Illuminate\Database\Eloquent\Builder|User whereUseMonospaceFont($value)
* @mixin \Eloquent
*/
-class User extends Authenticatable
+class User extends Authenticatable implements FilamentUser, HasName
{
use HasFactory;
use LogsActivity;
@@ -83,6 +85,16 @@ class User extends Authenticatable
'use_monospace_font' => 'boolean',
];
+ public function canAccessFilament(): bool
+ {
+ return $this->isAdmin;
+ }
+
+ public function getFilamentName(): string
+ {
+ return $this->full_name;
+ }
+
public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()->logOnlyDirty();
diff --git a/app/Policies/AirportLinkPolicy.php b/app/Policies/AirportLinkPolicy.php
index 60e6ac28..1d551897 100644
--- a/app/Policies/AirportLinkPolicy.php
+++ b/app/Policies/AirportLinkPolicy.php
@@ -10,6 +10,13 @@ class AirportLinkPolicy
{
use HandlesAuthorization;
+ public function before(User $user, $ability)
+ {
+ if ($user->isAdmin) {
+ return true;
+ }
+ }
+
/**
* Determine whether the user can view the airport link.
*
diff --git a/app/Policies/AirportPolicy.php b/app/Policies/AirportPolicy.php
index 21aa7d61..a3cf52ed 100644
--- a/app/Policies/AirportPolicy.php
+++ b/app/Policies/AirportPolicy.php
@@ -10,6 +10,13 @@ class AirportPolicy
{
use HandlesAuthorization;
+ public function before(User $user, $ability)
+ {
+ if ($user->isAdmin && $ability != 'delete') {
+ return true;
+ }
+ }
+
/**
* Determine whether the user can view the airport.
*
@@ -54,7 +61,7 @@ public function update(User $user, Airport $airport)
*/
public function delete(User $user, Airport $airport)
{
- return false;
+ return $user->isAdmin && $airport->flightsDep->isEmpty() && $airport->flightsArr->isEmpty();
}
/**
diff --git a/app/Policies/BookingPolicy.php b/app/Policies/BookingPolicy.php
index a8f44444..ff735f46 100644
--- a/app/Policies/BookingPolicy.php
+++ b/app/Policies/BookingPolicy.php
@@ -10,6 +10,13 @@ class BookingPolicy
{
use HandlesAuthorization;
+ public function before(User $user, $ability)
+ {
+ if ($user->isAdmin) {
+ return true;
+ }
+ }
+
/**
* Determine whether the user can view the booking.
*
diff --git a/app/Policies/EventLinkPolicy.php b/app/Policies/EventLinkPolicy.php
index 0be6b145..ae82cd3e 100644
--- a/app/Policies/EventLinkPolicy.php
+++ b/app/Policies/EventLinkPolicy.php
@@ -10,6 +10,13 @@ class EventLinkPolicy
{
use HandlesAuthorization;
+ public function before(User $user, $ability)
+ {
+ if ($user->isAdmin) {
+ return true;
+ }
+ }
+
/**
* Determine whether the user can view any models.
*
diff --git a/app/Policies/EventPolicy.php b/app/Policies/EventPolicy.php
index c7386ad5..6123e979 100644
--- a/app/Policies/EventPolicy.php
+++ b/app/Policies/EventPolicy.php
@@ -10,6 +10,13 @@ class EventPolicy
{
use HandlesAuthorization;
+ public function before(User $user, $ability)
+ {
+ // if ($user->isAdmin && $ability != 'delete') {
+ // return true;
+ // }
+ }
+
/**
* Determine whether the user can view the event.
*
@@ -19,7 +26,7 @@ class EventPolicy
*/
public function view(?User $user, Event $event)
{
- return true;
+ return $user->isAdmin || $event->is_online;
}
/**
@@ -30,7 +37,7 @@ public function view(?User $user, Event $event)
*/
public function create(User $user)
{
- return false;
+ return $user->isAdmin;
}
/**
@@ -42,7 +49,7 @@ public function create(User $user)
*/
public function update(User $user, Event $event)
{
- return false;
+ return $user->isAdmin && $event->startEvent->gt(now());
}
/**
@@ -54,7 +61,7 @@ public function update(User $user, Event $event)
*/
public function delete(User $user, Event $event)
{
- return false;
+ return $user->isAdmin && $event->startEvent->gt(now());
}
/**
diff --git a/app/Policies/FaqPolicy.php b/app/Policies/FaqPolicy.php
index 967b3a12..1d8f0f72 100644
--- a/app/Policies/FaqPolicy.php
+++ b/app/Policies/FaqPolicy.php
@@ -10,6 +10,13 @@ class FaqPolicy
{
use HandlesAuthorization;
+ public function before(User $user, $ability)
+ {
+ if ($user->isAdmin) {
+ return true;
+ }
+ }
+
/**
* Determine whether the user can view the faq.
*
diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php
index e32e5135..f05e9317 100644
--- a/app/Providers/AuthServiceProvider.php
+++ b/app/Providers/AuthServiceProvider.php
@@ -12,7 +12,6 @@
use App\Policies\BookingPolicy;
use App\Policies\EventPolicy;
use App\Policies\FaqPolicy;
-use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
@@ -38,11 +37,5 @@ class AuthServiceProvider extends ServiceProvider
public function boot()
{
$this->registerPolicies();
-
- Gate::before(function ($user, $ability) {
- if ($user->isAdmin) {
- return true;
- }
- });
}
}
diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php
index 4b1c3b8e..ebe649cb 100644
--- a/app/Providers/EventServiceProvider.php
+++ b/app/Providers/EventServiceProvider.php
@@ -12,26 +12,7 @@ class EventServiceProvider extends ServiceProvider
*
* @var array
*/
- protected $listen = [
- 'App\Events\BookingConfirmed' => [
- 'App\Listeners\SendBookingConfirmedNotification',
- ],
- 'App\Events\BookingCancelled' => [
- 'App\Listeners\SendBookingCancelledNotification',
- ],
- 'App\Events\BookingChanged' => [
- 'App\Listeners\SendBookingChangedNotification',
- ],
- 'App\Events\BookingDeleted' => [
- 'App\Listeners\SendBookingDeletedNotification',
- ],
- 'App\Events\EventBulkEmail' => [
- 'App\Listeners\SendEventBulkEmailNotification',
- ],
- 'App\Events\EventFinalInformation' => [
- 'App\Listeners\SendEventFinalInformationNotification',
- ]
- ];
+ protected $listen = [];
/**
* Register any events for your application.
@@ -44,4 +25,14 @@ public function boot()
//
}
+
+ /**
+ * Determine if events and listeners should be automatically discovered.
+ *
+ * @return bool
+ */
+ public function shouldDiscoverEvents()
+ {
+ return true;
+ }
}
diff --git a/app/View/Components/FlatPickr.php b/app/View/Components/FlatPickr.php
deleted file mode 100644
index 6ea28ef9..00000000
--- a/app/View/Components/FlatPickr.php
+++ /dev/null
@@ -1,15 +0,0 @@
- true,
- 'altFormat' => 'F j, Y H:i\\z',
- 'ariaDateFormat' => 'F j, Y H:i'
- ], parent::options());
- }
-}
diff --git a/composer.json b/composer.json
index fc964e52..10de79f0 100644
--- a/composer.json
+++ b/composer.json
@@ -11,10 +11,10 @@
"php": "^8.1",
"aws/aws-sdk-php": "^3.209",
"bensampo/laravel-enum": "^5.0",
- "blade-ui-kit/blade-ui-kit": "^0.3.3",
"bugsnag/bugsnag-laravel": "^2.22",
"cviebrock/eloquent-sluggable": "^9.0",
"doctrine/dbal": "^3.3",
+ "filament/filament": "^2.13",
"laravel/framework": "^9.0",
"laravel/horizon": "^5.8",
"laravel/telescope": "^4.7",
@@ -78,7 +78,8 @@
"php artisan ide-helper:generate",
"php artisan ide-helper:meta",
"@php artisan telescope:publish --ansi",
- "@php artisan horizon:publish --ansi"
+ "@php artisan horizon:publish --ansi",
+ "@php artisan filament:upgrade"
]
},
"config": {
diff --git a/composer.lock b/composer.lock
index 4fbdcec0..27cd1c35 100644
--- a/composer.lock
+++ b/composer.lock
@@ -4,8 +4,76 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
- "content-hash": "f85bdd783395128c8d0055121d97841a",
+ "content-hash": "9d7660632990a6e10a2d4c63e7714ee2",
"packages": [
+ {
+ "name": "akaunting/laravel-money",
+ "version": "3.0.1",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/akaunting/laravel-money.git",
+ "reference": "22336631239eb008e26d322faa208cbc50757a38"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/akaunting/laravel-money/zipball/22336631239eb008e26d322faa208cbc50757a38",
+ "reference": "22336631239eb008e26d322faa208cbc50757a38",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/contracts": "^8.67|^9.0",
+ "illuminate/support": "^8.67|^9.0",
+ "illuminate/view": "^8.67|^9.0",
+ "php": "^8.0",
+ "vlucas/phpdotenv": "^5.4.1"
+ },
+ "require-dev": {
+ "orchestra/testbench": "^6.23|^7.4",
+ "phpunit/phpunit": "^9.5",
+ "vimeo/psalm": "^4.23"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Akaunting\\Money\\Provider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Akaunting\\Money\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Denis Duliçi",
+ "email": "info@akaunting.com",
+ "homepage": "https://akaunting.com",
+ "role": "Developer"
+ }
+ ],
+ "description": "Currency formatting and conversion package for Laravel",
+ "keywords": [
+ "convert",
+ "currency",
+ "format",
+ "laravel",
+ "money"
+ ],
+ "support": {
+ "issues": "https://github.com/akaunting/laravel-money/issues",
+ "source": "https://github.com/akaunting/laravel-money/tree/3.0.1"
+ },
+ "time": "2022-05-11T06:34:38+00:00"
+ },
{
"name": "aws/aws-crt-php",
"version": "v1.0.2",
@@ -235,50 +303,119 @@
"time": "2022-06-22T08:35:50+00:00"
},
{
- "name": "blade-ui-kit/blade-ui-kit",
- "version": "0.3.4",
+ "name": "blade-ui-kit/blade-heroicons",
+ "version": "1.3.1",
"source": {
"type": "git",
- "url": "https://github.com/blade-ui-kit/blade-ui-kit.git",
- "reference": "139f387d219bceb647c02d18c6b74cebb4c8dae6"
+ "url": "https://github.com/blade-ui-kit/blade-heroicons.git",
+ "reference": "a2749abc7b8eb6149ff643ffa99a3d33a2de7961"
},
"dist": {
"type": "zip",
- "url": "https://api.github.com/repos/blade-ui-kit/blade-ui-kit/zipball/139f387d219bceb647c02d18c6b74cebb4c8dae6",
- "reference": "139f387d219bceb647c02d18c6b74cebb4c8dae6",
+ "url": "https://api.github.com/repos/blade-ui-kit/blade-heroicons/zipball/a2749abc7b8eb6149ff643ffa99a3d33a2de7961",
+ "reference": "a2749abc7b8eb6149ff643ffa99a3d33a2de7961",
"shasum": ""
},
"require": {
- "ext-json": "*",
- "illuminate/filesystem": "^7.0|^8.0|^9.0",
- "illuminate/support": "^7.0|^8.0|^9.0",
- "illuminate/view": "^7.0|^8.0|^9.0",
- "nesbot/carbon": "^2.38",
- "php": "^7.3|^8.0"
+ "blade-ui-kit/blade-icons": "^1.1",
+ "illuminate/support": "^8.0|^9.0",
+ "php": "^7.4|^8.0"
},
"require-dev": {
- "gajus/dindent": "^2.0",
- "guzzlehttp/guzzle": "^7.4",
- "league/commonmark": "^1.4|^2.0",
- "lorisleiva/cron-translator": "^0.1.1",
- "orchestra/testbench": "^5.0|^6.0|^7.1",
+ "orchestra/testbench": "^6.0|^7.0",
"phpunit/phpunit": "^9.0"
},
- "suggest": {
- "league/commonmark": "Required to use the markdown component (^1.4).",
- "lorisleiva/cron-translator": "Required to use the cron component (^0.1.1)."
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "BladeUI\\Heroicons\\BladeHeroiconsServiceProvider"
+ ]
+ }
},
+ "autoload": {
+ "psr-4": {
+ "BladeUI\\Heroicons\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Dries Vints",
+ "homepage": "https://driesvints.com"
+ }
+ ],
+ "description": "A package to easily make use of Heroicons in your Laravel Blade views.",
+ "homepage": "https://github.com/blade-ui-kit/blade-heroicons",
+ "keywords": [
+ "Heroicons",
+ "blade",
+ "laravel"
+ ],
+ "support": {
+ "issues": "https://github.com/blade-ui-kit/blade-heroicons/issues",
+ "source": "https://github.com/blade-ui-kit/blade-heroicons/tree/1.3.1"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/caneco",
+ "type": "github"
+ },
+ {
+ "url": "https://github.com/driesvints",
+ "type": "github"
+ }
+ ],
+ "time": "2022-03-02T11:50:13+00:00"
+ },
+ {
+ "name": "blade-ui-kit/blade-icons",
+ "version": "1.3.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/blade-ui-kit/blade-icons.git",
+ "reference": "57a7c41e1e79e38aed029d3e6ae690b04344c99e"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/blade-ui-kit/blade-icons/zipball/57a7c41e1e79e38aed029d3e6ae690b04344c99e",
+ "reference": "57a7c41e1e79e38aed029d3e6ae690b04344c99e",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/contracts": "^8.0|^9.0",
+ "illuminate/filesystem": "^8.0|^9.0",
+ "illuminate/support": "^8.0|^9.0",
+ "illuminate/view": "^8.0|^9.0",
+ "php": "^7.4|^8.0",
+ "symfony/console": "^5.3|^6.0",
+ "symfony/finder": "^5.3|^6.0"
+ },
+ "require-dev": {
+ "mockery/mockery": "^1.3",
+ "orchestra/testbench": "^6.0|^7.0",
+ "phpunit/phpunit": "^9.0"
+ },
+ "bin": [
+ "bin/blade-icons-generate"
+ ],
"type": "library",
"extra": {
"laravel": {
"providers": [
- "BladeUIKit\\BladeUIKitServiceProvider"
+ "BladeUI\\Icons\\BladeIconsServiceProvider"
]
}
},
"autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
"psr-4": {
- "BladeUIKit\\": "src"
+ "BladeUI\\Icons\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
@@ -291,16 +428,17 @@
"homepage": "https://driesvints.com"
}
],
- "description": "A set of renderless components to utilise in your Laravel Blade views.",
- "homepage": "https://github.com/blade-ui-kit/blade-ui-kit",
+ "description": "A package to easily make use of icons in your Laravel Blade views.",
+ "homepage": "https://github.com/blade-ui-kit/blade-icons",
"keywords": [
"blade",
+ "icons",
"laravel",
- "ui"
+ "svg"
],
"support": {
- "issues": "https://github.com/blade-ui-kit/blade-ui-kit/issues",
- "source": "https://github.com/blade-ui-kit/blade-ui-kit"
+ "issues": "https://github.com/blade-ui-kit/blade-icons/issues",
+ "source": "https://github.com/blade-ui-kit/blade-icons"
},
"funding": [
{
@@ -312,7 +450,7 @@
"type": "github"
}
],
- "time": "2022-04-17T13:03:05+00:00"
+ "time": "2022-05-11T12:38:11+00:00"
},
{
"name": "brick/math",
@@ -1323,6 +1461,111 @@
],
"time": "2022-01-25T02:55:58+00:00"
},
+ {
+ "name": "danharrin/date-format-converter",
+ "version": "v0.2.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danharrin/date-format-converter.git",
+ "reference": "ee448ab0cbe2ea36edb886a01670fc760e388f19"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danharrin/date-format-converter/zipball/ee448ab0cbe2ea36edb886a01670fc760e388f19",
+ "reference": "ee448ab0cbe2ea36edb886a01670fc760e388f19",
+ "shasum": ""
+ },
+ "require": {
+ "php": "^7.2|^8.0"
+ },
+ "type": "library",
+ "autoload": {
+ "files": [
+ "src/helpers.php",
+ "src/standards.php"
+ ],
+ "psr-4": {
+ "DanHarrin\\DateFormatConverter\\": "src/"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Dan Harrin",
+ "email": "dan@danharrin.com"
+ }
+ ],
+ "description": "Convert token-based date formats between standards.",
+ "homepage": "https://github.com/danharrin/date-format-converter",
+ "support": {
+ "issues": "https://github.com/danharrin/date-format-converter/issues",
+ "source": "https://github.com/danharrin/date-format-converter"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/danharrin",
+ "type": "github"
+ }
+ ],
+ "time": "2021-02-10T23:58:47+00:00"
+ },
+ {
+ "name": "danharrin/livewire-rate-limiting",
+ "version": "v1.0.0",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/danharrin/livewire-rate-limiting.git",
+ "reference": "b99facf5b607fb0cde92a6f254f437295339f7de"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/danharrin/livewire-rate-limiting/zipball/b99facf5b607fb0cde92a6f254f437295339f7de",
+ "reference": "b99facf5b607fb0cde92a6f254f437295339f7de",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/support": "^8.0|^9.0",
+ "php": "^8.0"
+ },
+ "require-dev": {
+ "livewire/livewire": "^2.3",
+ "orchestra/testbench": "^6.2|^7.0",
+ "phpunit/phpunit": "^9.4",
+ "symplify/monorepo-builder": "^9.0"
+ },
+ "type": "library",
+ "autoload": {
+ "psr-4": {
+ "DanHarrin\\LivewireRateLimiting\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "authors": [
+ {
+ "name": "Dan Harrin",
+ "email": "dan@danharrin.com"
+ }
+ ],
+ "description": "Apply rate limiters to Laravel Livewire actions.",
+ "homepage": "https://github.com/danharrin/livewire-rate-limiting",
+ "support": {
+ "issues": "https://github.com/danharrin/livewire-rate-limiting/issues",
+ "source": "https://github.com/danharrin/livewire-rate-limiting"
+ },
+ "funding": [
+ {
+ "url": "https://github.com/danharrin",
+ "type": "github"
+ }
+ ],
+ "time": "2022-01-21T11:26:58+00:00"
+ },
{
"name": "dflydev/dot-access-data",
"version": "v3.0.1",
@@ -2086,6 +2329,227 @@
},
"time": "2021-12-25T01:21:49+00:00"
},
+ {
+ "name": "filament/filament",
+ "version": "v2.13.14",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/filamentphp/admin.git",
+ "reference": "88324f6375c1af1ede797b48ad6f25ddeecbc632"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/filamentphp/admin/zipball/88324f6375c1af1ede797b48ad6f25ddeecbc632",
+ "reference": "88324f6375c1af1ede797b48ad6f25ddeecbc632",
+ "shasum": ""
+ },
+ "require": {
+ "danharrin/livewire-rate-limiting": "^0.3|^1.0",
+ "filament/forms": "self.version",
+ "filament/support": "self.version",
+ "filament/tables": "self.version",
+ "illuminate/auth": "^8.6|^9.0",
+ "illuminate/console": "^8.6|^9.0",
+ "illuminate/contracts": "^8.6|^9.0",
+ "illuminate/cookie": "^8.6|^9.0",
+ "illuminate/database": "^8.6|^9.0",
+ "illuminate/http": "^8.6|^9.0",
+ "illuminate/routing": "^8.6|^9.0",
+ "illuminate/session": "^8.6|^9.0",
+ "illuminate/support": "^8.6|^9.0",
+ "illuminate/view": "^8.6|^9.0",
+ "livewire/livewire": "^2.6",
+ "php": "^8.0",
+ "spatie/laravel-package-tools": "^1.9"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Filament\\FilamentServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Filament\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Effortlessly build TALL-powered admin panels.",
+ "homepage": "https://github.com/filamentphp/filament",
+ "support": {
+ "issues": "https://github.com/filamentphp/filament/issues",
+ "source": "https://github.com/filamentphp/filament"
+ },
+ "time": "2022-06-30T11:55:54+00:00"
+ },
+ {
+ "name": "filament/forms",
+ "version": "v2.13.14",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/filamentphp/forms.git",
+ "reference": "c40a067644b8b0bf40a17b236b22d2ef31489a8d"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/filamentphp/forms/zipball/c40a067644b8b0bf40a17b236b22d2ef31489a8d",
+ "reference": "c40a067644b8b0bf40a17b236b22d2ef31489a8d",
+ "shasum": ""
+ },
+ "require": {
+ "blade-ui-kit/blade-heroicons": "^1.2",
+ "danharrin/date-format-converter": "^0.2",
+ "filament/support": "self.version",
+ "illuminate/console": "^8.6|^9.0",
+ "illuminate/contracts": "^8.6|^9.0",
+ "illuminate/database": "^8.6|^9.0",
+ "illuminate/filesystem": "^8.6|^9.0",
+ "illuminate/support": "^8.6|^9.0",
+ "illuminate/validation": "^8.6|^9.0",
+ "illuminate/view": "^8.6|^9.0",
+ "livewire/livewire": "^2.6",
+ "php": "^8.0",
+ "spatie/laravel-package-tools": "^1.9"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Filament\\Forms\\FormsServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Filament\\Forms\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Effortlessly build TALL-powered forms.",
+ "homepage": "https://github.com/filamentphp/filament",
+ "support": {
+ "issues": "https://github.com/filamentphp/filament/issues",
+ "source": "https://github.com/filamentphp/filament"
+ },
+ "time": "2022-06-30T11:56:23+00:00"
+ },
+ {
+ "name": "filament/support",
+ "version": "v2.13.14",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/filamentphp/support.git",
+ "reference": "7ede0b21503000d11aed71e088f5f1b268bab0e5"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/filamentphp/support/zipball/7ede0b21503000d11aed71e088f5f1b268bab0e5",
+ "reference": "7ede0b21503000d11aed71e088f5f1b268bab0e5",
+ "shasum": ""
+ },
+ "require": {
+ "illuminate/contracts": "^8.6|^9.0",
+ "illuminate/support": "^8.6|^9.0",
+ "illuminate/view": "^8.6|^9.0",
+ "php": "^8.0",
+ "spatie/laravel-package-tools": "^1.9"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Filament\\Support\\SupportServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "files": [
+ "src/helpers.php"
+ ],
+ "psr-4": {
+ "Filament\\Support\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Associated helper methods and foundation code for Filament packages.",
+ "homepage": "https://github.com/filamentphp/filament",
+ "support": {
+ "issues": "https://github.com/filamentphp/filament/issues",
+ "source": "https://github.com/filamentphp/filament"
+ },
+ "time": "2022-06-29T21:09:03+00:00"
+ },
+ {
+ "name": "filament/tables",
+ "version": "v2.13.14",
+ "source": {
+ "type": "git",
+ "url": "https://github.com/filamentphp/tables.git",
+ "reference": "3d60211628dc237d98727c4deb157b0897a936fb"
+ },
+ "dist": {
+ "type": "zip",
+ "url": "https://api.github.com/repos/filamentphp/tables/zipball/3d60211628dc237d98727c4deb157b0897a936fb",
+ "reference": "3d60211628dc237d98727c4deb157b0897a936fb",
+ "shasum": ""
+ },
+ "require": {
+ "akaunting/laravel-money": "^1.2|^2.0|^3.0",
+ "blade-ui-kit/blade-heroicons": "^1.2",
+ "filament/forms": "self.version",
+ "filament/support": "self.version",
+ "illuminate/console": "^8.6|^9.0",
+ "illuminate/contracts": "^8.6|^9.0",
+ "illuminate/database": "^8.6|^9.0",
+ "illuminate/filesystem": "^8.6|^9.0",
+ "illuminate/support": "^8.6|^9.0",
+ "illuminate/view": "^8.6|^9.0",
+ "livewire/livewire": "^2.6",
+ "php": "^8.0",
+ "spatie/laravel-package-tools": "^1.9"
+ },
+ "type": "library",
+ "extra": {
+ "laravel": {
+ "providers": [
+ "Filament\\Tables\\TablesServiceProvider"
+ ]
+ }
+ },
+ "autoload": {
+ "psr-4": {
+ "Filament\\Tables\\": "src"
+ }
+ },
+ "notification-url": "https://packagist.org/downloads/",
+ "license": [
+ "MIT"
+ ],
+ "description": "Effortlessly build TALL-powered tables.",
+ "homepage": "https://github.com/filamentphp/filament",
+ "support": {
+ "issues": "https://github.com/filamentphp/filament/issues",
+ "source": "https://github.com/filamentphp/filament"
+ },
+ "time": "2022-06-30T11:55:52+00:00"
+ },
{
"name": "fruitcake/php-cors",
"version": "v1.2.0",
diff --git a/config/blade-ui-kit.php b/config/blade-ui-kit.php
deleted file mode 100644
index 0a18797c..00000000
--- a/config/blade-ui-kit.php
+++ /dev/null
@@ -1,132 +0,0 @@
- [
- // 'alert' => Components\Alerts\Alert::class,
- // 'avatar' => Components\Support\Avatar::class,
- // 'carbon' => Components\DateTime\Carbon::class,
- // 'checkbox' => Components\Forms\Inputs\Checkbox::class,
- // 'color-picker' => Components\Forms\Inputs\ColorPicker::class,
- // 'countdown' => Components\DateTime\Countdown::class,
- // 'cron' => Components\Support\Cron::class,
- // 'dropdown' => Components\Navigation\Dropdown::class,
- // 'easy-mde' => Components\Editors\EasyMDE::class,
- // 'email' => Components\Forms\Inputs\Email::class,
- // 'error' => Components\Forms\Error::class,
- 'flat-pickr' => FlatPickr::class,
- // 'form' => Components\Forms\Form::class,
- // 'form-button' => Components\Buttons\FormButton::class,
- // 'html' => Components\Layouts\Html::class,
- // 'input' => Components\Forms\Inputs\Input::class,
- // 'label' => Components\Forms\Label::class,
- // 'logout' => Components\Buttons\Logout::class,
- // 'mapbox' => Components\Maps\Mapbox::class,
- // 'markdown' => Components\Markdown\Markdown::class,
- // 'password' => Components\Forms\Inputs\Password::class,
- // 'pikaday' => Components\Forms\Inputs\Pikaday::class,
- // 'social-meta' => Components\Layouts\SocialMeta::class,
- // 'textarea' => Components\Forms\Inputs\Textarea::class,
- // 'toc' => Components\Markdown\ToC::class,
- // 'trix' => Components\Editors\Trix::class,
- // 'unsplash' => Components\Support\Unsplash::class,
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Livewire Components
- |--------------------------------------------------------------------------
- |
- | Below you reference all the Livewire components that should be loaded
- | for your app. By default all components from Blade UI Kit are loaded in.
- |
- */
-
- 'livewire' => [
- //
- ],
-
- /*
- |--------------------------------------------------------------------------
- | Components Prefix
- |--------------------------------------------------------------------------
- |
- | This value will set a prefix for all Blade UI Kit components.
- | By default it's empty. This is useful if you want to avoid
- | collision with components from other libraries.
- |
- | If set with "buk", for example, you can reference components like:
- |
- |
- |
- */
-
- 'prefix' => '',
-
- /*
- |--------------------------------------------------------------------------
- | Third Party Asset Libraries
- |--------------------------------------------------------------------------
- |
- | These settings hold reference to all third party libraries and their
- | asset files served through a CDN. Individual components can require
- | these asset files through their static `$assets` property.
- |
- */
-
- 'assets' => [
-
- 'alpine' => 'https://cdn.jsdelivr.net/gh/alpinejs/alpine@v2.3.5/dist/alpine.min.js',
-
- 'easy-mde' => [
- 'https://unpkg.com/easymde/dist/easymde.min.css',
- 'https://unpkg.com/easymde/dist/easymde.min.js',
- ],
-
- 'flat-pickr' => [
- 'https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css',
- 'https://cdn.jsdelivr.net/npm/flatpickr@4.6.9/dist/flatpickr.min.js',
- ],
-
- 'mapbox' => [
- 'https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.css',
- 'https://api.mapbox.com/mapbox-gl-js/v1.8.1/mapbox-gl.js',
- ],
-
- 'moment' => [
- 'https://cdn.jsdelivr.net/npm/moment@2.26.0/moment.min.js',
- 'https://cdn.jsdelivr.net/npm/moment-timezone@0.5.31/builds/moment-timezone-with-data.min.js',
- ],
-
- 'pickr' => [
- 'https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/themes/classic.min.css',
- 'https://cdn.jsdelivr.net/npm/@simonwep/pickr/dist/pickr.min.js',
- ],
-
- 'pikaday' => [
- 'https://cdn.jsdelivr.net/npm/pikaday/css/pikaday.css',
- 'https://cdn.jsdelivr.net/npm/pikaday/pikaday.js',
- ],
-
- 'trix' => [
- 'https://unpkg.com/trix@1.2.3/dist/trix.css',
- 'https://unpkg.com/trix@1.2.3/dist/trix.js',
- ],
-
- ],
-
-];
diff --git a/config/filament.php b/config/filament.php
new file mode 100644
index 00000000..035edc3a
--- /dev/null
+++ b/config/filament.php
@@ -0,0 +1,254 @@
+ env('FILAMENT_PATH', 'admin'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Filament Domain
+ |--------------------------------------------------------------------------
+ |
+ | You may change the domain where Filament should be active. If the domain
+ | is empty, all domains will be valid.
+ |
+ */
+
+ 'domain' => env('FILAMENT_DOMAIN'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Homepage URL
+ |--------------------------------------------------------------------------
+ |
+ | This is the URL that Filament will redirect the user to when they click
+ | on the sidebar's header.
+ |
+ */
+
+ 'home_url' => '/',
+
+ /*
+ |--------------------------------------------------------------------------
+ | Brand Name
+ |--------------------------------------------------------------------------
+ |
+ | This will be displayed on the login page and in the sidebar's header.
+ |
+ */
+
+ 'brand' => env('APP_NAME'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Auth
+ |--------------------------------------------------------------------------
+ |
+ | This is the configuration that Filament will use to handle authentication
+ | into the admin panel.
+ |
+ */
+
+ 'auth' => [
+ 'guard' => env('FILAMENT_AUTH_GUARD', 'web'),
+ 'pages' => [
+ 'login' => \Filament\Http\Livewire\Auth\Login::class,
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Pages
+ |--------------------------------------------------------------------------
+ |
+ | This is the namespace and directory that Filament will automatically
+ | register pages from. You may also register pages here.
+ |
+ */
+
+ 'pages' => [
+ 'namespace' => 'App\\Filament\\Pages',
+ 'path' => app_path('Filament/Pages'),
+ 'register' => [
+ Pages\Dashboard::class,
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Resources
+ |--------------------------------------------------------------------------
+ |
+ | This is the namespace and directory that Filament will automatically
+ | register resources from. You may also register resources here.
+ |
+ */
+
+ 'resources' => [
+ 'namespace' => 'App\\Filament\\Resources',
+ 'path' => app_path('Filament/Resources'),
+ 'register' => [],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Widgets
+ |--------------------------------------------------------------------------
+ |
+ | This is the namespace and directory that Filament will automatically
+ | register dashboard widgets from. You may also register widgets here.
+ |
+ */
+
+ 'widgets' => [
+ 'namespace' => 'App\\Filament\\Widgets',
+ 'path' => app_path('Filament/Widgets'),
+ 'register' => [
+ Widgets\AccountWidget::class,
+ Widgets\FilamentInfoWidget::class,
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Livewire
+ |--------------------------------------------------------------------------
+ |
+ | This is the namespace and directory that Filament will automatically
+ | register Livewire components inside.
+ |
+ */
+
+ 'livewire' => [
+ 'namespace' => 'App\\Filament',
+ 'path' => app_path('Filament'),
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Dark mode
+ |--------------------------------------------------------------------------
+ |
+ | By enabling this feature, your users are able to select between a light
+ | and dark appearance for the admin panel, or let their system decide.
+ |
+ */
+
+ 'dark_mode' => true,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Layout
+ |--------------------------------------------------------------------------
+ |
+ | This is the configuration for the general layout of the admin panel.
+ |
+ | You may configure the max content width from `xl` to `7xl`, or `full`
+ | for no max width.
+ |
+ */
+
+ 'layout' => [
+ 'forms' => [
+ 'actions' => [
+ 'alignment' => 'left',
+ ],
+ ],
+ 'footer' => [
+ 'should_show_logo' => true,
+ ],
+ 'max_content_width' => null,
+ 'tables' => [
+ 'actions' => [
+ 'type' => \Filament\Tables\Actions\LinkAction::class,
+ ],
+ ],
+ ],
+
+ /*
+ |--------------------------------------------------------------------------
+ | Favicon
+ |--------------------------------------------------------------------------
+ |
+ | This is the path to the favicon used for pages in the admin panel.
+ |
+ */
+
+ 'favicon' => null,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default Avatar Provider
+ |--------------------------------------------------------------------------
+ |
+ | This is the service that will be used to retrieve default avatars if one
+ | has not been uploaded.
+ |
+ */
+
+ 'default_avatar_provider' => \Filament\AvatarProviders\UiAvatarsProvider::class,
+
+ /*
+ |--------------------------------------------------------------------------
+ | Default Filesystem Disk
+ |--------------------------------------------------------------------------
+ |
+ | This is the storage disk Filament will use to put media. You may use any
+ | of the disks defined in the `config/filesystems.php`.
+ |
+ */
+
+ 'default_filesystem_disk' => env('FILAMENT_FILESYSTEM_DRIVER', 'public'),
+
+ /*
+ |--------------------------------------------------------------------------
+ | Middleware
+ |--------------------------------------------------------------------------
+ |
+ | You may customise the middleware stack that Filament uses to handle
+ | requests.
+ |
+ */
+
+ 'middleware' => [
+ 'auth' => [
+ Authenticate::class,
+ ],
+ 'base' => [
+ EncryptCookies::class,
+ AddQueuedCookiesToResponse::class,
+ StartSession::class,
+ AuthenticateSession::class,
+ ShareErrorsFromSession::class,
+ VerifyCsrfToken::class,
+ SubstituteBindings::class,
+ DispatchServingFilamentEvent::class,
+ MirrorConfigToSubpackages::class,
+ ],
+ ],
+
+];
diff --git a/database/migrations/2022_02_25_212605_create_files_table.php b/database/migrations/2022_02_25_212605_create_files_table.php
new file mode 100644
index 00000000..827fc79b
--- /dev/null
+++ b/database/migrations/2022_02_25_212605_create_files_table.php
@@ -0,0 +1,34 @@
+id();
+ $table->morphs('fileable');
+ $table->string('path');
+ $table->string('disk');
+ $table->string('type');
+ $table->timestamps();
+ });
+ }
+
+ /**
+ * Reverse the migrations.
+ *
+ * @return void
+ */
+ public function down()
+ {
+ Schema::dropIfExists('files');
+ }
+};
diff --git a/package-lock.json b/package-lock.json
index fcc62069..9b3717a2 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -10,7 +10,6 @@
"dependencies": {
"alpinejs": "^3.10.2",
"bootswatch": "^4.6.1",
- "flatpickr": "^4.6.13",
"sweetalert2": "^11.4.19"
},
"devDependencies": {
@@ -39,8 +38,7 @@
"resolve-url-loader": "^5.0.0",
"sass": "^1.53.0",
"sass-loader": "^13.0.2",
- "semantic-release": "^19.0.3",
- "tinymce": "^6.1.0"
+ "semantic-release": "^19.0.3"
}
},
"node_modules/@ampproject/remapping": {
@@ -7069,11 +7067,6 @@
"node": ">= 8"
}
},
- "node_modules/flatpickr": {
- "version": "4.6.13",
- "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
- "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw=="
- },
"node_modules/follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
@@ -15933,12 +15926,6 @@
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
"dev": true
},
- "node_modules/tinymce": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.1.0.tgz",
- "integrity": "sha512-IdSdMlmuyhpEpUuabhBUaRC2NzZZxP2/CO/F+/54kTaAifB1Et5mKEty03pJYZxl6GBdFgclKRA2UU5JKJtJbA==",
- "dev": true
- },
"node_modules/tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
@@ -22498,11 +22485,6 @@
"resolve-dir": "^1.0.1"
}
},
- "flatpickr": {
- "version": "4.6.13",
- "resolved": "https://registry.npmjs.org/flatpickr/-/flatpickr-4.6.13.tgz",
- "integrity": "sha512-97PMG/aywoYpB4IvbvUJi0RQi8vearvU0oov1WW3k0WZPBMrTQVqekSX5CjSG/M4Q3i6A/0FKXC7RyAoAUUSPw=="
- },
"follow-redirects": {
"version": "1.14.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz",
@@ -29063,12 +29045,6 @@
"integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=",
"dev": true
},
- "tinymce": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/tinymce/-/tinymce-6.1.0.tgz",
- "integrity": "sha512-IdSdMlmuyhpEpUuabhBUaRC2NzZZxP2/CO/F+/54kTaAifB1Et5mKEty03pJYZxl6GBdFgclKRA2UU5JKJtJbA==",
- "dev": true
- },
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
diff --git a/package.json b/package.json
index 5a778e78..5e49f6d3 100644
--- a/package.json
+++ b/package.json
@@ -47,13 +47,11 @@
"resolve-url-loader": "^5.0.0",
"sass": "^1.53.0",
"sass-loader": "^13.0.2",
- "semantic-release": "^19.0.3",
- "tinymce": "^6.1.0"
+ "semantic-release": "^19.0.3"
},
"dependencies": {
"alpinejs": "^3.10.2",
"bootswatch": "^4.6.1",
- "flatpickr": "^4.6.13",
"sweetalert2": "^11.4.19"
},
"release": {
diff --git a/resources/js/alpine.js b/resources/js/alpine.js
index 91c700cd..df80acc4 100644
--- a/resources/js/alpine.js
+++ b/resources/js/alpine.js
@@ -3,7 +3,3 @@ import Alpine from 'alpinejs';
window.Alpine = Alpine;
Alpine.start();
-
-
-import flatpickr from 'flatpickr';
-window.flatPickr = flatpickr;
diff --git a/resources/js/tinymce.js b/resources/js/tinymce.js
deleted file mode 100644
index b25f5ba3..00000000
--- a/resources/js/tinymce.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// TinyMCE
-import tinymce from 'tinymce';
-import 'tinymce/plugins/code';
-import 'tinymce/plugins/link';
-
-tinymce.init({
- selector: 'textarea.tinymce',
- plugins: ['code', 'link']
-});
diff --git a/resources/sass/app.scss b/resources/sass/app.scss
index e0c9b5fd..b1023ebb 100644
--- a/resources/sass/app.scss
+++ b/resources/sass/app.scss
@@ -1,6 +1,3 @@
-// Flatpickr
-@import "flatpickr/dist/flatpickr.min.css";
-
// Bootswatch Flatly variables
@import 'bootswatch/dist/flatly/variables';
diff --git a/resources/views/airport/admin/form.blade.php b/resources/views/airport/admin/form.blade.php
deleted file mode 100644
index d926cd41..00000000
--- a/resources/views/airport/admin/form.blade.php
+++ /dev/null
@@ -1,35 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
-
-
-
-
-
-
-
-
-
- @bind($airport)
-
-
-
-
-
-
-
- @if ($airport->id)
- {{ __('Edit') }}
- @else
- {{ __('Add') }}
- @endif
-
- @endbind
-
-
-
-
-
-@endsection
diff --git a/resources/views/airport/admin/overview.blade.php b/resources/views/airport/admin/overview.blade.php
deleted file mode 100644
index 2c86f7d2..00000000
--- a/resources/views/airport/admin/overview.blade.php
+++ /dev/null
@@ -1,92 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
- Airports Overview
-
- @include('layouts.alert')
- @push('scripts')
-
- @endpush
-
-
- {{ $airports->links() }}
-
-@endsection
diff --git a/resources/views/airport/admin/show.blade.php b/resources/views/airport/admin/show.blade.php
deleted file mode 100644
index 421f9eb6..00000000
--- a/resources/views/airport/admin/show.blade.php
+++ /dev/null
@@ -1,27 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
-
-
-
-
-
-
-
- @foreach($airport->links as $link)
-
- @endforeach
-
-
-
-
-@endsection
diff --git a/resources/views/airportLink/admin/form.blade.php b/resources/views/airportLink/admin/form.blade.php
deleted file mode 100644
index dc42370b..00000000
--- a/resources/views/airportLink/admin/form.blade.php
+++ /dev/null
@@ -1,44 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
-
-
-
-
-
-
-
-
-
- @bind($airportLink)
-
- @if ($airportLink->id)
-
- {{ $airportLink->airport->icao }} [{{ $airportLink->airport->name }}
- ({{ $airportLink->airport->iata }})]
-
- @else
-
- @endif
-
-
-
-
- @if ($airportLink->id)
- {{ __('Edit') }}
- @else
- {{ __('Add') }}
- @endif
-
- @endbind
-
-
-
-
-
-@endsection
diff --git a/resources/views/airportLink/admin/overview.blade.php b/resources/views/airportLink/admin/overview.blade.php
deleted file mode 100644
index f6cb4c0d..00000000
--- a/resources/views/airportLink/admin/overview.blade.php
+++ /dev/null
@@ -1,66 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
- Airport Links Overview
- @include('layouts.alert')
- @push('scripts')
-
- @endpush
-
- Add new
- Airport
- Link
-
-
- {{ $airportLinks->links() }}
-@endsection
diff --git a/resources/views/booking/overview/default.blade.php b/resources/views/booking/overview/default.blade.php
index 0a4ade1c..dd695bb7 100644
--- a/resources/views/booking/overview/default.blade.php
+++ b/resources/views/booking/overview/default.blade.php
@@ -9,9 +9,6 @@
Callsign
Aircraft
Book | Available until {{ $event->endBooking->format('d-m-Y H:i') }}z
- @if (auth()->check() && auth()->user()->isAdmin && $event->endEvent >= now())
- Admin actions
- @endif
@foreach ($bookings as $booking)
@@ -62,7 +59,7 @@
@else
Reserved
- {{ auth()->check() && auth()->user()->isAdmin ? '[' . $booking->user->pic . ']' : '' }}
+
@endcan
@else
@if (auth()->check())
@@ -87,28 +84,6 @@
@endif
@endif
- @if (auth()->check() && auth()->user()->isAdmin && $event->endEvent >= now())
- Edit
-
-
-
-
-
- @if ($booking->user_id)
-
-
- Send E-mail [{{ $booking->user->email }}]
-
-
- @endif
-
- @endif
@endif
@endforeach
diff --git a/resources/views/booking/overview/multiflights.blade.php b/resources/views/booking/overview/multiflights.blade.php
index c153c916..0fd6cc05 100644
--- a/resources/views/booking/overview/multiflights.blade.php
+++ b/resources/views/booking/overview/multiflights.blade.php
@@ -5,9 +5,6 @@
Callsign
Aircraft
Book | Available until {{ $event->endBooking->format('d-m-Y H:i') }}z
- @if (auth()->check() && auth()->user()->isAdmin && $event->endEvent >= now())
- Admin actions
- @endif
@foreach ($bookings as $booking)
@@ -45,7 +42,7 @@
@else
Reserved
- {{ auth()->check() && auth()->user()->isAdmin ? '[' . $booking->user->pic . ']' : '' }}
+
@endcan
@else
@if (auth()->check())
@@ -70,27 +67,5 @@
@endif
@endif
- @if (auth()->check() && auth()->user()->isAdmin && $event->endEvent >= now())
- Edit
-
-
-
-
-
- @if ($booking->user_id)
-
-
- Send E-mail [{{ $booking->user->email }}]
-
-
- @endif
-
- @endif
@endforeach
diff --git a/resources/views/event/admin/form.blade.php b/resources/views/event/admin/form.blade.php
deleted file mode 100644
index c33212e0..00000000
--- a/resources/views/event/admin/form.blade.php
+++ /dev/null
@@ -1,120 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
-
-
-
-
-
-
-
-
- @bind($event)
-
-
-
-
- @slot('help')
-
- {{ __("Choose here if you want the event to be reachable by it's generated url") }}
-
- @endslot
-
-
-
-
-
- @slot('help')
-
- {{ __("Choose here if you want to show the event on the homepage. If turned off, the event can only be reached by the url. NOTE: If 'Show Online' is off, the event won't be shown at all") }}
-
- @endslot
-
-
-
-
-
-
-
-
-
- @slot('help')
-
- {{ __('If enabled, only admins can fill in details via import script') }}
-
- @endslot
-
-
-
-
-
- @slot('help')
-
- {{ __('If enabled, CTOT and ETA (if set in booking) will be shown') }}
-
- @endslot
-
-
-
-
-
- @slot('help')
-
- {{ __('If enabled, a user is allowed to book multiple flights for this event') }}
-
- @endslot
-
-
-
-
-
- @slot('help')
-
- {{ __('If enabled, users can fill in a SELCAL code') }}
-
- @endslot
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- @if ($event->id)
- {{ __('Edit') }}
- @else
- {{ __('Add') }}
- @endif
-
-
- @endbind
-
-
-
-
-
-@endsection
diff --git a/resources/views/eventLink/admin/form.blade.php b/resources/views/eventLink/admin/form.blade.php
deleted file mode 100644
index 4a20ce7d..00000000
--- a/resources/views/eventLink/admin/form.blade.php
+++ /dev/null
@@ -1,42 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
-
-
-
-
-
-
-
-
-
- @bind($eventLink)
-
- @if ($eventLink->id)
-
- {{ $eventLink->event->name }} [{{ $eventLink->event->startEvent->format('d-m-Y') }}]
-
- @else
-
- @endif
-
-
-
-
- @if ($eventLink->id)
- {{ __('Edit') }}
- @else
- {{ __('Add') }}
- @endif
-
- @endbind
-
-
-
-
-
-@endsection
diff --git a/resources/views/eventLink/admin/overview.blade.php b/resources/views/eventLink/admin/overview.blade.php
deleted file mode 100644
index 74c0b168..00000000
--- a/resources/views/eventLink/admin/overview.blade.php
+++ /dev/null
@@ -1,65 +0,0 @@
-@extends('layouts.app')
-
-@section('content')
- Event Links Overview
- @include('layouts.alert')
- @push('scripts')
-
- @endpush
-
- Add new
- Event
- Link
-
-
- {{ $eventLinks->links() }}
-@endsection
diff --git a/resources/views/filament/resources/event-resource/pages/assign-routes.blade.php b/resources/views/filament/resources/event-resource/pages/assign-routes.blade.php
new file mode 100644
index 00000000..0ce51173
--- /dev/null
+++ b/resources/views/filament/resources/event-resource/pages/assign-routes.blade.php
@@ -0,0 +1,16 @@
+
+
+ {{ $this->form }}
+
+
+
+ Submit
+
+
+ Download template
+
+
+
+
+
diff --git a/resources/views/filament/resources/event-resource/pages/import-bookings.blade.php b/resources/views/filament/resources/event-resource/pages/import-bookings.blade.php
new file mode 100644
index 00000000..82299ae4
--- /dev/null
+++ b/resources/views/filament/resources/event-resource/pages/import-bookings.blade.php
@@ -0,0 +1,16 @@
+
+
+ {{ $this->form }}
+
+
+
+ Submit
+
+
+ Download template
+
+
+
+
+
diff --git a/resources/views/filament/resources/event-resource/pages/send-email.blade.php b/resources/views/filament/resources/event-resource/pages/send-email.blade.php
new file mode 100644
index 00000000..9abb4bf1
--- /dev/null
+++ b/resources/views/filament/resources/event-resource/pages/send-email.blade.php
@@ -0,0 +1,21 @@
+
+
+ {{ $this->finalInformationEmailForm }}
+
+
+ Send Final Information E-mail
+
+
+
+
+
+
+
+ {{ $this->emailForm }}
+
+
+ Send E-mail
+
+
+
+
diff --git a/resources/views/layouts/navbar.blade.php b/resources/views/layouts/navbar.blade.php
index 4714b522..a197ac9f 100644
--- a/resources/views/layouts/navbar.blade.php
+++ b/resources/views/layouts/navbar.blade.php
@@ -60,26 +60,9 @@ class="fas fa-chevron-right"> {{ $bookings->count() > 1 ? $booking->cal
@auth
@if (auth()->user()->isAdmin)
-
-
- {{ __('Admin') }}
-
-
+
+ {{ __('Admin') }}
@endif
@endauth
diff --git a/routes/breadcrumbs.php b/routes/breadcrumbs.php
index b5b4c5d9..43050cdf 100644
--- a/routes/breadcrumbs.php
+++ b/routes/breadcrumbs.php
@@ -5,102 +5,6 @@
$trail->push('Home', route('home'));
});
-// Home > Admin
-Breadcrumbs::for('admin', function ($trail) {
- $trail->parent('home');
- $trail->push('Admin');
-});
-
-// Home > Admin > Airports
-Breadcrumbs::for('admin.airports.index', function ($trail) {
- $trail->parent('admin');
- $trail->push('Airports', route('admin.airports.index'));
-});
-
-// Home > Admin > Airports > New
-Breadcrumbs::for('admin.airports.create', function ($trail) {
- $trail->parent('admin.airports.index');
- $trail->push('New', route('admin.airports.create'));
-});
-
-// Home > Admin > Airports > [Airport]
-Breadcrumbs::for('admin.airports.show', function ($trail, $airport) {
- $trail->parent('admin.airports.index');
- $trail->push($airport->name . ' [' . $airport->icao . ' | ' . $airport->iata . ']', route('admin.airports.show', $airport));
-});
-
-// Home > Admin > Airports > [Airport] > Edit Airport
-Breadcrumbs::for('admin.airports.edit', function ($trail, $airport) {
- $trail->parent('admin.airports.show', $airport);
- $trail->push('Edit Airport', route('admin.airports.edit', $airport));
-});
-
-// Home > Admin > Airport Links
-Breadcrumbs::for('admin.airportLinks.index', function ($trail) {
- $trail->parent('admin');
- $trail->push('Airport Links', route('admin.airportLinks.index'));
-});
-
-// Home > Admin > Airport Links > New
-Breadcrumbs::for('admin.airportLinks.create', function ($trail) {
- $trail->parent('admin.airportLinks.index');
- $trail->push('New', route('admin.airportLinks.create'));
-});
-
-// Home > Admin > Airports > [Airport] > [Airport Link] > Edit Airport Link
-Breadcrumbs::for('admin.airportLinks.edit', function ($trail, $airportLink) {
- $trail->parent('admin.airports.show', $airportLink->airport);
- $trail->push('Edit Airport Link', route('admin.airportLinks.edit', $airportLink));
-});
-
-// Home > Admin > Event Links
-Breadcrumbs::for('admin.eventLinks.index', function ($trail) {
- $trail->parent('admin');
- $trail->push('Event Links', route('admin.eventLinks.index'));
-});
-
-// Home > Admin > Event Links > New
-Breadcrumbs::for('admin.eventLinks.create', function ($trail) {
- $trail->parent('admin.eventLinks.index');
- $trail->push('New', route('admin.eventLinks.create'));
-});
-
-// Home > Admin > Events > [Event] > [Event Link] > Edit Event Link
-Breadcrumbs::for('admin.eventLinks.edit', function ($trail, $eventLink) {
- $trail->parent('admin.events.show', $eventLink->event);
- $trail->push('Edit Airport Link', route('admin.eventLinks.edit', $eventLink));
-});
-
-// Home > Admin > Events
-Breadcrumbs::for('admin.events.index', function ($trail) {
- $trail->parent('admin');
- $trail->push('Events', route('admin.events.index'));
-});
-
-// Home > Admin > Events > [Event] > Edit event
-Breadcrumbs::for('admin.events.edit', function ($trail, $event) {
- $trail->parent('admin.events.show', $event);
- $trail->push('Edit Event', route('admin.events.edit', $event));
-});
-
-// Home > Admin > Events > New
-Breadcrumbs::for('admin.events.create', function ($trail) {
- $trail->parent('admin.events.index');
- $trail->push('New', route('admin.events.create'));
-});
-
-// Home > Admin > Events > [Event]
-Breadcrumbs::for('admin.events.show', function ($trail, $event) {
- $trail->parent('admin.events.index');
- $trail->push($event->name . ' [' . $event->startEvent->toFormattedDateString() . ']', route('admin.events.show', $event));
-});
-
-// Home > Admin > Events > [Event] > Send E-mail
-Breadcrumbs::for('admin.events.email.form', function ($trail, $event) {
- $trail->parent('admin.events.show', $event);
- $trail->push('Send E-mail', route('admin.events.email.form', $event));
-});
-
// Home (no event found)
Breadcrumbs::for('bookings.index', function ($trail) {
$trail->parent('home');
@@ -130,66 +34,12 @@
$trail->push('My Booking', route('bookings.show', $booking));
});
-// Home > Admin > [Event] > Add Slot
-Breadcrumbs::for('admin.bookings.create', function ($trail, $event) {
- $trail->parent('admin.events.show', $event);
- $trail->push('Add Slot(s)', route('admin.bookings.create', $event));
-});
-
-// Home > Admin > [Event] > Import
-Breadcrumbs::for('admin.bookings.importForm', function ($trail, $event) {
- $trail->parent('admin.events.show', $event);
- $trail->push('Import', route('admin.bookings.importForm', $event));
-});
-
-// Home > Admin > [Event] > Booking
-Breadcrumbs::for('admin.bookings.edit', function ($trail, $booking) {
- $trail->parent('admin.events.show', $booking->event);
- $trail->push('Edit Booking', route('admin.bookings.edit', $booking));
-});
-
-// Home > Admin > [Event] > Auto-Assign FL / Route
-Breadcrumbs::for('admin.bookings.autoAssignForm', function ($trail, $event) {
- $trail->parent('admin.events.show', $event);
- $trail->push('Auto-Assign FL / Route', route('admin.bookings.autoAssignForm', $event));
-});
-
-// Home > Admin > [Event] > Route assign
-Breadcrumbs::for('admin.bookings.routeAssignForm', function ($trail, $event) {
- $trail->parent('admin.events.show', $event);
- $trail->push('Route assign', route('admin.bookings.routeAssignForm', $event));
-});
-
// Home > FAQ
Breadcrumbs::for('faq', function ($trail) {
$trail->parent('home');
$trail->push('FAQ', route('faq'));
});
-// Home > Admin > FAQ
-Breadcrumbs::for('admin.faq.index', function ($trail) {
- $trail->parent('admin');
- $trail->push('FAQ', route('admin.faq.index'));
-});
-
-// Home > Admin > FAQ > New
-Breadcrumbs::for('admin.faq.create', function ($trail) {
- $trail->parent('admin.faq.index');
- $trail->push('New', route('admin.faq.create'));
-});
-
-// Home > Admin > FAQ > [FAQ]
-Breadcrumbs::for('admin.faq.show', function ($trail, $faq) {
- $trail->parent('admin.faq.index');
- $trail->push('[' . $faq->id . '] ' . $faq->question);
-});
-
-// Home > Admin > FAQ > [FAQ] > Edit FAQ
-Breadcrumbs::for('admin.faq.edit', function ($trail, $faq) {
- $trail->parent('admin.faq.show', $faq);
- $trail->push('Edit FAQ', route('admin.faq.edit', $faq));
-});
-
// Home > My settings
Breadcrumbs::for('user.settings', function ($trail) {
$trail->parent('home');
diff --git a/routes/web.php b/routes/web.php
index ce870118..88fc688f 100644
--- a/routes/web.php
+++ b/routes/web.php
@@ -5,13 +5,8 @@
use App\Http\Controllers\User\UserController;
use App\Http\Controllers\Auth\LoginController;
use App\Http\Controllers\Event\EventController;
-use App\Http\Controllers\Faq\FaqAdminController;
use App\Http\Controllers\Booking\BookingController;
-use App\Http\Controllers\Event\EventAdminController;
-use App\Http\Controllers\Airport\AirportAdminController;
use App\Http\Controllers\Booking\BookingAdminController;
-use App\Http\Controllers\AirportLink\AirportLinkAdminController;
-use App\Http\Controllers\EventLink\EventLinkAdminController;
/*
|--------------------------------------------------------------------------
@@ -29,35 +24,15 @@
Route::get('/login', [LoginController::class, 'login'])->name('login');
Route::get('/logout', [LoginController::class, 'logout'])->name('logout');
+Route::get('admin/login', function () {
+ // Just redirect to login, we don't work with passwords
+ return to_route('login');
+})->name('filament.auth.login');
+
// Admin routes
Route::group(['as' => 'admin.', 'prefix' => 'admin', 'middleware' => 'auth.isAdmin'], function () {
- // Airports
- Route::post('airports/destroy-unused', [AirportAdminController::class, 'destroyUnused'])->name('airports.destroyUnused');
- Route::resource('airports', AirportAdminController::class);
-
- // AirportLinks
- Route::resource('airportLinks', AirportLinkAdminController::class)->except(['show']);
-
- // EventLinks
- Route::resource('eventLinks', EventLinkAdminController::class)->except(['show']);
-
- // Faq
- Route::resource('faq', FaqAdminController::class)->except('show');
- Route::patch('faq/{faq}/toggle-event/{event}', [FaqAdminController::class, 'toggleEvent'])->name('faq.toggleEvent');
-
- // Event
- Route::delete('events/{event}/delete-bookings', [EventAdminController::class, 'deleteAllBookings'])->name('events.delete-bookings');
- Route::resource('events', EventAdminController::class);
- Route::get('{event}/email', [EventAdminController::class, 'sendEmailForm'])->name('events.email.form');
- Route::patch('{event}/email', [EventAdminController::class, 'sendEmail'])->name('events.email');
- Route::patch(
- '{event}/email_final',
- [EventAdminController::class, 'sendFinalInformationMail']
- )->name('events.email.final');
-
// Booking
Route::resource('bookings', BookingAdminController::class)->except(['index', 'create', 'show']);
- Route::get('{event}/bookings/export/{vacc?}', [BookingAdminController::class, 'export'])->name('bookings.export');
Route::get('{event}/bookings/create/{bulk?}', [BookingAdminController::class, 'create'])->name('bookings.create');
Route::get('{event}/bookings/import', [BookingAdminController::class, 'importForm'])->name('bookings.importForm');
Route::post('{event}/bookings/import', [BookingAdminController::class, 'import'])->name('bookings.import');
diff --git a/webpack.mix.js b/webpack.mix.js
index 2ee9411a..6179e70f 100644
--- a/webpack.mix.js
+++ b/webpack.mix.js
@@ -17,22 +17,14 @@ require('dotenv').config();
mix.js('resources/js/app.js', 'public/js')
.js('resources/js/alpine.js', 'public/js')
- .js('resources/js/tinymce.js', 'public/js')
.sass('resources/sass/app.scss', 'public/css', {
additionalData: '$envColorPrimary: ' + (process.env.BOOTSTRAP_COLOR_PRIMARY || '#2C3E50') + '; $envColorSecondary: ' + (process.env.BOOTSTRAP_COLOR_SECONDARY || '#95a5a6') + '; $envColorTertiary: ' + (process.env.BOOTSTRAP_COLOR_TERTIARY || '#18BC9C') + '; $envColorSuccess: ' + (process.env.BOOTSTRAP_COLOR_SUCCESS || '#18BC9C') + '; $envColorWarning: ' + (process.env.BOOTSTRAP_COLOR_WARNING || '#F39C12') + '; $envColorDanger: ' + (process.env.BOOTSTRAP_COLOR_DANGER || '#E74C3C') + ';'
})
.purgeCss({
extend: {
content: [path.join(__dirname, 'vendor/laravel/framework/src/Illuminate/Pagination/resources/views/*bootstrap-4.blade.php')],
- safelist: {
- deep: [/\b(ui|flatpickr)-\S*$/]
- }
},
})
- .copyDirectory('node_modules/tinymce/icons', 'public/js/icons')
- .copyDirectory('node_modules/tinymce/models', 'public/js/models')
- .copyDirectory('node_modules/tinymce/themes', 'public/js/themes')
- .copyDirectory('node_modules/tinymce/skins', 'public/js/skins')
.extract();
if (mix.inProduction()) {