Skip to content

Commit

Permalink
feat: add network connection status to ui and redux
Browse files Browse the repository at this point in the history
  • Loading branch information
amy-corson-ibigroup committed Nov 27, 2024
1 parent bad8e44 commit 20047af
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 2 deletions.
2 changes: 2 additions & 0 deletions i18n/en-US.yml
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,8 @@ components:
closeMenu: Close Menu
fieldTrip: Field Trip
mailables: Mailables
networkConnectionLost: Network connection lost
networkConnectionRestored: Network connection restored
openMenu: Open Menu
skipNavigation: Skip navigation
BackToTripPlanner:
Expand Down
3 changes: 3 additions & 0 deletions lib/actions/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ const viewRoute = createAction('SET_VIEWED_ROUTE')
export const toggleAutoRefresh = createAction('TOGGLE_AUTO_REFRESH')
const settingItineraryView = createAction('SET_ITINERARY_VIEW')
export const setPopupContent = createAction('SET_POPUP_CONTENT')
export const setNetworkConnectionLost = createAction(
'SET_NETWORK_CONNECTION_LOST'
)

// This code-less action calls the reducer code
// and thus resets the session timeout.
Expand Down
8 changes: 8 additions & 0 deletions lib/components/app/desktop-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { DEFAULT_APP_TITLE } from '../../util/constants'
import InvisibleA11yLabel from '../util/invisible-a11y-label'
import NavLoginButtonAuth0 from '../user/nav-login-button-auth0'

import { NetworkConnectionBanner } from './network-connection-banner'
import AppMenu, { Icon } from './app-menu'
import LocaleSelector from './locale-selector'
import NavbarItem from './nav-item'
Expand Down Expand Up @@ -63,6 +64,7 @@ const NavItemOnLargeScreens = styled(NavbarItem)`
// Typscript TODO: otpConfig type
export type Props = {
locale: string
networkConnectionLost: boolean
otpConfig: AppConfig
popupTarget?: string
setPopupContent: (url: string) => void
Expand All @@ -83,6 +85,7 @@ export type Props = {
*/
const DesktopNav = ({
locale,
networkConnectionLost,
otpConfig,
popupTarget,
setPopupContent
Expand Down Expand Up @@ -117,6 +120,8 @@ const DesktopNav = ({
id: `config.popups.${popupTarget}`
})

console.log(networkConnectionLost)

return (
<header>
<Navbar fluid inverse>
Expand Down Expand Up @@ -166,15 +171,18 @@ const DesktopNav = ({
</StyledNav>
</Navbar.Header>
</Navbar>
<NetworkConnectionBanner networkConnectionLost={networkConnectionLost} />
</header>
)
}

// connect to the redux store
const mapStateToProps = (state: AppReduxState) => {
const { config: otpConfig } = state.otp
const { networkConnectionLost } = state.otp.ui.errors
return {
locale: state.otp.ui.locale,
networkConnectionLost,
otpConfig,
popupTarget: otpConfig.popups?.launchers?.toolbar
}
Expand Down
78 changes: 78 additions & 0 deletions lib/components/app/network-connection-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
import { CSSTransition, TransitionGroup } from 'react-transition-group'
import { FormattedMessage } from 'react-intl'
import React, { useRef } from 'react'
import styled from 'styled-components'

import { RED_ON_WHITE } from '../util/colors'

const containerClassname = 'network-connection-banner'
const timeout = 200

const TransitionStyles = styled.div`
.${containerClassname} {
background: ${RED_ON_WHITE};
border-left: 1px solid #e7e7e7;
border-right: 1px solid #e7e7e7;
color: #fff;
font-weight: 600;
padding: 5px;
position: absolute;
text-align: center;
top: 50px;
width: 100%;
z-index: 1;
}
.${containerClassname}-enter {
opacity: 0;
transform: translateY(-100%);
}
.${containerClassname}-enter-active {
opacity: 1;
transform: translateY(0);
transition: opacity ${timeout}ms ease-in;
}
.${containerClassname}-exit {
opacity: 1;
transform: translateY(0);
}
.${containerClassname}-exit-active {
opacity: 0;
transform: translateY(-100%);
transition: opacity ${timeout}ms ease-in, transform ${timeout}ms ease-in;
}
`
export const NetworkConnectionLostBanner = styled.div``

export const NetworkConnectionBanner = ({
networkConnectionLost
}: {
networkConnectionLost: boolean
}): JSX.Element => {
const connectionLostBannerRef = useRef<HTMLDivElement>(null)
return (
<TransitionStyles>
<TransitionGroup style={{ display: 'content' }}>
{networkConnectionLost && (
<CSSTransition
classNames={containerClassname}
nodeRef={connectionLostBannerRef}
timeout={timeout}
>
<NetworkConnectionLostBanner
aria-live="assertive"
className={containerClassname}
ref={connectionLostBannerRef}
role="status"
>
{networkConnectionLost ? (
<FormattedMessage id="components.AppMenu.networkConnectionLost" />
) : (
<FormattedMessage id="components.AppMenu.networkConnectionRestored" />
)}
</NetworkConnectionLostBanner>
</CSSTransition>
)}
</TransitionGroup>
</TransitionStyles>
)
}
6 changes: 5 additions & 1 deletion lib/components/app/responsive-webapp.js
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,13 @@ class ResponsiveWebapp extends Component {
map,
matchContentToUrl,
parseUrlQueryString,
receivedPositionResponse
receivedPositionResponse,
setNetworkConnectionLost
} = this.props
// Add on back button press behavior.
window.addEventListener('popstate', handleBackButtonPress)
window.addEventListener('online', () => setNetworkConnectionLost(false))
window.addEventListener('offline', () => setNetworkConnectionLost(true))

// If a URL is detected without hash routing (e.g., http://localhost:9966?sessionId=test),
// window.location.search will have a value. In this case, we need to redirect to the URL root with the
Expand Down Expand Up @@ -441,6 +444,7 @@ const mapStateToWrapperProps = (state) => {
const mapWrapperDispatchToProps = {
processSignIn: authActions.processSignIn,
setLocale: uiActions.setLocale,
setNetworkConnectionLost: uiActions.setNetworkConnectionLost,
showAccessTokenError: authActions.showAccessTokenError,
showLoginError: authActions.showLoginError
}
Expand Down
9 changes: 8 additions & 1 deletion lib/components/mobile/navigation-bar.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as uiActions from '../../actions/ui'
import { accountLinks, getAuth0Config } from '../../util/auth'
import { ComponentContext } from '../../util/contexts'
import { injectIntl } from 'react-intl'
import { NetworkConnectionBanner } from '../app/network-connection-banner'
import { StyledIconWrapper } from '../util/styledIcon'
import AppMenu from '../app/app-menu'
import LocaleSelector from '../app/locale-selector'
Expand All @@ -32,6 +33,7 @@ class MobileNavigationBar extends Component {
headerText: PropTypes.string,
intl: PropTypes.object,
locale: PropTypes.string,
networkConnectionLost: PropTypes.bool,
onBackClicked: PropTypes.func,
setMobileScreen: PropTypes.func,
showBackButton: PropTypes.bool
Expand All @@ -55,6 +57,7 @@ class MobileNavigationBar extends Component {
headerText,
intl,
locale,
networkConnectionLost,
showBackButton
} = this.props

Expand Down Expand Up @@ -111,6 +114,9 @@ class MobileNavigationBar extends Component {
)}
</MobileBar>
</Navbar>
<NetworkConnectionBanner
networkConnectionLost={networkConnectionLost}
/>
</header>
)
}
Expand All @@ -123,7 +129,8 @@ const mapStateToProps = (state) => {
auth0Config: getAuth0Config(state.otp.config.persistence),
configLanguages: state.otp.config.language,
extraMenuItems: state.otp?.config?.extraMenuItems,
locale: state.otp.ui.locale
locale: state.otp.ui.locale,
networkConnectionLost: state.otp.ui.errors.networkConnectionLost
}
}

Expand Down
12 changes: 12 additions & 0 deletions lib/reducers/create-otp-reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,9 @@ export function getInitialState(userDefinedConfig) {
},
ui: {
diagramLeg: null,
errors: {
networkConnectionLost: !navigator.onLine
},
locale: null,
localizedMessages: null,
mainPanelContent: null,
Expand Down Expand Up @@ -1108,6 +1111,15 @@ function createOtpReducer(config) {
}
}
})
case 'SET_NETWORK_CONNECTION_LOST':
console.log(action.payload)
return update(state, {
ui: {
errors: {
networkConnectionLost: { $set: action.payload }
}
}
})
case 'SERVICE_TIME_RANGE_REQUEST':
return update(state, {
serviceTimeRange: { $set: { pending: true } }
Expand Down

0 comments on commit 20047af

Please sign in to comment.