Merge pull request #947 from chaotixkilla/feat-replace-moment-usage
Replace moment usage
This commit is contained in:
commit
1cb715332a
36 changed files with 432 additions and 303 deletions
|
|
@ -1,5 +1,5 @@
|
|||
const { intervalToDuration, secondsToMilliseconds, formatDuration } = require('date-fns/fp')
|
||||
const _ = require('lodash/fp')
|
||||
const moment = require('moment')
|
||||
|
||||
const ticker = require('../ticker')
|
||||
const settingsLoader = require('./settings-loader')
|
||||
|
|
@ -37,8 +37,8 @@ function machinesLastPing () {
|
|||
|
||||
if (downRows.length === 1) {
|
||||
const row = downRows[0]
|
||||
const age = moment.duration(row.age, 'seconds')
|
||||
return `${row.name} down for ${age.humanize()}`
|
||||
const age = intervalToDuration({ start: 0, end: secondsToMilliseconds(row.age) })
|
||||
return `${row.name} down for ${formatDuration(age)}`
|
||||
}
|
||||
|
||||
return 'Multiple machines down'
|
||||
|
|
@ -54,9 +54,9 @@ function status () {
|
|||
|
||||
return Promise.all([checkWasConfigured(), db.oneOrNone(sql, ['ping']), machinesLastPing()])
|
||||
.then(([wasConfigured, statusRow, machineStatus]) => {
|
||||
const age = statusRow && moment.duration(statusRow.age, 'seconds')
|
||||
const age = statusRow && intervalToDuration({ start: 0, end: secondsToMilliseconds(statusRow.age) })
|
||||
const up = statusRow ? statusRow.age < CONSIDERED_UP_SECS : false
|
||||
const lastPing = statusRow && age.humanize()
|
||||
const lastPing = statusRow && formatDuration(age)
|
||||
|
||||
return settingsLoader.loadLatest()
|
||||
.catch(() => null)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const makeDir = require('make-dir')
|
|||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const util = require('util')
|
||||
const moment = require('moment')
|
||||
const { sub, differenceInHours } = require('date-fns/fp')
|
||||
|
||||
const db = require('./db')
|
||||
const BN = require('./bn')
|
||||
|
|
@ -215,14 +215,14 @@ function getDailyVolumeMinusCurrentTxQueries (id, txId) {
|
|||
}
|
||||
|
||||
function getHoursTillLimitClear (cashInDate, cashOutDate) {
|
||||
let startDate = moment()
|
||||
startDate = startDate.subtract(1, 'days')
|
||||
let startDate = new Date()
|
||||
startDate = sub({ days: 1 }, startDate)
|
||||
|
||||
const cashInMoment = moment(cashInDate || startDate)
|
||||
const cashOutMoment = moment(cashOutDate || startDate)
|
||||
const cashInMoment = new Date(cashInDate || startDate)
|
||||
const cashOutMoment = new Date(cashOutDate || startDate)
|
||||
|
||||
const cashInDuration = moment.duration(cashInMoment.diff(startDate)).asHours()
|
||||
const cashOutDuration = moment.duration(cashOutMoment.diff(startDate)).asHours()
|
||||
const cashInDuration = differenceInHours(cashInMoment, startDate)
|
||||
const cashOutDuration = differenceInHours(cashOutMoment, startDate)
|
||||
|
||||
return _.ceil(_.max([cashInDuration, cashOutDuration, 0]))
|
||||
}
|
||||
|
|
|
|||
16
lib/logs.js
16
lib/logs.js
|
|
@ -1,5 +1,6 @@
|
|||
const _ = require('lodash/fp')
|
||||
const moment = require('moment')
|
||||
const { format } = require('date-fns/fp')
|
||||
const { utcToZonedTime } = require('date-fns-tz/fp')
|
||||
|
||||
const db = require('./db')
|
||||
const pgp = require('pg-promise')()
|
||||
|
|
@ -112,12 +113,17 @@ function simpleGetMachineLogs (deviceId, from = new Date(0).toISOString(), until
|
|||
}
|
||||
|
||||
function logDateFormat (timezone, logs, fields) {
|
||||
const offset = timezone.split(':')[1]
|
||||
|
||||
return _.map(log => {
|
||||
const values = _.map(field => moment.utc(log[field]).utcOffset(parseInt(offset)).format('YYYY-MM-DDTHH:mm:ss.SSS'), fields)
|
||||
const values = _.map(
|
||||
field =>
|
||||
{
|
||||
if (_.isNil(log[field])) return null
|
||||
const date = utcToZonedTime(timezone, log[field])
|
||||
return `${format('yyyy-MM-dd', date)}T${format('HH:mm:ss.SSS', date)}`
|
||||
},
|
||||
fields
|
||||
)
|
||||
const fieldsToOverride = _.zipObject(fields, values)
|
||||
|
||||
return {
|
||||
...log,
|
||||
...fieldsToOverride
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ const argv = require('minimist')(process.argv.slice(2))
|
|||
const crypto = require('crypto')
|
||||
const pgp = require('pg-promise')()
|
||||
const dateFormat = require('dateformat')
|
||||
const { getTimezoneOffset } = require('date-fns-tz')
|
||||
const { millisecondsToMinutes } = require('date-fns/fp')
|
||||
|
||||
const BN = require('./bn')
|
||||
const dbm = require('./postgresql_interface')
|
||||
|
|
@ -230,7 +232,7 @@ function plugins (settings, deviceId) {
|
|||
const localeConfig = configManager.getLocale(deviceId, settings.config)
|
||||
const fiatCode = localeConfig.fiatCurrency
|
||||
const cryptoCodes = localeConfig.cryptoCurrencies
|
||||
const timezone = localeConfig.timezone.split(':')
|
||||
const timezone = millisecondsToMinutes(getTimezoneOffset(localeConfig.timezone))
|
||||
|
||||
const tickerPromises = cryptoCodes.map(c => ticker.getRates(settings, fiatCode, c))
|
||||
const balancePromises = cryptoCodes.map(c => fiatBalance(fiatCode, c))
|
||||
|
|
@ -239,13 +241,12 @@ function plugins (settings, deviceId) {
|
|||
const currentConfigVersionPromise = fetchCurrentConfigVersion()
|
||||
const currentAvailablePromoCodes = loyalty.getNumberOfAvailablePromoCodes()
|
||||
const supportsBatchingPromise = cryptoCodes.map(c => wallet.supportsBatching(settings, c))
|
||||
const timezoneObj = { utcOffset: timezone[0], dstOffset: timezone[1] }
|
||||
|
||||
const promises = [
|
||||
buildAvailableCassettes(),
|
||||
pingPromise,
|
||||
currentConfigVersionPromise,
|
||||
timezoneObj
|
||||
timezone
|
||||
].concat(
|
||||
supportsBatchingPromise,
|
||||
tickerPromises,
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ const semver = require('semver')
|
|||
const sms = require('../sms')
|
||||
const _ = require('lodash/fp')
|
||||
const BN = require('../bn')
|
||||
const { zonedTimeToUtc, utcToZonedTime } = require('date-fns-tz/fp')
|
||||
|
||||
const compliance = require('../compliance')
|
||||
const complianceTriggers = require('../compliance-triggers')
|
||||
|
|
@ -129,14 +130,12 @@ function buildSms (data, receiptOptions) {
|
|||
.then(([customer, deviceConfig]) => {
|
||||
const formattedTx = _.mapKeys(_.camelCase)(tx)
|
||||
const localeConfig = configManager.getLocale(formattedTx.deviceId, config)
|
||||
const timezone = localeConfig.timezone.split(':')
|
||||
const dstOffset = timezone[1]
|
||||
const timezone = localeConfig.timezone
|
||||
|
||||
const cashInCommission = new BN(1).plus(new BN(formattedTx.commissionPercentage))
|
||||
|
||||
const rate = new BN(formattedTx.rawTickerPrice).multipliedBy(cashInCommission).decimalPlaces(2)
|
||||
const date = new Date()
|
||||
date.setMinutes(date.getMinutes() + parseInt(dstOffset))
|
||||
const date = utcToZonedTime(timezone, zonedTimeToUtc(process.env.TZ, new Date()))
|
||||
const dateString = `${date.toISOString().replace('T', ' ').slice(0, 19)}`
|
||||
|
||||
const data = {
|
||||
|
|
|
|||
15
new-lamassu-admin/package-lock.json
generated
15
new-lamassu-admin/package-lock.json
generated
|
|
@ -10465,6 +10465,16 @@
|
|||
"whatwg-url": "^8.0.0"
|
||||
}
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.26.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.26.0.tgz",
|
||||
"integrity": "sha512-VQI812dRi3cusdY/fhoBKvc6l2W8BPWU1FNVnFH9Nttjx4AFBRzfSVb/Eyc7jBT6e9sg1XtAGsYpBQ6c/jygbg=="
|
||||
},
|
||||
"date-fns-tz": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.1.6.tgz",
|
||||
"integrity": "sha512-nyy+URfFI3KUY7udEJozcoftju+KduaqkVfwyTIE0traBiVye09QnyWKLZK7drRr5h9B7sPJITmQnS3U6YOdQg=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz",
|
||||
|
|
@ -18316,11 +18326,6 @@
|
|||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"moment": {
|
||||
"version": "2.24.0",
|
||||
"resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
|
||||
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
|
||||
},
|
||||
"move-concurrently": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
|
||||
|
|
|
|||
|
|
@ -19,6 +19,8 @@
|
|||
"classnames": "2.2.6",
|
||||
"countries-and-timezones": "^2.4.0",
|
||||
"d3": "^6.2.0",
|
||||
"date-fns": "^2.26.0",
|
||||
"date-fns-tz": "^1.1.6",
|
||||
"downshift": "3.3.4",
|
||||
"file-saver": "2.0.2",
|
||||
"formik": "2.2.0",
|
||||
|
|
@ -29,15 +31,14 @@
|
|||
"lamassu-coins": "git+https://github.com/lamassu/lamassu-coins.git",
|
||||
"libphonenumber-js": "^1.7.50",
|
||||
"match-sorter": "^4.2.0",
|
||||
"moment": "2.24.0",
|
||||
"pretty-ms": "^2.1.0",
|
||||
"qrcode.react": "0.9.3",
|
||||
"ramda": "^0.26.1",
|
||||
"react": "^16.12.0",
|
||||
"react-copy-to-clipboard": "^5.0.2",
|
||||
"react-dom": "^16.10.2",
|
||||
"react-material-ui-carousel": "^2.2.7",
|
||||
"react-dropzone": "^11.4.2",
|
||||
"react-material-ui-carousel": "^2.2.7",
|
||||
"react-number-format": "^4.4.1",
|
||||
"react-otp-input": "^2.3.0",
|
||||
"react-router-dom": "5.1.2",
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { useLazyQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles, ClickAwayListener } from '@material-ui/core'
|
||||
import classnames from 'classnames'
|
||||
import { format, isSameDay } from 'date-fns/fp'
|
||||
import FileSaver from 'file-saver'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState, useCallback } from 'react'
|
||||
|
||||
|
|
@ -65,12 +65,13 @@ const DateContainer = ({ date, children, ...props }) => {
|
|||
{date && (
|
||||
<>
|
||||
<div className={classes.container}>
|
||||
<div className={classes.bigNumber}>{date.format('D')}</div>
|
||||
<div className={classes.bigNumber}>{format('d', date)}</div>
|
||||
<div className={classes.monthWeekDayContainer}>
|
||||
<span className={classes.monthYear}>{`${date.format(
|
||||
'MMM'
|
||||
)} ${date.format('YYYY')}`}</span>
|
||||
<span className={classes.weekDay}>{date.format('dddd')}</span>
|
||||
<span className={classes.monthYear}>{`${format(
|
||||
'MMM',
|
||||
date
|
||||
)} ${format('yyyy', date)}`}</span>
|
||||
<span className={classes.weekDay}>{format('EEEE', date)}</span>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
|
|
@ -186,8 +187,8 @@ const LogsDownloaderPopover = ({
|
|||
}
|
||||
|
||||
if (!range || !range.from) return
|
||||
if (range.from && !range.until) range.until = moment()
|
||||
if (moment(range.from).isSame(range.until, 'day')) range.until = moment()
|
||||
if (range.from && !range.until) range.until = new Date()
|
||||
if (isSameDay(range.until, range.from)) range.until = new Date()
|
||||
|
||||
if (selectedRadio === RANGE) {
|
||||
fetchLogs({
|
||||
|
|
@ -203,7 +204,7 @@ const LogsDownloaderPopover = ({
|
|||
|
||||
const createLogsFile = (logs, range) => {
|
||||
const formatDateFile = date => {
|
||||
return formatDate(date, timezone, 'YYYY-MM-DD_HH-mm')
|
||||
return formatDate(date, timezone, 'yyyy-MM-dd_HH-mm')
|
||||
}
|
||||
|
||||
const blob = new window.Blob([logs], {
|
||||
|
|
@ -277,7 +278,7 @@ const LogsDownloaderPopover = ({
|
|||
)}
|
||||
</div>
|
||||
<DateRangePicker
|
||||
maxDate={moment()}
|
||||
maxDate={new Date()}
|
||||
onRangeChange={handleRangeChange}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import moment from 'moment'
|
||||
import {
|
||||
add,
|
||||
differenceInMonths,
|
||||
format,
|
||||
getDay,
|
||||
getDaysInMonth,
|
||||
isAfter,
|
||||
isSameDay,
|
||||
isSameMonth,
|
||||
lastDayOfMonth,
|
||||
startOfMonth,
|
||||
startOfWeek,
|
||||
sub
|
||||
} from 'date-fns/fp'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
|
|
@ -72,49 +85,36 @@ const styles = {
|
|||
const useStyles = makeStyles(styles)
|
||||
|
||||
const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
|
||||
const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(moment())
|
||||
const [currentDisplayedMonth, setCurrentDisplayedMonth] = useState(new Date())
|
||||
|
||||
const classes = useStyles()
|
||||
|
||||
const weekdays = moment.weekdaysMin().map(day => day.slice(0, 1))
|
||||
const monthLength = month =>
|
||||
Number.parseInt(
|
||||
moment(month)
|
||||
.endOf('month')
|
||||
.format('D')
|
||||
)
|
||||
const weekdays = Array.from(Array(7)).map((_, i) =>
|
||||
format('EEEEE', add({ days: i }, startOfWeek(new Date())))
|
||||
)
|
||||
|
||||
const monthLength = month => getDaysInMonth(month)
|
||||
|
||||
const monthdays = month => {
|
||||
const lastMonth = moment(month).subtract(1, 'month')
|
||||
const lastMonthRange = R.range(
|
||||
0,
|
||||
moment(month)
|
||||
.startOf('month')
|
||||
.weekday()
|
||||
).reverse()
|
||||
const lastMonth = sub({ months: 1 }, month)
|
||||
const lastMonthRange = R.range(0, getDay(startOfMonth(month))).reverse()
|
||||
const lastMonthDays = R.map(i =>
|
||||
moment(lastMonth)
|
||||
.endOf('month')
|
||||
.subtract(i, 'days')
|
||||
sub({ days: i }, lastDayOfMonth(lastMonth))
|
||||
)(lastMonthRange)
|
||||
|
||||
const thisMonthRange = R.range(0, monthLength(month))
|
||||
const thisMonthDays = R.map(i =>
|
||||
moment(month)
|
||||
.startOf('month')
|
||||
.add(i, 'days')
|
||||
)(thisMonthRange)
|
||||
const thisMonthDays = R.map(i => add({ days: i }, startOfMonth(month)))(
|
||||
thisMonthRange
|
||||
)
|
||||
|
||||
const nextMonth = moment(month).add(1, 'month')
|
||||
const nextMonth = add({ months: 1 }, month)
|
||||
const nextMonthRange = R.range(
|
||||
0,
|
||||
42 - lastMonthDays.length - thisMonthDays.length
|
||||
)
|
||||
const nextMonthDays = R.map(i =>
|
||||
moment(nextMonth)
|
||||
.startOf('month')
|
||||
.add(i, 'days')
|
||||
)(nextMonthRange)
|
||||
const nextMonthDays = R.map(i => add({ days: i }, startOfMonth(nextMonth)))(
|
||||
nextMonthRange
|
||||
)
|
||||
|
||||
return R.concat(R.concat(lastMonthDays, thisMonthDays), nextMonthDays)
|
||||
}
|
||||
|
|
@ -122,22 +122,24 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
|
|||
const getRow = (month, row) => monthdays(month).slice(row * 7 - 7, row * 7)
|
||||
|
||||
const handleNavPrev = currentMonth => {
|
||||
const prevMonth = moment(currentMonth).subtract(1, 'month')
|
||||
const prevMonth = sub({ months: 1 }, currentMonth)
|
||||
if (!minDate) setCurrentDisplayedMonth(prevMonth)
|
||||
else {
|
||||
setCurrentDisplayedMonth(
|
||||
prevMonth.isSameOrAfter(minDate, 'month')
|
||||
isSameMonth(minDate, prevMonth) ||
|
||||
differenceInMonths(minDate, prevMonth) > 0
|
||||
? prevMonth
|
||||
: currentDisplayedMonth
|
||||
)
|
||||
}
|
||||
}
|
||||
const handleNavNext = currentMonth => {
|
||||
const nextMonth = moment(currentMonth).add(1, 'month')
|
||||
const nextMonth = add({ months: 1 }, currentMonth)
|
||||
if (!maxDate) setCurrentDisplayedMonth(nextMonth)
|
||||
else {
|
||||
setCurrentDisplayedMonth(
|
||||
nextMonth.isSameOrBefore(maxDate, 'month')
|
||||
isSameMonth(maxDate, nextMonth) ||
|
||||
differenceInMonths(nextMonth, maxDate) > 0
|
||||
? nextMonth
|
||||
: currentDisplayedMonth
|
||||
)
|
||||
|
|
@ -153,9 +155,10 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
|
|||
<Arrow />
|
||||
</button>
|
||||
<span>
|
||||
{`${currentDisplayedMonth.format(
|
||||
'MMMM'
|
||||
)} ${currentDisplayedMonth.format('YYYY')}`}
|
||||
{`${format('MMMM', currentDisplayedMonth)} ${format(
|
||||
'yyyy',
|
||||
currentDisplayedMonth
|
||||
)}`}
|
||||
</span>
|
||||
<button
|
||||
className={classes.button}
|
||||
|
|
@ -180,13 +183,15 @@ const Calendar = ({ minDate, maxDate, handleSelect, ...props }) => {
|
|||
onClick={() => handleSelect(day, minDate, maxDate)}>
|
||||
<Tile
|
||||
isDisabled={
|
||||
(maxDate && day.isAfter(maxDate, 'day')) ||
|
||||
(minDate && day.isBefore(minDate, 'day'))
|
||||
(maxDate && isAfter(maxDate, day)) ||
|
||||
(minDate && isAfter(day, minDate))
|
||||
}
|
||||
isLowerBound={day.isSame(props.from, 'day')}
|
||||
isUpperBound={day.isSame(props.to, 'day')}
|
||||
isBetween={day.isBetween(props.from, props.to, 'day', [])}>
|
||||
{day.format('D')}
|
||||
isLowerBound={isSameDay(props.from, day)}
|
||||
isUpperBound={isSameDay(props.to, day)}
|
||||
isBetween={
|
||||
isAfter(props.from, day) && isAfter(day, props.to)
|
||||
}>
|
||||
{format('d', day)}
|
||||
</Tile>
|
||||
</td>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,11 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import classnames from 'classnames'
|
||||
import moment from 'moment'
|
||||
import {
|
||||
differenceInDays,
|
||||
differenceInMonths,
|
||||
isSameMonth,
|
||||
set
|
||||
} from 'date-fns/fp'
|
||||
import React, { useState, useEffect } from 'react'
|
||||
|
||||
import Calendar from './Calendar'
|
||||
|
|
@ -26,19 +31,25 @@ const DateRangePicker = ({ minDate, maxDate, className, onRangeChange }) => {
|
|||
|
||||
const handleSelect = (day, minDate, maxDate) => {
|
||||
if (
|
||||
(maxDate && day.isAfter(maxDate, 'day')) ||
|
||||
(minDate && day.isBefore(minDate, 'day'))
|
||||
(maxDate && differenceInDays(maxDate, day) > 0) ||
|
||||
(minDate && differenceInDays(day, minDate) > 0)
|
||||
)
|
||||
return
|
||||
|
||||
if (from && !to && day.isBefore(from, 'day')) {
|
||||
if (from && !to && differenceInDays(day, from) > 0) {
|
||||
setTo(from)
|
||||
setFrom(day)
|
||||
return
|
||||
}
|
||||
|
||||
if (from && !to && day.isSameOrAfter(from, 'day')) {
|
||||
setTo(moment(day.toDate().setHours(23, 59, 59, 999)))
|
||||
if (
|
||||
from &&
|
||||
!to &&
|
||||
(isSameMonth(from, day) || differenceInMonths(from, day) > 0)
|
||||
) {
|
||||
setTo(
|
||||
set({ hours: 23, minutes: 59, seconds: 59, milliseconds: 999 }, day)
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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, { useContext } from 'react'
|
||||
|
||||
|
|
@ -10,6 +9,7 @@ import { Tooltip } from 'src/components/Tooltip'
|
|||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
import { H4, Info2, P } from 'src/components/typography'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import styles from './Accounting.styles'
|
||||
|
||||
|
|
@ -49,6 +49,12 @@ const GET_OPERATOR_BY_USERNAME = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const GET_DATA = gql`
|
||||
query getData {
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const Assets = ({ balance, hedgingReserve, currency }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
|
|
@ -97,12 +103,20 @@ const Accounting = () => {
|
|||
const classes = useStyles()
|
||||
const { userData } = useContext(AppContext)
|
||||
|
||||
const { data, loading } = useQuery(GET_OPERATOR_BY_USERNAME, {
|
||||
context: { clientName: 'pazuz' },
|
||||
variables: { username: userData?.username }
|
||||
})
|
||||
const { data: opData, loading: operatorLoading } = useQuery(
|
||||
GET_OPERATOR_BY_USERNAME,
|
||||
{
|
||||
context: { clientName: 'pazuz' },
|
||||
variables: { username: userData?.username }
|
||||
}
|
||||
)
|
||||
|
||||
const operatorData = R.path(['operatorByUsername'], data)
|
||||
const { data: configResponse, loading: configLoading } = useQuery(GET_DATA)
|
||||
const timezone = R.path(['config', 'locale_timezone'], configResponse)
|
||||
|
||||
const loading = operatorLoading && configLoading
|
||||
|
||||
const operatorData = R.path(['operatorByUsername'], opData)
|
||||
|
||||
const elements = [
|
||||
{
|
||||
|
|
@ -144,14 +158,14 @@ const Accounting = () => {
|
|||
width: 150,
|
||||
size: 'sm',
|
||||
textAlign: 'right',
|
||||
view: it => moment.utc(it.created).format('YYYY-MM-DD')
|
||||
view: it => formatDate(it.created, timezone, 'YYYY-MM-DD')
|
||||
},
|
||||
{
|
||||
header: 'Time',
|
||||
width: 150,
|
||||
size: 'sm',
|
||||
textAlign: 'right',
|
||||
view: it => moment.utc(it.created).format('HH:mm:ss')
|
||||
view: it => formatDate(it.created, timezone, 'YYYY-MM-DD')
|
||||
}
|
||||
]
|
||||
|
||||
|
|
|
|||
|
|
@ -31,12 +31,12 @@ const GraphTooltip = ({
|
|||
formatDate(
|
||||
dateInterval[1],
|
||||
null,
|
||||
period.code === 'day' ? 'MMM D, HH:mm' : 'MMM D'
|
||||
period.code === 'day' ? 'MMM d, HH:mm' : 'MMM d'
|
||||
),
|
||||
formatDate(
|
||||
dateInterval[0],
|
||||
null,
|
||||
period.code === 'day' ? 'HH:mm' : 'MMM D'
|
||||
period.code === 'day' ? 'HH:mm' : 'MMM d'
|
||||
)
|
||||
]
|
||||
: [
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { Box } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import moment from 'moment'
|
||||
import { getTimezoneOffset } from 'date-fns-tz'
|
||||
import { format, add, startOfWeek } from 'date-fns/fp'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
|
|
@ -24,7 +25,9 @@ const dayOptions = R.map(
|
|||
code: R.toLower(it),
|
||||
display: it
|
||||
}),
|
||||
moment.weekdays()
|
||||
Array.from(Array(7)).map((_, i) =>
|
||||
format('EEEE', add({ days: i }, startOfWeek(new Date())))
|
||||
)
|
||||
)
|
||||
|
||||
const HourOfDayBarGraphHeader = ({
|
||||
|
|
@ -47,16 +50,14 @@ const HourOfDayBarGraphHeader = ({
|
|||
cashOut: <div className={classes.cashOutIcon}></div>
|
||||
}
|
||||
|
||||
const offset = parseInt(timezone.split(':')[1]) * MINUTE
|
||||
const offset = getTimezoneOffset(timezone)
|
||||
|
||||
const txsPerWeekday = R.reduce(
|
||||
(acc, value) => {
|
||||
const created = new Date(value.created)
|
||||
// console.log('before', R.clone(created))
|
||||
created.setTime(
|
||||
created.getTime() + created.getTimezoneOffset() * MINUTE + offset
|
||||
)
|
||||
// console.log('after', R.clone(created))
|
||||
switch (created.getDay()) {
|
||||
case 0:
|
||||
acc.sunday.push(value)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import BigNumber from 'bignumber.js'
|
||||
import * as d3 from 'd3'
|
||||
import moment from 'moment'
|
||||
import { getTimezoneOffset } from 'date-fns-tz'
|
||||
import { add, startOfDay } from 'date-fns/fp'
|
||||
import * as R from 'ramda'
|
||||
import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
|
||||
|
|
@ -13,6 +14,7 @@ import {
|
|||
subheaderColor
|
||||
} from 'src/styling/variables'
|
||||
import { MINUTE } from 'src/utils/time'
|
||||
import { toUtc } from 'src/utils/timezones'
|
||||
|
||||
const Graph = ({
|
||||
data,
|
||||
|
|
@ -38,7 +40,7 @@ const Graph = ({
|
|||
[]
|
||||
)
|
||||
|
||||
const offset = parseInt(timezone.split(':')[1]) * MINUTE
|
||||
const offset = getTimezoneOffset(timezone)
|
||||
|
||||
const getTickIntervals = (domain, interval) => {
|
||||
const ticks = []
|
||||
|
|
@ -97,13 +99,8 @@ const Graph = ({
|
|||
const x = d3
|
||||
.scaleUtc()
|
||||
.domain([
|
||||
moment()
|
||||
.startOf('day')
|
||||
.utc(),
|
||||
moment()
|
||||
.startOf('day')
|
||||
.add(1, 'day')
|
||||
.utc()
|
||||
toUtc(startOfDay(new Date())),
|
||||
toUtc(add({ days: 1 }, startOfDay(new Date())))
|
||||
])
|
||||
.rangeRound([GRAPH_MARGIN.left, GRAPH_WIDTH - GRAPH_MARGIN.right])
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import BigNumber from 'bignumber.js'
|
||||
import * as d3 from 'd3'
|
||||
import moment from 'moment'
|
||||
import { getTimezoneOffset } from 'date-fns-tz'
|
||||
import { add, format, startOfWeek, startOfYear } from 'date-fns/fp'
|
||||
import * as R from 'ramda'
|
||||
import React, { memo, useCallback, useEffect, useMemo, useRef } from 'react'
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ const Graph = ({
|
|||
[]
|
||||
)
|
||||
|
||||
const offset = parseInt(timezone.split(':')[1]) * MINUTE
|
||||
const offset = getTimezoneOffset(timezone)
|
||||
const NOW = Date.now() + offset
|
||||
|
||||
const periodDomains = {
|
||||
|
|
@ -86,8 +87,13 @@ const Graph = ({
|
|||
const previousDateWeekday = previousDate.getUTCDay()
|
||||
const previousDateMonth = previousDate.getUTCMonth()
|
||||
|
||||
const daysOfWeek = moment.weekdaysShort()
|
||||
const months = moment.monthsShort()
|
||||
const daysOfWeek = Array.from(Array(7)).map((_, i) =>
|
||||
format('EEE', add({ days: i }, startOfWeek(new Date())))
|
||||
)
|
||||
|
||||
const months = Array.from(Array(12)).map((_, i) =>
|
||||
format('LLL', add({ months: i }, startOfYear(new Date())))
|
||||
)
|
||||
|
||||
return {
|
||||
previous:
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import Grid from '@material-ui/core/Grid'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { differenceInYears, format } from 'date-fns/fp'
|
||||
import _ from 'lodash/fp'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import { useState, React } from 'react'
|
||||
import * as Yup from 'yup'
|
||||
|
|
@ -23,7 +23,6 @@ import { ReactComponent as CustomerListViewIcon } from 'src/styling/icons/circle
|
|||
import { ReactComponent as OverviewReversedIcon } from 'src/styling/icons/circle buttons/overview/white.svg'
|
||||
import { ReactComponent as OverviewIcon } from 'src/styling/icons/circle buttons/overview/zodiac.svg'
|
||||
import { URI } from 'src/utils/apollo'
|
||||
import { ifNotNull } from 'src/utils/nullCheck'
|
||||
|
||||
import styles from './CustomerData.styles.js'
|
||||
import { EditableCard } from './components'
|
||||
|
|
@ -116,16 +115,13 @@ const CustomerData = ({ customer, updateCustomer }) => {
|
|||
{
|
||||
name: 'birthDate',
|
||||
label: 'Birth Date',
|
||||
value: ifNotNull(rawDob, moment.utc(rawDob).format('YYYY-MM-DD')),
|
||||
value: (rawDob && format('yyyy-MM-dd', rawDob)) ?? '',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
name: 'age',
|
||||
label: 'Age',
|
||||
value: ifNotNull(
|
||||
rawDob,
|
||||
moment.utc().diff(moment.utc(rawDob).format('YYYY-MM-DD'), 'years')
|
||||
),
|
||||
value: (rawDob && differenceInYears(rawDob, new Date())) ?? '',
|
||||
component: TextInput
|
||||
},
|
||||
{
|
||||
|
|
@ -143,10 +139,8 @@ const CustomerData = ({ customer, updateCustomer }) => {
|
|||
{
|
||||
name: 'expirationDate',
|
||||
label: 'Expiration Date',
|
||||
value: ifNotNull(
|
||||
rawExpirationDate,
|
||||
moment.utc(rawExpirationDate).format('YYYY-MM-DD')
|
||||
),
|
||||
value:
|
||||
(rawExpirationDate && format('yyyy-MM-dd', rawExpirationDate)) ?? '',
|
||||
component: TextInput
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import moment from 'moment'
|
||||
import { format } from 'date-fns/fp'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
|
||||
|
|
@ -7,7 +7,6 @@ import { MainStatus } from 'src/components/Status'
|
|||
import DataTable from 'src/components/tables/DataTable'
|
||||
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
|
||||
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
|
||||
import { ifNotNull } from 'src/utils/nullCheck'
|
||||
|
||||
import styles from './CustomersList.styles'
|
||||
import { getAuthorizedStatus, getFormattedPhone, getName } from './helper'
|
||||
|
|
@ -45,7 +44,7 @@ const CustomersList = ({ data, locale, onClick, loading }) => {
|
|||
header: 'Last active',
|
||||
width: 137,
|
||||
view: it =>
|
||||
ifNotNull(it.lastActive, moment.utc(it.lastActive).format('YYYY-MM-D'))
|
||||
(it.lastActive && format('yyyy-MM-d', new Date(it.lastActive))) ?? ''
|
||||
},
|
||||
{
|
||||
header: 'Last transaction',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import { Box } from '@material-ui/core'
|
||||
import moment from 'moment'
|
||||
import { differenceInYears, format } from 'date-fns/fp'
|
||||
import * as R from 'ramda'
|
||||
import React, { memo } from 'react'
|
||||
|
||||
|
|
@ -9,6 +9,7 @@ import {
|
|||
OVERRIDE_REJECTED
|
||||
} from 'src/pages/Customers/components/propertyCard'
|
||||
import { ifNotNull } from 'src/utils/nullCheck'
|
||||
import { toUtc } from 'src/utils/timezones'
|
||||
|
||||
import { getName } from '../helper'
|
||||
|
||||
|
|
@ -33,14 +34,14 @@ const IdDataCard = memo(({ customerData, updateCustomer }) => {
|
|||
},
|
||||
{
|
||||
header: 'Birth Date',
|
||||
display: ifNotNull(rawDob, moment.utc(rawDob).format('YYYY-MM-DD')),
|
||||
display: ifNotNull(rawDob, format('YYYY-MM-DD', rawDob)),
|
||||
size: 110
|
||||
},
|
||||
{
|
||||
header: 'Age',
|
||||
display: ifNotNull(
|
||||
rawDob,
|
||||
moment.utc().diff(moment.utc(rawDob).format('YYYY-MM-DD'), 'years')
|
||||
differenceInYears(toUtc(rawDob), toUtc(new Date()))
|
||||
),
|
||||
size: 50
|
||||
},
|
||||
|
|
@ -58,7 +59,7 @@ const IdDataCard = memo(({ customerData, updateCustomer }) => {
|
|||
header: 'Expiration Date',
|
||||
display: ifNotNull(
|
||||
rawExpirationDate,
|
||||
moment.utc(rawExpirationDate).format('YYYY-MM-DD')
|
||||
format('YYYY-MM-DD', rawExpirationDate)
|
||||
)
|
||||
}
|
||||
]
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ const TransactionsList = ({ customer, data, loading, locale }) => {
|
|||
!R.isNil(timezone) &&
|
||||
ifNotNull(
|
||||
customer.lastActive,
|
||||
formatDate(customer.lastActive, timezone, 'YYYY-MM-D')
|
||||
formatDate(customer.lastActive, timezone, 'yyyy-MM-d')
|
||||
)
|
||||
},
|
||||
{
|
||||
|
|
@ -122,7 +122,7 @@ const TransactionsList = ({ customer, data, loading, locale }) => {
|
|||
{
|
||||
header: 'Date',
|
||||
width: 100,
|
||||
view: it => formatDate(it.created, timezone, 'YYYY-MM-D')
|
||||
view: it => formatDate(it.created, timezone, 'yyyy-MM-d')
|
||||
},
|
||||
{
|
||||
header: 'Time (h:m:s)',
|
||||
|
|
|
|||
|
|
@ -1,8 +1,9 @@
|
|||
import * as d3 from 'd3'
|
||||
import moment from 'moment'
|
||||
import { add } from 'date-fns/fp'
|
||||
import React, { useEffect, useRef, useCallback } from 'react'
|
||||
|
||||
import { backgroundColor, java, neon } from 'src/styling/variables'
|
||||
import { formatDate, toUtc } from 'src/utils/timezones'
|
||||
|
||||
const RefScatterplot = ({ data: realData, timeFrame, timezone }) => {
|
||||
const svgRef = useRef()
|
||||
|
|
@ -11,7 +12,6 @@ const RefScatterplot = ({ data: realData, timeFrame, timezone }) => {
|
|||
const margin = { top: 25, right: 0, bottom: 25, left: 15 }
|
||||
const width = 555 - margin.left - margin.right
|
||||
const height = 150 - margin.top - margin.bottom
|
||||
const dstOffset = parseInt(timezone.split(':')[1])
|
||||
// finds maximum value for the Y axis. Minimum value is 100. If value is multiple of 1000, add 100
|
||||
// (this is because the Y axis looks best with multiples of 100)
|
||||
const findMaxY = () => {
|
||||
|
|
@ -30,10 +30,7 @@ const RefScatterplot = ({ data: realData, timeFrame, timezone }) => {
|
|||
case 'Month':
|
||||
return d3.timeFormat('%b %d')(v)
|
||||
default:
|
||||
return moment
|
||||
.utc(v)
|
||||
.add(dstOffset, 'minutes')
|
||||
.format('HH:mm')
|
||||
return formatDate(v, timezone, 'HH:mm')
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -95,16 +92,14 @@ const RefScatterplot = ({ data: realData, timeFrame, timezone }) => {
|
|||
const x = d3
|
||||
.scaleTime()
|
||||
.domain([
|
||||
moment()
|
||||
.add(-xAxisSettings.subtractDays, 'day')
|
||||
.valueOf(),
|
||||
moment().valueOf()
|
||||
add({ days: -xAxisSettings.subtractDays }, new Date()).valueOf(),
|
||||
new Date().valueOf()
|
||||
])
|
||||
.range(xAxisSettings.timeRange)
|
||||
.nice(xAxisSettings.nice)
|
||||
|
||||
const timeValue = s => {
|
||||
const date = moment.utc(s)
|
||||
const date = toUtc(s)
|
||||
return x(date.valueOf())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@ import Grid from '@material-ui/core/Grid'
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classnames from 'classnames'
|
||||
import { isAfter, sub } from 'date-fns/fp'
|
||||
import gql from 'graphql-tag'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
|
|
@ -13,6 +13,7 @@ import { ReactComponent as PercentDownIcon } from 'src/styling/icons/dashboard/d
|
|||
import { ReactComponent as PercentNeutralIcon } from 'src/styling/icons/dashboard/equal.svg'
|
||||
import { ReactComponent as PercentUpIcon } from 'src/styling/icons/dashboard/up.svg'
|
||||
import { fromNamespace } from 'src/utils/config'
|
||||
import { toTimezone } from 'src/utils/timezones'
|
||||
|
||||
import PercentageChart from './Graphs/PercentageChart'
|
||||
import LineChart from './Graphs/RefLineChart'
|
||||
|
|
@ -28,22 +29,22 @@ const useStyles = makeStyles(styles)
|
|||
const mapToFee = R.map(R.prop('cashInFee'))
|
||||
|
||||
const getDateSecondsAgo = (seconds = 0, startDate = null) => {
|
||||
const date = startDate ? moment(startDate) : moment()
|
||||
return date.subtract(seconds, 'second')
|
||||
const date = startDate ? new Date(startDate) : new Date()
|
||||
return sub({ seconds: seconds }, date)
|
||||
}
|
||||
|
||||
const ranges = {
|
||||
Day: {
|
||||
left: getDateSecondsAgo(2 * 24 * 3600, moment()),
|
||||
right: getDateSecondsAgo(24 * 3600, moment())
|
||||
left: getDateSecondsAgo(2 * 24 * 3600, new Date()),
|
||||
right: getDateSecondsAgo(24 * 3600, new Date())
|
||||
},
|
||||
Week: {
|
||||
left: getDateSecondsAgo(14 * 24 * 3600, moment()),
|
||||
right: getDateSecondsAgo(7 * 24 * 3600, moment())
|
||||
left: getDateSecondsAgo(14 * 24 * 3600, new Date()),
|
||||
right: getDateSecondsAgo(7 * 24 * 3600, new Date())
|
||||
},
|
||||
Month: {
|
||||
left: getDateSecondsAgo(60 * 24 * 3600, moment()),
|
||||
right: getDateSecondsAgo(30 * 24 * 3600, moment())
|
||||
left: getDateSecondsAgo(60 * 24 * 3600, new Date()),
|
||||
right: getDateSecondsAgo(30 * 24 * 3600, new Date())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -83,18 +84,14 @@ const SystemPerformance = () => {
|
|||
if (!getLastTimePeriod) {
|
||||
return (
|
||||
t.error === null &&
|
||||
moment
|
||||
.utc(t.created)
|
||||
.utcOffset(timezone)
|
||||
.isBetween(ranges[selectedRange].right, moment())
|
||||
isAfter(ranges[selectedRange].right, toTimezone(t.created, timezone)) &&
|
||||
isAfter(toTimezone(t.created, timezone), new Date())
|
||||
)
|
||||
}
|
||||
return (
|
||||
t.error === null &&
|
||||
moment
|
||||
.utc(t.created)
|
||||
.utcOffset(timezone)
|
||||
.isBetween(ranges[selectedRange].left, ranges[selectedRange].right)
|
||||
isAfter(ranges[selectedRange].left, toTimezone(t.created, timezone)) &&
|
||||
isAfter(toTimezone(t.created, timezone), ranges[selectedRange].right)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@ import { useQuery } from '@apollo/react-hooks'
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classnames from 'classnames'
|
||||
import { format } from 'date-fns/fp'
|
||||
import gql from 'graphql-tag'
|
||||
import { utils as coinUtils } from 'lamassu-coins'
|
||||
import moment from 'moment'
|
||||
import QRCode from 'qrcode.react'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
|
@ -275,12 +275,8 @@ const Funding = () => {
|
|||
<Td width={sizes.big}>
|
||||
{it.fiatValue} {selected.fiatCode}
|
||||
</Td>
|
||||
<Td width={sizes.date}>
|
||||
{moment(it.date).format('YYYY-MM-DD')}
|
||||
</Td>
|
||||
<Td width={sizes.time}>
|
||||
{moment(it.date).format('hh:mm:ss')}
|
||||
</Td>
|
||||
<Td width={sizes.date}>{format('yyyy-MM-dd', it.date)}</Td>
|
||||
<Td width={sizes.time}>{format('hh:mm:ss', it.date)}</Td>
|
||||
<Td width={sizes.big}>add</Td>
|
||||
</Tr>
|
||||
))}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import * as ct from 'countries-and-timezones'
|
||||
import * as R from 'ramda'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import Autocomplete from 'src/components/inputs/formik/Autocomplete.js'
|
||||
import { getTzLabels } from 'src/utils/timezones'
|
||||
import timezoneList from 'src/utils/timezone-list'
|
||||
|
||||
const getFields = (getData, names, onChange, auxElements = []) => {
|
||||
return R.filter(
|
||||
|
|
@ -38,9 +37,7 @@ const allFields = (getData, onChange, auxElements = []) => {
|
|||
const currencyData = getData(['currencies'])
|
||||
const languageData = getData(['languages'])
|
||||
const cryptoData = getData(['cryptoCurrencies'])
|
||||
const timezonesData = R.values(ct.getAllTimezones())
|
||||
|
||||
const tzLabels = getTzLabels(timezonesData)
|
||||
const timezonesData = timezoneList
|
||||
|
||||
const findSuggestion = it => {
|
||||
const machine = R.find(R.propEq('deviceId', it.machine))(machineData)
|
||||
|
|
@ -117,10 +114,10 @@ const allFields = (getData, onChange, auxElements = []) => {
|
|||
name: 'timezone',
|
||||
width: 320,
|
||||
size: 'sm',
|
||||
view: getView(tzLabels, 'label'),
|
||||
view: getView(timezonesData, 'label'),
|
||||
input: Autocomplete,
|
||||
inputProps: {
|
||||
options: tzLabels,
|
||||
options: timezonesData,
|
||||
valueProp: 'code',
|
||||
labelProp: 'label'
|
||||
}
|
||||
|
|
@ -134,7 +131,8 @@ const mainFields = (auxData, configureCoin) => {
|
|||
return getFields(
|
||||
getData,
|
||||
['country', 'fiatCurrency', 'languages', 'cryptoCurrencies', 'timezone'],
|
||||
configureCoin
|
||||
configureCoin,
|
||||
undefined
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ const Details = ({ data, timezone }) => {
|
|||
<Label3 className={classes.label3}>Paired at</Label3>
|
||||
<P>
|
||||
{data.pairedAt
|
||||
? formatDate(data.pairedAt, timezone, 'YYYY-MM-DD HH:mm:ss')
|
||||
? formatDate(data.pairedAt, timezone, 'yyyy-MM-dd HH:mm:ss')
|
||||
: ''}
|
||||
</P>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import moment from 'moment'
|
||||
import { differenceInSeconds } from 'date-fns/fp'
|
||||
import React from 'react'
|
||||
|
||||
import { Status } from 'src/components/Status'
|
||||
|
|
@ -13,8 +13,7 @@ const useStyles = makeStyles(styles)
|
|||
|
||||
const makeLastPing = lastPing => {
|
||||
if (!lastPing) return null
|
||||
const now = moment()
|
||||
const secondsAgo = now.diff(lastPing, 'seconds')
|
||||
const secondsAgo = differenceInSeconds(lastPing, new Date())
|
||||
if (secondsAgo < 60) {
|
||||
return `${secondsAgo} ${secondsAgo === 1 ? 'second' : 'seconds'} ago`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
import { useLazyQuery } from '@apollo/react-hooks'
|
||||
import { useQuery, useLazyQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import gql from 'graphql-tag'
|
||||
import { utils as coinUtils } from 'lamassu-coins'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import React, { useEffect, useState } from 'react'
|
||||
|
||||
|
|
@ -12,6 +11,7 @@ import { mainStyles } from 'src/pages/Transactions/Transactions.styles'
|
|||
import { getStatus } from 'src/pages/Transactions/helper'
|
||||
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
|
||||
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import DataTable from './DataTable'
|
||||
const useStyles = makeStyles(mainStyles)
|
||||
|
|
@ -57,13 +57,19 @@ const GET_TRANSACTIONS = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const GET_DATA = gql`
|
||||
query getData {
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const Transactions = ({ id }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [extraHeight, setExtraHeight] = useState(0)
|
||||
const [clickedId, setClickedId] = useState('')
|
||||
|
||||
const [getTx, { data: txResponse, loading }] = useLazyQuery(
|
||||
const [getTx, { data: txResponse, loading: txLoading }] = useLazyQuery(
|
||||
GET_TRANSACTIONS,
|
||||
{
|
||||
variables: {
|
||||
|
|
@ -73,6 +79,11 @@ const Transactions = ({ id }) => {
|
|||
}
|
||||
)
|
||||
|
||||
const { data: configData, loading: configLoading } = useQuery(GET_DATA)
|
||||
const timezone = R.path(['config', 'locale_timezone'], configData)
|
||||
|
||||
const loading = txLoading && configLoading
|
||||
|
||||
if (!loading && txResponse) {
|
||||
txResponse.transactions = txResponse.transactions.splice(0, 5)
|
||||
}
|
||||
|
|
@ -135,7 +146,7 @@ const Transactions = ({ id }) => {
|
|||
},
|
||||
{
|
||||
header: 'Date (UTC)',
|
||||
view: it => moment.utc(it.created).format('YYYY-MM-DD'),
|
||||
view: it => formatDate(it.created, timezone, 'yyyy-MM-dd'),
|
||||
textAlign: 'left',
|
||||
size: 'sm',
|
||||
width: 140
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { useQuery, useMutation } 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 } from 'react'
|
||||
import * as Yup from 'yup'
|
||||
|
|
@ -13,6 +12,7 @@ import DataTable from 'src/components/tables/DataTable'
|
|||
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
||||
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
|
||||
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
const GET_BATCHES = gql`
|
||||
query cashboxBatches {
|
||||
|
|
@ -41,6 +41,12 @@ const EDIT_BATCH = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const GET_DATA = gql`
|
||||
query getData {
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const styles = {
|
||||
operationType: {
|
||||
marginLeft: 8
|
||||
|
|
@ -68,13 +74,18 @@ const CashboxHistory = ({ machines, currency }) => {
|
|||
const [error, setError] = useState(false)
|
||||
const [fields, setFields] = useState([])
|
||||
|
||||
const { data, loading } = useQuery(GET_BATCHES)
|
||||
const { data: batchesData, loading: batchesLoading } = useQuery(GET_BATCHES)
|
||||
|
||||
const [editBatch] = useMutation(EDIT_BATCH, {
|
||||
refetchQueries: () => ['cashboxBatches']
|
||||
})
|
||||
|
||||
const batches = R.path(['cashboxBatches'])(data)
|
||||
const { data: configData, loading: configLoading } = useQuery(GET_DATA)
|
||||
const timezone = R.path(['config', 'locale_timezone'], configData)
|
||||
|
||||
const loading = batchesLoading && configLoading
|
||||
|
||||
const batches = R.path(['cashboxBatches'])(batchesData)
|
||||
|
||||
const getOperationRender = R.reduce(
|
||||
(ret, i) =>
|
||||
|
|
@ -176,14 +187,14 @@ const CashboxHistory = ({ machines, currency }) => {
|
|||
header: 'Date',
|
||||
width: 135,
|
||||
textAlign: 'right',
|
||||
view: it => moment.utc(it.created).format('YYYY-MM-DD')
|
||||
view: it => formatDate(it.created, timezone, 'YYYY-MM-DD')
|
||||
},
|
||||
{
|
||||
name: 'time',
|
||||
header: 'Time (h:m)',
|
||||
width: 125,
|
||||
textAlign: 'right',
|
||||
view: it => moment.utc(it.created).format('HH:mm')
|
||||
view: it => formatDate(it.created, timezone, 'HH:mm')
|
||||
},
|
||||
{
|
||||
name: 'performedBy',
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { useQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
import { formatDistance } from 'date-fns'
|
||||
import gql from 'graphql-tag'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
import { useHistory, useLocation } from 'react-router-dom'
|
||||
|
|
@ -89,7 +89,12 @@ const MachineStatus = () => {
|
|||
width: 200,
|
||||
size: 'sm',
|
||||
textAlign: 'left',
|
||||
view: m => (m.lastPing ? moment(m.lastPing).fromNow() : 'unknown')
|
||||
view: m =>
|
||||
m.lastPing
|
||||
? formatDistance(new Date(m.lastPing), new Date(), {
|
||||
addSuffix: true
|
||||
})
|
||||
: 'unknown'
|
||||
},
|
||||
{
|
||||
header: 'Software Version',
|
||||
|
|
|
|||
|
|
@ -197,7 +197,7 @@ const Logs = () => {
|
|||
formatDate(
|
||||
log.timestamp,
|
||||
timezone,
|
||||
'YYYY-MM-DD HH:mm'
|
||||
'yyyy-MM-dd HH:mm'
|
||||
)}
|
||||
</TableCell>
|
||||
<TableCell>{log.logLevel}</TableCell>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||
import gql from 'graphql-tag'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
import parser from 'ua-parser-js'
|
||||
|
|
@ -9,6 +8,7 @@ import { IconButton } from 'src/components/buttons'
|
|||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
const GET_SESSIONS = gql`
|
||||
query sessions {
|
||||
|
|
@ -28,17 +28,28 @@ const DELETE_SESSION = gql`
|
|||
}
|
||||
`
|
||||
|
||||
const GET_DATA = gql`
|
||||
query getData {
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const isLocalhost = ip => {
|
||||
return ip === 'localhost' || ip === '::1' || ip === '127.0.0.1'
|
||||
}
|
||||
|
||||
const SessionManagement = () => {
|
||||
const { data: tknResponse } = useQuery(GET_SESSIONS)
|
||||
const { data: tknResponse, loading: sessionsLoading } = useQuery(GET_SESSIONS)
|
||||
|
||||
const [deleteSession] = useMutation(DELETE_SESSION, {
|
||||
refetchQueries: () => ['sessions']
|
||||
})
|
||||
|
||||
const { data: configResponse, loading: configLoading } = useQuery(GET_DATA)
|
||||
const timezone = R.path(['config', 'locale_timezone'], configResponse)
|
||||
|
||||
const loading = sessionsLoading && configLoading
|
||||
|
||||
const elements = [
|
||||
{
|
||||
header: 'Login',
|
||||
|
|
@ -73,9 +84,11 @@ const SessionManagement = () => {
|
|||
textAlign: 'right',
|
||||
size: 'sm',
|
||||
view: s =>
|
||||
`${moment.utc(s.expire).format('YYYY-MM-DD')} ${moment
|
||||
.utc(s.expire)
|
||||
.format('HH:mm:ss')}`
|
||||
`${formatDate(s.expire, timezone, 'yyyy-MM-dd')} ${formatDate(
|
||||
s.expire,
|
||||
timezone,
|
||||
'HH:mm:ss'
|
||||
)}`
|
||||
},
|
||||
{
|
||||
header: '',
|
||||
|
|
@ -94,10 +107,15 @@ const SessionManagement = () => {
|
|||
]
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitleSection title="Session Management" />
|
||||
<DataTable elements={elements} data={R.path(['sessions'])(tknResponse)} />
|
||||
</>
|
||||
!loading && (
|
||||
<>
|
||||
<TitleSection title="Session Management" />
|
||||
<DataTable
|
||||
elements={elements}
|
||||
data={R.path(['sessions'])(tknResponse)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
import { useLazyQuery, useMutation } from '@apollo/react-hooks'
|
||||
import { makeStyles, Box } from '@material-ui/core'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import { add, differenceInYears, format, sub } from 'date-fns/fp'
|
||||
import FileSaver from 'file-saver'
|
||||
import gql from 'graphql-tag'
|
||||
import JSZip from 'jszip'
|
||||
import { utils as coinUtils } from 'lamassu-coins'
|
||||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import React, { memo, useState } from 'react'
|
||||
|
||||
|
|
@ -120,20 +120,17 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
name: `${onlyFirstToUpper(
|
||||
tx.customerIdCardData.firstName
|
||||
)} ${onlyFirstToUpper(tx.customerIdCardData.lastName)}`,
|
||||
age: moment().diff(moment(tx.customerIdCardData.dateOfBirth), 'years'),
|
||||
age: differenceInYears(tx.customerIdCardData.dateOfBirth, new Date()),
|
||||
country: tx.customerIdCardData.country,
|
||||
idCardNumber: tx.customerIdCardData.documentNumber,
|
||||
idCardExpirationDate: moment(tx.customerIdCardData.expirationDate).format(
|
||||
'DD-MM-YYYY'
|
||||
idCardExpirationDate: format(
|
||||
'dd-MM-yyyy',
|
||||
tx.customerIdCardData.expirationDate
|
||||
)
|
||||
}
|
||||
|
||||
const from = moment(tx.created)
|
||||
.subtract(MINUTES_OFFSET, 'm')
|
||||
.format()
|
||||
const until = moment(tx.created)
|
||||
.add(MINUTES_OFFSET, 'm')
|
||||
.format()
|
||||
const from = sub({ minutes: MINUTES_OFFSET }, tx.created)
|
||||
const until = add({ minutes: MINUTES_OFFSET }, tx.created)
|
||||
|
||||
const downloadRawLogs = ({ id: txId, deviceId, txClass }, timezone) => {
|
||||
fetchSummary({
|
||||
|
|
|
|||
|
|
@ -218,7 +218,7 @@ const Transactions = () => {
|
|||
{
|
||||
header: 'Date (UTC)',
|
||||
view: it =>
|
||||
timezone && formatDate(it.created, timezone, 'YYYY-MM-DD HH:mm:ss'),
|
||||
timezone && formatDate(it.created, timezone, 'yyyy-MM-dd HH:mm:ss'),
|
||||
textAlign: 'right',
|
||||
size: 'sm',
|
||||
width: 195
|
||||
|
|
|
|||
120
new-lamassu-admin/src/utils/timezone-list.js
Normal file
120
new-lamassu-admin/src/utils/timezone-list.js
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
import { intervalToDuration } from 'date-fns'
|
||||
import { getTimezoneOffset } from 'date-fns-tz'
|
||||
import * as R from 'ramda'
|
||||
|
||||
const timezones = {
|
||||
'Pacific/Midway': 'Midway Island, Samoa',
|
||||
'Pacific/Honolulu': 'Hawaii',
|
||||
'America/Juneau': 'Alaska',
|
||||
'America/Boise': 'Mountain Time',
|
||||
'America/Dawson': 'Dawson, Yukon',
|
||||
'America/Chihuahua': 'Chihuahua, La Paz, Mazatlan',
|
||||
'America/Phoenix': 'Arizona',
|
||||
'America/Chicago': 'Central Time',
|
||||
'America/Regina': 'Saskatchewan',
|
||||
'America/Mexico_City': 'Guadalajara, Mexico City, Monterrey',
|
||||
'America/Belize': 'Central America',
|
||||
'America/Detroit': 'Eastern Time',
|
||||
'America/Bogota': 'Bogota, Lima, Quito',
|
||||
'America/Caracas': 'Caracas, La Paz',
|
||||
'America/Santiago': 'Santiago',
|
||||
'America/St_Johns': 'Newfoundland and Labrador',
|
||||
'America/Sao_Paulo': 'Brasilia',
|
||||
'America/Tijuana': 'Tijuana',
|
||||
'America/Montevideo': 'Montevideo',
|
||||
'America/Argentina/Buenos_Aires': 'Buenos Aires, Georgetown',
|
||||
'America/Godthab': 'Greenland',
|
||||
'America/Los_Angeles': 'Pacific Time',
|
||||
'Atlantic/Azores': 'Azores',
|
||||
'Atlantic/Cape_Verde': 'Cape Verde Islands',
|
||||
GMT: 'UTC',
|
||||
'Europe/London': 'Edinburgh, London',
|
||||
'Europe/Dublin': 'Dublin',
|
||||
'Europe/Lisbon': 'Lisbon',
|
||||
'Africa/Casablanca': 'Casablanca, Monrovia',
|
||||
'Atlantic/Canary': 'Canary Islands',
|
||||
'Europe/Belgrade': 'Belgrade, Bratislava, Budapest, Ljubljana, Prague',
|
||||
'Europe/Sarajevo': 'Sarajevo, Skopje, Warsaw, Zagreb',
|
||||
'Europe/Brussels': 'Brussels, Copenhagen, Madrid, Paris',
|
||||
'Europe/Amsterdam': 'Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna',
|
||||
'Africa/Algiers': 'West Central Africa',
|
||||
'Europe/Bucharest': 'Bucharest',
|
||||
'Africa/Cairo': 'Cairo',
|
||||
'Europe/Helsinki': 'Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius',
|
||||
'Europe/Athens': 'Athens, Istanbul, Minsk',
|
||||
'Asia/Jerusalem': 'Jerusalem',
|
||||
'Africa/Harare': 'Harare, Pretoria',
|
||||
'Europe/Moscow': 'Moscow, St. Petersburg, Volgograd',
|
||||
'Asia/Kuwait': 'Kuwait, Riyadh',
|
||||
'Africa/Nairobi': 'Nairobi',
|
||||
'Asia/Baghdad': 'Baghdad',
|
||||
'Asia/Tehran': 'Tehran',
|
||||
'Asia/Dubai': 'Abu Dhabi, Muscat',
|
||||
'Asia/Baku': 'Baku, Tbilisi, Yerevan',
|
||||
'Asia/Kabul': 'Kabul',
|
||||
'Asia/Yekaterinburg': 'Ekaterinburg',
|
||||
'Asia/Karachi': 'Islamabad, Karachi, Tashkent',
|
||||
'Asia/Kolkata': 'Chennai, Kolkata, Mumbai, New Delhi',
|
||||
'Asia/Kathmandu': 'Kathmandu',
|
||||
'Asia/Dhaka': 'Astana, Dhaka',
|
||||
'Asia/Colombo': 'Sri Jayawardenepura',
|
||||
'Asia/Almaty': 'Almaty, Novosibirsk',
|
||||
'Asia/Rangoon': 'Yangon Rangoon',
|
||||
'Asia/Bangkok': 'Bangkok, Hanoi, Jakarta',
|
||||
'Asia/Krasnoyarsk': 'Krasnoyarsk',
|
||||
'Asia/Shanghai': 'Beijing, Chongqing, Hong Kong SAR, Urumqi',
|
||||
'Asia/Kuala_Lumpur': 'Kuala Lumpur, Singapore',
|
||||
'Asia/Taipei': 'Taipei',
|
||||
'Australia/Perth': 'Perth',
|
||||
'Asia/Irkutsk': 'Irkutsk, Ulaanbaatar',
|
||||
'Asia/Seoul': 'Seoul',
|
||||
'Asia/Tokyo': 'Osaka, Sapporo, Tokyo',
|
||||
'Asia/Yakutsk': 'Yakutsk',
|
||||
'Australia/Darwin': 'Darwin',
|
||||
'Australia/Adelaide': 'Adelaide',
|
||||
'Australia/Sydney': 'Canberra, Melbourne, Sydney',
|
||||
'Australia/Brisbane': 'Brisbane',
|
||||
'Australia/Hobart': 'Hobart',
|
||||
'Asia/Vladivostok': 'Vladivostok',
|
||||
'Pacific/Guam': 'Guam, Port Moresby',
|
||||
'Asia/Magadan': 'Magadan, Solomon Islands, New Caledonia',
|
||||
'Asia/Kamchatka': 'Kamchatka, Marshall Islands',
|
||||
'Pacific/Fiji': 'Fiji Islands',
|
||||
'Pacific/Auckland': 'Auckland, Wellington',
|
||||
'Pacific/Tongatapu': "Nuku'alofa"
|
||||
}
|
||||
|
||||
const buildTzLabels = timezoneList => {
|
||||
const pairs = R.toPairs(timezoneList)
|
||||
return R.reduce(
|
||||
(acc, value) => {
|
||||
const isNegative = getTimezoneOffset(value[0]) < 0
|
||||
const duration = intervalToDuration({
|
||||
start: 0,
|
||||
end: Math.abs(getTimezoneOffset(value[0]))
|
||||
})
|
||||
|
||||
const hours = duration.hours.toLocaleString('en-US', {
|
||||
minimumIntegerDigits: 2,
|
||||
useGrouping: false
|
||||
})
|
||||
const minutes = duration.minutes.toLocaleString('en-US', {
|
||||
minimumIntegerDigits: 2,
|
||||
useGrouping: false
|
||||
})
|
||||
|
||||
const prefix = `(GMT${isNegative ? `-` : `+`}${hours}:${minutes})`
|
||||
|
||||
acc.push({
|
||||
label: `${prefix} - ${value[1]}`,
|
||||
code: value[0]
|
||||
})
|
||||
|
||||
return acc
|
||||
},
|
||||
[],
|
||||
pairs
|
||||
)
|
||||
}
|
||||
|
||||
export default buildTzLabels(timezones)
|
||||
|
|
@ -1,89 +1,25 @@
|
|||
import moment from 'moment'
|
||||
import * as R from 'ramda'
|
||||
import { zonedTimeToUtc, utcToZonedTime } from 'date-fns-tz/fp'
|
||||
import { format } from 'date-fns/fp'
|
||||
|
||||
const getPossibleUTCDSTPairs = timezones =>
|
||||
R.map(
|
||||
it => ({
|
||||
utcOffset: it.utcOffset,
|
||||
dstOffset: it.dstOffset,
|
||||
utcOffsetStr: it.utcOffsetStr,
|
||||
dstOffsetStr: it.dstOffsetStr
|
||||
}),
|
||||
R.uniqBy(
|
||||
it => [it.utcOffset, it.dstOffset, it.utcOffsetStr, it.dstOffsetStr],
|
||||
timezones
|
||||
)
|
||||
)
|
||||
|
||||
const getFormattedTimezones = timezones =>
|
||||
R.sort(
|
||||
R.ascend(R.prop('utcOffset')),
|
||||
R.map(
|
||||
it => ({
|
||||
utcOffset: it.utcOffset,
|
||||
dstOffset: it.dstOffset,
|
||||
utcOffsetStr: it.utcOffsetStr,
|
||||
dstOffsetStr: it.dstOffsetStr,
|
||||
cities: R.map(
|
||||
ite => {
|
||||
const regionCityPair = R.split('/', ite.name)
|
||||
return {
|
||||
region: regionCityPair[0],
|
||||
city: R.replace(/_/g, ' ', regionCityPair[1]),
|
||||
country: ite.country
|
||||
}
|
||||
},
|
||||
R.filter(
|
||||
itx =>
|
||||
R.eqProps('utcOffset', it, itx) &&
|
||||
R.eqProps('dstOffset', it, itx) &&
|
||||
!R.isNil(itx.country) &&
|
||||
!R.includes('Etc', itx.name) &&
|
||||
R.includes('/', itx.name),
|
||||
timezones
|
||||
)
|
||||
)
|
||||
}),
|
||||
getPossibleUTCDSTPairs(timezones)
|
||||
)
|
||||
)
|
||||
|
||||
const getFinalTimezones = timezones => {
|
||||
const formattedTimezones = getFormattedTimezones(timezones)
|
||||
const nonEmptyTimezones = R.filter(
|
||||
it => !R.isEmpty(it.cities),
|
||||
formattedTimezones
|
||||
)
|
||||
const nonDuplicateCities = R.map(
|
||||
it => ({
|
||||
...it,
|
||||
cities: R.uniqBy(R.prop('country'), R.uniqBy(R.prop('city'), it.cities))
|
||||
}),
|
||||
nonEmptyTimezones
|
||||
)
|
||||
return nonDuplicateCities
|
||||
const toUtc = date => {
|
||||
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
return zonedTimeToUtc(browserTimezone, date)
|
||||
}
|
||||
|
||||
const buildLabel = tz => {
|
||||
return `(UTC${tz.utcOffsetStr}) ${R.map(it => it.city, tz.cities).join(', ')}`
|
||||
const toTimezone = (date, timezone) => {
|
||||
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
return utcToZonedTime(timezone, zonedTimeToUtc(browserTimezone, date))
|
||||
}
|
||||
|
||||
const getTzLabels = timezones =>
|
||||
R.map(
|
||||
it => ({ label: buildLabel(it), code: `${it.utcOffset}:${it.dstOffset}` }),
|
||||
getFinalTimezones(timezones)
|
||||
const formatDate = (date, timezone, pattern) => {
|
||||
const browserTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone
|
||||
const newDate = utcToZonedTime(
|
||||
timezone,
|
||||
zonedTimeToUtc(browserTimezone, date)
|
||||
)
|
||||
|
||||
const formatDate = (date, timezoneCode, format) => {
|
||||
const dstOffset = timezoneCode?.split(':')[1] ?? 0
|
||||
return moment
|
||||
.utc(date)
|
||||
.utcOffset(parseInt(dstOffset))
|
||||
.format(format)
|
||||
return format(pattern, newDate)
|
||||
}
|
||||
|
||||
const formatDateNonUtc = (date, format) => {
|
||||
return moment(date).format(format)
|
||||
}
|
||||
const formatDateNonUtc = (date, pattern) => format(pattern, date)
|
||||
|
||||
export { getTzLabels, formatDate, formatDateNonUtc }
|
||||
export { toUtc, toTimezone, formatDate, formatDateNonUtc }
|
||||
|
|
|
|||
12
package-lock.json
generated
12
package-lock.json
generated
|
|
@ -8464,10 +8464,14 @@
|
|||
"integrity": "sha512-YzhyDAwA4TaQIhM5go+vCLmU0UikghC/t9DTQYZR2M/UvZ1MdOhPezSDZcjj9uqQJOMqjLcpWtyW2iNINdlatQ=="
|
||||
},
|
||||
"date-fns": {
|
||||
"version": "2.16.1",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.16.1.tgz",
|
||||
"integrity": "sha512-sAJVKx/FqrLYHAQeN7VpJrPhagZc9R4ImZIWYRFZaaohR3KzmuK88touwsSwSVT8Qcbd4zoDsnGfX4GFB4imyQ==",
|
||||
"dev": true
|
||||
"version": "2.26.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.26.0.tgz",
|
||||
"integrity": "sha512-VQI812dRi3cusdY/fhoBKvc6l2W8BPWU1FNVnFH9Nttjx4AFBRzfSVb/Eyc7jBT6e9sg1XtAGsYpBQ6c/jygbg=="
|
||||
},
|
||||
"date-fns-tz": {
|
||||
"version": "1.1.6",
|
||||
"resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-1.1.6.tgz",
|
||||
"integrity": "sha512-nyy+URfFI3KUY7udEJozcoftju+KduaqkVfwyTIE0traBiVye09QnyWKLZK7drRr5h9B7sPJITmQnS3U6YOdQg=="
|
||||
},
|
||||
"date-time": {
|
||||
"version": "2.1.0",
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@
|
|||
"cookie-parser": "^1.4.3",
|
||||
"cors": "^2.8.5",
|
||||
"dataloader": "^2.0.0",
|
||||
"date-fns": "^2.26.0",
|
||||
"date-fns-tz": "^1.1.6",
|
||||
"ethereumjs-tx": "^1.3.3",
|
||||
"ethereumjs-util": "^5.2.0",
|
||||
"ethereumjs-wallet": "^0.6.3",
|
||||
|
|
@ -52,7 +54,6 @@
|
|||
"mem": "^1.1.0",
|
||||
"migrate": "^1.6.2",
|
||||
"minimist": "^1.2.0",
|
||||
"moment": "^2.17.0",
|
||||
"morgan": "^1.8.2",
|
||||
"nan": "^2.14.0",
|
||||
"nano-markdown": "^1.2.0",
|
||||
|
|
@ -68,8 +69,8 @@
|
|||
"pify": "^3.0.0",
|
||||
"pretty-ms": "^2.1.0",
|
||||
"promise-sequential": "^1.1.1",
|
||||
"request-promise": "^4.2.6",
|
||||
"queue-promise": "^2.2.1",
|
||||
"request-promise": "^4.2.6",
|
||||
"semver": "^7.1.3",
|
||||
"serve-static": "^1.12.4",
|
||||
"socket.io": "^2.0.3",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue