Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: replace admin with filament #517

Merged
merged 36 commits into from
Jul 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
f59df0c
Require filament and basic setup
daveroverts Feb 17, 2022
427a4dd
Airport
daveroverts Feb 18, 2022
8aa2e14
Airport link
daveroverts Feb 18, 2022
3e29339
WIP Event
daveroverts Feb 18, 2022
693bc14
Event link
daveroverts Feb 19, 2022
f5970a7
Faq
daveroverts Feb 19, 2022
e939ac3
Add some filters to EventResource
daveroverts Feb 19, 2022
d879382
Faq - Event
daveroverts Feb 19, 2022
675cb1a
Better search support
daveroverts Feb 19, 2022
c9b62da
Remove admin actions from booking.overview views
daveroverts Feb 19, 2022
666d9b7
WIP Event -> Bookings
daveroverts Feb 19, 2022
8b4be8c
Move Event form stuff to a Trait
daveroverts Feb 19, 2022
00eb70c
WIP Booking form
daveroverts Feb 19, 2022
2850860
WIP
daveroverts Feb 20, 2022
b3e0a1b
FAQ -> Event: Override form to improve select
daveroverts Feb 21, 2022
80a1488
Remove packages we don't need anymore
daveroverts Feb 24, 2022
1045ba2
Add ability to remove unused airports
daveroverts Feb 24, 2022
9978745
Move global before gate to policies
daveroverts Feb 24, 2022
0c364d9
Delete FlatPickr.php
daveroverts Feb 25, 2022
fd1bdde
Admins should be able to do stuff
daveroverts Feb 25, 2022
b6afc1e
Add view page. Prevent update and destroy after event started
daveroverts Feb 25, 2022
b9d9080
WIP import bookings
daveroverts Feb 25, 2022
5da280e
Finally got booking import working
daveroverts Feb 26, 2022
0b09dc5
Apply fixes from StyleCI
StyleCIBot Feb 26, 2022
ca66fe0
Fix BookingsImport when using sync driver
daveroverts Feb 26, 2022
fa7bec3
Email
daveroverts Feb 26, 2022
06f942e
Admins are allowed to create events
daveroverts Feb 27, 2022
72b4cef
Regenerate phpdoc for models
daveroverts Feb 27, 2022
a8b9574
Add bookings export
daveroverts Feb 27, 2022
afb6e11
Fix ImportBookings page not working
daveroverts Feb 27, 2022
a79daf4
Add AssignRoutes (for multi flight events)
daveroverts Feb 27, 2022
5f0846b
Add type filter for events
daveroverts Feb 27, 2022
0ae05b6
Disable create booking form for the moment
daveroverts Mar 13, 2022
4bd1451
Re-enable create booking. It now finally works with flight relation
daveroverts May 3, 2022
883d160
Fix for undefined EventType
daveroverts Jul 1, 2022
9f83939
Merge branch 'beta' into feature/filament
daveroverts Jul 1, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -91,3 +92,5 @@ IGNITION_EDITOR=vscode
IGNITION_THEME=auto
IGNITION_REMOTE_SITES_PATH=
IGNITION_LOCAL_SITES_PATH=

FILAMENT_FILESYSTEM_DRIVER=public
2 changes: 2 additions & 0 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
39 changes: 39 additions & 0 deletions app/Events/FileCreated.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace App\Events;

use App\Models\File;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;

class FileCreated
{
use Dispatchable;
use InteractsWithSockets;
use SerializesModels;

/**
* Create a new event instance.
*
* @return void
*/
public function __construct(public File $file)
{
//
}

/**
* Get the channels the event should broadcast on.
*
* @return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
102 changes: 102 additions & 0 deletions app/Filament/Resources/AirportResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

namespace App\Filament\Resources;

use Filament\Forms;
use Filament\Tables;
use App\Models\Airport;
use Filament\Resources\Form;
use Filament\Resources\Table;
use Filament\Resources\Resource;
use Filament\Tables\Actions\Action;
use Illuminate\Database\Eloquent\Model;
use App\Filament\Resources\AirportResource\Pages;
use App\Filament\Resources\AirportResource\RelationManagers;
use Filament\Tables\Actions\ButtonAction;

class AirportResource extends Resource
{
protected static ?string $model = Airport::class;

protected static ?string $navigationIcon = 'heroicon-o-paper-airplane';

public static ?string $recordTitleAttribute = 'name';

public static function getGloballySearchableAttributes(): array
{
return ['icao', 'iata', 'name'];
}

public static function getGlobalSearchResultDetails(Model $record): array
{
return [
'ICAO' => $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'),
];
}
}
11 changes: 11 additions & 0 deletions app/Filament/Resources/AirportResource/Pages/CreateAirport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace App\Filament\Resources\AirportResource\Pages;

use App\Filament\Resources\AirportResource;
use Filament\Resources\Pages\CreateRecord;

class CreateAirport extends CreateRecord
{
protected static string $resource = AirportResource::class;
}
11 changes: 11 additions & 0 deletions app/Filament/Resources/AirportResource/Pages/EditAirport.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace App\Filament\Resources\AirportResource\Pages;

use App\Filament\Resources\AirportResource;
use Filament\Resources\Pages\EditRecord;

class EditAirport extends EditRecord
{
protected static string $resource = AirportResource::class;
}
11 changes: 11 additions & 0 deletions app/Filament/Resources/AirportResource/Pages/ListAirports.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace App\Filament\Resources\AirportResource\Pages;

use App\Filament\Resources\AirportResource;
use Filament\Resources\Pages\ListRecords;

class ListAirports extends ListRecords
{
protected static string $resource = AirportResource::class;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace App\Filament\Resources\AirportResource\RelationManagers;

use Filament\Forms;
use Filament\Tables;
use Filament\Resources\Form;
use Filament\Resources\Table;
use App\Models\AirportLinkType;
use Filament\Resources\RelationManagers\HasManyRelationManager;

class LinksRelationManager extends HasManyRelationManager
{
protected static string $relationship = 'links';

protected static ?string $recordTitleAttribute = 'icao';

public static function form(Form $form): Form
{
return $form
->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([
//
]);
}
}
130 changes: 130 additions & 0 deletions app/Filament/Resources/EventResource.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
<?php

namespace App\Filament\Resources;

use App\Enums\EventType;
use App\Exports\BookingsExport;
use App\Filament\Resources\EventResource\Pages;
use App\Filament\Resources\EventResource\RelationManagers;
use App\Filament\Resources\EventResource\Traits\EventForm;
use App\Models\Event;
use App\Models\EventType as ModelsEventType;
use Filament\Forms\Components\Toggle;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Filament\Tables\Actions\ButtonAction;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Filters\SelectFilter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Symfony\Component\HttpFoundation\BinaryFileResponse;

class EventResource extends Resource
{
use EventForm;

protected static ?string $model = Event::class;

protected static ?string $navigationIcon = 'heroicon-o-collection';

protected static ?string $recordTitleAttribute = 'name';

public static function getGlobalSearchResultDetails(Model $record): array
{
return [
'Type' => $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')
];
}
}
Loading