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 song preview to contest entry for submitted beatmap #11225

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
Open
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
9 changes: 4 additions & 5 deletions resources/css/bem/track-cover-preview.less
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,21 @@

.track-cover-preview {
.reset-input();
width: 32px;
height: $width;
width: 50px;
height: 100%;
.link-plain();
.center-content();
position: relative;
background-size: cover;
background-position: center;
color: hsl(var(--hsl-b1));
color: hsl(var(--hsl-c1));

.link-hover({
color: hsl(var(--hsl-c1));
color: hsl(var(--hsl-b1));
});

&::before {
.full-size();
content: '';
background-color: fade(#000, 75%);
}
}
4 changes: 2 additions & 2 deletions resources/js/components/track-preview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { urlPresence } from 'utils/css';

interface Props {
track: {
cover_url?: string | null;
coverUrl?: string | null;
preview: string;
};
}
Expand All @@ -17,7 +17,7 @@ export default function TrackPreview({ track }: Props) {
className='track-cover-preview js-audio--play js-audio--player'
data-audio-url={track.preview}
style={{
backgroundImage: urlPresence(track.cover_url),
backgroundImage: urlPresence(track.coverUrl),
}}
type='button'
>
Expand Down
103 changes: 0 additions & 103 deletions resources/js/contest-voting/entry.coffee

This file was deleted.

208 changes: 208 additions & 0 deletions resources/js/contest-voting/entry.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
// 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 TrackPreview from 'components/track-preview';
import { route } from 'laroute';
import { includes, round } from 'lodash';
import * as React from 'react';
import { transChoice } from 'utils/lang';
import UserLink from '../components/user-link';
import ContestEntryJson from '../interfaces/contest-entry-json';
import { ContestJsonForEntries } from '../interfaces/contest-json';
import { Voter } from './voter';

interface Props {
contest: ContestJsonForEntries;
entry: ContestEntryJson;
hideIfNotVoted: boolean;
options: {
showLink: boolean;
showPreview: boolean;
};
rank: number;
selected: number[];
waitingForResponse: boolean;
winnerVotes: number;
}

export const Entry = (props: Props) => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this function is too long and contains too many different things

(the original wasn't readable either and this conversion isn't helping at all if not making it a bit more verbose)

const selected = includes(props.selected, props.entry.id);

if (props.hideIfNotVoted && !selected) {
return;
}

const linkIcon =
props.contest.type === 'external' ? 'fa-external-link-alt' : 'fa-download';

const relativeVotePercentage = props.entry.results
? round((props.entry.results.votes / props.winnerVotes) * 100, 2)
: 0;

const usersVotedPercentage = props.entry.results
? round(
(props.entry.results.votes / props.contest.users_voted_count) * 100,
2,
)
: 0;

const renderUserLink = () => {
if (!props.entry.user) {
return <></>;
}

return (
<UserLink
className="contest-voting-list__entrant"
user={props.entry.user}
/>
);
};

const renderTitle = () => {
if (props.contest.type === 'external') {
return (
<>
<a className="contest-voting-list__title-link u-ellipsis-overflow u-relative">
{props.entry.title}
</a>
{renderUserLink()}
</>
);
}

if (
props.options.showLink &&
props.entry.preview !== null &&
props.contest.submitted_beatmaps
) {
return (
<>
<a
className="contest-voting-list__title-link u-ellipsis-overflow u-relative"
href={route('beatmapsets.show', {
beatmapset: props.entry.preview,
})}
>
{props.entry.title}
</a>
{renderUserLink()}
</>
);
}

return (
<>
<div className="u-relative u-ellipsis-overflow">
{props.entry.title}
</div>
{renderUserLink()}
</>
);
};

return (
<div
className={`contest-voting-list__row${
selected && !props.contest.show_votes
? ' contest-voting-list__row--selected'
: ''
}`}
>
{props.contest.show_votes && (
<div className="contest-voting-list__rank">
{props.rank < 4 ? (
<span
className={`contest-voting-list__trophy contest-voting-list__trophy--${props.rank}`}
>
<i className="fas fa-fw fa-trophy" />
</span>
) : (
`#${props.rank}`
)}
</div>
)}
{props.entry.preview !== undefined ? (
props.contest.submitted_beatmaps ? (
<div className="contest-voting-list__preview">
{props.entry.preview !== undefined && (
<TrackPreview
track={{
coverUrl: `https://b.ppy.sh/thumb/${props.entry.preview}.jpg`,
preview: props.entry.preview,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is very wrong

}}
/>
)}
</div>
) : (
<div className="contest-voting-list__icon contest-voting-list__icon--bg">
<a
className="contest-voting-list__link"
href={props.entry.preview}
rel="nofollow noreferrer"
target="_blank"
>
<i className={`fas fa-fw fa-lg ${linkIcon}`} />
</a>
</div>
)
) : (
<></>
)}
{props.contest.show_votes ? (
<div className="contest-voting-list__title contest-voting-list__title--show-votes">
<div
className="contest-voting-list__votes-bar"
style={{ width: `${relativeVotePercentage}%` }}
/>
{renderTitle()}
</div>
) : (
<div className="contest-voting-list__title">{renderTitle()}</div>
)}
{!props.contest.judged && (
<div
className={`contest__voting-star${
props.contest.show_votes ? ' contest__voting-star--dark-bg' : ''
}`}
>
<Voter
key={props.entry.id}
contest={props.contest}
entry={props.entry}
selected={props.selected}
waitingForResponse={props.waitingForResponse}
/>
</div>
)}
{props.contest.show_votes ? (
props.contest.best_of || props.contest.judged ? (
<div className="contest__vote-count contest__vote-count--no-percentages">
{props.entry.results &&
transChoice('contest.vote.points', props.entry.results.votes)}
</div>
) : (
<div className="contest__vote-count">
{props.entry.results &&
transChoice('contest.vote.count', props.entry.results.votes)}
{Number.isFinite(usersVotedPercentage)}
</div>
)
) : (
<></>
)}
{props.contest.judged && (
<div className="contest-voting-list__icon contest-voting-list__icon--bg">
<a
className="contest-voting-list__link"
href={route('contest-entries.judge-results', props.entry.id)}
rel="noreferrer"
target="_blank"
>
<i className="fas fa-fw fa-lg fa-external-link-alt" />
</a>
</div>
)}
</div>
);
};
17 changes: 17 additions & 0 deletions resources/js/contest-voting/voter.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// 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 ContestEntryJson from 'interfaces/contest-entry-json';
import { ContestJsonForEntries } from 'interfaces/contest-json';
import * as React from 'react';

interface Props {
buttonId?: string;
contest: ContestJsonForEntries;
entry: ContestEntryJson;
selected: number[];
theme?: string;
waitingForResponse: boolean;
}

export class Voter extends React.Component<Props> {}
1 change: 1 addition & 0 deletions resources/js/interfaces/contest-entry-json.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import ContestJudgeVoteJson, { ContestJudgeVoteJsonForResults } from './contest-
interface ContestEntryJsonAvailableIncludes {
current_user_judge_vote: ContestJudgeVoteJson;
judge_votes: ContestJudgeVoteJson[];
preview: string;
results: {
actual_name: string;
votes: number;
Expand Down
Loading