feat: timezone conversion

This commit is contained in:
Sérgio Salgado 2021-04-29 19:48:14 +01:00 committed by Josh Harvey
parent 72dbeccb4b
commit b2b4fedf42
10 changed files with 101 additions and 36 deletions

View file

@ -192,6 +192,7 @@ const CustomerProfile = memo(() => {
<TransactionsList
customer={customerData}
data={sortedTransactions}
locale={locale}
loading={loading}
/>
)}

View file

@ -1,6 +1,5 @@
import { makeStyles, Box } from '@material-ui/core'
import BigNumber from 'bignumber.js'
import moment from 'moment'
import * as R from 'ramda'
import React from 'react'
@ -10,17 +9,20 @@ import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { toUnit } from 'src/utils/coin'
import { ifNotNull } from 'src/utils/nullCheck'
import { formatDate } from 'src/utils/timezones'
import CopyToClipboard from '../../Transactions/CopyToClipboard'
import mainStyles from '../CustomersList.styles'
const useStyles = makeStyles(mainStyles)
const TransactionsList = ({ customer, data, loading }) => {
const TransactionsList = ({ customer, data, loading, locale }) => {
const classes = useStyles()
const LastTxIcon = customer.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon
const hasData = !(R.isEmpty(data) || R.isNil(data))
const timezone = locale.timezone
const summaryElements = [
{
header: 'Transactions',
@ -41,10 +43,12 @@ const TransactionsList = ({ customer, data, loading }) => {
{
header: 'Last active',
size: 142,
value: ifNotNull(
customer.lastActive,
moment.utc(customer.lastActive).format('YYYY-MM-D')
)
value:
!R.isNil(timezone) &&
ifNotNull(
customer.lastActive,
formatDate(customer.lastActive, timezone.dstOffset, 'YYYY-MM-D')
)
},
{
header: 'Last transaction',
@ -109,12 +113,12 @@ const TransactionsList = ({ customer, data, loading }) => {
{
header: 'Date',
width: 157,
view: it => moment.utc(it.created).format('YYYY-MM-D')
view: it => formatDate(it.created, timezone.dstOffset, 'YYYY-MM-D')
},
{
header: 'Time (h:m:s)',
width: 134,
view: it => moment.utc(it.created).format('hh:mm:ss')
view: it => formatDate(it.created, timezone.dstOffset, 'HH:mm:ss')
}
]

View file

@ -1,7 +1,6 @@
import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core/styles'
import gql from 'graphql-tag'
import moment from 'moment'
import * as R from 'ramda'
import React, { useState } from 'react'
@ -17,6 +16,7 @@ import {
TableCell
} from 'src/components/table'
import { Info3, H4 } from 'src/components/typography'
import { formatDate } from 'src/utils/timezones'
import styles from './Logs.styles'
@ -70,9 +70,11 @@ const GET_MACHINE_LOGS = gql`
}
`
const formatDate = date => {
return moment(date).format('YYYY-MM-DD HH:mm')
}
const GET_DATA = gql`
query getData {
config
}
`
const Logs = () => {
const classes = useStyles()
@ -84,6 +86,9 @@ const Logs = () => {
const { data: machineResponse } = useQuery(GET_MACHINES)
const { data: configResponse } = useQuery(GET_DATA)
const timezone = R.path(['config', 'locale_timezone'], configResponse)
const { data: logsResponse, loading } = useQuery(GET_MACHINE_LOGS, {
variables: { deviceId, limit: NUM_LOG_RESULTS },
skip: !selected,
@ -137,7 +142,14 @@ const Logs = () => {
{logsResponse &&
logsResponse.machineLogs.map((log, idx) => (
<TableRow key={idx} size="sm">
<TableCell>{formatDate(log.timestamp)}</TableCell>
<TableCell>
{timezone &&
formatDate(
log.timestamp,
timezone.dstOffset,
'YYYY-MM-DD HH:mm'
)}
</TableCell>
<TableCell>{log.logLevel}</TableCell>
<TableCell>{log.message}</TableCell>
</TableRow>

View file

@ -1,13 +1,14 @@
import { makeStyles } from '@material-ui/core/styles'
import moment from 'moment'
import React from 'react'
import { Label3, P } from 'src/components/typography'
import { formatDate } from 'src/utils/timezones'
import styles from '../Machines.styles'
const useStyles = makeStyles(styles)
const Details = ({ data }) => {
const Details = ({ data, timezone }) => {
console.log(timezone)
const classes = useStyles()
return (
<div className={classes.row}>
@ -15,7 +16,11 @@ const Details = ({ data }) => {
<Label3 className={classes.label3}>Paired at</Label3>
<P>
{data.pairedAt
? moment(data.pairedAt).format('YYYY-MM-DD HH:mm:ss')
? formatDate(
data.pairedAt,
timezone.dstOffset,
'YYYY-MM-DD HH:mm:ss'
)
: ''}
</P>
</div>

View file

@ -53,6 +53,7 @@ const Machines = () => {
const machines = getMachines(data) ?? []
const machineInfo = getMachineInfo(selectedMachine)(machines) ?? {}
const timezone = R.path(['config', 'locale_timezone'], data) ?? {}
// pre-selects first machine from the list, if there is a machine configured.
useEffect(() => {
@ -98,7 +99,7 @@ const Machines = () => {
<div
className={classnames(classes.detailItem, classes.detailsMargin)}>
<TL1 className={classes.subtitle}>{'Details'}</TL1>
<Details data={machineInfo} />
<Details data={machineInfo} timezone={timezone} />
</div>
<div className={classes.detailItem}>
<TL1 className={classes.subtitle}>{'Cash cassettes'}</TL1>

View file

@ -2,7 +2,6 @@ import { useMutation, useLazyQuery } from '@apollo/react-hooks'
import { Grid /*, Divider */ } from '@material-ui/core'
import { makeStyles } from '@material-ui/core/styles'
import gql from 'graphql-tag'
import moment from 'moment'
import React, { useState } from 'react'
import { ConfirmDialog } from 'src/components/ConfirmDialog'
@ -18,6 +17,7 @@ import { ReactComponent as ShutdownIcon } from 'src/styling/icons/button/shut do
import { ReactComponent as UnpairReversedIcon } from 'src/styling/icons/button/unpair/white.svg'
import { ReactComponent as UnpairIcon } from 'src/styling/icons/button/unpair/zodiac.svg'
import { modelPrettifier } from 'src/utils/machine'
import { formatDate } from 'src/utils/timezones'
import { labelStyles, machineDetailsStyles } from './MachineDetailsCard.styles'
@ -101,7 +101,7 @@ const getState = machineEventsLazy =>
JSON.parse(machineEventsLazy.machine.latestEvent?.note ?? '{"state": null}')
.state
const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
const MachineDetailsRow = ({ it: machine, onActionSuccess, timezone }) => {
const [action, setAction] = useState({ command: null })
const [errorMessage, setErrorMessage] = useState(null)
const classes = useMDStyles()
@ -214,7 +214,12 @@ const MachineDetailsRow = ({ it: machine, onActionSuccess }) => {
<Item xs={4}>
<Label>Paired at</Label>
<span>
{moment(machine.pairedAt).format('YYYY-MM-DD HH:mm:ss')}
{timezone &&
formatDate(
machine.pairedAt,
timezone.dstOffset,
'YYYY-MM-DD HH:mm:ss'
)}
</span>
</Item>
<Item xs={6}>

View file

@ -38,6 +38,12 @@ const GET_MACHINES = gql`
}
`
const GET_DATA = gql`
query getData {
config
}
`
const useStyles = makeStyles(mainStyles)
const MachineStatus = () => {
@ -46,6 +52,8 @@ const MachineStatus = () => {
const { state } = useLocation()
const addedMachineId = state?.id
const { data: machinesResponse, refetch, loading } = useQuery(GET_MACHINES)
const { data: configResponse, configLoading } = useQuery(GET_DATA)
const timezone = R.path(['config', 'locale_timezone'], configResponse)
const elements = [
{
@ -95,7 +103,7 @@ const MachineStatus = () => {
)
const InnerMachineDetailsRow = ({ it }) => (
<MachineDetailsRow it={it} onActionSuccess={refetch} />
<MachineDetailsRow it={it} onActionSuccess={refetch} timezone={timezone} />
)
return (
@ -116,7 +124,7 @@ const MachineStatus = () => {
</div>
</div>
<DataTable
loading={loading}
loading={loading && configLoading}
elements={elements}
data={machines}
Details={InnerMachineDetailsRow}

View file

@ -1,7 +1,6 @@
import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import gql from 'graphql-tag'
import moment from 'moment'
import * as R from 'ramda'
import React, { useState, useRef } from 'react'
@ -21,6 +20,7 @@ import { Info3, H4 } from 'src/components/typography'
import typographyStyles from 'src/components/typography/styles'
import { offColor } from 'src/styling/variables'
import { startCase } from 'src/utils/string'
import { formatDate } from 'src/utils/timezones'
import logsStyles from './Logs.styles'
@ -54,10 +54,6 @@ const useStyles = makeStyles(styles)
const SHOW_ALL = { code: 'SHOW_ALL', display: 'Show all' }
const formatDate = date => {
return moment(date).format('YYYY-MM-DD HH:mm')
}
const NUM_LOG_RESULTS = 500
const GET_CSV = gql`
@ -66,7 +62,7 @@ const GET_CSV = gql`
}
`
const GET_DATA = gql`
const GET_SERVER_DATA = gql`
query ServerData($limit: Int, $from: DateTime, $until: DateTime) {
serverVersion
uptime {
@ -83,6 +79,12 @@ const GET_DATA = gql`
}
`
const GET_DATA = gql`
query getData {
config
}
`
const Logs = () => {
const classes = useStyles()
@ -91,12 +93,14 @@ const Logs = () => {
const [saveMessage, setSaveMessage] = useState(null)
const [logLevel, setLogLevel] = useState(SHOW_ALL)
const { data, loading } = useQuery(GET_DATA, {
const { data, loading } = useQuery(GET_SERVER_DATA, {
onCompleted: () => setSaveMessage(''),
variables: {
limit: NUM_LOG_RESULTS
}
})
const { data: configResponse, configLoading } = useQuery(GET_DATA)
const timezone = R.path(['config', 'locale_timezone'], configResponse)
const defaultLogLevels = [
{ code: 'error', display: 'Error' },
@ -181,15 +185,22 @@ const Logs = () => {
)
.map((log, idx) => (
<TableRow key={idx} size="sm">
<TableCell>{formatDate(log.timestamp)}</TableCell>
<TableCell>
{timezone &&
formatDate(
log.timestamp,
timezone.dstOffset,
'YYYY-MM-DD HH:mm'
)}
</TableCell>
<TableCell>{log.logLevel}</TableCell>
<TableCell>{log.message}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
{loading && <H4>{'Loading...'}</H4>}
{!loading && !data?.serverLogs?.length && (
{loading && configLoading && <H4>{'Loading...'}</H4>}
{!loading && !configLoading && !data?.serverLogs?.length && (
<H4>{'No activity so far'}</H4>
)}
</div>

View file

@ -2,7 +2,6 @@ import { useQuery } from '@apollo/react-hooks'
import { makeStyles } from '@material-ui/core'
import BigNumber from 'bignumber.js'
import gql from 'graphql-tag'
import moment from 'moment'
import * as R from 'ramda'
import React from 'react'
import { useHistory } from 'react-router-dom'
@ -14,6 +13,7 @@ import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { ReactComponent as CustomerLinkIcon } from 'src/styling/icons/month arrows/right.svg'
import { toUnit, formatCryptoAddress } from 'src/utils/coin'
import { formatDate } from 'src/utils/timezones'
import DetailsRow from './DetailsCard'
import { mainStyles } from './Transactions.styles'
@ -23,6 +23,12 @@ const useStyles = makeStyles(mainStyles)
const NUM_LOG_RESULTS = 1000
const GET_DATA = gql`
query getData {
config
}
`
const GET_TRANSACTIONS_CSV = gql`
query transactions($limit: Int, $from: DateTime, $until: DateTime) {
transactionsCsv(limit: $limit, from: $from, until: $until)
@ -73,6 +79,9 @@ const Transactions = () => {
pollInterval: 10000
})
const { data: configResponse, configLoading } = useQuery(GET_DATA)
const timezone = R.path(['config', 'locale_timezone'], configResponse)
const redirect = customerId => {
return history.push(`/compliance/customer/${customerId}`)
}
@ -143,7 +152,9 @@ const Transactions = () => {
},
{
header: 'Date (UTC)',
view: it => moment.utc(it.created).format('YYYY-MM-DD HH:mm:ss'),
view: it =>
timezone &&
formatDate(it.created, timezone.dstOffset, 'YYYY-MM-DD HH:mm:ss'),
textAlign: 'right',
size: 'sm',
width: 195
@ -185,7 +196,7 @@ const Transactions = () => {
</div>
</div>
<DataTable
loading={loading}
loading={loading && configLoading}
emptyText="No transactions so far"
elements={elements}
data={R.path(['transactions'])(txResponse)}

View file

@ -1,3 +1,4 @@
import moment from 'moment'
import * as R from 'ramda'
const getPossibleUTCDSTPairs = timezones =>
@ -73,4 +74,10 @@ const getTzLabels = timezones =>
getFinalTimezones(timezones)
)
export { getTzLabels }
const formatDate = (date, offset, format) =>
moment
.utc(date)
.utcOffset(offset)
.format(format)
export { getTzLabels, formatDate }