People
Most questions about a recording start with a person: "what did she just do?". These pieces put recordings next to your users.
The model
Add the core's trait to the model people sign in with:
use Illuminate\Foundation\Auth\User as Authenticatable;
use Packstub\SessionReplay\Concerns\HasSessionReplays;
class User extends Authenticatable
{
use HasSessionReplays;
}
It adds the sessionReplays() relation (morphMany to ReplaySession), which the relation manager uses:
$user->sessionReplays()->latest('started_at')->first()?->url();
A person's recordings on their page
Add ReplaysRelationManager to your user resource:
use Packstub\SessionReplay\Filament\Resources\ReplaySessions\RelationManagers\ReplaysRelationManager;
public static function getRelations(): array
{
return [
ReplaysRelationManager::class,
];
}
The tab is titled "Session replays" and shows the same table as the Sessions resource, columns and filters included, limited to that person. It is read-only: one row action, Watch, which opens the recording in the Sessions resource.
The tab is only shown to people who may see the list (ReplaySessionResource::canViewAny()), and Watch only on recordings they may open, so the rules in Watching apply here too.
Watch last session
WatchLastSessionAction opens a person's most recent recording. On a table row:
use Packstub\SessionReplay\Filament\Actions\WatchLastSessionAction;
public static function table(Table $table): Table
{
return $table
->columns([/* ... */])
->recordActions([
WatchLastSessionAction::make(),
]);
}
Or in the header of a person's edit or view page:
protected function getHeaderActions(): array
{
return [
WatchLastSessionAction::make(),
];
}
The action is named watchLastSession, labelled "Watch last session", and links to the watch page. It is hidden when the person has no recording or when the viewer may not watch the latest one. It is a regular Filament action, so ->label(), ->icon(), ->color() and ->openUrlInNewTab() work as usual.
WatchLastSessionAction::lastSession($user) returns that recording (?ReplaySession) if you need it elsewhere.
The stats widget
$panel->plugin(SessionReplayPlugin::make()->widget());
ReplayStatsWidget shows the last seven days in three numbers, each linking to the list with the matching filter:
| Stat | Opens |
|---|---|
| Recordings, last 7 days | The list |
| With errors | The list filtered to recordings with errors |
| Slow pages (poor vitals) | The list filtered to poor vitals |
In a panel with tenancy the numbers are the current workspace's (see Tenancy). The widget is hidden from people who may not see the list. It does not poll.
To place it yourself instead of registering it on the whole panel, leave ->widget() off and add Packstub\SessionReplay\Filament\Widgets\ReplayStatsWidget::class to a dashboard's or a page's widgets.
Naming people
In the list and on the watch page a person is named by the first of these that has a value:
- What your
userLabelUsing()closure returns. - The attribute in the core's
viewer.user_labelconfig key (emailby default). name, thenemail.#and the person's key, for example#42, when the user no longer exists.
A recording without a person is "Guest".
use Packstub\SessionReplay\Models\ReplaySession;
SessionReplayPlugin::make()
->userLabelUsing(fn (ReplaySession $session): ?string => $session->user?->full_name);
Return null to fall through to the defaults.
Finding people
The table's search box looks for what you type in the name and email columns of your people's tables, and matches a person's key exactly. It works per model: recordings of a User and of an Admin are both found, each in its own table, and a column a table does not have is skipped. There is no join, so it also works when the recordings index lives on another connection than your users.
Only people with recordings in the list count: in a panel with tenancy, the current workspace's (and what SessionReplay::visibleUsing() allows). The search reads the matching people 500 at a time and stops at 200 with recordings in the list, or after 10,000, so a one-letter search stays quick; type more of the name when a very common one is not found.
SessionReplayPlugin::make()
->searchPeopleBy(['first_name', 'last_name', 'email']);
searchPeopleBy([]) leaves the search to the key alone.
These pieces link to the Sessions resource, so use them in a panel where the plugin is registered with the resource on (the default).