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

feat(hub): add support for content warnings #2952

Merged
Merged
Show file tree
Hide file tree
Changes from 41 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
23f0ee1
feat(hub): build dedicated pages for hubs
wescopeland Dec 8, 2024
c0a455f
chore: fix test in ci
wescopeland Dec 8, 2024
92c5272
chore: force skip the controller test in ci
wescopeland Dec 8, 2024
f85c0a1
refactor: make code more eloquent-like
wescopeland Dec 8, 2024
5c3dcdc
fix: update cache time
wescopeland Dec 8, 2024
c6c9161
docs: fixes
wescopeland Dec 8, 2024
5fcdca5
Merge branch 'master' into hubs-rework
wescopeland Dec 8, 2024
60522e7
fix: disable client-side navigation
wescopeland Dec 9, 2024
7eb9a88
Merge branch 'master' into hubs-rework
wescopeland Dec 11, 2024
e19b841
chore: tsc
wescopeland Dec 11, 2024
29cb714
chore: vitest
wescopeland Dec 11, 2024
3f062b6
fix: address pr feedback
wescopeland Dec 11, 2024
f88d3aa
chore: vitest
wescopeland Dec 11, 2024
f2e16b5
fix: address pr feedback
wescopeland Dec 12, 2024
58248af
Merge branch 'master' into hubs-rework
wescopeland Dec 12, 2024
7a6abd6
fix: more resilient breadcrumbs
wescopeland Dec 14, 2024
243d9fc
chore: phpstan
wescopeland Dec 14, 2024
68ab971
Merge branch 'master' into hubs-rework
wescopeland Dec 14, 2024
c5b50d0
fix: improve badge image double write logic
wescopeland Dec 14, 2024
610e0eb
Merge branch 'hubs-rework' of https://github.com/wescopeland/RAWeb in…
wescopeland Dec 14, 2024
f4bc52e
fix: 404 if game set is not actually a hub
wescopeland Dec 14, 2024
03d8dee
feat(manage): add hub management capabilities
wescopeland Dec 15, 2024
1b7ee78
fix: qol improvements
wescopeland Dec 15, 2024
afef141
fix: paste -> use
wescopeland Dec 15, 2024
c60fba7
fix(SyncGameSets): reset the auto-increment id counter on execute
wescopeland Dec 16, 2024
81573b8
Merge branch 'hubs-rework' into hubs-management
wescopeland Dec 16, 2024
bd74090
refactor(HubController): use abort_if
wescopeland Dec 16, 2024
c54cd7c
Merge branch 'hubs-rework' into hubs-management
wescopeland Dec 16, 2024
60ab539
fix: address pr feedback
wescopeland Dec 16, 2024
4a56d5b
refactor: minimize scope function
wescopeland Dec 16, 2024
5a59e48
Merge branch 'hubs-rework' into hubs-management
wescopeland Dec 16, 2024
b72f99a
chore: phpstan
wescopeland Dec 16, 2024
9d2000f
fix: use constants
wescopeland Dec 17, 2024
997bd34
Merge branch 'master' into hubs-rework
wescopeland Dec 17, 2024
6278a0b
test(HubControllerTest): try to re-enable in CI
wescopeland Dec 17, 2024
750c979
test(HubControllerTest): keep skipping in ci
wescopeland Dec 17, 2024
3ece174
Merge branch 'hubs-rework' into hubs-management
wescopeland Dec 17, 2024
5042333
Merge branch 'master' into hubs-management
wescopeland Dec 17, 2024
033b04a
feat(hub): add support for content warnings
wescopeland Dec 19, 2024
124edd5
Merge branch 'master' into hubs-content-warnings
wescopeland Dec 20, 2024
da3d3a5
Merge branch 'master' into hubs-content-warnings
wescopeland Dec 21, 2024
afec5ad
fix: address pr feedback
wescopeland Dec 27, 2024
5fdae6d
fix: update a test, rename some stuff
wescopeland Dec 27, 2024
c0b755a
fix: typo
wescopeland Dec 27, 2024
b61572e
Merge branch 'master' into hubs-content-warnings
wescopeland Dec 30, 2024
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
17 changes: 17 additions & 0 deletions app/Community/Controllers/UserSettingsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@
use App\Data\UserData;
use App\Data\UserPermissionsData;
use App\Enums\Permissions;
use App\Enums\UserPreference;
use App\Http\Controller;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Inertia\Inertia;
use Inertia\Response as InertiaResponse;
Expand Down Expand Up @@ -124,6 +126,21 @@ public function updateLocale(UpdateLocaleRequest $request): JsonResponse
return response()->json(['success' => true]);
}

