Skip to content

Commit

Permalink
Show team flag on user display
Browse files Browse the repository at this point in the history
  • Loading branch information
nanaya committed Dec 6, 2024
1 parent 85ec033 commit 86a89e8
Show file tree
Hide file tree
Showing 31 changed files with 280 additions and 59 deletions.
4 changes: 2 additions & 2 deletions app/Http/Controllers/BeatmapsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
class BeatmapsController extends Controller
{
const DEFAULT_API_INCLUDES = ['beatmapset.ratings', 'failtimes', 'max_combo'];
const DEFAULT_SCORE_INCLUDES = ['user', 'user.country', 'user.cover'];
const DEFAULT_SCORE_INCLUDES = ['user', 'user.country', 'user.cover', 'user.team'];

public function __construct()
{
Expand Down Expand Up @@ -74,7 +74,7 @@ private static function beatmapScores(string $id, ?string $scoreTransformerType,
'type' => $type,
'user' => $currentUser,
]);
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.country', 'processHistory']);
$scores = $esFetch->all()->loadMissing(['beatmap', 'user.team', 'processHistory']);
$userScore = $esFetch->userBest();
$scoreTransformer = new ScoreTransformer($scoreTransformerType);

Expand Down
1 change: 1 addition & 0 deletions app/Http/Controllers/Forum/TopicsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,7 @@ public function show($id)
'user.country',
'user.rank',
'user.supporterTagPurchases',
'user.team',
'user.userGroups',
]);

Expand Down
3 changes: 2 additions & 1 deletion app/Http/Controllers/RankingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ public function index($mode, $type)
$table = (new $class())->getTable();
$ppColumn = $class::ppColumn();
$stats = $class
::with(['user', 'user.country'])
::with(['user', 'user.team'])
->where($ppColumn, '>', 0)
->whereHas('user', function ($userQuery) {
$userQuery->default();
Expand Down Expand Up @@ -307,6 +307,7 @@ public function kudosu()
$page = min(get_int(request('page')) ?? 1, $maxPage);

$scores = User::default()
->with('team')
->orderBy('osu_kudostotal', 'desc')
->paginate(static::PAGE_SIZE, ['*'], 'page', $page, $maxResults);

Expand Down
1 change: 1 addition & 0 deletions app/Http/Controllers/UsersController.php
Original file line number Diff line number Diff line change
Expand Up @@ -931,6 +931,7 @@ private function showUserIncludes()
'statistics.country_rank',
'statistics.rank',
'statistics.variants',
'team',
'user_achievements',
];

Expand Down
1 change: 1 addition & 0 deletions app/Models/DeletedUser.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

class DeletedUser extends User
{
public null $team = null;
public $user_avatar = null;
public $username = '[deleted user]';

Expand Down
2 changes: 1 addition & 1 deletion app/Models/Multiplayer/Room.php
Original file line number Diff line number Diff line change
Expand Up @@ -676,7 +676,7 @@ public function startPlay(User $user, PlaylistItem $playlistItem, int $buildId)

public function topScores()
{
return $this->userHighScores()->forRanking()->with('user.country');
return $this->userHighScores()->forRanking()->with(['user.country', 'user.team']);
}

private function assertHostRoomAllowance()
Expand Down
2 changes: 1 addition & 1 deletion app/Models/Spotlight.php
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public function ranking(string $mode)
// These models will not have the correct table name set on them
// as they get overriden when Laravel hydrates them.
return $this->userStats($mode)
->with(['user', 'user.country'])
->with(['user', 'user.country', 'user.team'])
->whereHas('user', function ($userQuery) {
$model = new User();
$userQuery
Expand Down
14 changes: 14 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Database\Eloquent\Relations\HasOneThrough;
use Illuminate\Database\QueryException;
use Laravel\Passport\HasApiTokens;
use League\OAuth2\Server\Exception\OAuthServerException;
Expand Down Expand Up @@ -297,6 +298,18 @@ public function userCountryHistory(): HasMany
return $this->hasMany(UserCountryHistory::class);
}

public function team(): HasOneThrough
{
return $this->hasOneThrough(
Team::class,
TeamMember::class,
'user_id',
'id',
'user_id',
'team_id',
);
}

public function teamMembership(): HasOne
{
return $this->hasOne(TeamMember::class, 'user_id');
Expand Down Expand Up @@ -958,6 +971,7 @@ public function getAttribute($key)
'storeAddresses',
'supporterTagPurchases',
'supporterTags',
'team',
'teamMembership',
'tokens',
'topicWatches',
Expand Down
1 change: 1 addition & 0 deletions app/Transformers/CurrentUserTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public function __construct()
'friends',
'groups',
'is_admin',
'team',
'unread_pm_count',
'user_preferences',
];
Expand Down
23 changes: 23 additions & 0 deletions app/Transformers/TeamTransformer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

declare(strict_types=1);

namespace App\Transformers;

use App\Models\Team;

class TeamTransformer extends TransformerAbstract
{
public function transform(Team $team): array
{
return [
'id' => $team->getKey(),
'logo' => $team->logo()->url(),
'name' => $team->name,
'short_name' => $team->short_name,
];
}
}
12 changes: 12 additions & 0 deletions app/Transformers/UserCompactTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,12 @@ class UserCompactTransformer extends TransformerAbstract
'country',
'cover',
'groups',
'team',
];

const CARD_INCLUDES_PRELOAD = [
'userGroups',
'team',
];

// Paired with static::listIncludesPreload
Expand Down Expand Up @@ -92,6 +94,7 @@ class UserCompactTransformer extends TransformerAbstract
'statistics',
'statistics_rulesets',
'support_level',
'team',
'unread_pm_count',
'user_achievements',
'user_preferences',
Expand Down Expand Up @@ -454,6 +457,15 @@ public function includeSupportLevel(User $user)
return $this->primitive($user->supportLevel());
}

public function includeTeam(User $user)
{
$team = $user->team;

return $team === null
? $this->null()
: $this->item($team, new TeamTransformer());
}

public function includeUnreadPmCount(User $user)
{
// legacy pm has been turned off
Expand Down
1 change: 1 addition & 0 deletions resources/css/bem-index.less
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@
@import "bem/fileupload";
@import "bem/fixed-bar";
@import "bem/flag-country";
@import "bem/flag-team";
@import "bem/floating-toolbar";
@import "bem/floating-toolbar-button";
@import "bem/follow-mapper";
Expand Down
12 changes: 7 additions & 5 deletions resources/css/bem/beatmap-scoreboard-table.less
Original file line number Diff line number Diff line change
Expand Up @@ -184,11 +184,6 @@
}

&--user-link {
.link-inverted();
.link-hover({
text-decoration: underline;
});

position: absolute;
}

Expand Down Expand Up @@ -221,4 +216,11 @@
opacity: 1;
}
}

&__user-link {
.link-inverted();
.link-hover({
text-decoration: underline;
});
}
}
10 changes: 10 additions & 0 deletions resources/css/bem/flag-team.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

.flag-team {
height: 1em;
aspect-ratio: 2;
display: inline-block;
background-size: cover;
border-radius: min(0.25em, @border-radius-large);
}
1 change: 1 addition & 0 deletions resources/css/bem/forum-post-info.less
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
width: 100%;
display: flex;
justify-content: center;
font-size: 20px; // icon size
}

&--group-badge {
Expand Down
3 changes: 2 additions & 1 deletion resources/css/bem/profile-info.less
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@
}

&__flag-flag {
display: contents;
font-size: var(--icon-height); // icon size
}

Expand All @@ -130,7 +131,7 @@
--icon-height: 15px;

display: flex;
gap: 5px;
gap: 10px;
margin-top: 10px;

