improve filament trans + user profile actions

This commit is contained in:
xiaomlove
2022-06-30 21:08:25 +08:00
parent 459d7462de
commit 579351c0eb
27 changed files with 966 additions and 178 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ class StatTable extends Widget
protected function getHeader(): string
{
return nulll;
}
protected function getTableRows(): array
@@ -44,20 +44,20 @@ class AgentAllowResource extends Resource
{
return $form
->schema([
Forms\Components\TextInput::make('family')->required(),
Forms\Components\TextInput::make('start_name')->required(),
Forms\Components\TextInput::make('peer_id_start')->required(),
Forms\Components\TextInput::make('peer_id_pattern')->required(),
Forms\Components\Radio::make('peer_id_matchtype')->options(self::$matchTypes)->required(),
Forms\Components\TextInput::make('peer_id_match_num')->integer()->required(),
Forms\Components\TextInput::make('agent_start')->required(),
Forms\Components\TextInput::make('agent_pattern')->required(),
Forms\Components\Radio::make('agent_matchtype')->options(self::$matchTypes)->required(),
Forms\Components\TextInput::make('agent_match_num')->required(),
Forms\Components\Radio::make('exception')->options(self::$yesOrNo)->required(),
Forms\Components\Radio::make('allowhttps')->options(self::$yesOrNo)->required(),
Forms\Components\TextInput::make('family')->required()->label(__('label.agent_allow.family')),
Forms\Components\TextInput::make('start_name')->required()->label(__('label.agent_allow.start_name')),
Forms\Components\TextInput::make('peer_id_start')->required()->label(__('label.agent_allow.peer_id_start')),
Forms\Components\TextInput::make('peer_id_pattern')->required()->label(__('label.agent_allow.peer_id_pattern')),
Forms\Components\Radio::make('peer_id_matchtype')->options(self::$matchTypes)->required()->label(__('label.agent_allow.peer_id_matchtype')),
Forms\Components\TextInput::make('peer_id_match_num')->integer()->required()->label(__('label.agent_allow.peer_id_match_num')),
Forms\Components\TextInput::make('agent_start')->required()->label(__('label.agent_allow.agent_start')),
Forms\Components\TextInput::make('agent_pattern')->required()->label(__('label.agent_allow.agent_pattern')),
Forms\Components\Radio::make('agent_matchtype')->options(self::$matchTypes)->required()->label(__('label.agent_allow.agent_matchtype')),
Forms\Components\TextInput::make('agent_match_num')->required()->label(__('label.agent_allow.agent_match_num')),
Forms\Components\Radio::make('exception')->options(self::$yesOrNo)->required()->label(__('label.agent_allow.exception')),
Forms\Components\Radio::make('allowhttps')->options(self::$yesOrNo)->required()->label(__('label.agent_allow.allowhttps')),
Forms\Components\Textarea::make('comment'),
Forms\Components\Textarea::make('comment')->label(__('label.comment')),
]);
}
@@ -66,10 +66,10 @@ class AgentAllowResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('family')->searchable(),
Tables\Columns\TextColumn::make('start_name')->searchable(),
Tables\Columns\TextColumn::make('peer_id_start'),
Tables\Columns\TextColumn::make('agent_start'),
Tables\Columns\TextColumn::make('family')->searchable()->label(__('label.agent_allow.family')),
Tables\Columns\TextColumn::make('start_name')->searchable()->label(__('label.agent_allow.start_name')),
Tables\Columns\TextColumn::make('peer_id_start')->label(__('label.agent_allow.peer_id_start')),
Tables\Columns\TextColumn::make('agent_start')->label(__('label.agent_allow.agent_start')),
])
->filters([
//
@@ -4,8 +4,10 @@ namespace App\Filament\Resources\System\AgentAllowResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\System\AgentAllowResource;
use App\Repositories\AgentAllowRepository;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
use Filament\Forms;
class ListAgentAllows extends PageList
{
@@ -15,6 +17,23 @@ class ListAgentAllows extends PageList
{
return [
Actions\CreateAction::make(),
Actions\Action::make('check')
->label(__('admin.resources.agent_allow.check_modal_btn'))
->form([
Forms\Components\TextInput::make('peer_id')->required(),
Forms\Components\TextInput::make('agent')->required(),
])
->modalHeading(__('admin.resources.agent_allow.check_modal_header'))
->action(function ($data) {
$agentAllowRep = new AgentAllowRepository();
try {
$result = $agentAllowRep->checkClient($data['peer_id'], $data['agent']);
$this->notify('success', __('admin.resources.agent_allow.check_pass_msg', ['id' => $result->id]));
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
})
];
}
}
@@ -36,11 +36,11 @@ class AgentDenyResource extends Resource
return $form
->schema([
Forms\Components\Select::make('family_id')->label('Allow family')
->relationship('family', 'family')->required(),
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('peer_id')->required(),
Forms\Components\TextInput::make('agent')->required(),
Forms\Components\Textarea::make('comment'),
->relationship('family', 'family')->required()->label(__('label.agent_allow.family')),
Forms\Components\TextInput::make('name')->required()->label(__('label.name')),
Forms\Components\TextInput::make('peer_id')->required()->label(__('label.agent_deny.peer_id')),
Forms\Components\TextInput::make('agent')->required()->label(__('label.agent_deny.agent')),
Forms\Components\Textarea::make('comment')->label(__('label.comment')),
]);
}
@@ -49,10 +49,10 @@ class AgentDenyResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('family.family')->label('Family'),
Tables\Columns\TextColumn::make('name')->searchable(),
Tables\Columns\TextColumn::make('peer_id')->searchable(),
Tables\Columns\TextColumn::make('agent')->searchable(),
Tables\Columns\TextColumn::make('family.family')->label(__('label.agent_allow.family')),
Tables\Columns\TextColumn::make('name')->searchable()->label(__('label.name')),
Tables\Columns\TextColumn::make('peer_id')->searchable()->label(__('label.agent_deny.peer_id')),
Tables\Columns\TextColumn::make('agent')->searchable()->label(__('label.agent_deny.agent')),
])
->filters([
//
+46 -21
View File
@@ -2,6 +2,7 @@
namespace App\Filament\Resources\System;
use App\Filament\OptionsTrait;
use App\Filament\Resources\System\ExamResource\Pages;
use App\Filament\Resources\System\ExamResource\RelationManagers;
use App\Models\Exam;
@@ -16,12 +17,18 @@ use Illuminate\Database\Eloquent\SoftDeletingScope;
class ExamResource extends Resource
{
use OptionsTrait;
protected static ?string $model = Exam::class;
protected static ?string $navigationIcon = 'heroicon-o-exclamation';
protected static ?string $navigationGroup = 'System';
const IS_DISCOVERED_OPTIONS = ['0' => 'No', '1' => 'Yes'];
const STATUS_OPTIONS = ['0' => 'Enabled', '1' => 'Disabled'];
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.exams_list');
@@ -38,24 +45,41 @@ class ExamResource extends Resource
return $form
->schema([
Forms\Components\Section::make('Base info')->schema([
Forms\Components\TextInput::make('name')->required()->columnSpan(['sm' => 2]),
Forms\Components\TextInput::make('priority')->columnSpan(['sm' => 2])->helperText('The higher the value, the higher the priority, and when multiple exam match the same user, the one with the highest priority is assigned.'),
Forms\Components\Radio::make('status')->options(['0' => 'Enabled', '1' => 'Disabled'])->inline()->columnSpan(['sm' => 2]),
Forms\Components\Radio::make('is_discovered')->options(['0' => 'No', '1' => 'Yes'])->label('Discovered')->inline()->columnSpan(['sm' => 2]),
Forms\Components\TextInput::make('name')->required()->columnSpan(['sm' => 2])->label(__('label.name')),
Forms\Components\TextInput::make('priority')
->columnSpan(['sm' => 2])
->label(__("label.priority"))
->helperText('The higher the value, the higher the priority, and when multiple exam match the same user, the one with the highest priority is assigned.'),
Forms\Components\Radio::make('status')
->options(self::STATUS_OPTIONS)
->inline()
->label(__('label.status'))
->columnSpan(['sm' => 2]),
Forms\Components\Radio::make('is_discovered')
->options(self::IS_DISCOVERED_OPTIONS)
->label(__('label.exam.is_discovered'))
->inline()
->columnSpan(['sm' => 2]),
])->columns(2),
Forms\Components\Section::make('Time')->schema([
Forms\Components\DateTimePicker::make('begin'),
Forms\Components\DateTimePicker::make('end'),
Forms\Components\TextInput::make('duration')->integer()->columnSpan(['sm' => 2])
Forms\Components\DateTimePicker::make('begin')->label(__('label.begin')),
Forms\Components\DateTimePicker::make('end')->label(__('label.begin')),
Forms\Components\TextInput::make('duration')
->integer()
->columnSpan(['sm' => 2])
->label(__('label.duration'))
->helperText('Unit: days. When assign to user, begin and end are used if they are specified. Otherwise begin time is the time at assignment, and the end time is the time at assignment plus the duration.'),
])->columns(2),
Forms\Components\Section::make('Select user')->schema([
Forms\Components\CheckboxList::make('filters.classes')->options($userRep->listClass())->columnSpan(['sm' => 2])->columns(4)->label('Classes'),
Forms\Components\DateTimePicker::make('filters.register_time_range.0')->label('Register time begin'),
Forms\Components\DateTimePicker::make('filters.register_time_range.1')->label('Register time end'),
Forms\Components\Toggle::make('filters.donate_status')->label('Donated'),
Forms\Components\CheckboxList::make('filters.classes')
->options($userRep->listClass())->columnSpan(['sm' => 2])
->columns(4)
->label(__('label.user.class')),
Forms\Components\DateTimePicker::make('filters.register_time_range.0')->label(__("label.exam.register_time_range.begin")),
Forms\Components\DateTimePicker::make('filters.register_time_range.1')->label(__("label.exam.register_time_range.end")),
Forms\Components\Toggle::make('filters.donate_status')->label(__('label.exam.donated')),
])->columns(2),
@@ -68,18 +92,19 @@ class ExamResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('indexFormatted')->label('Indexes')->html(),
Tables\Columns\TextColumn::make('begin'),
Tables\Columns\TextColumn::make('end'),
Tables\Columns\TextColumn::make('durationText')->label('Duration'),
Tables\Columns\TextColumn::make('filterFormatted')->label('Target users')->html(),
Tables\Columns\BooleanColumn::make('is_discovered')->label('Discovered'),
Tables\Columns\TextColumn::make('priority')->label('Priority'),
Tables\Columns\TextColumn::make('statusText')->label('Status'),
Tables\Columns\TextColumn::make('name')->searchable()->label(__('label.name')),
Tables\Columns\TextColumn::make('indexFormatted')->label(__('label.exam.index_formatted'))->html(),
Tables\Columns\TextColumn::make('begin')->label(__('label.begin')),
Tables\Columns\TextColumn::make('end')->label(__('label.begin')),
Tables\Columns\TextColumn::make('durationText')->label(__('label.duration')),
Tables\Columns\TextColumn::make('filterFormatted')->label(__('label.exam.filter_formatted'))->html(),
Tables\Columns\BooleanColumn::make('is_discovered')->label(__('label.exam.is_discovered')),
Tables\Columns\TextColumn::make('priority')->label(__('label.priority')),
Tables\Columns\TextColumn::make('statusText')->label(__('label.status')),
])
->filters([
//
Tables\Filters\SelectFilter::make('is_discovered')->options(self::IS_DISCOVERED_OPTIONS)->label(__("label.exam.is_discovered")),
Tables\Filters\SelectFilter::make('status')->options(self::STATUS_OPTIONS)->label(__("label.status")),
])
->actions([
// Tables\Actions\EditAction::make(),
+22 -13
View File
@@ -35,13 +35,22 @@ class MedalResource extends Resource
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('price')->required()->integer(),
Forms\Components\TextInput::make('image_large')->required(),
Forms\Components\TextInput::make('image_small')->required(),
Forms\Components\Radio::make('get_type')->options(Medal::listGetTypes(true))->inline()->columnSpan(['sm' => 2])->required(),
Forms\Components\TextInput::make('duration')->integer()->columnSpan(['sm' => 2])->helperText('Unit: day, if empty, belongs to user forever.'),
Forms\Components\Textarea::make('description')->columnSpan(['sm' => 2]),
Forms\Components\TextInput::make('name')->required()->label(__('label.name')),
Forms\Components\TextInput::make('price')->required()->integer()->label(__('label.price')),
Forms\Components\TextInput::make('image_large')->required()->label(__('label.medal.image_large')),
Forms\Components\TextInput::make('image_small')->required()->label(__('label.medal.image_small')),
Forms\Components\Radio::make('get_type')
->options(Medal::listGetTypes(true))
->inline()
->columnSpan(['sm' => 2])
->label(__('label.medal.get_type'))
->required(),
Forms\Components\TextInput::make('duration')
->integer()
->columnSpan(['sm' => 2])
->label(__('label.medal.duration'))
->helperText(__('label.medal.duration_help')),
Forms\Components\Textarea::make('description')->columnSpan(['sm' => 2])->label(__('label.description')),
]);
}
@@ -50,12 +59,12 @@ class MedalResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\ImageColumn::make('image_large')->height(120),
Tables\Columns\ImageColumn::make('image_small')->height(120),
Tables\Columns\TextColumn::make('getTypeText')->label('Get type'),
Tables\Columns\TextColumn::make('price'),
Tables\Columns\TextColumn::make('duration'),
Tables\Columns\TextColumn::make('name')->label(__('label.name')),
Tables\Columns\ImageColumn::make('image_large')->height(120)->label(__('label.medal.image_large')),
Tables\Columns\ImageColumn::make('image_small')->height(120)->label(__('label.medal.image_small')),
Tables\Columns\TextColumn::make('getTypeText')->label('Get type')->label(__('label.medal.get_type')),
Tables\Columns\TextColumn::make('price')->label(__('label.price')),
Tables\Columns\TextColumn::make('duration')->label(__('label.medal.duration')),
])
->filters([
//
+17 -17
View File
@@ -35,14 +35,14 @@ class TagResource extends Resource
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('color')->required()->label('Background color'),
Forms\Components\TextInput::make('font_color')->required(),
Forms\Components\TextInput::make('font_size')->required(),
Forms\Components\TextInput::make('margin')->required(),
Forms\Components\TextInput::make('padding')->required(),
Forms\Components\TextInput::make('border_radius')->required(),
Forms\Components\TextInput::make('priority')->integer(),
Forms\Components\TextInput::make('name')->required()->label(__('label.name')),
Forms\Components\TextInput::make('color')->required()->label(__('label.tag.color')),
Forms\Components\TextInput::make('font_color')->required()->label(__('label.tag.font_color')),
Forms\Components\TextInput::make('font_size')->required()->label(__('label.tag.font_size')),
Forms\Components\TextInput::make('margin')->required()->label(__('label.tag.margin')),
Forms\Components\TextInput::make('padding')->required()->label(__('label.tag.padding')),
Forms\Components\TextInput::make('border_radius')->required()->label(__('label.tag.border_radius')),
Forms\Components\TextInput::make('priority')->integer()->label(__('label.priority')),
]);
}
@@ -51,15 +51,15 @@ class TagResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('color')->label('Background color'),
Tables\Columns\TextColumn::make('font_color'),
Tables\Columns\TextColumn::make('font_size'),
Tables\Columns\TextColumn::make('margin'),
Tables\Columns\TextColumn::make('padding'),
Tables\Columns\TextColumn::make('border_radius'),
Tables\Columns\TextColumn::make('priority'),
Tables\Columns\TextColumn::make('updated_at')->dateTime('Y-m-d H:i'),
Tables\Columns\TextColumn::make('name')->label(__('label.name')),
Tables\Columns\TextColumn::make('color')->label(__('label.tag.color')),
Tables\Columns\TextColumn::make('font_color')->label(__('label.tag.font_color')),
Tables\Columns\TextColumn::make('font_size')->label(__('label.tag.font_size')),
Tables\Columns\TextColumn::make('margin')->label(__('label.tag.margin')),
Tables\Columns\TextColumn::make('padding')->label(__('label.tag.padding')),
Tables\Columns\TextColumn::make('border_radius')->label(__('label.tag.border_radius')),
Tables\Columns\TextColumn::make('priority')->label(__('label.priority')),
Tables\Columns\TextColumn::make('updated_at')->dateTime()->label(__('label.updated_at')),
])
->filters([
//
@@ -48,15 +48,17 @@ class ExamUserResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('user.username')->label('User')->searchable(),
Tables\Columns\TextColumn::make('exam.name')->label('Exam'),
Tables\Columns\BooleanColumn::make('is_done')->label('Is done'),
Tables\Columns\TextColumn::make('statusText')->label('Status'),
Tables\Columns\TextColumn::make('created_at')->dateTime('Y-m-d H:i'),
Tables\Columns\TextColumn::make('user.username')->label(__('label.username'))->searchable(),
Tables\Columns\TextColumn::make('exam.name')->label(__('label.exam.label')),
Tables\Columns\TextColumn::make('begin')->label(__('label.begin'))->dateTime(),
Tables\Columns\TextColumn::make('end')->label(__('label.end'))->dateTime(),
Tables\Columns\BooleanColumn::make('is_done')->label(__('label.exam.is_done')),
Tables\Columns\TextColumn::make('statusText')->label(__('label.status')),
Tables\Columns\TextColumn::make('created_at')->dateTime()->label(__('label.created_at')),
])
->filters([
Tables\Filters\SelectFilter::make('status')->options(ExamUser::listStatus(true)),
Tables\Filters\SelectFilter::make('is_done')->options(['0' => 'No', '1' => 'yes']),
Tables\Filters\SelectFilter::make('status')->options(ExamUser::listStatus(true))->label(__("label.status")),
Tables\Filters\SelectFilter::make('is_done')->options(['0' => 'No', '1' => 'yes'])->label(__('label.exam.is_done')),
])
->actions([
// Tables\Actions\ViewAction::make(),
@@ -68,6 +70,8 @@ class ExamUserResource extends Resource
$rep->avoidExamUserBulk(['id' => $idArr], Auth::user());
})
->deselectRecordsAfterCompletion()
->label(__('admin.resources.exam_user.bulk_action_avoid_label'))
->icon('heroicon-o-x')
]);
}
@@ -52,17 +52,17 @@ class HitAndRunResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('user.username')->searchable(),
Tables\Columns\TextColumn::make('torrent.name')->limit(50),
Tables\Columns\TextColumn::make('snatch.uploadText')->label('Uploaded'),
Tables\Columns\TextColumn::make('snatch.downloadText')->label('Downloaded'),
Tables\Columns\TextColumn::make('snatch.shareRatio')->label('Ratio'),
Tables\Columns\TextColumn::make('seedTimeRequired'),
Tables\Columns\TextColumn::make('inspectTimeLeft'),
Tables\Columns\TextColumn::make('statusText')->label('Status'),
Tables\Columns\TextColumn::make('user.username')->searchable()->label(__('label.username')),
Tables\Columns\TextColumn::make('torrent.name')->limit(50)->label(__('label.torrent.label')),
Tables\Columns\TextColumn::make('snatch.uploadText')->label(__('label.uploaded')),
Tables\Columns\TextColumn::make('snatch.downloadText')->label(__('label.downloaded')),
Tables\Columns\TextColumn::make('snatch.shareRatio')->label(__('label.ratio')),
Tables\Columns\TextColumn::make('seedTimeRequired')->label(__('label.seed_time_required')),
Tables\Columns\TextColumn::make('inspectTimeLeft')->label(__('label.inspect_time_left')),
Tables\Columns\TextColumn::make('statusText')->label(__('label.status')),
])
->filters([
Tables\Filters\SelectFilter::make('status')->options(HitAndRun::listStatus(true)),
Tables\Filters\SelectFilter::make('status')->options(HitAndRun::listStatus(true))->label(__('label.status')),
])
->actions([
Tables\Actions\ViewAction::make(),
@@ -0,0 +1,78 @@
<?php
namespace App\Filament\Resources\User;
use App\Filament\Resources\User\UserMedalResource\Pages;
use App\Filament\Resources\User\UserMedalResource\RelationManagers;
use App\Models\UserMedal;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\Resource;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class UserMedalResource extends Resource
{
protected static ?string $model = UserMedal::class;
protected static ?string $navigationIcon = 'heroicon-o-flag';
protected static ?string $navigationGroup = 'User';
protected static function getNavigationLabel(): string
{
return __('admin.sidebar.users_medal');
}
public static function getBreadcrumb(): string
{
return self::getNavigationLabel();
}
public static function form(Form $form): Form
{
return $form
->schema([
//
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('user.username')->label(__('label.username'))->searchable(),
Tables\Columns\TextColumn::make('medal.name')->label(__('label.medal.label'))->searchable(),
Tables\Columns\ImageColumn::make('medal.image_large')->label(__('label.image')),
Tables\Columns\TextColumn::make('expire_at')->label(__('label.expire_at'))->dateTime(),
])
->filters([
])
->actions([
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListUserMedals::route('/'),
'create' => Pages\CreateUserMedal::route('/create'),
'edit' => Pages\EditUserMedal::route('/{record}/edit'),
];
}
}
@@ -0,0 +1,12 @@
<?php
namespace App\Filament\Resources\User\UserMedalResource\Pages;
use App\Filament\Resources\User\UserMedalResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\CreateRecord;
class CreateUserMedal extends CreateRecord
{
protected static string $resource = UserMedalResource::class;
}
@@ -0,0 +1,19 @@
<?php
namespace App\Filament\Resources\User\UserMedalResource\Pages;
use App\Filament\Resources\User\UserMedalResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\EditRecord;
class EditUserMedal extends EditRecord
{
protected static string $resource = UserMedalResource::class;
protected function getActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}
@@ -0,0 +1,20 @@
<?php
namespace App\Filament\Resources\User\UserMedalResource\Pages;
use App\Filament\PageList;
use App\Filament\Resources\User\UserMedalResource;
use Filament\Pages\Actions;
use Filament\Resources\Pages\ListRecords;
class ListUserMedals extends PageList
{
protected static string $resource = UserMedalResource::class;
protected function getActions(): array
{
return [
// Actions\CreateAction::make(),
];
}
}
+16 -13
View File
@@ -2,6 +2,7 @@
namespace App\Filament\Resources\User;
use App\Filament\OptionsTrait;
use App\Filament\Resources\User\UserResource\Pages;
use App\Filament\Resources\User\UserResource\RelationManagers;
use App\Models\User;
@@ -17,6 +18,8 @@ use Illuminate\Database\Eloquent\SoftDeletingScope;
class UserResource extends Resource
{
use OptionsTrait;
protected static ?string $model = User::class;
protected static ?string $navigationIcon = 'heroicon-o-users';
@@ -51,27 +54,27 @@ class UserResource extends Resource
return $table
->columns([
Tables\Columns\TextColumn::make('id')->sortable(),
Tables\Columns\TextColumn::make('username')->searchable(),
Tables\Columns\TextColumn::make('email')->searchable(),
Tables\Columns\TextColumn::make('username')->searchable()->label(__("label.user.username")),
Tables\Columns\TextColumn::make('email')->searchable()->label(__("label.email")),
Tables\Columns\TextColumn::make('class')->label('Class')
->formatStateUsing(fn(Tables\Columns\Column $column) => $column->getRecord()->classText)
->sortable(),
->sortable()->label(__("label.user.class")),
Tables\Columns\TextColumn::make('uploaded')->label('Uploaded')
->formatStateUsing(fn(Tables\Columns\Column $column) => $column->getRecord()->uploadedText)
->sortable(),
->sortable()->label(__("label.uploaded")),
Tables\Columns\TextColumn::make('downloaded')->label('Downloaded')
->formatStateUsing(fn(Tables\Columns\Column $column) => $column->getRecord()->downloadedText)
->sortable(),
Tables\Columns\BadgeColumn::make('status')->colors(['success' => 'confirmed', 'warning' => 'pending']),
Tables\Columns\BadgeColumn::make('enabled')->colors(['success' => 'yes', 'danger' => 'no']),
Tables\Columns\TextColumn::make('added')->sortable()->dateTime('Y-m-d H:i'),
Tables\Columns\TextColumn::make('last_access')->dateTime('Y-m-d H:i'),
->sortable()->label(__("label.downloaded")),
Tables\Columns\BadgeColumn::make('status')->colors(['success' => 'confirmed', 'warning' => 'pending'])->label(__("label.user.status")),
Tables\Columns\BadgeColumn::make('enabled')->colors(['success' => 'yes', 'danger' => 'no'])->label(__("label.user.enabled")),
Tables\Columns\TextColumn::make('added')->sortable()->dateTime('Y-m-d H:i')->label(__("label.added")),
Tables\Columns\TextColumn::make('last_access')->dateTime('Y-m-d H:i')->label(__("label.last_access")),
])
->defaultSort('added', 'desc')
->filters([
Tables\Filters\SelectFilter::make('class')->options(array_column(User::$classes, 'text')),
Tables\Filters\SelectFilter::make('status')->options(['confirmed' => 'confirmed', 'pending' => 'pending']),
Tables\Filters\SelectFilter::make('enabled')->options(['enabled' => 'enabled', 'disabled' => 'disabled']),
Tables\Filters\SelectFilter::make('class')->options(array_column(User::$classes, 'text'))->label(__('label.user.class')),
Tables\Filters\SelectFilter::make('status')->options(['confirmed' => 'confirmed', 'pending' => 'pending'])->label(__('label.user.status')),
Tables\Filters\SelectFilter::make('enabled')->options(self::$yesOrNo)->label(__('label.user.enabled')),
])
->actions([
Tables\Actions\ViewAction::make(),
@@ -84,7 +87,7 @@ class UserResource extends Resource
public static function getRelations(): array
{
return [
//
// RelationManagers\MedalsRelationManager::class,
];
}
@@ -3,27 +3,215 @@
namespace App\Filament\Resources\User\UserResource\Pages;
use App\Filament\Resources\User\UserResource;
use App\Models\Medal;
use App\Models\User;
use App\Repositories\ExamRepository;
use App\Repositories\UserRepository;
use Filament\Resources\Pages\Concerns\HasRelationManagers;
use Filament\Resources\Pages\Concerns\InteractsWithRecord;
use Filament\Resources\Pages\Page;
use Filament\Pages\Actions;
use Filament\Forms;
use Illuminate\Support\Facades\Auth;
class UserProfile extends Page
{
use InteractsWithRecord;
use HasRelationManagers;
protected static string $resource = UserResource::class;
protected static string $view = 'filament.resources.user.user-resource.pages.user-profile';
protected ?User $user;
const EVENT_RECORD_UPDATED = 'recordUpdated';
protected $listeners = [
self::EVENT_RECORD_UPDATED => 'updateRecord'
];
public function updateRecord($id)
{
$this->record = $this->resolveRecord($id);
}
public function mount($record)
{
$this->user = User::query()->with(['inviter'])->findOrFail($record);
$this->updateRecord($record);
}
protected function getViewData(): array
protected function getActions(): array
{
return [
'user' => $this->user,
];
$actions = [];
if ($this->record->two_step_secret) {
$actions[] = $this->buildDisableTwoStepAuthenticationAction();
}
$actions[] = $this->buildResetPasswordAction();
$actions[] = $this->buildAssignExamAction();
$actions[] = $this->buildGrantMedalAction();
$actions[] = $this->buildChangeBonusEtcAction();
$actions[] = $this->buildEnableDisableAction();
return $actions;
}
private function buildEnableDisableAction(): Actions\Action
{
return Actions\Action::make($this->record->enabled == 'yes' ? __('admin.resources.user.actions.disable_modal_btn') : __('admin.resources.user.actions.enable_modal_btn'))
->modalHeading($this->record->enabled == 'yes' ? __('admin.resources.user.actions.disable_modal_title') : __('admin.resources.user.actions.enable_modal_title'))
->form([
Forms\Components\TextInput::make('reason')->label(__('admin.resources.user.actions.enable_disable_reason'))->placeholder(__('admin.resources.user.actions.enable_disable_reason_placeholder')),
Forms\Components\Hidden::make('action')->default($this->record->enabled == 'yes' ? 'disable' : 'enable'),
Forms\Components\Hidden::make('uid')->default($this->record->id),
])
->action(function ($data) {
$userRep = new UserRepository();
try {
if ($data['action'] == 'enable') {
$userRep->enableUser(Auth::user(), $data['uid'], $data['reason']);
} elseif ($data['action'] == 'disable') {
$userRep->disableUser(Auth::user(), $data['uid'], $data['reason']);
}
$this->notify('success', 'Success!');
$this->emitSelf(self::EVENT_RECORD_UPDATED, $data['uid']);
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
});
}
private function buildDisableTwoStepAuthenticationAction(): Actions\Action
{
return Actions\Action::make(__('admin.resources.user.actions.disable_two_step_authentication'))
->modalHeading(__('admin.resources.user.actions.disable_two_step_authentication'))
->requiresConfirmation()
->action(function ($data) {
$userRep = new UserRepository();
try {
$userRep->removeTwoStepAuthentication(Auth::user(), $this->record->id);
$this->notify('success', 'Success!');
$this->emitSelf(self::EVENT_RECORD_UPDATED, $this->record->id);
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
});
}
private function buildChangeBonusEtcAction(): Actions\Action
{
return Actions\Action::make(__('admin.resources.user.actions.change_bonus_etc_btn'))
->modalHeading(__('admin.resources.user.actions.change_bonus_etc_btn'))
->form([
Forms\Components\Radio::make('field')->options([
'uploaded' => __('label.user.uploaded'),
'downloaded' => __('label.user.downloaded'),
'invites' => __('label.user.invites'),
'seedbonus' => __('label.user.seedbonus'),
'attendance_card' => __('label.user.attendance_card'),
])->label(__('admin.resources.user.actions.change_bonus_etc_field_label'))->inline()->required(),
Forms\Components\Radio::make('action')->options([
'Increment' => __("admin.resources.user.actions.change_bonus_etc_action_increment"),
'Decrement' => __("admin.resources.user.actions.change_bonus_etc_action_decrement"),
])->label(__('admin.resources.user.actions.change_bonus_etc_action_label'))->inline()->required(),
Forms\Components\TextInput::make('value')->integer()->required()
->label(__('admin.resources.user.actions.change_bonus_etc_value_label'))
->helperText(__('admin.resources.user.actions.change_bonus_etc_value_help')),
Forms\Components\Textarea::make('reason')->label(__('admin.resources.user.actions.change_bonus_etc_reason_label')),
])
->action(function ($data) {
$userRep = new UserRepository();
try {
$userRep->incrementDecrement(Auth::user(), $this->record->id, $data['action'], $data['field'], $data['value'], $data['reason']);
$this->notify('success', 'Success!');
$this->emitSelf(self::EVENT_RECORD_UPDATED, $this->record->id);
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
});
}
private function buildResetPasswordAction()
{
return Actions\Action::make(__('admin.resources.user.actions.reset_password_btn'))
->modalHeading(__('admin.resources.user.actions.reset_password_btn'))
->form([
Forms\Components\TextInput::make('password')->label(__('admin.resources.user.actions.reset_password_label'))->required(),
Forms\Components\TextInput::make('password_confirmation')
->label(__('admin.resources.user.actions.reset_password_confirmation_label'))
->same('password')
->required(),
])
->action(function ($data) {
$userRep = new UserRepository();
try {
$userRep->resetPassword($this->record->id, $data['password'], $data['password_confirmation']);
$this->notify('success', 'Success!');
$this->emitSelf(self::EVENT_RECORD_UPDATED, $this->record->id);
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
});
}
private function buildAssignExamAction()
{
return Actions\Action::make(__('admin.resources.user.actions.assign_exam_btn'))
->modalHeading(__('admin.resources.user.actions.assign_exam_btn'))
->form([
Forms\Components\Select::make('exam_id')
->options((new ExamRepository())->listMatchExam($this->record->id)->pluck('name', 'id'))
->label(__('admin.resources.user.actions.assign_exam_exam_label'))->required(),
Forms\Components\DateTimePicker::make('begin')->label(__('admin.resources.user.actions.assign_exam_begin_label')),
Forms\Components\DateTimePicker::make('end')->label(__('admin.resources.user.actions.assign_exam_end_label'))
->helperText(__('admin.resources.user.actions.assign_exam_end_help')),
])
->action(function ($data) {
$examRep = new ExamRepository();
try {
$examRep->assignToUser($this->record->id, $data['exam_id'], $data['begin'], $data['end']);
$this->notify('success', 'Success!');
$this->emitSelf(self::EVENT_RECORD_UPDATED, $this->record->id);
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
});
}
private function buildGrantMedalAction()
{
return Actions\Action::make(__('admin.resources.user.actions.grant_medal_btn'))
->modalHeading(__('admin.resources.user.actions.grant_medal_btn'))
->form([
Forms\Components\Select::make('medal_id')
->options(Medal::query()->pluck('name', 'id'))
->label(__('admin.resources.user.actions.grant_medal_medal_label'))
->required(),
Forms\Components\TextInput::make('duration')
->label(__('admin.resources.user.actions.grant_medal_duration_label'))
->helperText(__('admin.resources.user.actions.grant_medal_duration_help'))
->integer(),
])
->action(function ($data) {
$examRep = new ExamRepository();
try {
$examRep->assignToUser($this->record->id, $data['exam_id'], $data['begin'], $data['end']);
$this->notify('success', 'Success!');
$this->emitSelf(self::EVENT_RECORD_UPDATED, $this->record->id);
} catch (\Exception $exception) {
$this->notify('danger', $exception->getMessage());
}
});
}
// protected function getViewData(): array
// {
// return [
// 'enableDisableAction' => $this->buildEnableDisableAction(),
// ];
// }
}
@@ -0,0 +1,51 @@
<?php
namespace App\Filament\Resources\User\UserResource\RelationManagers;
use Filament\Forms;
use Filament\Resources\Form;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Resources\Table;
use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
class MedalsRelationManager extends RelationManager
{
protected static string $relationship = 'medals';
protected static ?string $recordTitleAttribute = 'name';
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')
->required()
->maxLength(255),
]);
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name')->label(__('label.name')),
Tables\Columns\ImageColumn::make('image_large')->label(__('label.image')),
Tables\Columns\ImageColumn::make('expire_at')->label(__('label.expire_at')),
])
->filters([
//
])
->headerActions([
// Tables\Actions\CreateAction::make(),
])
->actions([
// Tables\Actions\EditAction::make(),
Tables\Actions\DeleteAction::make(),
])
->bulkActions([
Tables\Actions\DeleteBulkAction::make(),
]);
}
}
+1 -1
View File
@@ -33,7 +33,7 @@ class ExamUser extends NexusModel
public function getStatusTextAttribute(): string
{
return self::$status[$this->status]['text'] ?? '';
return nexus_trans('exam-user.status.' . $this->status);
}
public function getIsDoneTextAttribute(): string
+9
View File
@@ -9,5 +9,14 @@ class UserMedal extends NexusModel
const STATUS_NOT_WEARING = 0;
const STATUS_WEARING = 1;
public function medal()
{
return $this->belongsTo(Medal::class, 'medal_id');
}
public function user()
{
return $this->belongsTo(User::class, 'uid');
}
}
+3 -3
View File
@@ -176,7 +176,7 @@ class UserRepository extends BaseRepository
return true;
}
public function enableUser(User $operator, $uid)
public function enableUser(User $operator, $uid, $reason = '')
{
$targetUser = User::query()->findOrFail($uid, ['id', 'enabled', 'username', 'class']);
if ($targetUser->enabled == User::ENABLED_YES) {
@@ -194,7 +194,7 @@ class UserRepository extends BaseRepository
$update['leechwarn'] = 'no';
$update['leechwarnuntil'] = null;
}
$modCommentText = sprintf("%s - Enable by %s.", now()->format('Y-m-d'), $operator->username);
$modCommentText = sprintf("%s - Enable by %s, reason: %s", now()->format('Y-m-d'), $operator->username, $reason);
$targetUser->updateWithModComment($update, $modCommentText);
do_log("user: $uid, $modCommentText, update: " . nexus_json_encode($update));
return true;
@@ -217,7 +217,7 @@ class UserRepository extends BaseRepository
$fieldMap = [
'uploaded' => 'uploaded',
'downloaded' => 'downloaded',
'bonus' => 'seedbonus',
'seedbonus' => 'seedbonus',
'invites' => 'invites',
'attendance_card' => 'attendance_card',
];