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

Add voter participation sticker for Project Loved #8652

Draft
wants to merge 5 commits into
base: master
Choose a base branch
from
Draft
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
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ SLACK_ENDPOINT=https://myconan.net/null/
# INITIAL_HELP_FORUM_IDS="5 47 85"
# ISSUE_FORUM_IDS=
# FORUM_POST_MINIMUM_PLAYS=200
# PROJECT_LOVED_FORUM_ID=120

# GA_TRACKING_ID=UA-xxx

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 @@ -498,6 +498,7 @@ public function me($mode = null)
* - statistics.variants
* - support_level
* - user_achievements
* - voted_in_project_loved
*
* @urlParam user integer required Id or username of the user. Id lookup is prioritised unless `key` parameter is specified. Previous usernames are also checked in some cases. Example: 1
* @urlParam mode string [GameMode](#gamemode). User default mode will be used if not specified. Example: osu
Expand Down
49 changes: 49 additions & 0 deletions app/Libraries/ProjectLovedPollsCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?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\Libraries;

use App\Models\Forum\Topic;
use App\Models\User;
use App\Traits\LocallyCached;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Collection;

class ProjectLovedPollsCache
{
use LocallyCached;

/**
* Get all topics on the Project Loved forum that have an open poll and finite poll length.
*/
public function all(): Collection
{
$topics = $this->cachedMemoize(__FUNCTION__, function () {
return Topic
::where('forum_id', config('osu.forum.project_loved_forum_id'))
->whereRaw('poll_start + poll_length > ?', [Carbon::now()->getTimestamp()])
->get();
});

if ($topics->contains(fn (Topic $topic) => !$topic->poll()->isOpen())) {
$this->resetCache();
return $this->all();
}

return $topics;
}

/**
* Check if the user voted in any open Project Loved polls.
*/
public function userVotedAny(User $user): bool
{
return $this->memoize(__FUNCTION__.':'.$user->getKey(), function () use ($user) {
return $this->all()->contains(fn (Topic $topic) => $topic->poll()->votedBy($user));
});
}
}
1 change: 1 addition & 0 deletions app/Listeners/OctaneResetLocalCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ public function handle($event): void
{
app('chat-filters')->incrementResetTicker();
app('groups')->incrementResetTicker();
app('loved-polls')->incrementResetTicker();
}
}
10 changes: 7 additions & 3 deletions app/Models/Forum/TopicPoll.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ public function save()
return false;
}

return DB::transaction(function () {
DB::transaction(function () {
$this->topic->update([
'poll_title' => $this->params['title'],
'poll_start' => Carbon::now(),
Expand All @@ -133,9 +133,13 @@ public function save()
'poll_option_text' => $value,
]);
}

return true;
});

if ($this->topic->forum_id === config('osu.forum.project_loved_forum_id')) {
app('loved-polls')->resetCache();
}

return true;
}

public function setTopic($topic)
Expand Down
3 changes: 3 additions & 0 deletions app/Providers/AppServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
use App\Libraries\OsuAuthorize;
use App\Libraries\OsuCookieJar;
use App\Libraries\OsuMessageSelector;
use App\Libraries\ProjectLovedPollsCache;
use App\Libraries\RouteSection;
use App\Libraries\User\ScorePins;
use Datadog;
Expand All @@ -34,6 +35,7 @@ class AppServiceProvider extends ServiceProvider
'assets-manifest' => AssetsManifest::class,
'chat-filters' => ChatFilters::class,
'groups' => Groups::class,
'loved-polls' => ProjectLovedPollsCache::class,
'route-section' => RouteSection::class,
'score-pins' => ScorePins::class,
];
Expand All @@ -55,6 +57,7 @@ public function boot()
app('OsuAuthorize')->resetCache();
app('groups')->incrementResetTicker();
app('chat-filters')->incrementResetTicker();
app('loved-polls')->incrementResetTicker();

Datadog::increment(
config('datadog-helper.prefix_web').'.queue.run',
Expand Down
7 changes: 7 additions & 0 deletions app/Transformers/UserCompactTransformer.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class UserCompactTransformer extends TransformerAbstract
'mapping_follower_count',
'previous_usernames',
'support_level',
'voted_in_project_loved',
];

protected string $mode;
Expand Down Expand Up @@ -85,6 +86,7 @@ class UserCompactTransformer extends TransformerAbstract
'unread_pm_count',
'user_achievements',
'user_preferences',
'voted_in_project_loved',
// TODO: should be changed to rank_history
// TODO: should be alphabetically ordered but lazer relies on being after statistics. can revert to alphabetical after 2020-05-01
'rankHistory',
Expand Down Expand Up @@ -427,6 +429,11 @@ public function includeUserPreferences(User $user)
]));
}

public function includeVotedInProjectLoved(User $user)
{
return $this->primitive(app('loved-polls')->userVotedAny($user));
}

