[admin] torrent add more bulk action

This commit is contained in:
xiaomlove
2022-10-02 21:14:11 +08:00
parent cdaec9bc62
commit bb000fb67a
28 changed files with 313 additions and 28 deletions
+8
View File
@@ -15,4 +15,12 @@ trait OptionsTrait
$disableValue => __('label.disabled'),
];
}
private static function getYesNoOptions($yesValue = 1, $noValue = 0): array
{
return [
$yesValue => 'Yes',
$noValue => 'No',
];
}
}
@@ -56,6 +56,7 @@ class SeedBoxRecordResource extends Resource
->columns([
Tables\Columns\TextColumn::make('id'),
Tables\Columns\TextColumn::make('typeText')->label(__('label.seed_box_record.type')),
Tables\Columns\TextColumn::make('uid')->searchable(),
Tables\Columns\TextColumn::make('user.username')->label(__('label.username'))->searchable(),
Tables\Columns\TextColumn::make('operator')->label(__('label.seed_box_record.operator'))->searchable(),
Tables\Columns\TextColumn::make('bandwidth')->label(__('label.seed_box_record.bandwidth')),
@@ -112,6 +112,7 @@ class EditSetting extends Page implements Forms\Contracts\HasForms
Forms\Components\TextInput::make('seed_box.not_seed_box_max_speed')->label(__('label.setting.seed_box.not_seed_box_max_speed'))->helperText(__('label.setting.seed_box.not_seed_box_max_speed_help'))->integer(),
Forms\Components\Radio::make('seed_box.no_promotion')->options(self::$yesOrNo)->inline(true)->label(__('label.setting.seed_box.no_promotion'))->helperText(__('label.setting.seed_box.no_promotion_help')),
Forms\Components\TextInput::make('seed_box.max_uploaded')->label(__('label.setting.seed_box.max_uploaded'))->helperText(__('label.setting.seed_box.max_uploaded_help'))->integer(),
Forms\Components\TextInput::make('seed_box.max_uploaded_duration')->label(__('label.setting.seed_box.max_uploaded_duration'))->helperText(__('label.setting.seed_box.max_uploaded_duration_help'))->integer(),
])->columns(2);
$tabs[] = Forms\Components\Tabs\Tab::make(__('label.setting.system.tab_header'))
@@ -9,6 +9,7 @@ use App\Models\Setting;
use App\Models\Tag;
use App\Models\Torrent;
use App\Models\TorrentTag;
use App\Models\User;
use App\Repositories\TagRepository;
use App\Repositories\TorrentRepository;
use Filament\Facades\Filament;
@@ -24,6 +25,7 @@ use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\HtmlString;
use Illuminate\Support\Str;
use Illuminate\Validation\Rule;
class TorrentResource extends Resource
{
@@ -83,10 +85,16 @@ class TorrentResource extends Resource
})->label(__('label.name'))->searchable(),
Tables\Columns\TextColumn::make('posStateText')->label(__('label.torrent.pos_state')),
Tables\Columns\TextColumn::make('spStateText')->label(__('label.torrent.sp_state')),
Tables\Columns\TextColumn::make('pickInfoText')
->label(__('label.torrent.picktype'))
->formatStateUsing(fn ($record) => $record->pickInfo['text'])
,
Tables\Columns\BooleanColumn::make('hr')
->label(__('label.torrent.hr'))
,
Tables\Columns\TextColumn::make('size')->label(__('label.torrent.size'))->formatStateUsing(fn ($state) => mksize($state)),
Tables\Columns\TextColumn::make('seeders')->label(__('label.torrent.seeders')),
Tables\Columns\TextColumn::make('leechers')->label(__('label.torrent.leechers')),
// Tables\Columns\TextColumn::make('times_completed')->label(__('label.torrent.times_completed')),
Tables\Columns\BadgeColumn::make('approval_status')
->visible($showApproval)
->label(__('label.torrent.approval_status'))
@@ -113,10 +121,18 @@ class TorrentResource extends Resource
->options(Torrent::listPromotionTypes(true))
->label(__('label.torrent.sp_state')),
Tables\Filters\SelectFilter::make('picktype')
->options(Torrent::listPickInfo(true))
->label(__('label.torrent.picktype')),
Tables\Filters\SelectFilter::make('approval_status')
->options(Torrent::listApprovalStatus(true))
->visible($showApproval)
->label(__('label.torrent.approval_status')),
Tables\Filters\SelectFilter::make('hr')
->options(self::getYesNoOptions())
->label(__('label.torrent.hr')),
])
->actions(self::getActions())
->bulkActions(self::getBulkActions());
@@ -146,6 +162,7 @@ class TorrentResource extends Resource
private static function getBulkActions(): array
{
$user = Auth::user();
$actions = [];
if (user_can('torrentsticky')) {
$actions[] = Tables\Actions\BulkAction::make('posState')
@@ -174,6 +191,66 @@ class TorrentResource extends Resource
->deselectRecordsAfterCompletion();
}
if (user_can('torrentonpromotion')) {
$actions[] = Tables\Actions\BulkAction::make('sp_state')
->label(__('admin.resources.torrent.bulk_action_sp_state'))
->form([
Forms\Components\Select::make('sp_state')
->label(__('label.torrent.sp_state'))
->options(Torrent::listPromotionTypes(true))
->required()
,
Forms\Components\Select::make('promotion_time_type')
->label(__('label.torrent.promotion_time_type'))
->options(Torrent::listPromotionTimeTypes(true))
->required()
,
Forms\Components\DateTimePicker::make('promotion_until')
->label(__('label.deadline'))
,
])
->icon('heroicon-o-speakerphone')
->action(function (Collection $records, array $data) {
$idArr = $records->pluck('id')->toArray();
try {
$torrentRep = new TorrentRepository();
$torrentRep->setSpState($idArr, $data['sp_state'], $data['promotion_time_type'], $data['promotion_until']);
} catch (\Exception $exception) {
do_log($exception->getMessage() . $exception->getTraceAsString(), 'error');
Filament::notify('danger', $exception->getMessage());
}
})
->deselectRecordsAfterCompletion();
}
if (user_can('torrentmanage') && ($user->picker == 'yes' || $user->class >= User::CLASS_SYSOP)) {
$actions[] = Tables\Actions\BulkAction::make('recommend')
->label(__('admin.resources.torrent.bulk_action_recommend'))
->form([
Forms\Components\Radio::make('picktype')
->label(__('admin.resources.torrent.bulk_action_recommend'))
->inline()
->options(Torrent::listPickInfo(true))
->required(),
])
->icon('heroicon-o-fire')
->action(function (Collection $records, array $data) {
if (empty($data['picktype'])) {
return;
}
$idArr = $records->pluck('id')->toArray();
try {
$torrentRep = new TorrentRepository();
$torrentRep->setPickType($idArr, $data['picktype']);
} catch (\Exception $exception) {
do_log($exception->getMessage() . $exception->getTraceAsString(), 'error');
Filament::notify('danger', class_basename($exception));
}
})
->deselectRecordsAfterCompletion();
}
if (user_can('torrentmanage')) {
$actions[] = Tables\Actions\BulkAction::make('remove_tag')
->label(__('admin.resources.torrent.bulk_action_remove_tag'))
@@ -217,6 +294,38 @@ class TorrentResource extends Resource
}
})
->deselectRecordsAfterCompletion();
$actions[] = Tables\Actions\BulkAction::make('hr')
->label(__('admin.resources.torrent.bulk_action_hr'))
->form([
Forms\Components\Radio::make('hr')
->label(__('admin.resources.torrent.bulk_action_hr'))
->inline()
->options(self::getYesNoOptions())
->required(),
])
->icon('heroicon-o-sparkles')
->action(function (Collection $records, array $data) {
if (empty($data['hr'])) {
return;
}
$idArr = $records->pluck('id')->toArray();
try {
$torrentRep = new TorrentRepository();
$torrentRep->setHr($idArr, $data['hr']);
} catch (\Exception $exception) {
do_log($exception->getMessage() . $exception->getTraceAsString(), 'error');
Filament::notify('danger', class_basename($exception));
}
})
->deselectRecordsAfterCompletion();
}
if (user_can('torrent-delete')) {
$actions[] = Tables\Actions\DeleteBulkAction::make('bulk-delete')->using(function (Collection $records) {
deletetorrent($records->pluck('id')->toArray());
});
}
return $actions;
@@ -248,7 +357,7 @@ class TorrentResource extends Resource
});
}
if (user_can('torrentmanage')) {
if (user_can('torrent-delete')) {
$actions[] = Tables\Actions\DeleteAction::make('delete')->using(function ($record) {
deletetorrent($record->id);
});
+15
View File
@@ -51,4 +51,19 @@ class NexusModel extends Model
return sprintf('%s: %s', nexus_trans('label.deadline'), $raw);
}
public static function listStaticProps($dataSource, $textTransPrefix, $onlyKeyValue = false, $valueField = 'text'): array
{
$result = $dataSource;
$keyValue = [];
foreach ($result as $key => &$info) {
$text = $textTransPrefix ? nexus_trans("$textTransPrefix.$key") : $info['text'];
$info['text'] = $text;
$keyValue[$key] = $info[$valueField];
}
if ($onlyKeyValue) {
return $keyValue;
}
return $result;
}
}
+8
View File
@@ -48,6 +48,14 @@ class Tag extends NexusModel
],
];
public static function listSpecial(): array
{
return array_filter([
Setting::get('system.official_tag'),
Setting::get('system.zero_bonus_tag'),
]);
}
public function torrents(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
{
return $this->belongsToMany(Torrent::class, 'torrent_tags', 'tag_id', 'torrent_id');
+15
View File
@@ -130,6 +130,16 @@ class Torrent extends NexusModel
self::PICK_RECOMMENDED => ['text' => self::PICK_RECOMMENDED, 'color' => '#820084'],
];
const PROMOTION_TIME_TYPE_GLOBAL = 0;
const PROMOTION_TIME_TYPE_PERMANENT = 1;
const PROMOTION_TIME_TYPE_DEADLINE = 2;
public static array $promotionTimeTypes = [
self::PROMOTION_TIME_TYPE_GLOBAL => ['text' => 'Global'],
self::PROMOTION_TIME_TYPE_PERMANENT => ['text' => 'Permanent'],
self::PROMOTION_TIME_TYPE_DEADLINE => ['text' => 'Until'],
];
const BONUS_REWARD_VALUES = [50, 100, 200, 500, 1000];
const APPROVAL_STATUS_NONE = 0;
@@ -272,6 +282,11 @@ class Torrent extends NexusModel
return $result;
}
public static function listPromotionTimeTypes($onlyKeyValue = false, $valueField = 'text'): array
{
return self::listStaticProps(self::$promotionTimeTypes, 'torrent.promotion_time_types', $onlyKeyValue, $valueField);
}
public static function listPickInfo($onlyKeyValue = false, $valueField = 'text'): array
{
$result = self::$pickTypes;
+10 -7
View File
@@ -50,10 +50,14 @@ class TagRepository extends BaseRepository
return Tag::query()->orderBy('priority', 'desc')->orderBy('id', 'desc');
}
public function renderCheckbox(array $checked = []): string
public function renderCheckbox(array $checked = [], $ignorePermission = false): string
{
$html = '';
$results = $this->createBasicQuery()->get();
$results = $this->listAll();
if (!$ignorePermission && !user_can('torrent-set-special-tag')) {
$specialTags = Tag::listSpecial();
$results = $results->filter(fn ($item) => !in_array($item->id, $specialTags));
}
foreach ($results as $value) {
$html .= sprintf(
'<label><input type="checkbox" name="tags[]" value="%s"%s />%s</label>',
@@ -65,11 +69,8 @@ class TagRepository extends BaseRepository
public function renderSpan(array $renderIdArr = [], $withFilterLink = false): string
{
if (empty(self::$allTags)) {
self::$allTags = self::createBasicQuery()->get();
}
$html = '';
foreach (self::$allTags as $value) {
foreach ($this->listAll() as $value) {
if (in_array($value->id, $renderIdArr) || (isset($renderIdArr[0]) && $renderIdArr[0] == '*')) {
$tagId = $value->id;
if ($value) {
@@ -150,7 +151,9 @@ class TagRepository extends BaseRepository
public function listAll()
{
self::$allTags = self::createBasicQuery()->get();
if (empty(self::$allTags)) {
self::$allTags = self::createBasicQuery()->get();
}
return self::$allTags;
}
+50
View File
@@ -616,6 +616,56 @@ class TorrentRepository extends BaseRepository
return Torrent::query()->whereIn('id', $idArr)->update($update);
}
public function setPickType($id, $pickType): int
{
user_can('torrentmanage', true);
if (!isset(Torrent::$pickTypes[$pickType])) {
throw new \InvalidArgumentException("Invalid pickType: $pickType");
}
$update = [
'picktype' => $pickType,
'picktime' => now(),
];
$idArr = Arr::wrap($id);
return Torrent::query()->whereIn('id', $idArr)->update($update);
}
public function setHr($id, $hrStatus): int
{
user_can('torrentmanage', true);
if (!isset(Torrent::$hrStatus[$hrStatus])) {
throw new \InvalidArgumentException("Invalid hrStatus: $hrStatus");
}
$update = [
'hr' => $hrStatus,
];
$idArr = Arr::wrap($id);
return Torrent::query()->whereIn('id', $idArr)->update($update);
}
public function setSpState($id, $spState, $promotionTimeType, $promotionUntil = null): int
{
user_can('torrentonpromotion', true);
if (!isset(Torrent::$promotionTypes[$spState])) {
throw new \InvalidArgumentException("Invalid spState: $spState");
}
if (!isset(Torrent::$promotionTimeTypes[$promotionTimeType])) {
throw new \InvalidArgumentException("Invalid promotionTimeType: $promotionTimeType");
}
if (in_array($promotionTimeType, [Torrent::PROMOTION_TIME_TYPE_GLOBAL, Torrent::PROMOTION_TIME_TYPE_PERMANENT])) {
$promotionUntil = null;
} elseif (!$promotionUntil || Carbon::parse($promotionUntil)->lte(now())) {
throw new \InvalidArgumentException("Invalid promotionUntil: $promotionUntil");
}
$update = [
'sp_state' => $spState,
'promotion_time_type' => $promotionTimeType,
'promotion_until' => $promotionUntil,
];
$idArr = Arr::wrap($id);
return Torrent::query()->whereIn('id', $idArr)->update($update);
}
public function buildUploadFieldInput($name, $value, $noteText, $btnText): string
{
$btn = $note = '';