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
|
req.session.user.role = user.role
|
||||||
|
|
||||||
res.set('lamassu_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')
|
res.set('Access-Control-Expose-Headers', 'lamassu_role')
|
||||||
|
|
||||||
return { req, res }
|
return { req, res }
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,3 @@ SKIP_PREFLIGHT_CHECK=true
|
||||||
HTTPS=true
|
HTTPS=true
|
||||||
REACT_APP_TYPE_CHECK_SANCTUARY=false
|
REACT_APP_TYPE_CHECK_SANCTUARY=false
|
||||||
PORT=3001
|
PORT=3001
|
||||||
REACT_APP_BUILD_TARGET=LAMASSU
|
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,7 @@
|
||||||
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
"analyze": "source-map-explorer 'build/static/js/*.js'",
|
||||||
"test": "react-scripts test",
|
"test": "react-scripts test",
|
||||||
"eject": "react-scripts eject",
|
"eject": "react-scripts eject",
|
||||||
"postinstall": "patch-package",
|
"postinstall": "patch-package"
|
||||||
"lamassu": "REACT_APP_BUILD_TARGET=LAMASSU react-scripts start",
|
|
||||||
"pazuz": "REACT_APP_BUILD_TARGET=PAZUZ react-scripts start"
|
|
||||||
},
|
},
|
||||||
"browserslist": {
|
"browserslist": {
|
||||||
"production": [
|
"production": [
|
||||||
|
|
|
||||||
|
|
@ -2,30 +2,10 @@ import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
|
|
||||||
import App from './App'
|
import App from './App'
|
||||||
import * as serviceWorker from './serviceWorker'
|
|
||||||
|
|
||||||
function checkBuildTarget() {
|
ReactDOM.render(
|
||||||
const buildTarget = process.env.REACT_APP_BUILD_TARGET
|
<React.StrictMode>
|
||||||
|
<App />
|
||||||
if (buildTarget !== 'LAMASSU' && buildTarget !== 'PAZUZ') {
|
</React.StrictMode>,
|
||||||
return Promise.reject(
|
document.getElementById('root')
|
||||||
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 { useMutation, useLazyQuery } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import base64 from 'base-64'
|
|
||||||
import { Form, Formik } from 'formik'
|
import { Form, Formik } from 'formik'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import React, { useContext, useState } from 'react'
|
import React, { useContext, useState } from 'react'
|
||||||
|
|
@ -59,14 +58,7 @@ const Input2FAState = ({ state, dispatch }) => {
|
||||||
const [input2FA, { error: mutationError }] = useMutation(INPUT_2FA, {
|
const [input2FA, { error: mutationError }] = useMutation(INPUT_2FA, {
|
||||||
onCompleted: ({ input2FA: success }) => {
|
onCompleted: ({ input2FA: success }) => {
|
||||||
if (success) {
|
if (success) {
|
||||||
const options = {
|
return getUserData()
|
||||||
context: {
|
|
||||||
headers: {
|
|
||||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return getUserData(options)
|
|
||||||
}
|
}
|
||||||
return setInvalidToken(true)
|
return setInvalidToken(true)
|
||||||
}
|
}
|
||||||
|
|
@ -94,11 +86,6 @@ const Input2FAState = ({ state, dispatch }) => {
|
||||||
password: state.passwordField,
|
password: state.passwordField,
|
||||||
code: state.twoFAField,
|
code: state.twoFAField,
|
||||||
rememberMe: state.rememberMeField
|
rememberMe: state.rememberMeField
|
||||||
},
|
|
||||||
context: {
|
|
||||||
headers: {
|
|
||||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { useMutation, useLazyQuery } from '@apollo/react-hooks'
|
import { useMutation, useLazyQuery } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import { startAssertion } from '@simplewebauthn/browser'
|
import { startAssertion } from '@simplewebauthn/browser'
|
||||||
import base64 from 'base-64'
|
|
||||||
import { Field, Form, Formik } from 'formik'
|
import { Field, Form, Formik } from 'formik'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import React, { useContext } from 'react'
|
import React, { useContext } from 'react'
|
||||||
|
|
@ -84,11 +83,6 @@ const LoginState = ({ state, dispatch, strategy }) => {
|
||||||
variables: {
|
variables: {
|
||||||
username,
|
username,
|
||||||
password
|
password
|
||||||
},
|
|
||||||
context: {
|
|
||||||
headers: {
|
|
||||||
'Pazuz-Operator-Identifier': base64.encode(username)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const { data: loginResponse } = await login(options)
|
const { data: loginResponse } = await login(options)
|
||||||
|
|
|
||||||
|
|
@ -90,16 +90,10 @@ const Register = () => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const history = useHistory()
|
const history = useHistory()
|
||||||
const token = QueryParams().get('t')
|
const token = QueryParams().get('t')
|
||||||
const identifier = QueryParams().get('id') ?? null
|
|
||||||
|
|
||||||
const [state, dispatch] = useReducer(reducer, initialState)
|
const [state, dispatch] = useReducer(reducer, initialState)
|
||||||
|
|
||||||
const queryOptions = {
|
const queryOptions = {
|
||||||
context: {
|
|
||||||
headers: {
|
|
||||||
'Pazuz-Operator-Identifier': identifier
|
|
||||||
}
|
|
||||||
},
|
|
||||||
variables: { token: token },
|
variables: { token: token },
|
||||||
onCompleted: ({ validateRegisterLink: info }) => {
|
onCompleted: ({ validateRegisterLink: info }) => {
|
||||||
if (!info) {
|
if (!info) {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { useMutation, useQuery, useLazyQuery } from '@apollo/react-hooks'
|
import { useMutation, useQuery, useLazyQuery } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import base64 from 'base-64'
|
|
||||||
import { Form, Formik } from 'formik'
|
import { Form, Formik } from 'formik'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import QRCode from 'qrcode.react'
|
import QRCode from 'qrcode.react'
|
||||||
|
|
@ -71,11 +70,6 @@ const Setup2FAState = ({ state, dispatch }) => {
|
||||||
|
|
||||||
const queryOptions = {
|
const queryOptions = {
|
||||||
variables: { username: state.clientField, password: state.passwordField },
|
variables: { username: state.clientField, password: state.passwordField },
|
||||||
context: {
|
|
||||||
headers: {
|
|
||||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onCompleted: ({ get2FASecret }) => {
|
onCompleted: ({ get2FASecret }) => {
|
||||||
setSecret(get2FASecret.secret)
|
setSecret(get2FASecret.secret)
|
||||||
setOtpauth(get2FASecret.otpauth)
|
setOtpauth(get2FASecret.otpauth)
|
||||||
|
|
@ -88,11 +82,6 @@ const Setup2FAState = ({ state, dispatch }) => {
|
||||||
password: state.passwordField,
|
password: state.passwordField,
|
||||||
rememberMe: state.rememberMeField,
|
rememberMe: state.rememberMeField,
|
||||||
codeConfirmation: twoFAConfirmation
|
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, {
|
const [setup2FA, { error: mutationError }] = useMutation(SETUP_2FA, {
|
||||||
onCompleted: ({ setup2FA: success }) => {
|
onCompleted: ({ setup2FA: success }) => {
|
||||||
const options = {
|
success ? getUserData() : setInvalidToken(true)
|
||||||
context: {
|
|
||||||
headers: {
|
|
||||||
'Pazuz-Operator-Identifier': base64.encode(state.clientField)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
success ? getUserData(options) : setInvalidToken(true)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
import { useMutation } from '@apollo/react-hooks'
|
import { useMutation } from '@apollo/react-hooks'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import base64 from 'base-64'
|
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import { Field, Form, Formik } from 'formik'
|
import { Field, Form, Formik } from 'formik'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
|
|
@ -75,12 +74,7 @@ const CreateUserModal = ({ state, dispatch }) => {
|
||||||
|
|
||||||
const [createUser, { error }] = useMutation(CREATE_USER, {
|
const [createUser, { error }] = useMutation(CREATE_USER, {
|
||||||
onCompleted: ({ createRegisterToken: token }) => {
|
onCompleted: ({ createRegisterToken: token }) => {
|
||||||
const queryParams =
|
setCreateUserURL(urlResolver(`/register?t${token.token}`))
|
||||||
// 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}`))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@ import { useQuery } from '@apollo/react-hooks'
|
||||||
import { makeStyles, Dialog, DialogContent } from '@material-ui/core'
|
import { makeStyles, Dialog, DialogContent } from '@material-ui/core'
|
||||||
import classnames from 'classnames'
|
import classnames from 'classnames'
|
||||||
import gql from 'graphql-tag'
|
import gql from 'graphql-tag'
|
||||||
import * as R from 'ramda'
|
|
||||||
import React, { useState, useContext } from 'react'
|
import React, { useState, useContext } from 'react'
|
||||||
import { useHistory } from 'react-router-dom'
|
import { useHistory } from 'react-router-dom'
|
||||||
|
|
||||||
|
|
@ -53,18 +52,6 @@ const Wizard = ({ fromAuthRegister }) => {
|
||||||
|
|
||||||
const [footerExp, setFooterExp] = useState(false)
|
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) {
|
if (loading) {
|
||||||
return <></>
|
return <></>
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +78,7 @@ const Wizard = ({ fromAuthRegister }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const doContinue = () => {
|
const doContinue = () => {
|
||||||
if (step >= steps.length - 1) {
|
if (step >= STEPS.length - 1) {
|
||||||
setOpen(false)
|
setOpen(false)
|
||||||
history.push('/')
|
history.push('/')
|
||||||
}
|
}
|
||||||
|
|
@ -102,7 +89,7 @@ const Wizard = ({ fromAuthRegister }) => {
|
||||||
setStep(nextStep)
|
setStep(nextStep)
|
||||||
}
|
}
|
||||||
|
|
||||||
const current = steps[step]
|
const current = STEPS[step]
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Dialog fullScreen open={open}>
|
<Dialog fullScreen open={open}>
|
||||||
|
|
@ -112,7 +99,7 @@ const Wizard = ({ fromAuthRegister }) => {
|
||||||
{!isWelcome && (
|
{!isWelcome && (
|
||||||
<Footer
|
<Footer
|
||||||
currentStep={step}
|
currentStep={step}
|
||||||
steps={steps.length - 1}
|
steps={STEPS.length - 1}
|
||||||
exImage={current.exImage}
|
exImage={current.exImage}
|
||||||
subtitle={current.subtitle}
|
subtitle={current.subtitle}
|
||||||
text={current.text}
|
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 PrivateRoute from './PrivateRoute'
|
||||||
import PublicRoute from './PublicRoute'
|
import PublicRoute from './PublicRoute'
|
||||||
import getLamassuRoutes from './lamassu.routes'
|
import getLamassuRoutes from './lamassu.routes'
|
||||||
import getPazuzRoutes from './pazuz.routes'
|
|
||||||
|
|
||||||
const useStyles = makeStyles({
|
const useStyles = makeStyles({
|
||||||
wrapper: {
|
wrapper: {
|
||||||
|
|
@ -34,19 +33,7 @@ const useStyles = makeStyles({
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const getTree = () => {
|
const tree = getLamassuRoutes()
|
||||||
const buildTarget = process.env.REACT_APP_BUILD_TARGET
|
|
||||||
|
|
||||||
if (buildTarget === 'LAMASSU') {
|
|
||||||
return getLamassuRoutes()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (buildTarget === 'PAZUZ') {
|
|
||||||
return getPazuzRoutes()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const tree = getTree()
|
|
||||||
|
|
||||||
const map = R.map(R.when(R.has('children'), R.prop('children')))
|
const map = R.map(R.when(R.has('children'), R.prop('children')))
|
||||||
const mappedRoutes = R.compose(R.flatten, map)(tree)
|
const mappedRoutes = R.compose(R.flatten, map)(tree)
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,3 @@ export const ROLES = {
|
||||||
USER: 'user',
|
USER: 'user',
|
||||||
SUPERUSER: 'superuser'
|
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 =
|
const URI =
|
||||||
process.env.NODE_ENV === 'development' ? 'https://localhost:8070' : ''
|
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({
|
const uploadLink = createUploadLink({
|
||||||
credentials: 'include',
|
credentials: 'include',
|
||||||
uri: `${URI}/graphql`
|
uri: `${URI}/graphql`
|
||||||
})
|
})
|
||||||
|
|
||||||
const uploadLinkALT = createUploadLink({
|
|
||||||
credentials: 'include',
|
|
||||||
uri: `${ALT_URI}/graphql`
|
|
||||||
})
|
|
||||||
|
|
||||||
const getClient = (history, location, getUserData, setUserData, setRole) =>
|
const getClient = (history, location, getUserData, setUserData, setRole) =>
|
||||||
new ApolloClient({
|
new ApolloClient({
|
||||||
link: ApolloLink.from([
|
link: ApolloLink.from([
|
||||||
|
|
@ -58,11 +48,7 @@ const getClient = (history, location, getUserData, setUserData, setRole) =>
|
||||||
return response
|
return response
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
ApolloLink.split(
|
uploadLink
|
||||||
operation => operation.getContext().clientName === 'pazuz',
|
|
||||||
uploadLinkALT,
|
|
||||||
uploadLink
|
|
||||||
)
|
|
||||||
]),
|
]),
|
||||||
cache: new InMemoryCache(),
|
cache: new InMemoryCache(),
|
||||||
defaultOptions: {
|
defaultOptions: {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue