Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: sort collections in the "cotm" table by votes/volume #627

Merged
merged 7 commits into from
Jan 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions app/Console/Kernel.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
use App\Console\Commands\UpdateTwitterFollowers;
use App\Enums\Features;
use App\Jobs\AggregateCollectionWinners;
use App\Jobs\ResetCollectionRanking;
use Illuminate\Console\Scheduling\Schedule;
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
use Laravel\Pennant\Feature;
Expand Down Expand Up @@ -182,9 +181,6 @@ private function scheduleJobsForCollections(Schedule $schedule): void
$schedule->job(AggregateCollectionWinners::class)
->monthly();

$schedule->job(ResetCollectionRanking::class)
->monthlyOn(dayOfMonth: 1, time: '0:0');

$schedule
->command(UpdateCollectionsFiatValue::class)
->withoutOverlapping()
Expand Down
6 changes: 3 additions & 3 deletions app/Data/Collections/VotableCollectionData.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,16 +36,16 @@ public function __construct(
) {
}

public static function fromModel(Collection $collection, CurrencyCode $currency, bool $showVotes, bool $alreadyWon = false): self
public static function fromModel(Collection $collection, CurrencyCode $currency, bool $showVotes, bool $alreadyWon = false, ?int $rank = null): self
{
/** @var mixed $collection */
return new self(
id: $collection->id,
rank: $collection->monthly_rank,
rank: $rank,
name: $collection->name,
address: $collection->address,
image: $collection->extra_attributes->get('image'),
votes: $showVotes ? $collection->monthly_votes : null,
votes: $showVotes ? $collection->votes_count : null,
floorPrice: $collection->floor_price,
floorPriceFiat: (float) $collection->fiatValue($currency),
floorPriceCurrency: $collection->floor_price_symbol,
Expand Down
12 changes: 8 additions & 4 deletions app/Http/Controllers/Api/NominatableCollectionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
namespace App\Http\Controllers\Api;

use App\Data\Collections\VotableCollectionData;
use App\Enums\CurrencyCode;
use App\Enums\Period;
use App\Http\Controllers\Controller;
use App\Models\Collection;
use App\Models\CollectionWinner;
Expand All @@ -19,14 +21,16 @@ public function index(Request $request): JsonResponse
'query' => 'nullable|string',
]);

$currency = $request->user()->currency();
$currency = $request->user()?->currency() ?? CurrencyCode::USD;

$collections = Collection::query()
->with('network.nativeToken')
->searchByName($request->get('query'))
->limit(15)
->votable(orderByVotes: false)
->with('network.nativeToken')
->orderBy('name', 'asc')
->votable()
->withCount(['votes' => fn ($q) => $q->inCurrentMonth()])
->orderBy('votes_count', 'desc')
->orderByVolume(period: Period::MONTH, currency: $currency)
->get();

$winners = CollectionWinner::ineligibleCollectionIds();
Expand Down
24 changes: 17 additions & 7 deletions app/Http/Controllers/CollectionController.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
use App\Support\RateLimiterHelpers;
use Carbon\Carbon;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection as SupportCollection;
Expand All @@ -50,17 +49,19 @@ class CollectionController extends Controller
{
use HasCollectionFilters;

public function index(Request $request): Response|JsonResponse|RedirectResponse
public function index(Request $request): Response
{
$votableCollections = $this->getVotableCollections($request);

return Inertia::render('Collections/Index', [
'allowsGuests' => true,
'filters' => fn () => $this->getFilters($request),
'title' => fn () => trans('metatags.collections.title'),
'collectionsOfTheMonth' => fn () => $this->getCollectionsOfTheMonth(),
'collections' => fn () => $this->getPopularCollections($request),
'featuredCollections' => fn () => $this->getFeaturedCollections($request),
'votedCollection' => fn () => $this->getVotedCollection($request),
'votableCollections' => fn () => $this->getVotableCollections($request),
'votedCollection' => fn () => $this->getVotedCollection($request, $votableCollections),
'votableCollections' => $votableCollections,
'latestArticles' => fn () => $this->getLatestArticles(),
'popularArticles' => fn () => $this->getPopularArticles(),
]);
Expand All @@ -77,8 +78,10 @@ private function getCollectionsOfTheMonth(): CollectionWinnersData

/**
* Get only the collection that the user has voted for in the current month.
*
* @param SupportCollection<int, VotableCollectionData> $votableCollections
*/
private function getVotedCollection(Request $request): ?VotableCollectionData
private function getVotedCollection(Request $request, SupportCollection $votableCollections): ?VotableCollectionData
{
$user = $request->user();

Expand All @@ -87,6 +90,7 @@ private function getVotedCollection(Request $request): ?VotableCollectionData
}

$collection = Collection::votable()
->withCount(['votes' => fn ($q) => $q->inCurrentMonth()])
->with('network.nativeToken')
->votedByUserInCurrentMonth($user)
->first();
Expand All @@ -95,10 +99,14 @@ private function getVotedCollection(Request $request): ?VotableCollectionData
return null;
}

/** @var int|false */
$index = $votableCollections->search(fn ($c) => $c->id === $collection->id);

return VotableCollectionData::fromModel(
$collection,
$user->currency(),
showVotes: true,
rank: $index === false ? null : ($index + 1),
);
}

Expand All @@ -114,13 +122,15 @@ private function getVotableCollections(Request $request): SupportCollection
$userVoted = $user !== null ? Collection::votedByUserInCurrentMonth($user)->exists() : false;

$collections = Collection::votable()
->withCount(['votes' => fn ($q) => $q->inCurrentMonth()])
->orderBy('votes_count', 'desc')
->orderByVolume(Period::MONTH, $currency)
->with('network.nativeToken')
->limit(13) // 8 collections on the vote table + 5 collections to nominate
->get();

$winners = CollectionWinner::ineligibleCollectionIds();

return $collections->map(fn ($collection) => VotableCollectionData::fromModel(
return $collections->take(13)->map(fn ($collection) => VotableCollectionData::fromModel(
$collection,
$currency,
showVotes: $userVoted,
Expand Down
3 changes: 0 additions & 3 deletions app/Http/Controllers/CollectionVoteController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

namespace App\Http\Controllers;

use App\Jobs\ResetCollectionRanking;
use App\Models\Collection;
use App\Models\CollectionWinner;
use Illuminate\Http\RedirectResponse;
Expand All @@ -24,8 +23,6 @@ public function store(Request $request, Collection $collection): RedirectRespons

$collection->addVote($request->wallet());

ResetCollectionRanking::dispatch();

return back()->toast(trans('pages.collections.collection_of_the_month.vote_success'), type: 'success');
}
}
2 changes: 0 additions & 2 deletions app/Jobs/FetchCollectionVolume.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,6 @@ public function handle(): void
'volume_7d' => $this->collection->totalVolumeSince(now()->subDays(7)),
'volume_30d' => $this->collection->totalVolumeSince(now()->subDays(30)),
]);

ResetCollectionRanking::dispatch();
}

public function uniqueId(): string
Expand Down
2 changes: 0 additions & 2 deletions app/Jobs/FetchCollectionVolumeHistory.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ public function handle(): void
'volume_7d' => $this->collection->totalVolumeSince(now()->subDays(7)),
'volume_30d' => $this->collection->totalVolumeSince(now()->subDays(30)),
]);

ResetCollectionRanking::dispatch();
}

public function uniqueId(): string
Expand Down
31 changes: 0 additions & 31 deletions app/Jobs/ResetCollectionRanking.php

This file was deleted.

24 changes: 11 additions & 13 deletions app/Models/Collection.php
Original file line number Diff line number Diff line change
Expand Up @@ -607,19 +607,17 @@ public function scopeFeatured(Builder $query): Builder
* @param Builder<self> $query
* @return Builder<self>
*/
public function scopeVotable(Builder $query, bool $orderByVotes = true): Builder
{
return $query
->addFloorPriceChange()
->addSelect([
'collections.*',
DB::raw('MIN(floor_price_token.symbol) as floor_price_symbol'),
DB::raw('MIN(floor_price_token.decimals) as floor_price_decimals'),
])
->leftJoin('tokens as floor_price_token', 'collections.floor_price_token_id', '=', 'floor_price_token.id')
->withCount('nfts')
->groupBy('collections.id')
->when($orderByVotes, fn ($q) => $q->orderBy('monthly_votes', 'desc')->orderByRaw('volume DESC NULLS LAST'));
public function scopeVotable(Builder $query): Builder
{
return $query->addFloorPriceChange()
->addSelect([
'collections.*',
DB::raw('MIN(floor_price_token.symbol) as floor_price_symbol'),
DB::raw('MIN(floor_price_token.decimals) as floor_price_decimals'),
])
->leftJoin('tokens as floor_price_token', 'collections.floor_price_token_id', '=', 'floor_price_token.id')
->withCount('nfts')
->groupBy('collections.id');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Traits/HasVolume.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ public function scopeOrderByVolume(Builder $query, ?Period $period = null, ?Curr
->addSelect('collections.*')
->leftJoin(
'tokens as native_token',
fn ($join) => $join->on('native_token.network_id', '=', 'collections.network_id')->where('is_native_token', true)
fn ($join) => $join->on('native_token.network_id', '=', 'collections.network_id')->where('native_token.is_native_token', true)
)
->addSelect($subselect)
->groupBy('collections.id')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

declare(strict_types=1);

use App\Jobs\ResetCollectionRanking;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
Expand All @@ -15,7 +14,5 @@ public function up(): void
$table->unsignedInteger('monthly_rank')->nullable();
$table->unsignedInteger('monthly_votes')->nullable();
});

ResetCollectionRanking::dispatchSync();
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

declare(strict_types=1);

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('collections', function (Blueprint $table) {
$table->dropColumn([
'monthly_rank',
'monthly_votes',
]);
});
}
};
22 changes: 0 additions & 22 deletions queries/collections.calculate_monthly_rank_and_votes_value.sql

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ export const NominationDialog = ({
collections: App.Data.Collections.VotableCollectionData[];
}>(route("nominatable-collections", { query: debouncedQuery }));

setCollections(data.collections);
setCollections(data.collections.reverse());
setSearching(false);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,10 +88,10 @@ export const VoteCollections = ({

const nominatableCollections = useMemo(() => {
if (isSmAndAbove) {
return collections.slice(8, 13);
return collections.slice(8, 13).reverse();
}

return collections.slice(4, 9);
return collections.slice(4, 9).reverse();
}, [isSmAndAbove, collections]);

const [isDialogOpen, setIsDialogOpen] = useState<boolean>(false);
Expand Down Expand Up @@ -129,7 +129,7 @@ export const VoteCollections = ({
{collectionsWithVote.slice(4, 8).map((collection, index) => (
<VoteCollection
key={index}
index={index + 4}
index={index + 5}
collection={collection}
setSelectedCollectionId={setSelectedCollectionId}
votedId={votedCollection?.id}
Expand Down
6 changes: 3 additions & 3 deletions routes/api.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
Route::get('/galleries-overview', [Api\GalleryOverviewController::class, 'index'])
->name('galleries-overview.index');

Route::get('/nominatable-collections', [Api\NominatableCollectionController::class, 'index'])
->name('nominatable-collections');

Route::middleware('auth:sanctum')->group(function () {
// Tokens...
Route::get('/tokens', [Controllers\TokenController::class, 'list'])->name('tokens.list');
Expand Down Expand Up @@ -48,9 +51,6 @@

Route::get('/user/nfts', Api\UserNftController::class)->name('user.nfts');

Route::get('/nominatable-collections', [Api\NominatableCollectionController::class, 'index'])
->name('nominatable-collections');

Route::post('/collections/{collection:slug}/{nft:token_number}/refresh', Controllers\RefreshedNftController::class)
->name('nft.refresh')
->middleware('throttle:nft:refresh');
Expand Down
Loading
Loading