refactor: move download popover to own component
This commit is contained in:
parent
e6dfb9dfd6
commit
0d9d54efaf
4 changed files with 173 additions and 160 deletions
134
new-lamassu-admin/src/components/LogsDownloaderPopover.js
Normal file
134
new-lamassu-admin/src/components/LogsDownloaderPopover.js
Normal file
|
|
@ -0,0 +1,134 @@
|
||||||
|
import React, { useState } from 'react'
|
||||||
|
import FileSaver from 'file-saver'
|
||||||
|
import classnames from 'classnames'
|
||||||
|
import { toInteger } from 'lodash/fp'
|
||||||
|
import moment from 'moment'
|
||||||
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
|
||||||
|
import typographyStyles from '../components/typography/styles'
|
||||||
|
import { primaryColor } from '../styling/variables'
|
||||||
|
|
||||||
|
import { Link } from './buttons'
|
||||||
|
import { RadioGroup } from './inputs'
|
||||||
|
import Popover from './Popover'
|
||||||
|
import DateRangePicker from './date-range-picker/DateRangePicker'
|
||||||
|
|
||||||
|
const { h4 } = typographyStyles
|
||||||
|
|
||||||
|
const styles = {
|
||||||
|
popoverContent: {
|
||||||
|
minWidth: 315
|
||||||
|
},
|
||||||
|
popoverHeader: {
|
||||||
|
extend: h4,
|
||||||
|
padding: [[20, 15, 0, 15]]
|
||||||
|
},
|
||||||
|
radioButtonsContainer: {
|
||||||
|
padding: [[10, 15, 10, 15]]
|
||||||
|
},
|
||||||
|
radioButtons: {
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
flexDirection: 'row',
|
||||||
|
color: primaryColor
|
||||||
|
},
|
||||||
|
dateRangePickerShowing: {
|
||||||
|
display: 'block',
|
||||||
|
height: '100%'
|
||||||
|
},
|
||||||
|
dateRangePickerHidden: {
|
||||||
|
display: 'none',
|
||||||
|
height: 0
|
||||||
|
},
|
||||||
|
download: {
|
||||||
|
padding: [[30, 15, 30, 15]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
const LogsDownloaderPopover = ({ id, open, anchorEl, onClose, logsResponse, ...props }) => {
|
||||||
|
const [radioButtons, setRadioButtons] = useState(0)
|
||||||
|
const [range, setRange] = useState(null)
|
||||||
|
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const dateRangePickerClasses = {
|
||||||
|
[classes.dateRangePickerShowing]: radioButtons === 1,
|
||||||
|
[classes.dateRangePickerHidden]: radioButtons === 0
|
||||||
|
}
|
||||||
|
|
||||||
|
const formatDateFile = date => {
|
||||||
|
return moment(date).format('YYYY-MM-DD_HH-mm')
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRadioButtons = (event) => {
|
||||||
|
setRadioButtons(toInteger(event.target.value))
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRangeChange = (from, to) => {
|
||||||
|
setRange({ from, to })
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Popover
|
||||||
|
id={id}
|
||||||
|
open={open}
|
||||||
|
anchorEl={anchorEl}
|
||||||
|
onClose={onClose}
|
||||||
|
anchorOrigin={{
|
||||||
|
vertical: 'bottom',
|
||||||
|
horizontal: 'center'
|
||||||
|
}}
|
||||||
|
transformOrigin={{
|
||||||
|
vertical: 'top',
|
||||||
|
horizontal: 'center'
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div className={classes.popoverContent}>
|
||||||
|
<div className={classes.popoverHeader}>
|
||||||
|
Download logs
|
||||||
|
</div>
|
||||||
|
<div className={classes.radioButtonsContainer}>
|
||||||
|
<RadioGroup
|
||||||
|
name='logs-select'
|
||||||
|
value={radioButtons}
|
||||||
|
labels={['All logs', 'Date range']}
|
||||||
|
ariaLabel='logs-select'
|
||||||
|
onChange={handleRadioButtons}
|
||||||
|
className={classes.radioButtons}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<DateRangePicker
|
||||||
|
maxDate={moment()}
|
||||||
|
handleChange={handleRangeChange}
|
||||||
|
className={classnames(dateRangePickerClasses)}
|
||||||
|
/>
|
||||||
|
<div className={classes.download}>
|
||||||
|
<Link
|
||||||
|
color='primary'
|
||||||
|
onClick={() => {
|
||||||
|
if (radioButtons === 0) {
|
||||||
|
const text = logsResponse.data.logs.map(it => JSON.stringify(it)).join('\n')
|
||||||
|
const blob = new window.Blob([text], {
|
||||||
|
type: 'text/plain;charset=utf-8'
|
||||||
|
})
|
||||||
|
FileSaver.saveAs(blob, `${formatDateFile(new Date())}_server`)
|
||||||
|
} else if (radioButtons === 1 && range.from && range.to) {
|
||||||
|
const text = logsResponse.data.logs.filter((log) => moment(log.timestamp).isBetween(range.from, range.to, 'day', '[]')).map(it => JSON.stringify(it)).join('\n')
|
||||||
|
const blob = new window.Blob([text], {
|
||||||
|
type: 'text/plain;charset=utf-8'
|
||||||
|
})
|
||||||
|
FileSaver.saveAs(blob, `${formatDateFile(range.from)}_${formatDateFile(range.to)}_server`)
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Download
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Popover>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default LogsDownloaderPopover
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
export default {
|
|
||||||
titleAndButtonsContainer: {
|
|
||||||
display: 'flex'
|
|
||||||
},
|
|
||||||
buttonsWrapper: {
|
|
||||||
display: 'flex',
|
|
||||||
marginLeft: 10,
|
|
||||||
'& > *': {
|
|
||||||
margin: 'auto 10px'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -39,8 +39,14 @@ export default {
|
||||||
button: {
|
button: {
|
||||||
margin: 8
|
margin: 8
|
||||||
},
|
},
|
||||||
|
titleAndButtonsContainer: {
|
||||||
|
display: 'flex'
|
||||||
|
},
|
||||||
buttonsWrapper: {
|
buttonsWrapper: {
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
alignItems: 'center'
|
marginLeft: 10,
|
||||||
|
'& > *': {
|
||||||
|
margin: 'auto 10px'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,95 +1,49 @@
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import FileSaver from 'file-saver'
|
import { concat, uniq, merge } from 'lodash/fp'
|
||||||
import classnames from 'classnames'
|
|
||||||
import { concat, uniq, toInteger } from 'lodash/fp'
|
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import useAxios from '@use-hooks/axios'
|
import useAxios from '@use-hooks/axios'
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
|
|
||||||
import Title from '../components/Title'
|
import Title from '../components/Title'
|
||||||
import { Info3 } from '../components/typography'
|
import { Info3 } from '../components/typography'
|
||||||
import { FeatureButton, SimpleButton, Link } from '../components/buttons'
|
import { FeatureButton, SimpleButton } from '../components/buttons'
|
||||||
import { Table, TableHead, TableRow, TableHeader, TableBody, TableCell } from '../components/table'
|
import { Table, TableHead, TableRow, TableHeader, TableBody, TableCell } from '../components/table'
|
||||||
import { Select, RadioGroup } from '../components/inputs'
|
import { Select } from '../components/inputs'
|
||||||
import Uptime from '../components/Uptime'
|
import Uptime from '../components/Uptime'
|
||||||
import DateRangePicker from '../components/date-range-picker/DateRangePicker'
|
import LogsDowloaderPopover from '../components/LogsDownloaderPopover'
|
||||||
import Popover from '../components/Popover'
|
|
||||||
import { ReactComponent as Download } from '../styling/icons/button/download/zodiac.svg'
|
import { ReactComponent as Download } from '../styling/icons/button/download/zodiac.svg'
|
||||||
import { ReactComponent as DownloadActive } from '../styling/icons/button/download/white.svg'
|
import { ReactComponent as DownloadActive } from '../styling/icons/button/download/white.svg'
|
||||||
import { primaryColor, comet } from '../styling/variables'
|
import { comet } from '../styling/variables'
|
||||||
import typographyStyles from '../components/typography/styles'
|
import typographyStyles from '../components/typography/styles'
|
||||||
|
|
||||||
import styles from './Logs.styles'
|
import logsStyles from './Logs.styles'
|
||||||
import logPageHeaderStyles from './LogPageHeader.styles'
|
|
||||||
|
|
||||||
const { regularLabel, h4 } = typographyStyles
|
const { regularLabel } = typographyStyles
|
||||||
const { tableWrapper } = styles
|
const { tableWrapper } = logsStyles
|
||||||
const { titleAndButtonsContainer, buttonsWrapper } = logPageHeaderStyles
|
|
||||||
|
|
||||||
styles.titleWrapper = {
|
const localStyles = {
|
||||||
display: 'flex',
|
serverTableWrapper: {
|
||||||
justifyContent: 'space-between'
|
extend: tableWrapper,
|
||||||
|
maxWidth: '100%',
|
||||||
|
marginLeft: 0
|
||||||
|
},
|
||||||
|
serverVersion: {
|
||||||
|
extend: regularLabel,
|
||||||
|
color: comet,
|
||||||
|
margin: 'auto 0 auto 0'
|
||||||
|
},
|
||||||
|
headerLine2: {
|
||||||
|
height: 60,
|
||||||
|
display: 'flex',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
marginBottom: 24
|
||||||
|
},
|
||||||
|
uptimeContainer: {
|
||||||
|
margin: 'auto 0 auto 0'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
styles.serverTableWrapper = {
|
const styles = merge(logsStyles, localStyles)
|
||||||
extend: tableWrapper,
|
|
||||||
maxWidth: '100%',
|
|
||||||
marginLeft: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.serverVersion = {
|
|
||||||
extend: regularLabel,
|
|
||||||
color: comet,
|
|
||||||
margin: 'auto 0 auto 0'
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.headerLine2 = {
|
|
||||||
height: 60,
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
marginBottom: 24
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.uptimeContainer = {
|
|
||||||
margin: 'auto 0 auto 0'
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.titleAndButtonsContainer = titleAndButtonsContainer
|
|
||||||
styles.buttonsWrapper = buttonsWrapper
|
|
||||||
|
|
||||||
styles.popoverContent = {
|
|
||||||
minWidth: 315
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.popoverHeader = {
|
|
||||||
extend: h4,
|
|
||||||
padding: [[20, 15, 0, 15]]
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.radioButtonsContainer = {
|
|
||||||
padding: [[10, 15, 10, 15]]
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.radioButtons = {
|
|
||||||
display: 'flex',
|
|
||||||
justifyContent: 'space-between',
|
|
||||||
flexDirection: 'row',
|
|
||||||
color: primaryColor
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.dateRangePickerShowing = {
|
|
||||||
display: 'block',
|
|
||||||
height: '100%'
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.dateRangePickerHidden = {
|
|
||||||
display: 'none',
|
|
||||||
height: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
styles.download = {
|
|
||||||
padding: [[30, 15, 30, 15]]
|
|
||||||
}
|
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
|
|
@ -104,8 +58,6 @@ const Logs = () => {
|
||||||
const [logLevel, setLogLevel] = useState(SHOW_ALL)
|
const [logLevel, setLogLevel] = useState(SHOW_ALL)
|
||||||
const [version, setVersion] = useState(null)
|
const [version, setVersion] = useState(null)
|
||||||
const [processStates, setProcessStates] = useState(null)
|
const [processStates, setProcessStates] = useState(null)
|
||||||
const [radioButtons, setRadioButtons] = useState(0)
|
|
||||||
const [range, setRange] = useState(null)
|
|
||||||
const [anchorEl, setAnchorEl] = useState(null)
|
const [anchorEl, setAnchorEl] = useState(null)
|
||||||
|
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
@ -155,15 +107,6 @@ const Logs = () => {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const formatDateFile = date => {
|
|
||||||
return moment(date).format('YYYY-MM-DD_HH-mm')
|
|
||||||
}
|
|
||||||
|
|
||||||
const dateRangePickerClasses = {
|
|
||||||
[classes.dateRangePickerShowing]: radioButtons === 1,
|
|
||||||
[classes.dateRangePickerHidden]: radioButtons === 0
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleOpenRangePicker = (event) => {
|
const handleOpenRangePicker = (event) => {
|
||||||
setAnchorEl(event.currentTarget)
|
setAnchorEl(event.currentTarget)
|
||||||
}
|
}
|
||||||
|
|
@ -172,14 +115,6 @@ const Logs = () => {
|
||||||
setAnchorEl(null)
|
setAnchorEl(null)
|
||||||
}
|
}
|
||||||
|
|
||||||
const handleRadioButtons = (event) => {
|
|
||||||
setRadioButtons(toInteger(event.target.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
const handleRangeChange = (from, to) => {
|
|
||||||
setRange({ from, to })
|
|
||||||
}
|
|
||||||
|
|
||||||
const open = Boolean(anchorEl)
|
const open = Boolean(anchorEl)
|
||||||
const id = open ? 'date-range-popover' : undefined
|
const id = open ? 'date-range-popover' : undefined
|
||||||
|
|
||||||
|
|
@ -197,63 +132,13 @@ const Logs = () => {
|
||||||
variant='contained'
|
variant='contained'
|
||||||
onClick={handleOpenRangePicker}
|
onClick={handleOpenRangePicker}
|
||||||
/>
|
/>
|
||||||
<Popover
|
<LogsDowloaderPopover
|
||||||
id={id}
|
id={id}
|
||||||
open={open}
|
open={open}
|
||||||
anchorEl={anchorEl}
|
anchorEl={anchorEl}
|
||||||
|
logsResponse={logsResponse}
|
||||||
onClose={handleCloseRangePicker}
|
onClose={handleCloseRangePicker}
|
||||||
anchorOrigin={{
|
/>
|
||||||
vertical: 'bottom',
|
|
||||||
horizontal: 'center'
|
|
||||||
}}
|
|
||||||
transformOrigin={{
|
|
||||||
vertical: 'top',
|
|
||||||
horizontal: 'center'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div className={classes.popoverContent}>
|
|
||||||
<div className={classes.popoverHeader}>
|
|
||||||
Download logs
|
|
||||||
</div>
|
|
||||||
<div className={classes.radioButtonsContainer}>
|
|
||||||
<RadioGroup
|
|
||||||
name='logs-select'
|
|
||||||
value={radioButtons}
|
|
||||||
labels={['All logs', 'Date range']}
|
|
||||||
ariaLabel='logs-select'
|
|
||||||
onChange={handleRadioButtons}
|
|
||||||
className={classes.radioButtons}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<DateRangePicker
|
|
||||||
maxDate={moment()}
|
|
||||||
handleChange={handleRangeChange}
|
|
||||||
className={classnames(dateRangePickerClasses)}
|
|
||||||
/>
|
|
||||||
<div className={classes.download}>
|
|
||||||
<Link
|
|
||||||
color='primary'
|
|
||||||
onClick={() => {
|
|
||||||
if (radioButtons === 0) {
|
|
||||||
const text = logsResponse.data.logs.map(it => JSON.stringify(it)).join('\n')
|
|
||||||
const blob = new window.Blob([text], {
|
|
||||||
type: 'text/plain;charset=utf-8'
|
|
||||||
})
|
|
||||||
FileSaver.saveAs(blob, `${formatDateFile(new Date())}_server`)
|
|
||||||
} else if (radioButtons === 1 && range.from && range.to) {
|
|
||||||
const text = logsResponse.data.logs.filter((log) => moment(log.timestamp).isBetween(range.from, range.to, 'day', '[]')).map(it => JSON.stringify(it)).join('\n')
|
|
||||||
const blob = new window.Blob([text], {
|
|
||||||
type: 'text/plain;charset=utf-8'
|
|
||||||
})
|
|
||||||
FileSaver.saveAs(blob, `${formatDateFile(range.from)}_${formatDateFile(range.to)}_server`)
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Download
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</Popover>
|
|
||||||
<SimpleButton className={classes.button} disabled={loading} onClick={sendSnapshot}>
|
<SimpleButton className={classes.button} disabled={loading} onClick={sendSnapshot}>
|
||||||
Share with Lamassu
|
Share with Lamassu
|
||||||
</SimpleButton>
|
</SimpleButton>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue