develop #215

Merged
andrey.dekterev merged 8 commits from develop into master 3 years ago
  1. 40
      .drone.yml
  2. 1
      package.json
  3. 1
      public/ads.txt
  4. BIN
      public/images/checkedRadiobutton.png
  5. BIN
      public/images/downloadIcon.png
  6. BIN
      public/images/radiobutton.png
  7. 54
      src/components/ErrorBoundary/index.tsx
  8. 2
      src/config/lexics/indexLexics.tsx
  9. 8
      src/config/lexics/matchDownload.tsx
  10. 2
      src/features/App/index.tsx
  11. 73
      src/features/MatchPage/components/MatchDownloadPopup/index.tsx
  12. 158
      src/features/MatchPage/components/MatchDownloadPopup/styled.tsx
  13. 67
      src/features/MatchSidePlaylists/components/MatchDownloadButton/index.tsx
  14. 4
      src/features/MatchSidePlaylists/components/MatchPlaylists/index.tsx
  15. 15
      src/features/MatchSidePlaylists/styled.tsx
  16. 10
      src/features/StreamPlayer/hooks/index.tsx
  17. 9
      src/helpers/callApi/logoutIfUnauthorized.tsx
  18. 15
      src/index.tsx
  19. 12
      src/requests/getUserInfo.tsx

