Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
andreiio committed Nov 28, 2023
1 parent fed52b2 commit 8375c62
Show file tree
Hide file tree
Showing 10 changed files with 167 additions and 28 deletions.
67 changes: 67 additions & 0 deletions app/Concerns/HasSlug.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace App\Concerns;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;

trait HasSlug
{
public function initializeHasSlug(): void
{
$this->fillable[] = $this->getSlugColumnName();
}

public static function bootHasSlug(): void
{
static::saving(function (Model $model) {
$model->slug = Str::slug($model->slug);

if (! $model->slug || ! $model->slugAlreadyUsed($model->slug)) {
$model->slug = $model->generateSlug();
}
});
}

protected function getSlugColumnName(): string
{
return 'slug';
}

protected function getSlugSource(): string
{
return $this->title;
}

public function scopeWhereSlug(Builder $query, string $slug): Builder
{
return $query->where($this->getSlugColumnName(), $slug);
}

public function generateSlug(): string
{
$base = $slug = Str::slug($this->getSlugSource());
$suffix = 1;

while ($this->slugAlreadyUsed($slug)) {
$slug = Str::slug($base . '_' . $suffix++);
}

return $slug;
}

protected function slugAlreadyUsed(string $slug): bool
{
$query = static::whereSlug($slug)
->withoutGlobalScopes();

if ($this->exists) {
$query->where($this->getKeyName(), '!=', $this->getKey());
}

return $query->exists();
}
}
3 changes: 2 additions & 1 deletion app/Filament/MediaLibrary/TenantPathGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ class TenantPathGenerator extends DefaultPathGenerator
protected function getBasePath(Media $media): string
{
return collect([
filament()->getTenant()?->ulid,
'org',
filament()->getTenant()->ulid,
$media->getKey(),
])
->filter()
Expand Down
22 changes: 22 additions & 0 deletions app/Filament/MediaLibrary/UserPathGenerator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?php

declare(strict_types=1);

namespace App\Filament\MediaLibrary;

use Spatie\MediaLibrary\MediaCollections\Models\Media;
use Spatie\MediaLibrary\Support\PathGenerator\DefaultPathGenerator;

class UserPathGenerator extends DefaultPathGenerator
{
protected function getBasePath(Media $media): string
{
return collect([
'user',
$media->model->ulid,
$media->getKey(),
])
->filter()
->join(\DIRECTORY_SEPARATOR);
}
}
58 changes: 37 additions & 21 deletions app/Filament/Pages/Profile/UserPersonalInfo.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@

namespace App\Filament\Pages\Profile;

use Filament\Facades\Filament;
use Filament\Forms\Components\Group;
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Jeffgreco13\FilamentBreezy\Livewire\PersonalInfo as BasePersonalInfo;

class UserPersonalInfo extends BasePersonalInfo
Expand All @@ -17,29 +19,43 @@ class UserPersonalInfo extends BasePersonalInfo
'email',
];

protected function getProfileFormSchema(): array
public function mount(): void
{
$groupFields = [];

if ($this->hasAvatars) {
$groupFields[] = SpatieMediaLibraryFileUpload::make('avatar')
->label(__('filament-breezy::default.fields.avatar'))
->avatar()
->collection('avatars')
->conversion('large');
}

$groupFields[] = Group::make()
->columnSpan(2)
->columns(2)
->schema([
TextInput::make('first_name'),
TextInput::make('last_name'),
$this->user = Filament::getCurrentPanel()->auth()->user();

$this->getEmailComponent()
->columnSpanFull(),
]);
$this->form->fill($this->user->only($this->only));
}

return $groupFields;
public function form(Form $form): Form
{
return $form
->columns(3)
->statePath('data')
->model($this->user)
->schema([
SpatieMediaLibraryFileUpload::make('avatar')
->label(__('filament-breezy::default.fields.avatar'))
->avatar()
->collection('avatar')
->conversion('large'),

Group::make()
->columnSpan(2)
->columns(2)
->schema([
TextInput::make('first_name')
->label(__('field.first_name')),

TextInput::make('last_name')
->label(__('field.last_name')),

TextInput::make('email')
->label(__('field.last_name'))
->unique(ignoreRecord:true)
->required()
->email()
->columnSpanFull(),
]),
]);
}
}
7 changes: 7 additions & 0 deletions app/Models/Organization.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace App\Models;