@media @desktop {
Expand Down
6 changes: 6 additions & 0 deletions resources/css/bem/ranking-page-table.less
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@
margin-left: 10px;
}

&__flags {
display: inline-flex;
gap: 10px;
font-size: 20px; // icon size
}

&__user-link {
display: flex;
align-items: center;
Expand Down
27 changes: 19 additions & 8 deletions resources/js/beatmapsets-show/scoreboard/table-row.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
// See the LICENCE file in the repository root for full licence text.

import FlagCountry from 'components/flag-country';
import FlagTeam from 'components/flag-team';
import Mod from 'components/mod';
import { PlayDetailMenu } from 'components/play-detail-menu';
import ScoreValue from 'components/score-value';
import ScoreboardTime from 'components/scoreboard-time';
import UserLink from 'components/user-link';
import BeatmapJson from 'interfaces/beatmap-json';
import { SoloScoreJsonForBeatmap } from 'interfaces/solo-score-json';
import { route } from 'laroute';
Expand Down Expand Up @@ -113,14 +115,23 @@ export default class ScoreboardTableRow extends React.Component<Props> {
</TdLink>
) : (
<td className={`${bn}__cell u-relative`}>
<a
className={`${bn}__cell-content ${bn}__cell-content--user-link js-usercard`}
data-user-id={score.user.id}
href={route('users.show', { mode: this.props.beatmap.mode, user: score.user.id })}
>
{score.user.username}
</a>

<span className={`${classWithModifiers(`${bn}__cell-content`, 'user-link')} u-hover`}>
<span>
{score.user.team != null &&
<>
<a href={route('teams.show', { id: score.user.team.id })}>
<FlagTeam team={score.user.team} />
</a>
{' '}
</>
}
<UserLink
className={`${bn}__user-link`}
mode={this.props.beatmap.mode}
user={score.user}
/>
</span>
</span>
<a className={`${bn}__cell-content`} href={this.scoreUrl} />
</td>
)}
Expand Down
38 changes: 25 additions & 13 deletions resources/js/beatmapsets-show/scoreboard/top-card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// See the LICENCE file in the repository root for full licence text.

import FlagCountry from 'components/flag-country';
import FlagTeam from 'components/flag-team';
import Mod from 'components/mod';
import ScorePin from 'components/score-pin';
import ScoreValue from 'components/score-value';
Expand Down Expand Up @@ -80,19 +81,30 @@ export default class TopCard extends React.PureComponent<Props> {
/>
</div>

<a
className='u-hover'
href={route('rankings', {
country: this.props.score.user.country_code,
mode: ruleset,
type: 'performance',
})}
>
<FlagCountry
country={this.props.score.user.country}
modifiers='flat'
/>
</a>
<div style={{ display: 'flex', gap: '5px', marginTop: '5px' }}>
<a
className='u-hover'
href={route('rankings', {
country: this.props.score.user.country_code,
mode: ruleset,
type: 'performance',
})}
>
<FlagCountry
country={this.props.score.user.country}
modifiers='flat'
/>
</a>

{this.props.score.user.team != null &&
<a
className='u-hover'
href={route('teams.show', { team: this.props.score.user.team.id })}
>
<FlagTeam team={this.props.score.user.team} />
</a>
}
</div>
</div>
</div>

Expand Down
23 changes: 23 additions & 0 deletions resources/js/components/flag-team.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

import TeamJson from 'interfaces/team-json';
import * as React from 'react';
import { classWithModifiers, Modifiers } from 'utils/css';

interface Props {
modifiers?: Modifiers;
team: TeamJson;
}

export default function TeamCountry({ team, modifiers }: Props) {
return (
<span
className={classWithModifiers('flag-team', modifiers)}
style={{
backgroundImage: `url('${team.logo}')`,
}}
title={team.name}
/>
);
}
Loading

0 comments on commit 86a89e8

Please sign in to comment.