diff --git a/new-lamassu-admin/src/components/buttons/SubpageButton.styles.js b/new-lamassu-admin/src/components/buttons/SubpageButton.styles.js
index 6217f03e..8280c1f3 100644
--- a/new-lamassu-admin/src/components/buttons/SubpageButton.styles.js
+++ b/new-lamassu-admin/src/components/buttons/SubpageButton.styles.js
@@ -25,13 +25,11 @@ export default {
}
},
buttonIcon: {
- '& svg': {
- width: 16,
- height: 16,
- overflow: 'visible',
- '& g': {
- strokeWidth: 1.8
- }
+ width: 16,
+ height: 16,
+ overflow: 'visible',
+ '& g': {
+ strokeWidth: 1.8
}
},
buttonIconActiveLeft: {
diff --git a/new-lamassu-admin/src/components/editableTable/Row.js b/new-lamassu-admin/src/components/editableTable/Row.js
index de1cc334..1db96b32 100644
--- a/new-lamassu-admin/src/components/editableTable/Row.js
+++ b/new-lamassu-admin/src/components/editableTable/Row.js
@@ -105,6 +105,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
textAlign,
suffix,
SuffixComponent = TL2,
+ textStyle = it => {},
view = it => it?.toString(),
inputProps = {}
} = config
@@ -144,9 +145,17 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
)}
{isEditing && !isField && }
- {!isEditing && values && <>{view(values[name], values)}>}
+ {!isEditing && values && (
+
-
+
{isOpen &&
items.map((item, index) => (
-
- {startCase(item)}
+ {toFirstUpper(item)}
))}
diff --git a/new-lamassu-admin/src/pages/Commissions/Commissions.js b/new-lamassu-admin/src/pages/Commissions/Commissions.js
index 588e10bb..e8d1a91c 100644
--- a/new-lamassu-admin/src/pages/Commissions/Commissions.js
+++ b/new-lamassu-admin/src/pages/Commissions/Commissions.js
@@ -1,22 +1,17 @@
import { useQuery, useMutation } from '@apollo/react-hooks'
+import { makeStyles, Box } from '@material-ui/core'
import gql from 'graphql-tag'
import * as R from 'ramda'
import React, { useState } from 'react'
-import { Table as EditableTable } from 'src/components/editableTable'
-import Section from 'src/components/layout/Section'
+import { SubpageButton } from 'src/components/buttons'
import TitleSection from 'src/components/layout/TitleSection'
+import { ReactComponent as ExeceptionViewIcon } from 'src/styling/icons/circle buttons/exception-view/white.svg'
+import { ReactComponent as ListingViewIcon } from 'src/styling/icons/circle buttons/listing-view/zodiac.svg'
import { fromNamespace, toNamespace, namespaces } from 'src/utils/config'
-import {
- mainFields,
- overrides,
- schema,
- getOverridesSchema,
- defaults,
- overridesDefaults,
- getOrder
-} from './helper'
+import CommissionsDetails from './components/CommissionsDetails'
+import CommissionsList from './components/CommissionsList'
const GET_DATA = gql`
query getData {
@@ -38,26 +33,46 @@ const SAVE_CONFIG = gql`
}
`
+const styles = {
+ titleWrapper: {
+ display: 'flex',
+ alignItems: 'center',
+ flexDirection: 'row'
+ },
+ subpageButton: {
+ marginLeft: 12
+ },
+ colorLabel: {
+ display: 'flex',
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginLeft: 'auto',
+ '& div': {
+ width: 12,
+ height: 12,
+ borderRadius: 3,
+ marginRight: 8,
+ backgroundColor: '#44e188'
+ }
+ }
+}
+
+const useStyles = makeStyles(styles)
+
const Commissions = ({ name: SCREEN_KEY }) => {
- const [isEditingDefault, setEditingDefault] = useState(false)
- const [isEditingOverrides, setEditingOverrides] = useState(false)
+ const classes = useStyles()
+
+ const [showMachines, setShowMachines] = useState(false)
const { data } = useQuery(GET_DATA)
const [saveConfig, { error }] = useMutation(SAVE_CONFIG, {
refetchQueries: () => ['getData']
})
const config = data?.config && fromNamespace(SCREEN_KEY)(data.config)
- const currency = R.path(['fiatCurrency'])(
- fromNamespace(namespaces.LOCALE)(data?.config)
- )
+ const localeConfig =
+ data?.config && fromNamespace(namespaces.LOCALE)(data.config)
- const commission = config && !R.isEmpty(config) ? config : defaults
- const commissionOverrides = commission?.overrides ?? []
-
- const orderedCommissionsOverrides = R.sortWith([
- R.ascend(getOrder),
- R.ascend(R.prop('machine'))
- ])(commissionOverrides)
+ const currency = R.path(['fiatCurrency'])(localeConfig)
const save = it => {
const config = toNamespace(SCREEN_KEY)(it.commissions[0])
@@ -69,51 +84,43 @@ const Commissions = ({ name: SCREEN_KEY }) => {
return saveConfig({ variables: { config } })
}
- const onEditingDefault = (it, editing) => setEditingDefault(editing)
- const onEditingOverrides = (it, editing) => setEditingOverrides(editing)
-
return (
<>
-
-
-
+
+
+ List view
+
+ {showMachines && (
+
+ )}
+
+ {!showMachines && (
+
-
-
+ )}
>
)
}
diff --git a/new-lamassu-admin/src/pages/Commissions/components/CommissionsDetails.js b/new-lamassu-admin/src/pages/Commissions/components/CommissionsDetails.js
new file mode 100644
index 00000000..77153ee3
--- /dev/null
+++ b/new-lamassu-admin/src/pages/Commissions/components/CommissionsDetails.js
@@ -0,0 +1,78 @@
+import * as R from 'ramda'
+import React, { useState, memo } from 'react'
+
+import { Table as EditableTable } from 'src/components/editableTable'
+import Section from 'src/components/layout/Section'
+import {
+ mainFields,
+ overrides,
+ schema,
+ getOverridesSchema,
+ defaults,
+ overridesDefaults,
+ getOrder
+} from 'src/pages/Commissions/helper'
+
+const CommissionsDetails = memo(
+ ({ config, currency, data, error, save, saveOverrides }) => {
+ const [isEditingDefault, setEditingDefault] = useState(false)
+ const [isEditingOverrides, setEditingOverrides] = useState(false)
+
+ const commission = config && !R.isEmpty(config) ? config : defaults
+ const commissionOverrides = commission?.overrides ?? []
+
+ const orderedCommissionsOverrides = R.sortWith([
+ R.ascend(getOrder),
+ R.ascend(R.prop('machine'))
+ ])(commissionOverrides)
+
+ const onEditingDefault = (it, editing) => setEditingDefault(editing)
+ const onEditingOverrides = (it, editing) => setEditingOverrides(editing)
+
+ return (
+ <>
+
+
+ >
+ )
+ }
+)
+
+export default CommissionsDetails
diff --git a/new-lamassu-admin/src/pages/Commissions/components/CommissionsList.js b/new-lamassu-admin/src/pages/Commissions/components/CommissionsList.js
new file mode 100644
index 00000000..3505698c
--- /dev/null
+++ b/new-lamassu-admin/src/pages/Commissions/components/CommissionsList.js
@@ -0,0 +1,107 @@
+import { makeStyles } from '@material-ui/core'
+import * as R from 'ramda'
+import React, { memo, useState } from 'react'
+
+import { Table as EditableTable } from 'src/components/editableTable'
+import { Select } from 'src/components/inputs'
+import {
+ overridesDefaults,
+ getCommissions,
+ getMachineCoins,
+ getListCommissionsSchema,
+ commissionsList,
+ sortCommissionsBy,
+ filterCommissions,
+ SHOW_ALL,
+ ORDER_OPTIONS
+} from 'src/pages/Commissions/helper'
+
+const styles = {
+ headerLine: {
+ display: 'flex',
+ justifyContent: '',
+ marginBottom: 24,
+ '& div': {
+ marginRight: 24
+ }
+ },
+ tableWrapper: {
+ flex: 1,
+ display: 'block',
+ overflowX: 'auto',
+ width: '100%',
+ maxHeight: '70vh'
+ }
+}
+
+const useStyles = makeStyles(styles)
+
+const CommissionsList = memo(
+ ({ config, localeConfig, currency, data, error, saveOverrides }) => {
+ const classes = useStyles()
+
+ const [machineFilter, setMachineFilter] = useState(SHOW_ALL)
+ const [coinFilter, setCoinFilter] = useState(SHOW_ALL)
+ const [orderProp, setOrderProp] = useState('Machine name')
+
+ const cryptoCurrencies = R.prop('cryptoCurrencies', localeConfig)
+
+ const machines = R.prop('machines', data)
+ const machinesIds = R.map(R.prop('deviceId'))(machines)
+ const machinesNames = R.map(R.prop('name'))(machines)
+
+ const machinesCoins = R.map(m =>
+ R.xprod([m], getMachineCoins(m, localeConfig))
+ )(machinesIds)
+
+ const machinesCoinsTuples = R.unnest(machinesCoins)
+
+ const commissions = R.map(([deviceId, cryptoCode]) =>
+ getCommissions(cryptoCode, deviceId, config)
+ )(machinesCoinsTuples)
+
+ return (
+
+ )
+ }
+)
+
+export default CommissionsList
diff --git a/new-lamassu-admin/src/pages/Commissions/helper.js b/new-lamassu-admin/src/pages/Commissions/helper.js
index 8f9b21ef..ae5f2cb9 100644
--- a/new-lamassu-admin/src/pages/Commissions/helper.js
+++ b/new-lamassu-admin/src/pages/Commissions/helper.js
@@ -1,9 +1,12 @@
+import * as _ from 'lodash/fp'
import * as R from 'ramda'
import React from 'react'
+import { v4 } from 'uuid'
import * as Yup from 'yup'
import { NumberInput } from 'src/components/inputs/formik'
import Autocomplete from 'src/components/inputs/formik/Autocomplete.js'
+import TextInput from 'src/components/inputs/formik/TextInput.js'
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
@@ -17,6 +20,17 @@ const ALL_COINS = {
code: 'ALL_COINS'
}
+const SHOW_ALL = 'Show all'
+
+const ORDER_OPTIONS = [
+ 'Machine name',
+ 'Cryptocurrency',
+ 'Cash-in',
+ 'Cash-out',
+ 'Fixed Fee',
+ 'Minimum Tx'
+]
+
const cashInAndOutHeaderStyle = { marginLeft: 6 }
const cashInHeader = (
@@ -345,6 +359,223 @@ const getOrder = ({ machine, cryptoCurrencies }) => {
return 3
}
+const createCommissions = (cryptoCode, deviceId, isDefault, config) => {
+ return {
+ minimumTx: config.minimumTx,
+ fixedFee: config.fixedFee,
+ cashOut: config.cashOut,
+ cashIn: config.cashIn,
+ machine: deviceId,
+ cryptoCurrencies: [cryptoCode],
+ default: isDefault,
+ id: v4()
+ }
+}
+
+const getCommissions = (cryptoCode, deviceId, config) => {
+ const overrides = R.prop('overrides', config)
+
+ if (overrides && !R.isEmpty(overrides)) {
+ const specificOverride = R.find(
+ it =>
+ it.machine === deviceId && _.includes(cryptoCode)(it.cryptoCurrencies)
+ )(overrides)
+
+ if (specificOverride !== undefined)
+ return createCommissions(cryptoCode, deviceId, false, specificOverride)
+
+ const machineOverride = R.find(
+ it =>
+ it.machine === deviceId && _.includes('ALL_COINS')(it.cryptoCurrencies)
+ )(overrides)
+
+ if (machineOverride !== undefined)
+ return createCommissions(cryptoCode, deviceId, false, machineOverride)
+
+ const coinOverride = R.find(
+ it =>
+ it.machine === 'ALL_MACHINES' &&
+ _.includes(cryptoCode)(it.cryptoCurrencies)
+ )(overrides)
+
+ if (coinOverride !== undefined)
+ return createCommissions(cryptoCode, deviceId, false, coinOverride)
+ }
+
+ return createCommissions(cryptoCode, deviceId, true, config)
+}
+
+const getMachineCoins = (deviceId, localeConfig) => {
+ const machineCoins = R.prop('cryptoCurrencies', localeConfig)
+
+ const overrides = R.prop('overrides', localeConfig)
+
+ if (!R.isEmpty(overrides)) {
+ const override = R.find(it => it.machine === deviceId)(overrides)
+
+ if (override !== undefined) return R.prop('cryptoCurrencies', override)
+ }
+ return machineCoins
+}
+
+const getListCommissionsSchema = () => {
+ return Yup.object().shape({
+ machine: Yup.string()
+ .label('Machine')
+ .required(),
+ cryptoCurrencies: Yup.array()
+ .label('Crypto Currency')
+ .required(),
+ cashIn: Yup.number()
+ .label('Cash-in')
+ .min(0)
+ .max(percentMax)
+ .required(),
+ cashOut: Yup.number()
+ .label('Cash-out')
+ .min(0)
+ .max(percentMax)
+ .required(),
+ fixedFee: Yup.number()
+ .label('Fixed Fee')
+ .min(0)
+ .max(currencyMax)
+ .required(),
+ minimumTx: Yup.number()
+ .label('Minimum Tx')
+ .min(0)
+ .max(currencyMax)
+ .required()
+ })
+}
+
+const getTextStyle = (obj, isEditing) => {
+ return { color: obj.default ? '#1b2559' : '#44e188' }
+}
+
+const commissionsList = (auxData, currency, auxElements) => {
+ const getData = R.path(R.__, auxData)
+
+ return getListCommissionsFields(getData, currency, defaults)
+}
+
+const getListCommissionsFields = (getData, currency, defaults) => {
+ const machineData = [ALL_MACHINES].concat(getData(['machines']))
+ // const rawCryptos = getData(['cryptoCurrencies'])
+ // const cryptoData = R.map(it => ({ display: it.code, code: it.code }))(
+ // rawCryptos ?? []
+ // )
+
+ return [
+ {
+ name: 'machine',
+ width: 196,
+ size: 'sm',
+ view: getView(machineData, 'name', 'deviceId'),
+ input: TextInput,
+ editable: false,
+ inputProps: {
+ valueProp: 'deviceId',
+ getLabel: R.path(['name'])
+ }
+ },
+ {
+ name: 'cryptoCurrencies',
+ display: 'Crypto Currency',
+ width: 280,
+ view: R.prop(0),
+ size: 'sm',
+ input: TextInput,
+ editable: false
+ },
+ {
+ header: cashInHeader,
+ name: 'cashIn',
+ display: 'Cash-in',
+ width: 130,
+ input: NumberInput,
+ textAlign: 'right',
+ suffix: '%',
+ textStyle: obj => getTextStyle(obj),
+ inputProps: {
+ decimalPlaces: 3
+ }
+ },
+ {
+ header: cashOutHeader,
+ name: 'cashOut',
+ display: 'Cash-out',
+ width: 130,
+ input: NumberInput,
+ textAlign: 'right',
+ greenText: true,
+ suffix: '%',
+ textStyle: obj => getTextStyle(obj),
+ inputProps: {
+ decimalPlaces: 3
+ }
+ },
+ {
+ name: 'fixedFee',
+ display: 'Fixed fee',
+ width: 144,
+ input: NumberInput,
+ doubleHeader: 'Cash-in only',
+ textAlign: 'right',
+ suffix: currency,
+ textStyle: obj => getTextStyle(obj),
+ inputProps: {
+ decimalPlaces: 2
+ }
+ },
+ {
+ name: 'minimumTx',
+ display: 'Minimun Tx',
+ width: 144,
+ input: NumberInput,
+ doubleHeader: 'Cash-in only',
+ textAlign: 'right',
+ suffix: currency,
+ textStyle: obj => getTextStyle(obj),
+ inputProps: {
+ decimalPlaces: 2
+ }
+ }
+ ]
+}
+
+const filterCommissions = (coinFilter, machineFilter, machines) =>
+ R.compose(
+ R.filter(byMachine(machineFilter, machines)),
+ R.filter(byCoin(coinFilter))
+ )
+
+const byMachine = (filter, machines) => it =>
+ (filter === SHOW_ALL) |
+ (filter === getView(machines, 'name', 'deviceId')(it.machine))
+
+const byCoin = filter => it =>
+ (filter === SHOW_ALL) | (filter === it.cryptoCurrencies[0])
+
+const sortCommissionsBy = (prop, machines) => {
+ switch (prop) {
+ case ORDER_OPTIONS[1]:
+ return R.sortBy(R.path(['cryptoCurrencies', 0]))
+ case ORDER_OPTIONS[2]:
+ return R.sortBy(R.prop('cashIn'))
+ case ORDER_OPTIONS[3]:
+ return R.sortBy(R.prop('cashOut'))
+ case ORDER_OPTIONS[4]:
+ return R.sortBy(R.prop('fixedFee'))
+ case ORDER_OPTIONS[5]:
+ return R.sortBy(R.prop('minimumTx'))
+ default:
+ return R.sortBy(
+ R.compose(getView(machines, 'name', 'deviceId'), R.prop('machine'))
+ )
+ }
+}
+
export {
mainFields,
overrides,
@@ -352,5 +583,16 @@ export {
getOverridesSchema,
defaults,
overridesDefaults,
- getOrder
+ getOrder,
+ getCommissions,
+ getMachineCoins,
+ getListCommissionsSchema,
+ commissionsList,
+ getView,
+ byMachine,
+ byCoin,
+ sortCommissionsBy,
+ filterCommissions,
+ SHOW_ALL,
+ ORDER_OPTIONS
}
diff --git a/new-lamassu-admin/src/utils/string.js b/new-lamassu-admin/src/utils/string.js
index 09dd8360..6b62ea0a 100644
--- a/new-lamassu-admin/src/utils/string.js
+++ b/new-lamassu-admin/src/utils/string.js
@@ -26,4 +26,4 @@ const startCase = R.compose(
splitOnUpper
)
-export { startCase, onlyFirstToUpper, formatLong }
+export { startCase, toFirstUpper, onlyFirstToUpper, formatLong }