chore: pazuz removal
This commit is contained in:
parent
770fa13ea0
commit
f936386712
21 changed files with 14 additions and 1477 deletions
|
|
@ -20,7 +20,6 @@ const buildApolloContext = async ({ req, res }) => {
|
|||
req.session.user.role = user.role
|
||||
|
||||
res.set('lamassu_role', user.role)
|
||||
res.cookie('pazuz_operatoridentifier', base64.encode(user.username))
|
||||
res.set('Access-Control-Expose-Headers', 'lamassu_role')
|
||||
|
||||
return { req, res }
|
||||
|
|
|
|||
|
|
@ -2,4 +2,3 @@ SKIP_PREFLIGHT_CHECK=true
|
|||
HTTPS=true
|
||||
REACT_APP_TYPE_CHECK_SANCTUARY=false
|
||||
PORT=3001
|
||||
REACT_APP_BUILD_TARGET=LAMASSU
|
||||
|
|
|
|||
|
|
@ -92,9 +92,7 @@
|
|||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject",
|
||||
"postinstall": "patch-package",
|
||||
"lamassu": "REACT_APP_BUILD_TARGET=LAMASSU react-scripts start",
|
||||
"pazuz": "REACT_APP_BUILD_TARGET=PAZUZ react-scripts start"
|
||||
"postinstall": "patch-package"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
|
|
|
|||
|
|
@ -2,30 +2,10 @@ import React from 'react'
|
|||
import ReactDOM from 'react-dom'
|
||||
|
||||
import App from './App'
|
||||
import * as serviceWorker from './serviceWorker'
|
||||
|
||||
function checkBuildTarget() {
|
||||
const buildTarget = process.env.REACT_APP_BUILD_TARGET
|
||||
|
||||
if (buildTarget !== 'LAMASSU' && buildTarget !== 'PAZUZ') {
|
||||
return Promise.reject(
|
||||
new Error('No such build target: ' + process.env.REACT_APP_BUILD_TARGET)
|
||||
)
|
||||
}
|
||||
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
checkBuildTarget().then(() =>
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
document.getElementById('root')
|
||||
)
|
||||
)
|
||||
|
||||
// If you want your app to work offline and load faster, you can change
|
||||
// unregister() to register() below. Note this comes with some pitfalls.
|
||||
// Learn more about service workers: https://bit.ly/CRA-PWA
|
||||
serviceWorker.unregister()
|
||||
|
|
|
|||
|
|
@ -1,258 +0,0 @@
|
|||
import { useQuery } from '@apollo/react-hooks'
|
||||
import { Paper } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import classnames from 'classnames'
|
||||
import gql from 'graphql-tag'
|
||||
import * as R from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
|
||||
import AppContext from 'src/AppContext'
|
||||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import { H3, Info2, Label2, Label3, P } from 'src/components/typography'
|
||||
import { ReactComponent as BitcoinLogo } from 'src/styling/logos/icon-bitcoin-colour.svg'
|
||||
import { ReactComponent as BitcoinCashLogo } from 'src/styling/logos/icon-bitcoincash-colour.svg'
|
||||
import { ReactComponent as DashLogo } from 'src/styling/logos/icon-dash-colour.svg'
|
||||
import { ReactComponent as EthereumLogo } from 'src/styling/logos/icon-ethereum-colour.svg'
|
||||
import { ReactComponent as LitecoinLogo } from 'src/styling/logos/icon-litecoin-colour.svg'
|
||||
import { ReactComponent as ZCashLogo } from 'src/styling/logos/icon-zcash-colour.svg'
|
||||
import { numberToFiatAmount, numberToCryptoAmount } from 'src/utils/number'
|
||||
|
||||
import styles from './ATMWallet.styles'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const GET_OPERATOR_BY_USERNAME = gql`
|
||||
query operatorByUsername($username: String) {
|
||||
operatorByUsername(username: $username) {
|
||||
id
|
||||
entityId
|
||||
name
|
||||
fiatBalances
|
||||
cryptoBalances
|
||||
machines
|
||||
joined
|
||||
assets
|
||||
preferredFiatCurrency
|
||||
contactInfo {
|
||||
name
|
||||
email
|
||||
}
|
||||
fundings {
|
||||
id
|
||||
origin
|
||||
destination
|
||||
fiatAmount
|
||||
fiatBalanceAfter
|
||||
fiatCurrency
|
||||
created
|
||||
status
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const CHIPS_PER_ROW = 6
|
||||
|
||||
const Assets = ({ balance, wallets, currency }) => {
|
||||
const classes = useStyles({ numberOfChips: CHIPS_PER_ROW })
|
||||
|
||||
const walletFiatSum = R.sum(R.map(it => it.fiatValue, wallets))
|
||||
const totalValue = BigNumber(balance)
|
||||
.plus(walletFiatSum)
|
||||
.toNumber()
|
||||
|
||||
return (
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<div className={classes.totalAssetFieldWrapper}>
|
||||
<P className={classes.fieldHeader}>Available balance</P>
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<Info2 noMargin className={classes.fieldValue}>
|
||||
{numberToFiatAmount(balance)}
|
||||
</Info2>
|
||||
<Info2 noMargin className={classes.fieldCurrency}>
|
||||
{R.toUpper(currency)}
|
||||
</Info2>
|
||||
</div>
|
||||
</div>
|
||||
<Info2 className={classes.separator}>+</Info2>
|
||||
<div className={classes.totalAssetFieldWrapper}>
|
||||
<P className={classes.fieldHeader}>Total balance in wallets</P>
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<Info2 noMargin className={classes.fieldValue}>
|
||||
{numberToFiatAmount(walletFiatSum)}
|
||||
</Info2>
|
||||
<Info2 noMargin className={classes.fieldCurrency}>
|
||||
{R.toUpper(currency)}
|
||||
</Info2>
|
||||
</div>
|
||||
</div>
|
||||
<Info2 className={classes.separator}>=</Info2>
|
||||
<div className={classes.totalAssetFieldWrapper}>
|
||||
<P className={classes.fieldHeader}>Total assets</P>
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<Info2 noMargin className={classes.fieldValue}>
|
||||
{numberToFiatAmount(totalValue)}
|
||||
</Info2>
|
||||
<Info2 noMargin className={classes.fieldCurrency}>
|
||||
{R.toUpper(currency)}
|
||||
</Info2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const WalletInfoChip = ({ wallet, currency }) => {
|
||||
const classes = useStyles({ numberOfChips: CHIPS_PER_ROW })
|
||||
|
||||
const getLogo = cryptoCode => {
|
||||
switch (cryptoCode) {
|
||||
case 'BTC':
|
||||
return <BitcoinLogo className={classes.logo} />
|
||||
case 'ETH':
|
||||
return <EthereumLogo className={classes.logo} />
|
||||
case 'LTC':
|
||||
return <LitecoinLogo className={classes.logo} />
|
||||
case 'ZEC':
|
||||
return (
|
||||
<ZCashLogo className={classnames(classes.logo, classes.zecLogo)} />
|
||||
)
|
||||
case 'BCH':
|
||||
return (
|
||||
<BitcoinCashLogo
|
||||
className={classnames(classes.logo, classes.bchLogo)}
|
||||
/>
|
||||
)
|
||||
case 'DASH':
|
||||
return <DashLogo className={classes.logo} />
|
||||
default:
|
||||
return <BitcoinLogo className={classes.logo} />
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.walletChipWrapper}>
|
||||
<Paper className={classes.walletChip}>
|
||||
<div className={classes.walletHeader}>
|
||||
{getLogo(wallet.cryptoCode)}
|
||||
<Label3 className={classes.hedgedText}>
|
||||
{wallet.isHedged ? 'Hedged' : 'Not hedged'}
|
||||
</Label3>
|
||||
</div>
|
||||
<div className={classes.walletValueWrapper}>
|
||||
<Label2 className={classes.fieldHeader}>{wallet.name} value</Label2>
|
||||
<Label2 className={classes.walletValue}>
|
||||
{numberToCryptoAmount(wallet.amount)} {wallet.cryptoCode}
|
||||
</Label2>
|
||||
<Label2 className={classes.fieldHeader}>Hedged value</Label2>
|
||||
<Label2 className={classes.walletValue}>
|
||||
{numberToFiatAmount(wallet.hedgedFiatValue)} {currency}
|
||||
</Label2>
|
||||
</div>
|
||||
</Paper>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const ATMWallet = () => {
|
||||
const classes = useStyles({ numberOfChips: CHIPS_PER_ROW })
|
||||
const { userData } = useContext(AppContext)
|
||||
|
||||
const { data, loading } = useQuery(GET_OPERATOR_BY_USERNAME, {
|
||||
context: { clientName: 'pazuz' },
|
||||
variables: { username: userData?.username }
|
||||
})
|
||||
|
||||
const operatorData = R.path(['operatorByUsername'], data)
|
||||
|
||||
const wallets = [
|
||||
{
|
||||
cryptoCode: 'BTC',
|
||||
name: 'Bitcoin',
|
||||
amount: operatorData?.cryptoBalances.xbt ?? 0,
|
||||
fiatValue: operatorData?.assets.values.cryptoBalancesInFiat.xbt ?? 0,
|
||||
hedgedFiatValue: operatorData?.assets.values.hedgedContracts.xbt ?? 0,
|
||||
isHedged: BigNumber(operatorData?.assets.values.hedgedCrypto.xbt ?? 0).gt(
|
||||
0
|
||||
)
|
||||
},
|
||||
{
|
||||
cryptoCode: 'ETH',
|
||||
name: 'Ethereum',
|
||||
amount: operatorData?.cryptoBalances.eth ?? 0,
|
||||
fiatValue: operatorData?.assets.values.cryptoBalancesInFiat.eth ?? 0,
|
||||
hedgedFiatValue: operatorData?.assets.values.hedgedContracts.eth ?? 0,
|
||||
isHedged: BigNumber(operatorData?.assets.values.hedgedCrypto.eth ?? 0).gt(
|
||||
0
|
||||
)
|
||||
},
|
||||
{
|
||||
cryptoCode: 'LTC',
|
||||
name: 'Litecoin',
|
||||
amount: operatorData?.cryptoBalances.ltc ?? 0,
|
||||
fiatValue: operatorData?.assets.values.cryptoBalancesInFiat.ltc ?? 0,
|
||||
hedgedFiatValue: operatorData?.assets.values.hedgedContracts.ltc ?? 0,
|
||||
isHedged: BigNumber(operatorData?.assets.values.hedgedCrypto.ltc ?? 0).gt(
|
||||
0
|
||||
)
|
||||
},
|
||||
{
|
||||
cryptoCode: 'ZEC',
|
||||
name: 'Zcash',
|
||||
amount: operatorData?.cryptoBalances.zec ?? 0,
|
||||
fiatValue: operatorData?.assets.values.cryptoBalancesInFiat.zec ?? 0,
|
||||
hedgedFiatValue: operatorData?.assets.values.hedgedContracts.zec ?? 0,
|
||||
isHedged: BigNumber(operatorData?.assets.values.hedgedCrypto.zec ?? 0).gt(
|
||||
0
|
||||
)
|
||||
},
|
||||
{
|
||||
cryptoCode: 'BCH',
|
||||
name: 'Bitcoin Cash',
|
||||
amount: operatorData?.cryptoBalances.bch ?? 0,
|
||||
fiatValue: operatorData?.assets.values.cryptoBalancesInFiat.bch ?? 0,
|
||||
hedgedFiatValue: operatorData?.assets.values.hedgedContracts.bch ?? 0,
|
||||
isHedged: BigNumber(operatorData?.assets.values.hedgedCrypto.bch ?? 0).gt(
|
||||
0
|
||||
)
|
||||
},
|
||||
{
|
||||
cryptoCode: 'DASH',
|
||||
name: 'Dash',
|
||||
amount: operatorData?.cryptoBalances.dash ?? 0,
|
||||
fiatValue: operatorData?.assets.values.cryptoBalancesInFiat.dash ?? 0,
|
||||
hedgedFiatValue: operatorData?.assets.values.hedgedContracts.dash ?? 0,
|
||||
isHedged: BigNumber(
|
||||
operatorData?.assets.values.hedgedCrypto.dash ?? 0
|
||||
).gt(0)
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
!loading && (
|
||||
<>
|
||||
<TitleSection title="ATM Wallets" />
|
||||
<Assets
|
||||
balance={
|
||||
operatorData?.fiatBalances[operatorData.preferredFiatCurrency] ?? 0
|
||||
}
|
||||
wallets={wallets}
|
||||
currency={operatorData?.preferredFiatCurrency ?? ''}
|
||||
/>
|
||||
<H3 className={classes.walletChipTitle}>ATM Wallets</H3>
|
||||
<div className={classes.walletChipList}>
|
||||
{R.map(
|
||||
it => (
|
||||
<WalletInfoChip wallet={it} currency={'USD'} />
|
||||
),
|
||||
wallets
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default ATMWallet
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
import { offColor } from 'src/styling/variables'
|
||||
|
||||
const styles = ({ numberOfChips }) => ({
|
||||
totalAssetWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
totalAssetFieldWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
fieldHeader: {
|
||||
color: offColor,
|
||||
marginBottom: 5
|
||||
},
|
||||
fieldValue: {
|
||||
fontSize: 36
|
||||
},
|
||||
fieldCurrency: {
|
||||
fontSize: 20,
|
||||
alignSelf: 'flex-end',
|
||||
margin: [[0, 0, 5, 5]]
|
||||
},
|
||||
separator: {
|
||||
fontSize: 32,
|
||||
alignSelf: 'center',
|
||||
margin: [[25, 20, 0, 20]]
|
||||
},
|
||||
walletChipList: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexWrap: 'wrap'
|
||||
},
|
||||
walletChipWrapper: {
|
||||
flexGrow: 0,
|
||||
flexShrink: 0,
|
||||
flexBasis: `16.66667%`,
|
||||
'&:nth-child(6n+1)': {
|
||||
'& > div': {
|
||||
margin: [[0, 10, 0, 0]]
|
||||
}
|
||||
},
|
||||
'&:nth-child(6n)': {
|
||||
'& > div': {
|
||||
margin: [[0, 0, 0, 10]]
|
||||
}
|
||||
},
|
||||
margin: [[10, 0]]
|
||||
},
|
||||
walletChip: {
|
||||
height: 200,
|
||||
margin: [[0, 10]]
|
||||
},
|
||||
walletHeader: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'space-between',
|
||||
height: 50
|
||||
},
|
||||
logo: {
|
||||
transform: `scale(0.4, 0.4)`,
|
||||
height: 80,
|
||||
maxWidth: 110,
|
||||
margin: [[-14, 0, 0, -26]]
|
||||
},
|
||||
zecLogo: {
|
||||
margin: [[-15, 0, 0, -10]]
|
||||
},
|
||||
bchLogo: {
|
||||
margin: [[-12, 0, 0, -18]]
|
||||
},
|
||||
hedgedText: {
|
||||
color: offColor,
|
||||
margin: [[13, 12, 0, 0]]
|
||||
},
|
||||
walletValueWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
margin: [[0, 0, 0, 15]]
|
||||
},
|
||||
walletValue: {
|
||||
fontSize: 18,
|
||||
margin: [[0, 0, 10, 0]]
|
||||
},
|
||||
walletChipTitle: {
|
||||
marginTop: 50
|
||||
}
|
||||
})
|
||||
|
||||
export default styles
|
||||
|
|
@ -1,203 +0,0 @@
|
|||
import { useQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import BigNumber from 'bignumber.js'
|
||||
import gql from 'graphql-tag'
|
||||
import * as R from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
|
||||
import AppContext from 'src/AppContext'
|
||||
import { HelpTooltip } from 'src/components/Tooltip'
|
||||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
import { H4, Info2, P } from 'src/components/typography'
|
||||
import { numberToFiatAmount } from 'src/utils/number'
|
||||
import { formatDate } from 'src/utils/timezones'
|
||||
|
||||
import styles from './Accounting.styles'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const GET_OPERATOR_BY_USERNAME = gql`
|
||||
query operatorByUsername($username: String) {
|
||||
operatorByUsername(username: $username) {
|
||||
id
|
||||
entityId
|
||||
name
|
||||
fiatBalances
|
||||
cryptoBalances
|
||||
machines
|
||||
joined
|
||||
assets
|
||||
preferredFiatCurrency
|
||||
contactInfo {
|
||||
name
|
||||
email
|
||||
}
|
||||
fundings {
|
||||
id
|
||||
origin
|
||||
destination
|
||||
fiatAmount
|
||||
fiatBalanceAfter
|
||||
fiatCurrency
|
||||
created
|
||||
status
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const GET_DATA = gql`
|
||||
query getData {
|
||||
config
|
||||
}
|
||||
`
|
||||
|
||||
const Assets = ({ balance, hedgingReserve, currency }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
return (
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<div className={classes.totalAssetFieldWrapper}>
|
||||
<P className={classes.fieldHeader}>Pazuz fiat balance</P>
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<Info2 noMargin className={classes.fieldValue}>
|
||||
{numberToFiatAmount(balance)}
|
||||
</Info2>
|
||||
<Info2 noMargin className={classes.fieldCurrency}>
|
||||
{R.toUpper(currency)}
|
||||
</Info2>
|
||||
</div>
|
||||
</div>
|
||||
<Info2 className={classes.separator}>-</Info2>
|
||||
<div className={classes.totalAssetFieldWrapper}>
|
||||
<P className={classes.fieldHeader}>Hedging reserve</P>
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<Info2 noMargin className={classes.fieldValue}>
|
||||
{numberToFiatAmount(hedgingReserve)}
|
||||
</Info2>
|
||||
<Info2 noMargin className={classes.fieldCurrency}>
|
||||
{R.toUpper(currency)}
|
||||
</Info2>
|
||||
</div>
|
||||
</div>
|
||||
<Info2 className={classes.separator}>=</Info2>
|
||||
<div className={classes.totalAssetFieldWrapper}>
|
||||
<P className={classes.fieldHeader}>Available balance</P>
|
||||
<div className={classes.totalAssetWrapper}>
|
||||
<Info2 noMargin className={classes.fieldValue}>
|
||||
{numberToFiatAmount(balance - hedgingReserve)}
|
||||
</Info2>
|
||||
<Info2 noMargin className={classes.fieldCurrency}>
|
||||
{R.toUpper(currency)}
|
||||
</Info2>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
const Accounting = () => {
|
||||
const classes = useStyles()
|
||||
const { userData } = useContext(AppContext)
|
||||
|
||||
const { data: opData, loading: operatorLoading } = useQuery(
|
||||
GET_OPERATOR_BY_USERNAME,
|
||||
{
|
||||
context: { clientName: 'pazuz' },
|
||||
variables: { username: userData?.username }
|
||||
}
|
||||
)
|
||||
|
||||
const { data: configResponse, loading: configLoading } = useQuery(GET_DATA)
|
||||
const timezone = R.path(['config', 'locale_timezone'], configResponse)
|
||||
|
||||
const loading = operatorLoading || configLoading
|
||||
|
||||
const operatorData = R.path(['operatorByUsername'], opData)
|
||||
|
||||
const elements = [
|
||||
{
|
||||
header: 'Operation',
|
||||
width: 500,
|
||||
size: 'sm',
|
||||
textAlign: 'left',
|
||||
view: it => {
|
||||
return (
|
||||
<span className={classes.operation}>
|
||||
{it.description}
|
||||
{!!it.extraInfo && (
|
||||
<HelpTooltip width={175}>
|
||||
<P>{it.extraInfo}</P>
|
||||
</HelpTooltip>
|
||||
)}
|
||||
</span>
|
||||
)
|
||||
}
|
||||
},
|
||||
{
|
||||
header: 'Amount',
|
||||
width: 147,
|
||||
size: 'sm',
|
||||
textAlign: 'right',
|
||||
view: it =>
|
||||
`${numberToFiatAmount(it.fiatAmount)} ${R.toUpper(it.fiatCurrency)}`
|
||||
},
|
||||
{
|
||||
header: 'Balance after operation',
|
||||
width: 250,
|
||||
size: 'sm',
|
||||
textAlign: 'right',
|
||||
view: it =>
|
||||
`${numberToFiatAmount(it.fiatBalanceAfter)} ${R.toUpper(
|
||||
it.fiatCurrency
|
||||
)}`
|
||||
},
|
||||
{
|
||||
header: 'Date',
|
||||
width: 150,
|
||||
size: 'sm',
|
||||
textAlign: 'right',
|
||||
view: it => formatDate(it.created, timezone, 'yyyy-MM-dd')
|
||||
},
|
||||
{
|
||||
header: 'Time',
|
||||
width: 150,
|
||||
size: 'sm',
|
||||
textAlign: 'right',
|
||||
view: it => formatDate(it.created, timezone, 'yyyy-MM-dd')
|
||||
}
|
||||
]
|
||||
|
||||
const hedgingReserve = BigNumber(
|
||||
R.reduce(
|
||||
(acc, value) => acc.plus(value),
|
||||
BigNumber(0),
|
||||
R.values(operatorData?.assets.values.hedgedContracts) ?? []
|
||||
) ?? 0
|
||||
).toNumber()
|
||||
|
||||
return (
|
||||
!loading && (
|
||||
<>
|
||||
<TitleSection title="Accounting" />
|
||||
<Assets
|
||||
balance={operatorData?.assets.total ?? 0}
|
||||
hedgingReserve={hedgingReserve}
|
||||
currency={operatorData?.preferredFiatCurrency ?? ''}
|
||||
/>
|
||||
<H4 className={classes.tableTitle}>Fiat balance history</H4>
|
||||
<DataTable
|
||||
loading={loading}
|
||||
emptyText="No transactions so far"
|
||||
elements={elements}
|
||||
data={operatorData?.fundings ?? []}
|
||||
rowSize="sm"
|
||||
/>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default Accounting
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
import { offColor } from 'src/styling/variables'
|
||||
|
||||
const styles = () => ({
|
||||
totalAssetWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row'
|
||||
},
|
||||
totalAssetFieldWrapper: {
|
||||
display: 'flex',
|
||||
flexDirection: 'column'
|
||||
},
|
||||
fieldHeader: {
|
||||
color: offColor,
|
||||
marginBottom: 5
|
||||
},
|
||||
fieldValue: {
|
||||
fontSize: 36
|
||||
},
|
||||
fieldCurrency: {
|
||||
fontSize: 20,
|
||||
alignSelf: 'flex-end',
|
||||
margin: [[0, 0, 5, 5]]
|
||||
},
|
||||
separator: {
|
||||
fontSize: 32,
|
||||
alignSelf: 'center',
|
||||
margin: [[25, 20, 0, 20]]
|
||||
},
|
||||
tableTitle: {
|
||||
marginTop: 35
|
||||
},
|
||||
operation: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center'
|
||||
}
|
||||
})
|
||||
|
||||
export default styles
|
||||
|
|
@ -1,258 +0,0 @@
|
|||
import { useQuery } from '@apollo/react-hooks'
|
||||
import Grid from '@material-ui/core/Grid'
|
||||
import Table from '@material-ui/core/Table'
|
||||
import TableBody from '@material-ui/core/TableBody'
|
||||
import TableCell from '@material-ui/core/TableCell'
|
||||
import TableContainer from '@material-ui/core/TableContainer'
|
||||
import TableHead from '@material-ui/core/TableHead'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import { makeStyles, withStyles } from '@material-ui/core/styles'
|
||||
import gql from 'graphql-tag'
|
||||
import * as R from 'ramda'
|
||||
import React, { useContext } from 'react'
|
||||
|
||||
import AppContext from 'src/AppContext'
|
||||
import TitleSection from 'src/components/layout/TitleSection'
|
||||
import { H4, Label2, P, Info2 } from 'src/components/typography'
|
||||
import { numberToFiatAmount } from 'src/utils/number'
|
||||
|
||||
import styles from './Assets.styles'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const GET_OPERATOR_BY_USERNAME = gql`
|
||||
query operatorByUsername($username: String) {
|
||||
operatorByUsername(username: $username) {
|
||||
id
|
||||
entityId
|
||||
name
|
||||
fiatBalances
|
||||
cryptoBalances
|
||||
machines
|
||||
joined
|
||||
assets
|
||||
preferredFiatCurrency
|
||||
contactInfo {
|
||||
name
|
||||
email
|
||||
}
|
||||
fundings {
|
||||
id
|
||||
origin
|
||||
destination
|
||||
fiatAmount
|
||||
fiatBalanceAfter
|
||||
fiatCurrency
|
||||
created
|
||||
status
|
||||
description
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const cellStyling = {
|
||||
borderBottom: '4px solid white',
|
||||
padding: 0,
|
||||
paddingLeft: 20,
|
||||
paddingRight: 20
|
||||
}
|
||||
|
||||
const Cell = withStyles({
|
||||
root: cellStyling
|
||||
})(TableCell)
|
||||
|
||||
const HeaderCell = withStyles({
|
||||
root: {
|
||||
...cellStyling,
|
||||
backgroundColor: 'white'
|
||||
}
|
||||
})(TableCell)
|
||||
|
||||
const AssetsAmountTable = ({ title, data = [], numToRender }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const totalAmount = R.compose(R.sum, R.map(R.path(['amount'])))(data) ?? 0
|
||||
const currency = data[0]?.currency ?? ''
|
||||
const selectAmountPrefix = it =>
|
||||
it.direction === 'in' ? '+' : R.isNil(it.direction) ? '' : '-'
|
||||
|
||||
return (
|
||||
<>
|
||||
<Grid item className={classes.card} xs={12}>
|
||||
<H4 className={classes.h4}>{title}</H4>
|
||||
<TableContainer>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
<HeaderCell>
|
||||
<div className={classes.asset}>
|
||||
<Label2 className={classes.label}>Asset</Label2>
|
||||
</div>
|
||||
</HeaderCell>
|
||||
<HeaderCell>
|
||||
<div className={classes.amount}>
|
||||
<Label2 className={classes.label}>Amount</Label2>
|
||||
</div>
|
||||
</HeaderCell>
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
{data?.map((asset, idx) => {
|
||||
if (!(idx < numToRender)) return <></>
|
||||
return (
|
||||
<TableRow className={classes.row} key={idx}>
|
||||
<Cell align="left">
|
||||
<P>{asset.display}</P>
|
||||
</Cell>
|
||||
<Cell align="right">
|
||||
<P>{`${selectAmountPrefix(asset)}
|
||||
${numberToFiatAmount(Math.abs(asset.amount))} ${
|
||||
asset.currency
|
||||
}`}</P>
|
||||
</Cell>
|
||||
</TableRow>
|
||||
)
|
||||
})}
|
||||
<TableRow className={classes.totalRow} key={data?.length + 1}>
|
||||
<Cell align="left">
|
||||
<Info2>{`Total ${R.toLower(title)}`}</Info2>
|
||||
</Cell>
|
||||
<Cell align="right">
|
||||
<Info2>{`${numberToFiatAmount(
|
||||
totalAmount
|
||||
)} ${currency}`}</Info2>
|
||||
</Cell>
|
||||
</TableRow>
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableContainer>
|
||||
</Grid>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
const Assets = () => {
|
||||
const classes = useStyles()
|
||||
const { userData } = useContext(AppContext)
|
||||
|
||||
const { data, loading } = useQuery(GET_OPERATOR_BY_USERNAME, {
|
||||
context: { clientName: 'pazuz' },
|
||||
variables: { username: userData?.username }
|
||||
})
|
||||
|
||||
const operatorData = R.path(['operatorByUsername'], data)
|
||||
|
||||
const balanceData = [
|
||||
{
|
||||
id: 'fiatBalance',
|
||||
display: 'Fiat balance',
|
||||
amount: operatorData?.assets.total ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
class: 'Available balance'
|
||||
},
|
||||
{
|
||||
id: 'hedgingReserve',
|
||||
display: 'Hedging reserve',
|
||||
amount:
|
||||
-R.sum(R.values(operatorData?.assets.values.hedgedContracts)) ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
class: 'Available balance',
|
||||
direction: 'out'
|
||||
}
|
||||
]
|
||||
|
||||
const walletData = [
|
||||
{
|
||||
id: 'hedgedWalletAssets',
|
||||
display: 'Hedged wallet assets',
|
||||
amount: R.sum(R.values(operatorData?.assets.values.hedgedContracts)) ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
class: 'Wallet assets',
|
||||
direction: 'in'
|
||||
},
|
||||
{
|
||||
id: 'unhedgedWalletAssets',
|
||||
display: 'Unhedged wallet assets',
|
||||
amount: R.sum(R.values(operatorData?.assets.values.unhedgedFiat)) ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
class: 'Wallet assets',
|
||||
direction: 'in'
|
||||
}
|
||||
]
|
||||
|
||||
const totalData = [
|
||||
{
|
||||
id: 'fiatBalance',
|
||||
display: 'Fiat balance',
|
||||
amount:
|
||||
operatorData?.fiatBalances[operatorData?.preferredFiatCurrency] ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? '')
|
||||
},
|
||||
{
|
||||
id: 'hedgingReserve',
|
||||
display: 'Hedging reserve',
|
||||
amount:
|
||||
-R.sum(R.values(operatorData?.assets.values.hedgedContracts)) ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
direction: 'out'
|
||||
},
|
||||
{
|
||||
id: 'hedgedWalletAssets',
|
||||
display: 'Market value of hedged wallet assets',
|
||||
amount: R.sum(R.values(operatorData?.assets.values.hedgedContracts)) ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
direction: 'in'
|
||||
},
|
||||
{
|
||||
id: 'unhedgedWalletAssets',
|
||||
display: 'Unhedged wallet assets',
|
||||
amount: R.sum(R.values(operatorData?.assets.values.unhedgedFiat)) ?? 0,
|
||||
currency: R.toUpper(operatorData?.preferredFiatCurrency ?? ''),
|
||||
direction: 'in'
|
||||
}
|
||||
]
|
||||
|
||||
return (
|
||||
!loading && (
|
||||
<>
|
||||
<TitleSection title="Balance sheet" />
|
||||
<div className={classes.root}>
|
||||
<Grid container>
|
||||
<Grid container direction="column" item xs={5}>
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.leftSide}>
|
||||
<AssetsAmountTable
|
||||
title="Available balance"
|
||||
data={balanceData}
|
||||
numToRender={balanceData.length}
|
||||
/>
|
||||
</div>
|
||||
<div className={classes.leftSide}>
|
||||
<AssetsAmountTable
|
||||
title="Wallet assets"
|
||||
data={walletData}
|
||||
numToRender={walletData.length}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid container direction="column" item xs={7}>
|
||||
<Grid item xs={12}>
|
||||
<div className={classes.rightSide}>
|
||||
<AssetsAmountTable
|
||||
title="Total assets"
|
||||
data={totalData}
|
||||
numToRender={totalData.length}
|
||||
/>
|
||||
</div>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
export default Assets
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
import {
|
||||
white,
|
||||
offColor,
|
||||
backgroundColor,
|
||||
subheaderColor
|
||||
} from 'src/styling/variables'
|
||||
|
||||
const styles = () => ({
|
||||
card: {
|
||||
wordWrap: 'break-word',
|
||||
boxShadow: '0 0 4px 0 rgba(0, 0, 0, 0.08)',
|
||||
borderRadius: 12,
|
||||
padding: 24,
|
||||
backgroundColor: white
|
||||
},
|
||||
h4: {
|
||||
marginTop: 0
|
||||
},
|
||||
label: {
|
||||
margin: 0,
|
||||
color: offColor
|
||||
},
|
||||
asset: {
|
||||
float: 'left'
|
||||
},
|
||||
amount: {
|
||||
float: 'right'
|
||||
},
|
||||
row: {
|
||||
backgroundColor: backgroundColor,
|
||||
borderBottom: 'none'
|
||||
},
|
||||
totalRow: {
|
||||
backgroundColor: subheaderColor,
|
||||
borderBottom: 'none'
|
||||
},
|
||||
leftSide: {
|
||||
margin: [[0, 10, 20, 0]]
|
||||
},
|
||||
rightSide: {
|
||||
margin: [[0, 0, 0, 10]]
|
||||
}
|
||||
})
|
||||
|
||||
export default styles
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import { useMutation, useLazyQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import base64 from 'base-64'
|
||||
import { Form, Formik } from 'formik'
|
||||
import gql from 'graphql-tag'
|
||||
import React, { useContext, useState } from 'react'
|
||||
|
|
@ -59,14 +58,7 @@ const Input2FAState = ({ state, dispatch }) => {
|
|||
const [input2FA, { error: mutationError }] = useMutation(INPUT_2FA, {
|
||||
onCompleted: ({ input2FA: success }) => {
|
||||
if (success) {
|
||||
const options = {
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
||||
}
|
||||
}
|
||||
}
|
||||
return getUserData(options)
|
||||
return getUserData()
|
||||
}
|
||||
return setInvalidToken(true)
|
||||
}
|
||||
|
|
@ -94,11 +86,6 @@ const Input2FAState = ({ state, dispatch }) => {
|
|||
password: state.passwordField,
|
||||
code: state.twoFAField,
|
||||
rememberMe: state.rememberMeField
|
||||
},
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
import { useMutation, useLazyQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import { startAssertion } from '@simplewebauthn/browser'
|
||||
import base64 from 'base-64'
|
||||
import { Field, Form, Formik } from 'formik'
|
||||
import gql from 'graphql-tag'
|
||||
import React, { useContext } from 'react'
|
||||
|
|
@ -84,11 +83,6 @@ const LoginState = ({ state, dispatch, strategy }) => {
|
|||
variables: {
|
||||
username,
|
||||
password
|
||||
},
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': base64.encode(username)
|
||||
}
|
||||
}
|
||||
}
|
||||
const { data: loginResponse } = await login(options)
|
||||
|
|
|
|||
|
|
@ -90,16 +90,10 @@ const Register = () => {
|
|||
const classes = useStyles()
|
||||
const history = useHistory()
|
||||
const token = QueryParams().get('t')
|
||||
const identifier = QueryParams().get('id') ?? null
|
||||
|
||||
const [state, dispatch] = useReducer(reducer, initialState)
|
||||
|
||||
const queryOptions = {
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': identifier
|
||||
}
|
||||
},
|
||||
variables: { token: token },
|
||||
onCompleted: ({ validateRegisterLink: info }) => {
|
||||
if (!info) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useMutation, useQuery, useLazyQuery } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import base64 from 'base-64'
|
||||
import { Form, Formik } from 'formik'
|
||||
import gql from 'graphql-tag'
|
||||
import QRCode from 'qrcode.react'
|
||||
|
|
@ -71,11 +70,6 @@ const Setup2FAState = ({ state, dispatch }) => {
|
|||
|
||||
const queryOptions = {
|
||||
variables: { username: state.clientField, password: state.passwordField },
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
||||
}
|
||||
},
|
||||
onCompleted: ({ get2FASecret }) => {
|
||||
setSecret(get2FASecret.secret)
|
||||
setOtpauth(get2FASecret.otpauth)
|
||||
|
|
@ -88,11 +82,6 @@ const Setup2FAState = ({ state, dispatch }) => {
|
|||
password: state.passwordField,
|
||||
rememberMe: state.rememberMeField,
|
||||
codeConfirmation: twoFAConfirmation
|
||||
},
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -107,14 +96,7 @@ const Setup2FAState = ({ state, dispatch }) => {
|
|||
|
||||
const [setup2FA, { error: mutationError }] = useMutation(SETUP_2FA, {
|
||||
onCompleted: ({ setup2FA: success }) => {
|
||||
const options = {
|
||||
context: {
|
||||
headers: {
|
||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
||||
}
|
||||
}
|
||||
}
|
||||
success ? getUserData(options) : setInvalidToken(true)
|
||||
success ? getUserData() : setInvalidToken(true)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import { useMutation } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core/styles'
|
||||
import base64 from 'base-64'
|
||||
import classnames from 'classnames'
|
||||
import { Field, Form, Formik } from 'formik'
|
||||
import gql from 'graphql-tag'
|
||||
|
|
@ -75,12 +74,7 @@ const CreateUserModal = ({ state, dispatch }) => {
|
|||
|
||||
const [createUser, { error }] = useMutation(CREATE_USER, {
|
||||
onCompleted: ({ createRegisterToken: token }) => {
|
||||
const queryParams =
|
||||
// Pazuz-created register tokens add a field to identify the creator
|
||||
process.env.REACT_APP_BUILD_TARGET === 'LAMASSU'
|
||||
? `t=${token.token}`
|
||||
: `t=${token.token}&id=${base64.encode(usernameField)}`
|
||||
setCreateUserURL(urlResolver(`/register?${queryParams}`))
|
||||
setCreateUserURL(urlResolver(`/register?t${token.token}`))
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { useQuery } from '@apollo/react-hooks'
|
|||
import { makeStyles, Dialog, DialogContent } from '@material-ui/core'
|
||||
import classnames from 'classnames'
|
||||
import gql from 'graphql-tag'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState, useContext } from 'react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
|
|
@ -53,18 +52,6 @@ const Wizard = ({ fromAuthRegister }) => {
|
|||
|
||||
const [footerExp, setFooterExp] = useState(false)
|
||||
|
||||
const getSteps = STEPS => {
|
||||
const buildTarget = process.env.REACT_APP_BUILD_TARGET
|
||||
if (buildTarget === 'PAZUZ') {
|
||||
return R.filter(step => step.id !== 'wallet' && step.id !== 'twilio')(
|
||||
STEPS
|
||||
)
|
||||
}
|
||||
return STEPS
|
||||
}
|
||||
|
||||
const steps = getSteps(STEPS)
|
||||
|
||||
if (loading) {
|
||||
return <></>
|
||||
}
|
||||
|
|
@ -91,7 +78,7 @@ const Wizard = ({ fromAuthRegister }) => {
|
|||
}
|
||||
|
||||
const doContinue = () => {
|
||||
if (step >= steps.length - 1) {
|
||||
if (step >= STEPS.length - 1) {
|
||||
setOpen(false)
|
||||
history.push('/')
|
||||
}
|
||||
|
|
@ -102,7 +89,7 @@ const Wizard = ({ fromAuthRegister }) => {
|
|||
setStep(nextStep)
|
||||
}
|
||||
|
||||
const current = steps[step]
|
||||
const current = STEPS[step]
|
||||
|
||||
return (
|
||||
<Dialog fullScreen open={open}>
|
||||
|
|
@ -112,7 +99,7 @@ const Wizard = ({ fromAuthRegister }) => {
|
|||
{!isWelcome && (
|
||||
<Footer
|
||||
currentStep={step}
|
||||
steps={steps.length - 1}
|
||||
steps={STEPS.length - 1}
|
||||
exImage={current.exImage}
|
||||
subtitle={current.subtitle}
|
||||
text={current.text}
|
||||
|
|
|
|||
|
|
@ -1,317 +0,0 @@
|
|||
import React from 'react'
|
||||
import { Redirect } from 'react-router-dom'
|
||||
|
||||
import ATMWallet from 'src/pages/ATMWallet/ATMWallet'
|
||||
import Accounting from 'src/pages/Accounting/Accounting'
|
||||
import Analytics from 'src/pages/Analytics/Analytics'
|
||||
import Assets from 'src/pages/Assets/Assets'
|
||||
import Blacklist from 'src/pages/Blacklist'
|
||||
import Cashout from 'src/pages/Cashout'
|
||||
import Commissions from 'src/pages/Commissions'
|
||||
import { Customers, CustomerProfile } from 'src/pages/Customers'
|
||||
import Locales from 'src/pages/Locales'
|
||||
import IndividualDiscounts from 'src/pages/LoyaltyPanel/IndividualDiscounts'
|
||||
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
|
||||
import MachineLogs from 'src/pages/MachineLogs'
|
||||
import CashUnits from 'src/pages/Maintenance/CashUnits'
|
||||
import MachineStatus from 'src/pages/Maintenance/MachineStatus'
|
||||
import Notifications from 'src/pages/Notifications/Notifications'
|
||||
import CoinAtmRadar from 'src/pages/OperatorInfo/CoinATMRadar'
|
||||
import ContactInfo from 'src/pages/OperatorInfo/ContactInfo'
|
||||
import MachineScreens from 'src/pages/OperatorInfo/MachineScreens'
|
||||
import ReceiptPrinting from 'src/pages/OperatorInfo/ReceiptPrinting'
|
||||
import SMSNotices from 'src/pages/OperatorInfo/SMSNotices/SMSNotices'
|
||||
import TermsConditions from 'src/pages/OperatorInfo/TermsConditions'
|
||||
import ServerLogs from 'src/pages/ServerLogs'
|
||||
import SessionManagement from 'src/pages/SessionManagement/SessionManagement'
|
||||
import Transactions from 'src/pages/Transactions/Transactions'
|
||||
import Triggers from 'src/pages/Triggers'
|
||||
import UserManagement from 'src/pages/UserManagement/UserManagement'
|
||||
import { namespaces } from 'src/utils/config'
|
||||
|
||||
import { ROLES } from './utils'
|
||||
|
||||
const getPazuzRoutes = () => [
|
||||
{
|
||||
key: 'transactions',
|
||||
label: 'Transactions',
|
||||
route: '/transactions',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Transactions
|
||||
},
|
||||
{
|
||||
key: 'maintenance',
|
||||
label: 'Maintenance',
|
||||
route: '/maintenance',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => <Redirect to={this.children[0].route} />
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: 'cash_units',
|
||||
label: 'Cash Units',
|
||||
route: '/maintenance/cash-units',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: CashUnits
|
||||
},
|
||||
{
|
||||
key: 'logs',
|
||||
label: 'Machine logs',
|
||||
route: '/maintenance/logs',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: MachineLogs
|
||||
},
|
||||
{
|
||||
key: 'machine-status',
|
||||
label: 'Machine status',
|
||||
route: '/maintenance/machine-status',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: MachineStatus
|
||||
},
|
||||
{
|
||||
key: 'server-logs',
|
||||
label: 'Server',
|
||||
route: '/maintenance/server-logs',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: ServerLogs
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'analytics',
|
||||
label: 'Analytics',
|
||||
route: '/analytics',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Analytics
|
||||
},
|
||||
{
|
||||
key: 'settings',
|
||||
label: 'Settings',
|
||||
route: '/settings',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => <Redirect to={this.children[0].route} />
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: namespaces.COMMISSIONS,
|
||||
label: 'Commissions',
|
||||
route: '/settings/commissions',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Commissions
|
||||
},
|
||||
{
|
||||
key: namespaces.LOCALE,
|
||||
label: 'Locales',
|
||||
route: '/settings/locale',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Locales
|
||||
},
|
||||
{
|
||||
key: namespaces.CASH_OUT,
|
||||
label: 'Cash-out',
|
||||
route: '/settings/cash-out',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Cashout
|
||||
},
|
||||
{
|
||||
key: namespaces.NOTIFICATIONS,
|
||||
label: 'Notifications',
|
||||
route: '/settings/notifications',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Notifications
|
||||
},
|
||||
{
|
||||
key: namespaces.OPERATOR_INFO,
|
||||
label: 'Operator info',
|
||||
route: '/settings/operator-info',
|
||||
title: 'Operator information',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: this.children[0].route,
|
||||
state: { prev: this.state?.prev }
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: 'contact-info',
|
||||
label: 'Contact information',
|
||||
route: '/settings/operator-info/contact-info',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: ContactInfo
|
||||
},
|
||||
{
|
||||
key: 'receipt-printing',
|
||||
label: 'Receipt',
|
||||
route: '/settings/operator-info/receipt-printing',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: ReceiptPrinting
|
||||
},
|
||||
{
|
||||
key: 'sms-notices',
|
||||
label: 'SMS notices',
|
||||
route: '/settings/operator-info/sms-notices',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: SMSNotices
|
||||
},
|
||||
{
|
||||
key: 'coin-atm-radar',
|
||||
label: 'Coin ATM Radar',
|
||||
route: '/settings/operator-info/coin-atm-radar',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: CoinAtmRadar
|
||||
},
|
||||
{
|
||||
key: 'terms-conditions',
|
||||
label: 'Terms & Conditions',
|
||||
route: '/settings/operator-info/terms-conditions',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: TermsConditions
|
||||
},
|
||||
{
|
||||
key: 'machine-screens',
|
||||
label: 'Machine screens',
|
||||
route: '/settings/operator-info/machine-screens',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: MachineScreens
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'compliance',
|
||||
label: 'Compliance',
|
||||
route: '/compliance',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => <Redirect to={this.children[0].route} />
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: 'triggers',
|
||||
label: 'Triggers',
|
||||
route: '/compliance/triggers',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Triggers
|
||||
},
|
||||
{
|
||||
key: 'customers',
|
||||
label: 'Customers',
|
||||
route: '/compliance/customers',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Customers
|
||||
},
|
||||
{
|
||||
key: 'blacklist',
|
||||
label: 'Blacklist',
|
||||
route: '/compliance/blacklist',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Blacklist
|
||||
},
|
||||
{
|
||||
key: 'loyalty',
|
||||
label: 'Loyalty',
|
||||
route: '/compliance/loyalty',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => (
|
||||
<Redirect
|
||||
to={{
|
||||
pathname: this.children[0].route,
|
||||
state: { prev: this.state?.prev }
|
||||
}}
|
||||
/>
|
||||
)
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: 'individual-discounts',
|
||||
label: 'Individual discounts',
|
||||
route: '/compliance/loyalty/individual-discounts',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: IndividualDiscounts
|
||||
},
|
||||
{
|
||||
key: 'promo-codes',
|
||||
label: 'Promo codes',
|
||||
route: '/compliance/loyalty/codes',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: PromoCodes
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'customer',
|
||||
route: '/compliance/customer/:id',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: CustomerProfile
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'accounting',
|
||||
label: 'Accounting',
|
||||
route: '/accounting',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => <Redirect to={this.children[0].route} />
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: 'accountingpage',
|
||||
label: 'Accounting',
|
||||
route: '/accounting/accounting',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Accounting
|
||||
},
|
||||
{
|
||||
key: 'atmwallets',
|
||||
label: 'ATM Wallets',
|
||||
route: '/accounting/wallets',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: ATMWallet
|
||||
},
|
||||
{
|
||||
key: 'assetspage',
|
||||
label: 'Assets',
|
||||
route: '/accounting/assets',
|
||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||
component: Assets
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
key: 'system',
|
||||
label: 'System',
|
||||
route: '/system',
|
||||
allowedRoles: [ROLES.SUPERUSER],
|
||||
get component() {
|
||||
return () => <Redirect to={this.children[0].route} />
|
||||
},
|
||||
children: [
|
||||
{
|
||||
key: 'user-management',
|
||||
label: 'User management',
|
||||
route: '/system/user-management',
|
||||
allowedRoles: [ROLES.SUPERUSER],
|
||||
component: UserManagement
|
||||
},
|
||||
{
|
||||
key: 'session-management',
|
||||
label: 'Session management',
|
||||
route: '/system/session-management',
|
||||
allowedRoles: [ROLES.SUPERUSER],
|
||||
component: SessionManagement
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
export default getPazuzRoutes
|
||||
|
|
@ -23,7 +23,6 @@ import Wizard from 'src/pages/Wizard'
|
|||
import PrivateRoute from './PrivateRoute'
|
||||
import PublicRoute from './PublicRoute'
|
||||
import getLamassuRoutes from './lamassu.routes'
|
||||
import getPazuzRoutes from './pazuz.routes'
|
||||
|
||||
const useStyles = makeStyles({
|
||||
wrapper: {
|
||||
|
|
@ -34,19 +33,7 @@ const useStyles = makeStyles({
|
|||
}
|
||||
})
|
||||
|
||||
const getTree = () => {
|
||||
const buildTarget = process.env.REACT_APP_BUILD_TARGET
|
||||
|
||||
if (buildTarget === 'LAMASSU') {
|
||||
return getLamassuRoutes()
|
||||
}
|
||||
|
||||
if (buildTarget === 'PAZUZ') {
|
||||
return getPazuzRoutes()
|
||||
}
|
||||
}
|
||||
|
||||
const tree = getTree()
|
||||
const tree = getLamassuRoutes()
|
||||
|
||||
const map = R.map(R.when(R.has('children'), R.prop('children')))
|
||||
const mappedRoutes = R.compose(R.flatten, map)(tree)
|
||||
|
|
|
|||
|
|
@ -9,8 +9,3 @@ export const ROLES = {
|
|||
USER: 'user',
|
||||
SUPERUSER: 'superuser'
|
||||
}
|
||||
|
||||
export const BUILD_TARGETS = {
|
||||
LAMASSU: 'LAMASSU',
|
||||
PAZUZ: 'PAZUZ'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,135 +0,0 @@
|
|||
// This optional code is used to register a service worker.
|
||||
// register() is not called by default.
|
||||
|
||||
// This lets the app load faster on subsequent visits in production, and gives
|
||||
// it offline capabilities. However, it also means that developers (and users)
|
||||
// will only see deployed updates on subsequent visits to a page, after all the
|
||||
// existing tabs open on the page have been closed, since previously cached
|
||||
// resources are updated in the background.
|
||||
|
||||
// To learn more about the benefits of this model and instructions on how to
|
||||
// opt-in, read https://bit.ly/CRA-PWA
|
||||
|
||||
const isLocalhost = Boolean(
|
||||
window.location.hostname === 'localhost' ||
|
||||
// [::1] is the IPv6 localhost address.
|
||||
window.location.hostname === '[::1]' ||
|
||||
// 127.0.0.1/8 is considered localhost for IPv4.
|
||||
window.location.hostname.match(
|
||||
/^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
|
||||
)
|
||||
)
|
||||
|
||||
export function register(config) {
|
||||
if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
|
||||
// The URL constructor is available in all browsers that support SW.
|
||||
const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href)
|
||||
if (publicUrl.origin !== window.location.origin) {
|
||||
// Our service worker won't work if PUBLIC_URL is on a different origin
|
||||
// from what our page is served on. This might happen if a CDN is used to
|
||||
// serve assets; see https://github.com/facebook/create-react-app/issues/2374
|
||||
return
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => {
|
||||
const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`
|
||||
|
||||
if (isLocalhost) {
|
||||
// This is running on localhost. Let's check if a service worker still exists or not.
|
||||
checkValidServiceWorker(swUrl, config)
|
||||
|
||||
// Add some additional logging to localhost, pointing developers to the
|
||||
// service worker/PWA documentation.
|
||||
navigator.serviceWorker.ready.then(() => {
|
||||
console.log(
|
||||
'This web app is being served cache-first by a service ' +
|
||||
'worker. To learn more, visit https://bit.ly/CRA-PWA'
|
||||
)
|
||||
})
|
||||
} else {
|
||||
// Is not localhost. Just register service worker
|
||||
registerValidSW(swUrl, config)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
function registerValidSW(swUrl, config) {
|
||||
navigator.serviceWorker
|
||||
.register(swUrl)
|
||||
.then(registration => {
|
||||
registration.onupdatefound = () => {
|
||||
const installingWorker = registration.installing
|
||||
if (installingWorker == null) {
|
||||
return
|
||||
}
|
||||
installingWorker.onstatechange = () => {
|
||||
if (installingWorker.state === 'installed') {
|
||||
if (navigator.serviceWorker.controller) {
|
||||
// At this point, the updated precached content has been fetched,
|
||||
// but the previous service worker will still serve the older
|
||||
// content until all client tabs are closed.
|
||||
console.log(
|
||||
'New content is available and will be used when all ' +
|
||||
'tabs for this page are closed. See https://bit.ly/CRA-PWA.'
|
||||
)
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onUpdate) {
|
||||
config.onUpdate(registration)
|
||||
}
|
||||
} else {
|
||||
// At this point, everything has been precached.
|
||||
// It's the perfect time to display a
|
||||
// "Content is cached for offline use." message.
|
||||
console.log('Content is cached for offline use.')
|
||||
|
||||
// Execute callback
|
||||
if (config && config.onSuccess) {
|
||||
config.onSuccess(registration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
console.error('Error during service worker registration:', error)
|
||||
})
|
||||
}
|
||||
|
||||
function checkValidServiceWorker(swUrl, config) {
|
||||
// Check if the service worker can be found. If it can't reload the page.
|
||||
fetch(swUrl)
|
||||
.then(response => {
|
||||
// Ensure service worker exists, and that we really are getting a JS file.
|
||||
const contentType = response.headers.get('content-type')
|
||||
if (
|
||||
response.status === 404 ||
|
||||
(contentType != null && contentType.indexOf('javascript') === -1)
|
||||
) {
|
||||
// No service worker found. Probably a different app. Reload the page.
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister().then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
})
|
||||
} else {
|
||||
// Service worker found. Proceed as normal.
|
||||
registerValidSW(swUrl, config)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
console.log(
|
||||
'No internet connection found. App is running in offline mode.'
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
export function unregister() {
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.ready.then(registration => {
|
||||
registration.unregister()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -12,21 +12,11 @@ import AppContext from 'src/AppContext'
|
|||
const URI =
|
||||
process.env.NODE_ENV === 'development' ? 'https://localhost:8070' : ''
|
||||
|
||||
const ALT_URI =
|
||||
process.env.NODE_ENV === 'development'
|
||||
? 'https://localhost:4001'
|
||||
: `https://${window.location.hostname}:4001`
|
||||
|
||||
const uploadLink = createUploadLink({
|
||||
credentials: 'include',
|
||||
uri: `${URI}/graphql`
|
||||
})
|
||||
|
||||
const uploadLinkALT = createUploadLink({
|
||||
credentials: 'include',
|
||||
uri: `${ALT_URI}/graphql`
|
||||
})
|
||||
|
||||
const getClient = (history, location, getUserData, setUserData, setRole) =>
|
||||
new ApolloClient({
|
||||
link: ApolloLink.from([
|
||||
|
|
@ -58,11 +48,7 @@ const getClient = (history, location, getUserData, setUserData, setRole) =>
|
|||
return response
|
||||
})
|
||||
}),
|
||||
ApolloLink.split(
|
||||
operation => operation.getContext().clientName === 'pazuz',
|
||||
uploadLinkALT,
|
||||
uploadLink
|
||||
)
|
||||
]),
|
||||
cache: new InMemoryCache(),
|
||||
defaultOptions: {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue