diff --git a/lib/customers.js b/lib/customers.js index ebbc76b5..0f68f1ed 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -587,7 +587,7 @@ function formatSubscriberInfo(customer) { const subscriberInfo = customer.subscriberInfo if(!subscriberInfo) return customer const result = subscriberInfo.result - if(subscriberInfo.status !== 'successful' || _.isEmpty(result)) return customer + if(_.isEmpty(result)) return _.omit(['subscriberInfo'], customer) const name = _.get('belongs_to.name')(result) const street = _.get('current_addresses[0].street_line_1')(result) diff --git a/lib/new-admin/config/accounts.js b/lib/new-admin/config/accounts.js index 3fe0fa7c..9ab0476c 100644 --- a/lib/new-admin/config/accounts.js +++ b/lib/new-admin/config/accounts.js @@ -49,7 +49,7 @@ const ALL_ACCOUNTS = [ { code: 'mock-id-verify', display: 'Mock ID verifier', class: ID_VERIFIER, dev: true }, { code: 'twilio', display: 'Twilio', class: SMS }, { code: 'mailgun', display: 'Mailgun', class: EMAIL }, - { code: 'none', display: 'None', class: ZERO_CONF, cryptos: [BTC, ZEC, LTC, DASH, BCH, ETH, XMR] }, + { code: 'none', display: 'None', class: ZERO_CONF, cryptos: ALL_CRYPTOS }, { code: 'blockcypher', display: 'Blockcypher', class: ZERO_CONF, cryptos: [BTC] }, { code: 'mock-zero-conf', display: 'Mock 0-conf', class: ZERO_CONF, cryptos: ALL_CRYPTOS, dev: true }, { code: 'ciphertrace', display: 'CipherTrace', class: WALLET_SCORING, cryptos: [BTC, ETH, LTC, BCH] }, diff --git a/lib/plugins/sms/twilio/twilio.js b/lib/plugins/sms/twilio/twilio.js index eb9fb0c4..bdfc3843 100644 --- a/lib/plugins/sms/twilio/twilio.js +++ b/lib/plugins/sms/twilio/twilio.js @@ -45,6 +45,12 @@ function getLookup (account, number) { .fetch({ addOns: ['lamassu_ekata'] }) }) .then(info => info.addOns.results['lamassu_ekata']) + .then(info => { + if (info.status !== 'successful') { + throw new Error(`Twilio error: ${info.message}`) + } + return info + }) .catch(err => { if (_.includes(err.code, BAD_NUMBER_CODES)) { const badNumberError = new Error(err.message) diff --git a/new-lamassu-admin/src/pages/AddMachine/AddMachine.js b/new-lamassu-admin/src/pages/AddMachine/AddMachine.js index 5cc36b47..f74deff2 100644 --- a/new-lamassu-admin/src/pages/AddMachine/AddMachine.js +++ b/new-lamassu-admin/src/pages/AddMachine/AddMachine.js @@ -125,7 +125,11 @@ const validationSchema = Yup.object().shape({ .test( 'unique-name', 'Machine name is already in use.', - (value, context) => !context.options.context.machineNames.includes(value) + (value, context) => + !R.any( + it => R.equals(R.toLower(it), R.toLower(value)), + context.options.context.machineNames + ) ) }) diff --git a/new-lamassu-admin/src/pages/Analytics/Analytics.js b/new-lamassu-admin/src/pages/Analytics/Analytics.js index 21c96751..3f11a5bb 100644 --- a/new-lamassu-admin/src/pages/Analytics/Analytics.js +++ b/new-lamassu-admin/src/pages/Analytics/Analytics.js @@ -3,7 +3,7 @@ import { Box } from '@material-ui/core' import { makeStyles } from '@material-ui/core/styles' import classnames from 'classnames' import { endOfToday } from 'date-fns' -import { subDays } from 'date-fns/fp' +import { subDays, format, add, startOfWeek } from 'date-fns/fp' import gql from 'graphql-tag' import * as R from 'ramda' import React, { useState } from 'react' @@ -43,6 +43,16 @@ const TIME_OPTIONS = { month: MONTH } +const DAY_OPTIONS = R.map( + it => ({ + code: R.toLower(it), + display: it + }), + Array.from(Array(7)).map((_, i) => + format('EEEE', add({ days: i }, startOfWeek(new Date()))) + ) +) + const GET_TRANSACTIONS = gql` query transactions( $from: Date @@ -138,6 +148,9 @@ const Analytics = () => { const [representing, setRepresenting] = useState(REPRESENTING_OPTIONS[0]) const [period, setPeriod] = useState(PERIOD_OPTIONS[0]) const [machine, setMachine] = useState(MACHINE_OPTIONS[0]) + const [selectedDay, setSelectedDay] = useState( + R.equals(representing.code, 'hourOfTheDay') ? DAY_OPTIONS[0] : null + ) const loading = txLoading || configLoading @@ -179,15 +192,27 @@ const Analytics = () => { const filteredData = timeInterval => ({ current: - machineTxs.filter( - d => new Date(d.created) >= Date.now() - TIME_OPTIONS[timeInterval] - ) ?? [], + machineTxs.filter(d => { + const txDay = new Date(d.created) + const isSameWeekday = !R.isNil(selectedDay) + ? R.equals(R.toLower(format('EEEE', txDay)), selectedDay.code) + : true + + return isSameWeekday && txDay >= Date.now() - TIME_OPTIONS[timeInterval] + }) ?? [], previous: - machineTxs.filter( - d => - new Date(d.created) < Date.now() - TIME_OPTIONS[timeInterval] && - new Date(d.created) >= Date.now() - 2 * TIME_OPTIONS[timeInterval] - ) ?? [] + machineTxs.filter(d => { + const txDay = new Date(d.created) + const isSameWeekday = !R.isNil(selectedDay) + ? R.equals(R.toLower(format('EEEE', txDay)), selectedDay.code) + : true + + return ( + isSameWeekday && + txDay < Date.now() - TIME_OPTIONS[timeInterval] && + txDay >= Date.now() - 2 * TIME_OPTIONS[timeInterval] + ) + }) ?? [] }) const txs = { @@ -224,6 +249,13 @@ const Analytics = () => { ) } + const handleRepresentationChange = newRepresentation => { + setRepresenting(newRepresentation) + setSelectedDay( + R.equals(newRepresentation.code, 'hourOfTheDay') ? DAY_OPTIONS[0] : null + ) + } + const getGraphInfo = representing => { switch (representing.code) { case 'overTime': @@ -264,6 +296,9 @@ const Analytics = () => { machines={machineOptions} selectedMachine={machine} handleMachineChange={setMachine} + selectedDay={selectedDay} + dayOptions={DAY_OPTIONS} + handleDayChange={setSelectedDay} timezone={timezone} currency={fiatLocale} /> @@ -296,7 +331,7 @@ const Analytics = () => {
diff --git a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js
index 18cccd18..cbc79296 100644
--- a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js
+++ b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js
@@ -745,7 +745,7 @@ const RetrieveDataDialog = ({
{error && (
All set
@@ -82,8 +96,8 @@ const AllSet = ({ data: currentData, doContinue }) => {
titleLg
name="All set"
namespaces={[coin]}
- data={toNamespace(coin, R.omit('coin', currentData))}
- elements={getElements(cryptoCurrencies, accountsConfig, true)}
+ data={presentableData}
+ elements={presentableElements}
/>