From c33acb586a9608f236f0400b9d214e25dcc1fbf4 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 18 Apr 2019 08:17:01 +0200 Subject: [PATCH 01/37] Add empty page for statistics of a tournament --- pages/tournament-statistics.js | 185 +++++++++++++++++++++++++++++++++ server.js | 6 ++ 2 files changed, 191 insertions(+) create mode 100644 pages/tournament-statistics.js diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js new file mode 100644 index 0000000..262dbab --- /dev/null +++ b/pages/tournament-statistics.js @@ -0,0 +1,185 @@ +import Head from 'next/head'; +import React from 'react'; +import { connect } from 'react-redux'; + +class StatisticsTournamentPage extends React.Component { + + static async getInitialProps({query}) { + return {query}; + } + +/* + team: 0x1234 // New York Excelsior + team: 0x1235 // Los Angeles Gladiators + team: 0x1236 // San Francisco Shock + team: 0x1237 // Vancouver Titans + team: 0x1238 // London Spitfire + team: 0x1239 //Dallas Fuel + team: 0x123a // Chengdu Hunters + team: 0x123b // Boston Uprising + team: 0x123c // Paris Eternal + team: 0x123d // Philadelphia Fusion + team: 0x123e // Hangzhou Spark + team: 0x123f // Houston Outlaws + team: 0x1240 // Shanghai Dragons + team: 0x1241 // Los Angeles Valiant + team: 0x1242 // Seoul Dynasty + team: 0x1243 // Atlanta Reign + team: 0x1244 // Toronto Defiant + team: 0x1245 // Florida Mayhem + team: 0x1246 // Washington Justice + team: 0x1247 // Guangzhou Charge +*/ + + render() { + let tournamentStatistics = { + tournament: { + code: 'abcd1234', + description: '', + id: 0xa1, + name: 'Overwatch League Season 2019 Stage 1', + owner_username: 'Blizzard Entertainment Inc.', + public: true + }, + teams: [ + { id: 0x1234, name: 'New York Excelsior' }, + { id: 0x1235, name: 'Los Angeles Gladiators' }, + { id: 0x1236, name: 'San Francisco Shock' }, + { id: 0x1237, name: 'Vancouver Titans' }, + { id: 0x1238, name: 'London Spitfire' }, + { id: 0x1239, name: 'Dallas Fuel' }, + { id: 0x123a, name: 'Chengdu Hunters' }, + { id: 0x123b, name: 'Boston Uprising' }, + { id: 0x123c, name: 'Paris Eternal' }, + { id: 0x123d, name: 'Philadelphia Fusion' }, + { id: 0x123e, name: 'Hangzhou Spark' }, + { id: 0x123f, name: 'Houston Outlaws' }, + { id: 0x1240, name: 'Shanghai Dragons' }, + { id: 0x1241, name: 'Los Angeles Valiant' }, + { id: 0x1242, name: 'Seoul Dynasty' }, + { id: 0x1243, name: 'Atlanta Reign' }, + { id: 0x1244, name: 'Toronto Defiant' }, + { id: 0x1245, name: 'Florida Mayhem' }, + { id: 0x1246, name: 'Washington Justice' }, + { id: 0x1247, name: 'Guangzhou Charge' } + ], + groupPhasePerformances: [ + { + winlossdifferential: 7, + pointDifferential: 16, + team: 0x1234 // New York Excelsior + }, + { + winlossdifferential: -1, + pointDifferential: 1, + team: 0x1235 // Los Angeles Gladiators + }, + { + winlossdifferential: 1, + pointDifferential: 5, + team: 0x1236 // San Francisco Shock + }, + { + winlossdifferential: 7, + pointDifferential: 18, + team: 0x1237 // Vancouver Titans + }, + { + winlossdifferential: -1, + pointDifferential: -4, + team: 0x1238 // London Spitfire + }, + { + winlossdifferential: 1, + pointDifferential: 0, + team: 0x1239 //Dallas Fuel + }, + { + winlossdifferential: -1, + pointDifferential: -8, + team: 0x123a // Chengdu Hunters + }, + { + winlossdifferential: 1, + pointDifferential: 3, + team: 0x123b // Boston Uprising + }, + { + winlossdifferential: -1, + pointDifferential: -8, + team: 0x123c // Paris Eternal + }, + { + winlossdifferential: 3, + pointDifferential: 5, + team: 0x123d // Philadelphia Fusion + }, + { + winlossdifferential: -1, + pointDifferential: -4, + team: 0x123e // Hangzhou Spark + }, + { + winlossdifferential: -1, + pointDifferential: -3, + team: 0x123f // Houston Outlaws + }, + { + winlossdifferential: -1, + pointDifferential: -4, + team: 0x1240 // Shanghai Dragons + }, + { + winlossdifferential: -7, + pointDifferential: -9, + team: 0x1241 // Los Angeles Valiant + }, + { + winlossdifferential: 1, + pointDifferential: 5, + team: 0x1242 // Seoul Dynasty + }, + { + winlossdifferential: 1, + pointDifferential: 6, + team: 0x1243 // Atlanta Reign + }, + { + winlossdifferential: 3, + pointDifferential: 5, + team: 0x1244 // Toronto Defiant + }, + { + winlossdifferential: -5, + pointDifferential: -12, + team: 0x1245 // Florida Mayhem + }, + { + winlossdifferential: -5, + pointDifferential: -11, + team: 0x1246 // Washington Justice + }, + { + winlossdifferential: -1, + pointDifferential: -1, + team: 0x1247 // Guangzhou Charge + } + ], + playoffPerformances: [ + ] + + }; + + return ( +
+ + Turnie.re - Turnieranzeige (Statistiken) + +

Turnieranzeige (Statistiken)

+

Code: {this.props.query.code}

+
+ ); + } +} + +export default connect()(StatisticsTournamentPage); diff --git a/server.js b/server.js index 6c90888..9b30a15 100644 --- a/server.js +++ b/server.js @@ -27,6 +27,12 @@ app.prepare() app.render(req, res, actualPage, queryParam); }); + server.get('/t/:code/statistics', (req, res) => { + const actualPage = '/tournament-statistics'; + const queryParam = { code: req.params.code }; + app.render(req, res, actualPage, queryParam); + }); + server.get('*', (req, res) => { return handle(req, res); }); From 41b05e446dde63de5865d393b36a712daab66805 Mon Sep 17 00:00:00 2001 From: Jonny Date: Tue, 23 Apr 2019 14:18:30 +0200 Subject: [PATCH 02/37] Add first prototype for the table view --- pages/tournament-statistics.js | 88 +++++++++++++++++++++++++++++++--- 1 file changed, 82 insertions(+), 6 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 262dbab..3475daa 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -1,6 +1,72 @@ import Head from 'next/head'; import React from 'react'; import { connect } from 'react-redux'; +import { + Card, + CardBody, + Container, + Table +} from 'reactstrap'; + +import { TurniereNavigation } from '../js/components/Navigation'; +import { BigImage } from '../js/components/BigImage'; +import { Footer } from '../js/components/Footer'; + + +class TeamRow extends React.Component { + constructor(props) { + super(props); + } + + render() { + return ( + + {this.findTeam(this.props.teams, this.props.teamToShow.team).name} + { this.props.teamToShow.winlossdifferential } + { this.props.teamToShow.pointDifferential } + + ); + } + + + findTeam(teams, id) { + for(let i = 0; i < teams.length; i++) { + if(teams[i].id === id) { + return teams[i]; + } + } + return null; + } +} + +class StatisticsComponent extends React.Component { + + constructor(props) { + super(props); + } + + render() { + return ( + + +

Turnier-Statistiken für {this.props.data.tournament.name}

+ + + + + + + + { this.props.data.groupPhasePerformances.map((team, index) => ( + + )) } + +
Team NameMatch DifferenzPunkt Differenz
+
+
+ ); + } +} class StatisticsTournamentPage extends React.Component { @@ -165,18 +231,28 @@ class StatisticsTournamentPage extends React.Component { team: 0x1247 // Guangzhou Charge } ], - playoffPerformances: [ - ] - + mostDominantTeam: { + id: 0x1234, + pointsMade: 94, + pointsReceived: 3 + }, + leastDominantTeam: { + id: 0x1240, + pointsMade: 2, + pointsReceived: 103 + } }; return (
- Turnie.re - Turnieranzeige (Statistiken) + {tournamentStatistics.tournament.name}: turnie.re -

Turnieranzeige (Statistiken)

-

Code: {this.props.query.code}

+ + + + +
); } From 7976d8b0f396a1a4a4a318baceadb5dbfe8c96f3 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 25 Apr 2019 09:26:48 +0200 Subject: [PATCH 03/37] Sort the teams accordings to match and point differential --- js/utils/sort.js | 73 ++++++++++++++++++++++++++++++++++ pages/tournament-statistics.js | 53 ++++++++++-------------- 2 files changed, 94 insertions(+), 32 deletions(-) create mode 100644 js/utils/sort.js diff --git a/js/utils/sort.js b/js/utils/sort.js new file mode 100644 index 0000000..04d8a74 --- /dev/null +++ b/js/utils/sort.js @@ -0,0 +1,73 @@ + +/** + * Constants for the ordering in which the sorting + * algorithm should bring the elements. + */ +export const Order = { + ascending : 1, + descending: 2 +}; + +/** + * A sorting function that can be used to sort any kind of data + * given an applicable comparator. Said comparator will take in two + * elements of the given array `data`, and produce an integer result + * which can be interpreted as follows: + * ``` + * comparator(a, b) < 0 => a < b + * comparator(a, b) = 0 => a = b + * comparator(a, b) > 0 => a > b + * ``` + * The parameter order should be given as one of the constants in Order. + * Said `order` parameter is optional; it will default to ascending. + * + * @param {T[]} data The array that is to be sorted. + * @param {(T, T) => int} comparator A function which can be used + * to compare any two elemments from the given array. + * @param {int} order The order in which the data should be sorted, + * as defined in Order. + * @return An array with the elements from data sorted in the given order. + */ +export function sort(data, comparator, order) { + if(order === undefined) { + order = Order.ascending; + } + let target = data.slice(); + return sortToTarget(data, target, 0, data.length, comparator, order); +} + +function sortToTarget(data, target, start, end, comparator, order) { + if(end - start < 2) { + return data; + } + + let middle = Math.floor((end + start) / 2); + + sortToTarget(target, data, start, middle, comparator, order); + sortToTarget(target, data, middle, end, comparator, order); + + return merge(data, target, start, middle, end, comparator, order); +} + +function merge(data, target, start, middle, end, comparator, order) { + let i = start; + let j = middle; + + for(let k = start; k < end; k++) { + if(order === Order.ascending) { + if(i < middle && (j >= end || comparator(data[i], data[j]) >= 0)) { + target[k] = data[i++]; + } else { + target[k] = data[j++]; + } + } else { + if(i < middle && (j >= end || comparator(data[i], data[j]) <= 0)) { + target[k] = data[i++]; + } else { + target[k] = data[j++]; + } + } + } + + return target; +} diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 3475daa..a30dfdf 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -11,6 +11,7 @@ import { import { TurniereNavigation } from '../js/components/Navigation'; import { BigImage } from '../js/components/BigImage'; import { Footer } from '../js/components/Footer'; +import { Order, sort } from '../js/utils/sort'; class TeamRow extends React.Component { @@ -22,8 +23,8 @@ class TeamRow extends React.Component { return ( {this.findTeam(this.props.teams, this.props.teamToShow.team).name} - { this.props.teamToShow.winlossdifferential } - { this.props.teamToShow.pointDifferential } + { this.props.teamToShow.winlossdifferential } + { this.props.teamToShow.pointDifferential } ); } @@ -46,18 +47,29 @@ class StatisticsComponent extends React.Component { } render() { + let performances = this.props.data.groupPhasePerformances; + + /** + * comparison(p1, p2) < 0 => p1 < p2 + * comparison(p1, p2) = 0 => p1 = p2 + * comparison(p1, p2) > 0 => p1 > p2 + */ + let sortedPerformances = sort(performances, (p1, p2) => { + return (p2.winlossdifferential - p1.winlossdifferential) * 100 + (p2.pointDifferential - p1.pointDifferential); + }, Order.descending); + return (

Turnier-Statistiken für {this.props.data.tournament.name}

- - - - - - { this.props.data.groupPhasePerformances.map((team, index) => ( + + + + + + { sortedPerformances.map((team, index) => ( )) } @@ -74,29 +86,6 @@ class StatisticsTournamentPage extends React.Component { return {query}; } -/* - team: 0x1234 // New York Excelsior - team: 0x1235 // Los Angeles Gladiators - team: 0x1236 // San Francisco Shock - team: 0x1237 // Vancouver Titans - team: 0x1238 // London Spitfire - team: 0x1239 //Dallas Fuel - team: 0x123a // Chengdu Hunters - team: 0x123b // Boston Uprising - team: 0x123c // Paris Eternal - team: 0x123d // Philadelphia Fusion - team: 0x123e // Hangzhou Spark - team: 0x123f // Houston Outlaws - team: 0x1240 // Shanghai Dragons - team: 0x1241 // Los Angeles Valiant - team: 0x1242 // Seoul Dynasty - team: 0x1243 // Atlanta Reign - team: 0x1244 // Toronto Defiant - team: 0x1245 // Florida Mayhem - team: 0x1246 // Washington Justice - team: 0x1247 // Guangzhou Charge -*/ - render() { let tournamentStatistics = { tournament: { @@ -244,7 +233,7 @@ class StatisticsTournamentPage extends React.Component { }; return ( -
+
{tournamentStatistics.tournament.name}: turnie.re From bfe89b6387b9827a52635b23b1c6a064def0215a Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 08:12:12 +0200 Subject: [PATCH 04/37] Introduce a more uniform look for the tournament statistics --- pages/tournament-statistics.js | 48 ++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 5 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index a30dfdf..ef719ed 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -5,6 +5,8 @@ import { Card, CardBody, Container, + ListGroup, + ListGroupItem, Table } from 'reactstrap'; @@ -90,7 +92,7 @@ class StatisticsTournamentPage extends React.Component { let tournamentStatistics = { tournament: { code: 'abcd1234', - description: '', + description: 'The Overwatch League Season 2 Stage 2', id: 0xa1, name: 'Overwatch League Season 2019 Stage 1', owner_username: 'Blizzard Entertainment Inc.', @@ -233,14 +235,20 @@ class StatisticsTournamentPage extends React.Component { }; return ( -
+
{tournamentStatistics.tournament.name}: turnie.re - - - + +
+ +
+ + + +
+
); @@ -248,3 +256,33 @@ class StatisticsTournamentPage extends React.Component { } export default connect()(StatisticsTournamentPage); + +class PrivateTournamentInformationView extends React.Component { + + render() { + const { tournament, isSignedIn, username } = this.props; + + return ( + +

{tournament.description}

+ + + {tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} + + Turnier-Code: {tournament.code} + von {tournament.owner_username} + +
+ ); + } +} + +function mapStateToPrivateTournamentInformationViewProps(state) { + const { isSignedIn, username } = state.userinfo; + return { isSignedIn, username }; +} + +const TournamentInformationView = connect( + mapStateToPrivateTournamentInformationViewProps +)(PrivateTournamentInformationView); + From 435f24cef87fbab86bbbbf87194c1fd11d539aed Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 08:19:36 +0200 Subject: [PATCH 05/37] Add button to get directly back to the tournament --- pages/tournament-statistics.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index ef719ed..ca651bd 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -92,7 +92,7 @@ class StatisticsTournamentPage extends React.Component { let tournamentStatistics = { tournament: { code: 'abcd1234', - description: 'The Overwatch League Season 2 Stage 2', + description: 'The Overwatch League Season 2 Stage 1', id: 0xa1, name: 'Overwatch League Season 2019 Stage 1', owner_username: 'Blizzard Entertainment Inc.', @@ -264,6 +264,7 @@ class PrivateTournamentInformationView extends React.Component { return ( +

{tournament.description}

@@ -286,3 +287,9 @@ const TournamentInformationView = connect( mapStateToPrivateTournamentInformationViewProps )(PrivateTournamentInformationView); +class TournamentButton extends React.Component { + render() { + const { id } = this.props; + return Zum Turnier; + } +} From 3bc7768bece740d75ea7edf70e12b68d05a71a41 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 08:37:44 +0200 Subject: [PATCH 06/37] Add button to return to tournament from statistics --- pages/tournament.js | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/pages/tournament.js b/pages/tournament.js index 8cf898c..bd20953 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -24,7 +24,7 @@ class PrivateTournamentPage extends React.Component { // TODO: Change href-prop of the anchor tag to contain the tournament code return (
- +

{description}

@@ -50,6 +50,16 @@ function mapStateToTournamentPageProperties(state) { const TournamentPage = connect(mapStateToTournamentPageProperties)(PrivateTournamentPage); +function ButtonsBadge(props) { + const { id, ownerName, isSignedIn, username } = props; + return ( +
+ + +
+ ); +} + function EditButton(props) { const {id, ownerName, isSignedIn, username} = props; @@ -60,6 +70,11 @@ function EditButton(props) { } } +function StatisticsButton(props) { + const { id } = props; + return Statistiken zum Turnier; +} + function getLevelName(levelNumber) { const names = ['Finale', 'Halbfinale', 'Viertelfinale', 'Achtelfinale']; if (levelNumber < names.length) { From d857a4e1592cfe2184d2aa0746afe27edf698a38 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 08:42:50 +0200 Subject: [PATCH 07/37] Properly style the buttons on the tournament and its statistics --- pages/tournament-statistics.js | 3 ++- pages/tournament.js | 44 ++++++++++++++++++++++++++++++---- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index ca651bd..e3d0580 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -2,6 +2,7 @@ import Head from 'next/head'; import React from 'react'; import { connect } from 'react-redux'; import { + Button, Card, CardBody, Container, @@ -290,6 +291,6 @@ const TournamentInformationView = connect( class TournamentButton extends React.Component { render() { const { id } = this.props; - return Zum Turnier; + return ; } } diff --git a/pages/tournament.js b/pages/tournament.js index bd20953..ba65366 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -1,3 +1,4 @@ +<<<<<<< HEAD import Head from 'next/head'; import React from 'react'; import {connect} from 'react-redux'; @@ -9,6 +10,39 @@ import {TurniereNavigation} from '../js/components/Navigation'; import {BigImage} from '../js/components/BigImage'; import {getState} from '../js/api'; import {getRequest} from '../js/redux/backendApi'; +======= +import Head from 'next/head'; +import React from 'react'; +import { connect } from 'react-redux'; +import { + Button, + ButtonGroup, + Card, + CardBody, + Col, + Container, + Input, + InputGroup, + InputGroupAddon, + ListGroup, + ListGroupItem, + Modal, + ModalBody, + ModalFooter, + ModalHeader, + Row, + Table +} from 'reactstrap'; + +import { ErrorPageComponent } from '../js/components/ErrorComponents'; +import { Footer } from '../js/components/Footer'; +import { TurniereNavigation } from '../js/components/Navigation'; +import { BigImage } from '../js/components/BigImage'; +import { + getRequest, + getState +} from '../js/api'; +>>>>>>> Properly style the buttons on the tournament and its statistics import 'bootstrap/dist/css/bootstrap.min.css'; @@ -53,18 +87,18 @@ const TournamentPage = connect(mapStateToTournamentPageProperties)(PrivateTourna function ButtonsBadge(props) { const { id, ownerName, isSignedIn, username } = props; return ( -
+ -
+ ); } function EditButton(props) { const {id, ownerName, isSignedIn, username} = props; - if (isSignedIn && ownerName === username) { - return (Turnier bearbeiten); + if(isSignedIn && ownerName === username) { + return (); } else { return null; } @@ -72,7 +106,7 @@ function EditButton(props) { function StatisticsButton(props) { const { id } = props; - return Statistiken zum Turnier; + return ; } function getLevelName(levelNumber) { From f2f72630954f0f73dfd92366c9468c5d2801840a Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 08:48:02 +0200 Subject: [PATCH 08/37] Fix a bug preventing the favicon from showing on certain sites --- pages/_app.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pages/_app.js b/pages/_app.js index ac91bd6..a2e98b1 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -15,12 +15,12 @@ class TurniereApp extends App { render() { const {Component, pageProps, reduxStore} = this.props; return ( - - - - - - ); + + + + + +
); } } From c66f9cf12873a12a378edcacb3f254160685a21f Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 08:58:43 +0200 Subject: [PATCH 09/37] Remove the grey background from statistics view --- pages/tournament-statistics.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index e3d0580..a92cbd6 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -244,11 +244,9 @@ class StatisticsTournamentPage extends React.Component {
-
- - - -
+ + +
From 9a8230f2548f8cf2ce2d4918d8abfd4a55c55d99 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 09:50:49 +0200 Subject: [PATCH 10/37] Add rank to the current standings --- pages/tournament-statistics.js | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index a92cbd6..79fe188 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -25,6 +25,7 @@ class TeamRow extends React.Component { render() { return (
+ @@ -64,10 +65,11 @@ class StatisticsComponent extends React.Component { return ( -

Turnier-Statistiken für {this.props.data.tournament.name}

+

Aktuelle Rangliste

Team NameMatch DifferenzPunkt Differenz
Team NameMatch DifferenzPunkt Differenz
{ this.props.teamToShow.rank } {this.findTeam(this.props.teams, this.props.teamToShow.team).name} { this.props.teamToShow.winlossdifferential } { this.props.teamToShow.pointDifferential }
+ @@ -125,101 +127,121 @@ class StatisticsTournamentPage extends React.Component { { winlossdifferential: 7, pointDifferential: 16, + rank: 2, team: 0x1234 // New York Excelsior }, { winlossdifferential: -1, pointDifferential: 1, + rank: 10, team: 0x1235 // Los Angeles Gladiators }, { winlossdifferential: 1, pointDifferential: 5, + rank: 6, team: 0x1236 // San Francisco Shock }, { winlossdifferential: 7, pointDifferential: 18, + rank: 1, team: 0x1237 // Vancouver Titans }, { winlossdifferential: -1, pointDifferential: -4, + rank: 13, team: 0x1238 // London Spitfire }, { winlossdifferential: 1, pointDifferential: 0, + rank: 9, team: 0x1239 //Dallas Fuel }, { winlossdifferential: -1, pointDifferential: -8, + rank: 16, team: 0x123a // Chengdu Hunters }, { winlossdifferential: 1, pointDifferential: 3, + rank: 8, team: 0x123b // Boston Uprising }, { winlossdifferential: -1, pointDifferential: -8, + rank: 17, team: 0x123c // Paris Eternal }, { winlossdifferential: 3, pointDifferential: 5, + rank: 3, team: 0x123d // Philadelphia Fusion }, { winlossdifferential: -1, pointDifferential: -4, + rank: 14, team: 0x123e // Hangzhou Spark }, { winlossdifferential: -1, pointDifferential: -3, + rank: 12, team: 0x123f // Houston Outlaws }, { winlossdifferential: -1, pointDifferential: -4, + rank: 15, team: 0x1240 // Shanghai Dragons }, { winlossdifferential: -7, pointDifferential: -9, + rank: 20, team: 0x1241 // Los Angeles Valiant }, { winlossdifferential: 1, pointDifferential: 5, + rank: 7, team: 0x1242 // Seoul Dynasty }, { winlossdifferential: 1, pointDifferential: 6, + rank: 5, team: 0x1243 // Atlanta Reign }, { winlossdifferential: 3, pointDifferential: 5, + rank: 4, team: 0x1244 // Toronto Defiant }, { winlossdifferential: -5, pointDifferential: -12, + rank: 19, team: 0x1245 // Florida Mayhem }, { winlossdifferential: -5, pointDifferential: -11, + rank: 18, team: 0x1246 // Washington Justice }, { winlossdifferential: -1, pointDifferential: -1, + rank: 11, team: 0x1247 // Guangzhou Charge } ], From 287ffe6cc52ad7bba281218ea43391b6bff33cc4 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 09:54:49 +0200 Subject: [PATCH 11/37] Sort performances by their rank and not by their differences --- pages/tournament-statistics.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 79fe188..575bdc7 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -58,9 +58,7 @@ class StatisticsComponent extends React.Component { * comparison(p1, p2) = 0 => p1 = p2 * comparison(p1, p2) > 0 => p1 > p2 */ - let sortedPerformances = sort(performances, (p1, p2) => { - return (p2.winlossdifferential - p1.winlossdifferential) * 100 + (p2.pointDifferential - p1.pointDifferential); - }, Order.descending); + let sortedPerformances = sort(performances, (p1, p2) => p1.rank - p2.rank, Order.descending); return ( From b1810fb2ee7ca51d68c59ef6517c41b58cedec19 Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 10:35:59 +0200 Subject: [PATCH 12/37] Make current standings table collapsible --- pages/tournament-statistics.js | 36 ++++++++++++++++++++++++++-- static/css/tournament-statistics.css | 4 ++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 static/css/tournament-statistics.css diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 575bdc7..6a1e3d4 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -16,6 +16,7 @@ import { BigImage } from '../js/components/BigImage'; import { Footer } from '../js/components/Footer'; import { Order, sort } from '../js/utils/sort'; +import '../static/css/tournament-statistics.css'; class TeamRow extends React.Component { constructor(props) { @@ -48,6 +49,11 @@ class StatisticsComponent extends React.Component { constructor(props) { super(props); + + this.state = { + showFullTable: false + }; + this.toggleShowFullTable = this.toggleShowFullTable.bind(this); } render() { @@ -72,15 +78,41 @@ class StatisticsComponent extends React.Component { - { sortedPerformances.map((team, index) => ( + { map(sortedPerformances, (team, index) => ( - )) } + ), 0, (this.state.showFullTable)? undefined : 3) } + + +
# Team Name Match Differenz Punkt DifferenzMatch Differenz Punkt Differenz
+ +
); } + + toggleShowFullTable() { + this.setState({ showFullTable: !this.state.showFullTable }); + } +} + +function map(arr, func, start, end) { + return arr.slice(start, end).map(func); +} + +class TableButton extends React.Component { + + render() { + const { isFullTableShown } = this.props; + + if(isFullTableShown) { + return ; + } else { + return ; + } + } } class StatisticsTournamentPage extends React.Component { diff --git a/static/css/tournament-statistics.css b/static/css/tournament-statistics.css new file mode 100644 index 0000000..cdb0f18 --- /dev/null +++ b/static/css/tournament-statistics.css @@ -0,0 +1,4 @@ + +.table-final-btn { + width: 100%; +} \ No newline at end of file From 25dfd57708f73c76a005b876deca01373a11debc Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 13:39:47 +0200 Subject: [PATCH 13/37] Add a client side animation of the collapse of the current standings table --- pages/tournament-statistics.js | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 6a1e3d4..e7700ab 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -5,6 +5,7 @@ import { Button, Card, CardBody, + Collapse, Container, ListGroup, ListGroupItem, @@ -71,22 +72,31 @@ class StatisticsComponent extends React.Component {

Aktuelle Rangliste

- + + + { map(sortedPerformances, (team, index) => ( - ), 0, (this.state.showFullTable)? undefined : 3) } + ), 0, 3) } + + + { map(sortedPerformances, (team, index) => ( + + ), 3) } + + - +
# Team Name Match Differenz Punkt Differenz
From dd7168da4f39d2f251912d6e2e2ca44f210a376d Mon Sep 17 00:00:00 2001 From: Jonny Date: Thu, 2 May 2019 16:25:21 +0200 Subject: [PATCH 14/37] Add most / least dominant team and styling for statistics --- pages/tournament-statistics.js | 61 ++++++++++++++++++++++------ static/css/tournament-statistics.css | 14 ++++++- 2 files changed, 62 insertions(+), 13 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index e7700ab..18ae0ea 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -5,10 +5,13 @@ import { Button, Card, CardBody, + CardTitle, + Col, Collapse, Container, ListGroup, ListGroupItem, + Row, Table } from 'reactstrap'; @@ -28,7 +31,7 @@ class TeamRow extends React.Component { return ( { this.props.teamToShow.rank } - {this.findTeam(this.props.teams, this.props.teamToShow.team).name} + {findTeam(this.props.teams, this.props.teamToShow.team).name} { this.props.teamToShow.winlossdifferential } { this.props.teamToShow.pointDifferential } @@ -36,17 +39,41 @@ class TeamRow extends React.Component { } - findTeam(teams, id) { - for(let i = 0; i < teams.length; i++) { - if(teams[i].id === id) { - return teams[i]; - } +} + +function findTeam(teams, id) { + for(let i = 0; i < teams.length; i++) { + if(teams[i].id === id) { + return teams[i]; } - return null; + } + return null; +} + + +class DominanceShower extends React.Component { + + render() { + return ( + + + {this.props.title} + + + + + + + + +
{findTeam(this.props.teams, this.props.stats.id).name}
{this.props.stats.pointsMade}{this.props.stats.pointsReceived}
+
+
+ ); } } -class StatisticsComponent extends React.Component { +class StandingsTable extends React.Component { constructor(props) { super(props); @@ -71,7 +98,7 @@ class StatisticsComponent extends React.Component {

Aktuelle Rangliste

- +
@@ -118,9 +145,9 @@ class TableButton extends React.Component { const { isFullTableShown } = this.props; if(isFullTableShown) { - return ; + return ; } else { - return ; + return ; } } } @@ -307,7 +334,17 @@ class StatisticsTournamentPage extends React.Component {
- + +
+ + + + + + + + +
diff --git a/static/css/tournament-statistics.css b/static/css/tournament-statistics.css index cdb0f18..f6dacdb 100644 --- a/static/css/tournament-statistics.css +++ b/static/css/tournament-statistics.css @@ -1,4 +1,16 @@ .table-final-btn { width: 100%; -} \ No newline at end of file +} + +.wins { + color: #64c100; +} + +.losses { + color: #f21a1e; +} + +.table-no-margin{ + margin: 0; +} From 9fc909e257f598088afecf61ea6b97beb7edf259 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 00:52:07 +0200 Subject: [PATCH 15/37] Extract the tournament information view for more consisten looks --- js/components/TournamentInformationView.js | 116 +++++++++++++++++++++ pages/tournament-statistics.js | 40 +------ pages/tournament.js | 74 +------------ 3 files changed, 121 insertions(+), 109 deletions(-) create mode 100644 js/components/TournamentInformationView.js diff --git a/js/components/TournamentInformationView.js b/js/components/TournamentInformationView.js new file mode 100644 index 0000000..3d6622b --- /dev/null +++ b/js/components/TournamentInformationView.js @@ -0,0 +1,116 @@ +import React from 'react'; +import { connect } from 'react-redux'; +import { + Button, + ButtonGroup, + Col, + Container, + ListGroup, + ListGroupItem +} from 'reactstrap'; + + +class PrivateTournamentInformationView extends React.Component { + + render() { + const { tournament, isSignedIn, username, currentpage } = this.props; + + return ( + + + + +

{tournament.description}

+ + + {tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} + + Turnier-Code: {tournament.code} + von {tournament.owner_username} + +
+ ); + } +} + +function mapStateToPrivateTournamentInformationViewProps(state) { + const { isSignedIn, username } = state.userinfo; + return { isSignedIn, username }; +} + +export const TournamentInformationView = connect( + mapStateToPrivateTournamentInformationViewProps +)(PrivateTournamentInformationView); + +function ButtonsBadge(props) { + const { id, ownerName, isSignedIn, username, currentpage } = props; + + switch(currentpage) { + case 'statistics': + return ( + + + + + ); + case 'tournament': + return ( + + + + + ); + case 'edit': + return ( + + + + + ); + default: return null; + } +} + +function TournamentButton(props) { + const { id } = props; + return ; +} + +function EditButton(props) { + const { id, ownerName, isSignedIn, username } = props; + + if(isSignedIn && ownerName === username) { + return ( + + ); + } else { + return null; + } +} + +function StatisticsButton(props) { + const { id } = props; + return ; +} + + + +/* + + +

{description}

+ + + {isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} + + Turnier-Code: {code} + von {ownerUsername} + +
+ +*/ diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 18ae0ea..6ef8f0e 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -16,6 +16,7 @@ import { } from 'reactstrap'; import { TurniereNavigation } from '../js/components/Navigation'; +import { TournamentInformationView } from '../js/components/TournamentInformationView'; import { BigImage } from '../js/components/BigImage'; import { Footer } from '../js/components/Footer'; import { Order, sort } from '../js/utils/sort'; @@ -332,7 +333,7 @@ class StatisticsTournamentPage extends React.Component {
- +
@@ -354,40 +355,3 @@ class StatisticsTournamentPage extends React.Component { } export default connect()(StatisticsTournamentPage); - -class PrivateTournamentInformationView extends React.Component { - - render() { - const { tournament, isSignedIn, username } = this.props; - - return ( - - -

{tournament.description}

- - - {tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} - - Turnier-Code: {tournament.code} - von {tournament.owner_username} - -
- ); - } -} - -function mapStateToPrivateTournamentInformationViewProps(state) { - const { isSignedIn, username } = state.userinfo; - return { isSignedIn, username }; -} - -const TournamentInformationView = connect( - mapStateToPrivateTournamentInformationViewProps -)(PrivateTournamentInformationView); - -class TournamentButton extends React.Component { - render() { - const { id } = this.props; - return ; - } -} diff --git a/pages/tournament.js b/pages/tournament.js index ba65366..6066739 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -1,4 +1,3 @@ -<<<<<<< HEAD import Head from 'next/head'; import React from 'react'; import {connect} from 'react-redux'; @@ -8,41 +7,9 @@ import {ErrorPageComponent} from '../js/components/ErrorComponents'; import {Footer} from '../js/components/Footer'; import {TurniereNavigation} from '../js/components/Navigation'; import {BigImage} from '../js/components/BigImage'; +import {TournamentInformationView} from '../js/components/TournamentInformationView'; import {getState} from '../js/api'; import {getRequest} from '../js/redux/backendApi'; -======= -import Head from 'next/head'; -import React from 'react'; -import { connect } from 'react-redux'; -import { - Button, - ButtonGroup, - Card, - CardBody, - Col, - Container, - Input, - InputGroup, - InputGroupAddon, - ListGroup, - ListGroupItem, - Modal, - ModalBody, - ModalFooter, - ModalHeader, - Row, - Table -} from 'reactstrap'; - -import { ErrorPageComponent } from '../js/components/ErrorComponents'; -import { Footer } from '../js/components/Footer'; -import { TurniereNavigation } from '../js/components/Navigation'; -import { BigImage } from '../js/components/BigImage'; -import { - getRequest, - getState -} from '../js/api'; ->>>>>>> Properly style the buttons on the tournament and its statistics import 'bootstrap/dist/css/bootstrap.min.css'; @@ -57,17 +24,7 @@ class PrivateTournamentPage extends React.Component { // TODO: Change href-prop of the anchor tag to contain the tournament code return (
- - -

{description}

- - - {isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} - - Turnier-Code: {code} - von {ownerUsername} - -
+
{playoffStages.map(stage => - - - - ); -} - -function EditButton(props) { - const {id, ownerName, isSignedIn, username} = props; - - if(isSignedIn && ownerName === username) { - return (); - } else { - return null; - } -} - -function StatisticsButton(props) { - const { id } = props; - return ; -} - function getLevelName(levelNumber) { const names = ['Finale', 'Halbfinale', 'Viertelfinale', 'Achtelfinale']; if (levelNumber < names.length) { @@ -153,7 +85,7 @@ function convertTournament(apiTournament) { description: apiTournament.description, name: apiTournament.name, isPublic: apiTournament.public, - ownerUsername: apiTournament.owner_username, + owner_username: apiTournament.owner_username, groupStage: groupStage, playoffStages: playoffStages }; From a38624fd5bca04922f3953839547712ca9e86e18 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 01:07:50 +0200 Subject: [PATCH 16/37] Adjust style of the tournament information view --- js/components/TournamentInformationView.js | 68 +++++++++------------- 1 file changed, 29 insertions(+), 39 deletions(-) diff --git a/js/components/TournamentInformationView.js b/js/components/TournamentInformationView.js index 3d6622b..99c465c 100644 --- a/js/components/TournamentInformationView.js +++ b/js/components/TournamentInformationView.js @@ -6,7 +6,8 @@ import { Col, Container, ListGroup, - ListGroupItem + ListGroupItem, + Row } from 'reactstrap'; @@ -17,22 +18,27 @@ class PrivateTournamentInformationView extends React.Component { return ( - - - -

{tournament.description}

- - - {tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} - - Turnier-Code: {tournament.code} - von {tournament.owner_username} - + +
+ +

{tournament.description}

+ +
+ + + {tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} + + Turnier-Code: {tournament.code} + von {tournament.owner_username} + + + ); } @@ -53,21 +59,21 @@ function ButtonsBadge(props) { switch(currentpage) { case 'statistics': return ( - + ); case 'tournament': return ( - + ); case 'edit': return ( - + @@ -78,7 +84,7 @@ function ButtonsBadge(props) { function TournamentButton(props) { const { id } = props; - return ; + return ; } function EditButton(props) { @@ -86,7 +92,7 @@ function EditButton(props) { if(isSignedIn && ownerName === username) { return ( - + ); } else { return null; @@ -95,22 +101,6 @@ function EditButton(props) { function StatisticsButton(props) { const { id } = props; - return ; + return ; } - - -/* - - -

{description}

- - - {isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} - - Turnier-Code: {code} - von {ownerUsername} - -
- -*/ From 7c1928dce34966af8412de17daa1b182569d4708 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 01:20:59 +0200 Subject: [PATCH 17/37] Adjust the style of the dominance shower view --- pages/tournament-statistics.js | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 6ef8f0e..221fe49 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -56,17 +56,23 @@ class DominanceShower extends React.Component { render() { return ( - + {this.props.title}
#
- - - - - - - + + + + + + + + + + + + +
{findTeam(this.props.teams, this.props.stats.id).name}
{this.props.stats.pointsMade}{this.props.stats.pointsReceived}
{findTeam(this.props.teams, this.props.stats.id).name}
{this.props.stats.pointsMade}{this.props.stats.pointsReceived}
Punkte erzieltPunkte kassiert
@@ -96,7 +102,7 @@ class StandingsTable extends React.Component { let sortedPerformances = sort(performances, (p1, p2) => p1.rank - p2.rank, Order.descending); return ( - +

Aktuelle Rangliste

@@ -120,7 +126,7 @@ class StandingsTable extends React.Component { - From d557a21d900a1321bed19bc6415fedbdce61e6ce Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 12:00:25 +0200 Subject: [PATCH 18/37] Extract the ranged map function --- js/utils/rangedmap.js | 4 ++++ pages/tournament-statistics.js | 7 +++---- 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 js/utils/rangedmap.js diff --git a/js/utils/rangedmap.js b/js/utils/rangedmap.js new file mode 100644 index 0000000..1373ebe --- /dev/null +++ b/js/utils/rangedmap.js @@ -0,0 +1,4 @@ + +export function rangedmap(arr, func, start, end) { + return arr.slice(start, end).map(func); +} diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 221fe49..dcfc34f 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -19,6 +19,7 @@ import { TurniereNavigation } from '../js/components/Navigation'; import { TournamentInformationView } from '../js/components/TournamentInformationView'; import { BigImage } from '../js/components/BigImage'; import { Footer } from '../js/components/Footer'; +import { rangedmap } from '../js/utils/rangedmap'; import { Order, sort } from '../js/utils/sort'; import '../static/css/tournament-statistics.css'; @@ -115,12 +116,12 @@ class StandingsTable extends React.Component { - { map(sortedPerformances, (team, index) => ( + { rangedmap(sortedPerformances, (team, index) => ( ), 0, 3) } - { map(sortedPerformances, (team, index) => ( + { rangedmap(sortedPerformances, (team, index) => ( ), 3) } @@ -142,8 +143,6 @@ class StandingsTable extends React.Component { } } -function map(arr, func, start, end) { - return arr.slice(start, end).map(func); } class TableButton extends React.Component { From e07378ba9268046bab0348eff90b9e7fbe0be044 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 12:19:27 +0200 Subject: [PATCH 19/37] Extract the findTeam-function --- js/utils/findTeam.js | 9 +++++++++ pages/tournament-statistics.js | 11 +---------- 2 files changed, 10 insertions(+), 10 deletions(-) create mode 100644 js/utils/findTeam.js diff --git a/js/utils/findTeam.js b/js/utils/findTeam.js new file mode 100644 index 0000000..1a9c0e6 --- /dev/null +++ b/js/utils/findTeam.js @@ -0,0 +1,9 @@ + +export function findTeam(teams, id) { + for(let i = 0; i < teams.length; i++) { + if(teams[i].id === id) { + return teams[i]; + } + } + return null; +} diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index dcfc34f..8457f5e 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -19,6 +19,7 @@ import { TurniereNavigation } from '../js/components/Navigation'; import { TournamentInformationView } from '../js/components/TournamentInformationView'; import { BigImage } from '../js/components/BigImage'; import { Footer } from '../js/components/Footer'; +import { findTeam } from '../js/utils/findTeam'; import { rangedmap } from '../js/utils/rangedmap'; import { Order, sort } from '../js/utils/sort'; @@ -43,16 +44,6 @@ class TeamRow extends React.Component { } -function findTeam(teams, id) { - for(let i = 0; i < teams.length; i++) { - if(teams[i].id === id) { - return teams[i]; - } - } - return null; -} - - class DominanceShower extends React.Component { render() { From 3e9307a79d9742c2f3b7b7bf770871bbef3a1ecb Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 12:43:27 +0200 Subject: [PATCH 20/37] Remove custom css and replace it with bootstrap classes --- pages/tournament-statistics.js | 44 ++++++++++++---------------- static/css/tournament-statistics.css | 16 ---------- 2 files changed, 19 insertions(+), 41 deletions(-) delete mode 100644 static/css/tournament-statistics.css diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 8457f5e..0a33e5b 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -23,27 +23,6 @@ import { findTeam } from '../js/utils/findTeam'; import { rangedmap } from '../js/utils/rangedmap'; import { Order, sort } from '../js/utils/sort'; -import '../static/css/tournament-statistics.css'; - -class TeamRow extends React.Component { - constructor(props) { - super(props); - } - - render() { - return ( - - - - - - - ); - } - - -} - class DominanceShower extends React.Component { render() { @@ -51,7 +30,7 @@ class DominanceShower extends React.Component { {this.props.title} -
+
{ this.props.teamToShow.rank }{findTeam(this.props.teams, this.props.teamToShow.team).name}{ this.props.teamToShow.winlossdifferential }{ this.props.teamToShow.pointDifferential }
+
@@ -97,7 +76,7 @@ class StandingsTable extends React.Component {

Aktuelle Rangliste

-
{findTeam(this.props.teams, this.props.stats.id).name}
+
@@ -134,6 +113,21 @@ class StandingsTable extends React.Component { } } +class TeamRow extends React.Component { + constructor(props) { + super(props); + } + + render() { + return ( + + + + + + + ); + } } class TableButton extends React.Component { @@ -142,9 +136,9 @@ class TableButton extends React.Component { const { isFullTableShown } = this.props; if(isFullTableShown) { - return ; + return ; } else { - return ; + return ; } } } diff --git a/static/css/tournament-statistics.css b/static/css/tournament-statistics.css deleted file mode 100644 index f6dacdb..0000000 --- a/static/css/tournament-statistics.css +++ /dev/null @@ -1,16 +0,0 @@ - -.table-final-btn { - width: 100%; -} - -.wins { - color: #64c100; -} - -.losses { - color: #f21a1e; -} - -.table-no-margin{ - margin: 0; -} From beffd2485579b7b32e9db26647489cc19bf701df Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 12:57:20 +0200 Subject: [PATCH 21/37] Extract the standings table view --- js/components/StandingsTable.js | 104 +++++++++++++++++++++ js/components/TournamentInformationView.js | 44 ++++----- pages/tournament-statistics.js | 99 +------------------- pages/tournament.js | 4 +- 4 files changed, 129 insertions(+), 122 deletions(-) create mode 100644 js/components/StandingsTable.js diff --git a/js/components/StandingsTable.js b/js/components/StandingsTable.js new file mode 100644 index 0000000..ecdb6ce --- /dev/null +++ b/js/components/StandingsTable.js @@ -0,0 +1,104 @@ +import React from 'react'; +import { + Button, + Card, + CardBody, + Collapse, + Table +} from 'reactstrap'; + +import { rangedmap } from '../utils/rangedmap'; +import { findTeam } from '../utils/findTeam'; +import { Order, sort } from '../utils/sort'; + +export class StandingsTable extends React.Component { + + constructor(props) { + super(props); + + this.state = { + showFullTable: false + }; + this.toggleShowFullTable = this.toggleShowFullTable.bind(this); + } + + render() { + let performances = this.props.data.groupPhasePerformances; + + /** + * comparison(p1, p2) < 0 => p1 < p2 + * comparison(p1, p2) = 0 => p1 = p2 + * comparison(p1, p2) > 0 => p1 > p2 + */ + let sortedPerformances = sort(performances, (p1, p2) => p1.rank - p2.rank, Order.descending); + + return ( + + +

Aktuelle Rangliste

+
#
{ this.props.teamToShow.rank }{findTeam(this.props.teams, this.props.teamToShow.team).name}{ this.props.teamToShow.winlossdifferential }{ this.props.teamToShow.pointDifferential }
+ + + + + + + + + + { rangedmap(sortedPerformances, (team, index) => ( + + ), 0, 3) } + + + { rangedmap(sortedPerformances, (team, index) => ( + + ), 3) } + + + + + + +
#Team NameMatch DifferenzPunkt Differenz
+ +
+
+
+ ); + } + + toggleShowFullTable() { + this.setState({ showFullTable: !this.state.showFullTable }); + } +} + +class TeamRow extends React.Component { + constructor(props) { + super(props); + } + + render() { + return ( + + { this.props.teamToShow.rank } + {findTeam(this.props.teams, this.props.teamToShow.team).name} + { this.props.teamToShow.winlossdifferential } + { this.props.teamToShow.pointDifferential } + + ); + } +} + +class TableButton extends React.Component { + + render() { + const { isFullTableShown } = this.props; + + if(isFullTableShown) { + return ; + } else { + return ; + } + } +} diff --git a/js/components/TournamentInformationView.js b/js/components/TournamentInformationView.js index 99c465c..c34b4b4 100644 --- a/js/components/TournamentInformationView.js +++ b/js/components/TournamentInformationView.js @@ -57,28 +57,28 @@ function ButtonsBadge(props) { const { id, ownerName, isSignedIn, username, currentpage } = props; switch(currentpage) { - case 'statistics': - return ( - - - - - ); - case 'tournament': - return ( - - - - - ); - case 'edit': - return ( - - - - - ); - default: return null; + case 'statistics': + return ( + + + + + ); + case 'tournament': + return ( + + + + + ); + case 'edit': + return ( + + + + + ); + default: return null; } } diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 0a33e5b..e65710c 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -2,15 +2,11 @@ import Head from 'next/head'; import React from 'react'; import { connect } from 'react-redux'; import { - Button, Card, CardBody, CardTitle, Col, - Collapse, Container, - ListGroup, - ListGroupItem, Row, Table } from 'reactstrap'; @@ -18,10 +14,9 @@ import { import { TurniereNavigation } from '../js/components/Navigation'; import { TournamentInformationView } from '../js/components/TournamentInformationView'; import { BigImage } from '../js/components/BigImage'; +import { StandingsTable } from '../js/components/StandingsTable'; import { Footer } from '../js/components/Footer'; import { findTeam } from '../js/utils/findTeam'; -import { rangedmap } from '../js/utils/rangedmap'; -import { Order, sort } from '../js/utils/sort'; class DominanceShower extends React.Component { @@ -51,98 +46,6 @@ class DominanceShower extends React.Component { } } -class StandingsTable extends React.Component { - - constructor(props) { - super(props); - - this.state = { - showFullTable: false - }; - this.toggleShowFullTable = this.toggleShowFullTable.bind(this); - } - - render() { - let performances = this.props.data.groupPhasePerformances; - - /** - * comparison(p1, p2) < 0 => p1 < p2 - * comparison(p1, p2) = 0 => p1 = p2 - * comparison(p1, p2) > 0 => p1 > p2 - */ - let sortedPerformances = sort(performances, (p1, p2) => p1.rank - p2.rank, Order.descending); - - return ( - - -

Aktuelle Rangliste

- - - - - - - - - - - { rangedmap(sortedPerformances, (team, index) => ( - - ), 0, 3) } - - - { rangedmap(sortedPerformances, (team, index) => ( - - ), 3) } - - - - - - -
#Team NameMatch DifferenzPunkt Differenz
- -
-
-
- ); - } - - toggleShowFullTable() { - this.setState({ showFullTable: !this.state.showFullTable }); - } -} - -class TeamRow extends React.Component { - constructor(props) { - super(props); - } - - render() { - return ( - - { this.props.teamToShow.rank } - {findTeam(this.props.teams, this.props.teamToShow.team).name} - { this.props.teamToShow.winlossdifferential } - { this.props.teamToShow.pointDifferential } - - ); - } -} - -class TableButton extends React.Component { - - render() { - const { isFullTableShown } = this.props; - - if(isFullTableShown) { - return ; - } else { - return ; - } - } -} - class StatisticsTournamentPage extends React.Component { static async getInitialProps({query}) { diff --git a/pages/tournament.js b/pages/tournament.js index 6066739..13d6b6d 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -19,9 +19,9 @@ import {Match} from '../js/components/Match'; class PrivateTournamentPage extends React.Component { render() { - const {id, description, isPublic, code, ownerUsername, playoffStages} = this.props.tournament; + const {ownerUsername, playoffStages} = this.props.tournament; const {isSignedIn, username} = this.props; - + // TODO: Change href-prop of the anchor tag to contain the tournament code return (
From 2ea9668f3820a7944f38679960741382e79b2576 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 13:07:17 +0200 Subject: [PATCH 22/37] Extract the dominance shower view --- js/components/DominanceShower.js | 37 ++++++++++++++++++++++++++++++++ pages/tournament-statistics.js | 36 ++----------------------------- 2 files changed, 39 insertions(+), 34 deletions(-) create mode 100644 js/components/DominanceShower.js diff --git a/js/components/DominanceShower.js b/js/components/DominanceShower.js new file mode 100644 index 0000000..4abcc58 --- /dev/null +++ b/js/components/DominanceShower.js @@ -0,0 +1,37 @@ +import React from 'react'; +import { + Card, + CardBody, + CardTitle, + Table +} from 'reactstrap'; + +import { findTeam } from '../utils/findTeam'; + +export class DominanceShower extends React.Component { + + render() { + return ( + + + {this.props.title} + + + + + + + + + + + + + + +
{findTeam(this.props.teams, this.props.stats.id).name}
{this.props.stats.pointsMade}{this.props.stats.pointsReceived}
Punkte erzieltPunkte kassiert
+
+
+ ); + } +} diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index e65710c..43b776d 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -2,49 +2,17 @@ import Head from 'next/head'; import React from 'react'; import { connect } from 'react-redux'; import { - Card, - CardBody, - CardTitle, Col, Container, - Row, - Table + Row } from 'reactstrap'; import { TurniereNavigation } from '../js/components/Navigation'; import { TournamentInformationView } from '../js/components/TournamentInformationView'; import { BigImage } from '../js/components/BigImage'; import { StandingsTable } from '../js/components/StandingsTable'; +import { DominanceShower } from '../js/components/DominanceShower'; import { Footer } from '../js/components/Footer'; -import { findTeam } from '../js/utils/findTeam'; - -class DominanceShower extends React.Component { - - render() { - return ( - - - {this.props.title} - - - - - - - - - - - - - - -
{findTeam(this.props.teams, this.props.stats.id).name}
{this.props.stats.pointsMade}{this.props.stats.pointsReceived}
Punkte erzieltPunkte kassiert
-
-
- ); - } -} class StatisticsTournamentPage extends React.Component { From 74a1052e25a822187f9819a065fd7670869abd47 Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 13:13:56 +0200 Subject: [PATCH 23/37] Change for-loop in findTeam to make it more readable --- js/utils/findTeam.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/js/utils/findTeam.js b/js/utils/findTeam.js index 1a9c0e6..24d88b0 100644 --- a/js/utils/findTeam.js +++ b/js/utils/findTeam.js @@ -1,8 +1,8 @@ export function findTeam(teams, id) { - for(let i = 0; i < teams.length; i++) { - if(teams[i].id === id) { - return teams[i]; + for(var team of teams) { + if(team.id === id) { + return team; } } return null; From a05cc768fd1c181857dff617536739db0631b64e Mon Sep 17 00:00:00 2001 From: Jonny Date: Fri, 3 May 2019 13:25:47 +0200 Subject: [PATCH 24/37] Fix a bug which resets the striping after the last element that has not been hidden --- js/components/StandingsTable.js | 8 ++++---- js/utils/rangedmap.js | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/components/StandingsTable.js b/js/components/StandingsTable.js index ecdb6ce..ea461ee 100644 --- a/js/components/StandingsTable.js +++ b/js/components/StandingsTable.js @@ -36,7 +36,7 @@ export class StandingsTable extends React.Component {

Aktuelle Rangliste

- +
@@ -47,12 +47,12 @@ export class StandingsTable extends React.Component { { rangedmap(sortedPerformances, (team, index) => ( - + ), 0, 3) } { rangedmap(sortedPerformances, (team, index) => ( - + ), 3) } @@ -80,7 +80,7 @@ class TeamRow extends React.Component { render() { return ( - + diff --git a/js/utils/rangedmap.js b/js/utils/rangedmap.js index 1373ebe..adedcb6 100644 --- a/js/utils/rangedmap.js +++ b/js/utils/rangedmap.js @@ -1,4 +1,4 @@ export function rangedmap(arr, func, start, end) { - return arr.slice(start, end).map(func); + return arr.slice(start, end).map((element, index) => func(element, start + index)); } From abfded9e0fdcc511d6c2d7b1c185c1ea784a033b Mon Sep 17 00:00:00 2001 From: Jonny Date: Tue, 7 May 2019 11:32:45 +0200 Subject: [PATCH 25/37] Adjust names of the used data to the (expected) backend names --- js/components/DominanceShower.js | 4 +- js/components/StandingsTable.js | 6 +- pages/tournament-statistics.js | 94 ++++++++++++++++---------------- 3 files changed, 52 insertions(+), 52 deletions(-) diff --git a/js/components/DominanceShower.js b/js/components/DominanceShower.js index 4abcc58..405a700 100644 --- a/js/components/DominanceShower.js +++ b/js/components/DominanceShower.js @@ -21,8 +21,8 @@ export class DominanceShower extends React.Component { - - + + diff --git a/js/components/StandingsTable.js b/js/components/StandingsTable.js index ea461ee..2538ed2 100644 --- a/js/components/StandingsTable.js +++ b/js/components/StandingsTable.js @@ -23,7 +23,7 @@ export class StandingsTable extends React.Component { } render() { - let performances = this.props.data.groupPhasePerformances; + let performances = this.props.data.group_phase_performances; /** * comparison(p1, p2) < 0 => p1 < p2 @@ -83,8 +83,8 @@ class TeamRow extends React.Component { - - + + ); } diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 43b776d..23008c1 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -52,118 +52,118 @@ class StatisticsTournamentPage extends React.Component { { id: 0x1246, name: 'Washington Justice' }, { id: 0x1247, name: 'Guangzhou Charge' } ], - groupPhasePerformances: [ + group_phase_performances: [ { - winlossdifferential: 7, - pointDifferential: 16, + win_loss_differential: 7, + point_differential: 16, rank: 2, team: 0x1234 // New York Excelsior }, { - winlossdifferential: -1, - pointDifferential: 1, + win_loss_differential: -1, + point_differential: 1, rank: 10, team: 0x1235 // Los Angeles Gladiators }, { - winlossdifferential: 1, - pointDifferential: 5, + win_loss_differential: 1, + point_differential: 5, rank: 6, team: 0x1236 // San Francisco Shock }, { - winlossdifferential: 7, - pointDifferential: 18, + win_loss_differential: 7, + point_differential: 18, rank: 1, team: 0x1237 // Vancouver Titans }, { - winlossdifferential: -1, - pointDifferential: -4, + win_loss_differential: -1, + point_differential: -4, rank: 13, team: 0x1238 // London Spitfire }, { - winlossdifferential: 1, - pointDifferential: 0, + win_loss_differential: 1, + point_differential: 0, rank: 9, team: 0x1239 //Dallas Fuel }, { - winlossdifferential: -1, - pointDifferential: -8, + win_loss_differential: -1, + point_differential: -8, rank: 16, team: 0x123a // Chengdu Hunters }, { - winlossdifferential: 1, - pointDifferential: 3, + win_loss_differential: 1, + point_differential: 3, rank: 8, team: 0x123b // Boston Uprising }, { - winlossdifferential: -1, - pointDifferential: -8, + win_loss_differential: -1, + point_differential: -8, rank: 17, team: 0x123c // Paris Eternal }, { - winlossdifferential: 3, - pointDifferential: 5, + win_loss_differential: 3, + point_differential: 5, rank: 3, team: 0x123d // Philadelphia Fusion }, { - winlossdifferential: -1, - pointDifferential: -4, + win_loss_differential: -1, + point_differential: -4, rank: 14, team: 0x123e // Hangzhou Spark }, { - winlossdifferential: -1, - pointDifferential: -3, + win_loss_differential: -1, + point_differential: -3, rank: 12, team: 0x123f // Houston Outlaws }, { - winlossdifferential: -1, - pointDifferential: -4, + win_loss_differential: -1, + point_differential: -4, rank: 15, team: 0x1240 // Shanghai Dragons }, { - winlossdifferential: -7, - pointDifferential: -9, + win_loss_differential: -7, + point_differential: -9, rank: 20, team: 0x1241 // Los Angeles Valiant }, { - winlossdifferential: 1, - pointDifferential: 5, + win_loss_differential: 1, + point_differential: 5, rank: 7, team: 0x1242 // Seoul Dynasty }, { - winlossdifferential: 1, - pointDifferential: 6, + win_loss_differential: 1, + point_differential: 6, rank: 5, team: 0x1243 // Atlanta Reign }, { - winlossdifferential: 3, - pointDifferential: 5, + win_loss_differential: 3, + point_differential: 5, rank: 4, team: 0x1244 // Toronto Defiant }, { - winlossdifferential: -5, - pointDifferential: -12, + win_loss_differential: -5, + point_differential: -12, rank: 19, team: 0x1245 // Florida Mayhem }, { - winlossdifferential: -5, - pointDifferential: -11, + win_loss_differential: -5, + point_differential: -11, rank: 18, team: 0x1246 // Washington Justice }, @@ -174,15 +174,15 @@ class StatisticsTournamentPage extends React.Component { team: 0x1247 // Guangzhou Charge } ], - mostDominantTeam: { + most_dominant_team: { id: 0x1234, - pointsMade: 94, - pointsReceived: 3 + points_made: 94, + points_received: 3 }, - leastDominantTeam: { + least_dominant_team: { id: 0x1240, - pointsMade: 2, - pointsReceived: 103 + points_made: 2, + points_received: 103 } }; @@ -198,10 +198,10 @@ class StatisticsTournamentPage extends React.Component { - + - + From 3aab76972b3b1a1f11429d4b731fb7849612d94f Mon Sep 17 00:00:00 2001 From: JP1998 Date: Wed, 29 May 2019 03:58:29 +0200 Subject: [PATCH 26/37] Add redux state and api calls for the statistics --- js/api.js | 67 ++++++++++++++++++++++++++++++++ js/redux/tournamentStatistics.js | 64 ++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 js/redux/tournamentStatistics.js diff --git a/js/api.js b/js/api.js index 3510c72..6f5b9ca 100644 --- a/js/api.js +++ b/js/api.js @@ -6,6 +6,10 @@ import {errorMessages} from './constants'; import {actionTypesUserinfo, defaultStateUserinfo} from './redux/userInfo'; import {actionTypesTournamentinfo, defaultStateTournamentinfo} from './redux/tournamentInfo'; +import { + actionTypesTournamentStatistics, defaultStateTournamentStatistics, + transformTournamentInfoToStatistics, transformTournamentStatsToStatistics +} from './redux/tournamentStatistics'; import {actionTypesTournamentlist, defaultStateTournamentlist} from './redux/tournamentList'; import {deleteRequest, getRequest, patchRequest, postRequest} from './redux/backendApi'; @@ -229,6 +233,51 @@ const reducerTournamentinfo = (state = defaultStateTournamentinfo, action) => { } }; +const reducerTournamentStatistics = (state = defaultStateTournamentStatistics, action) => { + switch (action.type) { + case actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS: + getRequest(action.state, '/tournaments/' + action.parameters.code).then(resp => { + storeOptionalToken(resp); + __store.dispatch({ + type: actionTypesTournamentStatistics.INT_REQUEST_TOURNAMENT_STATISTICS, + parameters: { + code: action.parameters.code, + tournamentInfo: transformTournamentInfoToStatistics(resp.data), + successCallback: action.parameters.successCallback, + errorCallback: action.parameters.errorCallback + } + }); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + return state; + case actionTypesTournamentStatistics.INT_REQUEST_TOURNAMENT_STATISTICS: + getRequest(action.state, '/tournaments/' + action.parameters.code + '/statistics').then(resp => { + storeOptionalToken(resp); + __store.dispatch({ + type: actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS_SUCCESS, + parameters: { + tournamentStatistics: transformTournamentStatsToStatistics(resp.data), + successCallback: action.parameters.successCallback + } + }); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + return Object.assign({}, state, action.parameters.tournamentInfo); + case actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS_SUCCESS: + action.parameters.successCallback(); + return Object.assign({}, state, tournamentStatistics); + default: return state; + } +} + const reducerTournamentlist = (state = defaultStateTournamentlist, action) => { switch (action.type) { case actionTypesTournamentlist.FETCH: @@ -256,12 +305,14 @@ const reducerTournamentlist = (state = defaultStateTournamentlist, action) => { const reducers = { userinfo: reducerUserinfo, tournamentinfo: reducerTournamentinfo, + tournamentStatistics: reducerTournamentStatistics, tournamentlist: reducerTournamentlist }; const defaultApplicationState = { userinfo: defaultStateUserinfo, tournamentinfo: defaultStateTournamentinfo, + tournamentStatistics: defaultStateTournamentStatistics, tournamentlist: defaultStateTournamentlist }; @@ -351,6 +402,18 @@ export function requestTournament(code, successCallback, errorCallback) { }); } +export function requestTournamentStatistics(code, successCallback, errorCallback) { + __store.dispatch({ + type: actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS, + parameters: { + code: code, + successCallback: successCallback, + errorCallback: errorCallback + }, + state: __store.getState() + }); +} + export function updateTeamName(team, successCB, errorCB) { __store.dispatch({ type: actionTypesTournamentinfo.MODIFY_TOURNAMENT, @@ -398,6 +461,10 @@ function rehydrateApplicationState() { type: actionTypesTournamentlist.REHYDRATE, parameters: Object.assign({}, persistedState.tournamentlist) }); + __store.dispatch({ + type: actionTypesTournamentStatistics.REHYDRATE, + parameters: Object.assign({}, persistedState.tournamentstatistics) + }); applicationHydrated = true; } } diff --git a/js/redux/tournamentStatistics.js b/js/redux/tournamentStatistics.js new file mode 100644 index 0000000..cbed36d --- /dev/null +++ b/js/redux/tournamentStatistics.js @@ -0,0 +1,64 @@ +export const actionTypesTournamentinfo = { + 'REQUEST_TOURNAMENT_STATISTICS': 'REQUEST_TOURNAMENT_STATISTICS', + 'INT_REQUEST_TOURNAMENT_STATISTICS': 'INT_REQUEST_TOURNAMENT_STATISTICS', + + 'REQUEST_TOURNAMENT_STATISTICS_SUCCESS': 'REQUEST_TOURNAMENT_STATISTICS_SUCCESS', + + 'REHYDRATE': 'TOURNAMENTINFO_REHYDRATE', + 'CLEAR': 'TOURNAMENTINFO_CLEAR' +}; + +export const defaultStateTournamentinfo = { + code: '', + description: '', + id: -1, + name: '', + ownerUsername: '', + isPublic: '', + + most_dominant_team: {}, + least_dominant_team: {}, + group_phase_performances: [] +}; + + +export function transformTournamentInfoToStatistics(data) { + return { + code: data.code, + description: data.description, + id: data.id, + name: data.name, + ownerUsername: data.owner_username, + isPublic: data.public + }; +} + +export function transformTournamentStatsToStatistics(data) { + const statistics = { + most_dominant_team: { + points_made: data.most_dominant_score.scored_points, + points_received: data.most_dominant_score.received_points, + team_name: data.most_dominant_score.team.name + }, + least_dominant_team: { + points_made: data.least_dominant_score.scored_points, + points_received: data.least_dominant_score.received_points, + team_name: data.least_dominant_score.team.name + }, + group_phase_performances: [] + }; + + for (let i = 0; i < data.group_scores.length; i++) { + let score = data.group_scores[i]; + + statistics.group_phase_performances[i] = { + win_loss_differential: score.group_points, + point_differential: score.scored_points - score.received_points, + rank: i + 1, + team: score.team.name + } + } + + return statistics; +} + From da4b5ac2e5df55b2beabb187143d07cb56e8ea3c Mon Sep 17 00:00:00 2001 From: JP1998 Date: Wed, 29 May 2019 04:03:32 +0200 Subject: [PATCH 27/37] Adjust DominanceShower to the actually implemented API data --- js/components/DominanceShower.js | 4 +--- pages/tournament-statistics.js | 6 ++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/js/components/DominanceShower.js b/js/components/DominanceShower.js index 405a700..01dc571 100644 --- a/js/components/DominanceShower.js +++ b/js/components/DominanceShower.js @@ -6,8 +6,6 @@ import { Table } from 'reactstrap'; -import { findTeam } from '../utils/findTeam'; - export class DominanceShower extends React.Component { render() { @@ -18,7 +16,7 @@ export class DominanceShower extends React.Component {
#
{ this.props.teamToShow.rank } {findTeam(this.props.teams, this.props.teamToShow.team).name} { this.props.teamToShow.winlossdifferential }{findTeam(this.props.teams, this.props.stats.id).name}
{this.props.stats.pointsMade}{this.props.stats.pointsReceived}{this.props.stats.points_made}{this.props.stats.points_received}
Punkte erzielt
{ this.props.teamToShow.rank } {findTeam(this.props.teams, this.props.teamToShow.team).name}{ this.props.teamToShow.winlossdifferential }{ this.props.teamToShow.pointDifferential }{ this.props.teamToShow.win_loss_differential }{ this.props.teamToShow.point_differential }
- + diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 23008c1..a9e765c 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -21,6 +21,7 @@ class StatisticsTournamentPage extends React.Component { } render() { + /* let tournamentStatistics = { tournament: { code: 'abcd1234', @@ -185,6 +186,7 @@ class StatisticsTournamentPage extends React.Component { points_received: 103 } }; + */ return (
@@ -198,10 +200,10 @@ class StatisticsTournamentPage extends React.Component {
- + - + From d24e464f8e2fbce2aaf24116ab9ad84216627bfb Mon Sep 17 00:00:00 2001 From: JP1998 Date: Wed, 29 May 2019 04:06:06 +0200 Subject: [PATCH 28/37] Adjust the title and image header to new API data --- pages/tournament-statistics.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index a9e765c..431a8dd 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -191,12 +191,12 @@ class StatisticsTournamentPage extends React.Component { return (
- {tournamentStatistics.tournament.name}: turnie.re + {tournamentStatistics.name}: turnie.re - +
- +
From e813726f505079d9459cbefc391f0af09dd8a2ac Mon Sep 17 00:00:00 2001 From: JP1998 Date: Wed, 29 May 2019 04:24:39 +0200 Subject: [PATCH 29/37] Adjust the StandingsTable to the new API data format --- js/components/StandingsTable.js | 19 +++------ js/redux/tournamentStatistics.js | 6 +-- js/utils/findTeam.js | 9 ---- js/utils/sort.js | 73 -------------------------------- 4 files changed, 8 insertions(+), 99 deletions(-) delete mode 100644 js/utils/findTeam.js delete mode 100644 js/utils/sort.js diff --git a/js/components/StandingsTable.js b/js/components/StandingsTable.js index 2538ed2..b2db7cb 100644 --- a/js/components/StandingsTable.js +++ b/js/components/StandingsTable.js @@ -8,8 +8,6 @@ import { } from 'reactstrap'; import { rangedmap } from '../utils/rangedmap'; -import { findTeam } from '../utils/findTeam'; -import { Order, sort } from '../utils/sort'; export class StandingsTable extends React.Component { @@ -25,13 +23,6 @@ export class StandingsTable extends React.Component { render() { let performances = this.props.data.group_phase_performances; - /** - * comparison(p1, p2) < 0 => p1 < p2 - * comparison(p1, p2) = 0 => p1 = p2 - * comparison(p1, p2) > 0 => p1 > p2 - */ - let sortedPerformances = sort(performances, (p1, p2) => p1.rank - p2.rank, Order.descending); - return ( @@ -46,13 +37,13 @@ export class StandingsTable extends React.Component { - { rangedmap(sortedPerformances, (team, index) => ( - + { rangedmap(performances, (team, index) => ( + ), 0, 3) } - { rangedmap(sortedPerformances, (team, index) => ( - + { rangedmap(performances, (team, index) => ( + ), 3) } @@ -82,7 +73,7 @@ class TeamRow extends React.Component { return ( - + diff --git a/js/redux/tournamentStatistics.js b/js/redux/tournamentStatistics.js index cbed36d..debf75e 100644 --- a/js/redux/tournamentStatistics.js +++ b/js/redux/tournamentStatistics.js @@ -1,4 +1,4 @@ -export const actionTypesTournamentinfo = { +export const actionTypesTournamentStatistics = { 'REQUEST_TOURNAMENT_STATISTICS': 'REQUEST_TOURNAMENT_STATISTICS', 'INT_REQUEST_TOURNAMENT_STATISTICS': 'INT_REQUEST_TOURNAMENT_STATISTICS', @@ -8,7 +8,7 @@ export const actionTypesTournamentinfo = { 'CLEAR': 'TOURNAMENTINFO_CLEAR' }; -export const defaultStateTournamentinfo = { +export const defaultStateTournamentStatistics = { code: '', description: '', id: -1, @@ -55,7 +55,7 @@ export function transformTournamentStatsToStatistics(data) { win_loss_differential: score.group_points, point_differential: score.scored_points - score.received_points, rank: i + 1, - team: score.team.name + team_name: score.team.name } } diff --git a/js/utils/findTeam.js b/js/utils/findTeam.js deleted file mode 100644 index 24d88b0..0000000 --- a/js/utils/findTeam.js +++ /dev/null @@ -1,9 +0,0 @@ - -export function findTeam(teams, id) { - for(var team of teams) { - if(team.id === id) { - return team; - } - } - return null; -} diff --git a/js/utils/sort.js b/js/utils/sort.js deleted file mode 100644 index 04d8a74..0000000 --- a/js/utils/sort.js +++ /dev/null @@ -1,73 +0,0 @@ - -/** - * Constants for the ordering in which the sorting - * algorithm should bring the elements. - */ -export const Order = { - ascending : 1, - descending: 2 -}; - -/** - * A sorting function that can be used to sort any kind of data - * given an applicable comparator. Said comparator will take in two - * elements of the given array `data`, and produce an integer result - * which can be interpreted as follows: - * ``` - * comparator(a, b) < 0 => a < b - * comparator(a, b) = 0 => a = b - * comparator(a, b) > 0 => a > b - * ``` - * The parameter order should be given as one of the constants in Order. - * Said `order` parameter is optional; it will default to ascending. - * - * @param {T[]} data The array that is to be sorted. - * @param {(T, T) => int} comparator A function which can be used - * to compare any two elemments from the given array. - * @param {int} order The order in which the data should be sorted, - * as defined in Order. - * @return An array with the elements from data sorted in the given order. - */ -export function sort(data, comparator, order) { - if(order === undefined) { - order = Order.ascending; - } - let target = data.slice(); - return sortToTarget(data, target, 0, data.length, comparator, order); -} - -function sortToTarget(data, target, start, end, comparator, order) { - if(end - start < 2) { - return data; - } - - let middle = Math.floor((end + start) / 2); - - sortToTarget(target, data, start, middle, comparator, order); - sortToTarget(target, data, middle, end, comparator, order); - - return merge(data, target, start, middle, end, comparator, order); -} - -function merge(data, target, start, middle, end, comparator, order) { - let i = start; - let j = middle; - - for(let k = start; k < end; k++) { - if(order === Order.ascending) { - if(i < middle && (j >= end || comparator(data[i], data[j]) >= 0)) { - target[k] = data[i++]; - } else { - target[k] = data[j++]; - } - } else { - if(i < middle && (j >= end || comparator(data[i], data[j]) <= 0)) { - target[k] = data[i++]; - } else { - target[k] = data[j++]; - } - } - } - - return target; -} From 54cca0f1d107c4ba1357b4dedae518e1e2e31aac Mon Sep 17 00:00:00 2001 From: JP1998 Date: Wed, 29 May 2019 04:42:26 +0200 Subject: [PATCH 30/37] Add actual API call to retrieve the statistics --- pages/tournament-statistics.js | 181 +++------------------------------ 1 file changed, 14 insertions(+), 167 deletions(-) diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 431a8dd..02af74d 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -13,6 +13,7 @@ import { BigImage } from '../js/components/BigImage'; import { StandingsTable } from '../js/components/StandingsTable'; import { DominanceShower } from '../js/components/DominanceShower'; import { Footer } from '../js/components/Footer'; +import { requestTournamentStatistics } from '../js/api'; class StatisticsTournamentPage extends React.Component { @@ -20,173 +21,12 @@ class StatisticsTournamentPage extends React.Component { return {query}; } + componentDidMount() { + requestTournamentStatistics(this.props.query.code, () => {}, () => {}); + } + render() { - /* - let tournamentStatistics = { - tournament: { - code: 'abcd1234', - description: 'The Overwatch League Season 2 Stage 1', - id: 0xa1, - name: 'Overwatch League Season 2019 Stage 1', - owner_username: 'Blizzard Entertainment Inc.', - public: true - }, - teams: [ - { id: 0x1234, name: 'New York Excelsior' }, - { id: 0x1235, name: 'Los Angeles Gladiators' }, - { id: 0x1236, name: 'San Francisco Shock' }, - { id: 0x1237, name: 'Vancouver Titans' }, - { id: 0x1238, name: 'London Spitfire' }, - { id: 0x1239, name: 'Dallas Fuel' }, - { id: 0x123a, name: 'Chengdu Hunters' }, - { id: 0x123b, name: 'Boston Uprising' }, - { id: 0x123c, name: 'Paris Eternal' }, - { id: 0x123d, name: 'Philadelphia Fusion' }, - { id: 0x123e, name: 'Hangzhou Spark' }, - { id: 0x123f, name: 'Houston Outlaws' }, - { id: 0x1240, name: 'Shanghai Dragons' }, - { id: 0x1241, name: 'Los Angeles Valiant' }, - { id: 0x1242, name: 'Seoul Dynasty' }, - { id: 0x1243, name: 'Atlanta Reign' }, - { id: 0x1244, name: 'Toronto Defiant' }, - { id: 0x1245, name: 'Florida Mayhem' }, - { id: 0x1246, name: 'Washington Justice' }, - { id: 0x1247, name: 'Guangzhou Charge' } - ], - group_phase_performances: [ - { - win_loss_differential: 7, - point_differential: 16, - rank: 2, - team: 0x1234 // New York Excelsior - }, - { - win_loss_differential: -1, - point_differential: 1, - rank: 10, - team: 0x1235 // Los Angeles Gladiators - }, - { - win_loss_differential: 1, - point_differential: 5, - rank: 6, - team: 0x1236 // San Francisco Shock - }, - { - win_loss_differential: 7, - point_differential: 18, - rank: 1, - team: 0x1237 // Vancouver Titans - }, - { - win_loss_differential: -1, - point_differential: -4, - rank: 13, - team: 0x1238 // London Spitfire - }, - { - win_loss_differential: 1, - point_differential: 0, - rank: 9, - team: 0x1239 //Dallas Fuel - }, - { - win_loss_differential: -1, - point_differential: -8, - rank: 16, - team: 0x123a // Chengdu Hunters - }, - { - win_loss_differential: 1, - point_differential: 3, - rank: 8, - team: 0x123b // Boston Uprising - }, - { - win_loss_differential: -1, - point_differential: -8, - rank: 17, - team: 0x123c // Paris Eternal - }, - { - win_loss_differential: 3, - point_differential: 5, - rank: 3, - team: 0x123d // Philadelphia Fusion - }, - { - win_loss_differential: -1, - point_differential: -4, - rank: 14, - team: 0x123e // Hangzhou Spark - }, - { - win_loss_differential: -1, - point_differential: -3, - rank: 12, - team: 0x123f // Houston Outlaws - }, - { - win_loss_differential: -1, - point_differential: -4, - rank: 15, - team: 0x1240 // Shanghai Dragons - }, - { - win_loss_differential: -7, - point_differential: -9, - rank: 20, - team: 0x1241 // Los Angeles Valiant - }, - { - win_loss_differential: 1, - point_differential: 5, - rank: 7, - team: 0x1242 // Seoul Dynasty - }, - { - win_loss_differential: 1, - point_differential: 6, - rank: 5, - team: 0x1243 // Atlanta Reign - }, - { - win_loss_differential: 3, - point_differential: 5, - rank: 4, - team: 0x1244 // Toronto Defiant - }, - { - win_loss_differential: -5, - point_differential: -12, - rank: 19, - team: 0x1245 // Florida Mayhem - }, - { - win_loss_differential: -5, - point_differential: -11, - rank: 18, - team: 0x1246 // Washington Justice - }, - { - winlossdifferential: -1, - pointDifferential: -1, - rank: 11, - team: 0x1247 // Guangzhou Charge - } - ], - most_dominant_team: { - id: 0x1234, - points_made: 94, - points_received: 3 - }, - least_dominant_team: { - id: 0x1240, - points_made: 2, - points_received: 103 - } - }; - */ + const { tournamentStatistics } = this.props; return (
@@ -217,4 +57,11 @@ class StatisticsTournamentPage extends React.Component { } } -export default connect()(StatisticsTournamentPage); +function mapTournamentStatisticsToProps(state) { + const {tournamentStatistics} = state; + return {tournamentStatistics}; +} + +export default connect( + mapTournamentStatisticsToProps +)(StatisticsTournamentPage); From a0bcd328e62afbcf72625ca4a64f1fa4614c09ae Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 29 May 2019 08:05:22 +0200 Subject: [PATCH 31/37] Fix bug preventing the request for the actual statistics to come through --- js/api.js | 1 + 1 file changed, 1 insertion(+) diff --git a/js/api.js b/js/api.js index ad3dd14..0ad5034 100644 --- a/js/api.js +++ b/js/api.js @@ -266,6 +266,7 @@ const reducerTournamentStatistics = (state = defaultStateTournamentStatistics, a storeOptionalToken(resp); __store.dispatch({ type: actionTypesTournamentStatistics.INT_REQUEST_TOURNAMENT_STATISTICS, + state: action.state, parameters: { code: action.parameters.code, tournamentInfo: transformTournamentInfoToStatistics(resp.data), From 3286120f26e2e91d3c7876eb046d077c410534b4 Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 29 May 2019 08:13:20 +0200 Subject: [PATCH 32/37] Add detection of empty statistics and show according message --- js/redux/tournamentStatistics.js | 21 ++++++++++++++++-- pages/tournament-statistics.js | 38 +++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/js/redux/tournamentStatistics.js b/js/redux/tournamentStatistics.js index debf75e..600c272 100644 --- a/js/redux/tournamentStatistics.js +++ b/js/redux/tournamentStatistics.js @@ -13,9 +13,11 @@ export const defaultStateTournamentStatistics = { description: '', id: -1, name: '', - ownerUsername: '', + owner_username: '', isPublic: '', + statistics_available: false, + most_dominant_team: {}, least_dominant_team: {}, group_phase_performances: [] @@ -28,13 +30,23 @@ export function transformTournamentInfoToStatistics(data) { description: data.description, id: data.id, name: data.name, - ownerUsername: data.owner_username, + owner_username: data.owner_username, isPublic: data.public }; } export function transformTournamentStatsToStatistics(data) { + if(statisticsUnavailable(data)) { + return { + statistics_available: false, + most_dominant_team: {}, + least_dominant_team: {}, + group_phase_performances: [] + }; + } + const statistics = { + statistics_available: true, most_dominant_team: { points_made: data.most_dominant_score.scored_points, points_received: data.most_dominant_score.received_points, @@ -62,3 +74,8 @@ export function transformTournamentStatsToStatistics(data) { return statistics; } +function statisticsUnavailable(data) { + return data === {} || data.most_dominant_score === null || + data.least_dominant_score === null || data.group_scores === []; +} + diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 02af74d..a38aefc 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -37,19 +37,7 @@ class StatisticsTournamentPage extends React.Component {
- - -
- - - - - - - - - - +
@@ -57,6 +45,30 @@ class StatisticsTournamentPage extends React.Component { } } +function StatisticsView(props) { + if (props.tournamentStatistics.statistics_available) { + return (
+ + +
+ + + + + + + + + + + ); + } else { + return ( +

Statistiken sind für dieses Turnier leider nicht verfügbar.

+
); + } +} + function mapTournamentStatisticsToProps(state) { const {tournamentStatistics} = state; return {tournamentStatistics}; From 7f28252ae8afb7b95254706ecca3e222f9a462d3 Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 29 May 2019 08:32:42 +0200 Subject: [PATCH 33/37] Fix bug preventing the edit match modal from showing to the owner --- pages/tournament.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pages/tournament.js b/pages/tournament.js index 826d196..b5972b2 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -19,14 +19,14 @@ import {Match} from '../js/components/Match'; class PrivateTournamentPage extends React.Component { render() { - const {ownerUsername, playoffStages} = this.props.tournament; + const {owner_username, playoffStages} = this.props.tournament; const {isSignedIn, username} = this.props; // TODO: Change href-prop of the anchor tag to contain the tournament code return (
- {playoffStages.map(stage => )}
From 38e24a2ec175b0f317324ed43e178f04ea8c6030 Mon Sep 17 00:00:00 2001 From: Jonny Date: Wed, 29 May 2019 08:42:12 +0200 Subject: [PATCH 34/37] Fix some code issues from eslint --- js/api.js | 4 +-- js/components/DominanceShower.js | 1 - js/components/StandingsTable.js | 21 ++++++++-------- js/components/TournamentInformationView.js | 27 ++++++++++---------- js/redux/tournamentStatistics.js | 8 +++--- pages/_app.js | 12 ++++----- pages/tournament-statistics.js | 29 +++++++++++----------- pages/tournament.js | 10 ++++---- server.js | 2 +- yarn.lock | 2 +- 10 files changed, 58 insertions(+), 58 deletions(-) diff --git a/js/api.js b/js/api.js index 0ad5034..7a81e2d 100644 --- a/js/api.js +++ b/js/api.js @@ -300,10 +300,10 @@ const reducerTournamentStatistics = (state = defaultStateTournamentStatistics, a return Object.assign({}, state, action.parameters.tournamentInfo); case actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS_SUCCESS: action.parameters.successCallback(); - return Object.assign({}, state, tournamentStatistics); + return Object.assign({}, state, action.parameters.tournamentStatistics); default: return state; } -} +}; const reducerTournamentlist = (state = defaultStateTournamentlist, action) => { switch (action.type) { diff --git a/js/components/DominanceShower.js b/js/components/DominanceShower.js index 01dc571..5861858 100644 --- a/js/components/DominanceShower.js +++ b/js/components/DominanceShower.js @@ -7,7 +7,6 @@ import { } from 'reactstrap'; export class DominanceShower extends React.Component { - render() { return ( diff --git a/js/components/StandingsTable.js b/js/components/StandingsTable.js index b2db7cb..c82d8ad 100644 --- a/js/components/StandingsTable.js +++ b/js/components/StandingsTable.js @@ -7,10 +7,9 @@ import { Table } from 'reactstrap'; -import { rangedmap } from '../utils/rangedmap'; +import {rangedmap} from '../utils/rangedmap'; export class StandingsTable extends React.Component { - constructor(props) { super(props); @@ -21,7 +20,7 @@ export class StandingsTable extends React.Component { } render() { - let performances = this.props.data.group_phase_performances; + const performances = this.props.data.group_phase_performances; return ( @@ -38,18 +37,21 @@ export class StandingsTable extends React.Component {
{ rangedmap(performances, (team, index) => ( - + ), 0, 3) } { rangedmap(performances, (team, index) => ( - + ), 3) } @@ -60,7 +62,7 @@ export class StandingsTable extends React.Component { } toggleShowFullTable() { - this.setState({ showFullTable: !this.state.showFullTable }); + this.setState({showFullTable: !this.state.showFullTable}); } } @@ -82,11 +84,10 @@ class TeamRow extends React.Component { } class TableButton extends React.Component { - render() { - const { isFullTableShown } = this.props; + const {isFullTableShown} = this.props; - if(isFullTableShown) { + if (isFullTableShown) { return ; } else { return ; diff --git a/js/components/TournamentInformationView.js b/js/components/TournamentInformationView.js index c34b4b4..b31c695 100644 --- a/js/components/TournamentInformationView.js +++ b/js/components/TournamentInformationView.js @@ -1,5 +1,5 @@ -import React from 'react'; -import { connect } from 'react-redux'; +import React from 'react'; +import {connect} from 'react-redux'; import { Button, ButtonGroup, @@ -12,15 +12,14 @@ import { class PrivateTournamentInformationView extends React.Component { - render() { - const { tournament, isSignedIn, username, currentpage } = this.props; + const {tournament, isSignedIn, username, currentpage} = this.props; return ( - @@ -83,14 +82,14 @@ function ButtonsBadge(props) { } function TournamentButton(props) { - const { id } = props; + const {id} = props; return ; } function EditButton(props) { - const { id, ownerName, isSignedIn, username } = props; + const {id, ownerName, isSignedIn, username} = props; - if(isSignedIn && ownerName === username) { + if (isSignedIn && ownerName === username) { return ( ); @@ -100,7 +99,7 @@ function EditButton(props) { } function StatisticsButton(props) { - const { id } = props; + const {id} = props; return ; } diff --git a/js/redux/tournamentStatistics.js b/js/redux/tournamentStatistics.js index 600c272..4d426ec 100644 --- a/js/redux/tournamentStatistics.js +++ b/js/redux/tournamentStatistics.js @@ -18,7 +18,7 @@ export const defaultStateTournamentStatistics = { statistics_available: false, - most_dominant_team: {}, + most_dominant_team: {}, least_dominant_team: {}, group_phase_performances: [] }; @@ -36,7 +36,7 @@ export function transformTournamentInfoToStatistics(data) { } export function transformTournamentStatsToStatistics(data) { - if(statisticsUnavailable(data)) { + if (statisticsUnavailable(data)) { return { statistics_available: false, most_dominant_team: {}, @@ -61,14 +61,14 @@ export function transformTournamentStatsToStatistics(data) { }; for (let i = 0; i < data.group_scores.length; i++) { - let score = data.group_scores[i]; + const score = data.group_scores[i]; statistics.group_phase_performances[i] = { win_loss_differential: score.group_points, point_differential: score.scored_points - score.received_points, rank: i + 1, team_name: score.team.name - } + }; } return statistics; diff --git a/pages/_app.js b/pages/_app.js index a2e98b1..6bc4dcb 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -15,12 +15,12 @@ class TurniereApp extends App { render() { const {Component, pageProps, reduxStore} = this.props; return ( - - - - - - ); + + + + + + ); } } diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index a38aefc..1fb27bb 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -1,22 +1,21 @@ -import Head from 'next/head'; -import React from 'react'; -import { connect } from 'react-redux'; +import Head from 'next/head'; +import React from 'react'; +import {connect} from 'react-redux'; import { Col, Container, Row } from 'reactstrap'; -import { TurniereNavigation } from '../js/components/Navigation'; -import { TournamentInformationView } from '../js/components/TournamentInformationView'; -import { BigImage } from '../js/components/BigImage'; -import { StandingsTable } from '../js/components/StandingsTable'; -import { DominanceShower } from '../js/components/DominanceShower'; -import { Footer } from '../js/components/Footer'; -import { requestTournamentStatistics } from '../js/api'; +import {TurniereNavigation} from '../js/components/Navigation'; +import {TournamentInformationView} from '../js/components/TournamentInformationView'; +import {BigImage} from '../js/components/BigImage'; +import {StandingsTable} from '../js/components/StandingsTable'; +import {DominanceShower} from '../js/components/DominanceShower'; +import {Footer} from '../js/components/Footer'; +import {requestTournamentStatistics} from '../js/api'; class StatisticsTournamentPage extends React.Component { - static async getInitialProps({query}) { return {query}; } @@ -26,7 +25,7 @@ class StatisticsTournamentPage extends React.Component { } render() { - const { tournamentStatistics } = this.props; + const {tournamentStatistics} = this.props; return (
@@ -51,10 +50,12 @@ function StatisticsView(props) {
- + - + diff --git a/pages/tournament.js b/pages/tournament.js index b5972b2..1b14ce7 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -1,7 +1,7 @@ import Head from 'next/head'; import React from 'react'; import {connect} from 'react-redux'; -import {Col, Container, ListGroup, ListGroupItem, Row} from 'reactstrap'; +import {Col, Container, Row} from 'reactstrap'; import {ErrorPageComponent} from '../js/components/ErrorComponents'; import {Footer} from '../js/components/Footer'; @@ -19,14 +19,14 @@ import {Match} from '../js/components/Match'; class PrivateTournamentPage extends React.Component { render() { - const {owner_username, playoffStages} = this.props.tournament; + const {ownerUsername, playoffStages} = this.props.tournament; const {isSignedIn, username} = this.props; - + // TODO: Change href-prop of the anchor tag to contain the tournament code return (
- {playoffStages.map(stage => )}
@@ -85,7 +85,7 @@ function convertTournament(apiTournament) { description: apiTournament.description, name: apiTournament.name, isPublic: apiTournament.public, - owner_username: apiTournament.owner_username, + ownerUsername: apiTournament.owner_username, groupStage: groupStage, playoffStages: playoffStages }; diff --git a/server.js b/server.js index 9b30a15..8772603 100644 --- a/server.js +++ b/server.js @@ -29,7 +29,7 @@ app.prepare() server.get('/t/:code/statistics', (req, res) => { const actualPage = '/tournament-statistics'; - const queryParam = { code: req.params.code }; + const queryParam = {code: req.params.code}; app.render(req, res, actualPage, queryParam); }); diff --git a/yarn.lock b/yarn.lock index 65790b4..6eb06b7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3291,7 +3291,7 @@ eslint-visitor-keys@^1.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz#3f3180fb2e291017716acb4c9d6d5b5c34a6a81d" integrity sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ== -eslint@^5.9.0: +eslint@^5.16.0: version "5.16.0" resolved "https://registry.yarnpkg.com/eslint/-/eslint-5.16.0.tgz#a1e3ac1aae4a3fbd8296fcf8f7ab7314cbb6abea" integrity sha512-S3Rz11i7c8AA5JPv7xAH+dOyq/Cu/VXHiHXBPOU1k/JAM5dXqQPt3qcrhpHSorXmrpu2g0gkIBVXAqCpzfoZIg== From bd994c9d042fb2ab531cfdd67eb9cf4ceaa35be6 Mon Sep 17 00:00:00 2001 From: Felix Hamme Date: Wed, 19 Jun 2019 17:52:03 +0200 Subject: [PATCH 35/37] Continuing merge: add api.js changes from ticket/TURNIERE-148 --- js/api.js | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 71 insertions(+), 2 deletions(-) diff --git a/js/api.js b/js/api.js index ad1d6df..6112c0d 100644 --- a/js/api.js +++ b/js/api.js @@ -8,6 +8,11 @@ import {actionTypesUserinfo, defaultStateUserinfo} from './redux/userInfo'; import {actionTypesTournamentinfo, defaultStateTournamentinfo} from './redux/tournamentInfo'; import {actionTypesTournamentlist, defaultStateTournamentlist} from './redux/tournamentList'; import {deleteRequest, getRequest, patchRequest, postRequest, putRequest} from './redux/backendApi'; +import { + actionTypesTournamentStatistics, + defaultStateTournamentStatistics, + transformTournamentInfoToStatistics, transformTournamentStatsToStatistics +} from './redux/tournamentStatistics'; function storeOptionalToken(response) { @@ -319,16 +324,64 @@ const reducerTournamentlist = (state = defaultStateTournamentlist, action) => { } }; +const reducerTournamentStatistics = (state = defaultStateTournamentStatistics, action) => { + switch (action.type) { + case actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS: + getRequest(action.state, '/tournaments/' + action.parameters.code).then(resp => { + storeOptionalToken(resp); + __store.dispatch({ + type: actionTypesTournamentStatistics.INT_REQUEST_TOURNAMENT_STATISTICS, + state: action.state, + parameters: { + code: action.parameters.code, + tournamentInfo: transformTournamentInfoToStatistics(resp.data), + successCallback: action.parameters.successCallback, + errorCallback: action.parameters.errorCallback + } + }); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + return state; + case actionTypesTournamentStatistics.INT_REQUEST_TOURNAMENT_STATISTICS: + getRequest(action.state, '/tournaments/' + action.parameters.code + '/statistics').then(resp => { + storeOptionalToken(resp); + __store.dispatch({ + type: actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS_SUCCESS, + parameters: { + tournamentStatistics: transformTournamentStatsToStatistics(resp.data), + successCallback: action.parameters.successCallback + } + }); + }).catch(error => { + if (error.response) { + storeOptionalToken(error.response); + } + action.parameters.errorCallback(); + }); + return Object.assign({}, state, action.parameters.tournamentInfo); + case actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS_SUCCESS: + action.parameters.successCallback(); + return Object.assign({}, state, action.parameters.tournamentStatistics); + default: return state; + } +}; + const reducers = { userinfo: reducerUserinfo, tournamentinfo: reducerTournamentinfo, - tournamentlist: reducerTournamentlist + tournamentlist: reducerTournamentlist, + tournamentStatistics: reducerTournamentStatistics }; const defaultApplicationState = { userinfo: defaultStateUserinfo, tournamentinfo: defaultStateTournamentinfo, - tournamentlist: defaultStateTournamentlist + tournamentlist: defaultStateTournamentlist, + tournamentStatistics: defaultStateTournamentStatistics }; let __store; @@ -499,6 +552,18 @@ export function requestTournamentList(type, successCallback, errorCallback) { }); } +export function requestTournamentStatistics(code, successCallback, errorCallback) { + __store.dispatch({ + type: actionTypesTournamentStatistics.REQUEST_TOURNAMENT_STATISTICS, + parameters: { + code: code, + successCallback: successCallback, + errorCallback: errorCallback + }, + state: __store.getState() + }); +} + function rehydrateApplicationState() { const persistedState = localStorage.getItem('reduxState') ? JSON.parse(localStorage.getItem('reduxState')) : @@ -517,6 +582,10 @@ function rehydrateApplicationState() { type: actionTypesTournamentlist.REHYDRATE, parameters: Object.assign({}, persistedState.tournamentlist) }); + __store.dispatch({ + type: actionTypesTournamentStatistics.REHYDRATE, + parameters: Object.assign({}, persistedState.tournamentstatistics) + }); } applicationHydrated = true; } From ecc1401042e6f95832790ceeb0c5a0dfa98bf8ea Mon Sep 17 00:00:00 2001 From: Felix Hamme Date: Wed, 19 Jun 2019 17:53:56 +0200 Subject: [PATCH 36/37] Continuing merge: add Statistics button to tournament page --- pages/tournament.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/pages/tournament.js b/pages/tournament.js index 5496d38..eac688a 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -42,12 +42,20 @@ function StatusBar(props) { {props.tournament.name} - + + ); } +function StatisticsButton(props) { + return ( + Statistiken + ); +} + function TournamentBigImage(props) { return (
@@ -77,10 +85,10 @@ function mapStateToTournamentPageProperties(state) { const TournamentPage = connect(mapStateToTournamentPageProperties)(PrivateTournamentPage); function EditButton(props) { - const {id, isOwner, isSignedIn} = props; + const {tournamentId, isOwner, isSignedIn} = props; if (isSignedIn && isOwner) { - return ( + return ( Turnier bearbeiten ); } else { From 778d0173024293ea3fa2e39b1f216c0c9c2efd4c Mon Sep 17 00:00:00 2001 From: Felix Hamme Date: Wed, 19 Jun 2019 18:55:04 +0200 Subject: [PATCH 37/37] Continuing merge: link tournament view, edit and statistics pages between each other, use new design from merged branch --- js/components/TournamentBigImage.js | 22 +++++ js/components/TournamentInformationView.js | 105 --------------------- js/components/TournamentStatusBar.js | 29 ++++++ js/redux/tournamentStatistics.js | 2 +- pages/tournament-statistics.js | 28 ++++-- pages/tournament.js | 56 +++-------- 6 files changed, 81 insertions(+), 161 deletions(-) create mode 100644 js/components/TournamentBigImage.js delete mode 100644 js/components/TournamentInformationView.js create mode 100644 js/components/TournamentStatusBar.js diff --git a/js/components/TournamentBigImage.js b/js/components/TournamentBigImage.js new file mode 100644 index 0000000..ed304f0 --- /dev/null +++ b/js/components/TournamentBigImage.js @@ -0,0 +1,22 @@ +import {Container, ListGroup, ListGroupItem} from 'reactstrap'; +import React from 'react'; + +export function TournamentBigImage(props) { + return (
+

{props.name}

+ + + +
); +} + +function TournamentProperties(props) { + return ( + {props.description && {props.description}} + + {props.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} + + Turnier-Code: {props.code} + von {props.ownerUsername} + ); +} diff --git a/js/components/TournamentInformationView.js b/js/components/TournamentInformationView.js deleted file mode 100644 index b31c695..0000000 --- a/js/components/TournamentInformationView.js +++ /dev/null @@ -1,105 +0,0 @@ -import React from 'react'; -import {connect} from 'react-redux'; -import { - Button, - ButtonGroup, - Col, - Container, - ListGroup, - ListGroupItem, - Row -} from 'reactstrap'; - - -class PrivateTournamentInformationView extends React.Component { - render() { - const {tournament, isSignedIn, username, currentpage} = this.props; - - return ( - - -
- -

{tournament.description}

- -
- - - {tournament.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} - - Turnier-Code: {tournament.code} - von {tournament.owner_username} - - - - - ); - } -} - -function mapStateToPrivateTournamentInformationViewProps(state) { - const {isSignedIn, username} = state.userinfo; - return {isSignedIn, username}; -} - -export const TournamentInformationView = connect( - mapStateToPrivateTournamentInformationViewProps -)(PrivateTournamentInformationView); - -function ButtonsBadge(props) { - const {id, ownerName, isSignedIn, username, currentpage} = props; - - switch (currentpage) { - case 'statistics': - return ( - - - - - ); - case 'tournament': - return ( - - - - - ); - case 'edit': - return ( - - - - - ); - default: return null; - } -} - -function TournamentButton(props) { - const {id} = props; - return ; -} - -function EditButton(props) { - const {id, ownerName, isSignedIn, username} = props; - - if (isSignedIn && ownerName === username) { - return ( - - ); - } else { - return null; - } -} - -function StatisticsButton(props) { - const {id} = props; - return ; -} - diff --git a/js/components/TournamentStatusBar.js b/js/components/TournamentStatusBar.js new file mode 100644 index 0000000..0fd018a --- /dev/null +++ b/js/components/TournamentStatusBar.js @@ -0,0 +1,29 @@ +import Navbar from 'react-bootstrap/Navbar'; +import {Container} from 'reactstrap'; +import React from 'react'; + +export function TournamentStatusBar(props) { + return ( + + {props.children} + + ); +} + +export function TournamentStatusBarButton(props) { + return ( + {props.children} + ); +} + +export function EditButton(props) { + const {tournamentId, isOwner, isSignedIn} = props; + + if (isSignedIn && isOwner) { + return ( + Turnier bearbeiten + ); + } else { + return null; + } +} diff --git a/js/redux/tournamentStatistics.js b/js/redux/tournamentStatistics.js index 4d426ec..4004982 100644 --- a/js/redux/tournamentStatistics.js +++ b/js/redux/tournamentStatistics.js @@ -30,7 +30,7 @@ export function transformTournamentInfoToStatistics(data) { description: data.description, id: data.id, name: data.name, - owner_username: data.owner_username, + ownerUsername: data.owner_username, isPublic: data.public }; } diff --git a/pages/tournament-statistics.js b/pages/tournament-statistics.js index 1fb27bb..0beb23b 100644 --- a/pages/tournament-statistics.js +++ b/pages/tournament-statistics.js @@ -1,19 +1,16 @@ import Head from 'next/head'; import React from 'react'; import {connect} from 'react-redux'; -import { - Col, - Container, - Row -} from 'reactstrap'; +import {Col, Container, Row} from 'reactstrap'; import {TurniereNavigation} from '../js/components/Navigation'; -import {TournamentInformationView} from '../js/components/TournamentInformationView'; -import {BigImage} from '../js/components/BigImage'; import {StandingsTable} from '../js/components/StandingsTable'; import {DominanceShower} from '../js/components/DominanceShower'; import {Footer} from '../js/components/Footer'; import {requestTournamentStatistics} from '../js/api'; +import {EditButton, TournamentStatusBar, TournamentStatusBarButton} from '../js/components/TournamentStatusBar'; +import Navbar from 'react-bootstrap/Navbar'; +import {TournamentBigImage} from '../js/components/TournamentBigImage'; class StatisticsTournamentPage extends React.Component { static async getInitialProps({query}) { @@ -33,9 +30,19 @@ class StatisticsTournamentPage extends React.Component { {tournamentStatistics.name}: turnie.re - + + + + {tournamentStatistics.name} + + + zurück zum Turnier + + +
-
@@ -72,7 +79,8 @@ function StatisticsView(props) { function mapTournamentStatisticsToProps(state) { const {tournamentStatistics} = state; - return {tournamentStatistics}; + const {isSignedIn, username} = state.userinfo; + return {tournamentStatistics, isSignedIn, username}; } export default connect( diff --git a/pages/tournament.js b/pages/tournament.js index eac688a..341adfe 100644 --- a/pages/tournament.js +++ b/pages/tournament.js @@ -1,7 +1,6 @@ import Head from 'next/head'; import React from 'react'; import {connect} from 'react-redux'; -import {Container, ListGroup, ListGroupItem} from 'reactstrap'; import Navbar from 'react-bootstrap/Navbar'; @@ -16,6 +15,8 @@ import '../static/css/tournament.css'; import {getTournament} from '../js/redux/tournamentApi'; import {PlayoffStages} from '../js/components/PlayoffStages'; import GroupStage from '../js/components/GroupStage'; +import {TournamentBigImage} from '../js/components/TournamentBigImage'; +import {EditButton, TournamentStatusBar, TournamentStatusBarButton} from '../js/components/TournamentStatusBar'; class PrivateTournamentPage extends React.Component { render() { @@ -38,45 +39,22 @@ class PrivateTournamentPage extends React.Component { } function StatusBar(props) { - return ( - - - {props.tournament.name} - - - - - ); + return ( + + {props.tournament.name} + + + + ); } function StatisticsButton(props) { - return ( + return ( Statistiken - ); + ); } -function TournamentBigImage(props) { - return (
-

{props.name}

- - - -
); -} - -function TournamentProperties(props) { - return ( - {props.description && {props.description}} - - {props.isPublic ? 'Das Turnier ist öffentlich.' : 'Das Turnier ist privat.'} - - Turnier-Code: {props.code} - von {props.ownerUsername} - ); -} - function mapStateToTournamentPageProperties(state) { const {isSignedIn, username} = state.userinfo; return {isSignedIn, username}; @@ -84,18 +62,6 @@ function mapStateToTournamentPageProperties(state) { const TournamentPage = connect(mapStateToTournamentPageProperties)(PrivateTournamentPage); -function EditButton(props) { - const {tournamentId, isOwner, isSignedIn} = props; - - if (isSignedIn && isOwner) { - return ( - Turnier bearbeiten - ); - } else { - return null; - } -} - class Main extends React.Component { static async getInitialProps({query}) { return {query};
{findTeam(this.props.teams, this.props.stats.id).name}{this.props.stats.team_name}
{this.props.stats.points_made}
{ this.props.teamToShow.rank }{findTeam(this.props.teams, this.props.teamToShow.team).name}{ this.props.teamToShow.team_name } { this.props.teamToShow.win_loss_differential } { this.props.teamToShow.point_differential }
- +