feat: created the base skeleton for the Coin ATM Radar Setup screen (#355)
For now it doesn't have any functionality, CSS styling, or tables feat: added tables to the Coin ATM Radar screen No styles or icons yet. feat: added Edit links to the Coin ATM Radar Setup screen chore: added some TODOs to the Coin ATM Radar Setup screen refactor: make a function to render both Coin ATM Radar Setup tables feat: toggle function on table (not working on table content yet) feat: added toggle state to the Share Information switch feat: make the Share Information toggle change the tables contents feat: added a 'Help' link Later will be replaced by a '?' button with a pop-up help text. feat: added radio groups when in editing mode of Coin ATM Radar screen chore: replaced edit and help placeholders with proper buttons style: defined some CSS styles feat: added a help popper feat: enable radio change events, so they can be selected style: defined row styles for the radio button groups For now the help popper contains only a placeholder text, which must be replaced. refactor: replaced help and edit Links with Buttons fix: fixed the margin spacing for buttons style: added more spacing between before the share information Switch refactor: made a function to check a table element boolean value fix: changed some typography styles for titles (from TL2 to H4) style: added the alternating row style to the information tables style: added true and false table icons replacing the placeholder texts style: fixed the radio groups right margin refactor: renamed everything from CoinATMRadarSetup to CoinATMRadar feat: integrate share information switch with graphql api Still needs to finish the tables api integration. refactor: rename properties from 'show' to 'send' feat: integrate tables with graphql api feat: updated the coinatmradar module with the new config properties feat: added logic to show only currently available CAR config properties feat: disable the edit button when 'Share Information' is set to 'No' chore: replaced the lorem ipsum with the correct text on the help popup fix: fixed some css styling errors chore: added link to the CAR page on the corresponding button refactor: refactored the information table to make a component out of it refactor: changed the name of the 'active' property of the properties table to 'disabled' and inverted it's logic refactor: created a component from the boolean property table refactor: delete repeated styling code on the car page and it's table style: update styles to be in accordance with the guidelines refactor: rename properties to make them more concise fix: readded the old coinatmradar module and renamed the current one refactor: replaced ternary if with a coalescing operator fix: make the info table always visible, and it's values not dependent on the disabled status fix: move link style to jss refactor: simplify the use of car properties, and remove currently unused ones fix: put hooks on their correct places fix: when changing the value of the switch, update only it's own config fix: rename booleanPropertiesTable file so it starts with a capital letter. chore: readd removed properties on the car settings (all commented out) chore: integrated CAR settings page into Operator Info page fix: replaced broken white and disabled versions of the edit icon
This commit is contained in:
parent
fdf18b60ad
commit
b37a672157
12 changed files with 619 additions and 22 deletions
178
lib/coinatmradar/new-coinatmradar.js
Normal file
178
lib/coinatmradar/new-coinatmradar.js
Normal file
|
|
@ -0,0 +1,178 @@
|
||||||
|
const axios = require('axios')
|
||||||
|
const _ = require('lodash/fp')
|
||||||
|
const hkdf = require('futoin-hkdf')
|
||||||
|
|
||||||
|
const pify = require('pify')
|
||||||
|
const fs = pify(require('fs'))
|
||||||
|
|
||||||
|
const db = require('../db')
|
||||||
|
const mnemonicHelpers = require('../mnemonic-helpers')
|
||||||
|
const configManager = require('../config-manager')
|
||||||
|
const options = require('../options')
|
||||||
|
const logger = require('../logger')
|
||||||
|
const plugins = require('../plugins')
|
||||||
|
|
||||||
|
const TIMEOUT = 10000
|
||||||
|
const MAX_CONTENT_LENGTH = 2000
|
||||||
|
|
||||||
|
// How long a machine can be down before it's considered offline
|
||||||
|
const STALE_INTERVAL = '2 minutes'
|
||||||
|
|
||||||
|
module.exports = { update, mapRecord }
|
||||||
|
|
||||||
|
function mapCoin (info, deviceId, settings, cryptoCode) {
|
||||||
|
const config = info.config
|
||||||
|
const rates = plugins(settings, deviceId).buildRates(info.rates)[cryptoCode] || { cashIn: null, cashOut: null }
|
||||||
|
const cryptoConfig = configManager.scoped(cryptoCode, deviceId, config)
|
||||||
|
const unscoped = configManager.unscoped(config)
|
||||||
|
const showCommissions = unscoped.coinAtmRadar.sendCommissions
|
||||||
|
|
||||||
|
const cashInFee = showCommissions ? cryptoConfig.cashInCommission / 100 : null
|
||||||
|
const cashOutFee = showCommissions ? cryptoConfig.cashOutCommission / 100 : null
|
||||||
|
const cashInRate = showCommissions ? _.invoke('cashIn.toNumber', rates) : null
|
||||||
|
const cashOutRate = showCommissions ? _.invoke('cashOut.toNumber', rates) : null
|
||||||
|
|
||||||
|
return {
|
||||||
|
cryptoCode,
|
||||||
|
cashInFee,
|
||||||
|
cashOutFee,
|
||||||
|
cashInRate,
|
||||||
|
cashOutRate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapIdentification (info, deviceId) {
|
||||||
|
const machineConfig = configManager.machineScoped(deviceId, info.config)
|
||||||
|
|
||||||
|
return {
|
||||||
|
isPhone: machineConfig.smsVerificationActive,
|
||||||
|
isPalmVein: false,
|
||||||
|
isPhoto: false,
|
||||||
|
isIdDocScan: machineConfig.idCardDataVerificationActive,
|
||||||
|
isFingerprint: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapMachine (info, settings, machineRow) {
|
||||||
|
const deviceId = machineRow.device_id
|
||||||
|
const config = info.config
|
||||||
|
const unscoped = configManager.unscoped(config)
|
||||||
|
const machineConfig = configManager.machineScoped(deviceId, config)
|
||||||
|
|
||||||
|
const lastOnline = machineRow.last_online.toISOString()
|
||||||
|
const status = machineRow.stale ? 'online' : 'offline'
|
||||||
|
const showSupportedCryptocurrencies =
|
||||||
|
unscoped.coinAtmRadar.sendSupportedCryptocurrencies
|
||||||
|
const showSupportedFiat =
|
||||||
|
unscoped.coinAtmRadar.sendSupportedFiat
|
||||||
|
const showSupportedBuySellDirection =
|
||||||
|
unscoped.coinAtmRadar.sendSupportedBuySellDirection
|
||||||
|
const showLimitsAndVerification =
|
||||||
|
unscoped.coinAtmRadar.sendLimitsAndVerification
|
||||||
|
|
||||||
|
const cashLimit = showLimitsAndVerification ? (
|
||||||
|
machineConfig.hardLimitVerificationActive
|
||||||
|
? machineConfig.hardLimitVerificationThreshold
|
||||||
|
: Infinity ) : null
|
||||||
|
|
||||||
|
const cryptoCurrencies = machineConfig.cryptoCurrencies
|
||||||
|
const cashInEnabled = showSupportedBuySellDirection ? true : null
|
||||||
|
const cashOutEnabled = showSupportedBuySellDirection
|
||||||
|
? machineConfig.cashOutEnabled
|
||||||
|
: null
|
||||||
|
const fiat = showSupportedFiat ? machineConfig.fiatCurrency : null
|
||||||
|
const identification = mapIdentification(info, deviceId)
|
||||||
|
const coins = showSupportedCryptocurrencies ?
|
||||||
|
_.map(_.partial(mapCoin, [info, deviceId, settings]), cryptoCurrencies)
|
||||||
|
: null
|
||||||
|
|
||||||
|
return {
|
||||||
|
machineId: deviceId,
|
||||||
|
address: {
|
||||||
|
streetAddress: null,
|
||||||
|
city: null,
|
||||||
|
region: null,
|
||||||
|
postalCode: null,
|
||||||
|
country: null
|
||||||
|
},
|
||||||
|
location: {
|
||||||
|
name: null,
|
||||||
|
url: null,
|
||||||
|
phone: null
|
||||||
|
},
|
||||||
|
status,
|
||||||
|
lastOnline,
|
||||||
|
cashIn: cashInEnabled,
|
||||||
|
cashOut: cashOutEnabled,
|
||||||
|
manufacturer: 'lamassu',
|
||||||
|
cashInTxLimit: cashLimit,
|
||||||
|
cashOutTxLimit: cashLimit,
|
||||||
|
cashInDailyLimit: cashLimit,
|
||||||
|
cashOutDailyLimit: cashLimit,
|
||||||
|
fiatCurrency: fiat,
|
||||||
|
identification,
|
||||||
|
coins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getMachines (info, settings) {
|
||||||
|
const sql = `select device_id, last_online, now() - last_online < $1 as stale from devices
|
||||||
|
where display=TRUE and
|
||||||
|
paired=TRUE
|
||||||
|
order by created`
|
||||||
|
|
||||||
|
return db.any(sql, [STALE_INTERVAL])
|
||||||
|
.then(_.map(_.partial(mapMachine, [info, settings])))
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendRadar (data) {
|
||||||
|
const url = _.get(['coinAtmRadar', 'url'], options)
|
||||||
|
|
||||||
|
if (_.isEmpty(url)) {
|
||||||
|
return Promise.reject(new Error('Missing coinAtmRadar url!'))
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
url,
|
||||||
|
method: 'post',
|
||||||
|
data,
|
||||||
|
timeout: TIMEOUT,
|
||||||
|
maxContentLength: MAX_CONTENT_LENGTH
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('%j', data)
|
||||||
|
|
||||||
|
return axios(config)
|
||||||
|
.then(r => console.log(r.status))
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapRecord (info, settings) {
|
||||||
|
const timestamp = new Date().toISOString()
|
||||||
|
return Promise.all([getMachines(info, settings), fs.readFile(options.mnemonicPath, 'utf8')])
|
||||||
|
.then(([machines, mnemonic]) => {
|
||||||
|
return {
|
||||||
|
operatorId: computeOperatorId(mnemonicHelpers.toEntropyBuffer(mnemonic)),
|
||||||
|
operator: {
|
||||||
|
name: null,
|
||||||
|
phone: null,
|
||||||
|
email: null
|
||||||
|
},
|
||||||
|
timestamp,
|
||||||
|
machines
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function update (info, settings) {
|
||||||
|
const config = configManager.unscoped(info.config)
|
||||||
|
|
||||||
|
if (!config.coinAtmRadar.active) return Promise.resolve()
|
||||||
|
|
||||||
|
return mapRecord(info, settings)
|
||||||
|
.then(sendRadar)
|
||||||
|
.catch(err => logger.error(`Failure to update CoinATMRadar`, err))
|
||||||
|
}
|
||||||
|
|
||||||
|
function computeOperatorId (masterSeed) {
|
||||||
|
return hkdf(masterSeed, 16, { salt: 'lamassu-server-salt', info: 'operator-id' }).toString('hex')
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,112 @@
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import React, { useState, memo } from 'react'
|
||||||
|
|
||||||
|
import { H4 } from 'src/components/typography'
|
||||||
|
import { Link } from 'src/components/buttons'
|
||||||
|
import { RadioGroup } from 'src/components/inputs'
|
||||||
|
import { Table, TableBody, TableRow, TableCell } from 'src/components/table'
|
||||||
|
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
||||||
|
import { ReactComponent as EditIconDisabled } from 'src/styling/icons/action/edit/disabled.svg'
|
||||||
|
import { ReactComponent as TrueIcon } from 'src/styling/icons/table/true.svg'
|
||||||
|
import { ReactComponent as FalseIcon } from 'src/styling/icons/table/false.svg'
|
||||||
|
|
||||||
|
import { booleanPropertiesTableStyles } from './BooleanPropertiesTable.styles'
|
||||||
|
|
||||||
|
const useStyles = makeStyles(booleanPropertiesTableStyles)
|
||||||
|
|
||||||
|
const BooleanPropertiesTable = memo(
|
||||||
|
({ title, disabled, data, elements, save }) => {
|
||||||
|
const [editing, setEditing] = useState(false)
|
||||||
|
const [radioGroupValues, setRadioGroupValues] = useState(elements)
|
||||||
|
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
const innerSave = () => {
|
||||||
|
radioGroupValues.forEach(element => {
|
||||||
|
data[element.name] = element.value
|
||||||
|
})
|
||||||
|
|
||||||
|
save(data)
|
||||||
|
setEditing(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const innerCancel = () => {
|
||||||
|
setEditing(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleRadioButtons = (elementName, newValue) => {
|
||||||
|
setRadioGroupValues(
|
||||||
|
radioGroupValues.map(element =>
|
||||||
|
element.name === elementName
|
||||||
|
? { ...element, value: newValue }
|
||||||
|
: element
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const radioButtonOptions = [
|
||||||
|
{ label: 'Yes', value: true },
|
||||||
|
{ label: 'No', value: false }
|
||||||
|
]
|
||||||
|
|
||||||
|
if (!elements || radioGroupValues?.length === 0) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className={classes.booleanPropertiesTableWrapper}>
|
||||||
|
<div className={classes.rowWrapper}>
|
||||||
|
<H4>{title}</H4>
|
||||||
|
{editing ? (
|
||||||
|
<div className={classes.rightAligned}>
|
||||||
|
<Link onClick={innerCancel} color="secondary">
|
||||||
|
Cancel
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
className={classes.rightLink}
|
||||||
|
onClick={innerSave}
|
||||||
|
color="primary">
|
||||||
|
Save
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<div className={classes.transparentButton}>
|
||||||
|
<button disabled={disabled} onClick={() => setEditing(true)}>
|
||||||
|
{disabled ? <EditIconDisabled /> : <EditIcon />}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<Table className={classes.fillColumn}>
|
||||||
|
<TableBody className={classes.fillColumn}>
|
||||||
|
{radioGroupValues &&
|
||||||
|
radioGroupValues.map((element, idx) => (
|
||||||
|
<TableRow key={idx} size="sm" className={classes.tableRow}>
|
||||||
|
<TableCell className={classes.tableCell}>
|
||||||
|
{element.display}
|
||||||
|
{editing ? (
|
||||||
|
<RadioGroup
|
||||||
|
options={radioButtonOptions}
|
||||||
|
value={element.value}
|
||||||
|
onChange={event =>
|
||||||
|
handleRadioButtons(
|
||||||
|
element.name,
|
||||||
|
event.target.value === 'true'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
className={classes.radioButtons}
|
||||||
|
/>
|
||||||
|
) : element.value ? (
|
||||||
|
<TrueIcon />
|
||||||
|
) : (
|
||||||
|
<FalseIcon />
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
export default BooleanPropertiesTable
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
import baseStyles from 'src/pages/Logs.styles'
|
||||||
|
import { tableCellColor, zircon } from 'src/styling/variables'
|
||||||
|
|
||||||
|
const { fillColumn } = baseStyles
|
||||||
|
|
||||||
|
const booleanPropertiesTableStyles = {
|
||||||
|
booleanPropertiesTableWrapper: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'column',
|
||||||
|
width: 396
|
||||||
|
},
|
||||||
|
tableRow: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
'&:nth-child(even)': {
|
||||||
|
backgroundColor: tableCellColor
|
||||||
|
},
|
||||||
|
'&:nth-child(odd)': {
|
||||||
|
backgroundColor: zircon
|
||||||
|
},
|
||||||
|
boxShadow: '0 0 0 0 rgba(0, 0, 0, 0)'
|
||||||
|
},
|
||||||
|
tableCell: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'space-between',
|
||||||
|
width: '100%',
|
||||||
|
height: 32,
|
||||||
|
padding: [[5, 14, 5, 20]]
|
||||||
|
},
|
||||||
|
transparentButton: {
|
||||||
|
'& > *': {
|
||||||
|
margin: 'auto 12px'
|
||||||
|
},
|
||||||
|
'& button': {
|
||||||
|
border: 'none',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowWrapper: {
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
position: 'relative',
|
||||||
|
flex: 'wrap'
|
||||||
|
},
|
||||||
|
rightAligned: {
|
||||||
|
display: 'flex',
|
||||||
|
position: 'absolute',
|
||||||
|
right: 0
|
||||||
|
},
|
||||||
|
radioButtons: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
marginRight: -15
|
||||||
|
},
|
||||||
|
rightLink: {
|
||||||
|
marginLeft: '20px'
|
||||||
|
},
|
||||||
|
fillColumn,
|
||||||
|
popoverContent: {
|
||||||
|
width: 272,
|
||||||
|
padding: [[10, 15]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { booleanPropertiesTableStyles }
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import BooleanPropertiesTable from './BooleanPropertiesTable'
|
||||||
|
|
||||||
|
export { BooleanPropertiesTable }
|
||||||
|
|
@ -0,0 +1,193 @@
|
||||||
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
|
import React, { useState, memo } from 'react'
|
||||||
|
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||||
|
import { gql } from 'apollo-boost'
|
||||||
|
|
||||||
|
import { BooleanPropertiesTable } from 'src/components/booleanPropertiesTable'
|
||||||
|
import { H4, P, Label2 } from 'src/components/typography'
|
||||||
|
import { Button } from 'src/components/buttons'
|
||||||
|
import Popper from 'src/components/Popper'
|
||||||
|
import { Switch } from 'src/components/inputs'
|
||||||
|
import { ReactComponent as HelpIcon } from 'src/styling/icons/action/help/zodiac.svg'
|
||||||
|
|
||||||
|
import { mainStyles } from './CoinATMRadar.styles'
|
||||||
|
|
||||||
|
const useStyles = makeStyles(mainStyles)
|
||||||
|
|
||||||
|
const initialValues = {
|
||||||
|
active: false,
|
||||||
|
// location: false,
|
||||||
|
commissions: false,
|
||||||
|
supportedCryptocurrencies: false,
|
||||||
|
supportedFiat: false,
|
||||||
|
supportedBuySellDirection: false,
|
||||||
|
limitsAndVerification: false
|
||||||
|
// operatorName: false,
|
||||||
|
// operatorPhoneNumber: false,
|
||||||
|
// operatorEmail: false
|
||||||
|
}
|
||||||
|
|
||||||
|
const GET_CONFIG = gql`
|
||||||
|
{
|
||||||
|
config
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const SAVE_CONFIG = gql`
|
||||||
|
mutation Save($config: JSONObject) {
|
||||||
|
saveConfig(config: $config)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
const CoinATMRadar = memo(() => {
|
||||||
|
const [helpPopperAnchorEl, setHelpPopperAnchorEl] = useState(null)
|
||||||
|
const [coinAtmRadarConfig, setCoinAtmRadarConfig] = useState(null)
|
||||||
|
|
||||||
|
const classes = useStyles()
|
||||||
|
|
||||||
|
// TODO: treat errors on useMutation and useQuery
|
||||||
|
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||||
|
onCompleted: configResponse =>
|
||||||
|
setCoinAtmRadarConfig(configResponse.saveConfig.coinAtmRadar)
|
||||||
|
})
|
||||||
|
useQuery(GET_CONFIG, {
|
||||||
|
onCompleted: configResponse => {
|
||||||
|
setCoinAtmRadarConfig(
|
||||||
|
configResponse?.config?.coinAtmRadar ?? initialValues
|
||||||
|
)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const save = it => saveConfig({ variables: { config: { coinAtmRadar: it } } })
|
||||||
|
|
||||||
|
const handleOpenHelpPopper = event => {
|
||||||
|
setHelpPopperAnchorEl(helpPopperAnchorEl ? null : event.currentTarget)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseHelpPopper = () => {
|
||||||
|
setHelpPopperAnchorEl(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
const helpPopperOpen = Boolean(helpPopperAnchorEl)
|
||||||
|
|
||||||
|
if (!coinAtmRadarConfig) return null
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<div className={classes.rightAligned}>
|
||||||
|
<div className={classes.button}>
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href="https://coinatmradar.com/">
|
||||||
|
<Button>Coin ATM Radar page</Button>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.rowWrapper}>
|
||||||
|
<H4>Coin ATM Radar share settings</H4>
|
||||||
|
<div className={classes.transparentButton}>
|
||||||
|
<button onClick={handleOpenHelpPopper}>
|
||||||
|
<HelpIcon />
|
||||||
|
<Popper
|
||||||
|
open={helpPopperOpen}
|
||||||
|
anchorEl={helpPopperAnchorEl}
|
||||||
|
placement="bottom"
|
||||||
|
onClose={handleCloseHelpPopper}>
|
||||||
|
<div className={classes.popoverContent}>
|
||||||
|
<P>
|
||||||
|
For details on configuring this panel, please read the
|
||||||
|
relevant knowledgebase article{' '}
|
||||||
|
<a
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href="https://support.lamassu.is/hc/en-us/articles/360023720472-Coin-ATM-Radar">
|
||||||
|
here
|
||||||
|
</a>
|
||||||
|
.
|
||||||
|
</P>
|
||||||
|
</div>
|
||||||
|
</Popper>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className={classes.rowWrapper}>
|
||||||
|
<P>Share information?</P>
|
||||||
|
<div className={classes.switchWrapper}>
|
||||||
|
<Switch
|
||||||
|
checked={coinAtmRadarConfig.active}
|
||||||
|
onChange={event =>
|
||||||
|
save({
|
||||||
|
active: event.target.checked
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<Label2>{coinAtmRadarConfig.active ? 'Yes' : 'No'}</Label2>
|
||||||
|
</div>
|
||||||
|
<BooleanPropertiesTable
|
||||||
|
title={'Machine info'}
|
||||||
|
disabled={!coinAtmRadarConfig.active}
|
||||||
|
data={coinAtmRadarConfig}
|
||||||
|
elements={[
|
||||||
|
// {
|
||||||
|
// name: 'location',
|
||||||
|
// display: 'Location',
|
||||||
|
// value: coinAtmRadarConfig.location
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
name: 'commissions',
|
||||||
|
display: 'Commissions',
|
||||||
|
value: coinAtmRadarConfig.commissions
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'supportedCryptocurrencies',
|
||||||
|
display: 'Supported Cryptocurrencies',
|
||||||
|
value: coinAtmRadarConfig.supportedCryptocurrencies
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'supportedFiat',
|
||||||
|
display: 'Supported Fiat',
|
||||||
|
value: coinAtmRadarConfig.supportedFiat
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'supportedBuySellDirection',
|
||||||
|
display: 'Supported Buy Sell Direction',
|
||||||
|
value: coinAtmRadarConfig.supportedBuySellDirection
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'limitsAndVerification',
|
||||||
|
display: 'Limits And Verification',
|
||||||
|
value: coinAtmRadarConfig.limitsAndVerification
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
save={save}
|
||||||
|
/>
|
||||||
|
{/* <BooleanPropertiesTable
|
||||||
|
title={'Operator info'}
|
||||||
|
disabled={!coinAtmRadarConfig.active}
|
||||||
|
data={coinAtmRadarConfig}
|
||||||
|
elements={[
|
||||||
|
{
|
||||||
|
name: 'operatorName',
|
||||||
|
display: 'Operator Name',
|
||||||
|
value: coinAtmRadarConfig.operatorName
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'operatorPhoneNumber',
|
||||||
|
display: 'Operator Phone Number',
|
||||||
|
value: coinAtmRadarConfig.operatorPhoneNumber
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'operatorEmail',
|
||||||
|
display: 'Operator Email',
|
||||||
|
value: coinAtmRadarConfig.operatorEmail
|
||||||
|
}
|
||||||
|
]}
|
||||||
|
save={save}
|
||||||
|
/> */}
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
export default CoinATMRadar
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import baseStyles from 'src/pages/Logs.styles'
|
||||||
|
import { booleanPropertiesTableStyles } from 'src/components/booleanPropertiesTable/BooleanPropertiesTable.styles'
|
||||||
|
|
||||||
|
const { button } = baseStyles
|
||||||
|
const { rowWrapper, rightAligned } = booleanPropertiesTableStyles
|
||||||
|
|
||||||
|
const mainStyles = {
|
||||||
|
button,
|
||||||
|
transparentButton: {
|
||||||
|
'& > *': {
|
||||||
|
margin: 'auto 15px'
|
||||||
|
},
|
||||||
|
'& button': {
|
||||||
|
border: 'none',
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
cursor: 'pointer'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
rowWrapper,
|
||||||
|
switchWrapper: {
|
||||||
|
display: 'flex',
|
||||||
|
marginLeft: 120
|
||||||
|
},
|
||||||
|
rightAligned,
|
||||||
|
popoverContent: {
|
||||||
|
width: 272,
|
||||||
|
padding: [[10, 15]]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { mainStyles }
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
import CoinATMRadar from './CoinATMRadar'
|
||||||
|
|
||||||
|
export default CoinATMRadar
|
||||||
|
|
@ -7,6 +7,7 @@ import Title from 'src/components/Title'
|
||||||
|
|
||||||
import logsStyles from '../Logs.styles'
|
import logsStyles from '../Logs.styles'
|
||||||
|
|
||||||
|
import CoinAtmRadar from './CoinATMRadar'
|
||||||
import ContactInfo from './ContactInfo'
|
import ContactInfo from './ContactInfo'
|
||||||
|
|
||||||
const localStyles = {
|
const localStyles = {
|
||||||
|
|
@ -49,6 +50,7 @@ const OperatorInfo = () => {
|
||||||
/>
|
/>
|
||||||
<div className={classes.contentWrapper}>
|
<div className={classes.contentWrapper}>
|
||||||
{isSelected(CONTACT_INFORMATION) && <ContactInfo />}
|
{isSelected(CONTACT_INFORMATION) && <ContactInfo />}
|
||||||
|
{isSelected(COIN_ATM_RADAR) && <CoinAtmRadar />}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
|
<!-- Generator: Sketch 62 (91390) - https://sketch.com -->
|
||||||
<title>icon/action/edit/disabled</title>
|
<title>icon/action/edit/disabled</title>
|
||||||
<desc>Created with Sketch.</desc>
|
<desc>Created with Sketch.</desc>
|
||||||
<defs>
|
<g id="icon/action/edit/disabled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<rect id="path-1" x="0" y="0" width="22" height="22"></rect>
|
<path d="M1,18 L1,18 C1,19.657 2.343,21 4,21 L18,21 C19.657,21 21,19.657 21,18" id="Stroke-1" stroke="#9B9B9B" stroke-width="2"></path>
|
||||||
</defs>
|
<polygon id="Stroke-3" stroke="#9B9B9B" stroke-width="2" points="6 12 17 1 21 5 10 16 6 16"></polygon>
|
||||||
<g id="icon/action/edit/disabled" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<mask id="mask-2" fill="white">
|
|
||||||
<use xlink:href="#path-1"></use>
|
|
||||||
</mask>
|
|
||||||
<g id="Background"></g>
|
|
||||||
<path d="M1,18 L1,18 C1,19.657 2.343,21 4,21 L18,21 C19.657,21 21,19.657 21,18" id="Stroke-1" stroke="#9B9B9B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)"></path>
|
|
||||||
<polygon id="Stroke-3" stroke="#9B9B9B" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)" points="6 12 17 1 21 5 10 16 6 16"></polygon>
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 749 B |
|
|
@ -1,17 +1,10 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg width="22px" height="22px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<!-- Generator: Sketch 60.1 (88133) - https://sketch.com -->
|
<!-- Generator: Sketch 62 (91390) - https://sketch.com -->
|
||||||
<title>icon/action/edit/white</title>
|
<title>icon/action/edit/white</title>
|
||||||
<desc>Created with Sketch.</desc>
|
<desc>Created with Sketch.</desc>
|
||||||
<defs>
|
<g id="icon/action/edit/white" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
|
||||||
<rect id="path-1" x="0" y="0" width="22" height="22"></rect>
|
<path d="M1,18 L1,18 C1,19.657 2.343,21 4,21 L18,21 C19.657,21 21,19.657 21,18" id="Stroke-1" stroke="#FFFFFF" stroke-width="2"></path>
|
||||||
</defs>
|
<polygon id="Stroke-3" stroke="#FFFFFF" stroke-width="2" points="6 12 17 1 21 5 10 16 6 16"></polygon>
|
||||||
<g id="icon/action/edit/white" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
|
||||||
<mask id="mask-2" fill="white">
|
|
||||||
<use xlink:href="#path-1"></use>
|
|
||||||
</mask>
|
|
||||||
<g id="Background"></g>
|
|
||||||
<path d="M1,18 L1,18 C1,19.657 2.343,21 4,21 L18,21 C19.657,21 21,19.657 21,18" id="Stroke-1" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)"></path>
|
|
||||||
<polygon id="Stroke-3" stroke="#FFFFFF" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" mask="url(#mask-2)" points="6 12 17 1 21 5 10 16 6 16"></polygon>
|
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
Before Width: | Height: | Size: 1 KiB After Width: | Height: | Size: 743 B |
12
new-lamassu-admin/src/styling/icons/table/false.svg
Normal file
12
new-lamassu-admin/src/styling/icons/table/false.svg
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
|
||||||
|
<title>icon/table/false</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<g id="icon/table/false" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="Group-4" stroke="#FF584A" stroke-width="4">
|
||||||
|
<line x1="13.5" y1="0.5" x2="0.995667" y2="13.004333" id="Line-7"></line>
|
||||||
|
<line x1="13.5" y1="0.5" x2="0.995667" y2="13.004333" id="Line-7" transform="translate(7.000000, 7.000000) scale(-1, 1) translate(-7.000000, -7.000000) "></line>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 763 B |
9
new-lamassu-admin/src/styling/icons/table/true.svg
Normal file
9
new-lamassu-admin/src/styling/icons/table/true.svg
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="16px" height="14px" viewBox="0 0 16 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<!-- Generator: Sketch 61.2 (89653) - https://sketch.com -->
|
||||||
|
<title>icon/table/true</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<g id="icon/table/true" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<path d="M4.17451294,13.3251347 L0.599425104,9.29667256 C-0.199808368,8.3960844 -0.199808368,6.94040225 0.599425104,6.03981409 C1.39865858,5.13922593 2.69051421,5.13922593 3.48974768,6.03981409 L5.61967423,8.439847 L12.5102523,0.675441122 C13.3094858,-0.225147041 14.6033855,-0.225147041 15.4005749,0.675441122 C16.1998084,1.57372599 16.1998084,3.03171143 15.4005749,3.93229959 L7.06483552,13.3251347 C6.66624082,13.7742771 6.14295752,14 5.61967423,14 C5.09639093,14 4.57310763,13.7742771 4.17451294,13.3251347 Z" id="Fill-1" fill="#48F694"></path>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 986 B |
Loading…
Add table
Add a link
Reference in a new issue