the browser-facing portion of osu!
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

use subtypes for results

Venix 7b1e5d12 1204dc4f

+68 -49
+15 -24
resources/js/contest-judge-results/header.tsx
··· 4 4 import BasicSelectOptions from 'components/basic-select-options'; 5 5 import UserLink from 'components/user-link'; 6 6 import ValueDisplay from 'components/value-display'; 7 - import ContestEntryJson from 'interfaces/contest-entry-json'; 8 - import ContestJson from 'interfaces/contest-json'; 7 + import { ContestEntryJsonForResults } from 'interfaces/contest-entry-json'; 8 + import { ContestJsonForResults } from 'interfaces/contest-json'; 9 9 import SelectOptionJson from 'interfaces/select-option-json'; 10 10 import * as React from 'react'; 11 11 import { trans } from 'utils/lang'; 12 12 13 13 interface Props { 14 - contest: ContestJson; 15 - entries: ContestEntryJson[]; 16 - entry: ContestEntryJson; 14 + contest: ContestJsonForResults; 15 + entries: ContestEntryJsonForResults[]; 16 + entry: ContestEntryJsonForResults; 17 17 } 18 18 19 19 export default class Header extends React.PureComponent<Props> { ··· 30 30 render() { 31 31 const { contest, entry } = this.props; 32 32 33 - const score = entry.results?.votes; 34 - const maxScore = (contest.max_judging_score ?? 0) * (entry.judge_votes?.length ?? 0); 33 + const score = entry.results.votes; 34 + const maxScore = contest.max_judging_score * entry.judge_votes.length; 35 35 const totalScore = `${score}/${maxScore}`; 36 - 37 - const userLink = this.renderUserLink(); 38 36 39 37 return ( 40 38 <div className='contest-judge-results-header'> ··· 45 43 /> 46 44 47 45 <div className='contest-judge-results-header__values'> 48 - {score != null && <ValueDisplay 46 + <ValueDisplay 49 47 label={trans('contest.judge_results.total_score')} 50 48 modifiers={'judge-results'} 51 49 value={totalScore} 52 - />} 50 + /> 53 51 54 - {userLink != null && <ValueDisplay 52 + <ValueDisplay 55 53 label={trans('contest.judge_results.creator')} 56 54 modifiers={'judge-results'} 57 - value={userLink} 58 - />} 55 + value={ 56 + <UserLink user={this.props.entry.user} /> 57 + } 58 + /> 59 59 </div> 60 60 </div> 61 61 ); 62 62 } 63 63 64 - private entryToSelectOption(entry: ContestEntryJson): SelectOptionJson { 64 + private entryToSelectOption(entry: ContestEntryJsonForResults): SelectOptionJson { 65 65 return { 66 66 id: entry.id, 67 67 text: entry.title, 68 68 }; 69 - } 70 - 71 - private renderUserLink() { 72 - const { user } = this.props.entry; 73 - if (user == null) return; 74 - 75 - return ( 76 - <UserLink user={user} /> 77 - ); 78 69 } 79 70 }
+6 -6
resources/js/contest-judge-results/main.tsx
··· 1 1 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 2 2 // See the LICENCE file in the repository root for full licence text. 3 3 4 - import ContestEntryJson from 'interfaces/contest-entry-json'; 5 - import ContestJson from 'interfaces/contest-json'; 4 + import { ContestEntryJsonForResults } from 'interfaces/contest-entry-json'; 5 + import { ContestJsonForResults } from 'interfaces/contest-json'; 6 6 import * as React from 'react'; 7 7 import Header from './header'; 8 8 import Vote from './vote'; 9 9 10 10 interface Props { 11 - contest: ContestJson; 12 - entries: ContestEntryJson[]; 13 - entry: ContestEntryJson; 11 + contest: ContestJsonForResults; 12 + entries: ContestEntryJsonForResults[]; 13 + entry: ContestEntryJsonForResults; 14 14 } 15 15 16 16 export default function Main(props: Props) { ··· 23 23 /> 24 24 25 25 <div className='contest-judge-results'> 26 - {props.entry.judge_votes?.map((vote) => ( 26 + {props.entry.judge_votes.map((vote) => ( 27 27 <Vote 28 28 key={vote.id} 29 29 contest={props.contest}
+5 -5
resources/js/contest-judge-results/vote.tsx
··· 4 4 import UserAvatar from 'components/user-avatar'; 5 5 import UserLink from 'components/user-link'; 6 6 import ValueDisplay from 'components/value-display'; 7 - import ContestJson from 'interfaces/contest-json'; 8 - import ContestJudgeVoteJson from 'interfaces/contest-judge-vote-json'; 7 + import { ContestJsonForResults } from 'interfaces/contest-json'; 8 + import { ContestJudgeVoteJsonForResults } from 'interfaces/contest-judge-vote-json'; 9 9 import * as React from 'react'; 10 10 import { trans } from 'utils/lang'; 11 11 12 12 interface Props { 13 - contest: ContestJson; 14 - vote: ContestJudgeVoteJson; 13 + contest: ContestJsonForResults; 14 + vote: ContestJudgeVoteJsonForResults; 15 15 } 16 16 17 17 export default function Vote(props: Props) { ··· 36 36 </div> 37 37 38 38 <div className='contest-judge-results-scores'> 39 - {props.vote.scores?.map((score) => ( 39 + {props.vote.scores.map((score) => ( 40 40 <div key={score.id} className='contest-judge-results-scores__row'> 41 41 <div className='contest-judge-results-scores__col'> 42 42 <div className='contest-judge-entry__description-icon' title={score.category?.description}>
+22 -9
resources/js/interfaces/contest-entry-json.ts
··· 1 1 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 2 2 // See the LICENCE file in the repository root for full licence text. 3 3 4 - import ContestJudgeVoteJson from './contest-judge-vote-json'; 4 + import ContestJudgeVoteJson, { ContestJudgeVoteJsonForResults } from './contest-judge-vote-json'; 5 5 6 - export default interface ContestEntryJson { 7 - contest_id: number; 8 - current_user_judge_vote?: ContestJudgeVoteJson; 9 - id: number; 10 - judge_votes?: ContestJudgeVoteJson[]; 11 - results?: { 6 + interface ContestEntryJsonAvailableIncludes { 7 + current_user_judge_vote: ContestJudgeVoteJson; 8 + results: { 12 9 actual_name: string; 13 10 votes: number; 14 11 }; 15 - title: string; 16 - user?: { 12 + judge_votes: ContestJudgeVoteJson[]; 13 + user: { 17 14 id: number; 18 15 username: string; 19 16 }; 20 17 } 18 + 19 + interface ContestEntryJsonDefaultAttributes { 20 + contest_id: number; 21 + id: number; 22 + title: string; 23 + } 24 + 25 + type ContestEntryJson = ContestEntryJsonDefaultAttributes 26 + & Partial<ContestEntryJsonAvailableIncludes>; 27 + export default ContestEntryJson; 28 + 29 + export type ContestEntryJsonForResults = ContestEntryJsonDefaultAttributes 30 + & Required<Pick<ContestEntryJsonAvailableIncludes, 'results' | 'user'>> 31 + & { 32 + judge_votes: ContestJudgeVoteJsonForResults[]; 33 + };
+17 -5
resources/js/interfaces/contest-json.ts
··· 1 1 // Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0. 2 2 // See the LICENCE file in the repository root for full licence text. 3 3 4 - import ContestEntryJson from './contest-entry-json'; 4 + import ContestEntryJson, { ContestEntryJsonForResults } from './contest-entry-json'; 5 5 import ContestScoringCategoryJson from './contest-scoring-category-json'; 6 6 7 - export default interface ContestJson { 8 - entries?: ContestEntryJson[]; 7 + interface ContestJsonAvailableIncludes { 8 + entries: ContestEntryJson[]; 9 + max_judging_score: number; 10 + scoring_categories: ContestScoringCategoryJson[]; 11 + } 12 + 13 + interface ContestJsonDefaultAttributes { 9 14 id: number; 10 - max_judging_score?: number; 11 15 name: string; 12 - scoring_categories?: ContestScoringCategoryJson[]; 13 16 } 17 + 18 + type ContestJson = ContestJsonDefaultAttributes & Partial<ContestJsonAvailableIncludes>; 19 + export default ContestJson; 20 + 21 + export type ContestJsonForResults = ContestJsonDefaultAttributes 22 + & Required<Pick<ContestJsonAvailableIncludes, 'max_judging_score' | 'scoring_categories'>> 23 + & { 24 + entires: ContestEntryJsonForResults; 25 + };
+3
resources/js/interfaces/contest-judge-vote-json.ts
··· 11 11 total_score?: number; 12 12 user?: UserJson; 13 13 } 14 + 15 + export type ContestJudgeVoteJsonForResults = ContestJudgeVoteJson 16 + & Required<Pick<ContestJudgeVoteJson, 'scores' | 'total_score'>>;