diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index f2daf4c42..608b9865d 100755 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -1239,6 +1239,29 @@ class UserController extends Controller ]); } + /** + * Get A Users Uploads Table. + */ + public function uploads(Request $request, string $username): \Illuminate\Contracts\View\Factory|\Illuminate\View\View + { + $user = User::where('username', '=', $username)->firstOrFail(); + + \abort_unless($request->user()->group->is_modo || $request->user()->id == $user->id, 403); + $hisUpl = History::where('user_id', '=', $user->id)->sum('actual_uploaded'); + $hisUplCre = History::where('user_id', '=', $user->id)->sum('uploaded'); + $hisDownl = History::where('user_id', '=', $user->id)->sum('actual_downloaded'); + $hisDownlCre = History::where('user_id', '=', $user->id)->sum('downloaded'); + + return \view('user.private.uploads', [ + 'route' => 'uploads', + 'user' => $user, + 'his_upl' => $hisUpl, + 'his_upl_cre' => $hisUplCre, + 'his_downl' => $hisDownl, + 'his_downl_cre' => $hisDownlCre, + ]); + } + /** * Get A Users Graveyard Resurrections. */ diff --git a/app/Http/Livewire/UserTorrents.php b/app/Http/Livewire/UserTorrents.php index 035e1d381..e60845de7 100644 --- a/app/Http/Livewire/UserTorrents.php +++ b/app/Http/Livewire/UserTorrents.php @@ -44,16 +44,12 @@ class UserTorrents extends Component public string $downloaded = 'any'; - public string $hasHistory = 'any'; - public array $status = []; public string $sortField = 'created_at'; public string $sortDirection = 'desc'; - public $unapprovedOnTop = true; - public $showMorePrecision = false; protected $queryString = [ @@ -69,9 +65,7 @@ class UserTorrents extends Component 'immune' => ['except' => 'any'], 'uploaded' => ['except' => 'any'], 'downloaded' => ['except' => 'any'], - 'hasHistory' => ['except' => 'any'], 'status' => ['except' => []], - 'unapprovedOnTop' => ['except' => true], 'showMorePrecision' => ['except' => false], ]; @@ -97,8 +91,14 @@ class UserTorrents extends Component final public function getHistoryProperty(): \Illuminate\Contracts\Pagination\LengthAwarePaginator { - return History::rightJoin('torrents', 'history.torrent_id', '=', 'torrents.id') + return History::query() + ->join('torrents', fn ($join) => $join + ->on('history.torrent_id', '=', 'torrents.id') + ->where('history.created_at', '>=', $this->user->created_at) // Unneeded, but increases performance + ->where('history.user_id', '=', $this->user->id) + ) ->select( + 'history.torrent_id', 'history.agent', 'history.uploaded', 'history.downloaded', @@ -112,7 +112,6 @@ class UserTorrents extends Component 'history.immune', 'history.hitrun', 'history.prewarn', - 'torrents.id', 'torrents.name', 'torrents.seeders', 'torrents.leechers', @@ -121,24 +120,12 @@ class UserTorrents extends Component 'torrents.user_id', 'torrents.status', ) - ->when( - $this->uploaded === 'include', - fn ($query) => $query->selectRaw('COALESCE(history.created_at, NOW()) as created_at'), - fn ($query) => $query->selectRaw('COALESCE(history.created_at, torrents.created_at) as created_at') - ) ->selectRaw('IF(torrents.user_id = ?, 1, 0) AS uploader', [$this->user->id]) ->selectRaw('history.active AND history.seeder AS seeding') ->selectRaw('history.active AND NOT history.seeder AS leeching') ->selectRaw('TIMESTAMPDIFF(SECOND, history.created_at, history.completed_at) AS leechtime') ->selectRaw('CAST(history.uploaded AS float) / CAST((history.downloaded + 1) AS float) AS ratio') ->selectRaw('CAST(history.actual_uploaded AS float) / CAST((history.actual_downloaded + 1) AS float) AS actual_ratio') - ->where(fn ($query) => $query - ->where('history.user_id', '=', $this->user->id) - ->orWhere(fn ($query) => $query - ->where('torrents.user_id', '=', $this->user->id) - ->whereNull('history.user_id') - ) - ) ->when($this->name, fn ($query) => $query ->where('name', 'like', '%'.str_replace(' ', '%', $this->name).'%') ) @@ -166,14 +153,11 @@ class UserTorrents extends Component ->when($this->hitrun === 'exclude', fn ($query) => $query->where(fn ($query) => $query->where('hitrun', '=', 0)->orWhereNull('hitrun'))) ->when($this->immune === 'include', fn ($query) => $query->where('immune', '=', 1)) ->when($this->immune === 'exclude', fn ($query) => $query->where(fn ($query) => $query->where('immune', '=', 0)->orWhereNull('immune'))) - ->when($this->hasHistory === 'include', fn ($query) => $query->whereNotNull('history.updated_at')) - ->when($this->hasHistory === 'exclude', fn ($query) => $query->whereNull('history.updated_at')) ->when($this->uploaded === 'include', fn ($query) => $query->where('torrents.user_id', '=', $this->user->id)) ->when($this->uploaded === 'exclude', fn ($query) => $query->where('torrents.user_id', '<>', $this->user->id)) ->when($this->downloaded === 'include', fn ($query) => $query->where('history.actual_downloaded', '>', 0)) ->when($this->downloaded === 'exclude', fn ($query) => $query->where('history.actual_downloaded', '=', 0)) ->when(! empty($this->status), fn ($query) => $query->whereIntegerInRaw('status', $this->status)) - ->when($this->unapprovedOnTop, fn ($query) => $query->orderByRaw('IF(status = 1, 1, 0)')) ->orderBy($this->sortField, $this->sortDirection) ->paginate($this->perPage); } diff --git a/app/Http/Livewire/UserUploads.php b/app/Http/Livewire/UserUploads.php new file mode 100644 index 000000000..5e932a510 --- /dev/null +++ b/app/Http/Livewire/UserUploads.php @@ -0,0 +1,104 @@ + + * @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0 + */ + +namespace App\Http\Livewire; + +use App\Models\Torrent; +use App\Models\User; +use Livewire\Component; +use Livewire\WithPagination; + +class UserUploads extends Component +{ + use WithPagination; + + public ?\Illuminate\Contracts\Auth\Authenticatable $user = null; + + public int $perPage = 25; + + public string $name = ''; + + public string $personalRelease = 'any'; + + public array $status = []; + + public string $sortField = 'created_at'; + + public string $sortDirection = 'desc'; + + public $showMorePrecision = false; + + protected $queryString = [ + 'perPage' => ['except' => ''], + 'name' => ['except' => ''], + 'personalRelease' => ['except' => 'any'], + 'sortField' => ['except' => 'created_at'], + 'sortDirection' => ['except' => 'desc'], + 'status' => ['except' => []], + ]; + + final public function mount($userId): void + { + $this->user = User::find($userId); + } + + final public function paginationView(): string + { + return 'vendor.pagination.livewire-pagination'; + } + + final public function updatedPage(): void + { + $this->emit('paginationChanged'); + } + + final public function updatingSearch(): void + { + $this->resetPage(); + } + + final public function getUploadsProperty(): \Illuminate\Contracts\Pagination\LengthAwarePaginator + { + return Torrent::query() + ->withCount('thanks') + ->withSum('tips', 'cost') + ->where('created_at', '>=', $this->user->created_at) // Unneeded, but increases performances + ->where('user_id', '=', $this->user->id) + ->when($this->name, fn ($query) => $query + ->where('name', 'like', '%'.str_replace(' ', '%', $this->name).'%') + ) + ->when(! empty($this->status), fn ($query) => $query->whereIntegerInRaw('status', $this->status)) + ->when($this->personalRelease === 'include', fn ($query) => $query->where('personal_release', '=', 1)) + ->when($this->personalRelease === 'exclude', fn ($query) => $query->where('personal_release', '=', 0)) + ->orderBy($this->sortField, $this->sortDirection) + ->paginate($this->perPage); + } + + final public function render(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application + { + return \view('livewire.user-uploads', [ + 'uploads' => $this->uploads, + ]); + } + + final public function sortBy($field): void + { + if ($this->sortField === $field) { + $this->sortDirection = $this->sortDirection === 'asc' ? 'desc' : 'asc'; + } else { + $this->sortDirection = 'asc'; + } + + $this->sortField = $field; + } +} diff --git a/resources/sass/app.scss b/resources/sass/app.scss index 6e308f582..5379c3833 100755 --- a/resources/sass/app.scss +++ b/resources/sass/app.scss @@ -19,6 +19,7 @@ @import 'components/quick_search'; @import 'components/user-active'; @import 'components/user-torrents'; +@import 'components/user-uploads'; @import 'layout/header'; @import 'layout/secondary-nav'; @import 'layout/top_nav'; diff --git a/resources/sass/components/_user-uploads.scss b/resources/sass/components/_user-uploads.scss new file mode 100644 index 000000000..5e1c276c8 --- /dev/null +++ b/resources/sass/components/_user-uploads.scss @@ -0,0 +1,61 @@ +.user-uploads__name-header, +.user-uploads__size-header, +.user-uploads__seeders-header, +.user-uploads__leechers-header, +.user-uploads__times-header, +.user-uploads__tips-header, +.user-uploads__thanks-header, +.user-uploads__created-at-header, +.user-uploads__personal-release-header, +.user-uploads__status-header { + cursor: pointer; + white-space: nowrap; + font-size: 11px; +} + +.user-uploads__name, +.user-uploads__size, +.user-uploads__seeders, +.user-uploads__leechers, +.user-uploads__times, +.user-uploads__tips, +.user-uploads__thanks, +.user-uploads__created-at { + font-size: 14px; +} + +.user-uploads__personal-release, +.user-uploads__status { + font-size: 11px; +} + +.user-uploads__size-header, +.user-uploads__seeders-header, +.user-uploads__leechers-header, +.user-uploads__times-header, +.user-uploads__size, +.user-uploads__seeders, +.user-uploads__leechers, +.user-uploads__times { + text-align: right; +} + +.user-uploads__personal-release-header, +.user-uploads__status-header, +.user-uploads__persona-release, +.user-uploads__status { + text-align: center; +} + +.user-uploads__name { + font-weight: bolder; + color: var(--text-color); +} + +.user-uploads__checkbox { + all: revert !important; +} + +.user-uploads__checkbox:indeterminate { + all: revert !important; +} diff --git a/resources/views/livewire/user-torrents.blade.php b/resources/views/livewire/user-torrents.blade.php index 33f5b4798..16fcc1f47 100644 --- a/resources/views/livewire/user-torrents.blade.php +++ b/resources/views/livewire/user-torrents.blade.php @@ -108,18 +108,6 @@ {{ __('torrent.downloaded') }} - - -
| + {{ __('torrent.name') }} + @include('livewire.includes._sort-icon', ['field' => 'name']) + | ++ {{ __('torrent.size') }} + @include('livewire.includes._sort-icon', ['field' => 'size']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'seeders']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'leechers']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'times_completed']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'tips_sum_cost']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'thanks_count']) + | ++ {{ __('torrent.uploaded') }} + @include('livewire.includes._sort-icon', ['field' => 'created_at']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'status']) + | ++ + @include('livewire.includes._sort-icon', ['field' => 'status']) + | + + + @foreach ($uploads as $torrent) +
|---|---|---|---|---|---|---|---|---|---|
| + @if ($torrent->internal) + + @endif + + {{ $torrent->name }} + + | ++ {{ App\Helpers\StringHelper::formatBytes($torrent->size) }} + | ++ + + {{ $torrent->seeders }} + + + | ++ + + {{ $torrent->leechers }} + + + | ++ + + {{ $torrent->times_completed }} + + + | ++ {{ $torrent->tips_sum_cost ?? 0 }} + | ++ {{ $torrent->thanks_count ?? 0 }} + | ++ + | ++ @if ($torrent->personal_release === 1) + + @else + + @endif + | ++ @switch($torrent->status) + @case(0) + + @break + @case(1) + + @break + @case(2) + + @break + @case(3) + + @break + @endswitch + | +