Skip to content

Commit 7db556e

Browse files
authored
Merge pull request #254 from TaloDev/develop
Release 0.29.0
2 parents 9e0b66f + f73e962 commit 7db556e

File tree

13 files changed

+131
-63
lines changed

13 files changed

+131
-63
lines changed

config/entrypoint.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh
22
for filename in /bin/www/js/*.js; do
3-
envsub $filename $filename
3+
envsub $filename $filename
44
done
55

66
nginx -g 'daemon off;'

cypress/e2e/pages/Demo.spec.cy.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// <reference types='cypress' />
2+
3+
describe('Demo', () => {
4+
it('should let users enter the demo dashboard', () => {
5+
cy.intercept('POST', 'http://talo.api/public/demo', {
6+
statusCode: 200,
7+
fixture: 'responses/auth/dev'
8+
})
9+
10+
cy.visitAsGuest('/demo')
11+
cy.findByText('Launch demo').click()
12+
13+
cy.findByText('Superstatic dashboard').should('exist')
14+
})
15+
16+
it('should handle errors', () => {
17+
cy.intercept('POST', 'http://talo.api/public/demo', {
18+
statusCode: 500,
19+
body: {
20+
message: 'Something went wrong'
21+
}
22+
})
23+
24+
cy.visitAsGuest('/demo')
25+
cy.findByText('Launch demo').click()
26+
27+
cy.findByText('Something went wrong').should('exist')
28+
})
29+
})

cypress/e2e/pages/Login.spec.cy.js

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ describe('Login', () => {
4747
cy.location('pathname').should('eq', '/account')
4848
})
4949

50-
it('should redirect to the dashboard after logging in if the intended route does not exist', () => {
50+
it('should redirect to the 404 page after logging in if the intended route does not exist', () => {
5151
cy.intercept('POST', 'http://talo.api/public/users/login', {
5252
statusCode: 200,
5353
fixture: 'responses/auth/dev'
@@ -58,7 +58,6 @@ describe('Login', () => {
5858
cy.findByLabelText('Password').type('password')
5959
cy.findByText('Login').click()
6060

61-
cy.findByText('Superstatic dashboard').should('exist')
62-
cy.location('pathname').should('eq', '/')
61+
cy.findByText('404 Not Found').should('exist')
6362
})
6463
})

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
"lint-staged": {
7272
"*.{js,jsx}": "eslint --fix"
7373
},
74-
"version": "0.28.1",
74+
"version": "0.29.0",
7575
"engines": {
7676
"node": "20.x"
7777
},

src/App.jsx

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,8 @@ function AppLoading() {
2020
function App() {
2121
const setUser = useSetRecoilState(userState)
2222

23-
const [isRefreshing, setRefreshing] = useState(true)
2423
const [hasTriedRefreshing, setTriedRefreshing] = useState(false)
25-
const [intendedUrl, setIntendedUrl] = useState(null)
24+
const [intendedRoute, setIntendedRoute] = useState(null)
2625

2726
const games = useRecoilValue(gamesState)
2827
const [activeGame, setActiveGame] = useRecoilState(activeGameState)
@@ -38,30 +37,34 @@ function App() {
3837
} catch (err) {
3938
setActiveGame(null)
4039
} finally {
41-
setRefreshing(false)
4240
setTriedRefreshing(true)
4341
}
4442
}
4543

4644
useEffect(() => {
47-
setIntendedUrl(window.location.pathname + window.location.search)
45+
const location = window.location.pathname + window.location.search
46+
if (location !== '/') {
47+
setIntendedRoute(location)
48+
} else {
49+
setTriedRefreshing(true)
50+
}
4851
}, [])
4952

5053
useEffect(() => {
51-
if (!hasTriedRefreshing && intendedUrl) {
54+
if (!hasTriedRefreshing && intendedRoute) {
5255
handleRefreshSession()
5356
}
54-
}, [intendedUrl, hasTriedRefreshing])
57+
}, [intendedRoute, hasTriedRefreshing])
5558

5659
useEffect(() => {
5760
if (!activeGame && games.length > 0) setActiveGame(games[0])
5861
}, [activeGame, games])
5962

60-
if (isRefreshing) return <AppLoading />
63+
if (!hasTriedRefreshing) return <AppLoading />
6164

6265
return (
6366
<Suspense fallback={<AppLoading />}>
64-
<Router intendedUrl={intendedUrl} />
67+
<Router intendedRoute={intendedRoute} />
6568
</Suspense>
6669
)
6770
}

src/Router.jsx

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import routes from './constants/routes'
88
import activeGameState from './state/activeGameState'
99
import AuthService from './services/AuthService'
1010
import canViewPage from './utils/canViewPage'
11-
import NotFoundHandler from './components/NotFoundHandler'
11+
import IntendedRouteHandler from './components/IntendedRouteHandler'
1212

1313
const Login = lazy(() => import(/* webpackChunkName: 'login' */ './pages/Login'))
1414
const Dashboard = lazy(() => import(/* webpackChunkName: 'dashboard' */ './pages/Dashboard'))
@@ -41,8 +41,9 @@ const ForgotPassword = lazy(() => import(/* webpackChunkName: 'forgot-password'
4141
const ResetPassword = lazy(() => import(/* webpackChunkName: 'reset-password' */ './pages/ResetPassword'))
4242
const PlayerSaves = lazy(() => import(/* webpackChunkName: 'player-saves' */ './pages/PlayerSaves'))
4343
const PlayerSaveContent = lazy(() => import(/* webpackChunkName: 'player-save-content' */ './pages/PlayerSaveContent'))
44+
const NotFound = lazy(() => import(/* webpackChunkName: 'not-found' */ './pages/NotFound'))
4445

