Chore: post-rebase fixes
This commit is contained in:
parent
c0106592eb
commit
ef60b15d82
29 changed files with 224 additions and 470 deletions
|
|
@ -248,12 +248,6 @@ const typeDefs = gql`
|
||||||
rate: Float
|
rate: Float
|
||||||
}
|
}
|
||||||
|
|
||||||
type Rate {
|
|
||||||
code: String
|
|
||||||
name: String
|
|
||||||
rate: Float
|
|
||||||
}
|
|
||||||
|
|
||||||
type Notification {
|
type Notification {
|
||||||
id: ID!
|
id: ID!
|
||||||
type: String
|
type: String
|
||||||
|
|
@ -297,6 +291,7 @@ const typeDefs = gql`
|
||||||
cryptoRates: JSONObject
|
cryptoRates: JSONObject
|
||||||
fiatRates: [Rate]
|
fiatRates: [Rate]
|
||||||
notifications: [Notification]
|
notifications: [Notification]
|
||||||
|
alerts: [Notification]
|
||||||
hasUnreadNotifications: Boolean
|
hasUnreadNotifications: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -396,7 +391,8 @@ const resolvers = {
|
||||||
}),
|
}),
|
||||||
fiatRates: () => forex.getFiatRates(),
|
fiatRates: () => forex.getFiatRates(),
|
||||||
notifications: () => notifierQueries.getNotifications(),
|
notifications: () => notifierQueries.getNotifications(),
|
||||||
hasUnreadNotifications: () => notifierQueries.hasUnreadNotifications()
|
hasUnreadNotifications: () => notifierQueries.hasUnreadNotifications(),
|
||||||
|
alerts: () => notifierQueries.getAlerts()
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
machineAction: (...[, { deviceId, action, cashbox, cassette1, cassette2, newName }]) => machineAction({ deviceId, action, cashbox, cassette1, cassette2, newName }),
|
machineAction: (...[, { deviceId, action, cashbox, cassette1, cassette2, newName }]) => machineAction({ deviceId, action, cashbox, cassette1, cassette2, newName }),
|
||||||
|
|
|
||||||
|
|
@ -356,207 +356,6 @@ const customerComplianceNotify = (customer, deviceId, code, days = null) => {
|
||||||
.catch(console.error)
|
.catch(console.error)
|
||||||
}
|
}
|
||||||
|
|
||||||
const clearOldCryptoNotifications = (balances) => {
|
|
||||||
// get valid crypto notifications from DB
|
|
||||||
// first, for each DB notification, if it doesn't exist in balances then it is old and should not be valid anymore
|
|
||||||
// if it exists in balances, add the index of it in balances to the array of duplicates
|
|
||||||
// return the array of duplicates so that balancesNotify doesn't add them
|
|
||||||
return queries.getAllValidNotifications(CRYPTO_BALANCE).then(res => {
|
|
||||||
const notifications = _.map(it => {
|
|
||||||
return {
|
|
||||||
id: it.id,
|
|
||||||
cryptoCode: it.detail.cryptoCode,
|
|
||||||
code: it.detail.code
|
|
||||||
}
|
|
||||||
}, res)
|
|
||||||
const duplicateIndexes = []
|
|
||||||
const idsToInvalidate = []
|
|
||||||
_.forEach(notification => {
|
|
||||||
const idx = _.findIndex(balance => {
|
|
||||||
return balance.code === notification.code && balance.cryptoCode === notification.cryptoCode
|
|
||||||
}, balances)
|
|
||||||
|
|
||||||
if (idx === -1) {
|
|
||||||
// if notification in DB doesnt exist in balances anymore then it is invalid now
|
|
||||||
idsToInvalidate.push(notification.id)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// if it exists then it is a duplicate, add it to array
|
|
||||||
duplicateIndexes.push(idx)
|
|
||||||
}
|
|
||||||
}, notifications)
|
|
||||||
return (idsToInvalidate.length > 0 ? queries.batchInvalidate(idsToInvalidate) : Promise.resolve()).then(() => duplicateIndexes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const cryptoBalancesNotify = (cryptoWarnings) => {
|
|
||||||
return clearOldCryptoNotifications(cryptoWarnings).then(duplicateIndexes => {
|
|
||||||
return cryptoWarnings.forEach((balance, idx) => {
|
|
||||||
if(duplicateIndexes.includes(idx)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const fiat = utils.formatCurrency(balance.fiatBalance.balance, balance.fiatCode)
|
|
||||||
const message = `${balance.code === 'HIGH_CRYPTO_BALANCE' ? 'High' : 'Low'} balance in ${balance.cryptoCode} [${fiat}]`
|
|
||||||
console.log(`Adding ${balance.code === 'HIGH_CRYPTO_BALANCE' ? 'high' : 'low'} balance notification for ${balance.cryptoCode}`)
|
|
||||||
const detailB = utils.buildDetail({cryptoCode: balance.cryptoCode, code: balance.code})
|
|
||||||
return queries.addNotification(CRYPTO_BALANCE, message, detailB)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearOldFiatNotifications = (balances) => {
|
|
||||||
return queries.getAllValidNotifications(FIAT_BALANCE).then(notifications => {
|
|
||||||
const duplicateIndexes = []
|
|
||||||
const idsToInvalidate = []
|
|
||||||
_.forEach(notification => {
|
|
||||||
const idx = _.findIndex(balance => {
|
|
||||||
return notification.detail.deviceId === balance.deviceId && notification.detail.cassette === balance.cassette
|
|
||||||
}, balances)
|
|
||||||
|
|
||||||
if (idx === -1) {
|
|
||||||
// if notification in DB doesnt exist in balances anymore then it is invalid now
|
|
||||||
idsToInvalidate.push(notification.id)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// if it exists then it is a duplicate, add it to array
|
|
||||||
duplicateIndexes.push(idx)
|
|
||||||
}
|
|
||||||
}, notifications)
|
|
||||||
return (idsToInvalidate.length > 0 ? queries.batchInvalidate(idsToInvalidate) : Promise.resolve()).then(() => duplicateIndexes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const fiatBalancesNotify = (fiatWarnings) => {
|
|
||||||
return clearOldFiatNotifications(fiatWarnings).then(duplicateIndexes => {
|
|
||||||
return fiatWarnings.forEach((balance, idx) => {
|
|
||||||
if(duplicateIndexes.includes(idx)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
console.log(`Adding low cash balance notification for cassette ${balance.cassette} at ${balance.machineName}`)
|
|
||||||
const message = `Cash-out cassette ${balance.cassette} almost empty!`
|
|
||||||
const detailB = utils.buildDetail({deviceId: balance.deviceId, cassette: balance.cassette})
|
|
||||||
return queries.addNotification(FIAT_BALANCE, message, detailB)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const balancesNotify = (balances) => {
|
|
||||||
const cryptoFilter = o => o.code === 'HIGH_CRYPTO_BALANCE' || o.code === 'LOW_CRYPTO_BALANCE'
|
|
||||||
const fiatFilter = o => o.code === 'LOW_CASH_OUT'
|
|
||||||
const cryptoWarnings = _.filter(cryptoFilter, balances)
|
|
||||||
const fiatWarnings = _.filter(fiatFilter, balances)
|
|
||||||
return Promise.all([cryptoBalancesNotify(cryptoWarnings), fiatBalancesNotify(fiatWarnings)]).catch(console.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const clearOldErrorNotifications = (alerts) => {
|
|
||||||
return queries.getAllValidNotifications(ERROR).then(res => {
|
|
||||||
const indexesToInvalidate = []
|
|
||||||
_.forEach(notification => {
|
|
||||||
const idx = _.findIndex(alert => {
|
|
||||||
return alert.code === notification.detail.code && alert.deviceId === notification.detail.deviceId
|
|
||||||
}, alerts)
|
|
||||||
if(idx !== -1) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// if the notification doesn't exist, then it is outdated and is not valid anymore
|
|
||||||
indexesToInvalidate.push(notification.id)
|
|
||||||
}, res)
|
|
||||||
return indexesToInvalidate.length > 0 ? queries.batchInvalidate(indexesToInvalidate) : null
|
|
||||||
}).catch(console.log)
|
|
||||||
}
|
|
||||||
|
|
||||||
const errorAlertsNotify = (alertRec) => {
|
|
||||||
let alerts = []
|
|
||||||
_.keys(alertRec.devices).forEach(function (device) {
|
|
||||||
// embed device ID in each alert object inside the deviceAlerts array
|
|
||||||
alertRec.devices[device].deviceAlerts = _.map(alert => {
|
|
||||||
return {...alert, deviceId: device}
|
|
||||||
}, alertRec.devices[device].deviceAlerts)
|
|
||||||
// concat every array into one
|
|
||||||
alerts = _.concat(alerts, alertRec.devices[device].deviceAlerts)
|
|
||||||
})
|
|
||||||
|
|
||||||
// now that we have all the alerts, we want to add PING and STALE alerts to the DB
|
|
||||||
// if there is a valid alert on the DB that doesn't exist on the new alerts array,
|
|
||||||
// that alert should be considered invalid
|
|
||||||
// after that, for the alerts array, we have to see if there is a valid alert of
|
|
||||||
// the sorts already on the DB
|
|
||||||
return clearOldErrorNotifications(alerts).then(() => {
|
|
||||||
_.forEach(alert => {
|
|
||||||
switch(alert.code) {
|
|
||||||
case PING: {
|
|
||||||
const detailB = utils.buildDetail({code: PING, age: alert.age ? alert.age : -1, deviceId: alert.deviceId})
|
|
||||||
return queries.getValidNotifications(ERROR, _.omit(['age'], detailB)).then(res => {
|
|
||||||
if(res.length > 0) {
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
console.log("Adding PING alert on database for " + alert.machineName)
|
|
||||||
const message = `Machine down`
|
|
||||||
return queries.addNotification(ERROR, message, detailB)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
case STALE: {
|
|
||||||
const detailB = utils.buildDetail({code: STALE, deviceId: alert.deviceId})
|
|
||||||
return queries.getValidNotifications(ERROR, detailB).then(res => {
|
|
||||||
if(res.length > 0) {
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
console.log("Adding STALE alert on database for " + alert.machineName)
|
|
||||||
const message = `Machine is stuck on ${alert.state} screen`
|
|
||||||
return queries.addNotification(ERROR, message, detailB)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}, alerts)
|
|
||||||
}).catch(console.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
const blacklistNotify = (tx, isAddressReuse) => {
|
|
||||||
let message = ''
|
|
||||||
let detailB = {}
|
|
||||||
if(isAddressReuse) {
|
|
||||||
detail = `${tx.cryptoCode}_REUSED_${tx.toAddress}`
|
|
||||||
detailB = utils.buildDetail({cryptoCode: tx.cryptoCode, code: 'REUSED', cryptoAddress: tx.toAddress})
|
|
||||||
message = `Blocked reused address: ${tx.cryptoCode} ${tx.toAddress.substr(0,10)}...`
|
|
||||||
} else {
|
|
||||||
detail = `${tx.cryptoCode}_BLOCKED_${tx.toAddress}`
|
|
||||||
detailB = utils.buildDetail({cryptoCode: tx.cryptoCode, code: 'BLOCKED', cryptoAddress: tx.toAddress})
|
|
||||||
message = `Blocked blacklisted address: ${tx.cryptoCode} ${tx.toAddress.substr(0,10)}...`
|
|
||||||
}
|
|
||||||
return queries.addNotification(COMPLIANCE, message, detailB)
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearBlacklistNotification = (cryptoCode, cryptoAddress) => {
|
|
||||||
return queries.clearBlacklistNotification(cryptoCode, cryptoAddress).catch(console.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
const clearOldCustomerSuspendedNotifications = (customerId, deviceId) => {
|
|
||||||
const detailB = utils.buildDetail({code: 'SUSPENDED', customerId, deviceId})
|
|
||||||
return queries.invalidateNotification(detailB, 'compliance')
|
|
||||||
}
|
|
||||||
|
|
||||||
const customerComplianceNotify = (customer, deviceId, code, days = null) => {
|
|
||||||
// code for now can be "BLOCKED", "SUSPENDED"
|
|
||||||
const detailB = utils.buildDetail({customerId: customer.id, code, deviceId})
|
|
||||||
const date = new Date()
|
|
||||||
if (days) {
|
|
||||||
date.setDate(date.getDate() + days)
|
|
||||||
}
|
|
||||||
const message = code === "SUSPENDED" ? `Customer suspended until ${date.toLocaleString()}` : `Customer blocked`
|
|
||||||
|
|
||||||
return clearOldCustomerSuspendedNotifications(customer.id, deviceId).then(() => {
|
|
||||||
return queries.getValidNotifications(COMPLIANCE, detailB)
|
|
||||||
}).then(res => {
|
|
||||||
if (res.length > 0) {
|
|
||||||
return Promise.resolve()
|
|
||||||
}
|
|
||||||
return queries.addNotification(COMPLIANCE, message, detailB)
|
|
||||||
}).catch(console.error)
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
transactionNotify,
|
transactionNotify,
|
||||||
checkNotification,
|
checkNotification,
|
||||||
|
|
|
||||||
|
|
@ -46,27 +46,27 @@ const getValidNotifications = (type, detail) => {
|
||||||
return db.any(sql, [type, detail])
|
return db.any(sql, [type, detail])
|
||||||
}
|
}
|
||||||
|
|
||||||
const getNotificationsGql = () => {
|
const getNotifications = () => {
|
||||||
const sql = `SELECT * FROM notifications ORDER BY created DESC`
|
const sql = `SELECT * FROM notifications ORDER BY created DESC`
|
||||||
return db.any(sql)
|
return db.any(sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
const markAsReadGql = (id) => {
|
const markAsRead = (id) => {
|
||||||
const sql = `UPDATE notifications SET read = 't' WHERE id = $1`
|
const sql = `UPDATE notifications SET read = 't' WHERE id = $1`
|
||||||
return db.none(sql, [id])
|
return db.none(sql, [id])
|
||||||
}
|
}
|
||||||
|
|
||||||
const markAllAsReadGql = () => {
|
const markAllAsRead = () => {
|
||||||
const sql = `UPDATE notifications SET read = 't'`
|
const sql = `UPDATE notifications SET read = 't'`
|
||||||
return db.none(sql)
|
return db.none(sql)
|
||||||
}
|
}
|
||||||
|
|
||||||
const hasUnreadNotificationsGql = () => {
|
const hasUnreadNotifications = () => {
|
||||||
const sql = `SELECT EXISTS (SELECT 1 FROM notifications WHERE read = 'f' LIMIT 1)`
|
const sql = `SELECT EXISTS (SELECT 1 FROM notifications WHERE read = 'f' LIMIT 1)`
|
||||||
return db.oneOrNone(sql).then(res => res.exists)
|
return db.oneOrNone(sql).then(res => res.exists)
|
||||||
}
|
}
|
||||||
|
|
||||||
const getAlertsGql = () => {
|
const getAlerts = () => {
|
||||||
const types = ['fiatBalance', 'cryptoBalance', 'error']
|
const types = ['fiatBalance', 'cryptoBalance', 'error']
|
||||||
const sql = `SELECT * FROM notifications WHERE valid = 't' AND type IN ($1:list) ORDER BY created DESC`
|
const sql = `SELECT * FROM notifications WHERE valid = 't' AND type IN ($1:list) ORDER BY created DESC`
|
||||||
return db.any(sql, [types])
|
return db.any(sql, [types])
|
||||||
|
|
@ -80,9 +80,9 @@ module.exports = {
|
||||||
batchInvalidate,
|
batchInvalidate,
|
||||||
clearBlacklistNotification,
|
clearBlacklistNotification,
|
||||||
getValidNotifications,
|
getValidNotifications,
|
||||||
getNotificationsGql,
|
getNotifications,
|
||||||
markAsReadGql,
|
markAsRead,
|
||||||
markAllAsReadGql,
|
markAllAsRead,
|
||||||
hasUnreadNotificationsGql,
|
hasUnreadNotifications,
|
||||||
getAlertsGql
|
getAlerts
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,11 +29,6 @@ function printSmsAlerts (alertRec, config) {
|
||||||
_.map('cryptoCode', entry[1]),
|
_.map('cryptoCode', entry[1]),
|
||||||
)
|
)
|
||||||
|
|
||||||
const cryptoCodes = _.filter(
|
|
||||||
_.negate(_.isEmpty),
|
|
||||||
_.map('cryptoCode', entry[1])
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
codeDisplay: utils.codeDisplay(code),
|
codeDisplay: utils.codeDisplay(code),
|
||||||
machineNames,
|
machineNames,
|
||||||
|
|
|
||||||
|
|
@ -25,8 +25,6 @@ const promoCodes = require('./promo-codes')
|
||||||
|
|
||||||
const notifier = require('./notifier')
|
const notifier = require('./notifier')
|
||||||
|
|
||||||
const notifier = require('./notifier/index')
|
|
||||||
|
|
||||||
const mapValuesWithKey = _.mapValues.convert({
|
const mapValuesWithKey = _.mapValues.convert({
|
||||||
cap: false
|
cap: false
|
||||||
})
|
})
|
||||||
|
|
@ -164,41 +162,30 @@ function plugins (settings, deviceId) {
|
||||||
? argv.cassettes.split(',')
|
? argv.cassettes.split(',')
|
||||||
: rec.counts
|
: rec.counts
|
||||||
|
|
||||||
return Promise.all([
|
const cassettes = [
|
||||||
dbm.cassetteCounts(deviceId),
|
{
|
||||||
cashOutHelper.redeemableTxs(deviceId, excludeTxId)
|
denomination: parseInt(denominations[0], 10),
|
||||||
]).then(([rec, _redeemableTxs]) => {
|
count: parseInt(counts[0], 10)
|
||||||
const redeemableTxs = _.reject(
|
},
|
||||||
_.matchesProperty('id', excludeTxId),
|
{
|
||||||
_redeemableTxs
|
denomination: parseInt(denominations[1], 10),
|
||||||
)
|
count: parseInt(counts[1], 10)
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
const counts = argv.cassettes ? argv.cassettes.split(',') : rec.counts
|
try {
|
||||||
|
return {
|
||||||
const cassettes = [
|
cassettes: computeAvailableCassettes(cassettes, redeemableTxs),
|
||||||
{
|
virtualCassettes
|
||||||
denomination: parseInt(denominations[0], 10),
|
}
|
||||||
count: parseInt(counts[0], 10)
|
} catch (err) {
|
||||||
},
|
logger.error(err)
|
||||||
{
|
return {
|
||||||
denomination: parseInt(denominations[1], 10),
|
cassettes,
|
||||||
count: parseInt(counts[1], 10)
|
virtualCassettes
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
})
|
||||||
|
|
||||||
try {
|
|
||||||
return {
|
|
||||||
cassettes: computeAvailableCassettes(cassettes, redeemableTxs),
|
|
||||||
virtualCassettes
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
logger.error(err)
|
|
||||||
return {
|
|
||||||
cassettes,
|
|
||||||
virtualCassettes
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function fetchCurrentConfigVersion () {
|
function fetchCurrentConfigVersion () {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { makeStyles } from '@material-ui/core/styles'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
import ActionButton from 'src/components/buttons/ActionButton'
|
import ActionButton from 'src/components/buttons/ActionButton'
|
||||||
import { H5 } from 'src/components/typography'
|
import { H5 } from 'src/components/typography'
|
||||||
import { ReactComponent as NotificationIconZodiac } from 'src/styling/icons/menu/notification-zodiac.svg'
|
import { ReactComponent as NotificationIconZodiac } from 'src/styling/icons/menu/notification-zodiac.svg'
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import { makeStyles } from '@material-ui/core/styles'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import prettyMs from 'pretty-ms'
|
import prettyMs from 'pretty-ms'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { Label1, Label2, TL2 } from 'src/components/typography'
|
import { Label1, Label2, TL2 } from 'src/components/typography'
|
||||||
import { ReactComponent as Wrench } from 'src/styling/icons/action/wrench/zodiac.svg'
|
import { ReactComponent as Wrench } from 'src/styling/icons/action/wrench/zodiac.svg'
|
||||||
import { ReactComponent as Transaction } from 'src/styling/icons/arrow/transaction.svg'
|
import { ReactComponent as Transaction } from 'src/styling/icons/arrow/transaction.svg'
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import classnames from 'classnames'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import React, { memo, useState } from 'react'
|
import React, { memo, useState } from 'react'
|
||||||
import { NavLink, useHistory } from 'react-router-dom'
|
import { NavLink, useHistory } from 'react-router-dom'
|
||||||
|
|
||||||
import NotificationCenter from 'src/components/NotificationCenter'
|
import NotificationCenter from 'src/components/NotificationCenter'
|
||||||
import ActionButton from 'src/components/buttons/ActionButton'
|
import ActionButton from 'src/components/buttons/ActionButton'
|
||||||
import { H4 } from 'src/components/typography'
|
import { H4 } from 'src/components/typography'
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,9 @@ import Grid from '@material-ui/core/Grid'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState, useEffect } from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
import { cardState as cardState_ } from 'src/components/CollapsibleCard'
|
||||||
import { Label1, H4 } from 'src/components/typography'
|
import { Label1, H4 } from 'src/components/typography'
|
||||||
|
|
||||||
import styles from '../Dashboard.styles'
|
import styles from '../Dashboard.styles'
|
||||||
|
|
@ -33,98 +35,58 @@ const GET_ALERTS = gql`
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const Alerts = ({ cardState, setRightSideState }) => {
|
const Alerts = ({ onReset, onExpand, size }) => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const [showAllItems, setShowAllItems] = useState(false)
|
const showAllItems = size === cardState_.EXPANDED
|
||||||
const { data } = useQuery(GET_ALERTS)
|
const { data } = useQuery(GET_ALERTS)
|
||||||
|
|
||||||
const alerts = R.path(['alerts'])(data) ?? []
|
const alerts = R.path(['alerts'])(data) ?? []
|
||||||
const machines = R.compose(
|
const machines = R.compose(
|
||||||
R.map(R.prop('name')),
|
R.map(R.prop('name')),
|
||||||
R.indexBy(R.prop('deviceId'))
|
R.indexBy(R.prop('deviceId'))
|
||||||
)(data?.machines ?? [])
|
)(data?.machines ?? [])
|
||||||
|
const alertsLength = alerts.length
|
||||||
const showExpandButton = alerts.length > NUM_TO_RENDER && !showAllItems
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (cardState.cardSize === 'small' || cardState.cardSize === 'default') {
|
|
||||||
setShowAllItems(false)
|
|
||||||
}
|
|
||||||
}, [cardState.cardSize])
|
|
||||||
|
|
||||||
const reset = () => {
|
|
||||||
setRightSideState({
|
|
||||||
systemStatus: { cardSize: 'default', buttonName: 'Show less' },
|
|
||||||
alerts: { cardSize: 'default', buttonName: 'Show less' }
|
|
||||||
})
|
|
||||||
setShowAllItems(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
const showAllClick = () => {
|
|
||||||
setShowAllItems(true)
|
|
||||||
setRightSideState({
|
|
||||||
systemStatus: { cardSize: 'small', buttonName: 'Show machines' },
|
|
||||||
alerts: { cardSize: 'big', buttonName: 'Show less' }
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<div
|
<div className={classes.container}>
|
||||||
style={{
|
<H4 className={classes.h4}>{`Alerts (${alertsLength})`}</H4>
|
||||||
display: 'flex',
|
{showAllItems && (
|
||||||
justifyContent: 'space-between'
|
<Label1 className={classes.upperButtonLabel}>
|
||||||
}}>
|
<Button
|
||||||
<H4 className={classes.h4}>{`Alerts ${
|
onClick={() => {
|
||||||
data ? `(${alerts.length})` : 0
|
console.log('aaaa')
|
||||||
}`}</H4>
|
onReset()
|
||||||
{(showAllItems || cardState.cardSize === 'small') && (
|
}}
|
||||||
<>
|
size="small"
|
||||||
<Label1
|
disableRipple
|
||||||
style={{
|
disableFocusRipple
|
||||||
textAlign: 'center',
|
className={classes.button}>
|
||||||
marginBottom: 0,
|
{'Show less'}
|
||||||
marginTop: 0
|
</Button>
|
||||||
}}>
|
</Label1>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Grid container spacing={1}>
|
||||||
|
<Grid item xs={12} className={classes.alertsTableMargin}>
|
||||||
|
<AlertsTable
|
||||||
|
numToRender={showAllItems ? alerts.length : NUM_TO_RENDER}
|
||||||
|
alerts={alerts}
|
||||||
|
machines={machines}
|
||||||
|
/>
|
||||||
|
{!showAllItems && alertsLength > NUM_TO_RENDER && (
|
||||||
|
<Label1 className={classes.centerLabel}>
|
||||||
<Button
|
<Button
|
||||||
onClick={reset}
|
onClick={() => onExpand('alerts')}
|
||||||
size="small"
|
size="small"
|
||||||
disableRipple
|
disableRipple
|
||||||
disableFocusRipple
|
disableFocusRipple
|
||||||
className={classes.button}>
|
className={classes.button}>
|
||||||
{cardState.buttonName}
|
{`Show all (${alerts.length})`}
|
||||||
</Button>
|
</Button>
|
||||||
</Label1>
|
</Label1>
|
||||||
</>
|
)}
|
||||||
)}
|
</Grid>
|
||||||
</div>
|
</Grid>
|
||||||
{cardState.cardSize !== 'small' && (
|
|
||||||
<>
|
|
||||||
<Grid container spacing={1}>
|
|
||||||
<Grid item xs={12}>
|
|
||||||
<AlertsTable
|
|
||||||
numToRender={showAllItems ? alerts.length : NUM_TO_RENDER}
|
|
||||||
alerts={alerts}
|
|
||||||
machines={machines}
|
|
||||||
/>
|
|
||||||
{showExpandButton && (
|
|
||||||
<>
|
|
||||||
<Label1 style={{ textAlign: 'center', marginBottom: 0 }}>
|
|
||||||
<Button
|
|
||||||
onClick={showAllClick}
|
|
||||||
size="small"
|
|
||||||
disableRipple
|
|
||||||
disableFocusRipple
|
|
||||||
className={classes.button}>
|
|
||||||
{`Show all (${alerts.length})`}
|
|
||||||
</Button>
|
|
||||||
</Label1>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,27 +45,10 @@ const styles = {
|
||||||
statusHeader: {
|
statusHeader: {
|
||||||
marginLeft: 2
|
marginLeft: 2
|
||||||
},
|
},
|
||||||
/* table: {
|
|
||||||
maxHeight: 440,
|
|
||||||
'&::-webkit-scrollbar': {
|
|
||||||
width: 7
|
|
||||||
},
|
|
||||||
'&::-webkit-scrollbar-thumb': {
|
|
||||||
backgroundColor: offColor,
|
|
||||||
borderRadius: 5
|
|
||||||
}
|
|
||||||
}, */
|
|
||||||
table: {
|
table: {
|
||||||
paddingTop: spacer * 4,
|
marginTop: spacer * 4,
|
||||||
maxHeight: 465,
|
maxHeight: 465,
|
||||||
overflow: 'auto',
|
overflow: 'auto'
|
||||||
'&::-webkit-scrollbar': {
|
|
||||||
width: 7
|
|
||||||
},
|
|
||||||
'&::-webkit-scrollbar-thumb': {
|
|
||||||
backgroundColor: offColor,
|
|
||||||
borderRadius: 5
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
tableBody: {
|
tableBody: {
|
||||||
overflow: 'auto'
|
overflow: 'auto'
|
||||||
|
|
@ -78,11 +61,6 @@ const styles = {
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
marginTop: 0
|
marginTop: 0
|
||||||
},
|
},
|
||||||
root: {
|
|
||||||
'&:nth-of-type(odd)': {
|
|
||||||
backgroundColor: backgroundColor
|
|
||||||
}
|
|
||||||
},
|
|
||||||
listItemText: {
|
listItemText: {
|
||||||
margin: '8px 0 8px 0'
|
margin: '8px 0 8px 0'
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,10 @@
|
||||||
import { withStyles, makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
import List from '@material-ui/core/List'
|
import List from '@material-ui/core/List'
|
||||||
import ListItem from '@material-ui/core/ListItem'
|
import ListItem from '@material-ui/core/ListItem'
|
||||||
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
||||||
import { P } from 'src/components/typography/index'
|
import { P } from 'src/components/typography/index'
|
||||||
import { ReactComponent as Wrench } from 'src/styling/icons/action/wrench/zodiac.svg'
|
import { ReactComponent as Wrench } from 'src/styling/icons/action/wrench/zodiac.svg'
|
||||||
import { ReactComponent as LinkIcon } from 'src/styling/icons/button/link/zodiac.svg'
|
import { ReactComponent as LinkIcon } from 'src/styling/icons/button/link/zodiac.svg'
|
||||||
|
|
@ -12,12 +14,6 @@ import { ReactComponent as WarningIcon } from 'src/styling/icons/warning-icon/to
|
||||||
import styles from './Alerts.styles'
|
import styles from './Alerts.styles'
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const StyledListItem = withStyles(() => ({
|
|
||||||
root: {
|
|
||||||
...styles.root
|
|
||||||
}
|
|
||||||
}))(ListItem)
|
|
||||||
|
|
||||||
const icons = {
|
const icons = {
|
||||||
error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />,
|
error: <WarningIcon style={{ height: 20, width: 20, marginRight: 12 }} />,
|
||||||
fiatBalance: (
|
fiatBalance: (
|
||||||
|
|
@ -34,25 +30,23 @@ const links = {
|
||||||
const AlertsTable = ({ numToRender, alerts, machines }) => {
|
const AlertsTable = ({ numToRender, alerts, machines }) => {
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
const alertsToRender = R.slice(0, numToRender, alerts)
|
||||||
return (
|
return (
|
||||||
<List dense className={classes.table}>
|
<List dense className={classes.table}>
|
||||||
{alerts.map((alert, idx) => {
|
{alertsToRender.map((alert, idx) => {
|
||||||
if (idx < numToRender) {
|
return (
|
||||||
return (
|
<ListItem key={idx}>
|
||||||
<StyledListItem key={idx}>
|
{icons[alert.type] || (
|
||||||
{icons[alert.type] || (
|
<Wrench style={{ height: 23, width: 23, marginRight: 8 }} />
|
||||||
<Wrench style={{ height: 23, width: 23, marginRight: 8 }} />
|
)}
|
||||||
)}
|
<P className={classes.listItemText}>{`${alert.message}${alert.detail
|
||||||
<P className={classes.listItemText}>{`${alert.message}${alert
|
.deviceId && ' - ' + machines[alert.detail.deviceId]}`}</P>
|
||||||
.detail.deviceId &&
|
<LinkIcon
|
||||||
' - ' + machines[alert.detail.deviceId]}`}</P>
|
className={classes.linkIcon}
|
||||||
<LinkIcon
|
onClick={() => history.push(links[alert.type] || '/dashboard')}
|
||||||
className={classes.linkIcon}
|
/>
|
||||||
onClick={() => history.push(links[alert.type] || '/dashboard')}
|
</ListItem>
|
||||||
/>
|
)
|
||||||
</StyledListItem>
|
|
||||||
)
|
|
||||||
} else return null
|
|
||||||
})}
|
})}
|
||||||
</List>
|
</List>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import Grid from '@material-ui/core/Grid'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import TitleSection from 'src/components/layout/TitleSection'
|
import TitleSection from 'src/components/layout/TitleSection'
|
||||||
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.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 { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
|
||||||
|
|
|
||||||
|
|
@ -52,11 +52,17 @@ const styles = {
|
||||||
upperButtonLabel: {
|
upperButtonLabel: {
|
||||||
textAlign: 'center',
|
textAlign: 'center',
|
||||||
marginBottom: 0,
|
marginBottom: 0,
|
||||||
marginTop: 16,
|
marginTop: 0,
|
||||||
marginLeft: spacer
|
marginLeft: spacer
|
||||||
},
|
},
|
||||||
alertsCard: {
|
alertsCard: {
|
||||||
marginBottom: 16
|
marginBottom: 16
|
||||||
|
},
|
||||||
|
h4: {
|
||||||
|
marginTop: 0
|
||||||
|
},
|
||||||
|
alertsTableMargin: {
|
||||||
|
marginTop: -30
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import classnames from 'classnames'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
import { Label2 } from 'src/components/typography'
|
import { Label2 } from 'src/components/typography'
|
||||||
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.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 { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ import Button from '@material-ui/core/Button'
|
||||||
import Grid from '@material-ui/core/Grid'
|
import Grid from '@material-ui/core/Grid'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard'
|
import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard'
|
||||||
import { H4, Label1 } from 'src/components/typography'
|
import { H4, Label1 } from 'src/components/typography'
|
||||||
|
|
||||||
// import Alerts from './Alerts'
|
import Alerts from './Alerts'
|
||||||
import styles from './Dashboard.styles'
|
import styles from './Dashboard.styles'
|
||||||
import SystemStatus from './SystemStatus'
|
import SystemStatus from './SystemStatus'
|
||||||
|
|
||||||
|
|
@ -33,35 +34,35 @@ const ShrunkCard = ({ title, buttonName, onUnshrink }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const RightSide = () => {
|
const RightSide = () => {
|
||||||
// const classes = useStyles()
|
const classes = useStyles()
|
||||||
const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT)
|
const [systemStatusSize, setSystemStatusSize] = useState(cardState.DEFAULT)
|
||||||
// const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT)
|
const [alertsSize, setAlertsSize] = useState(cardState.DEFAULT)
|
||||||
|
|
||||||
const onReset = () => {
|
const onReset = () => {
|
||||||
// setAlertsSize(cardState.DEFAULT)
|
setAlertsSize(cardState.DEFAULT)
|
||||||
setSystemStatusSize(cardState.DEFAULT)
|
setSystemStatusSize(cardState.DEFAULT)
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<Grid item xs={6}>
|
<Grid item xs={6}>
|
||||||
{/* <CollapsibleCard
|
<CollapsibleCard
|
||||||
className={classes.alertsCard}
|
className={classes.alertsCard}
|
||||||
state={alertsSize}
|
state={alertsSize}
|
||||||
shrunkComponent={
|
shrunkComponent={
|
||||||
<ShrunkCard
|
<ShrunkCard
|
||||||
title={'Alerts'}
|
title={'Alerts'}
|
||||||
buttonName={'Show alerts'}
|
buttonName={'Show alerts'}
|
||||||
onUnshrink={onReset}
|
onUnshrink={onReset}
|
||||||
/>
|
|
||||||
}>
|
|
||||||
<Alerts
|
|
||||||
onExpand={() => {
|
|
||||||
setAlertsSize(cardState.EXPANDED)
|
|
||||||
setSystemStatusSize(cardState.SHRUNK)
|
|
||||||
}}
|
|
||||||
onReset={onReset}
|
|
||||||
size={alertsSize}
|
|
||||||
/>
|
/>
|
||||||
</CollapsibleCard> */}
|
}>
|
||||||
|
<Alerts
|
||||||
|
onExpand={() => {
|
||||||
|
setAlertsSize(cardState.EXPANDED)
|
||||||
|
setSystemStatusSize(cardState.SHRUNK)
|
||||||
|
}}
|
||||||
|
onReset={onReset}
|
||||||
|
size={alertsSize}
|
||||||
|
/>
|
||||||
|
</CollapsibleCard>
|
||||||
<CollapsibleCard
|
<CollapsibleCard
|
||||||
state={systemStatusSize}
|
state={systemStatusSize}
|
||||||
shrunkComponent={
|
shrunkComponent={
|
||||||
|
|
@ -74,7 +75,7 @@ const RightSide = () => {
|
||||||
<SystemStatus
|
<SystemStatus
|
||||||
onExpand={() => {
|
onExpand={() => {
|
||||||
setSystemStatusSize(cardState.EXPANDED)
|
setSystemStatusSize(cardState.EXPANDED)
|
||||||
// setAlertsSize(cardState.SHRUNK)
|
setAlertsSize(cardState.SHRUNK)
|
||||||
}}
|
}}
|
||||||
onReset={onReset}
|
onReset={onReset}
|
||||||
size={systemStatusSize}
|
size={systemStatusSize}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { ReactComponent as CashIn } from 'src/styling/icons/direction/cash-in.svg'
|
|
||||||
import { ReactComponent as CashOut } from 'src/styling/icons/direction/cash-out.svg'
|
import { Label1 } from 'src/components/typography/index'
|
||||||
import { fontSize3, fontSecondary, fontColor } from 'src/styling/variables'
|
import { java, neon, white } from 'src/styling/variables'
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
wrapper: {
|
wrapper: {
|
||||||
|
|
@ -20,47 +20,52 @@ const styles = {
|
||||||
whiteSpace: 'pre'
|
whiteSpace: 'pre'
|
||||||
},
|
},
|
||||||
label: {
|
label: {
|
||||||
fontSize: fontSize3,
|
color: white
|
||||||
fontFamily: fontSecondary,
|
|
||||||
fontWeight: 700,
|
|
||||||
color: fontColor
|
|
||||||
},
|
},
|
||||||
cashIn: ({ value }) => ({
|
inColor: {
|
||||||
width: `${value}%`,
|
backgroundColor: java
|
||||||
marginRight: 4
|
},
|
||||||
}),
|
outColor: {
|
||||||
cashOut: ({ value }) => ({
|
backgroundColor: neon
|
||||||
width: `${100 - value}%`
|
},
|
||||||
})
|
other: {
|
||||||
|
minWidth: '6px',
|
||||||
|
borderRadius: 2
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const PercentageChart = ({ cashIn, cashOut }) => {
|
const PercentageChart = ({ cashIn, cashOut }) => {
|
||||||
|
const classes = useStyles()
|
||||||
const value = cashIn || cashOut !== 0 ? cashIn : 50
|
const value = cashIn || cashOut !== 0 ? cashIn : 50
|
||||||
const classes = useStyles({ value })
|
|
||||||
|
|
||||||
const buildPercentageView = (value, direction) => {
|
const buildPercentageView = value => {
|
||||||
const Operation = direction === 'cashIn' ? CashIn : CashOut
|
if (value > 15) {
|
||||||
if (value > 25) {
|
return <Label1 className={classes.label}>{` ${value}%`}</Label1>
|
||||||
return (
|
|
||||||
<>
|
|
||||||
<Operation />
|
|
||||||
{value > 25 && <span className={classes.label}>{` ${value}%`}</span>}
|
|
||||||
</>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
if (value >= 10) {
|
|
||||||
return <Operation />
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
<div className={classnames(classes.percentageBox, classes.cashIn)}>
|
<div
|
||||||
|
className={classnames(
|
||||||
|
classes.percentageBox,
|
||||||
|
classes.inColor,
|
||||||
|
// if value between [1, 4], percentage box should not go below 6 px and border radius is 2px
|
||||||
|
// if value is 0 or 100, then width will be allowed to be 0px in one of the boxes, making it disappear
|
||||||
|
value < 5 && value > 0 ? classes.other : null
|
||||||
|
)}
|
||||||
|
style={{ width: `${value}%`, marginRight: 4 }}>
|
||||||
{buildPercentageView(value, 'cashIn')}
|
{buildPercentageView(value, 'cashIn')}
|
||||||
</div>
|
</div>
|
||||||
<div className={classnames(classes.percentageBox, classes.cashOut)}>
|
<div
|
||||||
|
className={classnames(
|
||||||
|
classes.percentageBox,
|
||||||
|
classes.outColor,
|
||||||
|
100 - value < 5 && 100 - value > 0 ? classes.other : null
|
||||||
|
)}
|
||||||
|
style={{ width: `${100 - value}%` }}>
|
||||||
{buildPercentageView(100 - value, 'cashOut')}
|
{buildPercentageView(100 - value, 'cashOut')}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import * as d3 from 'd3'
|
import * as d3 from 'd3'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useEffect, useRef, useCallback } from 'react'
|
import React, { useEffect, useRef, useCallback } from 'react'
|
||||||
|
|
||||||
import { backgroundColor, zircon, primaryColor } from 'src/styling/variables'
|
import { backgroundColor, zircon, primaryColor } from 'src/styling/variables'
|
||||||
|
|
||||||
const transactionProfit = tx => {
|
const transactionProfit = tx => {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import * as d3 from 'd3'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useEffect, useRef, useCallback } from 'react'
|
import React, { useEffect, useRef, useCallback } from 'react'
|
||||||
|
|
||||||
import { backgroundColor, java, neon } from 'src/styling/variables'
|
import { backgroundColor, java, neon } from 'src/styling/variables'
|
||||||
|
|
||||||
const RefScatterplot = ({ data: realData, timeFrame }) => {
|
const RefScatterplot = ({ data: realData, timeFrame }) => {
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { makeStyles } from '@material-ui/core/styles'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
|
|
||||||
import { H4 } from 'src/components/typography'
|
import { H4 } from 'src/components/typography'
|
||||||
|
|
||||||
import styles from './SystemPerformance.styles'
|
import styles from './SystemPerformance.styles'
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@ import { useQuery } from '@apollo/react-hooks'
|
||||||
import Grid from '@material-ui/core/Grid'
|
import Grid from '@material-ui/core/Grid'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import BigNumber from 'bignumber.js'
|
import BigNumber from 'bignumber.js'
|
||||||
|
import classnames from 'classnames'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState } from 'react'
|
import React, { useState } from 'react'
|
||||||
import { Label2 } from 'src/components/typography/index'
|
|
||||||
|
import { Label1, Label2 } from 'src/components/typography/index'
|
||||||
import { ReactComponent as TriangleDown } from 'src/styling/icons/arrow/triangle_down.svg'
|
import { ReactComponent as TriangleDown } from 'src/styling/icons/arrow/triangle_down.svg'
|
||||||
import { ReactComponent as TriangleUp } from 'src/styling/icons/arrow/triangle_up.svg'
|
import { ReactComponent as TriangleUp } from 'src/styling/icons/arrow/triangle_up.svg'
|
||||||
import { fromNamespace } from 'src/utils/config'
|
import { fromNamespace } from 'src/utils/config'
|
||||||
|
|
@ -206,14 +208,29 @@ const SystemPerformance = () => {
|
||||||
<LineChart timeFrame={selectedRange} data={transactionsToShow} />
|
<LineChart timeFrame={selectedRange} data={transactionsToShow} />
|
||||||
</Grid>
|
</Grid>
|
||||||
<Grid item xs={4}>
|
<Grid item xs={4}>
|
||||||
<Label2>Direction</Label2>
|
|
||||||
<Grid container>
|
<Grid container>
|
||||||
<Grid item xs>
|
<Grid item style={{ marginRight: 34 }}>
|
||||||
<PercentageChart
|
<Label2>Direction</Label2>
|
||||||
cashIn={getDirectionPercent().cashIn}
|
|
||||||
cashOut={getDirectionPercent().cashOut}
|
|
||||||
/>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
|
<Grid
|
||||||
|
item
|
||||||
|
className={classnames(
|
||||||
|
classes.directionLabelContainer,
|
||||||
|
classes.dirLabContMargin
|
||||||
|
)}>
|
||||||
|
<div className={classes.outSquare} />
|
||||||
|
<Label1 className={classes.directionLabel}>Out</Label1>
|
||||||
|
</Grid>
|
||||||
|
<Grid item className={classes.directionLabelContainer}>
|
||||||
|
<div className={classes.inSquare} />
|
||||||
|
<Label1 className={classes.directionLabel}>In</Label1>
|
||||||
|
</Grid>
|
||||||
|
</Grid>
|
||||||
|
<Grid item xs>
|
||||||
|
<PercentageChart
|
||||||
|
cashIn={getDirectionPercent().cashIn}
|
||||||
|
cashOut={getDirectionPercent().cashOut}
|
||||||
|
/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
@ -223,30 +240,4 @@ const SystemPerformance = () => {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
<Grid item xs={4}>
|
|
||||||
<div style={{ display: 'flex' }}>
|
|
||||||
<Label2>Direction</Label2>
|
|
||||||
<div style={{ marginLeft: 8, display: 'flex' }}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
width: 8,
|
|
||||||
height: 8,
|
|
||||||
borderRadius: 2,
|
|
||||||
marginTop: 18,
|
|
||||||
marginRight: 8,
|
|
||||||
backgroundColor: 'pink'
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<p>In</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<Grid container>
|
|
||||||
<Grid item xs>
|
|
||||||
<PercentageChart data={getDirectionPercent()} />
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
</Grid>
|
|
||||||
*/
|
|
||||||
|
|
||||||
export default SystemPerformance
|
export default SystemPerformance
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,9 @@ import {
|
||||||
fontSecondary,
|
fontSecondary,
|
||||||
fontColor,
|
fontColor,
|
||||||
spring4,
|
spring4,
|
||||||
tomato
|
tomato,
|
||||||
|
java,
|
||||||
|
neon
|
||||||
} from 'src/styling/variables'
|
} from 'src/styling/variables'
|
||||||
|
|
||||||
const styles = {
|
const styles = {
|
||||||
|
|
@ -90,6 +92,28 @@ const styles = {
|
||||||
},
|
},
|
||||||
gridContainer: {
|
gridContainer: {
|
||||||
marginTop: 30
|
marginTop: 30
|
||||||
|
},
|
||||||
|
inSquare: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 2,
|
||||||
|
marginTop: 18,
|
||||||
|
marginRight: 4,
|
||||||
|
backgroundColor: java
|
||||||
|
},
|
||||||
|
outSquare: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 2,
|
||||||
|
marginTop: 18,
|
||||||
|
marginRight: 4,
|
||||||
|
backgroundColor: neon
|
||||||
|
},
|
||||||
|
directionLabelContainer: {
|
||||||
|
display: 'flex'
|
||||||
|
},
|
||||||
|
dirLabContMargin: {
|
||||||
|
marginRight: 20
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import TableRow from '@material-ui/core/TableRow'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
||||||
import { Status } from 'src/components/Status'
|
import { Status } from 'src/components/Status'
|
||||||
import { Label2, TL2 } from 'src/components/typography'
|
import { Label2, TL2 } from 'src/components/typography'
|
||||||
// import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
|
// import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ import Grid from '@material-ui/core/Grid'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { cardState as cardState_ } from 'src/components/CollapsibleCard'
|
import { cardState as cardState_ } from 'src/components/CollapsibleCard'
|
||||||
// import ActionButton from 'src/components/buttons/ActionButton'
|
// import ActionButton from 'src/components/buttons/ActionButton'
|
||||||
import { H4, TL2, Label1 } from 'src/components/typography'
|
import { H4, TL2, Label1 } from 'src/components/typography'
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,12 @@ import { useMutation } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core'
|
import { makeStyles } from '@material-ui/core'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
import * as Yup from 'yup'
|
||||||
|
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import { Table as EditableTable } from 'src/components/editableTable'
|
||||||
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
|
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
|
||||||
import { NumberInput } from 'src/components/inputs/formik'
|
import { NumberInput } from 'src/components/inputs/formik'
|
||||||
import { fromNamespace } from 'src/utils/config'
|
import { fromNamespace } from 'src/utils/config'
|
||||||
import * as Yup from 'yup'
|
|
||||||
|
|
||||||
import styles from './Cassettes.styles'
|
import styles from './Cassettes.styles'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@ import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { Table as EditableTable } from 'src/components/editableTable'
|
import { Table as EditableTable } from 'src/components/editableTable'
|
||||||
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
|
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
import { Label3, P } from 'src/components/typography'
|
import { Label3, P } from 'src/components/typography'
|
||||||
|
|
||||||
import styles from '../Machines.styles'
|
import styles from '../Machines.styles'
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import {
|
||||||
CellMeasurer,
|
CellMeasurer,
|
||||||
CellMeasurerCache
|
CellMeasurerCache
|
||||||
} from 'react-virtualized'
|
} from 'react-virtualized'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Table,
|
Table,
|
||||||
TBody,
|
TBody,
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import gql from 'graphql-tag'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useEffect, useState } from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
|
|
||||||
import DetailsRow from 'src/pages/Transactions/DetailsCard'
|
import DetailsRow from 'src/pages/Transactions/DetailsCard'
|
||||||
import { mainStyles } from 'src/pages/Transactions/Transactions.styles'
|
import { mainStyles } from 'src/pages/Transactions/Transactions.styles'
|
||||||
import { getStatus } from 'src/pages/Transactions/helper'
|
import { getStatus } from 'src/pages/Transactions/helper'
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
import * as R from 'ramda'
|
||||||
import React, { useState, useEffect } from 'react'
|
import React, { useState, useEffect } from 'react'
|
||||||
import { Link, useLocation } from 'react-router-dom'
|
import { Link, useLocation } from 'react-router-dom'
|
||||||
|
|
||||||
import { TL1, TL2, Label3 } from 'src/components/typography'
|
import { TL1, TL2, Label3 } from 'src/components/typography'
|
||||||
|
|
||||||
import Cassettes from './MachineComponents/Cassettes'
|
import Cassettes from './MachineComponents/Cassettes'
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue