Skip to content

Commit

Permalink
feat: replace admin with filament (#517)
Browse files Browse the repository at this point in the history
This replaces the admin with Filament

BREAKING CHANGE: Admin replaced with Filament
fix #432
  • Loading branch information
daveroverts authored Jul 1, 2022
1 parent 2e101bb commit 5b3f87e
Show file tree
Hide file tree
Showing 90 changed files with 2,251 additions and 2,036 deletions.
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

0 comments on commit 5b3f87e

Please sign in to comment.