Skip to content

Commit

Permalink
Merge pull request #11563 from nanaya/team-backend
Browse files Browse the repository at this point in the history
Add basic team backend
  • Loading branch information
notbakaneko authored Dec 3, 2024
2 parents 4def184 + 7575396 commit ceb8d7f
Show file tree
Hide file tree
Showing 20 changed files with 514 additions and 4 deletions.
26 changes: 26 additions & 0 deletions app/Http/Controllers/TeamsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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\Http\Controllers;

use App\Models\Team;
use App\Transformers\UserCompactTransformer;
use Symfony\Component\HttpFoundation\Response;

class TeamsController extends Controller
{
public function show(string $id): Response
{
$team = Team
::with(array_map(
fn (string $preload): string => "members.user.{$preload}",
UserCompactTransformer::CARD_INCLUDES_PRELOAD,
))->findOrFail($id);

return ext_view('teams.show', compact('team'));
}
}
82 changes: 82 additions & 0 deletions app/Models/Team.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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\Models;

use App\Libraries\BBCodeForDB;
use App\Libraries\Uploader;
use Illuminate\Database\Eloquent\Relations\HasMany;

class Team extends Model
{
protected $casts = ['is_open' => 'bool'];

private Uploader $header;
private Uploader $logo;

public function applications(): HasMany
{
return $this->hasMany(TeamApplication::class);
}

public function leader(): BelongsTo
{
return $this->belongsTo(User::class, 'leader_id');
}

public function members(): HasMany
{
return $this->hasMany(TeamMember::class);
}

public function setHeaderAttribute(?string $value): void
{
if ($value === null) {
$this->header()->delete();
} else {
$this->header()->store($value);
}
}

public function setLogoAttribute(?string $value): void
{
if ($value === null) {
$this->logo()->delete();
} else {
$this->logo()->store($value);
}
}

public function descriptionHtml(): string
{
$description = presence($this->description);

return $description === null
? ''
: bbcode((new BBCodeForDB($description))->generate());
}

public function header(): Uploader
{
return $this->header ??= new Uploader(
'teams/header',
$this,
'header_file',
['image' => ['maxDimensions' => [1000, 250]]],
);
}

public function logo(): Uploader
{
return $this->logo ??= new Uploader(
'teams/logo',
$this,
'logo_file',
['image' => ['maxDimensions' => [256, 128]]],
);
}
}
27 changes: 27 additions & 0 deletions app/Models/TeamMember.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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\Models;

use Illuminate\Database\Eloquent\Relations\BelongsTo;

class TeamMember extends Model
{
public $incrementing = false;

protected $primaryKey = 'user_id';

public function team(): BelongsTo
{
return $this->belongsTo(Team::class);
}

public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'user_id');
}
}
7 changes: 7 additions & 0 deletions app/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
* @property-read Collection<Store\Address> $storeAddresses
* @property-read Collection<UserDonation> $supporterTagPurchases
* @property-read Collection<UserDonation> $supporterTags
* @property-read TeamMember|null $teamMembership
* @property-read Collection<OAuth\Token> $tokens
* @property-read Collection<Forum\TopicWatch> $topicWatches
* @property-read Collection<UserAchievement> $userAchievements
Expand Down Expand Up @@ -296,6 +297,11 @@ public function userCountryHistory(): HasMany
return $this->hasMany(UserCountryHistory::class);
}

public function teamMembership(): HasOne
{
return $this->hasOne(TeamMember::class, 'user_id');
}

public function getAuthPassword()
{
return $this->user_password;
Expand Down Expand Up @@ -951,6 +957,7 @@ public function getAttribute($key)
'storeAddresses',
'supporterTagPurchases',
'supporterTags',
'teamMembership',
'tokens',
'topicWatches',
'userAchievements',
Expand Down
3 changes: 2 additions & 1 deletion app/helpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -922,6 +922,7 @@ function page_title()
$namespaceKey = "{$currentRoute['namespace']}._";
$namespaceKey = match ($namespaceKey) {
'admin_forum._' => 'admin._',
'teams._' => 'main.teams_controller._',
default => $namespaceKey,
};
$keys = [
Expand Down Expand Up @@ -1092,7 +1093,7 @@ function wiki_url($path = null, $locale = null, $api = null, $fullUrl = true)
return rtrim(str_replace($params['path'], $path, route($route, $params, $fullUrl)), '/');
}

function bbcode($text, $uid, $options = [])
function bbcode($text, $uid = null, $options = [])
{
return (new App\Libraries\BBCodeFromDB($text, $uid, $options))->toHTML();
}
Expand Down
32 changes: 32 additions & 0 deletions database/factories/TeamFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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 Database\Factories;

use App\Models\Team;
use App\Models\User;

class TeamFactory extends Factory
{
protected $model = Team::class;

public function configure(): static
{
return $this->afterCreating(function (Team $team): void {
$team->members()->create(['user_id' => $team->leader_id]);
});
}

public function definition(): array
{
return [
'name' => fn () => $this->faker->name(),
'short_name' => fn () => $this->faker->domainWord(),
'leader_id' => User::factory(),
];
}
}
39 changes: 39 additions & 0 deletions database/migrations/2024_11_30_000000_create_teams.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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);

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::create('teams', function (Blueprint $table) {
$table->id();
$table->string('name')->nullable(false);
$table->string('short_name')->nullable(false);
$table->string('logo_file')->nullable(true);
$table->string('header_file')->nullable(true);
$table->string('url')->nullable(true);
$table->text('description')->nullable(true);
$table->boolean('is_open')->nullable(false)->default(true);
$table->smallInteger('default_ruleset_id')->nullable(false)->default(0);
$table->bigInteger('leader_id')->nullable(false);
$table->timestampTz('created_at')->useCurrent();
$table->timestampTz('updated_at')->useCurrent();

$table->unique('name');
$table->unique('short_name');
});
}

