diff --git a/new-lamassu-admin/package-lock.json b/new-lamassu-admin/package-lock.json
index bdc74ca3..1c9e6540 100644
--- a/new-lamassu-admin/package-lock.json
+++ b/new-lamassu-admin/package-lock.json
@@ -6508,8 +6508,7 @@
"ansi-regex": {
"version": "2.1.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"aproba": {
"version": "1.2.0",
@@ -6530,14 +6529,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6552,20 +6549,17 @@
"code-point-at": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"core-util-is": {
"version": "1.0.2",
@@ -6682,8 +6676,7 @@
"inherits": {
"version": "2.0.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"ini": {
"version": "1.3.5",
@@ -6695,7 +6688,6 @@
"version": "1.0.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"number-is-nan": "^1.0.0"
}
@@ -6710,7 +6702,6 @@
"version": "3.0.4",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"brace-expansion": "^1.1.7"
}
@@ -6718,14 +6709,12 @@
"minimist": {
"version": "0.0.8",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"minipass": {
"version": "2.3.5",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"safe-buffer": "^5.1.2",
"yallist": "^3.0.0"
@@ -6744,7 +6733,6 @@
"version": "0.5.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"minimist": "0.0.8"
}
@@ -6825,8 +6813,7 @@
"number-is-nan": {
"version": "1.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"object-assign": {
"version": "4.1.1",
@@ -6838,7 +6825,6 @@
"version": "1.4.0",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"wrappy": "1"
}
@@ -6924,8 +6910,7 @@
"safe-buffer": {
"version": "5.1.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"safer-buffer": {
"version": "2.1.2",
@@ -6961,7 +6946,6 @@
"version": "1.0.2",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0",
@@ -6981,7 +6965,6 @@
"version": "3.0.1",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"ansi-regex": "^2.0.0"
}
@@ -7025,14 +7008,12 @@
"wrappy": {
"version": "1.0.2",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"yallist": {
"version": "3.0.3",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
}
}
},
@@ -8064,7 +8045,6 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
"integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
- "dev": true,
"requires": {
"es5-ext": "^0.10.50",
"type": "^1.0.1"
@@ -8880,7 +8860,6 @@
"version": "0.10.51",
"resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.51.tgz",
"integrity": "sha512-oRpWzM2WcLHVKpnrcyB7OW8j/s67Ba04JCm0WnNv3RiABSvs7mrQlutB8DBv793gKcp0XENR8Il8WxGTlZ73gQ==",
- "dev": true,
"requires": {
"es6-iterator": "~2.0.3",
"es6-symbol": "~3.1.1",
@@ -8897,7 +8876,6 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
- "dev": true,
"requires": {
"d": "1",
"es5-ext": "^0.10.35",
@@ -8914,7 +8892,6 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.2.tgz",
"integrity": "sha512-/ZypxQsArlv+KHpGvng52/Iz8by3EQPxhmbuz8yFG89N/caTFBSbcXONDw0aMjy827gQg26XAjP4uXFvnfINmQ==",
- "dev": true,
"requires": {
"d": "^1.0.1",
"es5-ext": "^0.10.51"
@@ -12702,14 +12679,12 @@
"balanced-match": {
"version": "1.0.0",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"brace-expansion": {
"version": "1.1.11",
"bundled": true,
"dev": true,
- "optional": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -12729,8 +12704,7 @@
"concat-map": {
"version": "0.0.1",
"bundled": true,
- "dev": true,
- "optional": true
+ "dev": true
},
"console-control-strings": {
"version": "1.1.0",
@@ -14733,6 +14707,14 @@
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
+ "moment-range": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/moment-range/-/moment-range-4.0.2.tgz",
+ "integrity": "sha512-n8sceWwSTjmz++nFHzeNEUsYtDqjgXgcOBzsHi+BoXQU2FW+eU92LUaK8gqOiSu5PG57Q9sYj1Fz4LRDj4FtKA==",
+ "requires": {
+ "es6-symbol": "^3.1.0"
+ }
+ },
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
@@ -14842,8 +14824,7 @@
"next-tick": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
- "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=",
- "dev": true
+ "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
},
"nice-try": {
"version": "1.0.5",
@@ -21979,8 +21960,7 @@
"type": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==",
- "dev": true
+ "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
},
"type-check": {
"version": "0.3.2",
diff --git a/new-lamassu-admin/package.json b/new-lamassu-admin/package.json
index 813a6ba2..a44911c9 100644
--- a/new-lamassu-admin/package.json
+++ b/new-lamassu-admin/package.json
@@ -15,6 +15,7 @@
"jss-plugin-extend": "^10.0.0",
"lodash": "4.17.15",
"moment": "2.24.0",
+ "moment-range": "^4.0.2",
"qrcode.react": "0.9.3",
"react": "^16.10.2",
"react-dom": "^16.10.2",
diff --git a/new-lamassu-admin/src/components/Popover.js b/new-lamassu-admin/src/components/Popover.js
new file mode 100644
index 00000000..1fd851a3
--- /dev/null
+++ b/new-lamassu-admin/src/components/Popover.js
@@ -0,0 +1,44 @@
+import React from 'react'
+import { makeStyles, Popover as MaterialPopover } from '@material-ui/core'
+
+const styles = {
+ arrow: {
+ width: 0,
+ height: 0,
+ position: 'absolute',
+ borderStyle: 'solid',
+ margin: 5,
+ borderWidth: [[0, 15, 18, 15]],
+ borderLeftColor: 'transparent',
+ borderRightColor: 'transparent',
+ borderTopColor: 'transparent',
+ top: -18,
+ left: 138,
+ marginTop: 0,
+ marginBottom: 0,
+ borderColor: '#ffffff'
+ },
+ paper: {
+ overflow: 'visible'
+ }
+}
+
+const useStyles = makeStyles(styles)
+
+const Popover = ({ children, ...props }) => {
+ const classes = useStyles()
+
+ return (
+
+ {children}
+
+
+ )
+}
+
+export default Popover
diff --git a/new-lamassu-admin/src/components/date-range-picker/Calendar.js b/new-lamassu-admin/src/components/date-range-picker/Calendar.js
new file mode 100644
index 00000000..a71355d8
--- /dev/null
+++ b/new-lamassu-admin/src/components/date-range-picker/Calendar.js
@@ -0,0 +1,144 @@
+import React, { useState } from 'react'
+import moment from 'moment'
+import { toInteger } from 'lodash/fp'
+import { makeStyles } from '@material-ui/core/styles'
+import Tile from './Tile'
+import { ReactComponent as Arrow } from '../../styling/icons/arrow/month_change.svg'
+import { primaryColor, zircon, fontSecondary } from '../../styling/variables'
+import typographyStyles from '../typography/styles'
+const { label2 } = typographyStyles
+
+const styles = {
+ navbar: {
+ display: 'flex',
+ justifyContent: 'space-between',
+ alignItems: 'center',
+ padding: [[15, 15]],
+ color: primaryColor,
+ '& button': {
+ display: 'flex',
+ alignItems: 'center',
+ padding: 0,
+ border: 'none',
+ backgroundColor: zircon,
+ cursor: 'pointer',
+ borderRadius: '50%',
+ width: 20,
+ height: 20,
+ position: 'relative',
+ overflow: 'hidden',
+ '& svg': {
+ position: 'absolute',
+ left: 0
+ }
+ },
+ fontFamily: fontSecondary,
+ fontSize: 16,
+ fontWeight: 500
+ },
+ table: {
+ borderCollapse: 'collapse',
+ color: primaryColor,
+ '& tr': {
+ '&:first-child': {
+ paddingLeft: 5
+ },
+ '&:last-child': {
+ paddingRight: 5
+ }
+ },
+ '& th, & td': {
+ margin: 0,
+ padding: [[3, 0, 3, 0]]
+ },
+ '& th': {
+ extend: label2
+ }
+ }
+}
+
+const useStyles = makeStyles(styles)
+
+const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
+ const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(moment())
+
+ const classes = useStyles()
+
+ const weekdays = moment.weekdaysMin().map(day => day.slice(0, 1))
+ const firstDayOfMonth = (month) => toInteger(moment(month).startOf('month').format('d'))
+ const monthLength = (month) => toInteger(moment(month).endOf('month').format('D'))
+
+ const monthdays = (month) => {
+ const days = []
+
+ const lastMonth = moment(month).subtract(1, 'month')
+ for (let i = firstDayOfMonth(month) - 1; i >= 0; i--) {
+ days.push(moment(lastMonth).endOf('month').subtract(i, 'days'))
+ }
+ for (let j = 0; j < monthLength(month); j++) {
+ days.push(moment(month).startOf('month').add(j, 'days'))
+ }
+ const nextMonth = moment(month).add(1, 'month')
+ for (let k = 0; days.length < 42; k++) {
+ days.push(moment(nextMonth).startOf('month').add(k, 'days'))
+ }
+
+ return days
+ }
+
+ const getRow = (month, row) => monthdays(month).slice(row * 7 - 7, row * 7)
+
+ const handleNavPrev = (currentMonth) => {
+ const prevMonth = moment(currentMonth).subtract(1, 'month')
+ if (!minDate) setCurrentDisplayedMonth(prevMonth)
+ else setCurrentDisplayedMonth(prevMonth.isSameOrAfter(minDate, 'month') ? prevMonth : currentDisplayedMonth)
+ }
+ const handleNavNext = (currentMonth) => {
+ const nextMonth = moment(currentMonth).add(1, 'month')
+ if (!maxDate) setCurrentDisplayedMonth(nextMonth)
+ else setCurrentDisplayedMonth(nextMonth.isSameOrBefore(maxDate, 'month') ? nextMonth : currentDisplayedMonth)
+ }
+
+ return (
+
+
+
+
{`${currentDisplayedMonth.format('MMMM')} ${currentDisplayedMonth.format('YYYY')}`}
+
+
+
+
+
+ {weekdays.map((day, key) => (
+ | {day} |
+ ))}
+
+
+
+ {[1, 2, 3, 4, 5, 6, 7].map((row, key) => (
+
+ {getRow(currentDisplayedMonth, row).map((day, key) => (
+ | handleSelect(day, minDate, maxDate)}>
+
+ {day.format('D')}
+
+ |
+ ))}
+
+ ))}
+
+
+
+ )
+}
+
+export default Calendar
diff --git a/new-lamassu-admin/src/components/date-range-picker/DateRangePicker.js b/new-lamassu-admin/src/components/date-range-picker/DateRangePicker.js
new file mode 100644
index 00000000..a7eefda1
--- /dev/null
+++ b/new-lamassu-admin/src/components/date-range-picker/DateRangePicker.js
@@ -0,0 +1,131 @@
+import React, { useState, useEffect } from 'react'
+import classnames from 'classnames'
+import { makeStyles } from '@material-ui/core/styles'
+
+import Calendar from './Calendar'
+import { ReactComponent as Arrow } from '../../styling/icons/arrow/download_logs.svg'
+
+import { primaryColor, offColor, zircon } from '../../styling/variables'
+
+import typographyStyles from '../typography/styles'
+const { info1, label, label3 } = typographyStyles
+
+const dateContainerStyles = {
+ wrapper: {
+ minWidth: 118
+ },
+ container: {
+ display: 'flex'
+ },
+ monthWeekDayContainer: {
+ display: 'flex',
+ flexDirection: 'column'
+ },
+ label: {
+ extend: label,
+ color: primaryColor
+ },
+ bigNumber: {
+ extend: info1,
+ marginRight: 7
+ },
+ monthYear: {
+ extend: label3,
+ color: primaryColor
+ },
+ weekDay: {
+ extend: label,
+ lineHeight: 1,
+ color: offColor
+ }
+}
+
+const dateContainerUseStyles = makeStyles(dateContainerStyles)
+
+const DateContainer = ({ date, children, ...props }) => {
+ const classes = dateContainerUseStyles()
+
+ return (
+
+
{children}
+ {date &&
+ <>
+
+
{date.format('D')}
+
+ {`${date.format('MMM')} ${date.format('YYYY')}`}
+ {date.format('dddd')}
+
+
+ >}
+
+ )
+}
+
+const styles = {
+ wrapper: {
+ backgroundColor: 'white',
+ borderRadius: 10
+ },
+ dateThingyContainer: {
+ height: 80,
+ display: 'flex',
+ justifyContent: 'space-between',
+ backgroundColor: zircon,
+ padding: [[5, 15, 0, 15]]
+ },
+ arrowContainer: {
+ width: 39,
+ display: 'flex',
+ alignSelf: 'center',
+ alignItems: 'center'
+ },
+ arrow: {
+ margin: 'auto'
+ }
+}
+
+const useStyles = makeStyles(styles)
+
+const DateRangePicker = ({ minDate, maxDate, className, handleChange, ...props }) => {
+ const [from, setFrom] = useState(null)
+ const [to, setTo] = useState(null)
+
+ useEffect(() => {
+ handleChange(from, to)
+ }, [to])
+
+ const classes = useStyles()
+
+ const handleSelect = (day, minDate, maxDate) => {
+ if ((maxDate && day.isAfter(maxDate, 'day')) || (minDate && day.isBefore(minDate, 'day'))) return
+ if (from && !to) {
+ if (day.isBefore(from, 'day')) {
+ setTo(from)
+ setFrom(day)
+ } else {
+ setTo(day)
+ }
+ } else {
+ setFrom(day)
+ setTo(null)
+ }
+ }
+
+ return (
+ <>
+
+ >
+ )
+}
+
+export default DateRangePicker
diff --git a/new-lamassu-admin/src/components/date-range-picker/Tile.js b/new-lamassu-admin/src/components/date-range-picker/Tile.js
new file mode 100644
index 00000000..c0132a8b
--- /dev/null
+++ b/new-lamassu-admin/src/components/date-range-picker/Tile.js
@@ -0,0 +1,94 @@
+import React from 'react'
+import classnames from 'classnames'
+import { makeStyles } from '@material-ui/core/styles'
+import { primaryColor, spring2, spring3, fontSecondary, disabledColor } from '../../styling/variables'
+
+const styles = {
+ wrapper: {
+ width: 45,
+ height: 26,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ position: 'relative'
+ },
+ button: {
+ border: 'none',
+ width: '100%',
+ height: '100%',
+ cursor: 'pointer',
+ padding: 0,
+ backgroundColor: 'transparent',
+ color: primaryColor,
+ zIndex: 2,
+ fontFamily: fontSecondary,
+ fontSize: 14,
+ fontWeight: 500
+ },
+ lowerBound: {
+ width: [['50%', '!important']],
+ left: '50%'
+ },
+ upperBound: {
+ width: [['50%', '!important']],
+ right: '50%'
+ },
+ selected: {
+ width: 26,
+ height: 26,
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'center',
+ backgroundColor: spring2,
+ borderRadius: '50%',
+ position: 'absolute',
+ zIndex: 1
+ },
+ between: {
+ position: 'absolute',
+ width: '100%',
+ height: '100%',
+ zIndex: 0,
+ backgroundColor: spring3
+ },
+ disabled: {
+ color: disabledColor,
+ cursor: 'default'
+ }
+}
+
+const useStyles = makeStyles(styles)
+
+const Tile = ({ isLowerBound, isUpperBound, isBetween, isDisabled, children, ...props }) => {
+ const classes = useStyles()
+ const selected = isLowerBound || isUpperBound
+
+ const rangeClasses = {
+ [classes.between]: isBetween && !(isLowerBound && isUpperBound),
+ [classes.lowerBound]: isLowerBound && !isUpperBound,
+ [classes.upperBound]: isUpperBound && !isLowerBound
+ }
+
+ const buttonWrapperClasses = {
+ [classes.wrapper]: true,
+ [classes.selected]: selected
+ }
+
+ const buttonClasses = {
+ [classes.button]: true,
+ [classes.disabled]: isDisabled
+ }
+
+ return (
+
+ )
+}
+
+export default Tile
diff --git a/new-lamassu-admin/src/components/inputs/base/RadioGroup.js b/new-lamassu-admin/src/components/inputs/base/RadioGroup.js
new file mode 100644
index 00000000..cbec62a3
--- /dev/null
+++ b/new-lamassu-admin/src/components/inputs/base/RadioGroup.js
@@ -0,0 +1,32 @@
+import React from 'react'
+import classnames from 'classnames'
+import { withStyles } from '@material-ui/styles'
+import FormControlLabel from '@material-ui/core/FormControlLabel'
+import { Radio as MaterialRadio, RadioGroup as MaterialRadioGroup } from '@material-ui/core'
+import { secondaryColor } from '../../../styling/variables'
+
+const GreenRadio = withStyles({
+ root: {
+ color: secondaryColor,
+ '&$checked': {
+ color: secondaryColor
+ }
+ },
+ checked: {}
+})(props => )
+
+const RadioGroup = ({ name, value, labels, ariaLabel, onChange, className, ...props }) => {
+ return (
+ <>
+ {labels && (
+
+ {labels.map((label, idx) => (
+ } label={label} />
+ ))}
+
+ )}
+ >
+ )
+}
+
+export default RadioGroup
diff --git a/new-lamassu-admin/src/components/inputs/index.js b/new-lamassu-admin/src/components/inputs/index.js
index c7af2a30..28347d38 100644
--- a/new-lamassu-admin/src/components/inputs/index.js
+++ b/new-lamassu-admin/src/components/inputs/index.js
@@ -5,5 +5,6 @@ import Radio from './base/Radio'
import TextInput from './base/TextInput'
import Switch from './base/Switch'
import Select from './base/Select'
+import RadioGroup from './base/RadioGroup'
-export { Autocomplete, AutocompleteMultiple, TextInput, Radio, Checkbox, Switch, Select }
+export { Autocomplete, AutocompleteMultiple, TextInput, Radio, Checkbox, Switch, Select, RadioGroup }
diff --git a/new-lamassu-admin/src/components/typography/styles.js b/new-lamassu-admin/src/components/typography/styles.js
index 06a1eabe..2921b161 100644
--- a/new-lamassu-admin/src/components/typography/styles.js
+++ b/new-lamassu-admin/src/components/typography/styles.js
@@ -119,6 +119,11 @@ export default {
fontWeight: 500,
color: fontColor
},
+ label3: {
+ fontSize: fontSize5,
+ fontFamily: fontSecondary,
+ fontWeight: 700
+ },
select: {
fontSize: fontSize3,
fontFamily: fontSecondary,
diff --git a/new-lamassu-admin/src/pages/ServerLogs.js b/new-lamassu-admin/src/pages/ServerLogs.js
index 968c275c..6f06d9ae 100644
--- a/new-lamassu-admin/src/pages/ServerLogs.js
+++ b/new-lamassu-admin/src/pages/ServerLogs.js
@@ -1,26 +1,28 @@
import React, { useState } from 'react'
import FileSaver from 'file-saver'
-import { concat, uniq } from 'lodash/fp'
+import classnames from 'classnames'
+import { concat, uniq, toInteger } from 'lodash/fp'
import moment from 'moment'
import useAxios from '@use-hooks/axios'
+import { makeStyles } from '@material-ui/core'
import Title from '../components/Title'
import { Info3 } from '../components/typography'
-import { FeatureButton, SimpleButton } from '../components/buttons'
+import { FeatureButton, SimpleButton, Link } from '../components/buttons'
import { Table, TableHead, TableRow, TableHeader, TableBody, TableCell } from '../components/table'
-import { Select } from '../components/inputs'
+import { Select, RadioGroup } from '../components/inputs'
import Uptime from '../components/Uptime'
+import DateRangePicker from '../components/date-range-picker/DateRangePicker'
+import Popover from '../components/Popover'
import { ReactComponent as Download } from '../styling/icons/button/download/zodiac.svg'
import { ReactComponent as DownloadActive } from '../styling/icons/button/download/white.svg'
-import { makeStyles } from '@material-ui/core'
-import typographyStyles from '../components/typography/styles'
-
-import { comet } from '../styling/variables'
+import { primaryColor, comet } from '../styling/variables'
import styles from './Logs.styles'
import logPageHeaderStyles from './LogPageHeader.styles'
-const { regularLabel } = typographyStyles
+import typographyStyles from '../components/typography/styles'
+const { regularLabel, h4 } = typographyStyles
const { tableWrapper } = styles
const { titleAndButtonsContainer, buttonsWrapper } = logPageHeaderStyles
@@ -55,6 +57,40 @@ styles.uptimeContainer = {
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 SHOW_ALL = 'Show all'
@@ -68,6 +104,9 @@ const Logs = () => {
const [logLevel, setLogLevel] = useState(SHOW_ALL)
const [version, setVersion] = useState(null)
const [processStates, setProcessStates] = useState(null)
+ const [radioButtons, setRadioButtons] = useState(0)
+ const [range, setRange] = useState(null)
+ const [anchorEl, setAnchorEl] = useState(null)
const classes = useStyles()
@@ -116,12 +155,34 @@ const Logs = () => {
}
})
- const handleLogLevelChange = (item) => setLogLevel(item)
-
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) => {
+ setAnchorEl(event.currentTarget)
+ }
+
+ const handleCloseRangePicker = () => {
+ setAnchorEl(null)
+ }
+
+ const handleRadioButtons = (event) => {
+ setRadioButtons(toInteger(event.target.value))
+ }
+
+ const handleRangeChange = (from, to) => {
+ setRange({ from, to })
+ }
+
+ const open = Boolean(anchorEl)
+ const id = open ? 'date-range-popover' : undefined
+
return (
<>
@@ -132,14 +193,67 @@ const Logs = () => {
{
- 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`)
- }}
+ aria-describedby={id}
+ variant='contained'
+ onClick={handleOpenRangePicker}
/>
+
+
+
+ Download logs
+
+
+
+
+
+
+ {
+ 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
+
+
+
+
Share with Lamassu
@@ -156,7 +270,7 @@ const Logs = () => {
{logsResponse && (