45-
function Router({ intendedUrl }) {
46+
function Router({ intendedRoute }) {
4647
const user = useRecoilValue(userState)
4748
const activeGame = useRecoilValue(activeGameState)
4849

@@ -60,7 +61,7 @@ function Router({ intendedUrl }) {
6061
<Route exact path={routes.forgotPassword} element={<ForgotPassword />} />
6162
<Route exact path={routes.resetPassword} element={<ResetPassword />} />
6263

63-
<Route path='*' element={<NotFoundHandler baseRoute={routes.login} intendedUrl={intendedUrl} />} />
64+
<Route path='*' element={<IntendedRouteHandler intendedRoute={intendedRoute} />} />
6465
</Routes>
6566
</main>
6667
}
@@ -99,7 +100,7 @@ function Router({ intendedUrl }) {
99100
</>
100101
}
101102

102-
<Route path='*' element={<NotFoundHandler baseRoute={routes.dashboard} intendedUrl={intendedUrl} />} />
103+
<Route path='*' element={<NotFound />} />
103104
</Routes>
104105
</main>
105106
</div>
@@ -109,7 +110,7 @@ function Router({ intendedUrl }) {
109110
}
110111

111112
Router.propTypes = {
112-
intendedUrl: PropTypes.string
113+
intendedRoute: PropTypes.string
113114
}
114115

115116
export default Router
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { useEffect } from 'react'
2+
import PropTypes from 'prop-types'
3+
import { Navigate } from 'react-router-dom'
4+
import routes from '../constants/routes'
5+
6+
// 1. user hits dashboard.trytalo.com/leaderboards but is logged out
7+
// 2. user is redirected to dashboard.trytalo.com/?next=%2Fleaderboards
8+
// 3. "next" search param is put into sessionStorage
9+
// 4. useIntendedRoute hook picks up logic to redirect based on the sessionStorage
10+
export default function IntendedRouteHandler({ intendedRoute }) {
11+
useEffect(() => {
12+
const next = new URLSearchParams(window.location.search).get('next')
13+
if (next) {
14+
window.sessionStorage.setItem('intendedRoute', next)
15+
}
16+
}, [])
17+
18+
if (!intendedRoute) {
19+
<Navigate to={routes.login} replace />
20+
}
21+
22+
return (
23+
<Navigate to={`${routes.login}?next=${encodeURIComponent(intendedRoute)}`} replace />
24+
)
25+
}
26+
27+
IntendedRouteHandler.propTypes = {
28+
intendedRoute: PropTypes.string.isRequired
29+
}

src/components/NotFoundHandler.jsx

Lines changed: 0 additions & 26 deletions
This file was deleted.

src/components/Page.jsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ import Title from './Title'
44
import Loading from './Loading'
55
import GlobalBanners from './GlobalBanners'
66

7-
export default function Page({ title, showBackButton = false, isLoading = false, containerClassName = '', extraTitleComponent, children, secondaryNav }) {
7+
export default function Page({ title, showBackButton = false, isLoading = false, containerClassName = '', extraTitleComponent, children, secondaryNav, disableBanners }) {
88
return (
99
<div className='space-y-8'>
1010
{secondaryNav}
1111

12-
<GlobalBanners />
12+
{!disableBanners && <GlobalBanners />}
1313

1414
<div className={clsx('space-y-8', containerClassName)}>
1515
<div className='flex items-center'>
@@ -37,5 +37,6 @@ Page.propTypes = {
3737
containerClassName: PropTypes.string,
3838
children: PropTypes.node.isRequired,
3939
extraTitleComponent: PropTypes.node,
40-
secondaryNav: PropTypes.node
40+
secondaryNav: PropTypes.node,
41+
disableBanners: PropTypes.bool
4142
}

0 commit comments

Comments
 (0)