From 6d38868560f5ce6e731465f39f25d9bd55419ab4 Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Thu, 16 Feb 2017 07:30:11 +0000 Subject: [PATCH 1/6] add highest/lowest mmr matches --- src/actions/index.js | 1 + src/actions/publicMatchesActions.js | 35 ++++++++++++ src/components/Heroes/index.jsx | 4 +- src/components/Matches/index.jsx | 82 ++++++++++++++++++++++++++--- src/components/Router/index.jsx | 4 +- src/lang/en-US.json | 6 ++- src/reducers/index.js | 3 ++ src/reducers/publicMatches.js | 15 ++++++ 8 files changed, 137 insertions(+), 13 deletions(-) create mode 100644 src/actions/publicMatchesActions.js create mode 100644 src/reducers/publicMatches.js diff --git a/src/actions/index.js b/src/actions/index.js index 35f83dca50..3efb820f31 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -27,3 +27,4 @@ export * from './proMatchesActions'; export * from './localizationActions'; export * from './pvgnaActions'; export * from './heroStatsActions'; +export * from './publicMatchesActions'; diff --git a/src/actions/publicMatchesActions.js b/src/actions/publicMatchesActions.js new file mode 100644 index 0000000000..07161f7d73 --- /dev/null +++ b/src/actions/publicMatchesActions.js @@ -0,0 +1,35 @@ +/* global API_HOST */ +import fetch from 'isomorphic-fetch'; +import querystring from 'querystring'; + +const REQUEST = 'publicMatches/REQUEST'; +const OK = 'publicMatches/OK'; +const ERROR = 'publicMatches/ERROR'; + +export const publicMatchesActions = { + REQUEST, + OK, + ERROR, +}; + +export const getPublicMatchesRequest = () => ({ + type: REQUEST, +}); + +export const getPublicMatchesOk = payload => ({ + type: OK, + payload, +}); + +export const getPublicMatchesError = payload => ({ + type: ERROR, + payload, +}); + +export const getPublicMatches = options => (dispatch) => { + dispatch(getPublicMatchesRequest()); + return fetch(`${API_HOST}/api/publicMatches?${querystring.stringify(options)}`) + .then(response => response.json()) + .then(json => dispatch(getPublicMatchesOk(json))) + .catch(error => dispatch(getPublicMatchesError(error))); +}; diff --git a/src/components/Heroes/index.jsx b/src/components/Heroes/index.jsx index f46a72e3b1..5f34ffd36a 100644 --- a/src/components/Heroes/index.jsx +++ b/src/components/Heroes/index.jsx @@ -94,7 +94,7 @@ class RequestLayer extends React.Component { route: '/heroes/public', }]; - const tab = heroTabs.find(tab => tab.key.toLowerCase() === route); + const tab = heroTabs.find(tab => tab.key === route); const loading = this.props.loading; return (
@@ -104,7 +104,7 @@ class RequestLayer extends React.Component { info={route} tabs={heroTabs} /> - {heroTabs && tab.content(processedData, columns[route])} + {tab && tab.content(processedData, columns[route])}
} ); } diff --git a/src/components/Matches/index.jsx b/src/components/Matches/index.jsx index 588d7702a4..44c24c7787 100644 --- a/src/components/Matches/index.jsx +++ b/src/components/Matches/index.jsx @@ -1,7 +1,7 @@ import React from 'react'; import { connect } from 'react-redux'; import Helmet from 'react-helmet'; -import { getProMatches } from 'actions'; +import { getProMatches, getPublicMatches } from 'actions'; import strings from 'lang'; import Table, { TableLink } from 'components/Table'; // import Heading from 'components/Heading'; @@ -9,7 +9,8 @@ import { transformations } from 'utility'; import subTextStyle from 'components/Visualizations/Table/subText.css'; import { IconRadiant, IconDire } from 'components/Icons'; import matchStyles from 'components/Match/Match.css'; -import Container from 'components/Container'; +import Match from 'components/Match'; +import TabBar from 'components/TabBar'; const matchesColumns = [{ displayName: strings.th_match_id, @@ -37,27 +38,94 @@ const matchesColumns = [{ color: matchStyles.red, }]; +const publicMatchesColumns = [ + { + displayName: strings.th_match_id, + field: 'match_id', + sortFn: true, + displayFn: (row, col, field) =>
+ {field} + + {row.avg_mmr} {strings.th_mmr} + +
, + }, { + displayName: strings.th_duration, + tooltip: strings.tooltip_duration, + field: 'duration', + sortFn: true, + displayFn: transformations.duration, + }, +]; + +const matchTabs = [{ + name: strings.hero_pro_tab, + key: 'pro', + content: props => (
+ + ), + route: '/matches/pro', +}, { + name: strings.matches_highest_mmr, + key: 'highMmr', + content: props => (
+
+ ), + route: '/matches/highMmr', +}, { + name: strings.matches_lowest_mmr, + key: 'lowMmr', + content: props => (
+
+ ), + route: '/matches/lowMmr', +}]; + +const getData = (props) => { + props.dispatchProMatches(); + props.dispatchPublicMatches({ mmr_ascending: Number(props.routeParams.matchId === 'lowMmr') }); +}; + class RequestLayer extends React.Component { componentDidMount() { - this.props.dispatchProMatches(); + getData(this.props); + } + + componentWillUpdate(nextProps) { + if (this.props.routeParams.matchId !== nextProps.routeParams.matchId) { + getData(nextProps); + } } render() { + const route = this.props.routeParams.matchId || 'pro'; + + if (Number.isInteger(Number(route))) { + return ; + } + + const tab = matchTabs.find(tab => tab.key === route); return (
- -
- +
+ + {tab && tab.content(this.props)} +
); } } const mapStateToProps = state => ({ - data: state.app.proMatches.list, + proData: state.app.proMatches.list, + publicData: state.app.publicMatches.list, loading: state.app.proMatches.loading, }); const mapDispatchToProps = dispatch => ({ dispatchProMatches: () => dispatch(getProMatches()), + dispatchPublicMatches: options => dispatch(getPublicMatches(options)), }); export default connect(mapStateToProps, mapDispatchToProps)(RequestLayer); diff --git a/src/components/Router/index.jsx b/src/components/Router/index.jsx index 3bae6c3857..bf9ffc659d 100644 --- a/src/components/Router/index.jsx +++ b/src/components/Router/index.jsx @@ -8,7 +8,6 @@ import { } from 'react-router'; import { syncHistoryWithStore } from 'react-router-redux'; import App from 'components/App'; -import Match from 'components/Match'; import Player from 'components/Player'; import Home from 'components/Home'; import Search from 'components/Search'; @@ -33,8 +32,7 @@ export default () => ( - - + diff --git a/src/lang/en-US.json b/src/lang/en-US.json index ad818f1928..bbbf3afdc9 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -330,6 +330,9 @@ "match_first_barracks": "First barracks", "match_pick": "Pick", "match_ban": "Ban", + + "matches_highest_mmr": "High MMR", + "matches_lowest_mmr": "Low MMR", "npc_dota_beastmaster_boar_#": "Boar", "npc_dota_lesser_eidolon": "Eidolon", @@ -551,6 +554,7 @@ "th_party_mmr": "Party MMR", "th_estimated_mmr": "Estimated MMR", "th_permanent_buffs": "Buffs", + "th_avg_mmr": "Average MMR", "ward_log_type": "Type", "ward_log_owner": "Owner", @@ -584,7 +588,7 @@ "title_default": "OpenDota - Dota 2 Statistics", "title_template": "%s - OpenDota - Dota 2 Statistics", - "title_matches": "Professional Matches", + "title_matches": "Matches", "title_request": "Request a Parse", "title_search": "Search", "title_status": "Status", diff --git a/src/reducers/index.js b/src/reducers/index.js index b70acc5ac4..0c325965b6 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -6,6 +6,7 @@ import heroRanking, { getHeroRanking } from 'reducers/heroRanking'; import heroBenchmark, { getHeroBenchmark } from 'reducers/heroBenchmark'; import search from 'reducers/search'; import proPlayers, { getProPlayers } from 'reducers/proPlayers'; +import publicMatches, { getPublicMatches } from 'reducers/publicMatches'; import proMatches, { getProMatches } from 'reducers/proMatches'; import gotPlayer, { player, @@ -55,6 +56,7 @@ export { getLocalization as localization, pvgnaGuides, getHeroStats as heroStats, + getPublicMatches as publicMatches, }; export default combineReducers({ @@ -73,4 +75,5 @@ export default combineReducers({ localization, pvgnaGuides, heroStats, + publicMatches, }); diff --git a/src/reducers/publicMatches.js b/src/reducers/publicMatches.js new file mode 100644 index 0000000000..8c0db58893 --- /dev/null +++ b/src/reducers/publicMatches.js @@ -0,0 +1,15 @@ +import { publicMatchesActions } from 'actions'; +import { listData, selectors } from './reducerFactory'; + +const initialState = { + loaded: false, + error: false, + loading: false, + list: [], +}; + +export default listData(initialState, publicMatchesActions); + +export const getPublicMatches = { + ...selectors(state => state.app.publicMatches), +}; From e24b6172c5b116395f1ec5dc85f4c27aab951c0d Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Thu, 16 Feb 2017 07:44:28 +0000 Subject: [PATCH 2/6] add winner display for pro matches --- src/components/Matches/Matches.css | 18 ++++++++++++++++++ src/components/Matches/index.jsx | 7 +++++-- src/lang/en-US.json | 1 - 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/src/components/Matches/Matches.css b/src/components/Matches/Matches.css index e6a13b442d..5c6f8020a1 100644 --- a/src/components/Matches/Matches.css +++ b/src/components/Matches/Matches.css @@ -1 +1,19 @@ @import "../palette.css"; + +.badge { + display: inline-block; + + & svg { + width: 10px !important; + height: 10px !important; + margin-right: 5px; + } +} + +.confirmed { + composes: badge; + + & svg { + fill: var(--colorGolden); + } +} \ No newline at end of file diff --git a/src/components/Matches/index.jsx b/src/components/Matches/index.jsx index 44c24c7787..9948aaacd2 100644 --- a/src/components/Matches/index.jsx +++ b/src/components/Matches/index.jsx @@ -7,10 +7,11 @@ import Table, { TableLink } from 'components/Table'; // import Heading from 'components/Heading'; import { transformations } from 'utility'; import subTextStyle from 'components/Visualizations/Table/subText.css'; -import { IconRadiant, IconDire } from 'components/Icons'; +import { IconRadiant, IconDire, IconTrophy } from 'components/Icons'; import matchStyles from 'components/Match/Match.css'; import Match from 'components/Match'; import TabBar from 'components/TabBar'; +import styles from './Matches.css'; const matchesColumns = [{ displayName: strings.th_match_id, @@ -32,10 +33,12 @@ const matchesColumns = [{ displayName: {strings.general_radiant}, field: 'radiant_name', color: matchStyles.green, + displayFn: (row, col, field) =>
{row.radiant_win && }{field}
}, { displayName: {strings.general_dire}, field: 'dire_name', color: matchStyles.red, + displayFn: (row, col, field) =>
{!row.radiant_win && }{field}
}]; const publicMatchesColumns = [ @@ -83,7 +86,7 @@ const matchTabs = [{ const getData = (props) => { props.dispatchProMatches(); - props.dispatchPublicMatches({ mmr_ascending: Number(props.routeParams.matchId === 'lowMmr') }); + props.dispatchPublicMatches({ mmr_ascending: props.routeParams.matchId === 'lowMmr' ? '1' : '' }); }; class RequestLayer extends React.Component { diff --git a/src/lang/en-US.json b/src/lang/en-US.json index bbbf3afdc9..ad30b5f0ff 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -554,7 +554,6 @@ "th_party_mmr": "Party MMR", "th_estimated_mmr": "Estimated MMR", "th_permanent_buffs": "Buffs", - "th_avg_mmr": "Average MMR", "ward_log_type": "Type", "ward_log_owner": "Owner", From 91ff12624f66f77a58d69c972f61019634b03d04 Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Thu, 16 Feb 2017 07:54:38 +0000 Subject: [PATCH 3/6] lint, fix some text --- src/components/Hero/index.jsx | 18 ++++++++++-------- src/components/Matches/index.jsx | 4 ++-- .../Player/Pages/Rankings/Rankings.jsx | 2 +- src/lang/en-US.json | 8 ++------ 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/components/Hero/index.jsx b/src/components/Hero/index.jsx index 0c9ec008f1..179e5be513 100644 --- a/src/components/Hero/index.jsx +++ b/src/components/Hero/index.jsx @@ -11,17 +11,19 @@ import styles from './Hero.css'; const getSingleHero = heroId => ({ ...heroes[heroId], img: API_HOST + heroes[heroId].img }); -const Hero = ({ props }) => (
+const Hero = ({ props }) => (
- - +
+ + +
- +
diff --git a/src/components/Matches/index.jsx b/src/components/Matches/index.jsx index 9948aaacd2..8a48d447fb 100644 --- a/src/components/Matches/index.jsx +++ b/src/components/Matches/index.jsx @@ -33,12 +33,12 @@ const matchesColumns = [{ displayName: {strings.general_radiant}, field: 'radiant_name', color: matchStyles.green, - displayFn: (row, col, field) =>
{row.radiant_win && }{field}
+ displayFn: (row, col, field) =>
{row.radiant_win && }{field}
, }, { displayName: {strings.general_dire}, field: 'dire_name', color: matchStyles.red, - displayFn: (row, col, field) =>
{!row.radiant_win && }{field}
+ displayFn: (row, col, field) =>
{!row.radiant_win && }{field}
, }]; const publicMatchesColumns = [ diff --git a/src/components/Player/Pages/Rankings/Rankings.jsx b/src/components/Player/Pages/Rankings/Rankings.jsx index 2a8c5bf34e..a5d1fa6c07 100644 --- a/src/components/Player/Pages/Rankings/Rankings.jsx +++ b/src/components/Player/Pages/Rankings/Rankings.jsx @@ -11,7 +11,7 @@ import playerRankingsColumns from './playerRankingsColumns'; const Rankings = ({ data, error, loading }) => (
- +
diff --git a/src/lang/en-US.json b/src/lang/en-US.json index ad30b5f0ff..a6b41c50e8 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -419,7 +419,7 @@ "tab_wardmap": "Wardmap", "tab_wordcloud": "Wordcloud", "tab_mmr": "MMR", - "tab_rankings": "Seasonal Rankings", + "tab_rankings": "Rankings", "tab_benchmarks": "Benchmarks", "tab_performances": "Performances", "tab_damage": "Damage", @@ -701,11 +701,7 @@ "xp_reasons_2": "Hero", "xp_reasons_3": "Roshan", - "subheading_ranking": "Based on wins and average visible MMR in matches played", - "teamfight_participation": "Radiant participation/Dire participation", - "teamfight_score": "Radiant kills/Dire kills", - "teamfight_radiant_gold_adv": "Net gold advantage for Radiant", - "teamfight_radiant_xp_adv": "Net XP advantage for Radiant", + "rankings_description": "Based on visible MMR in matches won. Resets each quarter.", "vision_expired": "Expired after", "vision_destroyed": "Destroyed after", From 8597f8c01fd1ce32e7dbd148fcbd596d39aa9557 Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Thu, 16 Feb 2017 08:17:13 +0000 Subject: [PATCH 4/6] newline --- src/components/Matches/Matches.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Matches/Matches.css b/src/components/Matches/Matches.css index 5c6f8020a1..325c3ac5c5 100644 --- a/src/components/Matches/Matches.css +++ b/src/components/Matches/Matches.css @@ -16,4 +16,4 @@ & svg { fill: var(--colorGolden); } -} \ No newline at end of file +} From aba99f681bf19ddf33dbe25e61e43b05e1ca96f7 Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Fri, 17 Feb 2017 04:55:44 +0000 Subject: [PATCH 5/6] add images for heroes on teams --- src/components/Matches/index.jsx | 12 ++++++++++++ src/lang/en-US.json | 1 + 2 files changed, 13 insertions(+) diff --git a/src/components/Matches/index.jsx b/src/components/Matches/index.jsx index 8a48d447fb..ef1d5a92ff 100644 --- a/src/components/Matches/index.jsx +++ b/src/components/Matches/index.jsx @@ -1,3 +1,4 @@ +/* global API_HOST */ import React from 'react'; import { connect } from 'react-redux'; import Helmet from 'react-helmet'; @@ -12,6 +13,7 @@ import matchStyles from 'components/Match/Match.css'; import Match from 'components/Match'; import TabBar from 'components/TabBar'; import styles from './Matches.css'; +import heroes from 'dotaconstants/build/heroes.json'; const matchesColumns = [{ displayName: strings.th_match_id, @@ -59,6 +61,16 @@ const publicMatchesColumns = [ sortFn: true, displayFn: transformations.duration, }, + { + displayName: {strings.general_radiant}, + field: 'radiant_team', + displayFn: (row, col, field) => (field || '').split(',').map(heroId => ), + }, + { + displayName: {strings.general_dire}, + field: 'dire_team', + displayFn: (row, col, field) => (field || '').split(',').map(heroId => ), + } ]; const matchTabs = [{ diff --git a/src/lang/en-US.json b/src/lang/en-US.json index a6b41c50e8..9bd2ada684 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -554,6 +554,7 @@ "th_party_mmr": "Party MMR", "th_estimated_mmr": "Estimated MMR", "th_permanent_buffs": "Buffs", + "th_winner": "Winner", "ward_log_type": "Type", "ward_log_owner": "Owner", From 297c595d1dbdf5a3171a15c4d7928fda76ee5af6 Mon Sep 17 00:00:00 2001 From: Howard Chung Date: Fri, 17 Feb 2017 05:02:05 +0000 Subject: [PATCH 6/6] fix lint --- src/components/Matches/index.jsx | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/components/Matches/index.jsx b/src/components/Matches/index.jsx index ef1d5a92ff..41e72429cd 100644 --- a/src/components/Matches/index.jsx +++ b/src/components/Matches/index.jsx @@ -12,8 +12,8 @@ import { IconRadiant, IconDire, IconTrophy } from 'components/Icons'; import matchStyles from 'components/Match/Match.css'; import Match from 'components/Match'; import TabBar from 'components/TabBar'; -import styles from './Matches.css'; import heroes from 'dotaconstants/build/heroes.json'; +import styles from './Matches.css'; const matchesColumns = [{ displayName: strings.th_match_id, @@ -62,15 +62,17 @@ const publicMatchesColumns = [ displayFn: transformations.duration, }, { - displayName: {strings.general_radiant}, + displayName: {strings.general_radiant}, field: 'radiant_team', - displayFn: (row, col, field) => (field || '').split(',').map(heroId => ), + displayFn: (row, col, field) => (field || '').split(',').map(heroId => + ), }, - { - displayName: {strings.general_dire}, + { + displayName: {strings.general_dire}, field: 'dire_team', - displayFn: (row, col, field) => (field || '').split(',').map(heroId => ), - } + displayFn: (row, col, field) => (field || '').split(',').map(heroId => + ), + }, ]; const matchTabs = [{