DrByte
DrByte
FFilament
Created by DrByte on 1/13/2024 in #❓┊help
Tracking Read/Unread or Viewed/NotViewed
This is a how-to, not a help-request: Tracking Views of a record, per user. views migration:
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('views', function (Blueprint $table) {
$table->id();
$table->foreignUlid('user_id')->nullable()->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->foreignUlid('post_id')->nullable()->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->timestamps();
});
}
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('views', function (Blueprint $table) {
$table->id();
$table->foreignUlid('user_id')->nullable()->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->foreignUlid('post_id')->nullable()->constrained()->cascadeOnDelete()->cascadeOnUpdate();
$table->timestamps();
});
}
View model:
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class View extends Model
{
use HasFactory;

protected $fillable = [
'post_id',
'user_id',
];

public function post(): BelongsTo
{
return $this->belongsTo(Post::class, 'post_id');
}

public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class View extends Model
{
use HasFactory;

protected $fillable = [
'post_id',
'user_id',
];

public function post(): BelongsTo
{
return $this->belongsTo(Post::class, 'post_id');
}

public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
User model:
public function views(): HasMany
{
return $this->hasMany(View::class, 'user_id', 'id');
}
public function views(): HasMany
{
return $this->hasMany(View::class, 'user_id', 'id');
}
Post model:
public function trackView(?User $user): void
{
$user_id = $user?->id ?? Auth::user()->id;
View::create([
'user_id' => $user_id,
'post_id' => $this->id,
]);
}

public function getIsViewedAttribute(?User $user)
{
$user_id = $user?->id ?? Auth::user()->id;
return $this->views->where('user_id', $user_id)->count();
}
public function trackView(?User $user): void
{
$user_id = $user?->id ?? Auth::user()->id;
View::create([
'user_id' => $user_id,
'post_id' => $this->id,
]);
}

public function getIsViewedAttribute(?User $user)
{
$user_id = $user?->id ?? Auth::user()->id;
return $this->views->where('user_id', $user_id)->count();
}
Then, for the component that "shows" the record, set its mountUsing() to track the "view":
->mountUsing(function (Post $record) {
$record->trackView(Auth::user());
})
->mountUsing(function (Post $record) {
$record->trackView(Auth::user());
})
CSS can be used to set a class when the isViewed() attribute is truthy.
9 replies
FFilament
Created by DrByte on 11/30/2023 in #❓┊help
Increase table->searchable() debounce from 500ms
I'm finding that when people use the Table-Column or Table-wide search, the debounce of 500ms is triggering a search much sooner than people are ready. The component seems to have the debounce hard-coded, and no hooks to intercept it. :wire:model.live.debounce.500ms="$wireModel" https://github.com/filamentphp/filament/blob/6794c14765fc103defce60c5ae67033971b2425e/packages/tables/resources/views/components/search-field.blade.php#L25 Are there any workarounds someone can offer? Or is it only fixable by a core code change? (or the unthinkable importing of the component and overriding it in-app)?
2 replies
FFilament
Created by DrByte on 10/11/2023 in #❓┊help
trigger multiple downloads from a header Action button
I know I can't have 2 ->action() calls ... but how would I return 2 different Responsable results to fire two separate downloads from clicking the Action button?
Actions\Action::make('export')
->visible(auth()->user()->can('export submissions'))
->color('secondary')
->icon('heroicon-s-arrow-down-tray')
->action(fn () => (new SubmissionsExport)->download('submissions-export-' . date('Y-m-d-i-h-s') . '.xlsx'))
->action(fn () => (new SubmissionsMediaExport)->download('submissions-media-export-' . date('Y-m-d-i-h-s') . '.zip'))
->successNotificationTitle('Exported. Check your Downloads directory.')
->label('Export Submissions'),
Actions\Action::make('export')
->visible(auth()->user()->can('export submissions'))
->color('secondary')
->icon('heroicon-s-arrow-down-tray')
->action(fn () => (new SubmissionsExport)->download('submissions-export-' . date('Y-m-d-i-h-s') . '.xlsx'))
->action(fn () => (new SubmissionsMediaExport)->download('submissions-media-export-' . date('Y-m-d-i-h-s') . '.zip'))
->successNotificationTitle('Exported. Check your Downloads directory.')
->label('Export Submissions'),
Calling either of these ->action() calls works fine independently, but how can I combine them into one?
25 replies
FFilament
Created by DrByte on 9/30/2023 in #❓┊help
Password-less login via email link ... in v3
I've seen a couple v2 plugins for password-less login via a signed magic-link sent via email. Looking for one that works with v3 ... because I've not yet been able to convert either of those to make it work. ie: I've tried https://github.com/ArtMin96/filament-password-less and https://github.com/bradyrenting/filament-passwordless
17 replies
FFilament
Created by DrByte on 9/29/2023 in #❓┊help
JS lightbox works in infobox but not in modal triggered by Table ViewAction in RelationManager
TLDR: This is about getting Filament's modal to properly call the js after the component is rendered to a modal. (This is not about fslightbox itself: It's working fine in a "Page" rendered by Filament. But Filament's modals won't let it run properly. I'm trying to figure out why.) Details: So I've got this fslightbox component I created by cloning the SpatieMediaLibraryImageEntry component, and basically all it does is pull image URLs for full-size and a smaller conversion size, passing those to the template, and customizes the template to wrap the <img src="(default-src)"> inside an <a href="(lrg-src)" data-fslightbox="lightbox"> element, so that fslightbox can identify the elements to attach itself to. So mostly just markup on the correct URLs to the image assets. It all works great in InfoBox mode when the infobox displays as a Page. (ie: Admin Panel has an Entry Resource to manage the model's entries, each which has one or more images attached via SpatieMediaLib.) So I know my component and template are working correctly. THE PROBLEM But I have another Panel where I display these Entry models as sub-records of Category models, and the RelationManager's "View" button fires the usual \Filament\Tables\Actions\ViewAction ... but only opens as a Modal, not as a Page, which is mostly fine for my needs, with one problem: The fslightbox JS doesn't register these elements. (SYMPTOM: clicking the images opens the a href URL directly, instead of firing the lightbox/gallery) I'm presuming it's because the elements aren't attaching because the modal has created a shadow DOM? I can go to the browser console and manually call refreshFsLightbox(); and the modal's images now work. So that's a "start", but not a solution, not even a workaround. How can I get the modal to run the lightbox js to register the elements itself after the Modal is rendered?
22 replies