public function setMode(string $mode)
{
$this->mode = $mode;
Expand Down
1 change: 1 addition & 0 deletions config/osu.php
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
'minimum_plays' => get_int(env('FORUM_POST_MINIMUM_PLAYS')) ?? 200,
'necropost_months' => 6,
'poll_edit_hours' => get_int(env('FORUM_POLL_EDIT_HOURS')) ?? 1,
'project_loved_forum_id' => get_int(env('PROJECT_LOVED_FORUM_ID')) ?? 120,

'double_post_time' => [
'author' => 24,
Expand Down
Binary file added public/images/layout/loved-voted-sticker.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion resources/assets/less/bem-index.less
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,8 @@
@import "bem/profile-previous-usernames";
@import "bem/profile-rank-count";
@import "bem/profile-stats";
@import "bem/profile-tournament-banner";
@import "bem/profile-header-banner";
@import "bem/profile-header-banners";
@import "bem/proportional-container";
@import "bem/qtip";
@import "bem/quick-info";
Expand Down
47 changes: 47 additions & 0 deletions resources/assets/less/bem/profile-header-banner.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// 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.

.profile-header-banner {
@_top: profile-header-banner;
overflow: hidden;

@media @desktop {
.own-layer();
transition: transform .2s cubic-bezier(.08,.82,.17,1);

&:hover {
transform: scale(1.1);
z-index: 1;
}

& + & {
margin-left: 10px;
}
}

&--loved-voted-sticker {
.default-border-radius();
.link-plain();
.link-white();
background-color: @osu-colour-b6;
display: flex;
flex-direction: row-reverse;
align-items: center;
padding: 4px 0 4px 10px;

.@{_top}__image {
margin-left: -10px;
}
}

&--tournament {
@media @desktop {
.default-border-radius();
width: 60%;
}

.@{_top}__image {
width: 100%;
}
}
}
11 changes: 11 additions & 0 deletions resources/assets/less/bem/profile-header-banners.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// 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.

.profile-header-banners {
display: flex;
align-items: end;

@media @desktop {
margin-bottom: 10px;
}
}
27 changes: 0 additions & 27 deletions resources/assets/less/bem/profile-tournament-banner.less

This file was deleted.

1 change: 0 additions & 1 deletion resources/assets/less/variables.less
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@

@z-index--beatmaps-panel: 4;
@z-index--profile-previous-usernames: 10;
@z-index--profile-tournament-banner: 11;
@z-index--page-extra-tabs: 99;
@z-index--profile-page-cover-selector: 100; // must be at least 1 more than @z-index--page-extra-tabs
@z-index--beatmap-discussion-editor-insertion-menu: 100;
Expand Down
41 changes: 41 additions & 0 deletions resources/assets/lib/components/profile-header-banners.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// 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.

import Img2x from 'components/img2x';
import UserProfileJson from 'interfaces/user-profile-json';
import { route } from 'laroute';
import * as React from 'react';

interface Props {
user: UserProfileJson;
}

export default function ProfileHeaderBanners({ user }: Props) {
const {
active_tournament_banner: tournamentBanner,
voted_in_project_loved: votedInProjectLoved,
} = user;

return (
<div className='profile-header-banners'>
{tournamentBanner != null && (
<a
className='profile-header-banner profile-header-banner--tournament'
href={route('tournaments.show', { tournament: tournamentBanner.tournament_id })}
>
<Img2x className='profile-header-banner__image' src={tournamentBanner.image} />
</a>
)}
{votedInProjectLoved && (
<a
className='profile-header-banner profile-header-banner--loved-voted-sticker'
href={route('forum.forums.show', { forum: 120 })}
title={osu.trans('users.show.loved_voted_sticker.title', { username: user.username })}
>
<Img2x className='profile-header-banner__image' src='/images/layout/loved-voted-sticker.png' />
<span>{osu.trans('users.show.loved_voted_sticker.content')}</span>
</a>
)}
</div>
);
}
24 changes: 0 additions & 24 deletions resources/assets/lib/components/profile-tournament-banner.tsx

This file was deleted.

1 change: 1 addition & 0 deletions resources/assets/lib/interfaces/user-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ interface UserJsonAvailableIncludes {
unread_pm_count: number;
user_achievements: UserAchievementJson[];
user_preferences: UserPreferencesJson;
voted_in_project_loved: boolean;
}

interface UserJsonDefaultAttributes {
Expand Down
20 changes: 20 additions & 0 deletions resources/assets/lib/interfaces/user-profile-json.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// 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.

import UserExtendedJson from './user-extended-json';
import UserJson from './user-json';

type UserProfileHeaderIncludes =
| 'active_tournament_banner'
| 'badges'
| 'comments_count'
| 'follower_count'
| 'groups'
| 'mapping_follower_count'
| 'previous_usernames'
| 'support_level'
| 'voted_in_project_loved';

type UserProfileJson = UserExtendedJson & Required<Pick<UserJson, UserProfileHeaderIncludes>>;

export default UserProfileJson;
5 changes: 2 additions & 3 deletions resources/assets/lib/modding-profile/header.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

import HeaderV4 from 'components/header-v4'
import Img2x from 'components/img2x'
import ProfileTournamentBanner from 'components/profile-tournament-banner'
import ProfileHeaderBanners from 'components/profile-header-banners'
import Badges from 'profile-page/badges'
import Detail from 'profile-page/detail'
import HeaderInfo from 'profile-page/header-info'
Expand All @@ -22,8 +22,7 @@ export class Header extends React.Component
'data-page-id': 'main'
el HeaderV4,
backgroundImage: @props.user.cover.url
contentPrepend: el ProfileTournamentBanner,
banner: @props.user.active_tournament_banner
contentPrepend: el ProfileHeaderBanners, user: @props.user
links: headerLinks(@props.user, 'modding')
theme: 'users'
div className: 'osu-page osu-page--users',
Expand Down
Loading