From c55916c3d4439fac2ce594faf662fe669b60d30c Mon Sep 17 00:00:00 2001 From: rjshrjndrn Date: Wed, 23 Feb 2022 13:01:26 +0100 Subject: [PATCH 1/5] chore(websocket): enabling consistent hashing for sticky load balancing Signed-off-by: rjshrjndrn --- .../nginx-ingress/templates/configMap.yaml | 21 +++++++++++-------- .../charts/utilities/templates/service.yaml | 20 ++++++++++++++++++ 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml b/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml index f5b7699cd..ee0bc590e 100644 --- a/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml +++ b/scripts/helmcharts/openreplay/charts/nginx-ingress/templates/configMap.yaml @@ -39,8 +39,8 @@ data: proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; proxy_set_header X-Forwarded-For $origin_forwarded_ip; - proxy_set_header X-Forwarded-Host $real_ip; - proxy_set_header X-Real-IP $real_ip; + proxy_set_header X-Forwarded-Host $origin_forwarded_ip; + proxy_set_header X-Real-IP $origin_forwarded_ip; proxy_set_header Host $host; proxy_pass http://http-openreplay.app.svc.cluster.local; proxy_read_timeout 300; @@ -81,8 +81,8 @@ data: proxy_set_header Connection "Upgrade"; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $origin_forwarded_ip; - proxy_set_header X-Real-IP $real_ip; - proxy_pass http://utilities-openreplay.app.svc.cluster.local:9001; + proxy_set_header X-Real-IP $origin_forwarded_ip; + proxy_pass http://utilities-pool; } location /assets/ { rewrite ^/assets/(.*) /sessions-assets/$1 break; @@ -139,7 +139,7 @@ data: # Need real ip address for flags in replay. # Some LBs will forward real ips as x-forwarded-for # So making that as priority - map $http_x_forwarded_for $real_ip { + map $http_x_forwarded_for $origin_forwarded_ip { ~^(\d+\.\d+\.\d+\.\d+) $1; default $remote_addr; } @@ -151,10 +151,6 @@ data: default $http_x_forwarded_proto; '' $scheme; } - map $http_x_forwarded_for $origin_forwarded_ip { - default $http_x_forwarded_for; - '' $remote_addr; - } # Default server for helath check server { listen 80 default_server; @@ -163,6 +159,13 @@ data: return 200 'OK'; } } + + upstream utilities-pool { + server utilities-openreplay-headless.app:9001; + # enable sticky session with either "hash" (uses the complete IP address) + hash $origin_forwarded_ip consistent; + } + server { listen 80; listen [::]:80; diff --git a/scripts/helmcharts/openreplay/charts/utilities/templates/service.yaml b/scripts/helmcharts/openreplay/charts/utilities/templates/service.yaml index 9ec9f18cf..8b1dc8753 100644 --- a/scripts/helmcharts/openreplay/charts/utilities/templates/service.yaml +++ b/scripts/helmcharts/openreplay/charts/utilities/templates/service.yaml @@ -15,3 +15,23 @@ spec: {{- end}} selector: {{- include "utilities.selectorLabels" . | nindent 4 }} + +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ include "utilities.fullname" . }}-headless + labels: + {{- include "utilities.labels" . | nindent 4 }} +spec: + type: ClusterIP + clusterIP: None + ports: + {{- range $key, $val := .Values.service.ports }} + - port: {{ $val }} + targetPort: {{ $key }} + protocol: TCP + name: {{ $key }} + {{- end}} + selector: + {{- include "utilities.selectorLabels" . | nindent 4 }} From f6668ebc97454dbc56cce451dbd64d4ed755c0e1 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 23 Feb 2022 14:17:56 +0100 Subject: [PATCH 2/5] feat(ui) - live player separate the route --- frontend/app/Router.js | 5 +- frontend/app/components/Assist/Assist.tsx | 5 +- frontend/app/components/Session/LivePlayer.js | 18 ++---- .../app/components/Session/LiveSession.js | 60 +++++++++++++++++++ .../Session_/Player/Controls/Controls.js | 57 ++++++++++-------- .../components/Session_/Player/Overlay.tsx | 4 +- .../Player/Overlay/LiveStatusText.tsx | 8 +++ .../app/components/Session_/Player/Player.js | 14 ++--- .../app/components/Session_/PlayerBlock.js | 5 +- .../components/Session_/PlayerBlockHeader.js | 30 +++------- .../shared/SessionItem/SessionItem.js | 4 +- .../managers/AssistManager.ts | 3 + frontend/app/routes.js | 4 +- frontend/tailwind.config.js | 2 +- 14 files changed, 140 insertions(+), 79 deletions(-) create mode 100644 frontend/app/components/Session/LiveSession.js diff --git a/frontend/app/Router.js b/frontend/app/Router.js index 0c0e7433a..86f07c4f6 100644 --- a/frontend/app/Router.js +++ b/frontend/app/Router.js @@ -11,6 +11,7 @@ import UpdatePassword from 'Components/UpdatePassword/UpdatePassword'; import ClientPure from 'Components/Client/Client'; import OnboardingPure from 'Components/Onboarding/Onboarding'; import SessionPure from 'Components/Session/Session'; +import LiveSessionPure from 'Components/Session/LiveSession'; import AssistPure from 'Components/Assist'; import BugFinderPure from 'Components/BugFinder/BugFinder'; import DashboardPure from 'Components/Dashboard/Dashboard'; @@ -31,6 +32,7 @@ import { setSessionPath } from 'Duck/sessions'; const BugFinder = withSiteIdUpdater(BugFinderPure); const Dashboard = withSiteIdUpdater(DashboardPure); const Session = withSiteIdUpdater(SessionPure); +const LiveSession = withSiteIdUpdater(LiveSessionPure); const Assist = withSiteIdUpdater(AssistPure); const Client = withSiteIdUpdater(ClientPure); const Onboarding = withSiteIdUpdater(OnboardingPure); @@ -119,7 +121,7 @@ class Router extends React.Component { render() { const { isLoggedIn, jwt, siteId, sites, loading, changePassword, location, existingTenant, onboarding } = this.props; const siteIdList = sites.map(({ id }) => id).toJS(); - const hideHeader = location.pathname && location.pathname.includes('/session/'); + const hideHeader = location.pathname && location.pathname.includes('/session/') || location.pathname.includes('/assist/'); return isLoggedIn ? @@ -160,6 +162,7 @@ class Router extends React.Component { + } /> { routes.redirects.map(([ fr, to ]) => ( diff --git a/frontend/app/components/Assist/Assist.tsx b/frontend/app/components/Assist/Assist.tsx index 77730f7b1..0d901337b 100644 --- a/frontend/app/components/Assist/Assist.tsx +++ b/frontend/app/components/Assist/Assist.tsx @@ -5,13 +5,10 @@ import cn from 'classnames' import withPageTitle from 'HOCs/withPageTitle'; import withPermissions from 'HOCs/withPermissions' -// @withPageTitle("Assist - OpenReplay") function Assist() { return (
- {/*
-
*/}
@@ -22,4 +19,4 @@ function Assist() { ) } -export default withPageTitle("Assist - OpenReplay")(withPermissions(['ASSIST_LIVE', 'SESSION_REPLAY'])(Assist)); +export default withPageTitle("Assist - OpenReplay")(withPermissions(['ASSIST_LIVE'])(Assist)); diff --git a/frontend/app/components/Session/LivePlayer.js b/frontend/app/components/Session/LivePlayer.js index 81b4df5e0..967807556 100644 --- a/frontend/app/components/Session/LivePlayer.js +++ b/frontend/app/components/Session/LivePlayer.js @@ -12,27 +12,19 @@ import { import withPermissions from 'HOCs/withPermissions'; import PlayerBlockHeader from '../Session_/PlayerBlockHeader'; -import EventsBlock from '../Session_/EventsBlock'; import PlayerBlock from '../Session_/PlayerBlock'; import styles from '../Session_/session.css'; - -const EventsBlockConnected = connectPlayer(state => ({ - currentTimeEventIndex: state.eventListNow.length > 0 ? state.eventListNow.length - 1 : 0, - playing: state.playing, -}))(EventsBlock) - - const InitLoader = connectPlayer(state => ({ loading: !state.initialized }))(Loader); -function WebPlayer ({ showAssist, session, toggleFullscreen, closeBottomBlock, live, fullscreen, jwt, loadingCredentials, assistCredendials, request, isEnterprise, hasSessionsPath }) { +function LivePlayer ({ session, toggleFullscreen, closeBottomBlock, fullscreen, jwt, loadingCredentials, assistCredendials, request, isEnterprise, hasErrors }) { useEffect(() => { if (!loadingCredentials) { - initPlayer(session, jwt, assistCredendials, !hasSessionsPath && session.live); + initPlayer(session, jwt, assistCredendials, true); } return () => cleanPlayer() }, [ session.sessionId, loadingCredentials, assistCredendials ]); @@ -48,11 +40,10 @@ function WebPlayer ({ showAssist, session, toggleFullscreen, closeBottomBlock, l } }, []) - return ( - +
@@ -78,7 +69,8 @@ export default withRequest({ fullscreen: state.getIn([ 'components', 'player', 'fullscreen' ]), hasSessionsPath: hasSessioPath && !isAssist, isEnterprise: state.getIn([ 'user', 'client', 'edition' ]) === 'ee', + hasErrors: !!state.getIn([ 'sessions', 'errors' ]), } }, { toggleFullscreen, closeBottomBlock }, -)(WebPlayer))); +)(LivePlayer))); diff --git a/frontend/app/components/Session/LiveSession.js b/frontend/app/components/Session/LiveSession.js new file mode 100644 index 000000000..46bd39cf5 --- /dev/null +++ b/frontend/app/components/Session/LiveSession.js @@ -0,0 +1,60 @@ +import { useEffect } from 'react'; +import { connect } from 'react-redux'; +import usePageTitle from 'App/hooks/usePageTitle'; +import { fetch as fetchSession } from 'Duck/sessions'; +import { fetchList as fetchSlackList } from 'Duck/integrations/slack'; +import { Link, NoContent, Loader } from 'UI'; +import { sessions as sessionsRoute } from 'App/routes'; +import withPermissions from 'HOCs/withPermissions' +import LivePlayer from './LivePlayer'; + +const SESSIONS_ROUTE = sessionsRoute(); + +function LiveSession({ + sessionId, + loading, + hasErrors, + session, + fetchSession, + fetchSlackList, + hasSessionsPath + }) { + usePageTitle("OpenReplay Assist"); + + useEffect(() => { + fetchSlackList() + }, []); + + useEffect(() => { + if (sessionId != null) { + fetchSession(sessionId) + } else { + console.error("No sessionID in route.") + } + return () => { + if (!session.exists()) return; + } + },[ sessionId, hasSessionsPath ]); + + return ( + + + + ); +} + +export default withPermissions(['ASSIST_LIVE'], '', true)(connect((state, props) => { + const { match: { params: { sessionId } } } = props; + const isAssist = state.getIn(['sessions', 'activeTab']).type === 'live'; + const hasSessiosPath = state.getIn([ 'sessions', 'sessionPath' ]).includes('/sessions'); + return { + sessionId, + loading: state.getIn([ 'sessions', 'loading' ]), + hasErrors: !!state.getIn([ 'sessions', 'errors' ]), + session: state.getIn([ 'sessions', 'current' ]), + hasSessionsPath: hasSessiosPath && !isAssist, + }; +}, { + fetchSession, + fetchSlackList, +})(LiveSession)); \ No newline at end of file diff --git a/frontend/app/components/Session_/Player/Controls/Controls.js b/frontend/app/components/Session_/Player/Controls/Controls.js index b21d45f77..464165e69 100644 --- a/frontend/app/components/Session_/Player/Controls/Controls.js +++ b/frontend/app/components/Session_/Player/Controls/Controls.js @@ -106,6 +106,7 @@ function getStorageName(type) { bottomBlock: state.getIn([ 'components', 'player', 'bottomBlock' ]), showStorage: props.showStorage || !state.getIn(['components', 'player', 'hiddenHints', 'storage']), showStack: props.showStack || !state.getIn(['components', 'player', 'hiddenHints', 'stack']), + closedLive: !!state.getIn([ 'sessions', 'errors' ]), } }, { fullscreenOn, @@ -253,7 +254,8 @@ export default class Controls extends React.Component { showExceptions, fullscreen, skipToIssue, - inspectorMode + inspectorMode, + closedLive, } = this.props; // const inspectorMode = bottomBlock === INSPECTOR; @@ -263,30 +265,35 @@ export default class Controls extends React.Component { { !live && } { !fullscreen &&
- { !live ? -
- { this.renderPlayBtn() } - - -
- : -
- - {'Elapsed'} - -
- } +
+ { !live && ( +
+ { this.renderPlayBtn() } + + +
+ )} + + { live && !closedLive && ( +
+ + {'Elapsed'} + +
+ )} +
+
{!live && diff --git a/frontend/app/components/Session_/Player/Overlay.tsx b/frontend/app/components/Session_/Player/Overlay.tsx index bed0e3a00..994608108 100644 --- a/frontend/app/components/Session_/Player/Overlay.tsx +++ b/frontend/app/components/Session_/Player/Overlay.tsx @@ -25,6 +25,7 @@ interface Props { nextId: string, togglePlay: () => void, + closedLive?: boolean } function Overlay({ @@ -41,6 +42,7 @@ function Overlay({ activeTargetIndex, nextId, togglePlay, + closedLive }: Props) { // useEffect(() =>{ @@ -56,7 +58,7 @@ function Overlay({ <> { showAutoplayTimer && } { showLiveStatusText && - + } { messagesLoading && } { showPlayIconLayer && diff --git a/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx b/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx index b642a8a7c..3f24901de 100644 --- a/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx +++ b/frontend/app/components/Session_/Player/Overlay/LiveStatusText.tsx @@ -12,6 +12,14 @@ interface Props { export default function LiveStatusText({ text, concetionStatus }: Props) { const renderView = () => { switch (concetionStatus) { + case ConnectionStatus.Closed: + return ( +
+
Session not found
+
The remote session doesn’t exist anymore.
The user may have closed the tab/browser while you were trying to establish a connection.
+
+ ) + case ConnectionStatus.Connecting: return (
diff --git a/frontend/app/components/Session_/Player/Player.js b/frontend/app/components/Session_/Player/Player.js index baae88ea3..a3a6e3b1a 100644 --- a/frontend/app/components/Session_/Player/Player.js +++ b/frontend/app/components/Session_/Player/Player.js @@ -1,7 +1,7 @@ import { connect } from 'react-redux'; import { findDOMNode } from 'react-dom'; import cn from 'classnames'; -import { Loader, IconButton, EscapeButton } from 'UI'; +import { EscapeButton } from 'UI'; import { hide as hideTargetDefiner } from 'Duck/components/targetDefiner'; import { fullscreenOff } from 'Duck/components/player'; import { attach as attachPlayer, Controls as PlayerControls, connectPlayer } from 'Player'; @@ -10,14 +10,13 @@ import Overlay from './Overlay'; import stl from './player.css'; import EventsToggleButton from '../../Session/EventsToggleButton'; - @connectPlayer(state => ({ live: state.live, })) @connect(state => ({ - //session: state.getIn([ 'sessions', 'current' ]), fullscreen: state.getIn([ 'components', 'player', 'fullscreen' ]), nextId: state.getIn([ 'sessions', 'nextId' ]), + closedLive: !!state.getIn([ 'sessions', 'errors' ]), }), { hideTargetDefiner, fullscreenOff, @@ -26,6 +25,8 @@ export default class Player extends React.PureComponent { screenWrapper = React.createRef(); componentDidMount() { + if (this.props.closedLive) return; + const parentElement = findDOMNode(this.screenWrapper.current); //TODO: good architecture attachPlayer(parentElement); } @@ -38,6 +39,7 @@ export default class Player extends React.PureComponent { fullscreenOff, nextId, live, + closedLive, } = this.props; return ( @@ -45,12 +47,10 @@ export default class Player extends React.PureComponent { className={ cn(className, stl.playerBody, "flex flex-col relative") } data-bottom-block={ bottomBlockIsActive } > - { fullscreen && - - } + {fullscreen && } {!live && !fullscreen && }
- +
({ fullscreen: state.getIn([ 'components', 'player', 'fullscreen' ]), bottomBlock: state.getIn([ 'components', 'player', 'bottomBlock' ]), + closedLive: !!state.getIn([ 'sessions', 'errors' ]), })) export default class PlayerBlock extends React.PureComponent { componentDidUpdate(prevProps) { @@ -44,13 +44,14 @@ export default class PlayerBlock extends React.PureComponent { } render() { - const { fullscreen, bottomBlock } = this.props; + const { fullscreen, bottomBlock, closedLive } = this.props; return (
{ !fullscreen && !!bottomBlock &&
diff --git a/frontend/app/components/Session_/PlayerBlockHeader.js b/frontend/app/components/Session_/PlayerBlockHeader.js index d352db2b4..6e274d4b1 100644 --- a/frontend/app/components/Session_/PlayerBlockHeader.js +++ b/frontend/app/components/Session_/PlayerBlockHeader.js @@ -2,12 +2,12 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { browserIcon, osIcon, deviceTypeIcon } from 'App/iconNames'; import { formatTimeOrDate } from 'App/date'; -import { sessions as sessionsRoute, withSiteId } from 'App/routes'; +import { sessions as sessionsRoute, assist as assistRoute, withSiteId } from 'App/routes'; import { Icon, CountryFlag, IconButton, BackLink, Popup } from 'UI'; import { toggleFavorite, setSessionPath } from 'Duck/sessions'; import cn from 'classnames'; import { connectPlayer } from 'Player'; -import HeaderInfo from './HeaderInfo'; +// import HeaderInfo from './HeaderInfo'; import SharePopup from '../shared/SharePopup/SharePopup'; import { fetchList as fetchListIntegration } from 'Duck/integrations/actions'; import { countries } from 'App/constants'; @@ -21,10 +21,7 @@ import AssistTabs from '../Assist/components/AssistTabs'; import SessionInfoItem from './SessionInfoItem' const SESSIONS_ROUTE = sessionsRoute(); - -function capitalise(str) { - return str[0].toUpperCase() + str.slice(1); -} +const ASSIST_ROUTE = assistRoute(); @connectPlayer(state => ({ width: state.width, height: state.height, @@ -46,6 +43,7 @@ function capitalise(str) { siteId: state.getIn([ 'user', 'siteId' ]), hasSessionsPath: hasSessioPath && !isAssist, metaList: state.getIn(['customFields', 'list']).map(i => i.key), + closedLive: !!state.getIn([ 'sessions', 'errors' ]), } }, { toggleFavorite, fetchListIntegration, setSessionPath @@ -67,8 +65,9 @@ export default class PlayerBlockHeader extends React.PureComponent { backHandler = () => { const { history, siteId, sessionPath } = this.props; - if (sessionPath === history.location.pathname || sessionPath.includes("/session/")) { - history.push(withSiteId(SESSIONS_ROUTE), siteId); + const isLiveSession = sessionPath.includes("/assist"); + if (sessionPath === history.location.pathname || sessionPath.includes("/session/") || isLiveSession) { + history.push(withSiteId(isLiveSession ? ASSIST_ROUTE: SESSIONS_ROUTE, siteId)); } else { history.push(sessionPath ? sessionPath : withSiteId(SESSIONS_ROUTE, siteId)); } @@ -107,6 +106,7 @@ export default class PlayerBlockHeader extends React.PureComponent { hasSessionsPath, sessionPath, metaList, + closedLive = false, } = this.props; const _live = live && !hasSessionsPath; @@ -122,20 +122,8 @@ export default class PlayerBlockHeader extends React.PureComponent {
{ _live && } - - {/*
- -
- { formatTimeOrDate(startedAt) } { this.props.local === 'UTC' ? 'UTC' : ''} -
-
- - - - */} - -
+
{ live && hasSessionsPath && ( <>
this.props.setSessionPath('')}> diff --git a/frontend/app/components/shared/SessionItem/SessionItem.js b/frontend/app/components/shared/SessionItem/SessionItem.js index 324c6b723..023c9c724 100644 --- a/frontend/app/components/shared/SessionItem/SessionItem.js +++ b/frontend/app/components/shared/SessionItem/SessionItem.js @@ -11,7 +11,7 @@ import { } from 'UI'; import { deviceTypeIcon } from 'App/iconNames'; import { toggleFavorite, setSessionPath } from 'Duck/sessions'; -import { session as sessionRoute, withSiteId } from 'App/routes'; +import { session as sessionRoute, liveSession as liveSessionRoute, withSiteId } from 'App/routes'; import { durationFormatted, formatTimeOrDate } from 'App/date'; import stl from './sessionItem.css'; import LiveTag from 'Shared/LiveTag'; @@ -136,7 +136,7 @@ export default class SessionItem extends React.PureComponent {
- +
diff --git a/frontend/app/player/MessageDistributor/managers/AssistManager.ts b/frontend/app/player/MessageDistributor/managers/AssistManager.ts index 0b09469a1..51895b327 100644 --- a/frontend/app/player/MessageDistributor/managers/AssistManager.ts +++ b/frontend/app/player/MessageDistributor/managers/AssistManager.ts @@ -26,6 +26,7 @@ export enum ConnectionStatus { Inactive, Disconnected, Error, + Closed, } export enum RemoteControlStatus { @@ -37,6 +38,8 @@ export enum RemoteControlStatus { export function getStatusText(status: ConnectionStatus): string { switch(status) { + case ConnectionStatus.Closed: + return 'Closed...'; case ConnectionStatus.Connecting: return "Connecting..."; case ConnectionStatus.Connected: diff --git a/frontend/app/routes.js b/frontend/app/routes.js index 0f10950df..f9987d49c 100644 --- a/frontend/app/routes.js +++ b/frontend/app/routes.js @@ -85,7 +85,8 @@ export const sessions = params => queried('/sessions', params); export const assist = params => queried('/assist', params); export const session = (sessionId = ':sessionId', hash) => hashed(`/session/${ sessionId }`, hash); -export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/live/session/${ sessionId }`, hash); +export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/assist/${ sessionId }`, hash); +// export const liveSession = (sessionId = ':sessionId', hash) => hashed(`/live/session/${ sessionId }`, hash); export const errors = params => queried('/errors', params); export const error = (id = ':errorId', hash) => hashed(`/errors/${ id }`, hash); @@ -132,7 +133,6 @@ export function isRoute(route, path){ const SITE_CHANGE_AVALIABLE_ROUTES = [ sessions(), assist(), dashboard(), errors(), onboarding('')]; export const siteChangeAvaliable = path => SITE_CHANGE_AVALIABLE_ROUTES.some(r => isRoute(r, path)); - export const redirects = Object.entries({ [ client('custom-fields') ]: client(CLIENT_TABS.CUSTOM_FIELDS), }); \ No newline at end of file diff --git a/frontend/tailwind.config.js b/frontend/tailwind.config.js index 2058dcc16..e15ec72e9 100644 --- a/frontend/tailwind.config.js +++ b/frontend/tailwind.config.js @@ -13,7 +13,7 @@ module.exports = { //'appearance', // 'backgroundAttachment', 'backgroundColor', - // 'backgroundOpacity', + 'backgroundOpacity', // 'backgroundPosition', // 'backgroundRepeat', // 'backgroundSize', From 49ed32c13838da5461c5e0a995e118ea36394950 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 23 Feb 2022 14:33:51 +0100 Subject: [PATCH 3/5] fix(ui) - offline to live link --- frontend/app/components/Session_/PlayerBlockHeader.js | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/frontend/app/components/Session_/PlayerBlockHeader.js b/frontend/app/components/Session_/PlayerBlockHeader.js index 6e274d4b1..e0883cc59 100644 --- a/frontend/app/components/Session_/PlayerBlockHeader.js +++ b/frontend/app/components/Session_/PlayerBlockHeader.js @@ -2,8 +2,8 @@ import { connect } from 'react-redux'; import { withRouter } from 'react-router-dom'; import { browserIcon, osIcon, deviceTypeIcon } from 'App/iconNames'; import { formatTimeOrDate } from 'App/date'; -import { sessions as sessionsRoute, assist as assistRoute, withSiteId } from 'App/routes'; -import { Icon, CountryFlag, IconButton, BackLink, Popup } from 'UI'; +import { sessions as sessionsRoute, assist as assistRoute, liveSession as liveSessionRoute, withSiteId } from 'App/routes'; +import { Icon, CountryFlag, IconButton, BackLink, Popup, Link } from 'UI'; import { toggleFavorite, setSessionPath } from 'Duck/sessions'; import cn from 'classnames'; import { connectPlayer } from 'Player'; @@ -107,6 +107,7 @@ export default class PlayerBlockHeader extends React.PureComponent { sessionPath, metaList, closedLive = false, + siteId, } = this.props; const _live = live && !hasSessionsPath; @@ -126,8 +127,10 @@ export default class PlayerBlockHeader extends React.PureComponent {
{ live && hasSessionsPath && ( <> -
this.props.setSessionPath('')}> - This Session is Now Continuing Live +
+ + This Session is Now Continuing Live +
From 29ff91b2559fe2444951e8005eaf14991b82710e Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 23 Feb 2022 14:44:59 +0100 Subject: [PATCH 4/5] fix(ui) - session health check --- .../app/components/shared/SessionItem/ErrorBars/ErrorBars.tsx | 2 +- frontend/app/components/shared/SessionItem/SessionItem.js | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/frontend/app/components/shared/SessionItem/ErrorBars/ErrorBars.tsx b/frontend/app/components/shared/SessionItem/ErrorBars/ErrorBars.tsx index 3b49db9c6..b867d1b2a 100644 --- a/frontend/app/components/shared/SessionItem/ErrorBars/ErrorBars.tsx +++ b/frontend/app/components/shared/SessionItem/ErrorBars/ErrorBars.tsx @@ -7,7 +7,7 @@ const LESS_CRITICAL = 'Few Issues' const CRITICAL = 'Many Issues' const getErrorState = (count: number) => { if (count === 0) { return GOOD } - if (count < 2) { return LESS_CRITICAL } + if (count < 3) { return LESS_CRITICAL } return CRITICAL } diff --git a/frontend/app/components/shared/SessionItem/SessionItem.js b/frontend/app/components/shared/SessionItem/SessionItem.js index 023c9c724..ca9f649d7 100644 --- a/frontend/app/components/shared/SessionItem/SessionItem.js +++ b/frontend/app/components/shared/SessionItem/SessionItem.js @@ -58,6 +58,7 @@ export default class SessionItem extends React.PureComponent { live, metadata, userSessionsCount, + issueTypes, }, timezone, onUserClick = () => null, @@ -129,7 +130,7 @@ export default class SessionItem extends React.PureComponent {
{ !isAssist && (
- +
)}
From da7f6cceada737d1b39f78d8df78a649ee1eb690 Mon Sep 17 00:00:00 2001 From: Shekar Siri Date: Wed, 23 Feb 2022 14:46:37 +0100 Subject: [PATCH 5/5] change(ui) - swap save search and save funnel --- frontend/app/components/shared/SessionSearch/SessionSearch.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx index a3f799ed7..264786fff 100644 --- a/frontend/app/components/shared/SessionSearch/SessionSearch.tsx +++ b/frontend/app/components/shared/SessionSearch/SessionSearch.tsx @@ -79,8 +79,8 @@ function SessionSearch(props: Props) {
- +