From c21cdb13e10d9f7e364a6085a1d91ba228a7966a Mon Sep 17 00:00:00 2001 From: Cesar <26280794+csrapr@users.noreply.github.com> Date: Tue, 17 Nov 2020 12:13:10 +0000 Subject: [PATCH] Feat: make dashboard and machine profile page --- lib/new-admin/graphql/schema.js | 4 + lib/new-admin/transactions.js | 4 +- lib/plugins.js | 63 ------ lib/ticker.js | 25 ++- .../src/components/typography/index.js | 4 +- .../src/pages/Dashboard/Alerts/Alerts.js | 158 +++++++++----- .../src/pages/Dashboard/Dashboard.js | 1 - .../src/pages/Dashboard/Footer/Footer.js | 1 - .../src/pages/Dashboard/RightSide.js | 1 - .../SystemPerformance/Graphs/RefLineChart.js | 1 - .../Graphs/RefScatterplot.js | 1 - .../SystemPerformance/Graphs/Scatterplot.js | 134 ++++++++++++ .../pages/Dashboard/SystemPerformance/Nav.js | 1 - .../SystemPerformance/SystemPerformance.js | 1 - .../Dashboard/SystemStatus/MachinesTable.js | 1 - .../Dashboard/SystemStatus/SystemStatus.js | 1 - .../MachineComponents/Cassettes/Cassettes.js | 3 +- .../Commissions/Commissions.js | 1 - .../Machines/MachineComponents/Details.js | 1 - .../Transactions/CopyToClipboard.js | 74 +++++++ .../Transactions/DataTable.js | 1 - .../Transactions/DataTable.styles.js | 43 ++++ .../Transactions/DetailsCard.js | 195 ++++++++++++++++++ .../Transactions/DetailsCard.styles.js | 84 ++++++++ .../MachineComponents/Transactions/Stripes.js | 12 ++ .../Transactions/Transactions.js | 1 - .../MachineComponents/Transactions/helper.js | 23 +++ .../src/pages/Machines/Machines.js | 1 - new-lamassu-admin/src/routing/routes.js | 12 ++ 29 files changed, 717 insertions(+), 135 deletions(-) create mode 100644 new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/Scatterplot.js create mode 100644 new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/CopyToClipboard.js create mode 100644 new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.styles.js create mode 100644 new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.js create mode 100644 new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.styles.js create mode 100644 new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Stripes.js create mode 100644 new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/helper.js diff --git a/lib/new-admin/graphql/schema.js b/lib/new-admin/graphql/schema.js index c363faff..92e514a6 100644 --- a/lib/new-admin/graphql/schema.js +++ b/lib/new-admin/graphql/schema.js @@ -240,6 +240,10 @@ const typeDefs = gql` created: Date age: Float deviceTime: Date + type Rate { + code: String + name: String + rate: Float } type Rate { diff --git a/lib/new-admin/transactions.js b/lib/new-admin/transactions.js index c7208961..ba3156d2 100644 --- a/lib/new-admin/transactions.js +++ b/lib/new-admin/transactions.js @@ -36,7 +36,7 @@ function batch (from = new Date(0).toISOString(), until = new Date().toISOString c.front_camera_path as customer_front_camera_path, c.id_card_photo_path as customer_id_card_photo_path, ((not txs.send_confirmed) and (txs.created <= now() - interval $1)) as expired - from cash_in_txs as txs + from cash_in_txs as txs left outer join customers c on txs.customer_id = c.id where txs.created >= $2 and txs.created <= $3 ${ id !== null ? `and txs.device_id = $6` : `` @@ -54,7 +54,7 @@ function batch (from = new Date(0).toISOString(), until = new Date().toISOString c.front_camera_path as customer_front_camera_path, c.id_card_photo_path as customer_id_card_photo_path, (extract(epoch from (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $1 as expired - from cash_out_txs txs + from cash_out_txs txs inner join cash_out_actions actions on txs.id = actions.tx_id and actions.action = 'provisionAddress' left outer join customers c on txs.customer_id = c.id diff --git a/lib/plugins.js b/lib/plugins.js index 3e13f650..8da6fa99 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -147,21 +147,6 @@ function plugins (settings, deviceId) { ] } -<<<<<<< HEAD -======= - function getLcmOrBigx2 (n1, n2) { - let big = Math.max(n1, n2) - let small = Math.min(n1, n2) - - let i = big * 2 - while (i % small !== 0) { - i += lar - } - - return i - } - ->>>>>>> 1706b2c... Feat: save highVolumeTxs on DB and plugins code refactor function buildAvailableCassettes (excludeTxId) { const cashOutConfig = configManager.getCashOut(deviceId, settings.config) @@ -169,7 +154,6 @@ function plugins (settings, deviceId) { const denominations = [cashOutConfig.top, cashOutConfig.bottom] -<<<<<<< HEAD const virtualCassettes = [Math.max(cashOutConfig.top, cashOutConfig.bottom) * 2] return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)]) @@ -179,11 +163,6 @@ function plugins (settings, deviceId) { const counts = argv.cassettes ? argv.cassettes.split(',') : rec.counts -======= - const virtualCassettes = [ - getLcmOrBigx2(cashOutConfig.top, cashOutConfig.bottom) - ] ->>>>>>> 1706b2c... Feat: save highVolumeTxs on DB and plugins code refactor return Promise.all([ dbm.cassetteCounts(deviceId), @@ -288,7 +267,6 @@ function plugins (settings, deviceId) { currentConfigVersionPromise ].concat(tickerPromises, balancePromises, testnetPromises, currentAvailablePromoCodes) -<<<<<<< HEAD return Promise.all(promises) .then(arr => { const cassettes = arr[0] @@ -310,26 +288,6 @@ function plugins (settings, deviceId) { areThereAvailablePromoCodes } }) -======= - return Promise.all(promises).then(arr => { - const cassettes = arr[0] - const configVersion = arr[2] - const cryptoCodesCount = cryptoCodes.length - const tickers = arr.slice(3, cryptoCodesCount + 3) - const balances = arr.slice(cryptoCodesCount + 3, 2 * cryptoCodesCount + 3) - const testNets = arr.slice(2 * cryptoCodesCount + 3) - const coinParams = _.zip(cryptoCodes, testNets) - const coinsWithoutRate = _.map(mapCoinSettings, coinParams) - - return { - cassettes, - rates: buildRates(tickers), - balances: buildBalances(balances), - coins: _.zipWith(_.assign, coinsWithoutRate, tickers), - configVersion - } - }) ->>>>>>> 1706b2c... Feat: save highVolumeTxs on DB and plugins code refactor } function sendCoins (tx) { @@ -648,15 +606,8 @@ function plugins (settings, deviceId) { const notifications = configManager.getGlobalNotifications(settings.config) let promises = [] -<<<<<<< HEAD if (notifications.email.active && rec.email) promises.push(email.sendMessage(settings, rec)) if (notifications.sms.active && rec.sms) promises.push(sms.sendMessage(settings, rec)) -======= - if (notifications.email.active && rec.email) - promises.push(email.sendMessage(settings, rec)) - if (notifications.sms.active && rec.sms) - promises.push(sms.sendMessage(settings, rec)) ->>>>>>> 1706b2c... Feat: save highVolumeTxs on DB and plugins code refactor return Promise.all(promises) } @@ -757,25 +708,11 @@ function plugins (settings, deviceId) { fiatCode } -<<<<<<< HEAD if (_.isFinite(lowAlertThreshold) && BN(fiatBalance.balance).lt(lowAlertThreshold)) { -======= - if ( - _.isFinite(lowAlertThreshold) && - BN(fiatBalance.balance).lt(lowAlertThreshold) - ) ->>>>>>> 1706b2c... Feat: save highVolumeTxs on DB and plugins code refactor return _.set('code')('LOW_CRYPTO_BALANCE')(req) } -<<<<<<< HEAD if (_.isFinite(highAlertThreshold) && BN(fiatBalance.balance).gt(highAlertThreshold)) { -======= - if ( - _.isFinite(highAlertThreshold) && - BN(fiatBalance.balance).gt(highAlertThreshold) - ) ->>>>>>> 1706b2c... Feat: save highVolumeTxs on DB and plugins code refactor return _.set('code')('HIGH_CRYPTO_BALANCE')(req) } diff --git a/lib/ticker.js b/lib/ticker.js index 85fc3266..ef710443 100644 --- a/lib/ticker.js +++ b/lib/ticker.js @@ -2,6 +2,7 @@ const mem = require('mem') const configManager = require('./new-config-manager') const ph = require('./plugin-helper') const logger = require('./logger') +const axios = require('axios') const lastRate = {} @@ -39,4 +40,26 @@ const getRates = mem(_getRates, { cacheKey: (settings, fiatCode, cryptoCode) => JSON.stringify([fiatCode, cryptoCode]) }) -module.exports = { getRates } +const getBtcRates = (to = null, from = 'USD') => { + // if to !== null, then we return only the rates with from (default USD) and to (so an array with 2 items) + return axios.get('https://bitpay.com/api/rates').then(response => { + const fxRates = response.data + if (to === null) { + return fxRates + } + const toRate = fxRates.find(o => o.code === to) + const fromRate = fxRates.find(o => o.code === from) + + let res = [] + if (toRate && to !== from) { + res = [...res, toRate] + } + if (fromRate) { + res = [...res, fromRate] + } + + return res + }) +} + +module.exports = { getBtcRates, getRates } diff --git a/new-lamassu-admin/src/components/typography/index.js b/new-lamassu-admin/src/components/typography/index.js index 2cd0a09e..a9681372 100644 --- a/new-lamassu-admin/src/components/typography/index.js +++ b/new-lamassu-admin/src/components/typography/index.js @@ -91,6 +91,7 @@ const TL2 = pBuilder('tl2') const Label1 = pBuilder('label1') const Label2 = pBuilder('label2') const Label3 = pBuilder('label3') +const Label4 = pBuilder('regularLabel') function pBuilder(elementClass) { return ({ inline, noMargin, className, children, ...props }) => { @@ -124,5 +125,6 @@ export { Mono, Label1, Label2, - Label3 + Label3, + Label4 } diff --git a/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.js b/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.js index 6ee74b27..d0ad8adb 100644 --- a/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.js +++ b/new-lamassu-admin/src/pages/Dashboard/Alerts/Alerts.js @@ -1,76 +1,130 @@ +import { useQuery } from '@apollo/react-hooks' import Button from '@material-ui/core/Button' import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' -import React from 'react' - -import { cardState as cardState_ } from 'src/components/CollapsibleCard' +import gql from 'graphql-tag' +import * as R from 'ramda' +import React, { useState, useEffect } from 'react' import { Label1, H4 } from 'src/components/typography' -import styles from './Alerts.styles' +import styles from '../Dashboard.styles' + import AlertsTable from './AlertsTable' const NUM_TO_RENDER = 3 -const data = { - alerts: [ - { text: 'alert 1' }, - { text: 'alert 2' }, - { text: 'alert 3' }, - { text: 'alert 4' }, - { text: 'alert 5' } - ] -} +const GET_ALERTS = gql` + query getAlerts { + alerts { + id + type + detail + message + created + read + valid + } + machines { + deviceId + name + } + } +` const useStyles = makeStyles(styles) -const Alerts = ({ onReset, onExpand, size }) => { +const Alerts = ({ cardState, setRightSideState }) => { const classes = useStyles() + const [showAllItems, setShowAllItems] = useState(false) + const { data } = useQuery(GET_ALERTS) - const showAllItems = size === cardState_.EXPANDED + const alerts = R.path(['alerts'])(data) ?? [] + const machines = R.compose( + R.map(R.prop('name')), + R.indexBy(R.prop('deviceId')) + )(data?.machines ?? []) - const alertsLength = () => (data ? data.alerts.length : 0) + 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 ( <> -
-

{`Alerts (${alertsLength()})`}

- {showAllItems && ( - - - +
+

{`Alerts ${ + data ? `(${alerts.length})` : 0 + }`}

+ {(showAllItems || cardState.cardSize === 'small') && ( + <> + + + + )}
- <> - - - - {!showAllItems && ( - <> - - - - - )} + {cardState.cardSize !== 'small' && ( + <> + + + + {showExpandButton && ( + <> + + + + + )} + - - + + )} ) } diff --git a/new-lamassu-admin/src/pages/Dashboard/Dashboard.js b/new-lamassu-admin/src/pages/Dashboard/Dashboard.js index dd875662..c345be9c 100644 --- a/new-lamassu-admin/src/pages/Dashboard/Dashboard.js +++ b/new-lamassu-admin/src/pages/Dashboard/Dashboard.js @@ -2,7 +2,6 @@ import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' import classnames from 'classnames' import React from 'react' - import TitleSection from 'src/components/layout/TitleSection' import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' diff --git a/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js b/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js index 1f9b2034..dd9a8ffa 100644 --- a/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js +++ b/new-lamassu-admin/src/pages/Dashboard/Footer/Footer.js @@ -6,7 +6,6 @@ import classnames from 'classnames' import gql from 'graphql-tag' import * as R from 'ramda' import React, { useState } from 'react' - import { Label2 } from 'src/components/typography' import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' diff --git a/new-lamassu-admin/src/pages/Dashboard/RightSide.js b/new-lamassu-admin/src/pages/Dashboard/RightSide.js index 4a8ab0a4..6d2e5461 100644 --- a/new-lamassu-admin/src/pages/Dashboard/RightSide.js +++ b/new-lamassu-admin/src/pages/Dashboard/RightSide.js @@ -2,7 +2,6 @@ import Button from '@material-ui/core/Button' import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' import React, { useState } from 'react' - import CollapsibleCard, { cardState } from 'src/components/CollapsibleCard' import { H4, Label1 } from 'src/components/typography' diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js index 29d92d4f..c90f8048 100644 --- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js +++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefLineChart.js @@ -1,7 +1,6 @@ import * as d3 from 'd3' import * as R from 'ramda' import React, { useEffect, useRef, useCallback } from 'react' - import { backgroundColor, zircon, primaryColor } from 'src/styling/variables' const transactionProfit = tx => { diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js index 4d7da250..a26da0a3 100644 --- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js +++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/RefScatterplot.js @@ -2,7 +2,6 @@ import * as d3 from 'd3' import moment from 'moment' import * as R from 'ramda' import React, { useEffect, useRef, useCallback } from 'react' - import { backgroundColor, java, neon } from 'src/styling/variables' const RefScatterplot = ({ data: realData, timeFrame }) => { diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/Scatterplot.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/Scatterplot.js new file mode 100644 index 00000000..ef08a169 --- /dev/null +++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Graphs/Scatterplot.js @@ -0,0 +1,134 @@ +/*eslint-disable*/ +import { scaleLinear, scaleTime, max, axisLeft, axisBottom, select } from 'd3' +import React, { useMemo } from 'react' +import moment from 'moment' + +const data = [ + [0, '2020-11-08T18:00:05.664Z'], + [40.01301, '2020-11-09T11:17:05.664Z'] +] + +const marginTop = 10 +const marginRight = 30 +const marginBottom = 30 +const marginLeft = 60 +const width = 510 - marginLeft - marginRight +const height = 141 - marginTop - marginBottom + +const Scatterplot = ({ data: realData }) => { + const x = scaleTime() + .domain([ + moment() + .add(-1, 'day') + .valueOf(), + moment().valueOf() + ]) + .range([0, width]) + .nice() + + const y = scaleLinear() + .domain([0, 1000]) + .range([height, 0]) + .nice() + + // viewBox="0 0 540 141" + return ( + <> + + + + {axisLeft(y)} + {/* */} + + + + + ) +} + +const XAxis = ({ + range = [10, 500], + transform, + scale: xScale, + numTicks = 7 +}) => { + const ticks = useMemo(() => { + return xScale.ticks(numTicks).map(value => ({ + value, + xOffset: xScale(value) + })) + }, [range.join('-')]) + + return ( + + {ticks.map(({ value, xOffset }) => ( + + + {value.getHours()} + + + ))} + + ) +} + +const YAxis = ({ + range = [10, 500], + transform, + scale: xScale, + numTicks = 7 +}) => { + const ticks = useMemo(() => { + return xScale.ticks(numTicks).map(value => ({ + value, + xOffset: xScale(value) + })) + }, [range.join('-')]) + + return ( + + {ticks.map(({ value, xOffset }) => ( + + + {value} + + + ))} + + ) +} + +const RenderCircles = ({ data, scale }) => { + let renderCircles = data.map((item, idx) => { + return ( + + ) + }) + return {renderCircles} +} + +export default Scatterplot diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Nav.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Nav.js index 04c9bd7a..c0de11d5 100644 --- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Nav.js +++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/Nav.js @@ -2,7 +2,6 @@ import { makeStyles } from '@material-ui/core/styles' import classnames from 'classnames' import * as R from 'ramda' import React, { useState } from 'react' - import { H4 } from 'src/components/typography' import styles from './SystemPerformance.styles' diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js index fd23dce7..bbfe8a3e 100644 --- a/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js +++ b/new-lamassu-admin/src/pages/Dashboard/SystemPerformance/SystemPerformance.js @@ -6,7 +6,6 @@ import gql from 'graphql-tag' import moment from 'moment' import * as R from 'ramda' import React, { useState } from 'react' - import { Label2 } from 'src/components/typography/index' import { ReactComponent as TriangleDown } from 'src/styling/icons/arrow/triangle_down.svg' import { ReactComponent as TriangleUp } from 'src/styling/icons/arrow/triangle_up.svg' diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemStatus/MachinesTable.js b/new-lamassu-admin/src/pages/Dashboard/SystemStatus/MachinesTable.js index df375db7..bbea843f 100644 --- a/new-lamassu-admin/src/pages/Dashboard/SystemStatus/MachinesTable.js +++ b/new-lamassu-admin/src/pages/Dashboard/SystemStatus/MachinesTable.js @@ -8,7 +8,6 @@ import TableRow from '@material-ui/core/TableRow' import classnames from 'classnames' import React from 'react' import { useHistory } from 'react-router-dom' - import { Status } from 'src/components/Status' import { Label2, TL2 } from 'src/components/typography' // import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' diff --git a/new-lamassu-admin/src/pages/Dashboard/SystemStatus/SystemStatus.js b/new-lamassu-admin/src/pages/Dashboard/SystemStatus/SystemStatus.js index 189c0902..aea73b0f 100644 --- a/new-lamassu-admin/src/pages/Dashboard/SystemStatus/SystemStatus.js +++ b/new-lamassu-admin/src/pages/Dashboard/SystemStatus/SystemStatus.js @@ -4,7 +4,6 @@ import Grid from '@material-ui/core/Grid' import { makeStyles } from '@material-ui/core/styles' import gql from 'graphql-tag' import React from 'react' - import { cardState as cardState_ } from 'src/components/CollapsibleCard' // import ActionButton from 'src/components/buttons/ActionButton' import { H4, TL2, Label1 } from 'src/components/typography' diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Cassettes/Cassettes.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Cassettes/Cassettes.js index 9cf06374..0b82420b 100644 --- a/new-lamassu-admin/src/pages/Machines/MachineComponents/Cassettes/Cassettes.js +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Cassettes/Cassettes.js @@ -2,12 +2,11 @@ import { useMutation } from '@apollo/react-hooks' import { makeStyles } from '@material-ui/core' import gql from 'graphql-tag' import React from 'react' -import * as Yup from 'yup' - import { Table as EditableTable } from 'src/components/editableTable' import { CashOut } from 'src/components/inputs/cashbox/Cashbox' import { NumberInput } from 'src/components/inputs/formik' import { fromNamespace } from 'src/utils/config' +import * as Yup from 'yup' import styles from './Cassettes.styles' diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Commissions/Commissions.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Commissions/Commissions.js index 6b569961..f19d95d9 100644 --- a/new-lamassu-admin/src/pages/Machines/MachineComponents/Commissions/Commissions.js +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Commissions/Commissions.js @@ -2,7 +2,6 @@ import { useQuery, useMutation } from '@apollo/react-hooks' import gql from 'graphql-tag' import * as R from 'ramda' import React from 'react' - import { Table as EditableTable } from 'src/components/editableTable' import { fromNamespace, toNamespace, namespaces } from 'src/utils/config' diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Details.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Details.js index a47adfc7..2787eb28 100644 --- a/new-lamassu-admin/src/pages/Machines/MachineComponents/Details.js +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Details.js @@ -1,7 +1,6 @@ import { makeStyles } from '@material-ui/core/styles' import moment from 'moment' import React from 'react' - import { Label3, P } from 'src/components/typography' import styles from '../Machines.styles' diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/CopyToClipboard.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/CopyToClipboard.js new file mode 100644 index 00000000..ce6065c6 --- /dev/null +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/CopyToClipboard.js @@ -0,0 +1,74 @@ +import { makeStyles } from '@material-ui/core/styles' +import classnames from 'classnames' +import * as R from 'ramda' +import React, { useState, useEffect } from 'react' +import { CopyToClipboard as ReactCopyToClipboard } from 'react-copy-to-clipboard' + +import Popover from 'src/components/Popper' +import { ReactComponent as CopyIcon } from 'src/styling/icons/action/copy/copy.svg' +import { comet } from 'src/styling/variables' + +import { cpcStyles } from './Transactions.styles' + +const useStyles = makeStyles(cpcStyles) + +const CopyToClipboard = ({ + className, + buttonClassname, + children, + ...props +}) => { + const [anchorEl, setAnchorEl] = useState(null) + + useEffect(() => { + if (anchorEl) setTimeout(() => setAnchorEl(null), 3000) + }, [anchorEl]) + + const classes = useStyles() + + const handleClick = event => { + setAnchorEl(anchorEl ? null : event.currentTarget) + } + + const handleClose = () => { + setAnchorEl(null) + } + + const open = Boolean(anchorEl) + const id = open ? 'simple-popper' : undefined + + return ( +
+ {children && ( + <> +
+ {children} +
+
+ + + +
+ +
+
Copied to clipboard!
+
+
+ + )} +
+ ) +} + +export default CopyToClipboard diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.js index 55bef3af..eaab5696 100644 --- a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.js +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.js @@ -8,7 +8,6 @@ import { CellMeasurer, CellMeasurerCache } from 'react-virtualized' - import { Table, TBody, diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.styles.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.styles.js new file mode 100644 index 00000000..838dbad8 --- /dev/null +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DataTable.styles.js @@ -0,0 +1,43 @@ +import { zircon } from 'src/styling/variables' + +export default { + expandButton: { + outline: 'none', + border: 'none', + backgroundColor: 'transparent', + cursor: 'pointer', + padding: 4 + }, + rowWrapper: { + // workaround to shadows cut by r-virtualized when scroll is visible + padding: 1 + }, + row: { + border: [[2, 'solid', 'transparent']], + borderRadius: 0 + }, + expanded: { + border: [[2, 'solid', zircon]], + boxShadow: '0 0 8px 0 rgba(0,0,0,0.08)' + }, + before: { + paddingTop: 12 + }, + after: { + paddingBottom: 12 + }, + pointer: { + cursor: 'pointer' + }, + body: { + flex: [[1, 1, 'auto']] + }, + table: ({ width }) => ({ + marginBottom: 30, + minHeight: 200, + width, + flex: 1, + display: 'flex', + flexDirection: 'column' + }) +} diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.js new file mode 100644 index 00000000..6dc282f5 --- /dev/null +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.js @@ -0,0 +1,195 @@ +import { makeStyles, Box } from '@material-ui/core' +import BigNumber from 'bignumber.js' +import moment from 'moment' +import React, { memo } from 'react' + +import { IDButton } from 'src/components/buttons' +import { Label1 } from 'src/components/typography' +import { ReactComponent as CardIdInverseIcon } from 'src/styling/icons/ID/card/white.svg' +import { ReactComponent as CardIdIcon } from 'src/styling/icons/ID/card/zodiac.svg' +import { ReactComponent as PhoneIdInverseIcon } from 'src/styling/icons/ID/phone/white.svg' +import { ReactComponent as PhoneIdIcon } from 'src/styling/icons/ID/phone/zodiac.svg' +import { ReactComponent as CamIdInverseIcon } from 'src/styling/icons/ID/photo/white.svg' +import { ReactComponent as CamIdIcon } from 'src/styling/icons/ID/photo/zodiac.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 { URI } from 'src/utils/apollo' +import { toUnit, formatCryptoAddress } from 'src/utils/coin' +import { onlyFirstToUpper } from 'src/utils/string' + +import CopyToClipboard from './CopyToClipboard' +import styles from './DetailsCard.styles' +import { getStatus } from './helper' + +const useStyles = makeStyles(styles) + +const formatAddress = (cryptoCode = '', address = '') => + formatCryptoAddress(cryptoCode, address).replace(/(.{5})/g, '$1 ') + +const Label = ({ children }) => { + const classes = useStyles() + return {children} +} + +const DetailsRow = ({ it: tx }) => { + const classes = useStyles() + + const fiat = Number.parseFloat(tx.fiat) + const crypto = toUnit(new BigNumber(tx.cryptoAtoms), tx.cryptoCode) + const commissionPercentage = Number.parseFloat(tx.commissionPercentage, 2) + const commission = Number(fiat * commissionPercentage).toFixed(2) + const exchangeRate = Number(fiat / crypto).toFixed(3) + const displayExRate = `1 ${tx.cryptoCode} = ${exchangeRate} ${tx.fiatCode}` + + const customer = tx.customerIdCardData && { + name: `${onlyFirstToUpper( + tx.customerIdCardData.firstName + )} ${onlyFirstToUpper(tx.customerIdCardData.lastName)}`, + age: moment().diff(moment(tx.customerIdCardData.dateOfBirth), 'years'), + country: tx.customerIdCardData.country, + idCardNumber: tx.customerIdCardData.documentNumber, + idCardExpirationDate: moment(tx.customerIdCardData.expirationDate).format( + 'DD-MM-YYYY' + ) + } + + return ( +
+
+
+ +
+ + {tx.txClass === 'cashOut' ? : } + + {tx.txClass === 'cashOut' ? 'Cash-out' : 'Cash-in'} +
+
+ +
+ + + {tx.customerPhone && ( + + {tx.customerPhone} + + )} + {tx.customerIdCardPhotoPath && !tx.customerIdCardData && ( + + + + )} + {tx.customerIdCardData && ( + +
+
+
+ +
{customer.name}
+
+
+ +
{customer.age}
+
+
+ +
{customer.country}
+
+
+
+
+ +
{customer.idCardNumber}
+
+
+ +
{customer.idCardExpirationDate}
+
+
+
+
+ )} + {tx.customerFrontCameraPath && ( + + + + )} +
+
+
+ +
{crypto > 0 ? displayExRate : '-'}
+
+
+ +
+ {`${commission} ${tx.fiatCode} (${commissionPercentage * 100} %)`} +
+
+
+ +
+ {tx.txClass === 'cashIn' + ? `${Number.parseFloat(tx.cashInFee)} ${tx.fiatCode}` + : 'N/A'} +
+
+
+
+
+ +
+ + {formatAddress(tx.cryptoCode, tx.toAddress)} + +
+
+
+ +
+ {tx.txClass === 'cashOut' ? ( + 'N/A' + ) : ( + {tx.txHash} + )} +
+
+
+ + {tx.id} +
+
+
+
+ + {getStatus(tx)} +
+
+
+ ) +} + +export default memo(DetailsRow, (prev, next) => prev.id === next.id) diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.styles.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.styles.js new file mode 100644 index 00000000..277bcfd2 --- /dev/null +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/DetailsCard.styles.js @@ -0,0 +1,84 @@ +import typographyStyles from 'src/components/typography/styles' +import { offColor } from 'src/styling/variables' + +const { p } = typographyStyles + +export default { + wrapper: { + display: 'flex', + flexDirection: 'column', + marginTop: 24 + }, + row: { + display: 'flex', + flexDirection: 'row', + marginBottom: 36 + }, + secondRow: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'space-between', + marginBottom: 36 + }, + lastRow: { + display: 'flex', + flexDirection: 'row', + marginBottom: 32 + }, + label: { + color: offColor, + margin: [[0, 0, 6, 0]] + }, + txIcon: { + marginRight: 10 + }, + popover: { + height: 164, + width: 215 + }, + idButton: { + marginRight: 4 + }, + idCardDataCard: { + extend: p, + display: 'flex', + padding: [[11, 8]], + // rework this into a proper component + '& > div': { + display: 'flex', + flexDirection: 'column', + '& > div': { + width: 144, + height: 37, + marginBottom: 15, + '&:last-child': { + marginBottom: 0 + } + } + } + }, + bold: { + fontWeight: 700 + }, + direction: { + width: 233 + }, + availableIds: { + width: 232 + }, + exchangeRate: { + width: 250 + }, + commission: { + width: 217 + }, + address: { + width: 280 + }, + transactionId: { + width: 280 + }, + sessionId: { + width: 215 + } +} diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Stripes.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Stripes.js new file mode 100644 index 00000000..59cf8ce6 --- /dev/null +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Stripes.js @@ -0,0 +1,12 @@ +import React from 'react' + +import { Td } from 'src/components/fake-table/Table' +import { ReactComponent as StripesSvg } from 'src/styling/icons/stripes.svg' + +const Stripes = ({ width }) => ( + + + +) + +export default Stripes diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Transactions.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Transactions.js index 75e6f6f7..a4dae14e 100644 --- a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Transactions.js +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/Transactions.js @@ -5,7 +5,6 @@ import gql from 'graphql-tag' import moment from 'moment' import * as R from 'ramda' import React, { useEffect, useState } from 'react' - import DetailsRow from 'src/pages/Transactions/DetailsCard' import { mainStyles } from 'src/pages/Transactions/Transactions.styles' import { getStatus } from 'src/pages/Transactions/helper' diff --git a/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/helper.js b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/helper.js new file mode 100644 index 00000000..91c0a7b9 --- /dev/null +++ b/new-lamassu-admin/src/pages/Machines/MachineComponents/Transactions/helper.js @@ -0,0 +1,23 @@ +const getCashOutStatus = it => { + if (it.hasError) return 'Error' + if (it.dispense) return 'Success' + if (it.expired) return 'Expired' + return 'Pending' +} + +const getCashInStatus = it => { + if (it.operatorCompleted) return 'Cancelled' + if (it.hasError) return 'Error' + if (it.sendConfirmed) return 'Sent' + if (it.expired) return 'Expired' + return 'Pending' +} + +const getStatus = it => { + if (it.class === 'cashOut') { + return getCashOutStatus(it) + } + return getCashInStatus(it) +} + +export { getStatus } diff --git a/new-lamassu-admin/src/pages/Machines/Machines.js b/new-lamassu-admin/src/pages/Machines/Machines.js index 43914f98..af8f3fdf 100644 --- a/new-lamassu-admin/src/pages/Machines/Machines.js +++ b/new-lamassu-admin/src/pages/Machines/Machines.js @@ -8,7 +8,6 @@ import gql from 'graphql-tag' import * as R from 'ramda' import React, { useState, useEffect } from 'react' import { Link, useLocation } from 'react-router-dom' - import { TL1, TL2, Label3 } from 'src/components/typography' import Cassettes from './MachineComponents/Cassettes' diff --git a/new-lamassu-admin/src/routing/routes.js b/new-lamassu-admin/src/routing/routes.js index be3e1c2c..bd176c85 100644 --- a/new-lamassu-admin/src/routing/routes.js +++ b/new-lamassu-admin/src/routing/routes.js @@ -51,6 +51,18 @@ const useStyles = makeStyles({ }) const tree = [ + { + key: 'dashboard', + label: 'Dashboard', + route: '/dashboard', + component: Dashboard + }, + { + key: 'machines', + label: 'Machines', + route: '/machines', + component: Machines + }, { key: 'transactions', label: 'Transactions',