Skip to content

Commit 1049824

Browse files
authored
Merge pull request #494 from docat-org/feature/480-not-latest-version-banner
Feature: Add Info banner if user is not on latest version
2 parents 3d8d18b + bd4cbc0 commit 1049824

File tree

7 files changed

+60
-44
lines changed

7 files changed

+60
-44
lines changed

web/src/components/InfoBanner.tsx

+7-21
Original file line numberDiff line numberDiff line change
@@ -4,43 +4,29 @@ import React, { useEffect, useState } from 'react'
44
import { Message } from '../data-providers/MessageBannerProvider'
55

66
interface Props {
7-
errorMsg?: string
8-
successMsg?: string
7+
message: Message
98
}
109

11-
export default function Banner(props: Props): JSX.Element {
12-
const messageFromProps = (props: Props): Message => {
13-
if (props.errorMsg != null && props.errorMsg.trim() !== '') {
14-
return { text: props.errorMsg, type: 'error' }
15-
}
16-
if (props.successMsg != null && props.successMsg.trim() !== '') {
17-
return { text: props.successMsg, type: 'success' }
18-
}
19-
20-
return { text: undefined, type: 'success' }
21-
}
22-
23-
const [msg, setMsg] = useState<Message>(messageFromProps(props))
10+
export default function Banner (props: Props): JSX.Element {
2411
const [show, setShow] = useState<boolean>(false)
2512

2613
useEffect(() => {
2714
setShow(true)
28-
setMsg(messageFromProps(props))
29-
}, [props])
15+
}, [props.message])
3016

3117
return (
3218
<Snackbar
3319
key={uniqueId()}
34-
open={show && msg.text != null}
35-
autoHideDuration={6000}
20+
open={show && props.message.content != null}
21+
autoHideDuration={props.message.showMs}
3622
onClose={() => setShow(false)}
3723
>
3824
<Alert
3925
onClose={() => setShow(false)}
40-
severity={msg.type}
26+
severity={props.message.type}
4127
sx={{ width: '100%' }}
4228
>
43-
{msg.text}
29+
{props.message.content}
4430
</Alert>
4531
</Snackbar>
4632
)

web/src/data-providers/MessageBannerProvider.tsx

+18-15
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ import React, { useState, useCallback, useContext } from 'react'
88
import Banner from '../components/InfoBanner'
99

1010
export interface Message {
11-
text: string | undefined
12-
type: 'error' | 'success'
11+
content: string | JSX.Element | undefined
12+
type: 'success' | 'info' | 'warning' | 'error'
13+
showMs: number | null // null = infinite
1314
}
1415

1516
interface MessageBannerState {
@@ -22,14 +23,13 @@ export const Context = React.createContext<MessageBannerState>({
2223
}
2324
})
2425

