Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 23 additions & 2 deletions app/src/app/AppLayout/AppLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { useLocation } from 'react-router-dom'
import {
Brand,
Button,
Label,
Masthead,
MastheadBrand,
MastheadContent,
Expand All @@ -15,7 +16,8 @@ import {
Page,
PageSidebar,
PageSidebarBody,
SkipToContent
SkipToContent,
Text
} from '@patternfly/react-core'
import BarsIcon from '@patternfly/react-icons/dist/esm/icons/bars-icon'
import { HeaderToolbar } from './HeaderToolbar'
Expand All @@ -24,6 +26,7 @@ import logo from '@app/bgimages/basil.svg'
import * as Constants from '../Constants/constants'
import { useAuth } from '../User/AuthProvider'
import { AutoRefresh } from '@app/Common/AutoRefresh/AutoRefresh'
import { InfoCircleIcon } from '@patternfly/react-icons'

interface IAppLayout {
children: React.ReactNode
Expand All @@ -40,6 +43,7 @@ const AppLayout: React.FunctionComponent<IAppLayout> = ({ children }) => {
const [libraries, setLibraries] = React.useState([])
const [fetchNotificationCount, setFetchNotificationCount] = React.useState(0)
const [fetchLibrariesCount, setFetchLibrariesCount] = React.useState(0)
const [newVersionAvailabe, setNewVersionAvailable] = React.useState(false)

const search = window.location.search
const params = new URLSearchParams(search)
Expand All @@ -60,6 +64,7 @@ const AppLayout: React.FunctionComponent<IAppLayout> = ({ children }) => {
if (libraries.length == 0) {
loadLibraries()
}
Constants.checkNewVersionAvailable(setNewVersionAvailable)
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])

Expand Down Expand Up @@ -352,7 +357,23 @@ const AppLayout: React.FunctionComponent<IAppLayout> = ({ children }) => {
</NavList>
</Nav>
<div style={{ flexGrow: 1 }} />
<div style={{ padding: '1.5rem', fontSize: '0.8rem', color: '#FFF' }}>Version: {Constants.BASIL_VERSION}</div>
<div style={{ padding: '1.5rem', fontSize: '0.8rem', color: '#FFF' }}>
<Text>Version: {Constants.BASIL_VERSION}</Text>
{newVersionAvailabe ? (
<a
href='https://github.com/elisa-tech/BASIL/releases'
target='_blank'
rel='noopener noreferrer'
style={{ textDecoration: 'none' }}
>
<Label isCompact variant='filled' color='green' icon={<InfoCircleIcon />}>
New version available
</Label>
</a>
) : (
''
)}
</div>
</>
)

Expand Down
66 changes: 66 additions & 0 deletions app/src/app/Constants/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ export const BASIL_VERSION = '1.8.2'
export const TESTING_FARM_COMPOSES_URL = 'https://api.dev.testing-farm.io/v0.1/composes'
export const force_reload = true

const GITHUB_REPO_RELEASES_URL = 'https://api.github.com/repos/elisa-tech/BASIL/releases/latest'
const COOKIE_BASIL_LASTEST_RELEASE_VERSION = 'basil-latest-release-version'

export const _A = 'api'
export const _D = 'document'
export const _Ds = 'documents'
Expand Down Expand Up @@ -443,6 +446,69 @@ export const isValidId = (id_str: string) => {
return /^\d+$/.test(id_str) && Number(id_str) > 0 && Number.isSafeInteger(Number(id_str))
}

export const setCookie = (name, value, days) => {
const date = new Date()
date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000)
const expires = 'expires=' + date.toUTCString()
document.cookie = `${name}=${value}; ${expires}; path=/`
}

export const getCookieValue = (name) => {
const cookies = document.cookie.split(';')

for (let cookie of cookies) {
const [key, value] = cookie.trim().split('=')
if (key === name) {
return decodeURIComponent(value)
}
}

return undefined
}

// Compare semantic versions (e.g. "1.8.0" < "1.9.0")
export const isNewerVersion = (latest: string = '', current: string = '') => {
const latestParts = latest.split('.').map(Number)
const currentParts = current.split('.').map(Number)

for (let i = 0; i < latestParts.length; i++) {
if ((latestParts[i] || 0) > (currentParts[i] || 0)) return true
if ((latestParts[i] || 0) < (currentParts[i] || 0)) return false
}
return false
}

export const checkNewVersionAvailable = (setNewVersionAvailable) => {
const value = getCookieValue(COOKIE_BASIL_LASTEST_RELEASE_VERSION)

if (value !== undefined) {
setNewVersionAvailable(isNewerVersion(value, BASIL_VERSION))
return
} else {
fetch(GITHUB_REPO_RELEASES_URL)
.then((res) => {
if (!res.ok) {
setNewVersionAvailable(false)
throw new Error('Unable to read last release from github')
} else {
return res.json()
}
})
.then((data) => {
if (!data || typeof data !== 'object' || !data.tag_name) {
throw new Error('`tag_name` not found in GitHub response')
}
const tag = data.tag_name.replace(/^v/, '') // strip "v" if release is like "v1.9.0"
setCookie(COOKIE_BASIL_LASTEST_RELEASE_VERSION, tag, 1) // expires in 1 day
setNewVersionAvailable(isNewerVersion(tag, BASIL_VERSION))
})
.catch((err) => {
console.error('ERROR: ' + err.message)
setNewVersionAvailable(false)
})
}
}

export const logObject = (obj) => {
let i
let k
Expand Down
Loading