You've already forked Atomcms-edit
Initial commit
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Filament\Resources\User\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\User\Users\UserResource;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateUser extends CreateRecord
|
||||
{
|
||||
#[\Override]
|
||||
protected static string $resource = UserResource::class;
|
||||
}
|
||||
+229
@@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\User\Users\Pages;
|
||||
|
||||
use App\Actions\SendCurrency;
|
||||
use App\Enums\CurrencyTypes;
|
||||
use App\Filament\Resources\User\Users\UserResource;
|
||||
use App\Models\Game\Player\UserCurrency;
|
||||
use App\Models\User;
|
||||
/** @var User $record */
|
||||
use App\Services\RconService;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Filament\Support\Exceptions\Halt;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* @method \App\Models\User getRecord()
|
||||
*
|
||||
* @property-read User $record
|
||||
*/
|
||||
class EditUser extends EditRecord
|
||||
{
|
||||
#[\Override]
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
#[\Override]
|
||||
protected function getActions(): array
|
||||
{
|
||||
return [
|
||||
DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
protected function mutateFormDataBeforeFill(array $data): array
|
||||
{
|
||||
return static::$resource::fillWithOutsideData(
|
||||
$this->getRecord(),
|
||||
$data,
|
||||
);
|
||||
}
|
||||
|
||||
public static function getEloquentQuery(): Builder
|
||||
{
|
||||
return parent::getEloquentQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Halt
|
||||
*/
|
||||
protected function beforeSave(): void
|
||||
{
|
||||
$user = $this->getRecord();
|
||||
$data = $this->form->getState();
|
||||
|
||||
if ($data['rank'] > auth()->user()->rank) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('You cannot edit this user!'))
|
||||
->body(__('You cannot edit users with a higher rank than yours.'))
|
||||
->send();
|
||||
|
||||
$this->halt();
|
||||
}
|
||||
|
||||
$rcon = app(RconService::class);
|
||||
|
||||
if (! $user->online) {
|
||||
DB::transaction(function () use ($user, $data) {
|
||||
$this->treatChangedCurrenciesWithoutRcon($user, $data);
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $rcon->isConnected()) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('RCON is not enabled!'))
|
||||
->body(__('You cannot edit users because RCON is not enabled and the user is online.'))
|
||||
->send();
|
||||
|
||||
$this->halt();
|
||||
}
|
||||
|
||||
DB::transaction(function () use ($user, $data, $rcon) {
|
||||
if ($data['credits'] != $user->credits) {
|
||||
$rcon->giveCredits($user, -$user->credits + $data['credits']);
|
||||
}
|
||||
|
||||
$this->checkUsernameChangedPermission($user, $data, $rcon);
|
||||
$this->treatChangedCurrencies($user, $data);
|
||||
$this->treatChangedUserRank($user, $data, $rcon);
|
||||
$this->treatChangedUserMotto($user, $data, $rcon);
|
||||
});
|
||||
}
|
||||
|
||||
private function treatChangedCurrenciesWithoutRcon(User $user, array $data): void
|
||||
{
|
||||
$user->currencies->each(function (UserCurrency $currency) use ($data, $user) {
|
||||
$updatedCurrencyAmount = $data["currency_{$currency->type}"] ?? $currency->amount;
|
||||
if ($updatedCurrencyAmount == $currency->amount) {
|
||||
return;
|
||||
}
|
||||
|
||||
$updated = $user->currencies()->where('type', $currency->type)->update(['amount' => $updatedCurrencyAmount]);
|
||||
|
||||
if ($updated) {
|
||||
activity()
|
||||
->performedOn($currency)
|
||||
->withProperties(['old_amount' => $currency->amount, 'new_amount' => $updatedCurrencyAmount, 'user_id' => $user->id, 'type' => $currency->type])
|
||||
->event('updated')
|
||||
->log("Currency updated for user {$user->username}");
|
||||
|
||||
} else {
|
||||
activity()
|
||||
->withProperties(['user_id' => $user->id, 'type' => $currency->type])
|
||||
->event('failed_update')
|
||||
->log("Failed to update currency for user {$user->username}");
|
||||
}
|
||||
});
|
||||
|
||||
$user->settings->update(['can_change_name' => $data['allow_change_username'] ? '1' : '0']);
|
||||
}
|
||||
|
||||
private function checkUsernameChangedPermission(User $user, array $data, RconService $rcon): void
|
||||
{
|
||||
if ($data['allow_change_username'] == $user->settings->can_change_name) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $rcon->isConnected()) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('RCON is not enabled!'))
|
||||
->body(__('You cannot edit users because RCON is not enabled and the user is online.'))
|
||||
->send();
|
||||
|
||||
$this->halt();
|
||||
}
|
||||
|
||||
$rcon->disconnectUser($user);
|
||||
$user->settings->update(['can_change_name' => $data['allow_change_username'] ? '1' : '0']);
|
||||
}
|
||||
|
||||
private function treatChangedCurrencies(User $user, array $data): void
|
||||
{
|
||||
$user->currencies->each(function (UserCurrency $currency) use ($data, $user) {
|
||||
$updatedCurrencyAmount = $data["currency_{$currency->type}"] ?? $currency->amount;
|
||||
$currencyType = match ($currency->type) {
|
||||
CurrencyTypes::Duckets => 'duckets',
|
||||
CurrencyTypes::Diamonds => 'diamonds',
|
||||
CurrencyTypes::Points => 'points',
|
||||
default => null,
|
||||
};
|
||||
|
||||
if ($currencyType === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($updatedCurrencyAmount == $currency->amount) {
|
||||
return;
|
||||
}
|
||||
|
||||
app(SendCurrency::class)->execute($user, $currencyType, -$currency->amount + $updatedCurrencyAmount);
|
||||
});
|
||||
}
|
||||
|
||||
private function treatChangedUserRank(User $user, array $data, RconService $rcon): void
|
||||
{
|
||||
if ($data['rank'] == $user->rank) {
|
||||
return;
|
||||
}
|
||||
if ($data['rank'] > auth()->user()->rank) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user->online && ! $rcon->isConnected()) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('RCON is not enabled!'))
|
||||
->body(__('You cannot edit users because RCON is not enabled and the user is online.'))
|
||||
->send();
|
||||
|
||||
$this->halt();
|
||||
}
|
||||
|
||||
if (! $user->online) {
|
||||
$user->update(['rank' => $data['rank']]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$rcon->alertUser($user, __('You have been disconnected because your rank has been changed. Please re-enter the hotel.'));
|
||||
sleep(2);
|
||||
|
||||
$rcon->disconnectUser($user);
|
||||
$rcon->setRank($user, $data['rank']);
|
||||
}
|
||||
|
||||
private function treatChangedUserMotto(User $user, array $data, RconService $rcon): void
|
||||
{
|
||||
if ($data['motto'] == $user->motto) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($user->online && ! $rcon->isConnected()) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title(__('RCON is not enabled!'))
|
||||
->body(__('You cannot edit users because RCON is not enabled and the user is online.'))
|
||||
->send();
|
||||
|
||||
$this->halt();
|
||||
}
|
||||
|
||||
if (! $user->online) {
|
||||
$user->update(['motto' => $data['motto']]);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$rcon->setMotto($user, $data['motto']);
|
||||
$rcon->alertUser($user, __('Your motto has been changed by a staff member.'));
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\User\Users\Pages;
|
||||
|
||||
use App\Enums\NotificationType;
|
||||
use App\Filament\Resources\User\Users\UserResource;
|
||||
use App\Models\User;
|
||||
use App\Models\User\UserNotification;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListUsers extends ListRecords
|
||||
{
|
||||
#[\Override]
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
#[\Override]
|
||||
protected function getActions(): array
|
||||
{
|
||||
return [
|
||||
Action::make(__('filament::resources.actions.send_notifications'))
|
||||
->modal()
|
||||
->color('gray')
|
||||
->modalHeading(__('filament::resources.actions.send_notifications'))
|
||||
->icon('heroicon-o-bell')
|
||||
->schema([
|
||||
Select::make('users')
|
||||
->label(__('filament::resources.inputs.users'))
|
||||
->searchable()
|
||||
->getSearchResultsUsing(fn (string $search): array => User::query()->where('username', 'like', "%{$search}%")->limit(50)->pluck('username', 'id')->toArray())
|
||||
->multiple()
|
||||
->native(false)
|
||||
->nullable(),
|
||||
|
||||
TextInput::make('message')
|
||||
->label(__('filament::resources.inputs.message'))
|
||||
->maxLength(100)
|
||||
->required(),
|
||||
|
||||
TextInput::make('url')
|
||||
->label(__('filament::resources.inputs.url'))
|
||||
->nullable(),
|
||||
|
||||
Toggle::make('as_staff')
|
||||
->label(__('filament::resources.inputs.as_staff'))
|
||||
->default(false),
|
||||
])
|
||||
->action(function (array $data) {
|
||||
$users = collect($data['users'] ?? [])->values();
|
||||
$senderId = $data['as_staff'] ? null : auth()->id();
|
||||
|
||||
if ($users->isEmpty()) {
|
||||
$users = User::pluck('id');
|
||||
}
|
||||
|
||||
$notifications = $users->map(fn ($id) => [
|
||||
'sender_id' => $senderId,
|
||||
'recipient_id' => $id,
|
||||
'type' => NotificationType::HousekeepingCustomMessage,
|
||||
'message' => $data['message'],
|
||||
'url' => $data['url'] ?? null,
|
||||
'created_at' => now(),
|
||||
'updated_at' => now(),
|
||||
]);
|
||||
|
||||
UserNotification::insert($notifications->toArray());
|
||||
|
||||
Notification::make()->body('Notification sent successfully.')->icon('heroicon-o-check-circle')->iconColor('success')->send();
|
||||
}),
|
||||
|
||||
CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\User\Users\Pages;
|
||||
|
||||
use App\Filament\Resources\User\Users\UserResource;
|
||||
use Filament\Resources\Pages\ViewRecord;
|
||||
|
||||
class ViewUser extends ViewRecord
|
||||
{
|
||||
#[\Override]
|
||||
protected static string $resource = UserResource::class;
|
||||
|
||||
#[\Override]
|
||||
protected function mutateFormDataBeforeFill(array $data): array
|
||||
{
|
||||
return static::$resource::fillWithOutsideData(
|
||||
$this->getRecord(),
|
||||
$data,
|
||||
);
|
||||
}
|
||||
}
|
||||
+139
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\User\Users\RelationManagers;
|
||||
|
||||
use App\Filament\Tables\Columns\HabboBadgeColumn;
|
||||
use App\Filament\Traits\TranslatableResource;
|
||||
use App\Models\Game\Player\UserBadge;
|
||||
use App\Models\User;
|
||||
use App\Services\RconService;
|
||||
use Filament\Actions\CreateAction;
|
||||
use Filament\Actions\DeleteAction;
|
||||
use Filament\Actions\DeleteBulkAction;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class BadgesRelationManager extends RelationManager
|
||||
{
|
||||
use TranslatableResource;
|
||||
|
||||
#[\Override]
|
||||
protected static string $relationship = 'badges';
|
||||
|
||||
#[\Override]
|
||||
protected static ?string $recordTitleAttribute = 'badge_code';
|
||||
|
||||
protected static ?string $translateIdentifier = 'badges';
|
||||
|
||||
#[\Override]
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
TextInput::make('badge_code')
|
||||
->label(__('filament::resources.inputs.badge_code'))
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->modifyQueryUsing(fn ($query) => $query->latest('id'))
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label(__('filament::resources.columns.id')),
|
||||
|
||||
HabboBadgeColumn::make('badge')
|
||||
->alignCenter()
|
||||
->label(__('filament::resources.columns.image')),
|
||||
|
||||
TextColumn::make('badge_code')
|
||||
->label(__('filament::resources.columns.badge_code'))
|
||||
->searchable(),
|
||||
|
||||
IconColumn::make('slot_id')
|
||||
->label(__('filament::resources.columns.equipped'))
|
||||
->icon(fn ($record) => $record->slot_id > 0 ? 'heroicon-o-check-circle' : 'heroicon-o-x-circle')
|
||||
->colors([
|
||||
'success' => fn (string $state) => $state > 0,
|
||||
'danger' => fn (string $state) => $state <= 0,
|
||||
]),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->headerActions([
|
||||
CreateAction::make()
|
||||
->before(function (CreateAction $action, RelationManager $livewire): void {
|
||||
/** @var User $user */
|
||||
$user = $livewire->getOwnerRecord();
|
||||
$hasRconEnabled = config('hotel.rcon.enabled');
|
||||
|
||||
if (! $user->online) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $hasRconEnabled) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title('RCON is not enabled!')
|
||||
->body("You can't send badges to online users if RCON is not enabled.")
|
||||
->persistent()
|
||||
->send();
|
||||
} else {
|
||||
$rcon = app(RconService::class);
|
||||
$data = $action->getFormData();
|
||||
|
||||
$rcon->sendSafelyFromDashboard('sendBadge', [$user, $data['badge_code']], 'RCON: Failed to send the badge');
|
||||
}
|
||||
|
||||
$action->cancel();
|
||||
}),
|
||||
])
|
||||
->recordActions([
|
||||
DeleteAction::make()
|
||||
->before(fn (DeleteAction $action, RelationManager $livewire) => self::onDeleteBadgeAction($action, $livewire)),
|
||||
])
|
||||
->toolbarActions([
|
||||
DeleteBulkAction::make()
|
||||
->before(fn (DeleteBulkAction $action, RelationManager $livewire) => self::onDeleteBadgeAction($action, $livewire)),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function onDeleteBadgeAction(DeleteAction|DeleteBulkAction $action, RelationManager $livewire): void
|
||||
{
|
||||
/** @var User $user */
|
||||
$user = $livewire->getOwnerRecord();
|
||||
$hasRconEnabled = config('hotel.rcon.enabled');
|
||||
|
||||
if (! $user->online) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $hasRconEnabled) {
|
||||
Notification::make()
|
||||
->danger()
|
||||
->title('RCON is not enabled!')
|
||||
->body("You can't remove badges to online users if RCON is not enabled.")
|
||||
->persistent()
|
||||
->send();
|
||||
} else {
|
||||
$rcon = app(RconService::class);
|
||||
$badge = $action instanceof DeleteAction
|
||||
? $action->getRecord()?->badge_code
|
||||
: $action->getRecords()->map(fn (UserBadge $record) => $record->badge_code)->join(';');
|
||||
|
||||
$rcon->sendSafelyFromDashboard('removeBadge', [$user, $badge], 'RCON: Failed to remove the badge');
|
||||
}
|
||||
|
||||
$action->cancel();
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Filament\Resources\User\Users\RelationManagers;
|
||||
|
||||
use App\Filament\Resources\Hotel\ChatlogPrivates\ChatlogPrivateResource;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class ChatLogPrivateRelationManager extends RelationManager
|
||||
{
|
||||
#[\Override]
|
||||
protected static string $relationship = 'chatLogsPrivate';
|
||||
|
||||
protected static $targetResource = ChatlogPrivateResource::class;
|
||||
|
||||
#[\Override]
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema;
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table->columns(ChatlogPrivateResource::getTable())
|
||||
->defaultSort('timestamp', 'desc');
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Filament\Resources\User\Users\RelationManagers;
|
||||
|
||||
use App\Filament\Resources\Hotel\ChatlogRooms\ChatlogRoomResource;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class ChatLogRelationManager extends RelationManager
|
||||
{
|
||||
#[\Override]
|
||||
protected static string $relationship = 'chatLogs';
|
||||
|
||||
protected static $targetResource = ChatlogRoomResource::class;
|
||||
|
||||
#[\Override]
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema;
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table->columns(ChatlogRoomResource::getTable())
|
||||
->defaultSort('timestamp', 'desc');
|
||||
}
|
||||
}
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\User\Users\RelationManagers;
|
||||
|
||||
use App\Filament\Traits\TranslatableResource;
|
||||
use App\Models\User;
|
||||
use Carbon\CarbonInterval;
|
||||
use Filament\Actions\Action;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Resources\RelationManagers\RelationManager;
|
||||
use Filament\Schemas\Components\Tabs;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Table;
|
||||
|
||||
class SettingsRelationManager extends RelationManager
|
||||
{
|
||||
use TranslatableResource;
|
||||
|
||||
#[\Override]
|
||||
protected static string $relationship = 'settings';
|
||||
|
||||
protected static string $translateIdentifier = 'settings';
|
||||
|
||||
#[\Override]
|
||||
public function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Tabs::make('Settings')
|
||||
->schema([
|
||||
Tab::make(__('filament::resources.tabs.Account Data'))
|
||||
->schema([
|
||||
TextInput::make('achievement_score')
|
||||
->label(__('filament::resources.inputs.achievement_score'))
|
||||
->disabled()
|
||||
->required(),
|
||||
|
||||
TextInput::make('respects_received')
|
||||
->label(__('filament::resources.inputs.respects_received'))
|
||||
->disabled()
|
||||
->required(),
|
||||
|
||||
Select::make('can_trade')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.can_trade'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
Select::make('block_following')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.block_following'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
Select::make('block_friendrequests')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.block_friendrequests'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
Select::make('block_roominvites')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.block_roominvites'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
TextInput::make('max_rooms')
|
||||
->label(__('filament::resources.inputs.max_rooms'))
|
||||
->numeric()
|
||||
->required(),
|
||||
|
||||
TextInput::make('max_friends')
|
||||
->label(__('filament::resources.inputs.max_friends'))
|
||||
->numeric()
|
||||
->required(),
|
||||
])
|
||||
->columns(['sm' => 2]),
|
||||
|
||||
Tab::make(__('filament::resources.tabs.Extra Settings'))
|
||||
->schema([
|
||||
Select::make('old_chat')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.old_chat'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
Select::make('block_camera_follow')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.block_camera_follow'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
Select::make('ignore_bots')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.ignore_bots'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
Select::make('ignore_pets')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.ignore_pets'))
|
||||
->options([
|
||||
'0' => __('filament::resources.common.No'),
|
||||
'1' => __('filament::resources.common.Yes'),
|
||||
])
|
||||
->required(),
|
||||
])->columns(['sm' => 2]),
|
||||
])->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
TextColumn::make('achievement_score')
|
||||
->label(__('filament::resources.columns.achievement_score'))
|
||||
->toggleable(),
|
||||
|
||||
TextColumn::make('respects_received')
|
||||
->label(__('filament::resources.columns.respects_received'))
|
||||
->toggleable(),
|
||||
|
||||
TextColumn::make('online_time')
|
||||
->label(__('filament::resources.columns.online_time'))
|
||||
->formatStateUsing(fn (string $state) => __(':m minutes', ['m' => round(CarbonInterval::seconds($state)->totalMinutes)]))
|
||||
->toggleable(),
|
||||
|
||||
IconColumn::make('can_trade')
|
||||
->label(__('filament::resources.columns.can_trade'))
|
||||
->icon(fn (string $state) => $state === '1' ? 'heroicon-o-check-circle' : 'heroicon-o-x-circle')
|
||||
->colors([
|
||||
'success' => '1',
|
||||
'danger' => '0',
|
||||
]),
|
||||
|
||||
IconColumn::make('can_change_name')
|
||||
->label(__('filament::resources.columns.can_change_name'))
|
||||
->icon(fn (string $state) => $state === '1' ? 'heroicon-o-check-circle' : 'heroicon-o-x-circle')
|
||||
->colors([
|
||||
'success' => '1',
|
||||
'danger' => '0',
|
||||
]),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->headerActions([
|
||||
Action::make('helper')
|
||||
->label('Settings Tip')
|
||||
->icon('heroicon-o-exclamation-triangle')
|
||||
->tooltip('You can only change the offline user settings.')
|
||||
->extraAttributes(['style' => 'cursor: default !important']),
|
||||
])
|
||||
->recordActions([
|
||||
EditAction::make()
|
||||
->disabled(function (RelationManager $livewire): bool {
|
||||
/** @var User $user */
|
||||
$user = $livewire->getOwnerRecord();
|
||||
|
||||
return $user->online;
|
||||
}),
|
||||
])
|
||||
->toolbarActions([]);
|
||||
}
|
||||
}
|
||||
+306
@@ -0,0 +1,306 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\User\Users;
|
||||
|
||||
use App\Filament\Resources\User\Users\Pages\CreateUser;
|
||||
use App\Filament\Resources\User\Users\Pages\EditUser;
|
||||
use App\Filament\Resources\User\Users\Pages\ListUsers;
|
||||
use App\Filament\Resources\User\Users\Pages\ViewUser;
|
||||
use App\Filament\Resources\User\Users\RelationManagers\BadgesRelationManager;
|
||||
use App\Filament\Resources\User\Users\RelationManagers\ChatLogPrivateRelationManager;
|
||||
use App\Filament\Resources\User\Users\RelationManagers\ChatLogRelationManager;
|
||||
use App\Filament\Resources\User\Users\RelationManagers\SettingsRelationManager;
|
||||
use App\Filament\Tables\Columns\UserAvatarColumn;
|
||||
use App\Filament\Traits\TranslatableResource;
|
||||
use App\Models\Community\Staff\WebsiteTeam;
|
||||
use App\Models\Game\Permission;
|
||||
use App\Models\User;
|
||||
use Filament\Actions\EditAction;
|
||||
use Filament\Actions\ViewAction;
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
use Filament\Forms\Components\Select;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Components\Toggle;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Schemas\Components\Section;
|
||||
use Filament\Schemas\Components\Tabs;
|
||||
use Filament\Schemas\Components\Tabs\Tab;
|
||||
use Filament\Schemas\Schema;
|
||||
use Filament\Tables\Columns\IconColumn;
|
||||
use Filament\Tables\Columns\TextColumn;
|
||||
use Filament\Tables\Filters\Filter;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
|
||||
class UserResource extends Resource
|
||||
{
|
||||
use TranslatableResource;
|
||||
|
||||
#[\Override]
|
||||
protected static ?string $model = User::class;
|
||||
|
||||
#[\Override]
|
||||
protected static string|\BackedEnum|null $navigationIcon = 'heroicon-o-users';
|
||||
|
||||
#[\Override]
|
||||
protected static string|\UnitEnum|null $navigationGroup = 'User Management';
|
||||
|
||||
#[\Override]
|
||||
protected static ?string $slug = 'user-management/users';
|
||||
|
||||
public static string $translateIdentifier = 'users';
|
||||
|
||||
#[\Override]
|
||||
public static function form(Schema $schema): Schema
|
||||
{
|
||||
return $schema
|
||||
->components([
|
||||
Tabs::make('Main')
|
||||
->tabs([
|
||||
Tab::make(__('filament::resources.tabs.General Information'))
|
||||
->schema([
|
||||
TextInput::make('username')
|
||||
->label(__('filament::resources.inputs.username'))
|
||||
->required()
|
||||
->disabled()
|
||||
->unique(ignoreRecord: true)
|
||||
->maxLength(25),
|
||||
|
||||
TextInput::make('motto')
|
||||
->label(__('filament::resources.inputs.motto'))
|
||||
->required()
|
||||
->maxLength(127),
|
||||
|
||||
Select::make('gender')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.gender'))
|
||||
->options([
|
||||
'M' => __('filament::resources.common.Male'),
|
||||
'F' => __('filament::resources.common.Female'),
|
||||
])
|
||||
->required(),
|
||||
|
||||
DateTimePicker::make('account_created')
|
||||
->native(false)
|
||||
->displayFormat('Y-m-d H:i:s')
|
||||
->dehydrateStateUsing(fn (User $record) => $record->account_created)
|
||||
->disabled()
|
||||
->label(__('filament::resources.inputs.created_at')),
|
||||
|
||||
DateTimePicker::make('last_login')
|
||||
->native(false)
|
||||
->displayFormat('Y-m-d H:i:s')
|
||||
->dehydrateStateUsing(fn (User $record) => $record->last_login)
|
||||
->disabled()
|
||||
->label(__('filament::resources.inputs.last_login')),
|
||||
|
||||
DateTimePicker::make('last_online')
|
||||
->native(false)
|
||||
->displayFormat('Y-m-d H:i:s')
|
||||
->dehydrateStateUsing(fn (User $record) => $record->last_online)
|
||||
->disabled()
|
||||
->label(__('filament::resources.inputs.last_online')),
|
||||
|
||||
TextInput::make('ip_register')
|
||||
->label(__('filament::resources.inputs.ip_register'))
|
||||
->disabled(),
|
||||
|
||||
TextInput::make('ip_current')
|
||||
->label(__('filament::resources.inputs.ip_current'))
|
||||
->disabled(),
|
||||
|
||||
TextInput::make('referral_code')
|
||||
->label(__('filament::resources.inputs.referral_code'))
|
||||
->disabled(),
|
||||
|
||||
TextInput::make('referrer_code')
|
||||
->label(__('filament::resources.inputs.referrer_code'))
|
||||
->nullable()
|
||||
->maxLength(15),
|
||||
|
||||
Select::make('team_id')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.team_id'))
|
||||
->options(WebsiteTeam::all()->pluck('rank_name', 'id'))
|
||||
->columnSpanFull(),
|
||||
])->columns(['sm' => 2]),
|
||||
|
||||
Tab::make(__('filament::resources.tabs.Currencies'))
|
||||
->schema([
|
||||
TextInput::make('credits')
|
||||
->label(__('filament::resources.common.Credits'))
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->columnSpanFull(),
|
||||
|
||||
TextInput::make('currency_0')
|
||||
->label(__('filament::resources.common.Duckets'))
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->columnSpanFull(),
|
||||
|
||||
TextInput::make('currency_5')
|
||||
->label(__('filament::resources.common.Diamonds'))
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->columnSpanFull(),
|
||||
|
||||
TextInput::make('currency_101')
|
||||
->label(__('filament::resources.common.Points'))
|
||||
->numeric()
|
||||
->minValue(0)
|
||||
->columnSpanFull(),
|
||||
])
|
||||
->columns(['sm' => 2]),
|
||||
|
||||
Tab::make(__('filament::resources.tabs.Security'))
|
||||
->schema([
|
||||
Section::make(__('filament::resources.tabs.Change Username'))
|
||||
->description(__('filament::resources.helpers.change_username_description'))
|
||||
->schema([
|
||||
Toggle::make('allow_change_username')
|
||||
->label(__('filament::resources.inputs.allow_change_username')),
|
||||
])->collapsible()->collapsed(),
|
||||
|
||||
Section::make(__('filament::resources.tabs.Change Email'))
|
||||
->schema([
|
||||
TextInput::make('mail')
|
||||
->label(__('filament::resources.inputs.email'))
|
||||
->email()
|
||||
->required(),
|
||||
])->collapsible()->collapsed(),
|
||||
|
||||
Section::make(__('filament::resources.tabs.Change Password'))
|
||||
->description(__('filament::resources.helpers.change_password_description'))
|
||||
->schema([
|
||||
TextInput::make('password')
|
||||
->label(__('filament::resources.inputs.new_password'))
|
||||
->dehydrateStateUsing(fn ($state) => Hash::make($state))
|
||||
->dehydrated(fn ($state) => filled($state))
|
||||
->password()
|
||||
->confirmed(),
|
||||
|
||||
TextInput::make('password_confirmation')
|
||||
->label(__('filament::resources.inputs.new_password_confirmation'))
|
||||
->dehydrated(false)
|
||||
->password(),
|
||||
])->collapsible()
|
||||
->columns(['sm' => 2])
|
||||
->collapsed(),
|
||||
|
||||
Section::make(__('filament::resources.tabs.Change Rank'))
|
||||
->schema([
|
||||
Select::make('rank')
|
||||
->native(false)
|
||||
->label(__('filament::resources.inputs.rank'))
|
||||
->options(Permission::query()->where('id', '<', auth()->user()->rank ?? 0)->pluck('rank_name', 'id')),
|
||||
|
||||
Toggle::make('is_hidden')
|
||||
->label(__('filament::resources.inputs.is_hidden'))
|
||||
->default(false),
|
||||
])->collapsible()
|
||||
->collapsed(),
|
||||
]),
|
||||
])->columnSpanFull(),
|
||||
]);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public static function getEloquentQuery(): Builder
|
||||
{
|
||||
return static::getModel()::query();
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->defaultSort('id', 'desc')
|
||||
->columns([
|
||||
TextColumn::make('id')
|
||||
->label(__('filament::resources.columns.id'))
|
||||
->searchable(),
|
||||
|
||||
UserAvatarColumn::make('avatar')
|
||||
->toggleable()
|
||||
->label(__('filament::resources.columns.avatar'))
|
||||
->options('&size=m&head_direction=3&gesture=sml&headonly=1'),
|
||||
|
||||
TextColumn::make('username')
|
||||
->label(__('filament::resources.columns.username'))
|
||||
->searchable(),
|
||||
|
||||
TextColumn::make('mail')
|
||||
->label(__('filament::resources.columns.email'))
|
||||
->toggleable()
|
||||
->searchable()
|
||||
->limit(50),
|
||||
|
||||
TextColumn::make('motto')
|
||||
->label(__('filament::resources.columns.motto'))
|
||||
->toggleable()
|
||||
->limit(30)
|
||||
->searchable(),
|
||||
|
||||
IconColumn::make('online')
|
||||
->label(__('filament::resources.columns.online'))
|
||||
->icon(fn (User $record) => $record->online ? 'heroicon-o-check-circle' : 'heroicon-o-x-circle')
|
||||
->colors([
|
||||
'danger' => false,
|
||||
'success' => true,
|
||||
]),
|
||||
|
||||
TextColumn::make('account_created')
|
||||
->toggleable()
|
||||
->date('Y-m-d H:i')
|
||||
->label(__('filament::resources.columns.created_at')),
|
||||
])
|
||||
->filters([
|
||||
Filter::make('ip_search')
|
||||
->label('IP')
|
||||
->form([TextInput::make('ip')->placeholder('IP address')->live()])
|
||||
->query(fn (Builder $query, array $data) => empty($data['ip']) ? $query : $query->where('ip_current', 'like', '%' . $data['ip'] . '%')->orWhere('ip_register', 'like', '%' . $data['ip'] . '%')),
|
||||
])
|
||||
->recordActions([
|
||||
ViewAction::make(),
|
||||
EditAction::make(),
|
||||
])
|
||||
->toolbarActions([]);
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
SettingsRelationManager::class,
|
||||
BadgesRelationManager::class,
|
||||
ChatLogRelationManager::class,
|
||||
ChatLogPrivateRelationManager::class,
|
||||
];
|
||||
}
|
||||
|
||||
public static function fillWithOutsideData(User $record, array $formData): array
|
||||
{
|
||||
$formData['currency_0'] = $record->currency('duckets');
|
||||
$formData['currency_5'] = $record->currency('diamonds');
|
||||
$formData['currency_101'] = $record->currency('points');
|
||||
|
||||
if ($record->settings) {
|
||||
$formData['allow_change_username'] = $record->settings->can_change_name;
|
||||
}
|
||||
|
||||
return $formData;
|
||||
}
|
||||
|
||||
#[\Override]
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => ListUsers::route('/'),
|
||||
'create' => CreateUser::route('/create'),
|
||||
'view' => ViewUser::route('/{record}'),
|
||||
'edit' => EditUser::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user