@ -658,9 +658,28 @@ trigger:
- refs/heads/test-auth
steps:
- name: deploy script
- name: npm-install
image: node:16-alpine
environment:
REACT_APP_STRIPE_PK:
from_secret: REACT_APP_STRIPE_PK
commands:
- apk add --no-cache make
- npm install --legacy-peer-deps
- name: make-auth
image: node:16-alpine
environment:
REACT_APP_STRIPE_PK:
from_secret: REACT_APP_STRIPE_PK
commands:
- apk add --no-cache make
- make auth-build
depends_on:
- npm-install
- name: deploy-S3-auth
image: amazon/aws-cli:latest
environment:
AWS_ACCESS_KEY_ID:
from_secret: AWS_ACCESS_KEY_ID
@ -668,23 +687,12 @@ steps:
from_secret: AWS_SECRET_ACCESS_KEY
AWS_DEFAULT_REGION:
from_secret: AWS_DEFAULT_REGION
REACT_APP_STRIPE_PK:
from_secret: REACT_APP_STRIPE_PK_TEST
SSH_KEY_AUTH_TEST:
from_secret: SSH_KEY_AUTH_TEST
AWS_MAX_ATTEMPTS: 10
commands:
- apk add --no-cache aws-cli bash git openssh-client make rsync
- npm install --legacy-peer-deps
- make auth-build
- eval $(ssh-agent -s)
- echo -n "$SSH_KEY_AUTH_TEST" | tr -d '\r' | ssh-add -
- mkdir -p ~/.ssh && chmod 700 ~/.ssh
- ssh-keyscan auth.test.insports.tv >> ~/.ssh/known_hosts
- rsync -v -r -C build_auth/ ubuntu@auth.test.insports.tv:/home/ubuntu/ott-auth/src/frontend/
- rsync -v -r -C build_auth/clients/* ubuntu@auth.test.insports.tv:/home/ubuntu/ott-auth/src/frontend/templates
- aws s3 sync build_auth s3://auth-insports-test --delete
- aws s3 sync build_auth s3://insports-auth-test --delete
- aws cloudfront create-invalidation --distribution-id E10YI3RFOZZDLZ --paths "/*"
depends_on:
- make-auth
---

@ -23,6 +23,7 @@
},
"dependencies": {
"@reactour/tour": "^3.3.0",
"@sentry/react": "^7.53.1",
"@stripe/react-stripe-js": "^1.4.0",
"@stripe/stripe-js": "^1.13.2",
"babel-polyfill": "^6.26.0",

@ -0,0 +1 @@
google.com, pub-6802442215403184, DIRECT, f08c47fec0942fa0

Binary file not shown.

After

Width:  |  Height:  |  Size: 568 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 624 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

@ -1,8 +1,8 @@
// eslint-disable react/destructuring-assignment
import React from 'react'
import { Component } from 'react'
import type{ ReactNode } from 'react'
import type{ ErrorInfo, ReactNode } from 'react'
import * as Sentry from '@sentry/react'
import { Error } from '../Error'
@ -10,41 +10,15 @@ interface Props {
children?: ReactNode,
}
interface State {
hasError: boolean,
}
class ErrorBoundary extends Component<Props, State> {
// eslint-disable-next-line react/state-in-constructor
public state: State = {
hasError: false,
}
public static getDerivedStateFromError(_: Error): State {
// Update state so the next render will show the fallback UI.
return { hasError: true }
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
// eslint-disable-next-line no-console
console.error(
'Uncaught error:',
error,
errorInfo,
)
}
public render() {
const { hasError } = this.state
const { children } = this.props
return (
<>
{hasError && <Error />}
{children}
</>
)
}
}
export const ErrorBoundary = ({ children }: Props) => (
<Sentry.ErrorBoundary fallback={(
<>
{children}
<Error />
</>
)}
>
{ children }
</Sentry.ErrorBoundary>
)
export default ErrorBoundary

@ -4,6 +4,7 @@ import { highlightsPageLexic } from './highlightsPageLexic'
import { mailingsLexics } from './mailings'
import { sportsLexic } from './sportsLexic'
import { landingLexics } from './landingLexics'
import { matchDownload } from './matchDownload'
const matchPopupLexics = {
actions: 1020,
@ -221,4 +222,5 @@ export const indexLexics = {
...sportsLexic,
...sportsPopup,
...landingLexics,
...matchDownload,
}

@ -0,0 +1,8 @@
export const matchDownload = {
choose_what_to_download: 20193,
download_files_for_periods: 20197,
download_full_match: 9435,
download_single_file: 20196,
entire_record: 20195,
in_game_time_only: 20194,
}

@ -23,7 +23,7 @@ import { GlobalStyles } from 'features/GlobalStyles'
import { Theme } from 'features/Theme'
import { UnavailableText } from 'components/UnavailableText'
import ErrorBoundary from 'components/ErrorBoundary'
import { ErrorBoundary } from 'components/ErrorBoundary'
import { AuthenticatedApp } from './AuthenticatedApp'
import { useAuthStore } from '../AuthStore'

@ -0,0 +1,73 @@
import { useState } from 'react'
import { T9n } from 'features/T9n'
import {
Header,
Footer,
Modal,
ScApplyButton,
HeaderTitle,
Wrapper,
DownloadIcon,
FirstTitle,
SecondTitle,
RadioButtonsWrapper,
Input,
Label,
} from './styled'
type Props = {
closePopup: () => void,
isModalOpen: boolean,
}
export const MatchDownloadPopup = ({
closePopup,
isModalOpen,
}: Props) => {
const [selected, setSelected] = useState(true)
return (
<Modal
close={closePopup}
isOpen={isModalOpen}
>
<Wrapper>
<Header>
<DownloadIcon src='/images/downloadIcon.png' />
<HeaderTitle>
<FirstTitle t='download_full_match' />
<SecondTitle t='choose_what_to_download' />
</HeaderTitle>
</Header>
<RadioButtonsWrapper>
<Label>
<Input
defaultChecked={selected}
name='in_game_time_only'
onClick={() => setSelected(true)}
/>
<T9n t='in_game_time_only' />
</Label>
<Label>
<Input
name='entire_record'
defaultChecked={!selected}
onClick={() => setSelected(false)}
/>
<T9n t='entire_record' />
</Label>
</RadioButtonsWrapper>
<Footer>
<ScApplyButton>
<T9n t='download_single_file' />
</ScApplyButton>
<ScApplyButton disabled={!selected}>
<T9n t='download_files_for_periods' />
</ScApplyButton>
</Footer>
</Wrapper>
</Modal>
)
}

@ -0,0 +1,158 @@
import styled, { css } from 'styled-components/macro'
import { isMobileDevice } from 'config'
import { T9n } from 'features/T9n'
import { ModalWindow, ModalCloseButton } from 'features/Modal/styled'
import { Header as BaseHeader } from 'features/PopupComponents'
import {
ApplyButton,
Modal as BaseModal,
} from 'features/AuthServiceApp/components/RegisterPopup/styled'
export const Modal = styled(BaseModal)`
${ModalWindow} {
width: 577px;
height: 490px;
padding: 80px 90px 65px;
min-height: auto;
${ModalCloseButton} {
height: 28px;
width: 28px;
svg {
width: 20px;
height: 12px;
}
}
${isMobileDevice
? css`
max-width: 95vw;
max-height: 75vh;
top: -3vh;
padding: 60px 14px 20px;`
: ''};
`
export const Wrapper = styled.div``
export const Header = styled(BaseHeader)`
display: flex;
align-items: center;
height: 100%;
`
export const DownloadIcon = styled.img`
margin-right: 25px;
${isMobileDevice
? css`
height: 55px;
width: 44px;`
: ''};
`
export const HeaderTitle = styled.div`
display: flex;
flex-direction: column;
`
export const FirstTitle = styled(T9n)`
font-weight: 700;
font-size: 24px;
line-height: 24px;
margin-bottom: 10px;
${isMobileDevice
? css`
font-size: 20px;`
: ''};
`
export const SecondTitle = styled(T9n)`
font-weight: 400;
font-size: 20px;
line-height: 28px;
${isMobileDevice
? css`
font-size: 14px;
line-height: 17px;`
: ''};
`
export const RadioButtonsWrapper = styled.div`
margin: 25px 0;
`
export const Label = styled.label`
display: flex;
cursor: pointer;
font-size: 18px;
line-height: 50px;
align-items: center;
${isMobileDevice
? css`
font-size: 14px;`
: ''};
`
export const Input = styled.input.attrs(() => ({
type: 'radio',
}))`
margin: 0 25px 0 0;
appearance: none;
width: 25px;
height: 25px;
cursor: pointer;
background-image: url(/images/${({ defaultChecked }) => (
defaultChecked
? 'checkedRadiobutton.png'
: 'radiobutton.png'
)});
${isMobileDevice
? css`
margin-right: 10px;`
: ''};
`
export const Footer = styled.div``
export const ScApplyButton = styled(ApplyButton)`
width: 400px;
height: 50px;
margin: 0;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0) 100%), #3F3F3F;
transition: background-color 0.3s;
:first-child {
margin-bottom: 20px;
}
&:hover {
background-color: ${({ theme: { colors } }) => colors.button};
}
:disabled {
pointer-events: none;
}
${isMobileDevice
? css`
font-size: 14px;
width: 100%;
height: 50px;
:first-child {
margin-bottom: 10px;
}`
: ''};
`

@ -0,0 +1,67 @@
import some from 'lodash/some'
import type { TeamsAndTournaments } from 'requests'
import { useToggle } from 'hooks/useToggle'
import { T9n } from 'features/T9n'
import { useMatchPageStore } from 'features/MatchPage/store'
import { useAuthStore } from 'features/AuthStore'
import { MatchDownloadPopup } from 'features/MatchPage/components/MatchDownloadPopup'
import { usePageParams } from 'hooks/usePageParams'
import { Item } from '../MatchPlaylists'
import { DownloadButton, Title } from '../../styled'
export const MatchDownloadButton = () => {
const { user, userInfo } = useAuthStore()
const { profile } = useMatchPageStore()
const { sportType } = usePageParams()
const {
close,
isOpen,
open,
} = useToggle()
const checkDownloadData = (
checkArray: Array<TeamsAndTournaments>,
id?: number,
) => some(checkArray, (['c_sport', sportType] && ['id', id]))
const teams = userInfo?.download.teams
const tournaments = userInfo?.download.tournaments
const isAvailableTeams = () => {
if (teams) {
return checkDownloadData(teams, profile?.team1.id)
|| checkDownloadData(teams, profile?.team2.id)
}
return null
}
const isAvailableTournaments = () => {
if (tournaments) return checkDownloadData(tournaments, profile?.tournament.id)
return null
}
const isNeedDownloadButton = user && (isAvailableTournaments() || isAvailableTeams())
if (!isNeedDownloadButton) return null
return (
<Item>
<MatchDownloadPopup
isModalOpen={isOpen}
closePopup={close}
/>
<DownloadButton onClick={open}>
<Title>
<T9n t='download_full_match' />
</Title>
</DownloadButton>
</Item>
)
}

@ -20,6 +20,7 @@ import { useMatchPageStore } from 'features/MatchPage/store'
import { useLexicsStore } from 'features/LexicsStore'
import { PlayButton } from '../PlayButton'
import { MatchDownloadButton } from '../MatchDownloadButton'
export const LIST_INDENT = 30
@ -34,7 +35,7 @@ const List = styled.ul`
margin-bottom: ${LIST_INDENT}px;
`
const Item = styled.li`
export const Item = styled.li`
margin-bottom: 12px;
width: 100%;
height: 36px;
@ -94,6 +95,7 @@ export const MatchPlaylists = forwardRef(
</Item>
))
}
<MatchDownloadButton />
</List>
)
},

@ -219,6 +219,21 @@ export const Button = styled.button<ButtonProps>`
}}
`
export const DownloadButton = styled(Button)`
:hover {
background-color: ${({ theme }) => theme.colors.buttonHover};
}
${({ active }) => (active
? css`
border: 1px solid #FFFFFF;
border-radius: 2px;
background-color: black;
`
: '')}
`
export const Title = styled.span`
font-weight: 600;
font-size: 14px;

@ -20,7 +20,11 @@ import values from 'lodash/values'
import Hls from 'hls.js'
import { isIOS, KEYBOARD_KEYS } from 'config'
import {
isIOS,
isMobileDevice,
KEYBOARD_KEYS,
} from 'config'
import {
useObjectState,
@ -601,13 +605,13 @@ export const useVideoPlayer = ({
}, [setPlayerState])
useEffect(() => {
if (ready && videoRef && !isPlayingEpisode) {
if (ready && videoRef && !isMobileDevice) {
videoRef.current?.scrollIntoView({
behavior: 'smooth',
block: 'start',
})
}
}, [ready, videoRef, isPlayingEpisode])
}, [ready, videoRef])
useEffect(() => {
setCircleAnimation((state) => ({

@ -1,5 +1,13 @@
import * as Sentry from '@sentry/react'
export const logoutIfUnauthorized = async (response: Response) => {
/* отключили из-за доступа без авторизации */
const body = await response.json()
if (response.status === 400) {
Sentry.captureException(body)
}
if (response.status === 401 || response.status === 403) {
window.dispatchEvent(new Event('FORBIDDEN_REQUEST'))
}
@ -8,6 +16,5 @@ export const logoutIfUnauthorized = async (response: Response) => {
// eslint-disable-next-line no-console
console.error(error)
const body = await response.json()
return Promise.reject(body)
}

@ -5,11 +5,24 @@ import {
} from 'react'
import ReactDOM from 'react-dom'
import { isIOS } from 'config/userAgent'
import * as Sentry from '@sentry/react'
import { BrowserTracing } from '@sentry/react'
import { isIOS, ENV } from 'config'
// import { makeServer } from 'utilits/mirage/Mirage'
import * as serviceWorker from './serviceWorker'
if (process.env.NODE_ENV !== 'development') {
Sentry.init({
dsn: 'https://bbe0cdfb954644ebaf3be16bb472cc3d@sentry.insports.tv/21',
environment: ENV,
integrations: [new BrowserTracing()],
tracesSampleRate: 1.0,
})
}
export const App = process.env.REACT_APP_TYPE === 'auth-service'
? lazy(() => import('features/AuthServiceApp'))
: lazy(() => import('features/App'))

@ -6,6 +6,13 @@ import { callApi } from 'helpers'
const proc = PROCEDURES.get_user_info
export type TeamsAndTournaments = {
c_sport: number,
id: number,
name_eng: string,
name_rus: string,
}
export type UserInfo = {
address_line1: string | null,
address_line2: string | null,
@ -16,6 +23,11 @@ export type UserInfo = {
name_eng: string,
name_rus: string,
},
download: {
id?: number,
teams: Array<TeamsAndTournaments> | null,
tournaments: Array<TeamsAndTournaments> | null,
},
email: string,
firstname: string | null,
has_subscription: boolean,

Loading…
Cancel
Save