use App\Concerns\HasLocation;
use App\Concerns\HasSlug;
use App\Concerns\HasUlid;
use Filament\Models\Contracts\HasAvatar;
use Illuminate\Database\Eloquent\Factories\HasFactory;
Expand All @@ -19,6 +20,7 @@ class Organization extends Model implements HasAvatar, HasMedia
use HasFactory;
use HasLocation;
use HasUlid;
use HasSlug;
use InteractsWithMedia;

protected $fillable = [
Expand Down Expand Up @@ -59,4 +61,9 @@ public function getFilamentAvatarUrl(): ?string
{
return $this->getFirstMediaUrl('logo', 'thumb');
}

protected function getSlugSource(): string
{
return $this->name;
}
}
27 changes: 23 additions & 4 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

// use Illuminate\Contracts\Auth\MustVerifyEmail;

use App\Concerns\HasUlid;
use Filament\Models\Contracts\FilamentUser;
use Filament\Models\Contracts\HasAvatar;
use Filament\Models\Contracts\HasName;
Expand All @@ -17,14 +18,18 @@
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Storage;
use Jeffgreco13\FilamentBreezy\Traits\TwoFactorAuthenticatable;
use Laravel\Sanctum\HasApiTokens;
use Spatie\Image\Manipulations;
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;

class User extends Authenticatable implements FilamentUser, HasAvatar, HasName, HasTenants
class User extends Authenticatable implements FilamentUser, HasAvatar, HasName, HasMedia, HasTenants
{
use HasApiTokens;
use HasFactory;
use HasUlid;
use InteractsWithMedia;
use Notifiable;
use TwoFactorAuthenticatable;

Expand All @@ -38,7 +43,6 @@ class User extends Authenticatable implements FilamentUser, HasAvatar, HasName,
'last_name',
'email',
'password',
'avatar_url',
];

/**
Expand Down Expand Up @@ -66,14 +70,29 @@ public function organizations(): MorphToMany
return $this->morphToMany(Organization::class, 'model', 'model_has_organizations', 'model_id');
}

public function registerMediaCollections(): void
{
$this->addMediaCollection('avatar')
->singleFile()
->registerMediaConversions(function () {
$this->addMediaConversion('thumb')
->fit(Manipulations::FIT_CONTAIN, 64, 64)
->optimize();

$this->addMediaConversion('large')
->fit(Manipulations::FIT_CONTAIN, 256, 256)
->optimize();
});
}

public function canAccessPanel(Panel $panel): bool
{
return $this->hasVerifiedEmail();
}

public function getFilamentAvatarUrl(): ?string
{
return $this->avatar_url ? Storage::url($this->avatar_url) : null;
return $this->getFirstMediaUrl('avatar', 'thumb');
}

public function getFilamentName(): string
Expand Down
7 changes: 6 additions & 1 deletion app/Providers/Filament/OrganizationPanelProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,11 @@
use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent;
use Filament\Pages\Page;
use Filament\Panel;
use Filament\PanelProvider;
use Filament\Support\Colors\Color;
use Filament\Support\Enums\Alignment;
use Filament\Widgets;
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
use Illuminate\Cookie\Middleware\EncryptCookies;
Expand Down Expand Up @@ -60,6 +62,9 @@ public function panel(Panel $panel): Panel
->widgets([
// Widgets\AccountWidget::class,
])
->bootUsing(function () {
Page::formActionsAlignment(Alignment::End);
})
->databaseNotifications()
->plugins([
BreezyCore::make()
Expand All @@ -86,7 +91,7 @@ public function panel(Panel $panel): Panel
->authMiddleware([
Authenticate::class,
])
->tenant(Organization::class)
->tenant(Organization::class, 'slug')
->tenantProfile(EditOrganizationProfile::class)
->tenantMiddleware([
// ApplyTenantScopes::class,
Expand Down
1 change: 1 addition & 0 deletions config/media-library.php
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
// Model::class => PathGenerator::class
// or
// 'model_morph_alias' => PathGenerator::class
App\Models\User::class => App\Filament\MediaLibrary\UserPathGenerator::class,
],

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public function up(): void
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->ulid()->unique();
$table->string('first_name');
$table->string('last_name');
$table->string('email')->unique();
Expand Down
2 changes: 1 addition & 1 deletion tests/Feature/LoginTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@
});

it('can redirect unauthenticated app requests', function () {
$this->get(route('filament.admin.pages.dashboard'))
$this->get(route('filament.organization.pages.dashboard', ['tenant' => 'test']))
->assertRedirect(Filament::getLoginUrl());
});

Expand Down

0 comments on commit 8375c62

Please sign in to comment.