// TODO migrate to $user->preferences blob
public function enableSuppressMatureContentWarning(Request $request): JsonResponse
{
/** @var User $user */
$user = $request->user();

$currentPreferences = (int) $user->getAttribute('websitePrefs');
$newPreferences = $currentPreferences | (1 << UserPreference::Site_SuppressMatureContentWarning);

$user->websitePrefs = $newPreferences;
$user->save();

return response()->json(['success' => true]);
}

// TODO migrate to $user->preferences blob
public function updatePreferences(UpdateWebsitePrefsRequest $request): JsonResponse
{
Expand Down
3 changes: 3 additions & 0 deletions app/Community/RouteServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,9 @@ protected function mapWebRoutes(): void
'middleware' => ['auth'],
'prefix' => 'internal-api/settings',
], function () {
Route::patch('/preferences/content-warning', [UserSettingsController::class, 'enableSuppressMatureContentWarning'])
->name('api.settings.preferences.suppress-mature-content-warning');

Route::put('profile', [UserSettingsController::class, 'updateProfile'])->name('api.settings.profile.update');
Route::put('locale', [UserSettingsController::class, 'updateLocale'])->name('api.settings.locale.update');
Route::put('preferences', [UserSettingsController::class, 'updatePreferences'])->name('api.settings.preferences.update');
Expand Down
6 changes: 5 additions & 1 deletion app/Data/UserData.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,10 @@ public function __construct(
public Lazy|string|null $visibleRole = null,
public Lazy|int|null $websitePrefs = null,

#[TypeScriptType(['prefersAbsoluteDates' => 'boolean'])]
#[TypeScriptType([
'shouldAlwaysBypassContentWarnings' => 'boolean',
'prefersAbsoluteDates' => 'boolean',
])]
public Lazy|array|null $preferences = [],
#[LiteralTypeScriptType('App.Models.UserRole[]')]
public Lazy|array|null $roles = [],
Expand Down Expand Up @@ -82,6 +85,7 @@ public static function fromUser(User $user): self
motto: Lazy::create(fn () => $user->Motto),
preferences: Lazy::create(
fn () => [
'shouldAlwaysBypassContentWarnings' => $user->should_always_bypass_content_warnings,
'prefersAbsoluteDates' => $user->prefers_absolute_dates,
]
),
Expand Down
16 changes: 16 additions & 0 deletions app/Filament/Resources/HubResource.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
use App\Filament\Resources\HubResource\RelationManagers\GamesRelationManager;
use App\Filament\Resources\HubResource\RelationManagers\ParentHubsRelationManager;
use App\Models\GameSet;
use App\Models\User;
use App\Platform\Enums\GameSetType;
use App\Support\Rules\NoEmoji;
use Filament\Forms;
Expand All @@ -20,6 +21,7 @@
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Facades\Auth;