public function down(): void
{
Schema::dropIfExists('teams');
}
};
30 changes: 30 additions & 0 deletions database/migrations/2024_11_30_000001_create_team_members.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

// Copyright (c) ppy Pty Ltd <[email protected]>. 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);

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::create('team_members', function (Blueprint $table) {
$table->unsignedBigInteger('user_id')->primary();
$table->unsignedBigInteger('team_id')->nullable(false);
$table->timestampTz('created_at')->useCurrent();
$table->timestampTz('updated_at')->useCurrent();

$table->index('team_id');
});
}

public function down(): void
{
Schema::dropIfExists('team_members');
}
};
4 changes: 4 additions & 0 deletions resources/css/bem-index.less
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,10 @@
@import "bem/supporter-promo";
@import "bem/supporter-quote";
@import "bem/supporter-status";
@import "bem/team-info-entries";
@import "bem/team-info-entry";
@import "bem/team-members";
@import "bem/team-summary";
@import "bem/textual-button";
@import "bem/title";
@import "bem/tooltip-achievement";
Expand Down
24 changes: 21 additions & 3 deletions resources/css/bem/profile-info.less
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,26 @@
// See the LICENCE file in the repository root for full licence text.

.profile-info {
--avatar: none;
--avatar-radius-extended-desktop: 40px;
--avatar-radius-extended: 20px;
--avatar-radius: 20px;
--avatar-size-extended-desktop: @profile-avatar-size;
--avatar-size-extended: var(--content-height);
--avatar-size: var(--content-height);

--avatar-height: var(--avatar-size);
--avatar-width: var(--avatar-size);

--bg: none;

--content-height: 65px;
--vertical-padding: 10px;

--info-margin-extended-desktop: 20px;
--info-margin-extended: 10px;
--info-margin: 10px;
--vertical-padding: 10px;

display: flex;
flex-direction: column;
flex: none;
Expand All @@ -29,6 +38,13 @@
background-color: hsl(var(--hsl-b4));
}

&--team {
--avatar-width: calc(var(--avatar-height) * 2);
--avatar: url("~@images/headers/generic.jpg");
--bg: url("~@images/headers/generic.jpg");
background-color: hsl(var(--hsl-b4));
}

@media @desktop {
--avatar-radius-extended: var(--avatar-radius-extended-desktop);
--avatar-size-extended: var(--avatar-size-extended-desktop);
Expand All @@ -38,17 +54,19 @@
&__avatar {
.own-layer(); // required by safari for border-radius to be applied correctly
flex: none;
width: var(--avatar-size);
height: var(--avatar-size);
width: var(--avatar-width);
height: var(--avatar-height);
border-radius: var(--avatar-radius);
overflow: hidden;
align-self: flex-end;
margin-bottom: var(--vertical-padding);
background-image: var(--avatar);
.default-box-shadow();
}

&__bg {
position: relative;
background-image: var(--bg);
background-size: cover;
background-position: center;
height: 100px;
Expand Down
8 changes: 8 additions & 0 deletions resources/css/bem/team-info-entries.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

.team-info-entries {
display: grid;
gap: 10px;
margin-bottom: 20px;
}
12 changes: 12 additions & 0 deletions resources/css/bem/team-info-entry.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Copyright (c) ppy Pty Ltd <[email protected]>. Licensed under the GNU Affero General Public License v3.0.
// See the LICENCE file in the repository root for full licence text.

.team-info-entry {
display: grid;

&__value {
color: hsl(var(--hsl-c2));
display: grid;
min-width: 0;
}
}
Loading

0 comments on commit ceb8d7f

Please sign in to comment.