From 579351c0eb22be876595e5c7febce6c229bd7296 Mon Sep 17 00:00:00 2001 From: xiaomlove Date: Thu, 30 Jun 2022 21:08:25 +0800 Subject: [PATCH] improve filament trans + user profile actions --- app/Filament/Custom/Widgets/StatTable.php | 2 +- .../Resources/System/AgentAllowResource.php | 34 +-- .../Pages/ListAgentAllows.php | 19 ++ .../Resources/System/AgentDenyResource.php | 18 +- .../Resources/System/ExamResource.php | 67 ++++-- .../Resources/System/MedalResource.php | 35 +-- .../Resources/Torrent/TagResource.php | 34 +-- .../Resources/User/ExamUserResource.php | 18 +- .../Resources/User/HitAndRunResource.php | 18 +- .../Resources/User/UserMedalResource.php | 78 +++++++ .../Pages/CreateUserMedal.php | 12 ++ .../UserMedalResource/Pages/EditUserMedal.php | 19 ++ .../Pages/ListUserMedals.php | 20 ++ app/Filament/Resources/User/UserResource.php | 29 +-- .../User/UserResource/Pages/UserProfile.php | 200 +++++++++++++++++- .../MedalsRelationManager.php | 51 +++++ app/Models/ExamUser.php | 2 +- app/Models/UserMedal.php | 9 + app/Repositories/UserRepository.php | 6 +- resources/lang/en/admin.php | 41 ++++ resources/lang/en/label.php | 62 +++++- resources/lang/zh_CN/admin.php | 42 ++++ resources/lang/zh_CN/label.php | 84 +++++++- resources/lang/zh_TW/admin.php | 42 ++++ resources/lang/zh_TW/label.php | 84 +++++++- .../pages/user-profile.blade.php | 56 ++--- .../filament/widgets/stat-table.blade.php | 62 +++--- 27 files changed, 966 insertions(+), 178 deletions(-) create mode 100644 app/Filament/Resources/User/UserMedalResource.php create mode 100644 app/Filament/Resources/User/UserMedalResource/Pages/CreateUserMedal.php create mode 100644 app/Filament/Resources/User/UserMedalResource/Pages/EditUserMedal.php create mode 100644 app/Filament/Resources/User/UserMedalResource/Pages/ListUserMedals.php create mode 100644 app/Filament/Resources/User/UserResource/RelationManagers/MedalsRelationManager.php diff --git a/app/Filament/Custom/Widgets/StatTable.php b/app/Filament/Custom/Widgets/StatTable.php index 1ff84dac..f05c7b84 100644 --- a/app/Filament/Custom/Widgets/StatTable.php +++ b/app/Filament/Custom/Widgets/StatTable.php @@ -11,7 +11,7 @@ class StatTable extends Widget protected function getHeader(): string { - return nulll; + } protected function getTableRows(): array diff --git a/app/Filament/Resources/System/AgentAllowResource.php b/app/Filament/Resources/System/AgentAllowResource.php index 85298d63..79a16f0f 100644 --- a/app/Filament/Resources/System/AgentAllowResource.php +++ b/app/Filament/Resources/System/AgentAllowResource.php @@ -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([ // diff --git a/app/Filament/Resources/System/AgentAllowResource/Pages/ListAgentAllows.php b/app/Filament/Resources/System/AgentAllowResource/Pages/ListAgentAllows.php index 413914c1..e76240ef 100644 --- a/app/Filament/Resources/System/AgentAllowResource/Pages/ListAgentAllows.php +++ b/app/Filament/Resources/System/AgentAllowResource/Pages/ListAgentAllows.php @@ -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()); + } + }) + ]; } } diff --git a/app/Filament/Resources/System/AgentDenyResource.php b/app/Filament/Resources/System/AgentDenyResource.php index 94b191c5..efea3ab6 100644 --- a/app/Filament/Resources/System/AgentDenyResource.php +++ b/app/Filament/Resources/System/AgentDenyResource.php @@ -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([ // diff --git a/app/Filament/Resources/System/ExamResource.php b/app/Filament/Resources/System/ExamResource.php index a63ac219..875c51bd 100644 --- a/app/Filament/Resources/System/ExamResource.php +++ b/app/Filament/Resources/System/ExamResource.php @@ -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(), diff --git a/app/Filament/Resources/System/MedalResource.php b/app/Filament/Resources/System/MedalResource.php index 7efc2224..7690e389 100644 --- a/app/Filament/Resources/System/MedalResource.php +++ b/app/Filament/Resources/System/MedalResource.php @@ -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([ // diff --git a/app/Filament/Resources/Torrent/TagResource.php b/app/Filament/Resources/Torrent/TagResource.php index 22148419..5218f009 100644 --- a/app/Filament/Resources/Torrent/TagResource.php +++ b/app/Filament/Resources/Torrent/TagResource.php @@ -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([ // diff --git a/app/Filament/Resources/User/ExamUserResource.php b/app/Filament/Resources/User/ExamUserResource.php index 80071189..46ce3690 100644 --- a/app/Filament/Resources/User/ExamUserResource.php +++ b/app/Filament/Resources/User/ExamUserResource.php @@ -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') ]); } diff --git a/app/Filament/Resources/User/HitAndRunResource.php b/app/Filament/Resources/User/HitAndRunResource.php index aa2190b5..e571ffa4 100644 --- a/app/Filament/Resources/User/HitAndRunResource.php +++ b/app/Filament/Resources/User/HitAndRunResource.php @@ -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(), diff --git a/app/Filament/Resources/User/UserMedalResource.php b/app/Filament/Resources/User/UserMedalResource.php new file mode 100644 index 00000000..bea7de7f --- /dev/null +++ b/app/Filament/Resources/User/UserMedalResource.php @@ -0,0 +1,78 @@ +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'), + ]; + } +} diff --git a/app/Filament/Resources/User/UserMedalResource/Pages/CreateUserMedal.php b/app/Filament/Resources/User/UserMedalResource/Pages/CreateUserMedal.php new file mode 100644 index 00000000..7023c796 --- /dev/null +++ b/app/Filament/Resources/User/UserMedalResource/Pages/CreateUserMedal.php @@ -0,0 +1,12 @@ +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, ]; } diff --git a/app/Filament/Resources/User/UserResource/Pages/UserProfile.php b/app/Filament/Resources/User/UserResource/Pages/UserProfile.php index c163e130..58ae14b4 100644 --- a/app/Filament/Resources/User/UserResource/Pages/UserProfile.php +++ b/app/Filament/Resources/User/UserResource/Pages/UserProfile.php @@ -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(), +// ]; +// } } diff --git a/app/Filament/Resources/User/UserResource/RelationManagers/MedalsRelationManager.php b/app/Filament/Resources/User/UserResource/RelationManagers/MedalsRelationManager.php new file mode 100644 index 00000000..ab14f90c --- /dev/null +++ b/app/Filament/Resources/User/UserResource/RelationManagers/MedalsRelationManager.php @@ -0,0 +1,51 @@ +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(), + ]); + } +} diff --git a/app/Models/ExamUser.php b/app/Models/ExamUser.php index 61a7a4e1..6f2cc10f 100644 --- a/app/Models/ExamUser.php +++ b/app/Models/ExamUser.php @@ -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 diff --git a/app/Models/UserMedal.php b/app/Models/UserMedal.php index 291b266d..c845748e 100644 --- a/app/Models/UserMedal.php +++ b/app/Models/UserMedal.php @@ -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'); + } } diff --git a/app/Repositories/UserRepository.php b/app/Repositories/UserRepository.php index da62764c..416f3784 100644 --- a/app/Repositories/UserRepository.php +++ b/app/Repositories/UserRepository.php @@ -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', ]; diff --git a/resources/lang/en/admin.php b/resources/lang/en/admin.php index 457ebe94..dd54edf7 100644 --- a/resources/lang/en/admin.php +++ b/resources/lang/en/admin.php @@ -12,4 +12,45 @@ return [ 'medals_list' => 'Medals', 'settings' => 'Settings', ], + 'resources' => [ + 'agent_allow' => [ + 'check_modal_btn' => 'Check', + 'check_modal_header' => 'Detect if the client is allowed', + 'check_pass_msg' => 'Congratulations, this client was passed by rule :id!', + ], + 'user' => [ + 'actions' => [ + 'enable_modal_btn' => 'Enable', + 'enable_modal_title' => 'Enable user', + 'enable_disable_reason' => 'Reason', + 'enable_disable_reason_placeholder' => 'Optional', + 'disable_modal_btn' => 'Disable', + 'disable_modal_title' => 'Disable user', + 'disable_two_step_authentication' => 'Cancel two-step authentication', + 'change_bonus_etc_btn' => 'Change Uploaded etc.', + 'change_bonus_etc_action_increment' => 'Increment', + 'change_bonus_etc_action_decrement' => 'Decrement', + 'change_bonus_etc_field_label' => 'Field', + 'change_bonus_etc_action_label' => 'Action', + 'change_bonus_etc_value_label' => 'Value', + 'change_bonus_etc_value_help' => 'If the type is Uploaded/Download, the unit is: GB', + 'change_bonus_etc_reason_label' => 'Reason', + 'reset_password_btn' => 'Reset password', + 'reset_password_label' => 'New password', + 'reset_password_confirmation_label' => 'Confirm new password', + 'assign_exam_btn' => 'Assign exam', + 'assign_exam_exam_label' => 'Select exam', + 'assign_exam_begin_label' => 'Begin time', + 'assign_exam_end_label' => 'End time', + 'assign_exam_end_help' => 'If you do not specify a begin/end time, the time range set by the exam itself will be used', + 'grant_medal_btn' => 'Grant medal', + 'grant_medal_medal_label' => 'Select medal', + 'grant_medal_duration_label' => 'Duration', + 'grant_medal_duration_help' => 'Unit: days. If left blank, the user has permanent possession', + ] + ], + 'exam_user' => [ + 'bulk_action_avoid_label' => 'Bulk avoid', + ], + ] ]; diff --git a/resources/lang/en/label.php b/resources/lang/en/label.php index 50082889..f69f7d30 100644 --- a/resources/lang/en/label.php +++ b/resources/lang/en/label.php @@ -36,6 +36,66 @@ return [ ] ], 'user' => [ + 'uploaded' => 'Uploaded', + 'downloaded' => 'Downloaded', + 'invites' => 'Invites', + 'seedbonus' => 'Bonus', + 'attendance_card' => 'Attendance ard', + 'class' => 'Class', + 'status' => 'Status', + 'enabled' => 'Enabled', + 'username' => 'Username', + ], + 'medal' => [ + 'label' => 'Medal', + 'image_large' => 'Image large', + 'image_small' => 'Image small', + 'get_type' => 'Get type', + 'duration' => 'Duration', + 'duration_help' => 'Unit: days. If left blank, the user has permanent possession', + ], + 'exam' => [ + 'label' => 'Exam', + 'is_done' => 'Is done', + 'is_discovered' => 'Discovered', + 'register_time_range' => [ + 'begin' => 'Register time begin', + 'end' => 'Register time end', + ], + 'donated' => 'Donated', + 'index_formatted' => 'Exam indexes', + 'filter_formatted' => 'Target users', + ], + 'torrent' => [ + 'label' => 'Torrent', + ], + 'hit_and_run' => [ - ] + ], + 'tag' => [ + 'color' => 'Background color', + 'font_color' => 'Font color', + 'font_size' => 'Font size', + 'margin' => 'Margin', + 'padding' => 'Padding', + 'border_radius' => 'Border radius', + ], + 'agent_allow' => [ + 'family' => 'Family', + 'start_name' => 'Start name', + 'peer_id_start' => 'Peer ID start', + 'peer_id_pattern' => 'Peer ID pattern', + 'peer_id_matchtype' => 'Peer ID match type', + 'peer_id_match_num' => 'Peer ID match num', + 'agent_start' => 'Agent start', + 'agent_pattern' => 'Agent pattern', + 'agent_matchtype' => 'Agent match type', + 'agent_match_num' => 'Agent match num', + 'exception' => 'Exception', + 'allowhttps' => 'Allow https', + ], + 'agent_deny' => [ + 'peer_id' => 'Peer ID', + 'agent' => 'Agent', + ], ]; diff --git a/resources/lang/zh_CN/admin.php b/resources/lang/zh_CN/admin.php index 3112c308..4e63fffa 100644 --- a/resources/lang/zh_CN/admin.php +++ b/resources/lang/zh_CN/admin.php @@ -11,5 +11,47 @@ return [ 'exams_list' => '考核', 'medals_list' => '勋章', 'settings' => '设置', + 'users_medal' => '用户勋章', ], + 'resources' => [ + 'agent_allow' => [ + 'check_modal_btn' => '检测', + 'check_modal_header' => '检测客户端是否被允许', + 'check_pass_msg' => '恭喜,此客户端被规则 :id 通过!', + ], + 'user' => [ + 'actions' => [ + 'enable_modal_btn' => '启用', + 'enable_modal_title' => '启用用户', + 'enable_disable_reason' => '原因', + 'enable_disable_reason_placeholder' => '可选', + 'disable_modal_btn' => '禁用', + 'disable_modal_title' => '禁用用户', + 'disable_two_step_authentication' => '取消两步登录验证', + 'change_bonus_etc_btn' => '修改上传量等', + 'change_bonus_etc_action_increment' => '增加', + 'change_bonus_etc_action_decrement' => '减少', + 'change_bonus_etc_field_label' => '类别', + 'change_bonus_etc_action_label' => '动作', + 'change_bonus_etc_value_label' => '数量', + 'change_bonus_etc_value_help' => '如果类别是上传量/下载量,单位为:GB', + 'change_bonus_etc_reason_label' => '原因', + 'reset_password_btn' => '重置密码', + 'reset_password_label' => '新密码', + 'reset_password_confirmation_label' => '确认新密码', + 'assign_exam_btn' => '分配考核', + 'assign_exam_exam_label' => '选择考核', + 'assign_exam_begin_label' => '开始时间', + 'assign_exam_end_label' => '结束时间', + 'assign_exam_end_help' => '如果不指定开始/结束时间,将使用考核本身设定的时间范围', + 'grant_medal_btn' => '授予勋章', + 'grant_medal_medal_label' => '选择勋章', + 'grant_medal_duration_label' => '有效时长', + 'grant_medal_duration_help' => '单位:天。如果留空,用户永久拥有', + ] + ], + 'exam_user' => [ + 'bulk_action_avoid_label' => '批量免除', + ], + ] ]; diff --git a/resources/lang/zh_CN/label.php b/resources/lang/zh_CN/label.php index bd5f3abc..459fae74 100644 --- a/resources/lang/zh_CN/label.php +++ b/resources/lang/zh_CN/label.php @@ -1,6 +1,28 @@ '名称', + 'email' => '邮箱', + 'image' => '图片', + 'expire_at' => '过期时间', + 'username' => '用户', + 'status' => '状态', + 'created_at' => '创建时间', + 'updated_at' => '更新时间', + 'begin' => '开始时间', + 'end' => '结束时间', + 'uploaded' => '上传量', + 'downloaded' => '下载量', + 'ratio' => '分享率', + 'seed_time_required' => '还需做种时间', + 'inspect_time_left' => '考察剩余时间', + 'added' => '添加时间', + 'last_access' => '最后访问时间', + 'priority' => '优先级', + 'comment' => '备注', + 'duration' => '时长', + 'description' => '描述', + 'price' => '价格', 'setting' => [ 'nav_text' => '设置', 'backup' => [ @@ -36,6 +58,66 @@ return [ ] ], 'user' => [ + 'uploaded' => '上传量', + 'downloaded' => '下载量', + 'invites' => '邀请', + 'seedbonus' => '魔力', + 'attendance_card' => '补签卡', + 'class' => '等级', + 'status' => '状态', + 'enabled' => '启用', + 'username' => '用户名', + ], + 'medal' => [ + 'label' => '勋章', + 'image_large' => '大图', + 'image_small' => '小图', + 'get_type' => '获取方式', + 'duration' => '有效时长', + 'duration_help' => '单位:天。如果留空,用户永久拥有', + ], + 'exam' => [ + 'label' => '考核', + 'is_done' => '是否完成', + 'is_discovered' => '自动发现', + 'register_time_range' => [ + 'begin' => '注册时间开始', + 'end' => '注册时间结束', + ], + 'donated' => '是否捐赠', + 'index_formatted' => '考核指标', + 'filter_formatted' => '目标用户', + ], + 'torrent' => [ + 'label' => '种子', + ], + 'hit_and_run' => [ - ] + ], + 'tag' => [ + 'color' => '背景颜色', + 'font_color' => '字体颜色', + 'font_size' => '字体大小', + 'margin' => '外边距', + 'padding' => '内边距', + 'border_radius' => '边框圆角', + ], + 'agent_allow' => [ + 'family' => '系列', + 'start_name' => '起始名称', + 'peer_id_start' => 'Peer ID 超始', + 'peer_id_pattern' => 'Peer ID 正则', + 'peer_id_matchtype' => 'Peer ID 匹配类型', + 'peer_id_match_num' => 'Peer ID 匹配次数', + 'agent_start' => 'Agent 起始', + 'agent_pattern' => 'Agent 正则', + 'agent_matchtype' => 'Agent 匹配类型', + 'agent_match_num' => 'Agent 匹配次数', + 'exception' => '排除', + 'allowhttps' => '允许 https', + ], + 'agent_deny' => [ + 'peer_id' => 'Peer ID', + 'agent' => 'Agent', + ], ]; diff --git a/resources/lang/zh_TW/admin.php b/resources/lang/zh_TW/admin.php index 4b5d4cd1..db540684 100644 --- a/resources/lang/zh_TW/admin.php +++ b/resources/lang/zh_TW/admin.php @@ -11,5 +11,47 @@ return [ 'exams_list' => '考核', 'medals_list' => '勛章', 'settings' => '設置', + 'users_medal' => '用戶勛章', ], + 'resources' => [ + 'agent_allow' => [ + 'check_modal_btn' => '檢測', + 'check_modal_header' => '檢測客戶端是否被允許', + 'check_pass_msg' => '恭喜,此客戶端被規則 :id 通過!', + ], + 'user' => [ + 'actions' => [ + 'enable_modal_btn' => '啟用', + 'enable_modal_title' => '啟用用戶', + 'enable_disable_reason' => '原因', + 'enable_disable_reason_placeholder' => '可選', + 'disable_modal_btn' => '禁用', + 'disable_modal_title' => '禁用用戶', + 'disable_two_step_authentication' => '取消兩步登錄驗證', + 'change_bonus_etc_btn' => '修改上傳量等', + 'change_bonus_etc_action_increment' => '增加', + 'change_bonus_etc_action_decrement' => '減少', + 'change_bonus_etc_field_label' => '類別', + 'change_bonus_etc_action_label' => '動作', + 'change_bonus_etc_value_label' => '數量', + 'change_bonus_etc_value_help' => '如果類別是上傳量/下載量,單位為:GB', + 'change_bonus_etc_reason_label' => '原因', + 'reset_password_btn' => '重置密碼', + 'reset_password_label' => '新密碼', + 'reset_password_confirmation_label' => '確認新密碼', + 'assign_exam_btn' => '分配考核', + 'assign_exam_exam_label' => '選擇考核', + 'assign_exam_begin_label' => '開始時間', + 'assign_exam_end_label' => '結束時間', + 'assign_exam_end_help' => '如果不指定開始/結束時間,將使用考核本身設定的時間範圍', + 'grant_medal_btn' => '授予勛章', + 'grant_medal_medal_label' => '選擇勛章', + 'grant_medal_duration_label' => '有效時長', + 'grant_medal_duration_help' => '單位:天。如果留空,用戶永久擁有', + ] + ], + 'exam_user' => [ + 'bulk_action_avoid_label' => '批量免除', + ], + ] ]; diff --git a/resources/lang/zh_TW/label.php b/resources/lang/zh_TW/label.php index d42fa3c7..ef944cfb 100644 --- a/resources/lang/zh_TW/label.php +++ b/resources/lang/zh_TW/label.php @@ -1,6 +1,28 @@ '名稱', + 'email' => '郵箱', + 'image' => '圖片', + 'expire_at' => '過期時間', + 'username' => '用戶', + 'status' => '狀態', + 'created_at' => '創建時間', + 'updated_at' => '更新時間', + 'begin' => '開始時間', + 'end' => '結束時間', + 'uploaded' => '上傳量', + 'downloaded' => '下載量', + 'ratio' => '分享率', + 'seed_time_required' => '還需做種時間', + 'inspect_time_left' => '考察剩余時間', + 'added' => '添加時間', + 'last_access' => '最後訪問時間', + 'priority' => '優先級', + 'comment' => '備註', + 'duration' => '時長', + 'description' => '描述', + 'price' => '價格', 'setting' => [ 'nav_text' => '設置', 'backup' => [ @@ -36,6 +58,66 @@ return [ ] ], 'user' => [ + 'uploaded' => '上傳量', + 'downloaded' => '下載量', + 'invites' => '邀請', + 'seedbonus' => '魔力', + 'attendance_card' => '補簽卡', + 'class' => '等級', + 'status' => '狀態', + 'enabled' => '啟用', + 'username' => '用戶名', + ], + 'medal' => [ + 'label' => '勛章', + 'image_large' => '大圖', + 'image_small' => '小圖', + 'get_type' => '獲取方式', + 'duration' => '有效時長', + 'duration_help' => '單位:天。如果留空,用戶永久擁有', + ], + 'exam' => [ + 'label' => '考核', + 'is_done' => '是否完成', + 'is_discovered' => '自動發現', + 'register_time_range' => [ + 'begin' => '註冊時間開始', + 'end' => '註冊時間結束', + ], + 'donated' => '是否捐贈', + 'index_formatted' => '考核指標', + 'filter_formatted' => '目標用戶', + ], + 'torrent' => [ + 'label' => '種子', + ], + 'hit_and_run' => [ - ] + ], + 'tag' => [ + 'color' => '背景顏色', + 'font_color' => '字體顏色', + 'font_size' => '字體大小', + 'margin' => '外邊距', + 'padding' => '內邊距', + 'border_radius' => '邊框圓角', + ], + 'agent_allow' => [ + 'family' => '系列', + 'start_name' => '起始名稱', + 'peer_id_start' => 'Peer ID 超始', + 'peer_id_pattern' => 'Peer ID 正則', + 'peer_id_matchtype' => 'Peer ID 匹配類型', + 'peer_id_match_num' => 'Peer ID 匹配次數', + 'agent_start' => 'Agent 起始', + 'agent_pattern' => 'Agent 正則', + 'agent_matchtype' => 'Agent 匹配類型', + 'agent_match_num' => 'Agent 匹配次數', + 'exception' => '排除', + 'allowhttps' => '允許 https', + ], + 'agent_deny' => [ + 'peer_id' => 'Peer ID', + 'agent' => 'Agent', + ], ]; diff --git a/resources/views/filament/resources/user/user-resource/pages/user-profile.blade.php b/resources/views/filament/resources/user/user-resource/pages/user-profile.blade.php index 03744c83..021659fb 100644 --- a/resources/views/filament/resources/user/user-resource/pages/user-profile.blade.php +++ b/resources/views/filament/resources/user/user-resource/pages/user-profile.blade.php @@ -5,83 +5,83 @@ UID - {{$user->id}} + {{$record->id}} Username - {{$user->username}} + {{$record->username}} Email - {{$user->email}} + {{$record->email}} Status - {{$user->status}} + {{$record->status}} Enabled - {{$user->enabled}} - + {{$record->enabled}} + Added - {{$user->added}} + {{$record->added}} Last access - {{$user->last_access}} + {{$record->last_access}} Class - {{$user->classText}} + {{$record->classText}} Invite by - {{$user->inviter->username ?? ''}} - + {{$record->inviter->username ?? ''}} + Tow-step authentication - {{$user->two_step_secret ? 'Enabled' : 'Disabled'}} - + {{$record->two_step_secret ? 'Enabled' : 'Disabled'}} + Seed points - {{$user->seed_points}} - + {{$record->seed_points}} + Attendance card - {{$user->attendance_card}} - + {{$record->attendance_card}} + Invites - {{$user->invites}} - + {{$record->invites}} + Uploaded - {{$user->uploadedText}} - + {{$record->uploadedText}} + Downloaded - {{$user->downloadedText}} - + {{$record->downloadedText}} + Bonus - {{$user->seedbonus}} - + {{$record->seedbonus}} + @@ -91,4 +91,10 @@ + + @if (count($relationManagers = $this->getRelationManagers())) + + + + @endif diff --git a/resources/views/filament/widgets/stat-table.blade.php b/resources/views/filament/widgets/stat-table.blade.php index cf4b9e5c..4cb9e4f5 100644 --- a/resources/views/filament/widgets/stat-table.blade.php +++ b/resources/views/filament/widgets/stat-table.blade.php @@ -1,40 +1,36 @@ - - -
-
-
-
-

- {{$header}} -

-
- - - -
- - - @foreach(array_chunk($data, 2) as $chunk) - - @foreach($chunk as $item) - - - @endforeach - + +
+
+
+
+

+ {{$header}} +

+
+ +
+
{{$item['text']}}
count == 1) - colspan="3" - @endif - > -
{{$item['value']}}
-
+ + @foreach(array_chunk($data, 2) as $chunk) + + @foreach($chunk as $item) + + @endforeach + + @endforeach - -
{{$item['text']}}
count == 1) + colspan="3" + @endif + > +
{{$item['value']}}
+
+ + -
-
+