class HubResource extends Resource
{
Expand Down Expand Up @@ -57,6 +59,11 @@ public static function infolist(Infolist $infolist): Infolist
Infolists\Components\TextEntry::make('title')
->label('Title'),

Infolists\Components\TextEntry::make('has_content_warning')
->label('Has Content Warning')
->formatStateUsing(fn (bool $state): string => $state ? 'Yes' : 'No')
->color(fn (bool $state): string => $state ? 'danger' : ''),

BreadcrumbPreview::make('breadcrumbs')
->label('Breadcrumb Preview')
->columnSpanFull(),
Expand All @@ -74,6 +81,9 @@ public static function infolist(Infolist $infolist): Infolist

public static function form(Form $form): Form
{
/** @var User $user */
$user = Auth::user();

return $form
->schema([
Forms\Components\Section::make('Primary Details')
Expand All @@ -85,6 +95,12 @@ public static function form(Form $form): Form
->minLength(2)
->maxLength(80)
->rules([new NoEmoji()]),

Forms\Components\Toggle::make('has_content_warning')
->label('Has Content Warning')
->helperText('CAUTION: If this is enabled, players will get a warning when opening any game in the hub!')
->default(false)
->visible(fn ($record) => $user->can('toggleHasContentWarning', $record)),
Jamiras marked this conversation as resolved.
Show resolved Hide resolved
]),

Forms\Components\Section::make('Internal Notes')
Expand Down
5 changes: 5 additions & 0 deletions app/Models/Game.php
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,11 @@ public function getCanonicalUrlAttribute(): string
return route('game.show', [$this, $this->getSlugAttribute()]);
}

public function getHasContentWarningAttribute(): bool
{
return $this->gameSets()->where('has_content_warning', true)->exists();
}

public function getLastUpdatedAttribute(): Carbon
{
return $this->last_achievement_update ?? $this->Updated;
Expand Down
7 changes: 5 additions & 2 deletions app/Models/GameSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ class GameSet extends BaseModel
'game_id',
'internal_notes',
'image_asset_path',
'has_content_warning',
'title',
'type',
'updated_at',
'user_id',
];

protected $casts = [
'has_content_warning' => 'boolean',
'type' => GameSetType::class,
];

Expand Down Expand Up @@ -148,9 +150,10 @@ public function getActivitylogOptions(): LogOptions
{
return LogOptions::defaults()
->logOnly([
'title',
'internal_notes',
'has_content_warning',
'image_asset_path',
'internal_notes',
'title',
])
->logOnlyDirty()
->dontSubmitEmptyLogs();
Expand Down
5 changes: 5 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -428,6 +428,11 @@ public function getPermissionsAttribute(): int
return $this->attributes['Permissions'];
}

public function getShouldAlwaysBypassContentWarningsAttribute(): bool
{
return BitSet($this->getAttribute('websitePrefs'), UserPreference::Site_SuppressMatureContentWarning);
}

public function getPrefersAbsoluteDatesAttribute(): bool
{
return BitSet($this->getAttribute('websitePrefs'), UserPreference::Forum_ShowAbsoluteDates);
Expand Down
1 change: 1 addition & 0 deletions app/Platform/Actions/BuildGameSetRelatedHubsAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public function execute(GameSet $gameSet): array
'title',
'image_asset_path',
'type',
'has_content_warning',
'updated_at',
])
->withCount([
Expand Down
4 changes: 3 additions & 1 deletion app/Platform/Actions/BuildHubBreadcrumbsAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Models\GameSet;
use App\Platform\Data\GameSetData;
use App\Platform\Enums\GameSetType;
use Carbon\Carbon;
use Illuminate\Support\Facades\Cache;

/**
Expand Down Expand Up @@ -163,7 +164,8 @@ public function execute(GameSet $gameSet): array
badgeUrl: media_asset($data['image_asset_path']),
gameCount: 0,
linkCount: 0,
updatedAt: new \Carbon\Carbon($data['updated_at']),
updatedAt: new Carbon($data['updated_at']),
hasContentWarning: false, // doesn't matter, this is just a breadcrumb
),
$cachedData ?? [],
);
Expand Down
2 changes: 1 addition & 1 deletion app/Platform/Controllers/HubController.php
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ public function show(GameListRequest $request, ?GameSet $gameSet): InertiaRespon
$can = UserPermissionsData::fromUser($user)->include('develop', 'manageGameSets');

$props = new HubPagePropsData(
hub: GameSetData::from($gameSet)->include('title', 'badgeUrl', 'updatedAt'),
hub: GameSetData::from($gameSet)->include('title', 'badgeUrl', 'updatedAt', 'hasContentWarning'),
relatedHubs: (new BuildGameSetRelatedHubsAction())->execute($gameSet),
breadcrumbs: (new BuildHubBreadcrumbsAction())->execute($gameSet),
paginatedGameListEntries: $paginatedData,
Expand Down
3 changes: 3 additions & 0 deletions app/Platform/Data/GameSetData.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use App\Platform\Enums\GameSetType;
use Carbon\Carbon;
use Spatie\LaravelData\Data;
use Spatie\LaravelData\Lazy;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript('GameSet')]
Expand All @@ -21,6 +22,7 @@ public function __construct(
public int $gameCount,
public int $linkCount,
public Carbon $updatedAt,
public Lazy|bool $hasContentWarning,
) {
}

Expand All @@ -37,6 +39,7 @@ public static function fromGameSetWithCounts(GameSet $gameSet): self
gameCount: $gameSet->games_count ?? 0,
linkCount: $gameSet->link_count ?? 0,
updatedAt: $gameSet->updated_at,
hasContentWarning: Lazy::create(fn () => $gameSet->has_content_warning),
);
}
}
8 changes: 8 additions & 0 deletions app/Policies/GameSetPolicy.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,4 +67,12 @@ public function forceDelete(User $user, GameSet $gameSet): bool
{
return false;
}

public function toggleHasContentWarning(User $user, GameSet $gameSet): bool
{
return $user->hasAnyRole([
Role::ADMINISTRATOR,
Role::DEVELOPER_STAFF,
]);
}
}
23 changes: 23 additions & 0 deletions database/migrations/2024_12_18_000000_update_game_sets_tables.php
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 {
public function up(): void
{
Schema::table('game_sets', function (Blueprint $table) {
$table->boolean('has_content_warning')->default(false)->after('definition');
});
}

public function down(): void
{
Schema::table('game_sets', function (Blueprint $table) {
$table->dropColumn('has_content_warning');
});
}
};
5 changes: 4 additions & 1 deletion lang/en_US.json
Original file line number Diff line number Diff line change
Expand Up @@ -502,7 +502,6 @@
"Go to previous news page": "Go to previous news page",
"Go to next news page": "Go to next news page",
"Swipe to view more": "Swipe to view more",
"All {{systemName}} Games": "All {{systemName}} Games",
"rowGroupAriaLabel_one": "{{systemName}} group with {{val, number}} game",
"rowGroupAriaLabel_other": "{{systemName}} group with {{val, number}} games",
"Games are now grouped by system": "Games are now grouped by system",
Expand All @@ -512,5 +511,9 @@
"Getting Started": "Getting Started",
"Moderation Comments - {{user}}": "Moderation Comments - {{user}}",
"Moderation Comments": "Moderation Comments",
"Content Warning": "Content Warning",
"This page may contain content that is not appropriate for all ages.": "This page may contain content that is not appropriate for all ages.",
"Are you sure you want to view this page?": "Are you sure you want to view this page?",
"Yes, and don't ask again": "Yes, and don't ask again",
"Columns": "Columns"
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"@floating-ui/dom": "^1.5.1",
"@hookform/resolvers": "^3.9.0",
"@inertiajs/core": "^1.2.0",
"@radix-ui/react-alert-dialog": "^1.1.4",
"@radix-ui/react-checkbox": "^1.1.1",
"@radix-ui/react-dialog": "^1.1.2",
"@radix-ui/react-dropdown-menu": "^2.1.1",
Expand Down
Loading