diff --git a/Dockerfile b/Dockerfile index a3f91cd156..78130c7a7e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,4 +4,4 @@ ENV NPM_CONFIG_LOGLEVEL warn WORKDIR /usr/src -CMD ["npm", "start:install"] +CMD ["npm", "run", "start:install"] diff --git a/package-lock.json b/package-lock.json index 96ea00d5fc..130c941e54 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9009,7 +9009,8 @@ }, "ansi-regex": { "version": "2.1.1", - "bundled": true + "bundled": true, + "optional": true }, "aproba": { "version": "1.2.0", @@ -9027,11 +9028,13 @@ }, "balanced-match": { "version": "1.0.0", - "bundled": true + "bundled": true, + "optional": true }, "brace-expansion": { "version": "1.1.11", "bundled": true, + "optional": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -9044,15 +9047,18 @@ }, "code-point-at": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "concat-map": { "version": "0.0.1", - "bundled": true + "bundled": true, + "optional": true }, "console-control-strings": { "version": "1.1.0", - "bundled": true + "bundled": true, + "optional": true }, "core-util-is": { "version": "1.0.2", @@ -9155,7 +9161,8 @@ }, "inherits": { "version": "2.0.3", - "bundled": true + "bundled": true, + "optional": true }, "ini": { "version": "1.3.5", @@ -9165,6 +9172,7 @@ "is-fullwidth-code-point": { "version": "1.0.0", "bundled": true, + "optional": true, "requires": { "number-is-nan": "^1.0.0" } @@ -9177,17 +9185,20 @@ "minimatch": { "version": "3.0.4", "bundled": true, + "optional": true, "requires": { "brace-expansion": "^1.1.7" } }, "minimist": { "version": "0.0.8", - "bundled": true + "bundled": true, + "optional": true }, "minipass": { "version": "2.2.4", "bundled": true, + "optional": true, "requires": { "safe-buffer": "^5.1.1", "yallist": "^3.0.0" @@ -9204,6 +9215,7 @@ "mkdirp": { "version": "0.5.1", "bundled": true, + "optional": true, "requires": { "minimist": "0.0.8" } @@ -9276,7 +9288,8 @@ }, "number-is-nan": { "version": "1.0.1", - "bundled": true + "bundled": true, + "optional": true }, "object-assign": { "version": "4.1.1", @@ -9286,6 +9299,7 @@ "once": { "version": "1.4.0", "bundled": true, + "optional": true, "requires": { "wrappy": "1" } @@ -9361,7 +9375,8 @@ }, "safe-buffer": { "version": "5.1.1", - "bundled": true + "bundled": true, + "optional": true }, "safer-buffer": { "version": "2.1.2", @@ -9391,6 +9406,7 @@ "string-width": { "version": "1.0.2", "bundled": true, + "optional": true, "requires": { "code-point-at": "^1.0.0", "is-fullwidth-code-point": "^1.0.0", @@ -9408,6 +9424,7 @@ "strip-ansi": { "version": "3.0.1", "bundled": true, + "optional": true, "requires": { "ansi-regex": "^2.0.0" } @@ -9446,11 +9463,13 @@ }, "wrappy": { "version": "1.0.2", - "bundled": true + "bundled": true, + "optional": true }, "yallist": { "version": "3.0.2", - "bundled": true + "bundled": true, + "optional": true } } }, diff --git a/public/assets/images/dotacoach-32x24.png b/public/assets/images/dotacoach-32x24.png deleted file mode 100644 index ebd9497728..0000000000 Binary files a/public/assets/images/dotacoach-32x24.png and /dev/null differ diff --git a/public/assets/images/dotacoach-logo.png b/public/assets/images/dotacoach-logo.png deleted file mode 100644 index 80e45f9285..0000000000 Binary files a/public/assets/images/dotacoach-logo.png and /dev/null differ diff --git a/public/assets/images/gamerzclass-24px.png b/public/assets/images/gamerzclass-24px.png new file mode 100644 index 0000000000..9cc8425179 Binary files /dev/null and b/public/assets/images/gamerzclass-24px.png differ diff --git a/public/assets/images/gamerzclass-logo.png b/public/assets/images/gamerzclass-logo.png new file mode 100644 index 0000000000..2a45be20bc Binary files /dev/null and b/public/assets/images/gamerzclass-logo.png differ diff --git a/src/components/Home/Sponsors.jsx b/src/components/Home/Sponsors.jsx index 93b31110e3..92b4a6c1cb 100644 --- a/src/components/Home/Sponsors.jsx +++ b/src/components/Home/Sponsors.jsx @@ -1,9 +1,9 @@ -import React from 'react'; -import FlatButton from 'material-ui/FlatButton'; -import { connect } from 'react-redux'; -import PropTypes from 'prop-types'; -import styled from 'styled-components'; -import { ButtonsDiv } from './Styled'; +import React from "react"; +import FlatButton from "material-ui/FlatButton"; +import { connect } from "react-redux"; +import PropTypes from "prop-types"; +import styled from "styled-components"; +import { ButtonsDiv } from "./Styled"; const StyledDiv = styled.div` display: flex; @@ -35,33 +35,46 @@ const StyledDiv = styled.div` const Sponsors = ({ strings }) => ( -
- {strings.home_sponsored_by} -
+
{strings.home_sponsored_by}
- - + + - + - + - + - { process.env.ENABLE_GOSUAI && - + {process.env.ENABLE_GOSUAI && ( + - } + + )}
- {strings.home_become_sponsor} - + {strings.home_become_sponsor} } href="//carry.opendota.com" /> @@ -70,11 +83,11 @@ const Sponsors = ({ strings }) => ( ); Sponsors.propTypes = { - strings: PropTypes.shape({}), + strings: PropTypes.shape({}) }; const mapStateToProps = state => ({ - strings: state.app.strings, + strings: state.app.strings }); export default connect(mapStateToProps)(Sponsors); diff --git a/src/components/Match/MatchHeader/MatchHeader.jsx b/src/components/Match/MatchHeader/MatchHeader.jsx index 3b86b76db0..258ac4a18b 100644 --- a/src/components/Match/MatchHeader/MatchHeader.jsx +++ b/src/components/Match/MatchHeader/MatchHeader.jsx @@ -7,228 +7,239 @@ import styled from 'styled-components'; import NavigationRefresh from 'material-ui/svg-icons/navigation/refresh'; import ActionFingerprint from 'material-ui/svg-icons/action/fingerprint'; import FileFileDownload from 'material-ui/svg-icons/file/file-download'; +import ReactGA from 'react-ga'; import { transformations, isRadiant, sum } from '../../../utility'; import { IconRadiant, IconDire } from '../../Icons'; import Warning from '../../Alerts'; import constants from '../../constants'; const Styled = styled.header` -.matchInfo { - display: flex; - justify-content: space-between; - flex-wrap: wrap; -} - -.team { - box-sizing: border-box; - flex-basis: 33.33%; - max-width: 33.33%; - - @media only screen and (max-width: 1023px) { - flex-basis: 100%; - max-width: 100%; + .matchInfo { + display: flex; + justify-content: space-between; + flex-wrap: wrap; } - padding: 20px 0 10px; - font-size: 28px; - @media only screen and (max-width: 1023px) { - text-align: center; - margin: 10px 0; - } + .team { + box-sizing: border-box; + flex-basis: 33.33%; + max-width: 33.33%; - & > span { - padding-bottom: 5px; - letter-spacing: 1px; - } - - &.radiant > span { - background: linear-gradient(to right,rgba(167, 195, 42, 0) 0%, - rgba(129, 146, 60, 0) 5%,rgba(19,82,44,0.3) 50%, - rgba(96, 236, 8, 0.05) 87%, rgba(255,255,255,0) 100%); - } + @media only screen and (max-width: 1023px) { + flex-basis: 100%; + max-width: 100%; + } + padding: 20px 0 10px; + font-size: 28px; - &.dire > span { - background: linear-gradient(to right,rgba(117,132,52,0) 0%, - rgba(129,146,60,0) 5%,rgba(111,34,26,0.3) 50%, - rgba(255, 71, 0, 0.05) 87%, rgba(255,255,255,0) 100%); - } + @media only screen and (max-width: 1023px) { + text-align: center; + margin: 10px 0; + } - & svg { - width: 32px; - height: 32px; - margin: 0 15px; - vertical-align: sub; + & > span { + padding-bottom: 5px; + letter-spacing: 1px; + } - @media only screen and (max-width: 1023px) { - display: block; - margin: 0 auto; - width: 48px; - height: 48px; + &.radiant > span { + background: linear-gradient( + to right, + rgba(167, 195, 42, 0) 0%, + rgba(129, 146, 60, 0) 5%, + rgba(19, 82, 44, 0.3) 50%, + rgba(96, 236, 8, 0.05) 87%, + rgba(255, 255, 255, 0) 100% + ); } - } -} -.nowinner { - color: ${constants.colorMuted}; -} + &.dire > span { + background: linear-gradient( + to right, + rgba(117, 132, 52, 0) 0%, + rgba(129, 146, 60, 0) 5%, + rgba(111, 34, 26, 0.3) 50%, + rgba(255, 71, 0, 0.05) 87%, + rgba(255, 255, 255, 0) 100% + ); + } -.radiant { - color: ${constants.colorSuccess}; + & svg { + width: 32px; + height: 32px; + margin: 0 15px; + vertical-align: sub; - & svg { - filter: drop-shadow(0 0 5px green); - fill: ${constants.textColorPrimary} !important; + @media only screen and (max-width: 1023px) { + display: block; + margin: 0 auto; + width: 48px; + height: 48px; + } + } } -} -.dire { - color: ${constants.colorDanger}; - - & svg { - filter: drop-shadow(0 0 5px ${constants.colorDanger}); - fill: black !important; + .nowinner { + color: ${constants.colorMuted}; } -} -.mainInfo { - box-sizing: border-box; - flex-basis: 33.33%; - max-width: 33.33%; + .radiant { + color: ${constants.colorSuccess}; - @media only screen and (max-width: 1023px) { - flex-basis: 100%; - max-width: 100%; + & svg { + filter: drop-shadow(0 0 5px green); + fill: ${constants.textColorPrimary} !important; + } } - display: flex; - justify-content: center; - text-align: center; -} -.gmde { - margin: 0 20px; + .dire { + color: ${constants.colorDanger}; - @media only screen and (max-width: 400px) { - margin: 0 10px; + & svg { + filter: drop-shadow(0 0 5px ${constants.colorDanger}); + fill: black !important; + } } - & span { - text-transform: uppercase; - display: block; - } + .mainInfo { + box-sizing: border-box; + flex-basis: 33.33%; + max-width: 33.33%; - & .gameMode { - font-size: ${constants.fontSizeMedium}; + @media only screen and (max-width: 1023px) { + flex-basis: 100%; + max-width: 100%; + } + display: flex; + justify-content: center; + text-align: center; } - & .duration { - font-size: 28px; + .gmde { + margin: 0 20px; @media only screen and (max-width: 400px) { - font-size: 24px; + margin: 0 10px; } - } - & .ended { - font-size: ${constants.fontSizeSmall}; - color: ${constants.colorMutedLight}; - margin-top: 3px; + & span { + text-transform: uppercase; + display: block; + } - & > div { - display: inline-block; + & .gameMode { + font-size: ${constants.fontSizeMedium}; } - } -} -.killsRadiant { - font-size: 48px; - text-align: center; + & .duration { + font-size: 28px; - @media only screen and (max-width: 400px) { - font-size: 40px; - } - color: ${constants.colorSuccess}; -} + @media only screen and (max-width: 400px) { + font-size: 24px; + } + } -.killsDire { - font-size: 48px; - text-align: center; + & .ended { + font-size: ${constants.fontSizeSmall}; + color: ${constants.colorMutedLight}; + margin-top: 3px; - @media only screen and (max-width: 400px) { - font-size: 40px; + & > div { + display: inline-block; + } + } } - color: ${constants.colorDanger}; -} -.additionalInfo { - box-sizing: border-box; - flex-basis: 33.33%; - max-width: 33.33%; + .killsRadiant { + font-size: 48px; + text-align: center; - @media only screen and (max-width: 1023px) { - flex-basis: 100%; - max-width: 100%; + @media only screen and (max-width: 400px) { + font-size: 40px; + } + color: ${constants.colorSuccess}; } - text-align: right; - padding-top: 20px; - @media only screen and (max-width: 1023px) { + .killsDire { + font-size: 48px; text-align: center; - & span { - margin-bottom: 5px; + @media only screen and (max-width: 400px) { + font-size: 40px; } + color: ${constants.colorDanger}; } - & ul { - padding: 0; - margin: 0; + .additionalInfo { + box-sizing: border-box; + flex-basis: 33.33%; + max-width: 33.33%; - & li { - display: inline-block; - margin-left: 20px; + @media only screen and (max-width: 1023px) { + flex-basis: 100%; + max-width: 100%; + } + text-align: right; + padding-top: 20px; - & > span { - display: block; - text-transform: uppercase; - font-size: ${constants.fontSizeSmall}; - color: ${constants.colorMutedLight}; + @media only screen and (max-width: 1023px) { + text-align: center; + + & span { + margin-bottom: 5px; } } - & li:first-child { - margin-left: 0; - } - } -} + & ul { + padding: 0; + margin: 0; -.matchButtons { - display: table; - margin: 10px auto 0; + & li { + display: inline-block; + margin-left: 20px; - /* Material-ui buttons */ - & a { - float: left; - margin: 5px !important; - line-height: 34px !important; + & > span { + display: block; + text-transform: uppercase; + font-size: ${constants.fontSizeSmall}; + color: ${constants.colorMutedLight}; + } + } + + & li:first-child { + margin-left: 0; + } + } } - @media only screen and (max-width: 620px) { + .matchButtons { + display: table; + margin: 10px auto 0; + + /* Material-ui buttons */ & a { - min-width: 24px !important; + float: left; + margin: 5px !important; + line-height: 34px !important; + } - & span { - font-size: 0 !important; - padding-left: 0 !important; - padding-right: 12px !important; + @media only screen and (max-width: 620px) { + & a { + min-width: 24px !important; + + & span { + font-size: 0 !important; + padding-left: 0 !important; + padding-right: 12px !important; + } } } } -} -.unparsed { - text-align: center; - margin-top: 12px; -} + .unparsed { + text-align: center; + margin-top: 12px; + } `; const getWinnerStyle = (radiantWin) => { @@ -238,44 +249,42 @@ const getWinnerStyle = (radiantWin) => { return radiantWin ? 'radiant' : 'dire'; }; -const MatchHeader = ({ match, user, strings }) => { +const MatchHeader = ({ match, strings }) => { if (!match) { return null; } - const mapPlayers = (key, radiant) => - player => - ((radiant === undefined || radiant === isRadiant(player.player_slot)) ? Number(player[key]) : null); - - const victorySection = match.radiant_win - ? ( - - - {match.radiant_team && match.radiant_team.name - ? `${match.radiant_team.name} ${strings.match_team_win}` - : strings.match_radiant_win - } - ) - : ( - - - {match.dire_team && match.dire_team.name - ? `${match.dire_team.name} ${strings.match_team_win}` - : strings.match_dire_win - } - ); + const mapPlayers = (key, radiant) => player => + (radiant === undefined || radiant === isRadiant(player.player_slot) + ? Number(player[key]) + : null); + + const victorySection = match.radiant_win ? ( + + + {match.radiant_team && match.radiant_team.name + ? `${match.radiant_team.name} ${strings.match_team_win}` + : strings.match_radiant_win} + + ) : ( + + + {match.dire_team && match.dire_team.name + ? `${match.dire_team.name} ${strings.match_team_win}` + : strings.match_dire_win} + + ); return (
- {match.radiant_win === null || match.radiant_win === undefined ? strings.td_no_result : victorySection} + {match.radiant_win === null || match.radiant_win === undefined + ? strings.td_no_result + : victorySection}
- { - match.radiant_score || match.players - .map(mapPlayers('kills', true)) - .reduce(sum, 0) - } + {match.radiant_score || + match.players.map(mapPlayers('kills', true)).reduce(sum, 0)}
@@ -285,24 +294,27 @@ const MatchHeader = ({ match, user, strings }) => { {transformations.duration(null, null, match.duration)} - {strings.match_ended} {transformations.start_time(null, null, match.start_time + match.duration)} + {strings.match_ended}{' '} + {transformations.start_time( + null, + null, + match.start_time + match.duration, + )}
- { - match.dire_score || match.players - .map(mapPlayers('kills', false)) - .reduce(sum, 0) - } + {match.dire_score || + match.players.map(mapPlayers('kills', false)).reduce(sum, 0)}
    - {match.league && + {match.league && (
  • league {match.league.name} -
  • } + + )}
  • {strings.match_id} {match.match_id} @@ -313,39 +325,55 @@ const MatchHeader = ({ match, user, strings }) => {
  • {strings.th_skill} - {(match.skill) ? strings[`skill_${match.skill}`] : strings.general_unknown} + {match.skill + ? strings[`skill_${match.skill}`] + : strings.general_unknown}
- {!match.version && - - {strings.tooltip_unparsed} - } + {!match.version && ( + {strings.tooltip_unparsed} + )}
: } containerElement={r} /> - {match.replay_url && + {match.replay_url && ( } href={match.replay_url} target="_blank" rel="noopener noreferrer" - />} + /> + )} } - href={`//dotacoach.org/Hire/OpenDota?matchID=${match.match_id}&userSteamId=${user && user.account_id}`} + label={strings.app_gamerzclass} + icon={ + GamerzClass + } + href="https://gamerzclass.com/products/johan-n0tail-sundstein" target="_blank" - rel="noopener noreferrer" + onclick={() => + ReactGA.event({ + category: 'sponsor', + action: 'gamerzclass', + label: 'matchPage', + }) + } /> } + icon={ + + } href="https://www.rivalry.com/opendota" target="_blank" rel="noopener noreferrer" diff --git a/src/components/Player/Header/PlayerButtons.jsx b/src/components/Player/Header/PlayerButtons.jsx index d575aafc18..7110bdd8dd 100644 --- a/src/components/Player/Header/PlayerButtons.jsx +++ b/src/components/Player/Header/PlayerButtons.jsx @@ -4,6 +4,7 @@ import { connect } from 'react-redux'; import FlatButton from 'material-ui/FlatButton'; import ActionUpdate from 'material-ui/svg-icons/navigation/refresh'; import styled from 'styled-components'; +import ReactGA from 'react-ga'; import { toggleShowForm as toggleShowFormAction } from '../../../actions/formActions'; const Styled = styled.div` @@ -37,41 +38,47 @@ const Styled = styled.div` class PlayerButtons extends React.Component { static propTypes = { playerId: PropTypes.string, - playerSoloCompetitiveRank: PropTypes.number, strings: PropTypes.shape({}), - } + }; - state = { disableRefresh: false } + state = { disableRefresh: false }; render() { - const { - playerId, - playerSoloCompetitiveRank, - strings, - } = this.props; + const { playerId, strings } = this.props; return ( -
+
} disabled={this.state.disableRefresh} onClick={() => { - fetch(`${process.env.REACT_APP_API_HOST}/api/players/${playerId}/refresh`, { method: 'POST' }); + fetch( + `${process.env.REACT_APP_API_HOST}/api/players/${playerId}/refresh`, + { method: 'POST' }, + ); this.setState({ disableRefresh: true }); }} label={strings.app_refresh_label} />
} - href={`https://dotacoach.org/Hire/OpenDota?userSteamId=${playerId}&playerMmr=${playerSoloCompetitiveRank}`} + icon={ + GamerzClass + } + href="https://gamerzclass.com/products/johan-n0tail-sundstein" + target="_blank" + onclick={() => + ReactGA.event({ + category: 'sponsor', + action: 'gamerzclass', + label: 'playerPage', + }) + } /> - ); + + ); } } @@ -84,4 +91,7 @@ const mapDispatchToProps = dispatch => ({ toggleShowForm: () => dispatch(toggleShowFormAction('tableFilter')), }); -export default connect(mapStateToProps, mapDispatchToProps)(PlayerButtons); +export default connect( + mapStateToProps, + mapDispatchToProps, +)(PlayerButtons); diff --git a/src/lang/en-US.json b/src/lang/en-US.json index 0a5b862cbe..2056ec6592 100644 --- a/src/lang/en-US.json +++ b/src/lang/en-US.json @@ -85,9 +85,7 @@ "app_tracked": "This user has visited recently, and replays of new matches will be automatically parsed.", "app_cheese_bought": "Cheese bought", "app_contributor": "This user has contributed to the development of the OpenDota project", - "app_dotacoach": "Ask a Coach", - "app_pvgna": "Find a Guide", - "app_pvgna_alt": "Find a Dota 2 Guide on Pvgna", + "app_gamerzclass": "Take N0tail's Masterclass", "app_rivalry": "Bet on Pro Matches - 1st Bet is FREE", "app_rivalry_team": "Bet on {0} Matches - 1st Bet is FREE", "app_refresh": "Refresh Match History: Queue a scan to find missing matches due to privacy settings",