25-
export function MessageBannerProvider({ children }: any): JSX.Element {
26+
export function MessageBannerProvider ({ children }: any): JSX.Element {
2627
// We need to store the last timeout, so we can clear when a new message is shown
27-
const [lastTimeout, setLastTimeout] = useState<NodeJS.Timeout | undefined>(
28-
undefined
29-
)
28+
const [lastTimeout, setLastTimeout] = useState<NodeJS.Timeout>()
3029
const [message, setMessage] = useState<Message>({
31-
text: undefined,
32-
type: 'success'
30+
content: undefined,
31+
type: 'success',
32+
showMs: 6000
3333
})
3434

3535
const showMessage = useCallback((message: Message) => {
@@ -39,25 +39,28 @@ export function MessageBannerProvider({ children }: any): JSX.Element {
3939

4040
setMessage(message)
4141

42+
if (message.showMs === null) {
43+
// don't hide message
44+
return
45+
}
46+
4247
// Hide message after 6 seconds
4348
const newTimeout = setTimeout(
4449
() =>
4550
setMessage({
46-
text: undefined,
47-
type: 'success'
51+
content: undefined,
52+
type: 'success',
53+
showMs: 6000
4854
}),
49-
6000
55+
message.showMs
5056
)
5157

5258
setLastTimeout(newTimeout)
5359
}, [])
5460

5561
return (
5662
<Context.Provider value={{ showMessage }}>
57-
<Banner
58-
successMsg={message.type === 'success' ? message.text : undefined}
59-
errorMsg={message.type === 'error' ? message.text : undefined}
60-
/>
63+
<Banner message={message} />
6164
{children}
6265
</Context.Provider>
6366
)

web/src/data-providers/ProjectDataProvider.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,9 @@ export function ProjectDataProvider({ children }: any): JSX.Element {
5757
console.error(e)
5858

5959
showMessage({
60-
text: 'Failed to load projects',
61-
type: 'error'
60+
content: 'Failed to load projects',
61+
type: 'error',
62+
showMs: 6000
6263
})
6364

6465
setProjects({

web/src/pages/Claim.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,9 @@ export default function Claim(): JSX.Element {
3030
} catch (e) {
3131
console.error(e)
3232
showMessage({
33-
text: (e as { message: string }).message,
34-
type: 'error'
33+
content: (e as { message: string }).message,
34+
type: 'error',
35+
showMs: 6000
3536
})
3637
}
3738
}

web/src/pages/Delete.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@ export default function Delete(): JSX.Element {
5454

5555
showMessage({
5656
type: 'success',
57-
text: `Documentation for ${project} (${version}) deleted successfully.`
57+
content: `Documentation for ${project} (${version}) deleted successfully.`,
58+
showMs: 6000
5859
})
5960
setProject('none')
6061
setVersion('none')
@@ -65,7 +66,8 @@ export default function Delete(): JSX.Element {
6566

6667
showMessage({
6768
type: 'error',
68-
text: (e as { message: string }).message
69+
content: (e as { message: string }).message,
70+
showMs: 6000
6971
})
7072
}
7173
})()

web/src/pages/Docs.tsx

+21
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import NotFound from './NotFound'
1414

1515
import styles from './../style/pages/Docs.module.css'
1616
import { uniqueId } from 'lodash'
17+
import { useMessageBanner } from '../data-providers/MessageBannerProvider'
1718

1819
export default function Docs (): JSX.Element {
1920
const projectParam = useParams().project ?? ''
@@ -31,6 +32,7 @@ export default function Docs (): JSX.Element {
3132
const [versions, setVersions] = useState<ProjectDetails[]>([])
3233
const [loadingFailed, setLoadingFailed] = useState<boolean>(false)
3334

35+
const { showMessage } = useMessageBanner()
3436
const location = useLocation()
3537
const iFrameRef = useRef<HTMLIFrameElement>(null)
3638

@@ -186,6 +188,25 @@ export default function Docs (): JSX.Element {
186188
}
187189
}, [location])
188190

191+
useEffect(() => {
192+
// check every time the version changes whether the version
193+
// is the latest version and if not, show a banner
194+
if (versions.length === 0) {
195+
return
196+
}
197+
198+
const latestVersion = ProjectRepository.getLatestVersion(versions).name
199+
if (version === latestVersion) {
200+
return
201+
}
202+
203+
showMessage({
204+
content: 'You are viewing an outdated version of the documentation.',
205+
type: 'warning',
206+
showMs: null
207+
})
208+
}, [version, versions])
209+
189210
if (loadingFailed) {
190211
return <NotFound />
191212
}

web/src/pages/Upload.tsx

+4-2
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,8 @@ export default function Upload(): JSX.Element {
110110
setValidation({})
111111
showMessage({
112112
type: 'success',
113-
text: 'Documentation uploaded successfully'
113+
content: 'Documentation uploaded successfully',
114+
showMs: 6000
114115
})
115116

116117
// reload the projects
@@ -121,7 +122,8 @@ export default function Upload(): JSX.Element {
121122
const message = (e as { message: string }).message
122123
showMessage({
123124
type: 'error',
124-
text: message
125+
content: message,
126+
showMs: 6000
125127
})
126128
} finally {
127129
setIsUploading(false)

0 commit comments

Comments
 (0)