Merge remote-tracking branch 'upstream/release-7.5.0' into chore/merge-release-into-dev
1
.env.sample
Normal file
|
|
@ -0,0 +1 @@
|
|||
LAMASSU_DB=DEV
|
||||
1
.gitignore
vendored
|
|
@ -40,3 +40,4 @@ terraform.*
|
|||
.terraform
|
||||
|
||||
db.json
|
||||
.env
|
||||
|
|
|
|||
34
bin/lamassu-update-cassettes
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const _ = require('lodash')
|
||||
const db = require('../lib/db')
|
||||
|
||||
if (process.argv.length !== 4) {
|
||||
console.log('Usage: lamassu-update-cassettes <device_id> <number_of_cassettes>')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
if (!_.isFinite(parseInt(process.argv[3]))) {
|
||||
console.log('Error: <number_of_cassettes> is not a valid number (%s)', err)
|
||||
process.exit(3)
|
||||
}
|
||||
|
||||
if (parseInt(process.argv[3]) > 4 || parseInt(process.argv[3]) < 2) {
|
||||
console.log('Error: <number_of_cassettes> is out of range. Should be a number between 2 and 4')
|
||||
process.exit(3)
|
||||
}
|
||||
|
||||
const deviceId = process.argv[2]
|
||||
const numberOfCassettes = parseInt(process.argv[3])
|
||||
|
||||
const query = `UPDATE devices SET number_of_cassettes = $1 WHERE device_id = $2`
|
||||
|
||||
db.none(query, [numberOfCassettes, deviceId])
|
||||
.then(() => {
|
||||
console.log('Success! Device %s updated to %s cassettes', deviceId, numberOfCassettes)
|
||||
process.exit(0)
|
||||
})
|
||||
.catch(err => {
|
||||
console.log('Error: %s', err)
|
||||
process.exit(3)
|
||||
})
|
||||
|
|
@ -33,7 +33,7 @@ function batch () {
|
|||
order by created desc limit $2`
|
||||
|
||||
const cashOutSql = `select 'cashOut' as tx_class, cash_out_txs.*,
|
||||
(extract(epoch from (now() - greatest(created, confirmed_at))) * 1000) >= $2 as expired
|
||||
(NOT dispense AND extract(epoch from (now() - greatest(created, confirmed_at))) >= $2) as expired
|
||||
from cash_out_txs
|
||||
order by created desc limit $1`
|
||||
|
||||
|
|
@ -51,7 +51,7 @@ function single (txId) {
|
|||
where id=$2`
|
||||
|
||||
const cashOutSql = `select 'cashOut' as tx_class,
|
||||
(extract(epoch from (now() - greatest(created, confirmed_at))) * 1000) >= $2 as expired,
|
||||
(NOT dispense AND extract(epoch from (now() - greatest(created, confirmed_at))) >= $2) as expired,
|
||||
cash_out_txs.*
|
||||
from cash_out_txs
|
||||
where id=$1`
|
||||
|
|
|
|||
217
lib/bill-math.js
|
|
@ -1,16 +1,78 @@
|
|||
const _ = require('lodash/fp')
|
||||
const uuid = require('uuid')
|
||||
|
||||
// Custom algorith for two cassettes. For three or more denominations, we'll need
|
||||
// to rethink this. Greedy algorithm fails to find *any* solution in some cases.
|
||||
// Dynamic programming may be too inefficient for large amounts.
|
||||
//
|
||||
// We can either require canononical denominations for 3+, or try to expand
|
||||
// this algorithm.
|
||||
exports.makeChange = function makeChange (cassettes, amount) {
|
||||
// Note: Everything here is converted to primitive numbers,
|
||||
// since they're all integers, well within JS number range,
|
||||
// and this is way more efficient in a tight loop.
|
||||
const MAX_AMOUNT_OF_SOLUTIONS = 10000
|
||||
const MAX_BRUTEFORCE_ITERATIONS = 10000000
|
||||
|
||||
function newSolution(cassettes, c0, c1, c2, c3, shouldFlip) {
|
||||
return [
|
||||
{
|
||||
provisioned: shouldFlip ? cassettes[0].count - c0 : c0,
|
||||
denomination: cassettes[0].denomination
|
||||
},
|
||||
{
|
||||
provisioned: shouldFlip ? cassettes[1].count - c1 : c1,
|
||||
denomination: cassettes[1].denomination
|
||||
},
|
||||
{
|
||||
provisioned: shouldFlip ? cassettes[2].count - c2 : c2,
|
||||
denomination: cassettes[2].denomination
|
||||
},
|
||||
{
|
||||
provisioned: shouldFlip ? cassettes[3].count - c3 : c3,
|
||||
denomination: cassettes[3].denomination
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
function mergeCassettes(cassettes) {
|
||||
const map = {}
|
||||
|
||||
_.forEach(it => {
|
||||
if (!map[it.denomination]) {
|
||||
map[it.denomination] = 0
|
||||
}
|
||||
map[it.denomination] += it.count
|
||||
}, cassettes)
|
||||
|
||||
return _.map(it => ({ denomination: it, count: map[it] }), _.keys(map))
|
||||
}
|
||||
|
||||
function unmergeCassettes(cassettes, output) {
|
||||
const map = {}
|
||||
|
||||
_.forEach(it => {
|
||||
if (!map[it.denomination]) {
|
||||
map[it.denomination] = 0
|
||||
}
|
||||
map[it.denomination] += it.provisioned
|
||||
}, output)
|
||||
|
||||
const response = []
|
||||
_.forEach(it => {
|
||||
const value = {
|
||||
denomination: it.denomination,
|
||||
id: uuid.v4()
|
||||
}
|
||||
|
||||
const amountNeeded = map[it.denomination]
|
||||
if (!amountNeeded) {
|
||||
return response.push({ provisioned: 0, ...value })
|
||||
}
|
||||
|
||||
if (amountNeeded < it.count) {
|
||||
map[it.denomination] = 0
|
||||
return response.push({ provisioned: amountNeeded, ...value })
|
||||
}
|
||||
|
||||
map[it.denomination] -= it.count
|
||||
return response.push({ provisioned: it.count, ...value })
|
||||
}, cassettes)
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
function makeChangeDuo(cassettes, amount) {
|
||||
const small = cassettes[0]
|
||||
const large = cassettes[1]
|
||||
|
||||
|
|
@ -23,15 +85,140 @@ exports.makeChange = function makeChange (cassettes, amount) {
|
|||
const remainder = amountNum - largeDenom * i
|
||||
|
||||
if (remainder % smallDenom !== 0) continue
|
||||
|
||||
const smallCount = remainder / smallDenom
|
||||
if (smallCount > small.count) continue
|
||||
|
||||
return [
|
||||
{provisioned: smallCount, denomination: small.denomination, id: uuid.v4()},
|
||||
{provisioned: i, denomination: largeDenom, id: uuid.v4()}
|
||||
{
|
||||
provisioned: smallCount,
|
||||
denomination: small.denomination,
|
||||
id: uuid.v4()
|
||||
},
|
||||
{ provisioned: i, denomination: largeDenom, id: uuid.v4() }
|
||||
]
|
||||
}
|
||||
|
||||
return null
|
||||
return []
|
||||
}
|
||||
|
||||
function makeChange(outCassettes, amount) {
|
||||
const available = _.reduce(
|
||||
(res, val) => res + val.count * val.denomination,
|
||||
0,
|
||||
outCassettes
|
||||
)
|
||||
|
||||
if (available < amount) {
|
||||
console.log(`Tried to dispense more than was available for amount ${amount.toNumber()} with cassettes ${JSON.stringify(cassettes)}`)
|
||||
return null
|
||||
}
|
||||
|
||||
const cassettes = mergeCassettes(outCassettes)
|
||||
const result =
|
||||
_.size(cassettes) >= 3
|
||||
? makeChangeDynamic(cassettes, amount, available)
|
||||
: makeChangeDuo(cassettes, amount)
|
||||
|
||||
if (!result.length) return null
|
||||
return unmergeCassettes(outCassettes, result)
|
||||
}
|
||||
|
||||
function makeChangeDynamicBruteForce(outCassettes, amount, available) {
|
||||
const solutions = []
|
||||
let x = 0
|
||||
|
||||
const shouldFlip = amount > _.max(_.map(it => it.denomination * it.count, outCassettes))
|
||||
const amountNum = shouldFlip ? available - amount : amount
|
||||
|
||||
const cassettes = shouldFlip ? _.reverse(outCassettes) : outCassettes
|
||||
const { denomination: denomination0, count: count0 } = cassettes[0]
|
||||
const { denomination: denomination1, count: count1 } = cassettes[1]
|
||||
const { denomination: denomination2, count: count2 } = cassettes[2]
|
||||
const { denomination: denomination3, count: count3 } = cassettes[3]
|
||||
|
||||
const startTime = new Date().getTime()
|
||||
|
||||
loop1: for (let i = 0; i <= count0; i++) {
|
||||
const firstSum = i * denomination0
|
||||
|
||||
for (let j = 0; j <= count1; j++) {
|
||||
const secondSum = firstSum + j * denomination1
|
||||
if (secondSum > amountNum) break
|
||||
|
||||
if (secondSum === amountNum) {
|
||||
solutions.push(newSolution(cassettes, i, j, 0, 0, shouldFlip))
|
||||
}
|
||||
|
||||
for (let k = 0; k <= count2; k++) {
|
||||
const thirdSum = secondSum + k * denomination2
|
||||
if (thirdSum > amountNum) break
|
||||
|
||||
if (denomination2 === 0) break
|
||||
|
||||
if (thirdSum === amountNum) {
|
||||
solutions.push(newSolution(cassettes, i, j, k, 0, shouldFlip))
|
||||
}
|
||||
|
||||
for (let l = 0; l <= count3; l++) {
|
||||
if ((x > MAX_AMOUNT_OF_SOLUTIONS && solutions.length >= 1) || x > MAX_BRUTEFORCE_ITERATIONS) break loop1
|
||||
x++
|
||||
const fourthSum = thirdSum + l * denomination3
|
||||
if (fourthSum > amountNum) break
|
||||
|
||||
if (denomination3 === 0) break
|
||||
|
||||
if (fourthSum === amountNum) {
|
||||
solutions.push(newSolution(cassettes, i, j, k, l, shouldFlip))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const endTime = new Date().getTime()
|
||||
|
||||
console.log(`Exiting bruteforce after ${x} tries. Took ${endTime - startTime} ms`)
|
||||
return solutions
|
||||
}
|
||||
|
||||
function makeChangeDynamic(cassettes, amount, available) {
|
||||
while (_.size(cassettes) < 4) {
|
||||
cassettes.push({ denomination: 0, count: 0 })
|
||||
}
|
||||
|
||||
const amountNum = amount.toNumber()
|
||||
|
||||
const solutions = makeChangeDynamicBruteForce(cassettes, amountNum, available)
|
||||
|
||||
const sortedSolutions = _.sortBy(it => {
|
||||
const arr = []
|
||||
|
||||
for (let la = 0; la < 4; la++) {
|
||||
arr.push(cassettes[la].count - it[la].provisioned)
|
||||
}
|
||||
|
||||
if (arr.length < 2) return Infinity
|
||||
return _.max(arr) - _.min(arr)
|
||||
}, solutions)
|
||||
|
||||
const cleanSolution = _.filter(
|
||||
it => it.denomination > 0,
|
||||
_.head(sortedSolutions)
|
||||
)
|
||||
|
||||
const response = cleanSolution
|
||||
|
||||
// Final sanity check
|
||||
let total = 0
|
||||
_.forEach(it => {
|
||||
total += it.provisioned * it.denomination
|
||||
}, response)
|
||||
|
||||
if (total === amountNum) return response
|
||||
|
||||
console.log(
|
||||
`Failed to find a solution for ${amountNum} with cassettes ${JSON.stringify(cassettes)}`
|
||||
)
|
||||
return []
|
||||
}
|
||||
|
||||
module.exports = { makeChange }
|
||||
|
|
|
|||
|
|
@ -25,16 +25,16 @@ const BINARIES = {
|
|||
BTC: {
|
||||
defaultUrl: 'https://bitcoincore.org/bin/bitcoin-core-0.20.0/bitcoin-0.20.0-x86_64-linux-gnu.tar.gz',
|
||||
defaultDir: 'bitcoin-0.20.0/bin',
|
||||
url: 'https://bitcoincore.org/bin/bitcoin-core-0.21.0/bitcoin-0.21.0-x86_64-linux-gnu.tar.gz',
|
||||
dir: 'bitcoin-0.21.0/bin'
|
||||
url: 'https://bitcoincore.org/bin/bitcoin-core-22.0/bitcoin-22.0-x86_64-linux-gnu.tar.gz',
|
||||
dir: 'bitcoin-22.0/bin'
|
||||
},
|
||||
ETH: {
|
||||
url: 'https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.10.8-26675454.tar.gz',
|
||||
dir: 'geth-linux-amd64-1.10.8-26675454'
|
||||
url: 'https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.10.12-6c4dc6c3.tar.gz',
|
||||
dir: 'geth-linux-amd64-1.10.12-6c4dc6c3'
|
||||
},
|
||||
ZEC: {
|
||||
url: 'https://z.cash/downloads/zcash-4.4.1-linux64-debian-stretch.tar.gz',
|
||||
dir: 'zcash-4.4.1/bin'
|
||||
url: 'https://z.cash/downloads/zcash-4.5.1-1-linux64-debian-stretch.tar.gz',
|
||||
dir: 'zcash-4.5.1-1/bin'
|
||||
},
|
||||
DASH: {
|
||||
url: 'https://github.com/dashpay/dash/releases/download/v0.17.0.3/dashcore-0.17.0.3-x86_64-linux-gnu.tar.gz',
|
||||
|
|
@ -83,6 +83,8 @@ autostart=true
|
|||
autorestart=true
|
||||
stderr_logfile=/var/log/supervisor/${cryptoCode}${isWallet ? `-wallet` : ``}.err.log
|
||||
stdout_logfile=/var/log/supervisor/${cryptoCode}${isWallet ? `-wallet` : ``}.out.log
|
||||
stderr_logfile_backups=2
|
||||
stdout_logfile_backups=2
|
||||
environment=HOME="/root"
|
||||
`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,6 +26,6 @@ function updateCore (coinRec, isCurrentlyRunning) {
|
|||
function setup (dataDir) {
|
||||
const coinRec = coinUtils.getCryptoCurrency('ETH')
|
||||
common.firewall([coinRec.defaultPort])
|
||||
const cmd = `/usr/local/bin/${coinRec.daemon} --datadir "${dataDir}" --syncmode="light" --cache 2048 --maxpeers 40 --rpc`
|
||||
const cmd = `/usr/local/bin/${coinRec.daemon} --datadir "${dataDir}" --syncmode="light" --cache 2048 --maxpeers 40 --http`
|
||||
common.writeSupervisorConfig(coinRec, cmd)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,8 +23,8 @@ const PLUGINS = {
|
|||
DASH: require('./dash.js'),
|
||||
ETH: require('./ethereum.js'),
|
||||
LTC: require('./litecoin.js'),
|
||||
ZEC: require('./zcash.js'),
|
||||
XMR: require('./monero.js')
|
||||
XMR: require('./monero.js'),
|
||||
ZEC: require('./zcash.js')
|
||||
}
|
||||
|
||||
module.exports = {run}
|
||||
|
|
|
|||
|
|
@ -37,14 +37,14 @@ function mapDispense (tx) {
|
|||
|
||||
if (_.isEmpty(bills)) return {}
|
||||
|
||||
return {
|
||||
provisioned_1: bills[0].provisioned,
|
||||
provisioned_2: bills[1].provisioned,
|
||||
dispensed_1: bills[0].dispensed,
|
||||
dispensed_2: bills[1].dispensed,
|
||||
rejected_1: bills[0].rejected,
|
||||
rejected_2: bills[1].rejected,
|
||||
denomination_1: bills[0].denomination,
|
||||
denomination_2: bills[1].denomination
|
||||
}
|
||||
const res = {}
|
||||
|
||||
_.forEach(it => {
|
||||
res[`provisioned_${it + 1}`] = bills[it].provisioned
|
||||
res[`denomination_${it + 1}`] = bills[it].denomination
|
||||
res[`dispensed_${it + 1}`] = bills[it].dispensed
|
||||
res[`rejected_${it + 1}`] = bills[it].rejected
|
||||
}, _.times(_.identity(), _.size(bills)))
|
||||
|
||||
return res
|
||||
}
|
||||
|
|
|
|||
|
|
@ -108,16 +108,24 @@ function updateCassettes (t, tx) {
|
|||
if (!dispenseOccurred(tx.bills)) return Promise.resolve()
|
||||
|
||||
const sql = `update devices set
|
||||
cassette1 = cassette1 - $1,
|
||||
cassette2 = cassette2 - $2
|
||||
where device_id = $3
|
||||
returning cassette1, cassette2`
|
||||
${_.size(tx.bills) > 0 ? `cassette1 = cassette1 - $1` : ``}
|
||||
${_.size(tx.bills) > 1 ? `, cassette2 = cassette2 - $2` : ``}
|
||||
${_.size(tx.bills) > 2 ? `, cassette3 = cassette3 - $3` : ``}
|
||||
${_.size(tx.bills) > 3 ? `, cassette4 = cassette4 - $4` : ``}
|
||||
where device_id = $${_.size(tx.bills) + 1}
|
||||
returning
|
||||
${_.size(tx.bills) > 0 ? `cassette1` : ``}
|
||||
${_.size(tx.bills) > 1 ? `, cassette2`: ``}
|
||||
${_.size(tx.bills) > 2 ? `, cassette3` : ``}
|
||||
${_.size(tx.bills) > 3 ? `, cassette4` : ``}`
|
||||
|
||||
const values = [
|
||||
tx.bills[0].dispensed + tx.bills[0].rejected,
|
||||
tx.bills[1].dispensed + tx.bills[1].rejected,
|
||||
tx.deviceId
|
||||
]
|
||||
const values = []
|
||||
|
||||
_.forEach(it => values.push(
|
||||
tx.bills[it].dispensed + tx.bills[it].rejected
|
||||
), _.times(_.identity(), _.size(tx.bills)))
|
||||
|
||||
values.push(tx.deviceId)
|
||||
|
||||
return t.one(sql, values)
|
||||
.then(r => socket.emit(_.assign(r, {op: 'cassetteUpdate', deviceId: tx.deviceId})))
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@ const db = require('../db')
|
|||
const T = require('../time')
|
||||
const BN = require('../bn')
|
||||
|
||||
const REDEEMABLE_AGE = T.day
|
||||
// FP operations on Postgres result in very big errors.
|
||||
// E.g.: 1853.013808 * 1000 = 1866149.494
|
||||
const REDEEMABLE_AGE = T.day / 1000
|
||||
|
||||
const CASH_OUT_TRANSACTION_STATES = `
|
||||
case
|
||||
|
|
@ -47,12 +49,18 @@ function addDbBills (tx) {
|
|||
const bills = tx.bills
|
||||
if (_.isEmpty(bills)) return tx
|
||||
|
||||
return _.assign(tx, {
|
||||
provisioned1: bills[0].provisioned,
|
||||
provisioned2: bills[1].provisioned,
|
||||
denomination1: bills[0].denomination,
|
||||
denomination2: bills[1].denomination
|
||||
})
|
||||
const billsObj = {
|
||||
provisioned1: bills[0]?.provisioned ?? 0,
|
||||
provisioned2: bills[1]?.provisioned ?? 0,
|
||||
provisioned3: bills[2]?.provisioned ?? 0,
|
||||
provisioned4: bills[3]?.provisioned ?? 0,
|
||||
denomination1: bills[0]?.denomination ?? 0,
|
||||
denomination2: bills[1]?.denomination ?? 0,
|
||||
denomination3: bills[2]?.denomination ?? 0,
|
||||
denomination4: bills[3]?.denomination ?? 0
|
||||
}
|
||||
|
||||
return _.assign(tx, billsObj)
|
||||
}
|
||||
|
||||
function toDb (tx) {
|
||||
|
|
@ -84,12 +92,12 @@ function toObj (row) {
|
|||
|
||||
newObj.direction = 'cashOut'
|
||||
|
||||
const billFields = ['denomination1', 'denomination2', 'provisioned1', 'provisioned2']
|
||||
const billFields = ['denomination1', 'denomination2', 'denomination3', 'denomination4', 'provisioned1', 'provisioned2', 'provisioned3', 'provisioned4']
|
||||
|
||||
if (_.every(_.isNil, _.at(billFields, newObj))) return newObj
|
||||
if (_.some(_.isNil, _.at(billFields, newObj))) throw new Error('Missing cassette values')
|
||||
|
||||
const bills = [
|
||||
const billFieldsArr = [
|
||||
{
|
||||
denomination: newObj.denomination1,
|
||||
provisioned: newObj.provisioned1
|
||||
|
|
@ -97,9 +105,21 @@ function toObj (row) {
|
|||
{
|
||||
denomination: newObj.denomination2,
|
||||
provisioned: newObj.provisioned2
|
||||
},
|
||||
{
|
||||
denomination: newObj.denomination3,
|
||||
provisioned: newObj.provisioned3
|
||||
},
|
||||
{
|
||||
denomination: newObj.denomination4,
|
||||
provisioned: newObj.provisioned4
|
||||
}
|
||||
]
|
||||
|
||||
// There can't be bills with denomination === 0.
|
||||
// If a bill has denomination === 0, then that cassette is not set and should be filtered out.
|
||||
const bills = _.filter(it => it.denomination > 0, billFieldsArr)
|
||||
|
||||
return _.set('bills', bills, _.omit(billFields, newObj))
|
||||
}
|
||||
|
||||
|
|
@ -109,7 +129,7 @@ function redeemableTxs (deviceId) {
|
|||
and redeem=$2
|
||||
and dispense=$3
|
||||
and provisioned_1 is not null
|
||||
and (extract(epoch from (now() - greatest(created, confirmed_at))) * 1000) < $4`
|
||||
and extract(epoch from (now() - greatest(created, confirmed_at))) < $4`
|
||||
|
||||
return db.any(sql, [deviceId, true, false, REDEEMABLE_AGE])
|
||||
.then(_.map(toObj))
|
||||
|
|
|
|||
|
|
@ -63,17 +63,12 @@ function postProcess (txVector, justAuthorized, pi) {
|
|||
return bills
|
||||
})
|
||||
.then(bills => {
|
||||
const provisioned1 = bills[0].provisioned
|
||||
const provisioned2 = bills[1].provisioned
|
||||
const denomination1 = bills[0].denomination
|
||||
const denomination2 = bills[1].denomination
|
||||
const rec = {}
|
||||
|
||||
const rec = {
|
||||
provisioned_1: provisioned1,
|
||||
provisioned_2: provisioned2,
|
||||
denomination_1: denomination1,
|
||||
denomination_2: denomination2
|
||||
}
|
||||
_.forEach(it => {
|
||||
rec[`provisioned_${it + 1}`] = bills[it].provisioned
|
||||
rec[`denomination_${it + 1}`] = bills[it].denomination
|
||||
}, _.times(_.identity(), _.size(bills)))
|
||||
|
||||
return cashOutActions.logAction(db, 'provisionNotes', rec, newTx)
|
||||
.then(_.constant({ bills }))
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ function getMachines () {
|
|||
cashbox: r.cashbox,
|
||||
cassette1: r.cassette1,
|
||||
cassette2: r.cassette2,
|
||||
cassette3: r.cassette3,
|
||||
cassette4: r.cassette4,
|
||||
numberOfCassettes: r.number_of_cassettes,
|
||||
version: r.version,
|
||||
model: r.model,
|
||||
pairedAt: new Date(r.created),
|
||||
|
|
@ -74,21 +77,7 @@ function getMachineNames (config) {
|
|||
const mergeByDeviceId = (x, y) => _.values(_.merge(_.keyBy('deviceId', x), _.keyBy('deviceId', y)))
|
||||
const machines = mergeByDeviceId(mergeByDeviceId(rawMachines, heartbeat), performance)
|
||||
|
||||
const addName = r => {
|
||||
const cashOutConfig = configManager.getCashOut(r.deviceId, config)
|
||||
|
||||
const cashOut = !!cashOutConfig.active
|
||||
|
||||
const statuses = [
|
||||
getStatus(
|
||||
_.first(pings[r.deviceId]),
|
||||
_.first(checkStuckScreen(events, r.name))
|
||||
)
|
||||
]
|
||||
|
||||
return _.assign(r, { cashOut, statuses })
|
||||
}
|
||||
return _.map(addName, machines)
|
||||
return machines.map(addName(pings, events, config))
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -115,6 +104,9 @@ function getMachine (machineId, config) {
|
|||
cashbox: r.cashbox,
|
||||
cassette1: r.cassette1,
|
||||
cassette2: r.cassette2,
|
||||
cassette3: r.cassette3,
|
||||
cassette4: r.cassette4,
|
||||
numberOfCassettes: r.number_of_cassettes,
|
||||
version: r.version,
|
||||
model: r.model,
|
||||
pairedAt: new Date(r.created),
|
||||
|
|
@ -127,7 +119,7 @@ function getMachine (machineId, config) {
|
|||
.then(([machine, events, config]) => {
|
||||
const pings = checkPings([machine])
|
||||
|
||||
return [machine].map(addName(pings, events, config))[0]
|
||||
return addName(pings, events, config)(machine)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -138,8 +130,8 @@ function renameMachine (rec) {
|
|||
|
||||
function resetCashOutBills (rec) {
|
||||
const detailB = notifierUtils.buildDetail({ deviceId: rec.deviceId })
|
||||
const sql = `UPDATE devices SET cassette1=$1, cassette2=$2 WHERE device_id=$3;`
|
||||
return db.none(sql, [rec.cassettes[0], rec.cassettes[1], rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance'))
|
||||
const sql = `UPDATE devices SET cassette1=$1, cassette2=$2, cassette3=$3, cassette4=$4 WHERE device_id=$5;`
|
||||
return db.none(sql, [rec.cassettes[0], rec.cassettes[1], rec.cassettes[2], rec.cassettes[3], rec.deviceId]).then(() => notifierQueries.invalidateNotification(detailB, 'fiatBalance'))
|
||||
}
|
||||
|
||||
function emptyCashInBills (rec) {
|
||||
|
|
@ -148,8 +140,8 @@ function emptyCashInBills (rec) {
|
|||
}
|
||||
|
||||
function setCassetteBills (rec) {
|
||||
const sql = 'update devices set cashbox=$1, cassette1=$2, cassette2=$3 where device_id=$4'
|
||||
return db.none(sql, [rec.cashbox, rec.cassettes[0], rec.cassettes[1], rec.deviceId])
|
||||
const sql = 'update devices set cashbox=$1, cassette1=$2, cassette2=$3, cassette3=$4, cassette4=$5 where device_id=$6'
|
||||
return db.none(sql, [rec.cashbox, rec.cassettes[0], rec.cassettes[1], rec.cassettes[2], rec.cassettes[3], rec.deviceId])
|
||||
}
|
||||
|
||||
function unpair (rec) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
const _ = require('lodash/fp')
|
||||
const crypto = require('crypto')
|
||||
|
||||
const logger = require('../logger')
|
||||
|
||||
function sha256 (buf) {
|
||||
const hash = crypto.createHash('sha256')
|
||||
|
||||
|
|
@ -9,6 +11,7 @@ function sha256 (buf) {
|
|||
}
|
||||
|
||||
const populateDeviceId = function (req, res, next) {
|
||||
logger.info(`DEBUG LOG - Method: ${req.method} Path: ${req.path}`)
|
||||
const deviceId = _.isFunction(req.connection.getPeerCertificate)
|
||||
? sha256(req.connection.getPeerCertificate().raw)
|
||||
: null
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ const resolvers = {
|
|||
machine: (...[, { deviceId }]) => machineLoader.getMachine(deviceId)
|
||||
},
|
||||
Mutation: {
|
||||
machineAction: (...[, { deviceId, action, cashbox, cassette1, cassette2, newName }, context]) => machineAction({ deviceId, action, cashbox, cassette1, cassette2, newName }, context)
|
||||
machineAction: (...[, { deviceId, action, cashbox, cassette1, cassette2, cassette3, cassette4, newName }, context]) => machineAction({ deviceId, action, cashbox, cassette1, cassette2, cassette3, cassette4, newName }, context)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ const typeDef = gql`
|
|||
cashbox: Int
|
||||
cassette1: Int
|
||||
cassette2: Int
|
||||
cassette3: Int
|
||||
cassette4: Int
|
||||
numberOfCassettes: Int
|
||||
statuses: [MachineStatus]
|
||||
latestEvent: MachineEvent
|
||||
downloadSpeed: String
|
||||
|
|
@ -51,7 +54,7 @@ const typeDef = gql`
|
|||
}
|
||||
|
||||
type Mutation {
|
||||
machineAction(deviceId:ID!, action: MachineAction!, cashbox: Int, cassette1: Int, cassette2: Int, newName: String): Machine @auth
|
||||
machineAction(deviceId:ID!, action: MachineAction!, cashbox: Int, cassette1: Int, cassette2: Int, cassette3: Int, cassette4: Int, newName: String): Machine @auth
|
||||
}
|
||||
`
|
||||
|
||||
|
|
|
|||
|
|
@ -6,14 +6,14 @@ function getMachine (machineId) {
|
|||
.then(machines => machines.find(({ deviceId }) => deviceId === machineId))
|
||||
}
|
||||
|
||||
function machineAction ({ deviceId, action, cashbox, cassette1, cassette2, newName }, context) {
|
||||
function machineAction ({ deviceId, action, cashbox, cassette1, cassette2, cassette3, cassette4, newName }) {
|
||||
const operatorId = context.res.locals.operatorId
|
||||
return getMachine(deviceId)
|
||||
.then(machine => {
|
||||
if (!machine) throw new UserInputError(`machine:${deviceId} not found`, { deviceId })
|
||||
return machine
|
||||
})
|
||||
.then(machineLoader.setMachine({ deviceId, action, cashbox, cassettes: [cassette1, cassette2], newName }, operatorId))
|
||||
.then(machineLoader.setMachine({ deviceId, action, cashbox, cassettes: [cassette1, cassette2, cassette3, cassette4], newName }, operatorId))
|
||||
.then(getMachine(deviceId))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ function batch (
|
|||
c.id_card_photo_path AS customer_id_card_photo_path,
|
||||
txs.tx_customer_photo_at AS tx_customer_photo_at,
|
||||
txs.tx_customer_photo_path AS tx_customer_photo_path,
|
||||
(extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $1 AS expired
|
||||
(NOT txs.dispense AND extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) >= $1) AS expired
|
||||
FROM (SELECT *, ${CASH_OUT_TRANSACTION_STATES} AS txStatus FROM cash_out_txs) txs
|
||||
INNER JOIN cash_out_actions actions ON txs.id = actions.tx_id
|
||||
AND actions.action = 'provisionAddress'
|
||||
|
|
@ -186,7 +186,7 @@ function getCustomerTransactionsBatch (ids) {
|
|||
c.name AS customer_name,
|
||||
c.front_camera_path AS customer_front_camera_path,
|
||||
c.id_card_photo_path AS customer_id_card_photo_path,
|
||||
(extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $3 AS expired
|
||||
(NOT txs.dispense AND extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) >= $3) AS expired
|
||||
FROM cash_out_txs txs
|
||||
INNER JOIN cash_out_actions actions ON txs.id = actions.tx_id
|
||||
AND actions.action = 'provisionAddress'
|
||||
|
|
@ -230,7 +230,7 @@ function single (txId) {
|
|||
c.front_camera_path AS customer_front_camera_path,
|
||||
|
||||
c.id_card_photo_path AS customer_id_card_photo_path,
|
||||
(extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) * 1000) >= $2 AS expired
|
||||
(NOT txs.dispense AND extract(epoch FROM (now() - greatest(txs.created, txs.confirmed_at))) >= $2) AS expired
|
||||
FROM cash_out_txs txs
|
||||
INNER JOIN cash_out_actions actions ON txs.id = actions.tx_id
|
||||
AND actions.action = 'provisionAddress'
|
||||
|
|
|
|||
|
|
@ -55,6 +55,7 @@ const getGlobalLocale = it => getLocale(null, it)
|
|||
|
||||
const getWalletSettings = (key, it) => _.compose(fromNamespace(key), fromNamespace(namespaces.WALLETS))(it)
|
||||
const getCashOut = (key, it) => _.compose(fromNamespace(key), fromNamespace(namespaces.CASH_OUT))(it)
|
||||
const getGlobalCashOut = fromNamespace(namespaces.CASH_OUT)
|
||||
const getOperatorInfo = fromNamespace(namespaces.OPERATOR_INFO)
|
||||
const getCoinAtmRadar = fromNamespace(namespaces.COIN_ATM_RADAR)
|
||||
const getTermsConditions = fromNamespace(namespaces.TERMS_CONDITIONS)
|
||||
|
|
@ -152,6 +153,7 @@ module.exports = {
|
|||
getAllCryptoCurrencies,
|
||||
getTriggers,
|
||||
getTriggersAutomation,
|
||||
getGlobalCashOut,
|
||||
getCashOut,
|
||||
getCryptosFromWalletNamespace,
|
||||
getCryptoUnits
|
||||
|
|
|
|||
|
|
@ -6,12 +6,12 @@ const _ = require('lodash/fp')
|
|||
|
||||
require('dotenv').config()
|
||||
|
||||
const DATABASE = process.env.LAMASSU_DB ?? 'DEV'
|
||||
|
||||
const DATABASE = process.env.LAMASSU_DB ?? 'PROD'
|
||||
const dbMapping = psqlConf => ({
|
||||
STRESS_TEST: _.replace('lamassu', 'lamassu_stress', psqlConf),
|
||||
RELEASE: _.replace('lamassu', 'lamassu_release', psqlConf),
|
||||
DEV: _.replace('lamassu', 'lamassu', psqlConf)
|
||||
DEV: _.replace('lamassu', 'lamassu', psqlConf),
|
||||
PROD: _.replace('lamassu', 'lamassu', psqlConf)
|
||||
})
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,6 +5,10 @@ const db = require('./db')
|
|||
const options = require('./options')
|
||||
const logger = require('./logger')
|
||||
|
||||
// A machine on an older version (no multicassette code) could be paired with a server with multicassette code.
|
||||
// This makes sure that the server stores a default value
|
||||
const DEFAULT_NUMBER_OF_CASSETTES = 2
|
||||
|
||||
function pullToken (token) {
|
||||
const sql = `delete from pairing_tokens
|
||||
where token=$1
|
||||
|
|
@ -13,23 +17,26 @@ function pullToken (token) {
|
|||
}
|
||||
|
||||
function unpair (deviceId) {
|
||||
const sql = 'delete from devices where device_id=$1'
|
||||
const deleteMachinePings = 'delete from machine_pings where device_id=$1'
|
||||
|
||||
// TODO new-admin: We should remove all configs related to that device. This can get tricky.
|
||||
return Promise.all([db.none(sql, [deviceId]), db.none(deleteMachinePings, [deviceId])])
|
||||
return db.tx(t => {
|
||||
const q1 = t.none('DELETE FROM devices WHERE device_id=$1', [deviceId])
|
||||
const q2 = t.none('DELETE FROM machine_pings WHERE device_id=$1', [deviceId])
|
||||
const q3 = t.none('DELETE FROM machine_network_heartbeat WHERE device_id=$1', [deviceId])
|
||||
const q4 = t.none('DELETE FROM machine_network_performance WHERE device_id=$1', [deviceId])
|
||||
return Promise.all([q1, q2, q3, q4])
|
||||
})
|
||||
}
|
||||
|
||||
function pair (token, deviceId, machineModel) {
|
||||
function pair (token, deviceId, machineModel, numOfCassettes = DEFAULT_NUMBER_OF_CASSETTES) {
|
||||
return pullToken(token)
|
||||
.then(r => {
|
||||
if (r.expired) return false
|
||||
|
||||
const insertSql = `insert into devices (device_id, name) values ($1, $2)
|
||||
const insertSql = `insert into devices (device_id, name, number_of_cassettes) values ($1, $2, $3)
|
||||
on conflict (device_id)
|
||||
do update set paired=TRUE, display=TRUE`
|
||||
|
||||
return db.none(insertSql, [deviceId, r.name])
|
||||
return db.none(insertSql, [deviceId, r.name, numOfCassettes])
|
||||
.then(() => true)
|
||||
})
|
||||
.catch(err => {
|
||||
|
|
|
|||
|
|
@ -112,8 +112,10 @@ function plugins (settings, deviceId) {
|
|||
if (_.isEmpty(redeemableTxs)) return cassettes
|
||||
|
||||
const sumTxs = (sum, tx) => {
|
||||
const bills = tx.bills
|
||||
const sameDenominations = a => a[0].denomination === a[1].denomination
|
||||
// cash-out-helper sends 0 as fallback value, need to filter it out as there are no '0' denominations
|
||||
const bills = _.filter(it => it.denomination > 0, tx.bills)
|
||||
const sameDenominations = a => a[0]?.denomination === a[1]?.denomination
|
||||
|
||||
const doDenominationsMatch = _.every(sameDenominations, _.zip(cassettes, bills))
|
||||
|
||||
if (!doDenominationsMatch) {
|
||||
|
|
@ -123,7 +125,7 @@ function plugins (settings, deviceId) {
|
|||
return _.map(r => r[0] + r[1].provisioned, _.zip(sum, tx.bills))
|
||||
}
|
||||
|
||||
const provisioned = _.reduce(sumTxs, [0, 0], redeemableTxs)
|
||||
const provisioned = _.reduce(sumTxs, _.times(_.constant(0), _.size(cassettes)), redeemableTxs)
|
||||
const zipped = _.zip(_.map('count', cassettes), provisioned)
|
||||
const counts = _.map(r => r[0] - r[1], zipped)
|
||||
|
||||
|
|
@ -131,16 +133,15 @@ function plugins (settings, deviceId) {
|
|||
throw new Error('Negative note count: %j', counts)
|
||||
}
|
||||
|
||||
return [
|
||||
{
|
||||
denomination: cassettes[0].denomination,
|
||||
count: counts[0]
|
||||
},
|
||||
{
|
||||
denomination: cassettes[1].denomination,
|
||||
count: counts[1]
|
||||
}
|
||||
]
|
||||
const computedCassettes = []
|
||||
_.forEach(it => {
|
||||
computedCassettes.push({
|
||||
denomination: cassettes[it].denomination,
|
||||
count: counts[it]
|
||||
})
|
||||
}, _.times(_.identity(), _.size(cassettes)))
|
||||
|
||||
return computedCassettes
|
||||
}
|
||||
|
||||
function buildAvailableCassettes (excludeTxId) {
|
||||
|
|
@ -148,28 +149,32 @@ function plugins (settings, deviceId) {
|
|||
|
||||
if (!cashOutConfig.active) return Promise.resolve()
|
||||
|
||||
const denominations = [cashOutConfig.top, cashOutConfig.bottom]
|
||||
|
||||
const virtualCassettes = [Math.max(cashOutConfig.top, cashOutConfig.bottom) * 2]
|
||||
|
||||
return Promise.all([dbm.cassetteCounts(deviceId), cashOutHelper.redeemableTxs(deviceId, excludeTxId)])
|
||||
.then(([rec, _redeemableTxs]) => {
|
||||
const redeemableTxs = _.reject(_.matchesProperty('id', excludeTxId), _redeemableTxs)
|
||||
|
||||
const denominations = []
|
||||
_.forEach(it => {
|
||||
denominations.push(cashOutConfig[`cassette${it + 1}`])
|
||||
}, _.times(_.identity(), rec.numberOfCassettes))
|
||||
|
||||
const virtualCassettes = [Math.max(...denominations) * 2]
|
||||
|
||||
const counts = argv.cassettes
|
||||
? argv.cassettes.split(',')
|
||||
: rec.counts
|
||||
|
||||
const cassettes = [
|
||||
{
|
||||
denomination: parseInt(denominations[0], 10),
|
||||
count: parseInt(counts[0], 10)
|
||||
},
|
||||
{
|
||||
denomination: parseInt(denominations[1], 10),
|
||||
count: parseInt(counts[1], 10)
|
||||
}
|
||||
]
|
||||
if (rec.counts.length !== denominations.length) {
|
||||
throw new Error('Denominations and respective counts do not match!')
|
||||
}
|
||||
|
||||
const cassettes = []
|
||||
_.forEach(it => {
|
||||
cassettes.push({
|
||||
denomination: parseInt(denominations[it], 10),
|
||||
count: parseInt(counts[it], 10)
|
||||
})
|
||||
}, _.times(_.identity(), rec.numberOfCassettes))
|
||||
|
||||
try {
|
||||
return {
|
||||
|
|
@ -320,7 +325,7 @@ function plugins (settings, deviceId) {
|
|||
|
||||
function dispenseAck (tx) {
|
||||
const cashOutConfig = configManager.getCashOut(deviceId, settings.config)
|
||||
const cassettes = [cashOutConfig.top, cashOutConfig.bottom]
|
||||
const cassettes = [cashOutConfig.cassette1, cashOutConfig.cassette2, cashOutConfig.cassette3, cashOutConfig.cassette4]
|
||||
|
||||
return dbm.addDispense(deviceId, tx, cassettes)
|
||||
}
|
||||
|
|
@ -614,8 +619,10 @@ function plugins (settings, deviceId) {
|
|||
|
||||
function checkDeviceCashBalances (fiatCode, device) {
|
||||
const cashOutConfig = configManager.getCashOut(device.deviceId, settings.config)
|
||||
const denomination1 = cashOutConfig.top
|
||||
const denomination2 = cashOutConfig.bottom
|
||||
const denomination1 = cashOutConfig.cassette1
|
||||
const denomination2 = cashOutConfig.cassette2
|
||||
const denomination3 = cashOutConfig.cassette3
|
||||
const denomination4 = cashOutConfig.cassette4
|
||||
const cashOutEnabled = cashOutConfig.active
|
||||
const isCassetteLow = (have, max, limit) => cashOutEnabled && ((have / max) * 100) < limit
|
||||
|
||||
|
|
@ -632,7 +639,7 @@ function plugins (settings, deviceId) {
|
|||
}
|
||||
: null
|
||||
|
||||
const cassette1Alert = isCassetteLow(device.cassette1, cassetteMaxCapacity, notifications.fillingPercentageCassette1)
|
||||
const cassette1Alert = device.numberOfCassettes >= 1 && isCassetteLow(device.cassette1, cassetteMaxCapacity, notifications.fillingPercentageCassette1)
|
||||
? {
|
||||
code: 'LOW_CASH_OUT',
|
||||
cassette: 1,
|
||||
|
|
@ -644,7 +651,7 @@ function plugins (settings, deviceId) {
|
|||
}
|
||||
: null
|
||||
|
||||
const cassette2Alert = isCassetteLow(device.cassette2, cassetteMaxCapacity, notifications.fillingPercentageCassette2)
|
||||
const cassette2Alert = device.numberOfCassettes >= 2 && isCassetteLow(device.cassette2, cassetteMaxCapacity, notifications.fillingPercentageCassette2)
|
||||
? {
|
||||
code: 'LOW_CASH_OUT',
|
||||
cassette: 2,
|
||||
|
|
@ -656,7 +663,31 @@ function plugins (settings, deviceId) {
|
|||
}
|
||||
: null
|
||||
|
||||
return _.compact([cashInAlert, cassette1Alert, cassette2Alert])
|
||||
const cassette3Alert = device.numberOfCassettes >= 3 && isCassetteLow(device.cassette3, cassetteMaxCapacity, notifications.fillingPercentageCassette3)
|
||||
? {
|
||||
code: 'LOW_CASH_OUT',
|
||||
cassette: 3,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cassette3,
|
||||
denomination: denomination3,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
const cassette4Alert = device.numberOfCassettes >= 4 && isCassetteLow(device.cassette4, cassetteMaxCapacity, notifications.fillingPercentageCassette4)
|
||||
? {
|
||||
code: 'LOW_CASH_OUT',
|
||||
cassette: 4,
|
||||
machineName,
|
||||
deviceId: device.deviceId,
|
||||
notes: device.cassette4,
|
||||
denomination: denomination4,
|
||||
fiatCode
|
||||
}
|
||||
: null
|
||||
|
||||
return _.compact([cashInAlert, cassette1Alert, cassette2Alert, cassette3Alert, cassette4Alert])
|
||||
}
|
||||
|
||||
function checkCryptoBalances (fiatCode, devices) {
|
||||
|
|
|
|||
|
|
@ -98,3 +98,17 @@ function parseConf (confPath) {
|
|||
|
||||
return res
|
||||
}
|
||||
|
||||
function rpcConfig (cryptoRec) {
|
||||
try {
|
||||
const configPath = coinUtils.configPath(cryptoRec)
|
||||
const config = parseConf(configPath)
|
||||
return {
|
||||
username: config.rpcuser,
|
||||
password: config.rpcpassword,
|
||||
port: config.rpcport || cryptoRec.defaultPort
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error('Wallet is currently not installed')
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,24 +8,11 @@ const logger = require('../../../logger')
|
|||
const { utils: coinUtils } = require('lamassu-coins')
|
||||
|
||||
const cryptoRec = coinUtils.getCryptoCurrency('BTC')
|
||||
const configPath = coinUtils.configPath(cryptoRec, options.blockchainDir)
|
||||
const unitScale = cryptoRec.unitScale
|
||||
|
||||
function rpcConfig () {
|
||||
try {
|
||||
const config = jsonRpc.parseConf(configPath)
|
||||
return {
|
||||
username: config.rpcuser,
|
||||
password: config.rpcpassword,
|
||||
port: config.rpcport || cryptoRec.defaultPort
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error('wallet is currently not installed')
|
||||
}
|
||||
}
|
||||
const rpcConfig = jsonRpc.rpcConfig(cryptoRec)
|
||||
|
||||
function fetch (method, params) {
|
||||
return jsonRpc.fetch(rpcConfig(), method, params)
|
||||
return jsonRpc.fetch(rpcConfig, method, params)
|
||||
}
|
||||
|
||||
function checkCryptoCode (cryptoCode) {
|
||||
|
|
|
|||
|
|
@ -8,24 +8,11 @@ const BN = require('../../../bn')
|
|||
const E = require('../../../error')
|
||||
|
||||
const cryptoRec = coinUtils.getCryptoCurrency('DASH')
|
||||
const configPath = coinUtils.configPath(cryptoRec, options.blockchainDir)
|
||||
const unitScale = cryptoRec.unitScale
|
||||
|
||||
function rpcConfig () {
|
||||
try {
|
||||
const config = jsonRpc.parseConf(configPath)
|
||||
return {
|
||||
username: config.rpcuser,
|
||||
password: config.rpcpassword,
|
||||
port: config.rpcport || cryptoRec.defaultPort
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error('wallet is currently not installed')
|
||||
}
|
||||
}
|
||||
const rpcConfig = jsonRpc.rpcConfig(cryptoRec)
|
||||
|
||||
function fetch (method, params) {
|
||||
return jsonRpc.fetch(rpcConfig(), method, params)
|
||||
return jsonRpc.fetch(rpcConfig, method, params)
|
||||
}
|
||||
|
||||
function checkCryptoCode (cryptoCode) {
|
||||
|
|
|
|||
|
|
@ -8,23 +8,11 @@ const BN = require('../../../bn')
|
|||
const E = require('../../../error')
|
||||
|
||||
const cryptoRec = coinUtils.getCryptoCurrency('LTC')
|
||||
const configPath = coinUtils.configPath(cryptoRec, options.blockchainDir)
|
||||
const unitScale = cryptoRec.unitScale
|
||||
const rpcConfig = jsonRpc.rpcConfig(cryptoRec)
|
||||
|
||||
function rpcConfig () {
|
||||
try {
|
||||
const config = jsonRpc.parseConf(configPath)
|
||||
return {
|
||||
username: config.rpcuser,
|
||||
password: config.rpcpassword,
|
||||
port: config.rpcport || cryptoRec.defaultPort
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error('wallet is currently not installed')
|
||||
}
|
||||
}
|
||||
function fetch (method, params) {
|
||||
return jsonRpc.fetch(rpcConfig(), method, params)
|
||||
return jsonRpc.fetch(rpcConfig, method, params)
|
||||
}
|
||||
|
||||
function checkCryptoCode (cryptoCode) {
|
||||
|
|
|
|||
|
|
@ -9,24 +9,11 @@ const BN = require('../../../bn')
|
|||
const E = require('../../../error')
|
||||
|
||||
const cryptoRec = coinUtils.getCryptoCurrency('ZEC')
|
||||
const configPath = coinUtils.configPath(cryptoRec, options.blockchainDir)
|
||||
const unitScale = cryptoRec.unitScale
|
||||
|
||||
function rpcConfig () {
|
||||
try {
|
||||
const config = jsonRpc.parseConf(configPath)
|
||||
return {
|
||||
username: config.rpcuser,
|
||||
password: config.rpcpassword,
|
||||
port: config.rpcport || cryptoRec.defaultPort
|
||||
}
|
||||
} catch (err) {
|
||||
throw new Error('wallet is currently not installed')
|
||||
}
|
||||
}
|
||||
const rpcConfig = jsonRpc.rpcConfig(cryptoRec)
|
||||
|
||||
function fetch (method, params) {
|
||||
return jsonRpc.fetch(rpcConfig(), method, params)
|
||||
return jsonRpc.fetch(rpcConfig, method, params)
|
||||
}
|
||||
|
||||
function checkCryptoCode (cryptoCode) {
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ const TRADE_INTERVAL = 60 * T.seconds
|
|||
const PONG_INTERVAL = 10 * T.seconds
|
||||
const LOGS_CLEAR_INTERVAL = 1 * T.day
|
||||
const SANCTIONS_INITIAL_DOWNLOAD_INTERVAL = 5 * T.minutes
|
||||
const SANCTIONS_UPDATE_INTERVAL = 1 * T.week
|
||||
const SANCTIONS_UPDATE_INTERVAL = 1 * T.day
|
||||
const RADAR_UPDATE_INTERVAL = 5 * T.minutes
|
||||
const PRUNE_MACHINES_HEARTBEAT = 1 * T.day
|
||||
|
||||
|
|
|
|||
|
|
@ -26,13 +26,17 @@ exports.recordDeviceEvent = function recordDeviceEvent (deviceId, event) {
|
|||
}
|
||||
|
||||
exports.cassetteCounts = function cassetteCounts (deviceId) {
|
||||
const sql = 'SELECT cassette1, cassette2 FROM devices ' +
|
||||
const sql = 'SELECT cassette1, cassette2, cassette3, cassette4, number_of_cassettes FROM devices ' +
|
||||
'WHERE device_id=$1'
|
||||
|
||||
return db.one(sql, [deviceId])
|
||||
.then(row => {
|
||||
const counts = [row.cassette1, row.cassette2]
|
||||
return {counts}
|
||||
const counts = []
|
||||
_.forEach(it => {
|
||||
counts.push(row[`cassette${it + 1}`])
|
||||
}, _.times(_.identity(), row.number_of_cassettes))
|
||||
|
||||
return { numberOfCassettes: row.number_of_cassettes, counts }
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,8 +10,9 @@ function pair (req, res, next) {
|
|||
const token = req.query.token
|
||||
const deviceId = req.deviceId
|
||||
const model = req.query.model
|
||||
const numOfCassettes = req.query.numOfCassettes
|
||||
|
||||
return pairing.pair(token, deviceId, model)
|
||||
return pairing.pair(token, deviceId, model, numOfCassettes)
|
||||
.then(isValid => {
|
||||
if (isValid) return res.json({ status: 'paired' })
|
||||
throw httpError('Pairing failed')
|
||||
|
|
|
|||
|
|
@ -11,6 +11,20 @@ const semver = require('semver')
|
|||
const state = require('../middlewares/state')
|
||||
const version = require('../../package.json').version
|
||||
|
||||
const urlsToPing = [
|
||||
`us.archive.ubuntu.com`,
|
||||
`uk.archive.ubuntu.com`,
|
||||
`za.archive.ubuntu.com`,
|
||||
`cn.archive.ubuntu.com`
|
||||
]
|
||||
|
||||
const speedtestFiles = [
|
||||
{
|
||||
url: 'https://github.com/lamassu/speed-test-assets/raw/main/python-defaults_2.7.18-3.tar.gz',
|
||||
size: 44668
|
||||
}
|
||||
]
|
||||
|
||||
function checkHasLightning (settings) {
|
||||
return configManager.getWalletSettings('BTC', settings.config).layer2 !== 'no-layer2'
|
||||
}
|
||||
|
|
@ -86,7 +100,9 @@ function poll (req, res, next) {
|
|||
operatorInfo,
|
||||
machineInfo,
|
||||
triggers,
|
||||
triggersAutomation
|
||||
triggersAutomation,
|
||||
speedtestFiles,
|
||||
urlsToPing
|
||||
}
|
||||
|
||||
// BACKWARDS_COMPATIBILITY 7.6
|
||||
|
|
|
|||
|
|
@ -5,7 +5,9 @@ const CashInTx = require('./cash-in/cash-in-tx')
|
|||
const CashOutTx = require('./cash-out/cash-out-tx')
|
||||
const T = require('./time')
|
||||
|
||||
const REDEEMABLE_AGE = T.day
|
||||
// FP operations on Postgres result in very big errors.
|
||||
// E.g.: 1853.013808 * 1000 = 1866149.494
|
||||
const REDEEMABLE_AGE = T.day / 1000
|
||||
|
||||
function process (tx, pi) {
|
||||
const mtx = massage(tx, pi)
|
||||
|
|
@ -78,7 +80,7 @@ function customerHistory (customerId, thresholdDays) {
|
|||
AND fiat > 0
|
||||
UNION
|
||||
SELECT txOut.id, txOut.created, txOut.fiat, 'cashOut' AS direction,
|
||||
(extract(epoch FROM (now() - greatest(txOut.created, txOut.confirmed_at))) * 1000) >= $4 AS expired
|
||||
(NOT txOut.dispense AND extract(epoch FROM (now() - greatest(txOut.created, txOut.confirmed_at))) >= $4) AS expired
|
||||
FROM cash_out_txs txOut
|
||||
WHERE txOut.customer_id = $1
|
||||
AND txOut.created > now() - interval $2
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ function mergeStatusMode (a, b) {
|
|||
}
|
||||
|
||||
function getWalletStatus (settings, tx) {
|
||||
const fudgeFactorEnabled = configManager.getWalletSettings(tx.cryptoCode, settings.config).fudgeFactorActive
|
||||
const fudgeFactorEnabled = configManager.getGlobalCashOut(settings.config).fudgeFactorActive
|
||||
const fudgeFactor = fudgeFactorEnabled ? 100 : 0
|
||||
const requested = tx.cryptoAtoms.minus(fudgeFactor)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,11 @@ exports.up = function (next) {
|
|||
'cash-out-1-refill',
|
||||
'cash-out-1-empty',
|
||||
'cash-out-2-refill',
|
||||
'cash-out-2-empty'
|
||||
'cash-out-2-empty',
|
||||
'cash-out-3-refill',
|
||||
'cash-out-3-empty',
|
||||
'cash-out-4-refill',
|
||||
'cash-out-4-empty'
|
||||
)`,
|
||||
`ALTER TABLE cashbox_batches ADD COLUMN operation_type cashbox_batch_type NOT NULL`,
|
||||
`ALTER TABLE cashbox_batches ADD COLUMN bill_count_override SMALLINT`,
|
||||
|
|
|
|||
|
|
@ -7,6 +7,8 @@ exports.up = function (next) {
|
|||
.then(({ config }) => {
|
||||
const fiatBalance1 = config.notifications_fiatBalanceCassette1
|
||||
const fiatBalance2 = config.notifications_fiatBalanceCassette2
|
||||
const fiatBalance3 = config.notifications_fiatBalanceCassette3
|
||||
const fiatBalance4 = config.notifications_fiatBalanceCassette4
|
||||
const overrides = config.notifications_fiatBalanceOverrides
|
||||
const newConfig = {}
|
||||
if (fiatBalance1) {
|
||||
|
|
@ -17,6 +19,14 @@ exports.up = function (next) {
|
|||
newConfig.notifications_fillingPercentageCassette2 = (100 * (fiatBalance2 / cassetteMaxCapacity)).toFixed(0)
|
||||
newConfig.notifications_fiatBalanceCassette2 = null
|
||||
}
|
||||
if (fiatBalance3) {
|
||||
newConfig.notifications_fillingPercentageCassette3 = (100 * (fiatBalance3 / cassetteMaxCapacity)).toFixed(0)
|
||||
newConfig.notifications_fiatBalanceCassette3 = null
|
||||
}
|
||||
if (fiatBalance4) {
|
||||
newConfig.notifications_fillingPercentageCassette4 = (100 * (fiatBalance4 / cassetteMaxCapacity)).toFixed(0)
|
||||
newConfig.notifications_fiatBalanceCassette4 = null
|
||||
}
|
||||
|
||||
if (overrides) {
|
||||
newConfig.notifications_fiatBalanceOverrides = _.map(override => {
|
||||
|
|
@ -27,6 +37,12 @@ exports.up = function (next) {
|
|||
if (override.fiatBalanceCassette2) {
|
||||
newOverride.fillingPercentageCassette2 = (100 * (override.fiatBalanceCassette2 / cassetteMaxCapacity)).toFixed(0)
|
||||
}
|
||||
if (override.fiatBalanceCassette3) {
|
||||
newOverride.fillingPercentageCassette3 = (100 * (override.fiatBalanceCassette3 / cassetteMaxCapacity)).toFixed(0)
|
||||
}
|
||||
if (override.fiatBalanceCassette4) {
|
||||
newOverride.fillingPercentageCassette4 = (100 * (override.fiatBalanceCassette4 / cassetteMaxCapacity)).toFixed(0)
|
||||
}
|
||||
newOverride.machine = override.machine
|
||||
newOverride.id = override.id
|
||||
|
||||
|
|
|
|||
48
migrations/1630432869178-add-more-cassette-support.js
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
var db = require('./db')
|
||||
const _ = require('lodash/fp')
|
||||
const { saveConfig, loadLatest } = require('../lib/new-settings-loader')
|
||||
const { getMachines } = require('../lib/machine-loader')
|
||||
|
||||
exports.up = function (next) {
|
||||
var sql = [
|
||||
'ALTER TABLE devices ADD COLUMN cassette3 INTEGER NOT NULL DEFAULT 0',
|
||||
'ALTER TABLE devices ADD COLUMN cassette4 INTEGER NOT NULL DEFAULT 0',
|
||||
'ALTER TABLE cash_out_txs ADD COLUMN provisioned_3 INTEGER',
|
||||
'ALTER TABLE cash_out_txs ADD COLUMN provisioned_4 INTEGER',
|
||||
'ALTER TABLE cash_out_txs ADD COLUMN denomination_3 INTEGER',
|
||||
'ALTER TABLE cash_out_txs ADD COLUMN denomination_4 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN provisioned_3 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN provisioned_4 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN dispensed_3 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN dispensed_4 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN rejected_3 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN rejected_4 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN denomination_3 INTEGER',
|
||||
'ALTER TABLE cash_out_actions ADD COLUMN denomination_4 INTEGER',
|
||||
'ALTER TABLE devices ADD COLUMN number_of_cassettes INTEGER NOT NULL DEFAULT 2'
|
||||
]
|
||||
|
||||
return Promise.all([loadLatest(), getMachines()])
|
||||
.then(([config, machines]) => {
|
||||
const formattedMachines = _.map(it => _.pick(['deviceId'], it), machines)
|
||||
const newConfig = _.reduce((acc, value) => {
|
||||
if(_.includes(`cashOut_${value.deviceId}_top`, _.keys(config.config))) {
|
||||
acc[`cashOut_${value.deviceId}_cassette1`] = config.config[`cashOut_${value.deviceId}_top`]
|
||||
}
|
||||
|
||||
if(_.includes(`cashOut_${value.deviceId}_bottom`, _.keys(config.config))) {
|
||||
acc[`cashOut_${value.deviceId}_cassette2`] = config.config[`cashOut_${value.deviceId}_bottom`]
|
||||
}
|
||||
|
||||
return acc
|
||||
}, {}, formattedMachines)
|
||||
|
||||
return saveConfig(newConfig)
|
||||
.then(() => db.multi(sql, next))
|
||||
.catch(err => next(err))
|
||||
})
|
||||
}
|
||||
|
||||
exports.down = function (next) {
|
||||
next()
|
||||
}
|
||||
|
|
@ -34,6 +34,7 @@ const Header = () => {
|
|||
const {
|
||||
elements,
|
||||
enableEdit,
|
||||
enableEditText,
|
||||
editWidth,
|
||||
enableDelete,
|
||||
deleteWidth,
|
||||
|
|
@ -72,7 +73,7 @@ const Header = () => {
|
|||
{innerElements.map(mapElement2)}
|
||||
{enableEdit && (
|
||||
<Td header width={editWidth} textAlign="center">
|
||||
Edit
|
||||
{enableEditText ?? `Edit`}
|
||||
</Td>
|
||||
)}
|
||||
{enableDelete && (
|
||||
|
|
|
|||
|
|
@ -131,6 +131,7 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
|
|||
suffix,
|
||||
SuffixComponent = Label2,
|
||||
textStyle = it => {},
|
||||
isHidden = it => false,
|
||||
view = it => it?.toString(),
|
||||
inputProps = {}
|
||||
} = config
|
||||
|
|
@ -168,22 +169,25 @@ const ECol = ({ editing, focus, config, extraPaddingRight, extraPadding }) => {
|
|||
size={size}
|
||||
bold={bold}
|
||||
textAlign={textAlign}>
|
||||
{isEditing && isField && (
|
||||
{isEditing && isField && !isHidden(values) && (
|
||||
<Field name={name} component={input} {...innerProps} />
|
||||
)}
|
||||
{isEditing && !isField && <config.input name={name} />}
|
||||
{!isEditing && values && (
|
||||
{isEditing && !isField && !isHidden(values) && (
|
||||
<config.input name={name} />
|
||||
)}
|
||||
{!isEditing && values && !isHidden(values) && (
|
||||
<div style={textStyle(values, isEditing)}>
|
||||
{view(values[name], values)}
|
||||
</div>
|
||||
)}
|
||||
{suffix && (
|
||||
{suffix && !isHidden(values) && (
|
||||
<SuffixComponent
|
||||
className={classes.suffix}
|
||||
style={isEditing ? {} : textStyle(values, isEditing)}>
|
||||
{suffix}
|
||||
</SuffixComponent>
|
||||
)}
|
||||
{isHidden(values) && <StripesSvg />}
|
||||
</Td>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default {
|
|||
paddingRight: 39
|
||||
},
|
||||
withSuffix: ({ textAlign }) => {
|
||||
const justifyContent = textAlign === 'right' ? 'end' : textAlign
|
||||
const justifyContent = textAlign === 'right' ? 'flex-end' : textAlign
|
||||
return {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ const ETable = ({
|
|||
validationSchema,
|
||||
enableCreate,
|
||||
enableEdit,
|
||||
enableEditText,
|
||||
editWidth: outerEditWidth,
|
||||
enableDelete,
|
||||
deleteWidth = ACTION_COL_SIZE,
|
||||
|
|
@ -87,7 +88,6 @@ const ETable = ({
|
|||
}
|
||||
|
||||
setAdding(false)
|
||||
setEditingId(null)
|
||||
setEditing && setEditing(false)
|
||||
setSaving(false)
|
||||
}
|
||||
|
|
@ -139,6 +139,7 @@ const ETable = ({
|
|||
const ctxValue = {
|
||||
elements,
|
||||
enableEdit,
|
||||
enableEditText,
|
||||
onEdit,
|
||||
clearError: () => setError(null),
|
||||
error: error,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ const gridClasses = makeStyles(gridStyles)
|
|||
const Cashbox = ({
|
||||
percent = 0,
|
||||
cashOut = false,
|
||||
width,
|
||||
className,
|
||||
emptyPartClassName,
|
||||
labelClassName,
|
||||
|
|
@ -21,7 +22,13 @@ const Cashbox = ({
|
|||
omitInnerPercentage,
|
||||
isLow
|
||||
}) => {
|
||||
const classes = cashboxClasses({ percent, cashOut, applyColorVariant, isLow })
|
||||
const classes = cashboxClasses({
|
||||
percent,
|
||||
cashOut,
|
||||
width,
|
||||
applyColorVariant,
|
||||
isLow
|
||||
})
|
||||
const ltHalf = percent <= 51
|
||||
|
||||
const showCashBox = {
|
||||
|
|
@ -76,7 +83,8 @@ const CashOut = ({
|
|||
notes,
|
||||
className,
|
||||
editingMode = false,
|
||||
threshold
|
||||
threshold,
|
||||
width
|
||||
}) => {
|
||||
const percent = (100 * notes) / capacity
|
||||
const isLow = percent < threshold
|
||||
|
|
@ -90,6 +98,7 @@ const CashOut = ({
|
|||
percent={percent}
|
||||
cashOut
|
||||
isLow={isLow}
|
||||
width={width}
|
||||
/>
|
||||
</div>
|
||||
{!editingMode && (
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ const cashboxStyles = {
|
|||
borderColor: colorPicker,
|
||||
backgroundColor: colorPicker,
|
||||
height: 118,
|
||||
width: 80,
|
||||
width: ({ width }) => width ?? 80,
|
||||
border: '2px solid',
|
||||
textAlign: 'end',
|
||||
display: 'inline-block'
|
||||
|
|
@ -65,7 +65,7 @@ const gridStyles = {
|
|||
justifyContent: 'flex-start'
|
||||
},
|
||||
col2: {
|
||||
marginLeft: 16
|
||||
marginLeft: 14
|
||||
},
|
||||
noMarginText: {
|
||||
marginTop: 0,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { makeStyles } from '@material-ui/core'
|
||||
import classNames from 'classnames'
|
||||
import React, { memo, useState } from 'react'
|
||||
|
||||
import { CashOut } from 'src/components/inputs/cashbox/Cashbox'
|
||||
|
|
@ -9,40 +10,42 @@ const useStyles = makeStyles({
|
|||
display: 'flex'
|
||||
},
|
||||
cashCassette: {
|
||||
width: 80,
|
||||
height: 36,
|
||||
marginRight: 16
|
||||
marginRight: 14
|
||||
}
|
||||
})
|
||||
|
||||
const CashCassetteInput = memo(({ decimalPlaces, threshold, ...props }) => {
|
||||
const classes = useStyles()
|
||||
const { name, onChange, onBlur, value } = props.field
|
||||
const { touched, errors } = props.form
|
||||
const [notes, setNotes] = useState(value)
|
||||
const error = !!(touched[name] && errors[name])
|
||||
return (
|
||||
<div className={classes.flex}>
|
||||
<CashOut
|
||||
className={classes.cashCassette}
|
||||
notes={notes}
|
||||
editingMode={true}
|
||||
threshold={threshold}
|
||||
/>
|
||||
<NumberInput
|
||||
name={name}
|
||||
onChange={e => {
|
||||
setNotes(e.target.value)
|
||||
return onChange(e)
|
||||
}}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
error={error}
|
||||
decimalPlaces={decimalPlaces}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
const CashCassetteInput = memo(
|
||||
({ decimalPlaces, width, threshold, inputClassName, ...props }) => {
|
||||
const classes = useStyles()
|
||||
const { name, onChange, onBlur, value } = props.field
|
||||
const { touched, errors } = props.form
|
||||
const [notes, setNotes] = useState(value)
|
||||
const error = !!(touched[name] && errors[name])
|
||||
return (
|
||||
<div className={classes.flex}>
|
||||
<CashOut
|
||||
className={classNames(classes.cashCassette, inputClassName)}
|
||||
notes={notes}
|
||||
editingMode={true}
|
||||
width={width}
|
||||
threshold={threshold}
|
||||
/>
|
||||
<NumberInput
|
||||
name={name}
|
||||
onChange={e => {
|
||||
setNotes(e.target.value)
|
||||
return onChange(e)
|
||||
}}
|
||||
onBlur={onBlur}
|
||||
value={value}
|
||||
error={error}
|
||||
decimalPlaces={decimalPlaces}
|
||||
{...props}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
export default CashCassetteInput
|
||||
|
|
|
|||
|
|
@ -18,8 +18,7 @@ import { DenominationsSchema, getElements } from './helper'
|
|||
const useStyles = makeStyles({
|
||||
fudgeFactor: {
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
marginRight: 156
|
||||
alignItems: 'center'
|
||||
},
|
||||
switchLabel: {
|
||||
margin: 6,
|
||||
|
|
@ -44,6 +43,9 @@ const GET_INFO = gql`
|
|||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
cassette3
|
||||
cassette4
|
||||
numberOfCassettes
|
||||
}
|
||||
config
|
||||
}
|
||||
|
|
@ -65,6 +67,7 @@ const CashOut = ({ name: SCREEN_KEY }) => {
|
|||
}
|
||||
|
||||
const config = data?.config && fromNamespace(SCREEN_KEY)(data.config)
|
||||
|
||||
const fudgeFactorActive = config?.fudgeFactorActive ?? false
|
||||
const locale = data?.config && fromNamespace('locale')(data.config)
|
||||
const machines = data?.machines ?? []
|
||||
|
|
|
|||
|
|
@ -7,16 +7,17 @@ import { Autocomplete } from 'src/components/inputs/formik'
|
|||
import denominations from 'src/utils/bill-denominations'
|
||||
import { getBillOptions } from 'src/utils/bill-options'
|
||||
import { toNamespace } from 'src/utils/config'
|
||||
import { transformNumber } from 'src/utils/number'
|
||||
|
||||
import WizardSplash from './WizardSplash'
|
||||
import WizardStep from './WizardStep'
|
||||
import { DenominationsSchema } from './helper'
|
||||
|
||||
const LAST_STEP = 3
|
||||
const MODAL_WIDTH = 554
|
||||
const MODAL_HEIGHT = 520
|
||||
|
||||
const Wizard = ({ machine, locale, onClose, save, error }) => {
|
||||
const LAST_STEP = machine.numberOfCassettes + 2
|
||||
const [{ step, config }, setState] = useState({
|
||||
step: 0,
|
||||
config: { active: true }
|
||||
|
|
@ -30,7 +31,10 @@ const Wizard = ({ machine, locale, onClose, save, error }) => {
|
|||
const onContinue = async it => {
|
||||
if (isLastStep) {
|
||||
return save(
|
||||
toNamespace(machine.deviceId, DenominationsSchema.cast(config))
|
||||
toNamespace(
|
||||
machine.deviceId,
|
||||
DenominationsSchema.cast(config, { assert: false })
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -42,33 +46,55 @@ const Wizard = ({ machine, locale, onClose, save, error }) => {
|
|||
})
|
||||
}
|
||||
|
||||
const steps = [
|
||||
{
|
||||
type: 'top',
|
||||
display: 'Cassette 1 (Top)',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: R.map(it => ({ code: it, display: it }))(options),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
}
|
||||
const steps = []
|
||||
|
||||
R.until(
|
||||
R.gt(R.__, machine.numberOfCassettes),
|
||||
it => {
|
||||
steps.push({
|
||||
type: `cassette${it}`,
|
||||
display: `Cassette ${it}`,
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: R.map(it => ({ code: it, display: it }))(options),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
}
|
||||
})
|
||||
return R.add(1, it)
|
||||
},
|
||||
{
|
||||
type: 'bottom',
|
||||
display: 'Cassette 2',
|
||||
component: Autocomplete,
|
||||
inputProps: {
|
||||
options: R.map(it => ({ code: it, display: it }))(options),
|
||||
labelProp: 'display',
|
||||
valueProp: 'code'
|
||||
}
|
||||
}
|
||||
]
|
||||
1
|
||||
)
|
||||
|
||||
steps.push({
|
||||
type: 'zeroConfLimit',
|
||||
display: '0-conf Limit',
|
||||
schema: Yup.object().shape({
|
||||
zeroConfLimit: Yup.number().required()
|
||||
})
|
||||
})
|
||||
|
||||
const schema = () =>
|
||||
Yup.object().shape({
|
||||
top: Yup.number().required(),
|
||||
bottom: step >= 2 ? Yup.number().required() : Yup.number()
|
||||
cassette1: Yup.number().required(),
|
||||
cassette2:
|
||||
machine.numberOfCassettes > 1 && step >= 2
|
||||
? Yup.number().required()
|
||||
: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.nullable(),
|
||||
cassette3:
|
||||
machine.numberOfCassettes > 2 && step >= 3
|
||||
? Yup.number().required()
|
||||
: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.nullable(),
|
||||
cassette4:
|
||||
machine.numberOfCassettes > 3 && step >= 4
|
||||
? Yup.number().required()
|
||||
: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.nullable()
|
||||
})
|
||||
|
||||
return (
|
||||
|
|
@ -85,6 +111,7 @@ const Wizard = ({ machine, locale, onClose, save, error }) => {
|
|||
<WizardStep
|
||||
step={step}
|
||||
name={machine.name}
|
||||
numberOfCassettes={machine.numberOfCassettes}
|
||||
error={error}
|
||||
lastStep={isLastStep}
|
||||
steps={steps}
|
||||
|
|
|
|||
|
|
@ -9,11 +9,36 @@ import { NumberInput } from 'src/components/inputs/formik'
|
|||
import { Info2, H4, P, Info1, Label1 } from 'src/components/typography'
|
||||
import cassetteOne from 'src/styling/icons/cassettes/cashout-cassette-1.svg'
|
||||
import cassetteTwo from 'src/styling/icons/cassettes/cashout-cassette-2.svg'
|
||||
import tejo3CassetteOne from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-1-left.svg'
|
||||
import tejo3CassetteTwo from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-2-left.svg'
|
||||
import tejo3CassetteThree from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-3-left.svg'
|
||||
import tejo4CassetteOne from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-1-left.svg'
|
||||
import tejo4CassetteTwo from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-2-left.svg'
|
||||
import tejo4CassetteThree from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-3-left.svg'
|
||||
import tejo4CassetteFour from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-4-left.svg'
|
||||
import { ReactComponent as WarningIcon } from 'src/styling/icons/warning-icon/comet.svg'
|
||||
|
||||
import styles from './WizardStep.styles'
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const getCassetesArtworks = () => ({
|
||||
2: {
|
||||
1: cassetteOne,
|
||||
2: cassetteTwo
|
||||
},
|
||||
3: {
|
||||
1: tejo3CassetteOne,
|
||||
2: tejo3CassetteTwo,
|
||||
3: tejo3CassetteThree
|
||||
},
|
||||
4: {
|
||||
1: tejo4CassetteOne,
|
||||
2: tejo4CassetteTwo,
|
||||
3: tejo4CassetteThree,
|
||||
4: tejo4CassetteFour
|
||||
}
|
||||
})
|
||||
|
||||
const WizardStep = ({
|
||||
name,
|
||||
step,
|
||||
|
|
@ -23,30 +48,31 @@ const WizardStep = ({
|
|||
onContinue,
|
||||
steps,
|
||||
fiatCurrency,
|
||||
options
|
||||
options,
|
||||
numberOfCassettes
|
||||
}) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const label = lastStep ? 'Finish' : 'Next'
|
||||
|
||||
const cassetesArtworks = {
|
||||
1: cassetteOne,
|
||||
2: cassetteTwo
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={classes.content}>
|
||||
<>
|
||||
<div className={classes.titleDiv}>
|
||||
<Info2 className={classes.title}>{name}</Info2>
|
||||
<Stepper steps={3} currentStep={step} />
|
||||
<Stepper steps={steps.length + 1} currentStep={step} />
|
||||
</div>
|
||||
|
||||
{step <= 2 && (
|
||||
{step <= numberOfCassettes && (
|
||||
<Formik
|
||||
validateOnBlur={false}
|
||||
validateOnChange={false}
|
||||
onSubmit={onContinue}
|
||||
initialValues={{ top: '', bottom: '' }}
|
||||
initialValues={{
|
||||
cassette1: '',
|
||||
cassette2: '',
|
||||
cassette3: '',
|
||||
cassette4: ''
|
||||
}}
|
||||
enableReinitialize
|
||||
validationSchema={schema}>
|
||||
<Form>
|
||||
|
|
@ -84,8 +110,8 @@ const WizardStep = ({
|
|||
className={classes.stepImage}
|
||||
alt="cassette"
|
||||
width="148"
|
||||
height="196"
|
||||
src={cassetesArtworks[step]}></img>
|
||||
height="205"
|
||||
src={getCassetesArtworks()[numberOfCassettes][step]}></img>
|
||||
</div>
|
||||
|
||||
<Button className={classes.submit} type="submit">
|
||||
|
|
@ -94,6 +120,46 @@ const WizardStep = ({
|
|||
</Form>
|
||||
</Formik>
|
||||
)}
|
||||
|
||||
{step === numberOfCassettes + 1 && (
|
||||
<Formik
|
||||
validateOnBlur={false}
|
||||
validateOnChange={false}
|
||||
onSubmit={onContinue}
|
||||
initialValues={{ zeroConfLimit: '' }}
|
||||
enableReinitialize
|
||||
validationSchema={steps[step - 1].schema}>
|
||||
<Form>
|
||||
<div className={classes.thirdStepHeader}>
|
||||
<div className={classes.step}>
|
||||
<H4 className={classes.edit}>Edit 0-conf Limit</H4>
|
||||
|
||||
<Label1>Choose a limit</Label1>
|
||||
<div className={classes.bill}>
|
||||
<Field
|
||||
className={classes.billInput}
|
||||
type="text"
|
||||
size="lg"
|
||||
autoFocus={true}
|
||||
component={NumberInput}
|
||||
fullWidth
|
||||
decimalPlaces={0}
|
||||
name={steps[step - 1].type}
|
||||
/>
|
||||
<Info1 noMargin className={classes.suffix}>
|
||||
{fiatCurrency}
|
||||
</Info1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<Button className={classes.submit} type="submit">
|
||||
{label}
|
||||
</Button>
|
||||
</Form>
|
||||
</Formik>
|
||||
)}
|
||||
|
||||
{lastStep && (
|
||||
<div className={classes.disclaimer}>
|
||||
<Info2 className={classes.title}>Cash-out Bill Count</Info2>
|
||||
|
|
@ -122,7 +188,7 @@ const WizardStep = ({
|
|||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ export default {
|
|||
},
|
||||
header: {
|
||||
display: 'flex',
|
||||
paddingBottom: 95
|
||||
marginBottom: 95
|
||||
},
|
||||
thirdStepHeader: {
|
||||
display: 'flex',
|
||||
|
|
|
|||
|
|
@ -6,21 +6,44 @@ import { bold } from 'src/styling/helpers'
|
|||
import denominations from 'src/utils/bill-denominations'
|
||||
import { getBillOptions } from 'src/utils/bill-options'
|
||||
import { CURRENCY_MAX } from 'src/utils/constants'
|
||||
import { transformNumber } from 'src/utils/number'
|
||||
|
||||
const DenominationsSchema = Yup.object().shape({
|
||||
top: Yup.number()
|
||||
.label('Cassette 1 (Top)')
|
||||
cassette1: Yup.number()
|
||||
.label('Cassette 1')
|
||||
.required()
|
||||
.min(1)
|
||||
.max(CURRENCY_MAX),
|
||||
bottom: Yup.number()
|
||||
.label('Cassette 2 (Bottom)')
|
||||
cassette2: Yup.number()
|
||||
.label('Cassette 2')
|
||||
.required()
|
||||
.min(1)
|
||||
.max(CURRENCY_MAX),
|
||||
cassette3: Yup.number()
|
||||
.label('Cassette 3')
|
||||
.min(1)
|
||||
.max(CURRENCY_MAX)
|
||||
.nullable()
|
||||
.transform(transformNumber),
|
||||
cassette4: Yup.number()
|
||||
.label('Cassette 4')
|
||||
.min(1)
|
||||
.max(CURRENCY_MAX)
|
||||
.nullable()
|
||||
.transform(transformNumber),
|
||||
zeroConfLimit: Yup.number()
|
||||
.label('0-conf Limit')
|
||||
.required()
|
||||
.min(0)
|
||||
.max(CURRENCY_MAX)
|
||||
})
|
||||
|
||||
const getElements = (machines, locale = {}, classes) => {
|
||||
const fiatCurrency = R.prop('fiatCurrency')(locale)
|
||||
const maxNumberOfCassettes = Math.max(
|
||||
...R.map(it => it.numberOfCassettes, machines)
|
||||
)
|
||||
|
||||
const options = getBillOptions(locale, denominations)
|
||||
const cassetteProps =
|
||||
options?.length > 0
|
||||
|
|
@ -32,7 +55,7 @@ const getElements = (machines, locale = {}, classes) => {
|
|||
}
|
||||
: { decimalPlaces: 0 }
|
||||
|
||||
return [
|
||||
const elements = [
|
||||
{
|
||||
name: 'id',
|
||||
header: 'Machine',
|
||||
|
|
@ -40,32 +63,50 @@ const getElements = (machines, locale = {}, classes) => {
|
|||
view: it => machines.find(({ deviceId }) => deviceId === it).name,
|
||||
size: 'sm',
|
||||
editable: false
|
||||
},
|
||||
{
|
||||
name: 'top',
|
||||
header: 'Cassette 1 (Top)',
|
||||
stripe: true,
|
||||
width: 250,
|
||||
textAlign: 'right',
|
||||
view: it => it,
|
||||
input: options?.length > 0 ? Autocomplete : NumberInput,
|
||||
inputProps: cassetteProps,
|
||||
suffix: R.prop('fiatCurrency')(locale),
|
||||
bold: bold
|
||||
},
|
||||
{
|
||||
name: 'bottom',
|
||||
header: 'Cassette 2 (Bottom)',
|
||||
stripe: true,
|
||||
textAlign: 'right',
|
||||
width: 250,
|
||||
view: it => it,
|
||||
input: options?.length > 0 ? Autocomplete : NumberInput,
|
||||
inputProps: cassetteProps,
|
||||
suffix: R.prop('fiatCurrency')(locale),
|
||||
bold: bold
|
||||
}
|
||||
]
|
||||
|
||||
R.until(
|
||||
R.gt(R.__, maxNumberOfCassettes),
|
||||
it => {
|
||||
elements.push({
|
||||
name: `cassette${it}`,
|
||||
header: `Cassette ${it}`,
|
||||
size: 'sm',
|
||||
stripe: true,
|
||||
textAlign: 'right',
|
||||
width: (maxNumberOfCassettes > 2 ? 600 : 460) / maxNumberOfCassettes,
|
||||
suffix: fiatCurrency,
|
||||
bold: bold,
|
||||
view: it => it,
|
||||
input: options?.length > 0 ? Autocomplete : NumberInput,
|
||||
inputProps: cassetteProps,
|
||||
doubleHeader: 'Denominations',
|
||||
isHidden: machine =>
|
||||
it >
|
||||
machines.find(({ deviceId }) => deviceId === machine.id)
|
||||
.numberOfCassettes
|
||||
})
|
||||
return R.add(1, it)
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
elements.push({
|
||||
name: 'zeroConfLimit',
|
||||
header: '0-conf Limit',
|
||||
size: 'sm',
|
||||
stripe: true,
|
||||
textAlign: 'right',
|
||||
width: maxNumberOfCassettes > 2 ? 150 : 290,
|
||||
input: NumberInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
},
|
||||
suffix: fiatCurrency
|
||||
})
|
||||
|
||||
return elements
|
||||
}
|
||||
|
||||
export { DenominationsSchema, getElements }
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import TableContainer from '@material-ui/core/TableContainer'
|
|||
import TableHead from '@material-ui/core/TableHead'
|
||||
import TableRow from '@material-ui/core/TableRow'
|
||||
import classnames from 'classnames'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
import { useHistory } from 'react-router-dom'
|
||||
|
||||
|
|
@ -60,6 +61,10 @@ const MachinesTable = ({ machines, numToRender }) => {
|
|||
})
|
||||
}
|
||||
|
||||
const maxNumberOfCassettes = Math.max(
|
||||
...R.map(it => it.numberOfCassettes, machines)
|
||||
)
|
||||
|
||||
return (
|
||||
<TableContainer className={classes.table}>
|
||||
<Table>
|
||||
|
|
@ -80,18 +85,17 @@ const MachinesTable = ({ machines, numToRender }) => {
|
|||
<TxInIcon />
|
||||
</div>
|
||||
</HeaderCell> */}
|
||||
<HeaderCell>
|
||||
<div className={classes.header}>
|
||||
<TxOutIcon />
|
||||
<Label2 className={classes.label}> 1</Label2>
|
||||
</div>
|
||||
</HeaderCell>
|
||||
<HeaderCell>
|
||||
<div className={classes.header}>
|
||||
<TxOutIcon />
|
||||
<Label2 className={classes.label}> 2</Label2>
|
||||
</div>
|
||||
</HeaderCell>
|
||||
{R.map(
|
||||
it => (
|
||||
<HeaderCell>
|
||||
<div className={classes.header}>
|
||||
<TxOutIcon />
|
||||
<Label2 className={classes.label}> {it + 1}</Label2>
|
||||
</div>
|
||||
</HeaderCell>
|
||||
),
|
||||
R.times(R.identity, maxNumberOfCassettes)
|
||||
)}
|
||||
</TableRow>
|
||||
</TableHead>
|
||||
<TableBody>
|
||||
|
|
@ -120,12 +124,19 @@ const MachinesTable = ({ machines, numToRender }) => {
|
|||
{/* <StyledCell align="left">
|
||||
{makePercentageText(machine.cashbox)}
|
||||
</StyledCell> */}
|
||||
<StyledCell align="left">
|
||||
{makePercentageText(machine.cassette1)}
|
||||
</StyledCell>
|
||||
<StyledCell align="left">
|
||||
{makePercentageText(machine.cassette2)}
|
||||
</StyledCell>
|
||||
{R.map(
|
||||
it =>
|
||||
machine.numberOfCassettes > it ? (
|
||||
<StyledCell align="left">
|
||||
{makePercentageText(machine[`cassette${it + 1}`])}
|
||||
</StyledCell>
|
||||
) : (
|
||||
<StyledCell align="left">
|
||||
<TL2>{`— %`}</TL2>
|
||||
</StyledCell>
|
||||
),
|
||||
R.times(R.identity, maxNumberOfCassettes)
|
||||
)}
|
||||
</TableRow>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ const GET_DATA = gql`
|
|||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
cassette3
|
||||
cassette4
|
||||
numberOfCassettes
|
||||
statuses {
|
||||
label
|
||||
type
|
||||
|
|
|
|||
|
|
@ -1,18 +1,25 @@
|
|||
import { useMutation } from '@apollo/react-hooks'
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
import gql from 'graphql-tag'
|
||||
import * as R from 'ramda'
|
||||
import React from 'react'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import { Table as EditableTable } from 'src/components/editableTable'
|
||||
import { CashOut, CashIn } from 'src/components/inputs/cashbox/Cashbox'
|
||||
import { NumberInput } from 'src/components/inputs/formik'
|
||||
import { NumberInput, CashCassetteInput } from 'src/components/inputs/formik'
|
||||
import { fromNamespace } from 'src/utils/config'
|
||||
|
||||
import styles from './Cassettes.styles'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const widthsByNumberOfCassettes = {
|
||||
2: { cashbox: 116, cassette: 280, cassetteGraph: 80, editWidth: 174 },
|
||||
3: { cashbox: 106, cassette: 200, cassetteGraph: 60, editWidth: 145 },
|
||||
4: { cashbox: 106, cassette: 164, cassetteGraph: 40, editWidth: 90 }
|
||||
}
|
||||
|
||||
const ValidationSchema = Yup.object().shape({
|
||||
name: Yup.string().required('Required'),
|
||||
cashbox: Yup.number()
|
||||
|
|
@ -27,6 +34,16 @@ const ValidationSchema = Yup.object().shape({
|
|||
.min(0)
|
||||
.max(500),
|
||||
cassette2: Yup.number()
|
||||
.required('Required')
|
||||
.integer()
|
||||
.min(0)
|
||||
.max(500),
|
||||
cassette3: Yup.number()
|
||||
.required('Required')
|
||||
.integer()
|
||||
.min(0)
|
||||
.max(500),
|
||||
cassette4: Yup.number()
|
||||
.required('Required')
|
||||
.integer()
|
||||
.min(0)
|
||||
|
|
@ -40,6 +57,8 @@ const SET_CASSETTE_BILLS = gql`
|
|||
$cashbox: Int!
|
||||
$cassette1: Int!
|
||||
$cassette2: Int!
|
||||
$cassette3: Int!
|
||||
$cassette4: Int!
|
||||
) {
|
||||
machineAction(
|
||||
deviceId: $deviceId
|
||||
|
|
@ -47,11 +66,15 @@ const SET_CASSETTE_BILLS = gql`
|
|||
cashbox: $cashbox
|
||||
cassette1: $cassette1
|
||||
cassette2: $cassette2
|
||||
cassette3: $cassette3
|
||||
cassette4: $cassette4
|
||||
) {
|
||||
deviceId
|
||||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
cassette3
|
||||
cassette4
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
@ -64,6 +87,7 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
|||
const fillingPercentageSettings =
|
||||
config && fromNamespace('notifications', config)
|
||||
const fiatCurrency = locale?.fiatCurrency
|
||||
const numberOfCassettes = machine.numberOfCassettes
|
||||
|
||||
const getCashoutSettings = deviceId => fromNamespace(deviceId)(cashout)
|
||||
const isCashOutDisabled = ({ deviceId }) =>
|
||||
|
|
@ -73,7 +97,7 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
|||
{
|
||||
name: 'cashbox',
|
||||
header: 'Cashbox',
|
||||
width: 240,
|
||||
width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
|
||||
stripe: false,
|
||||
view: value => (
|
||||
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
|
||||
|
|
@ -82,61 +106,63 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
|||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'cassette1',
|
||||
header: 'Cash-out 1',
|
||||
width: 265,
|
||||
stripe: true,
|
||||
view: (value, { deviceId }) => (
|
||||
<CashOut
|
||||
className={classes.cashbox}
|
||||
denomination={getCashoutSettings(deviceId)?.top}
|
||||
currency={{ code: fiatCurrency }}
|
||||
notes={value}
|
||||
threshold={fillingPercentageSettings.fillingPercentageCassette1}
|
||||
/>
|
||||
),
|
||||
input: NumberInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'cassette2',
|
||||
header: 'Cash-out 2',
|
||||
width: 265,
|
||||
stripe: true,
|
||||
view: (value, { deviceId }) => {
|
||||
return (
|
||||
<CashOut
|
||||
className={classes.cashbox}
|
||||
denomination={getCashoutSettings(deviceId)?.bottom}
|
||||
currency={{ code: fiatCurrency }}
|
||||
notes={value}
|
||||
threshold={fillingPercentageSettings.fillingPercentageCassette2}
|
||||
/>
|
||||
)
|
||||
},
|
||||
input: NumberInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
R.until(
|
||||
R.gt(R.__, numberOfCassettes),
|
||||
it => {
|
||||
elements.push({
|
||||
name: `cassette${it}`,
|
||||
header: `Cash-out ${it}`,
|
||||
width: widthsByNumberOfCassettes[numberOfCassettes].cassette,
|
||||
stripe: true,
|
||||
doubleHeader: 'Cash-out',
|
||||
view: value => {
|
||||
return (
|
||||
<CashOut
|
||||
className={classes.cashbox}
|
||||
denomination={
|
||||
getCashoutSettings(machine.deviceId)?.[`cassette${it}`]
|
||||
}
|
||||
currency={{ code: fiatCurrency }}
|
||||
notes={value}
|
||||
width={widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph}
|
||||
threshold={
|
||||
fillingPercentageSettings[`fillingPercentageCassette${it}`]
|
||||
}
|
||||
/>
|
||||
)
|
||||
},
|
||||
isHidden: ({ numberOfCassettes }) => it > numberOfCassettes,
|
||||
input: CashCassetteInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0,
|
||||
width: widthsByNumberOfCassettes[numberOfCassettes].cassetteGraph,
|
||||
inputClassName: classes.cashbox
|
||||
}
|
||||
})
|
||||
return R.add(1, it)
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
|
||||
refetchQueries: () => refetchData()
|
||||
})
|
||||
|
||||
const onSave = (...[, { deviceId, cashbox, cassette1, cassette2 }]) => {
|
||||
const onSave = (
|
||||
...[, { deviceId, cashbox, cassette1, cassette2, cassette3, cassette4 }]
|
||||
) => {
|
||||
return setCassetteBills({
|
||||
variables: {
|
||||
action: 'setCassetteBills',
|
||||
deviceId: deviceId,
|
||||
cashbox,
|
||||
cassette1,
|
||||
cassette2
|
||||
cassette2,
|
||||
cassette3,
|
||||
cassette4
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
@ -144,6 +170,8 @@ const CashCassettes = ({ machine, config, refetchData }) => {
|
|||
return machine.name ? (
|
||||
<EditableTable
|
||||
error={error?.message}
|
||||
enableEdit
|
||||
editWidth={widthsByNumberOfCassettes[numberOfCassettes].editWidth}
|
||||
stripeWhen={isCashOutDisabled}
|
||||
disableRowEdit={isCashOutDisabled}
|
||||
name="cashboxes"
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
const styles = {
|
||||
cashbox: {
|
||||
width: 80,
|
||||
height: 36
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ const GET_INFO = gql`
|
|||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
cassette3
|
||||
cassette4
|
||||
numberOfCassettes
|
||||
statuses {
|
||||
label
|
||||
type
|
||||
|
|
@ -84,15 +87,6 @@ const Machines = () => {
|
|||
<Overview data={machine} onActionSuccess={refetch} />
|
||||
</div>
|
||||
</Grid>
|
||||
<Grid item xs={12}>
|
||||
{/* on hold for now <Sidebar
|
||||
isSelected={R.equals(selectedMachine)}
|
||||
selectItem={setSelectedMachine}
|
||||
data={machines}
|
||||
getText={R.prop('name')}
|
||||
getKey={R.prop('deviceId')}
|
||||
/> */}
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid item xs={9}>
|
||||
<div className={classes.content}>
|
||||
|
|
|
|||
|
|
@ -37,19 +37,39 @@ const ValidationSchema = Yup.object().shape({
|
|||
.min(0)
|
||||
.max(1000),
|
||||
cassette1: Yup.number()
|
||||
.label('Cassette 1 (top)')
|
||||
.label('Cassette 1')
|
||||
.required()
|
||||
.integer()
|
||||
.min(0)
|
||||
.max(500),
|
||||
cassette2: Yup.number()
|
||||
.label('Cassette 2 (bottom)')
|
||||
.label('Cassette 2')
|
||||
.required()
|
||||
.integer()
|
||||
.min(0)
|
||||
.max(500),
|
||||
cassette3: Yup.number()
|
||||
.label('Cassette 3')
|
||||
.required()
|
||||
.integer()
|
||||
.min(0)
|
||||
.max(500),
|
||||
cassette4: Yup.number()
|
||||
.label('Cassette 4')
|
||||
.required()
|
||||
.integer()
|
||||
.min(0)
|
||||
.max(500)
|
||||
})
|
||||
|
||||
const CREATE_BATCH = gql`
|
||||
mutation createBatch($deviceId: ID, $cashboxCount: Int) {
|
||||
createBatch(deviceId: $deviceId, cashboxCount: $cashboxCount) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const GET_MACHINES_AND_CONFIG = gql`
|
||||
query getData {
|
||||
machines {
|
||||
|
|
@ -58,6 +78,9 @@ const GET_MACHINES_AND_CONFIG = gql`
|
|||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
cassette3
|
||||
cassette4
|
||||
numberOfCassettes
|
||||
}
|
||||
config
|
||||
}
|
||||
|
|
@ -85,6 +108,8 @@ const SET_CASSETTE_BILLS = gql`
|
|||
$cashbox: Int!
|
||||
$cassette1: Int!
|
||||
$cassette2: Int!
|
||||
$cassette3: Int!
|
||||
$cassette4: Int!
|
||||
) {
|
||||
machineAction(
|
||||
deviceId: $deviceId
|
||||
|
|
@ -92,11 +117,15 @@ const SET_CASSETTE_BILLS = gql`
|
|||
cashbox: $cashbox
|
||||
cassette1: $cassette1
|
||||
cassette2: $cassette2
|
||||
cassette3: $cassette3
|
||||
cassette4: $cassette4
|
||||
) {
|
||||
deviceId
|
||||
cashbox
|
||||
cassette1
|
||||
cassette2
|
||||
cassette3
|
||||
cassette4
|
||||
}
|
||||
}
|
||||
`
|
||||
|
|
@ -117,6 +146,7 @@ const CashCassettes = () => {
|
|||
const [setCassetteBills, { error }] = useMutation(SET_CASSETTE_BILLS, {
|
||||
refetchQueries: () => ['getData']
|
||||
})
|
||||
const [createBatch] = useMutation(CREATE_BATCH)
|
||||
const [saveConfig] = useMutation(SAVE_CONFIG, {
|
||||
onCompleted: () => setEditingSchema(false),
|
||||
refetchQueries: () => ['getData']
|
||||
|
|
@ -129,6 +159,37 @@ const CashCassettes = () => {
|
|||
const cashout = data?.config && fromNamespace('cashOut')(data.config)
|
||||
const locale = data?.config && fromNamespace('locale')(data.config)
|
||||
const fiatCurrency = locale?.fiatCurrency
|
||||
const maxNumberOfCassettes = Math.max(
|
||||
...R.map(it => it.numberOfCassettes, machines)
|
||||
)
|
||||
const cashboxCounts = R.reduce(
|
||||
(ret, m) => R.assoc(m.id, m.cashbox, ret),
|
||||
{},
|
||||
machines
|
||||
)
|
||||
|
||||
const onSave = (id, cashbox, cassette1, cassette2, cassette3, cassette4) => {
|
||||
const oldCashboxCount = cashboxCounts[id]
|
||||
if (cashbox < oldCashboxCount) {
|
||||
createBatch({
|
||||
variables: {
|
||||
deviceId: id,
|
||||
cashboxCount: oldCashboxCount
|
||||
}
|
||||
})
|
||||
}
|
||||
return setCassetteBills({
|
||||
variables: {
|
||||
action: 'setCassetteBills',
|
||||
deviceId: id,
|
||||
cashbox,
|
||||
cassette1,
|
||||
cassette2,
|
||||
cassette3,
|
||||
cassette4
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const cashboxReset =
|
||||
data?.config && fromNamespace('cashIn')(data.config).cashboxReset
|
||||
|
|
@ -144,17 +205,7 @@ const CashCassettes = () => {
|
|||
setEditingSchema(false)
|
||||
}
|
||||
}
|
||||
const onSave = (id, cashbox, cassette1, cassette2) => {
|
||||
return setCassetteBills({
|
||||
variables: {
|
||||
action: 'setCassetteBills',
|
||||
deviceId: id,
|
||||
cashbox,
|
||||
cassette1,
|
||||
cassette2
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const getCashoutSettings = id => fromNamespace(id)(cashout)
|
||||
const isCashOutDisabled = ({ id }) => !getCashoutSettings(id).active
|
||||
|
||||
|
|
@ -172,14 +223,14 @@ const CashCassettes = () => {
|
|||
{
|
||||
name: 'name',
|
||||
header: 'Machine',
|
||||
width: 254,
|
||||
width: 184,
|
||||
view: name => <>{name}</>,
|
||||
input: ({ field: { value: name } }) => <>{name}</>
|
||||
},
|
||||
{
|
||||
name: 'cashbox',
|
||||
header: 'Cashbox',
|
||||
width: 240,
|
||||
header: 'Cash-in',
|
||||
width: maxNumberOfCassettes > 2 ? 140 : 280,
|
||||
view: value => (
|
||||
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} />
|
||||
),
|
||||
|
|
@ -187,68 +238,60 @@ const CashCassettes = () => {
|
|||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'cassette1',
|
||||
header: 'Cassette 1 (Top)',
|
||||
width: 265,
|
||||
stripe: true,
|
||||
view: (value, { id }) => (
|
||||
<CashOut
|
||||
className={classes.cashbox}
|
||||
denomination={getCashoutSettings(id)?.top}
|
||||
currency={{ code: fiatCurrency }}
|
||||
notes={value}
|
||||
threshold={fillingPercentageSettings.fillingPercentageCassette1}
|
||||
/>
|
||||
),
|
||||
input: CashCassetteInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0,
|
||||
threshold: fillingPercentageSettings.fillingPercentageCassette1
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'cassette2',
|
||||
header: 'Cassette 2 (Bottom)',
|
||||
width: 265,
|
||||
stripe: true,
|
||||
view: (value, { id }) => {
|
||||
return (
|
||||
<CashOut
|
||||
className={classes.cashbox}
|
||||
denomination={getCashoutSettings(id)?.bottom}
|
||||
currency={{ code: fiatCurrency }}
|
||||
notes={value}
|
||||
threshold={fillingPercentageSettings.fillingPercentageCassette2}
|
||||
/>
|
||||
)
|
||||
},
|
||||
input: CashCassetteInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0,
|
||||
threshold: fillingPercentageSettings.fillingPercentageCassette2
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'edit',
|
||||
header: 'Edit',
|
||||
width: 175,
|
||||
textAlign: 'center',
|
||||
view: (value, { id }) => {
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setMachineId(id)
|
||||
setWizard(true)
|
||||
}}>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
R.until(
|
||||
R.gt(R.__, maxNumberOfCassettes),
|
||||
it => {
|
||||
elements.push({
|
||||
name: `cassette${it}`,
|
||||
header: `Cassette ${it}`,
|
||||
width: (maxNumberOfCassettes > 2 ? 700 : 560) / maxNumberOfCassettes,
|
||||
stripe: true,
|
||||
doubleHeader: 'Cash-out',
|
||||
view: (value, { id }) => (
|
||||
<CashOut
|
||||
className={classes.cashbox}
|
||||
denomination={getCashoutSettings(id)?.[`cassette${it}`]}
|
||||
currency={{ code: fiatCurrency }}
|
||||
notes={value}
|
||||
width={50}
|
||||
threshold={
|
||||
fillingPercentageSettings[`fillingPercentageCassette${it}`]
|
||||
}
|
||||
/>
|
||||
),
|
||||
isHidden: ({ numberOfCassettes }) => it > numberOfCassettes,
|
||||
input: CashCassetteInput,
|
||||
inputProps: {
|
||||
decimalPlaces: 0,
|
||||
width: 50,
|
||||
inputClassName: classes.cashbox
|
||||
}
|
||||
})
|
||||
return R.add(1, it)
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
elements.push({
|
||||
name: 'edit',
|
||||
header: 'Edit',
|
||||
width: 87,
|
||||
view: (value, { id }) => {
|
||||
return (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setMachineId(id)
|
||||
setWizard(true)
|
||||
}}>
|
||||
<EditIcon />
|
||||
</IconButton>
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
<>
|
||||
<TitleSection
|
||||
|
|
@ -292,7 +335,6 @@ const CashCassettes = () => {
|
|||
stripeWhen={isCashOutDisabled}
|
||||
elements={elements}
|
||||
data={machines}
|
||||
save={onSave}
|
||||
validationSchema={ValidationSchema}
|
||||
tbodyWrapperClass={classes.tBody}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ import { offColor } from 'src/styling/variables'
|
|||
|
||||
export default {
|
||||
cashbox: {
|
||||
width: 80,
|
||||
height: 36
|
||||
},
|
||||
tableContainer: {
|
||||
|
|
|
|||
|
|
@ -25,16 +25,23 @@ const CashCassettesFooter = ({
|
|||
const classes = useStyles()
|
||||
const cashout = config && fromNamespace('cashOut')(config)
|
||||
const getCashoutSettings = id => fromNamespace(id)(cashout)
|
||||
const reducerFn = (acc, { cassette1, cassette2, id }) => {
|
||||
const topDenomination = getCashoutSettings(id).top ?? 0
|
||||
const bottomDenomination = getCashoutSettings(id).bottom ?? 0
|
||||
const reducerFn = (
|
||||
acc,
|
||||
{ cassette1, cassette2, cassette3, cassette4, id }
|
||||
) => {
|
||||
const cassette1Denomination = getCashoutSettings(id).cassette1 ?? 0
|
||||
const cassette2Denomination = getCashoutSettings(id).cassette2 ?? 0
|
||||
const cassette3Denomination = getCashoutSettings(id).cassette3 ?? 0
|
||||
const cassette4Denomination = getCashoutSettings(id).cassette4 ?? 0
|
||||
return [
|
||||
(acc[0] += cassette1 * topDenomination),
|
||||
(acc[1] += cassette2 * bottomDenomination)
|
||||
(acc[0] += cassette1 * cassette1Denomination),
|
||||
(acc[1] += cassette2 * cassette2Denomination),
|
||||
(acc[2] += cassette3 * cassette3Denomination),
|
||||
(acc[3] += cassette4 * cassette4Denomination)
|
||||
]
|
||||
}
|
||||
|
||||
const totalInCassettes = R.sum(R.reduce(reducerFn, [0, 0], machines))
|
||||
const totalInCassettes = R.sum(R.reduce(reducerFn, [0, 0, 0, 0], machines))
|
||||
|
||||
/* const totalInCashBox = R.sum(
|
||||
R.flatten(
|
||||
|
|
|
|||
|
|
@ -76,38 +76,34 @@ const CashboxHistory = ({ machines, currency }) => {
|
|||
|
||||
const batches = R.path(['cashboxBatches'])(data)
|
||||
|
||||
const getOperationRender = {
|
||||
'cash-in-empty': (
|
||||
<>
|
||||
<TxInIcon />
|
||||
<span className={classes.operationType}>Cash-in emptied</span>
|
||||
</>
|
||||
),
|
||||
'cash-out-1-refill': (
|
||||
<>
|
||||
<TxOutIcon />
|
||||
<span className={classes.operationType}>Cash-out 1 refill</span>
|
||||
</>
|
||||
),
|
||||
'cash-out-1-empty': (
|
||||
<>
|
||||
<TxOutIcon />
|
||||
<span className={classes.operationType}>Cash-out 1 emptied</span>
|
||||
</>
|
||||
),
|
||||
'cash-out-2-refill': (
|
||||
<>
|
||||
<TxOutIcon />
|
||||
<span className={classes.operationType}>Cash-out 2 refill</span>
|
||||
</>
|
||||
),
|
||||
'cash-out-2-empty': (
|
||||
<>
|
||||
<TxOutIcon />
|
||||
<span className={classes.operationType}>Cash-out 2 emptied</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
const getOperationRender = R.reduce(
|
||||
(ret, i) =>
|
||||
R.pipe(
|
||||
R.assoc(
|
||||
`cash-out-${i}-refill`,
|
||||
<>
|
||||
<TxOutIcon />
|
||||
<span className={classes.operationType}>Cash-out {i} refill</span>
|
||||
</>
|
||||
),
|
||||
R.assoc(
|
||||
`cash-out-${i}-empty`,
|
||||
<>
|
||||
<TxOutIcon />
|
||||
<span className={classes.operationType}>Cash-out {i} emptied</span>
|
||||
</>
|
||||
)
|
||||
)(ret),
|
||||
{
|
||||
'cash-in-empty': (
|
||||
<>
|
||||
<TxInIcon />
|
||||
<span className={classes.operationType}>Cash-in emptied</span>
|
||||
</>
|
||||
)
|
||||
},
|
||||
R.range(1, 5)
|
||||
)
|
||||
|
||||
const save = row => {
|
||||
const field = R.find(f => f.id === row.id, fields)
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@ const Wizard = ({ machine, cashoutSettings, locale, onClose, save, error }) => {
|
|||
const isCashOutDisabled =
|
||||
R.isEmpty(cashoutSettings) || !cashoutSettings?.active
|
||||
|
||||
const LAST_STEP = isCashOutDisabled ? 1 : 3
|
||||
const numberOfCassettes = isCashOutDisabled ? 0 : machine.numberOfCassettes
|
||||
|
||||
const LAST_STEP = numberOfCassettes + 1
|
||||
|
||||
const title = `Update counts`
|
||||
const isLastStep = step === LAST_STEP
|
||||
|
|
@ -57,12 +59,8 @@ const Wizard = ({ machine, cashoutSettings, locale, onClose, save, error }) => {
|
|||
})
|
||||
}
|
||||
|
||||
save(
|
||||
machine.id,
|
||||
parseInt(cashbox),
|
||||
parseInt(it.cassette1Count ?? 0),
|
||||
parseInt(it.cassette2Count ?? 0)
|
||||
)
|
||||
const { cassette1, cassette2, cassette3, cassette4 } = R.map(parseInt, it)
|
||||
save(machine.id, cashbox, cassette1, cassette2, cassette3, cassette4)
|
||||
return onClose()
|
||||
}
|
||||
|
||||
|
|
@ -72,7 +70,24 @@ const Wizard = ({ machine, cashoutSettings, locale, onClose, save, error }) => {
|
|||
})
|
||||
}
|
||||
|
||||
const steps = [
|
||||
const makeCassetteSteps = R.pipe(
|
||||
R.add(1),
|
||||
R.range(1),
|
||||
R.map(i => ({
|
||||
type: `cassette ${i}`,
|
||||
schema: Yup.object().shape({
|
||||
[`cassette${i}`]: Yup.number()
|
||||
.label('Bill count')
|
||||
.positive()
|
||||
.integer()
|
||||
.required()
|
||||
.min(0)
|
||||
.max(CASHBOX_DEFAULT_CAPACITY)
|
||||
})
|
||||
}))
|
||||
)
|
||||
|
||||
const steps = R.prepend(
|
||||
{
|
||||
type: 'cashbox',
|
||||
schema: Yup.object().shape({
|
||||
|
|
@ -80,33 +95,8 @@ const Wizard = ({ machine, cashoutSettings, locale, onClose, save, error }) => {
|
|||
}),
|
||||
cashoutRequired: false
|
||||
},
|
||||
{
|
||||
type: 'cassette 1',
|
||||
schema: Yup.object().shape({
|
||||
cassette1Count: Yup.number()
|
||||
.label('Bill count')
|
||||
.required()
|
||||
.min(0)
|
||||
.max(CASHBOX_DEFAULT_CAPACITY)
|
||||
}),
|
||||
cashoutRequired: true
|
||||
},
|
||||
{
|
||||
type: 'cassette 2',
|
||||
schema: Yup.object().shape({
|
||||
cassette2Count: Yup.number()
|
||||
.label('Bill count')
|
||||
.required()
|
||||
.min(0)
|
||||
.max(CASHBOX_DEFAULT_CAPACITY)
|
||||
}),
|
||||
cashoutRequired: true
|
||||
}
|
||||
]
|
||||
|
||||
const filteredSteps = R.filter(it => {
|
||||
return !it.cashoutRequired || (!isCashOutDisabled && it.cashoutRequired)
|
||||
}, steps)
|
||||
makeCassetteSteps(numberOfCassettes)
|
||||
)
|
||||
|
||||
return (
|
||||
<Modal
|
||||
|
|
@ -127,7 +117,7 @@ const Wizard = ({ machine, cashoutSettings, locale, onClose, save, error }) => {
|
|||
cassetteCapacity={CASHBOX_DEFAULT_CAPACITY}
|
||||
error={error}
|
||||
lastStep={isLastStep}
|
||||
steps={filteredSteps}
|
||||
steps={steps}
|
||||
fiatCurrency={locale.fiatCurrency}
|
||||
onContinue={onContinue}
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -13,6 +13,13 @@ import { Info2, H4, P, Info1 } from 'src/components/typography'
|
|||
import cashbox from 'src/styling/icons/cassettes/acceptor-left.svg'
|
||||
import cassetteOne from 'src/styling/icons/cassettes/dispenser-1.svg'
|
||||
import cassetteTwo from 'src/styling/icons/cassettes/dispenser-2.svg'
|
||||
import tejo3CassetteOne from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-1-left.svg'
|
||||
import tejo3CassetteTwo from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-2-left.svg'
|
||||
import tejo3CassetteThree from 'src/styling/icons/cassettes/tejo/3-cassettes/3-cassettes-open-3-left.svg'
|
||||
import tejo4CassetteOne from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-1-left.svg'
|
||||
import tejo4CassetteTwo from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-2-left.svg'
|
||||
import tejo4CassetteThree from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-3-left.svg'
|
||||
import tejo4CassetteFour from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-4-left.svg'
|
||||
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
|
||||
import { comet, errorColor } from 'src/styling/variables'
|
||||
|
||||
|
|
@ -91,6 +98,13 @@ const styles = {
|
|||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const cassetesArtworks = (numberOfCassettes, step) =>
|
||||
[
|
||||
[cassetteOne, cassetteTwo],
|
||||
[tejo3CassetteOne, tejo3CassetteTwo, tejo3CassetteThree],
|
||||
[tejo4CassetteOne, tejo4CassetteTwo, tejo4CassetteThree, tejo4CassetteFour]
|
||||
][numberOfCassettes - 2][step - 2]
|
||||
|
||||
const WizardStep = ({
|
||||
step,
|
||||
name,
|
||||
|
|
@ -107,28 +121,23 @@ const WizardStep = ({
|
|||
|
||||
const label = lastStep ? 'Finish' : 'Confirm'
|
||||
|
||||
const cassetesArtworks = {
|
||||
1: cashbox,
|
||||
2: cassetteOne,
|
||||
3: cassetteTwo
|
||||
}
|
||||
|
||||
const stepOneRadioOptions = [
|
||||
{ display: 'Yes', code: 'YES' },
|
||||
{ display: 'No', code: 'NO' }
|
||||
]
|
||||
|
||||
const cassetteInfo = {
|
||||
amount: step === 2 ? machine?.cassette1 : machine?.cassette2,
|
||||
denomination: step === 2 ? cashoutSettings.top : cashoutSettings.bottom
|
||||
}
|
||||
const cassetteField = `cassette${step - 1}`
|
||||
const numberOfCassettes = machine.numberOfCassettes
|
||||
const originalCassetteCount = machine?.[cassetteField]
|
||||
const cassetteDenomination = cashoutSettings?.[cassetteField]
|
||||
|
||||
const getPercentage = values => {
|
||||
const cassetteCount =
|
||||
step === 2 ? values.cassette1Count : values.cassette2Count
|
||||
const value = cassetteCount ?? cassetteInfo.amount
|
||||
return R.clamp(0, 100, 100 * (value / cassetteCapacity))
|
||||
}
|
||||
const cassetteCount = values => values[cassetteField] || originalCassetteCount
|
||||
const cassetteTotal = values => cassetteCount(values) * cassetteDenomination
|
||||
const getPercentage = R.pipe(
|
||||
cassetteCount,
|
||||
count => 100 * (count / cassetteCapacity),
|
||||
R.clamp(0, 100)
|
||||
)
|
||||
|
||||
return (
|
||||
<div className={classes.content}>
|
||||
|
|
@ -144,7 +153,7 @@ const WizardStep = ({
|
|||
onSubmit={onContinue}
|
||||
initialValues={{ wasCashboxEmptied: '' }}
|
||||
enableReinitialize
|
||||
validationSchema={steps[step - 1].schema}>
|
||||
validationSchema={steps[0].schema}>
|
||||
{({ values, errors }) => (
|
||||
<Form>
|
||||
<div
|
||||
|
|
@ -152,7 +161,7 @@ const WizardStep = ({
|
|||
<img
|
||||
className={classes.stepImage}
|
||||
alt="cassette"
|
||||
src={cassetesArtworks[step]}></img>
|
||||
src={cashbox}></img>
|
||||
<div className={classes.formWrapper}>
|
||||
<div
|
||||
className={classnames(
|
||||
|
|
@ -205,12 +214,17 @@ const WizardStep = ({
|
|||
</Formik>
|
||||
)}
|
||||
|
||||
{(step === 2 || step === 3) && (
|
||||
{step > 1 && (
|
||||
<Formik
|
||||
validateOnBlur={false}
|
||||
validateOnChange={false}
|
||||
onSubmit={onContinue}
|
||||
initialValues={{ cassette1Count: '', cassette2Count: '' }}
|
||||
initialValues={{
|
||||
cassette1: '',
|
||||
cassette2: '',
|
||||
cassette3: '',
|
||||
cassette4: ''
|
||||
}}
|
||||
enableReinitialize
|
||||
validationSchema={steps[step - 1].schema}>
|
||||
{({ values, errors }) => (
|
||||
|
|
@ -220,7 +234,7 @@ const WizardStep = ({
|
|||
<img
|
||||
className={classes.stepImage}
|
||||
alt="cassette"
|
||||
src={cassetesArtworks[step]}></img>
|
||||
src={cassetesArtworks(numberOfCassettes, step)}></img>
|
||||
<div className={classes.formWrapper}>
|
||||
<div
|
||||
className={classnames(
|
||||
|
|
@ -260,27 +274,16 @@ const WizardStep = ({
|
|||
component={NumberInput}
|
||||
decimalPlaces={0}
|
||||
width={50}
|
||||
placeholder={cassetteInfo.amount.toString()}
|
||||
name={`cassette${step - 1}Count`}
|
||||
placeholder={originalCassetteCount.toString()}
|
||||
name={cassetteField}
|
||||
className={classes.cashboxBills}
|
||||
/>
|
||||
<P>
|
||||
{cassetteInfo.denomination} {fiatCurrency} bills loaded
|
||||
{cassetteDenomination} {fiatCurrency} bills loaded
|
||||
</P>
|
||||
</div>
|
||||
<P noMargin className={classes.fiatTotal}>
|
||||
={' '}
|
||||
{step === 2
|
||||
? (values.cassette1Count ?? 0) *
|
||||
cassetteInfo.denomination
|
||||
: (values.cassette2Count ?? 0) *
|
||||
cassetteInfo.denomination}{' '}
|
||||
{fiatCurrency}
|
||||
</P>
|
||||
<P className={classes.errorMessage}>
|
||||
{step === 2
|
||||
? errors.cassette1Count
|
||||
: errors.cassette2Count}
|
||||
= {cassetteTotal(values)} {fiatCurrency}
|
||||
</P>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ const GET_INFO = gql`
|
|||
machines {
|
||||
name
|
||||
deviceId
|
||||
numberOfCassettes
|
||||
}
|
||||
cryptoCurrencies {
|
||||
code
|
||||
|
|
|
|||
|
|
@ -18,13 +18,23 @@ import styles from './FiatBalanceAlerts.styles.js'
|
|||
const useStyles = makeStyles(styles)
|
||||
|
||||
const NAME = 'fiatBalanceAlerts'
|
||||
const DEFAULT_NUMBER_OF_CASSETTES = 2
|
||||
|
||||
const FiatBalance = ({ section, min = 0, max = 100, fieldWidth = 80 }) => {
|
||||
const { isEditing, isDisabled, setEditing, data, save } = useContext(
|
||||
NotificationsCtx
|
||||
)
|
||||
const {
|
||||
isEditing,
|
||||
isDisabled,
|
||||
setEditing,
|
||||
data,
|
||||
save,
|
||||
machines
|
||||
} = useContext(NotificationsCtx)
|
||||
const classes = useStyles()
|
||||
|
||||
const maxNumberOfCassettes =
|
||||
Math.max(...R.map(it => it.numberOfCassettes, machines)) ??
|
||||
DEFAULT_NUMBER_OF_CASSETTES
|
||||
|
||||
const editing = isEditing(NAME)
|
||||
|
||||
const schema = Yup.object().shape({
|
||||
|
|
@ -35,6 +45,18 @@ const FiatBalance = ({ section, min = 0, max = 100, fieldWidth = 80 }) => {
|
|||
.max(max)
|
||||
.nullable(),
|
||||
fillingPercentageCassette2: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(min)
|
||||
.max(max)
|
||||
.nullable(),
|
||||
fiatBalanceCassette3: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(min)
|
||||
.max(max)
|
||||
.nullable(),
|
||||
fiatBalanceCassette4: Yup.number()
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(min)
|
||||
|
|
@ -48,10 +70,10 @@ const FiatBalance = ({ section, min = 0, max = 100, fieldWidth = 80 }) => {
|
|||
validateOnChange={false}
|
||||
enableReinitialize
|
||||
initialValues={{
|
||||
fillingPercentageCassette1:
|
||||
R.path(['fillingPercentageCassette1'])(data) ?? '',
|
||||
fillingPercentageCassette2:
|
||||
R.path(['fillingPercentageCassette2'])(data) ?? ''
|
||||
fillingPercentageCassette1: data?.fillingPercentageCassette1 ?? '',
|
||||
fillingPercentageCassette2: data?.fillingPercentageCassette2 ?? '',
|
||||
fillingPercentageCassette3: data?.fillingPercentageCassette3 ?? '',
|
||||
fillingPercentageCassette4: data?.fillingPercentageCassette4 ?? ''
|
||||
}}
|
||||
validationSchema={schema}
|
||||
onSubmit={it => save(section, schema.cast(it))}
|
||||
|
|
@ -68,58 +90,38 @@ const FiatBalance = ({ section, min = 0, max = 100, fieldWidth = 80 }) => {
|
|||
setEditing={it => setEditing(NAME, it)}
|
||||
/>
|
||||
<div className={classes.wrapper}>
|
||||
<div className={classes.first}>
|
||||
<div className={classes.row}>
|
||||
<Cashbox
|
||||
labelClassName={classes.cashboxLabel}
|
||||
emptyPartClassName={classes.cashboxEmptyPart}
|
||||
percent={
|
||||
values.fillingPercentageCassette1 ??
|
||||
data?.fillingPercentageCassette1
|
||||
}
|
||||
applyColorVariant
|
||||
applyFiatBalanceAlertsStyling
|
||||
omitInnerPercentage
|
||||
cashOut
|
||||
/>
|
||||
<div className={classes.col2}>
|
||||
<TL2 className={classes.title}>Cassette 1 (Top)</TL2>
|
||||
<EditableNumber
|
||||
label="Alert me under"
|
||||
name="fillingPercentageCassette1"
|
||||
editing={editing}
|
||||
displayValue={x => (x === '' ? '-' : x)}
|
||||
decoration="%"
|
||||
width={fieldWidth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={classes.row}>
|
||||
<Cashbox
|
||||
labelClassName={classes.cashboxLabel}
|
||||
emptyPartClassName={classes.cashboxEmptyPart}
|
||||
percent={
|
||||
values.fillingPercentageCassette2 ??
|
||||
data?.fillingPercentageCassette2
|
||||
}
|
||||
applyColorVariant
|
||||
applyFiatBalanceAlertsStyling
|
||||
omitInnerPercentage
|
||||
cashOut
|
||||
/>
|
||||
<div className={classes.col2}>
|
||||
<TL2 className={classes.title}>Cassette 2 (Bottom)</TL2>
|
||||
<EditableNumber
|
||||
label="Alert me under"
|
||||
name="fillingPercentageCassette2"
|
||||
editing={editing}
|
||||
displayValue={x => (x === '' ? '-' : x)}
|
||||
decoration="%"
|
||||
width={fieldWidth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
{R.map(
|
||||
it => (
|
||||
<>
|
||||
<div className={classes.row}>
|
||||
<Cashbox
|
||||
labelClassName={classes.cashboxLabel}
|
||||
emptyPartClassName={classes.cashboxEmptyPart}
|
||||
percent={
|
||||
values[`fillingPercentageCassette${it + 1}`] ??
|
||||
data[`cassette${it + 1}`]
|
||||
}
|
||||
applyColorVariant
|
||||
applyFiatBalanceAlertsStyling
|
||||
omitInnerPercentage
|
||||
cashOut
|
||||
/>
|
||||
<div className={classes.col2}>
|
||||
<TL2 className={classes.title}>Cassette {it + 1}</TL2>
|
||||
<EditableNumber
|
||||
label="Alert me under"
|
||||
name={`fillingPercentageCassette${it + 1}`}
|
||||
editing={editing}
|
||||
displayValue={x => (x === '' ? '-' : x)}
|
||||
decoration="%"
|
||||
width={fieldWidth}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
),
|
||||
R.times(R.identity, maxNumberOfCassettes)
|
||||
)}
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -7,14 +7,11 @@ export default {
|
|||
form: {
|
||||
marginBottom: 36
|
||||
},
|
||||
first: {
|
||||
width: 236
|
||||
},
|
||||
title: {
|
||||
marginTop: 0
|
||||
},
|
||||
row: {
|
||||
width: 183,
|
||||
width: 236,
|
||||
display: 'grid',
|
||||
gridTemplateColumns: 'repeat(2,1fr)',
|
||||
gridTemplateRows: '1fr',
|
||||
|
|
|
|||
|
|
@ -11,9 +11,18 @@ import NotificationsCtx from '../NotificationsContext'
|
|||
|
||||
const CASSETTE_1_KEY = 'fillingPercentageCassette1'
|
||||
const CASSETTE_2_KEY = 'fillingPercentageCassette2'
|
||||
const CASSETTE_3_KEY = 'fillingPercentageCassette3'
|
||||
const CASSETTE_4_KEY = 'fillingPercentageCassette4'
|
||||
const MACHINE_KEY = 'machine'
|
||||
const NAME = 'fiatBalanceOverrides'
|
||||
|
||||
const CASSETTE_LIST = [
|
||||
CASSETTE_1_KEY,
|
||||
CASSETTE_2_KEY,
|
||||
CASSETTE_3_KEY,
|
||||
CASSETTE_4_KEY
|
||||
]
|
||||
|
||||
const FiatBalanceOverrides = ({ section }) => {
|
||||
const {
|
||||
machines = [],
|
||||
|
|
@ -41,42 +50,62 @@ const FiatBalanceOverrides = ({ section }) => {
|
|||
const initialValues = {
|
||||
[MACHINE_KEY]: null,
|
||||
[CASSETTE_1_KEY]: '',
|
||||
[CASSETTE_2_KEY]: ''
|
||||
[CASSETTE_2_KEY]: '',
|
||||
[CASSETTE_3_KEY]: '',
|
||||
[CASSETTE_4_KEY]: ''
|
||||
}
|
||||
|
||||
const maxNumberOfCassettes = Math.max(
|
||||
...R.map(it => it.numberOfCassettes, machines)
|
||||
)
|
||||
|
||||
const percentMin = 0
|
||||
const percentMax = 100
|
||||
const validationSchema = Yup.object().shape(
|
||||
{
|
||||
const validationSchema = Yup.object()
|
||||
.shape({
|
||||
[MACHINE_KEY]: Yup.string()
|
||||
.label('Machine')
|
||||
.nullable()
|
||||
.required(),
|
||||
[CASSETTE_1_KEY]: Yup.number()
|
||||
.label('Cassette 1 (top)')
|
||||
.when(CASSETTE_2_KEY, {
|
||||
is: CASSETTE_2_KEY => !CASSETTE_2_KEY,
|
||||
then: Yup.number().required()
|
||||
})
|
||||
.label('Cassette 1')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(percentMin)
|
||||
.max(percentMax)
|
||||
.nullable(),
|
||||
[CASSETTE_2_KEY]: Yup.number()
|
||||
.label('Cassette 2 (bottom)')
|
||||
.when(CASSETTE_1_KEY, {
|
||||
is: CASSETTE_1_KEY => !CASSETTE_1_KEY,
|
||||
then: Yup.number().required()
|
||||
})
|
||||
.label('Cassette 2')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(percentMin)
|
||||
.max(percentMax)
|
||||
.nullable(),
|
||||
[CASSETTE_3_KEY]: Yup.number()
|
||||
.label('Cassette 3')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(percentMin)
|
||||
.max(percentMax)
|
||||
.nullable(),
|
||||
[CASSETTE_4_KEY]: Yup.number()
|
||||
.label('Cassette 4')
|
||||
.transform(transformNumber)
|
||||
.integer()
|
||||
.min(percentMin)
|
||||
.max(percentMax)
|
||||
.nullable()
|
||||
},
|
||||
[CASSETTE_1_KEY, CASSETTE_2_KEY]
|
||||
)
|
||||
})
|
||||
.test((values, context) => {
|
||||
const picked = R.pick(CASSETTE_LIST, values)
|
||||
|
||||
if (CASSETTE_LIST.some(it => !R.isNil(picked[it]))) return
|
||||
|
||||
return context.createError({
|
||||
path: CASSETTE_1_KEY,
|
||||
message: 'At least one of the cassettes must have a value'
|
||||
})
|
||||
})
|
||||
|
||||
const viewMachine = it =>
|
||||
R.compose(R.path(['name']), R.find(R.propEq('deviceId', it)))(machines)
|
||||
|
|
@ -93,35 +122,35 @@ const FiatBalanceOverrides = ({ section }) => {
|
|||
valueProp: 'deviceId',
|
||||
labelProp: 'name'
|
||||
}
|
||||
},
|
||||
{
|
||||
name: CASSETTE_1_KEY,
|
||||
header: 'Cash-out 1',
|
||||
width: 155,
|
||||
textAlign: 'right',
|
||||
doubleHeader: 'Cash-out (Cassette Empty)',
|
||||
bold: true,
|
||||
input: NumberInput,
|
||||
suffix: '%',
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
},
|
||||
{
|
||||
name: CASSETTE_2_KEY,
|
||||
header: 'Cash-out 2',
|
||||
width: 155,
|
||||
textAlign: 'right',
|
||||
doubleHeader: 'Cash-out (Cassette Empty)',
|
||||
bold: true,
|
||||
input: NumberInput,
|
||||
suffix: '%',
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
R.until(
|
||||
R.gt(R.__, maxNumberOfCassettes),
|
||||
it => {
|
||||
elements.push({
|
||||
name: `fillingPercentageCassette${it}`,
|
||||
display: `Cash-out ${it}`,
|
||||
width: 155,
|
||||
textAlign: 'right',
|
||||
doubleHeader: 'Cash-out (Cassette Empty)',
|
||||
bold: true,
|
||||
input: NumberInput,
|
||||
suffix: '%',
|
||||
inputProps: {
|
||||
decimalPlaces: 0
|
||||
},
|
||||
view: it => it?.toString() ?? '—',
|
||||
isHidden: value =>
|
||||
it >
|
||||
machines.find(({ deviceId }) => deviceId === value.machine)
|
||||
?.numberOfCassettes
|
||||
})
|
||||
return R.add(1, it)
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
return (
|
||||
<EditableTable
|
||||
name={NAME}
|
||||
|
|
|
|||
|
|
@ -306,7 +306,7 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
) : (
|
||||
errorElements
|
||||
)}
|
||||
{getStatus(tx) === 'Pending' && (
|
||||
{tx.txClass === 'cashOut' && getStatus(tx) === 'Pending' && (
|
||||
<ActionButton
|
||||
color="primary"
|
||||
Icon={CancelIcon}
|
||||
|
|
@ -362,5 +362,7 @@ const DetailsRow = ({ it: tx, timezone }) => {
|
|||
export default memo(
|
||||
DetailsRow,
|
||||
(prev, next) =>
|
||||
prev.it.id === next.it.id && getStatus(prev.it) === getStatus(next.it)
|
||||
prev.it.id === next.it.id &&
|
||||
prev.it.hasError === next.it.hasError &&
|
||||
getStatus(prev.it) === getStatus(next.it)
|
||||
)
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -0,0 +1,85 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="316" viewBox="0 0 192 316">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-10, .cls-4 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-8 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-11 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 222.37 141.47 158 181.89 181.41 70.74 245.78 30.32 222.37"/>
|
||||
<polyline class="cls-2" points="141.48 202.52 68.77 244.64 32.31 223.53 141.48 160.3"/>
|
||||
<polygon class="cls-3" points="70.74 292.59 181.9 228.22 181.89 181.41 70.74 245.78 70.74 292.59"/>
|
||||
<polygon class="cls-4" points="141.48 160.3 141.48 202.52 159.71 191.97 177.93 181.41 141.48 160.3"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 163.85 141.47 99.48 181.89 122.89 70.74 187.26 30.32 163.85"/>
|
||||
<polyline class="cls-2" points="141.48 144 68.77 186.12 32.31 165.01 141.48 101.78"/>
|
||||
<polygon class="cls-3" points="70.74 234.07 181.9 169.71 181.89 122.89 70.74 187.26 70.74 234.07"/>
|
||||
<polygon class="cls-4" points="141.48 101.78 141.48 144 159.71 133.45 177.93 122.89 141.48 101.78"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="121.27 97.18 68.77 127.6 32.31 106.49 121.27 54.96"/>
|
||||
<polygon class="cls-6" points="30.32 105.33 121.26 52.67 161.68 76.07 70.74 128.74 30.32 105.33"/>
|
||||
<polygon class="cls-7" points="10.1 70.22 10.11 280.89 70.74 316 70.74 105.33 10.1 70.22"/>
|
||||
<polygon class="cls-3" points="20.21 169.71 60.63 193.11 60.63 239.93 20.21 216.52 20.21 169.71"/>
|
||||
<polygon class="cls-3" points="20.21 228.22 60.63 251.63 60.63 298.45 20.21 275.04 20.21 228.22"/>
|
||||
<polygon class="cls-8" points="0 122.89 40.42 146.3 40.42 193.11 0 169.7 0 122.89"/>
|
||||
<polygon class="cls-5" points="40.42 193.11 60.63 181.41 60.63 134.59 40.42 146.3 40.42 193.11"/>
|
||||
<polygon class="cls-5" points="70.74 175.56 161.69 122.89 161.68 76.07 70.74 128.74 70.74 175.56"/>
|
||||
<polyline class="cls-6" points="60.63 134.59 40.42 146.3 0 122.89 20.21 111.19"/>
|
||||
<polyline class="cls-5" points="58.65 133.44 40.42 144 3.97 122.89 22.2 112.33"/>
|
||||
<polygon class="cls-9" points="22.2 112.33 22.2 133.44 40.42 144 58.65 133.44 22.2 112.33"/>
|
||||
<polygon class="cls-9" points="121.27 54.96 121.27 97.18 139.49 86.63 157.72 76.07 121.27 54.96"/>
|
||||
<g>
|
||||
<polygon class="cls-10" points="70.74 105.33 192 35.11 192 245.78 70.74 316 70.74 105.33"/>
|
||||
<polygon class="cls-11" points="10.1 70.22 131.37 0 192 35.11 70.74 105.33 10.1 70.22"/>
|
||||
</g>
|
||||
<path class="cls-12" d="M13.08,161.89l4.4,2.94,0-11.26c0-.68,0-1.35,0-1.35l-.06,0a1.79,1.79,0,0,1-.88.55l-1.63.46-2.17-3.74L17.88,148l3.22,2.15v17.13l4.4,2.95v3.18l-12.42-8.31Z"/>
|
||||
<path class="cls-7" d="M32.61,210.69c0-7.57,9.51-3.1,9.51-7.41a5.94,5.94,0,0,0-3.07-4.79c-2.36-1.36-3.65.41-3.65.41l-2.73-3.49s1.87-3.15,6.7-.43c3.56,2,6.57,6.06,6.57,10.2,0,7-9.08,2.71-9.18,6.67l9.5,5.92v3.44l-13.48-8.55A16.93,16.93,0,0,1,32.61,210.69Z"/>
|
||||
<path class="cls-7" d="M33.74,265.64a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.37-4.34-5.85l-1.4-.88-.82-2.4,3.71-2.09a7.93,7.93,0,0,1,1.46-.63v-.06s-.6-.29-1.8-1l-6-3.78v-3.17l12.38,7.72V260l-5,2.65c2.8,2.15,5.54,5.86,5.54,9.38s-2.64,5-7.16,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -0,0 +1,85 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="316" viewBox="0 0 192 316">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-10, .cls-4 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-8 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-11 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 222.37 50.52 158 10.11 181.41 121.26 245.78 161.68 222.37"/>
|
||||
<polyline class="cls-2" points="50.52 202.52 123.23 244.64 159.69 223.53 50.52 160.3"/>
|
||||
<polygon class="cls-3" points="121.26 292.59 10.1 228.22 10.11 181.41 121.26 245.78 121.26 292.59"/>
|
||||
<polygon class="cls-4" points="50.52 160.3 50.52 202.52 32.29 191.97 14.07 181.41 50.52 160.3"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 163.85 50.53 99.48 10.11 122.89 121.26 187.26 161.68 163.85"/>
|
||||
<polyline class="cls-2" points="50.52 144 123.23 186.12 159.69 165.01 50.52 101.78"/>
|
||||
<polygon class="cls-3" points="121.26 234.07 10.1 169.71 10.11 122.89 121.26 187.26 121.26 234.07"/>
|
||||
<polygon class="cls-4" points="50.52 101.78 50.52 144 32.29 133.45 14.07 122.89 50.52 101.78"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="70.73 97.18 123.23 127.6 159.69 106.49 70.73 54.96"/>
|
||||
<polygon class="cls-6" points="161.68 105.33 70.74 52.67 30.32 76.07 121.26 128.74 161.68 105.33"/>
|
||||
<polygon class="cls-7" points="181.9 70.22 181.89 280.89 121.26 316 121.26 105.33 181.9 70.22"/>
|
||||
<polygon class="cls-3" points="171.79 169.71 131.37 193.11 131.37 239.93 171.79 216.52 171.79 169.71"/>
|
||||
<polygon class="cls-3" points="171.79 228.22 131.37 251.63 131.37 298.45 171.79 275.04 171.79 228.22"/>
|
||||
<polygon class="cls-8" points="192 122.89 151.58 146.3 151.58 193.11 192 169.7 192 122.89"/>
|
||||
<polygon class="cls-5" points="151.58 193.11 131.37 181.41 131.37 134.59 151.58 146.3 151.58 193.11"/>
|
||||
<polygon class="cls-5" points="121.26 175.56 30.32 122.89 30.32 76.07 121.26 128.74 121.26 175.56"/>
|
||||
<polyline class="cls-6" points="131.37 134.59 151.58 146.3 192 122.89 171.79 111.19"/>
|
||||
<polyline class="cls-5" points="133.35 133.44 151.58 144 188.03 122.89 169.81 112.33"/>
|
||||
<polygon class="cls-9" points="169.81 112.33 169.81 133.44 151.58 144 133.35 133.44 169.81 112.33"/>
|
||||
<polygon class="cls-9" points="70.73 54.96 70.73 97.18 52.51 86.63 34.28 76.07 70.73 54.96"/>
|
||||
<g>
|
||||
<polygon class="cls-10" points="121.26 105.33 0 35.11 0 245.78 121.26 316 121.26 105.33"/>
|
||||
<polygon class="cls-11" points="181.9 70.22 60.63 0 0 35.11 121.26 105.33 181.9 70.22"/>
|
||||
</g>
|
||||
<path class="cls-12" d="M166.87,169.18l4.35-2.47-.05-11.22c0-.68,0-1.38,0-1.38l-.05,0a10,10,0,0,1-.87,1.62l-1.59,2.44-2.12-1.11,4.95-7.64,3.14-1.74.12,17,4.35-2.47,0,3.13-12.29,7Z"/>
|
||||
<path class="cls-7" d="M145.58,218.78c0-7.34,9.32-13.48,9.29-17.48,0-1.75-1.37-2.09-3-1.21-2.32,1.23-3.57,4.29-3.57,4.29l-2.68-.41a15.18,15.18,0,0,1,6.54-7.51c3.47-1.83,6.45-1.23,6.49,2.55.07,6.43-8.86,12.32-8.93,16.19l9.37-5,0,3.13-13.34,7.21A13,13,0,0,1,145.58,218.78Z"/>
|
||||
<path class="cls-7" d="M147.85,270a4.94,4.94,0,0,0,4.55-.34c2.09-1.11,3.6-3.19,3.59-4.92,0-2.12-2-2.1-4.3-.87l-1.38.72-.81-1.46,3.61-6.28c.78-1.34,1.41-2.27,1.41-2.27v-.06s-.58.39-1.75,1l-5.91,3.07v-3.17l12.07-6.25,0,2.29-4.81,8.22c2.75-1,5.46-.48,5.51,3s-2.53,7.95-7,10.33c-4.28,2.28-6.66.82-6.66.82Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -0,0 +1,89 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="316" viewBox="0 0 192 316">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-4, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-4 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 222.37 141.47 158 181.89 181.41 70.74 245.78 30.32 222.37"/>
|
||||
<polyline class="cls-2" points="141.48 202.52 68.77 244.64 32.31 223.53 141.48 160.3"/>
|
||||
<polygon class="cls-3" points="70.74 292.59 181.9 228.22 181.89 181.41 70.74 245.78 70.74 292.59"/>
|
||||
<polygon class="cls-4" points="141.48 160.3 141.48 202.52 159.71 191.97 177.93 181.41 141.48 160.3"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="121.27 155.7 68.77 186.12 32.31 165.01 121.27 113.48"/>
|
||||
<polygon class="cls-6" points="30.32 163.85 121.26 111.18 161.68 134.59 70.74 187.26 30.32 163.85"/>
|
||||
<polygon class="cls-5" points="70.74 234.07 161.69 181.41 161.68 134.59 70.74 187.26 70.74 234.07"/>
|
||||
<polygon class="cls-7" points="121.27 113.48 121.27 155.7 139.5 145.15 157.72 134.59 121.27 113.48"/>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 105.33 141.47 40.96 181.89 64.37 70.74 128.74 30.32 105.33"/>
|
||||
<polyline class="cls-2" points="141.48 85.48 68.77 127.6 32.31 106.49 141.48 43.26"/>
|
||||
<polygon class="cls-3" points="70.74 175.55 181.9 111.18 181.89 64.37 70.74 128.74 70.74 175.55"/>
|
||||
<polygon class="cls-4" points="141.48 43.26 141.48 85.48 159.71 74.92 177.93 64.37 141.48 43.26"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="10.11 70.22 10.11 280.89 70.74 316 70.74 105.33 10.11 70.22"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="70.74 105.33 192 35.11 192 245.78 70.74 316 70.74 105.33"/>
|
||||
<polygon class="cls-10" points="10.11 70.22 131.37 0 192 35.11 70.74 105.33 10.11 70.22"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-3" points="20.21 228.22 60.63 251.63 60.63 298.45 20.21 275.04 20.21 228.22"/>
|
||||
<path class="cls-8" d="M33.74,265.64a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.37-4.34-5.85l-1.4-.88-.82-2.4,3.71-2.09a7.93,7.93,0,0,1,1.46-.63v-.06s-.6-.29-1.8-1l-6-3.78v-3.17l12.38,7.72V260l-5,2.65c2.8,2.15,5.54,5.86,5.54,9.38s-2.64,5-7.16,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="20.21 111.18 60.63 134.59 60.63 181.41 20.21 158 20.21 111.18"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-6" points="60.63 193.11 40.42 204.82 0 181.41 20.21 169.71"/>
|
||||
<polygon class="cls-11" points="0 181.41 40.42 204.82 40.42 251.63 0 228.22 0 181.41"/>
|
||||
<polygon class="cls-5" points="40.42 251.63 60.63 239.93 60.63 193.11 40.42 204.82 40.42 251.63"/>
|
||||
<polyline class="cls-5" points="58.65 191.96 40.42 202.52 3.97 181.41 22.19 170.85"/>
|
||||
<polygon class="cls-7" points="22.19 170.85 22.19 191.96 40.42 202.52 58.65 191.96 22.19 170.85"/>
|
||||
<path class="cls-12" d="M13.39,220.52c0-7.56,9.51-3.1,9.51-7.4a6,6,0,0,0-3.07-4.79c-2.36-1.36-3.65.4-3.65.4l-2.73-3.48s1.87-3.16,6.7-.43c3.56,2,6.57,6.05,6.57,10.19,0,7.05-9.08,2.71-9.18,6.68L27,227.61V231l-13.48-8.55A19,19,0,0,1,13.39,220.52Z"/>
|
||||
</g>
|
||||
<path class="cls-8" d="M32.29,147.62l4.4,2.95,0-11.26c0-.69,0-1.36,0-1.36l-.06,0a1.72,1.72,0,0,1-.88.55l-1.63.45L32,135.19l5.09-1.49,3.22,2.15V153l4.4,3v3.17l-12.42-8.31Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,92 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="316" viewBox="0 0 192 316">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-4, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-4 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 222.37 50.52 158 10.11 181.41 121.26 245.78 161.68 222.37"/>
|
||||
<polyline class="cls-2" points="50.52 202.52 123.23 244.64 159.69 223.53 50.52 160.3"/>
|
||||
<polygon class="cls-3" points="121.26 292.59 10.1 228.22 10.11 181.41 121.26 245.78 121.26 292.59"/>
|
||||
<polygon class="cls-4" points="50.52 160.3 50.52 202.52 32.29 191.97 14.07 181.41 50.52 160.3"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="70.73 155.7 123.23 186.12 159.69 165.01 70.73 113.48"/>
|
||||
<polygon class="cls-6" points="161.68 163.85 70.74 111.18 30.32 134.59 121.26 187.26 161.68 163.85"/>
|
||||
<polygon class="cls-5" points="121.26 234.07 30.31 181.41 30.32 134.59 121.26 187.26 121.26 234.07"/>
|
||||
<polygon class="cls-7" points="70.73 113.48 70.73 155.7 52.51 145.15 34.28 134.59 70.73 113.48"/>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 105.33 50.52 40.96 10.11 64.37 121.26 128.74 161.68 105.33"/>
|
||||
<polyline class="cls-2" points="50.52 85.48 123.23 127.6 159.69 106.49 50.52 43.26"/>
|
||||
<polygon class="cls-3" points="121.26 175.55 10.1 111.18 10.11 64.37 121.26 128.74 121.26 175.55"/>
|
||||
<polygon class="cls-4" points="50.52 43.26 50.52 85.48 32.29 74.92 14.07 64.37 50.52 43.26"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="181.9 70.22 181.89 280.89 121.26 316 121.26 105.33 181.9 70.22"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="121.26 105.33 0 35.11 0 245.78 121.26 316 121.26 105.33"/>
|
||||
<polygon class="cls-10" points="181.9 70.22 60.63 0 0 35.11 121.26 105.33 181.9 70.22"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-3" points="171.79 228.22 131.37 251.63 131.37 298.45 171.79 275.04 171.79 228.22"/>
|
||||
<path class="cls-8" d="M147.85,270a4.94,4.94,0,0,0,4.55-.34c2.09-1.11,3.6-3.19,3.58-4.92,0-2.12-2-2.1-4.29-.87l-1.38.72-.82-1.46,3.62-6.28c.78-1.34,1.41-2.27,1.41-2.27v-.06s-.58.39-1.75,1l-5.92,3.07v-3.17l12.07-6.25,0,2.29-4.81,8.22c2.75-1,5.46-.48,5.5,3s-2.52,7.95-7,10.33c-4.27,2.28-6.65.82-6.65.82Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="171.79 111.18 131.37 134.59 131.37 181.41 171.79 158 171.79 111.18"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-6" points="131.37 193.11 151.58 204.82 192 181.41 171.79 169.71"/>
|
||||
<polygon class="cls-11" points="192 181.41 151.58 204.82 151.58 251.63 192 228.22 192 181.41"/>
|
||||
<polygon class="cls-5" points="151.58 251.63 131.37 239.93 131.37 193.11 151.58 204.82 151.58 251.63"/>
|
||||
<polyline class="cls-5" points="133.35 191.96 151.58 202.52 188.03 181.41 169.81 170.85"/>
|
||||
<polygon class="cls-7" points="169.81 170.85 169.81 191.96 151.58 202.52 133.35 191.96 169.81 170.85"/>
|
||||
<g>
|
||||
<path class="cls-12" d="M165.65,229.37c0-7.33,9.32-13.48,9.29-17.47,0-1.76-1.37-2.1-3-1.21-2.32,1.22-3.57,4.28-3.57,4.28l-2.68-.41a15.13,15.13,0,0,1,6.54-7.5c3.47-1.83,6.45-1.24,6.49,2.54.07,6.43-8.86,12.32-8.93,16.19l9.37-5,0,3.13-13.34,7.21A13,13,0,0,1,165.65,229.37Z"/>
|
||||
<path class="cls-8" d="M165.65,229.37c0-7.33,9.32-13.48,9.29-17.47,0-1.76-1.37-2.1-3-1.21-2.32,1.22-3.57,4.28-3.57,4.28l-2.68-.41a15.13,15.13,0,0,1,6.54-7.5c3.47-1.83,6.45-1.24,6.49,2.54.07,6.43-8.86,12.32-8.93,16.19l9.37-5,0,3.13-13.34,7.21A13,13,0,0,1,165.65,229.37Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path class="cls-8" d="M147.65,155,152,152.5l0-11.22c0-.68,0-1.38,0-1.38l-.06,0a9.35,9.35,0,0,1-.86,1.62L149.47,144l-2.13-1.1,4.95-7.65,3.15-1.74.12,17,4.35-2.47,0,3.13-12.29,7Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -0,0 +1,91 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="316" viewBox="0 0 192 316">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-12, .cls-4 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-7, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-7 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polyline class="cls-1" points="121.27 214.22 68.77 244.64 32.31 223.53 121.27 172"/>
|
||||
<polygon class="cls-2" points="30.32 222.37 121.26 169.7 161.68 193.11 70.74 245.78 30.32 222.37"/>
|
||||
<polygon class="cls-1" points="70.74 292.59 161.69 239.93 161.68 193.11 70.74 245.78 70.74 292.59"/>
|
||||
<polygon class="cls-3" points="121.27 172 121.27 214.22 139.5 203.67 157.72 193.11 121.27 172"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="30.32 163.85 141.47 99.48 181.89 122.89 70.74 187.26 30.32 163.85"/>
|
||||
<polyline class="cls-5" points="141.48 144 68.77 186.12 32.31 165.01 141.48 101.78"/>
|
||||
<polygon class="cls-6" points="70.74 234.07 181.9 169.7 181.89 122.89 70.74 187.26 70.74 234.07"/>
|
||||
<polygon class="cls-7" points="141.48 101.78 141.48 144 159.71 133.44 177.93 122.89 141.48 101.78"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="30.32 105.33 141.47 40.96 181.89 64.37 70.74 128.74 30.32 105.33"/>
|
||||
<polyline class="cls-5" points="141.48 85.48 68.77 127.6 32.31 106.49 141.48 43.26"/>
|
||||
<polygon class="cls-6" points="70.74 175.55 181.9 111.18 181.89 64.37 70.74 128.74 70.74 175.55"/>
|
||||
<polygon class="cls-7" points="141.48 43.26 141.48 85.48 159.71 74.92 177.93 64.37 141.48 43.26"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="10.1 70.22 10.11 280.89 70.74 316 70.74 105.33 10.1 70.22"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="70.74 105.33 192 35.11 192 245.78 70.74 316 70.74 105.33"/>
|
||||
<polygon class="cls-10" points="10.1 70.22 131.37 0 192 35.11 70.74 105.33 10.1 70.22"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-6" points="20.21 169.71 60.63 193.11 60.63 239.93 20.21 216.52 20.21 169.71"/>
|
||||
<path class="cls-8" d="M32.61,210.69c0-7.57,9.51-3.1,9.51-7.41a5.94,5.94,0,0,0-3.07-4.79c-2.36-1.36-3.65.41-3.65.41l-2.73-3.49s1.87-3.15,6.7-.43c3.56,2,6.57,6.06,6.57,10.2,0,7-9.08,2.71-9.18,6.67l9.5,5.92v3.44l-13.48-8.55A16.93,16.93,0,0,1,32.61,210.69Z"/>
|
||||
</g>
|
||||
<polygon class="cls-6" points="20.21 111.18 60.63 134.59 60.63 181.41 20.21 158 20.21 111.18"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-2" points="60.63 251.63 40.42 263.33 0 239.93 20.21 228.22"/>
|
||||
<polygon class="cls-11" points="0 239.93 40.42 263.33 40.42 310.15 0 286.74 0 239.93"/>
|
||||
<polygon class="cls-1" points="40.42 310.15 60.63 298.44 60.63 251.63 40.42 263.33 40.42 310.15"/>
|
||||
<polyline class="cls-1" points="58.65 250.48 40.42 261.04 3.97 239.93 22.2 229.37"/>
|
||||
<polygon class="cls-3" points="22.2 229.37 22.2 250.48 40.42 261.04 58.65 250.48 22.2 229.37"/>
|
||||
<path class="cls-12" d="M14.55,279a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.38-4.34-5.86l-1.4-.87-.82-2.4L20,271.93a8,8,0,0,1,1.45-.63v-.06s-.59-.29-1.79-1l-6-3.77v-3.17L26,271v2.32L21,276c2.8,2.14,5.54,5.86,5.54,9.38s-2.63,5-7.15,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
</g>
|
||||
<path class="cls-8" d="M32.29,147.62l4.4,2.95,0-11.26c0-.69,0-1.36,0-1.36l-.06,0a1.72,1.72,0,0,1-.88.55l-1.63.45L32,135.19l5.09-1.49,3.22,2.15V153l4.4,3v3.17l-12.42-8.31Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
|
@ -0,0 +1,91 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="316" viewBox="0 0 192 316">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-12, .cls-4 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-7, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-7 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polyline class="cls-1" points="70.73 214.22 123.23 244.64 159.69 223.53 70.73 172"/>
|
||||
<polygon class="cls-2" points="161.68 222.37 70.74 169.7 30.32 193.11 121.26 245.78 161.68 222.37"/>
|
||||
<polygon class="cls-1" points="121.26 292.59 30.31 239.93 30.32 193.11 121.26 245.78 121.26 292.59"/>
|
||||
<polygon class="cls-3" points="70.73 172 70.73 214.22 52.51 203.67 34.28 193.11 70.73 172"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="161.68 163.85 50.52 99.48 10.11 122.89 121.26 187.26 161.68 163.85"/>
|
||||
<polyline class="cls-5" points="50.52 144 123.23 186.12 159.69 165.01 50.52 101.78"/>
|
||||
<polygon class="cls-6" points="121.26 234.07 10.1 169.7 10.11 122.89 121.26 187.26 121.26 234.07"/>
|
||||
<polygon class="cls-7" points="50.52 101.78 50.52 144 32.29 133.44 14.07 122.89 50.52 101.78"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="161.68 105.33 50.52 40.96 10.11 64.37 121.26 128.74 161.68 105.33"/>
|
||||
<polyline class="cls-5" points="50.52 85.48 123.23 127.6 159.69 106.49 50.52 43.26"/>
|
||||
<polygon class="cls-6" points="121.26 175.55 10.1 111.18 10.11 64.37 121.26 128.74 121.26 175.55"/>
|
||||
<polygon class="cls-7" points="50.52 43.26 50.52 85.48 32.29 74.92 14.07 64.37 50.52 43.26"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="181.9 70.22 181.89 280.89 121.26 316 121.26 105.33 181.9 70.22"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="121.26 105.33 0 35.11 0 245.78 121.26 316 121.26 105.33"/>
|
||||
<polygon class="cls-10" points="181.9 70.22 60.63 0 0 35.11 121.26 105.33 181.9 70.22"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-6" points="171.79 169.71 131.37 193.11 131.37 239.93 171.79 216.52 171.79 169.71"/>
|
||||
<path class="cls-8" d="M145.58,218.78c0-7.34,9.32-13.48,9.28-17.48,0-1.75-1.36-2.09-3-1.21-2.32,1.23-3.57,4.29-3.57,4.29l-2.68-.41a15.18,15.18,0,0,1,6.54-7.51c3.47-1.83,6.44-1.23,6.49,2.55.07,6.43-8.86,12.32-8.93,16.19l9.37-5,0,3.13-13.34,7.21A13,13,0,0,1,145.58,218.78Z"/>
|
||||
</g>
|
||||
<polygon class="cls-6" points="171.79 111.18 131.37 134.59 131.37 181.41 171.79 158 171.79 111.18"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-2" points="131.37 251.63 151.58 263.33 192 239.93 171.79 228.22"/>
|
||||
<polygon class="cls-11" points="192 239.93 151.58 263.33 151.58 310.15 192 286.74 192 239.93"/>
|
||||
<polygon class="cls-1" points="151.58 310.15 131.37 298.44 131.37 251.63 151.58 263.33 151.58 310.15"/>
|
||||
<polyline class="cls-1" points="133.35 250.48 151.58 261.04 188.03 239.93 169.81 229.37"/>
|
||||
<polygon class="cls-3" points="169.81 229.37 169.81 250.48 151.58 261.04 133.35 250.48 169.81 229.37"/>
|
||||
<path class="cls-12" d="M167.44,283.32A5,5,0,0,0,172,283c2.08-1.11,3.6-3.19,3.58-4.92,0-2.12-2-2.09-4.29-.87l-1.38.72-.82-1.45,3.62-6.29c.77-1.34,1.41-2.27,1.41-2.27v-.06a19.72,19.72,0,0,1-1.76,1l-5.91,3.07v-3.17l12.07-6.25,0,2.29L173.73,273c2.75-1,5.46-.48,5.5,3s-2.52,8-7,10.34c-4.27,2.27-6.65.81-6.65.81Z"/>
|
||||
</g>
|
||||
<path class="cls-8" d="M147.66,155,152,152.5l0-11.22c0-.68,0-1.38,0-1.38l-.06,0a9.35,9.35,0,0,1-.86,1.62L149.47,144l-2.13-1.1,5-7.65,3.14-1.74.12,17,4.35-2.47,0,3.13-12.29,7Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,95 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376" viewBox="0 0 192 376">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-10, .cls-4 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-8 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-11 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 282 141.47 217.37 181.89 240.87 70.74 305.5 30.32 282"/>
|
||||
<polyline class="cls-2" points="141.48 262.07 68.77 304.35 32.31 283.16 141.48 219.68"/>
|
||||
<polygon class="cls-3" points="70.74 352.5 181.9 287.87 181.89 240.87 70.74 305.5 70.74 352.5"/>
|
||||
<polygon class="cls-4" points="141.48 219.68 141.48 262.07 159.71 251.47 177.93 240.87 141.48 219.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 223.25 141.47 158.63 181.89 182.13 70.74 246.75 30.32 223.25"/>
|
||||
<polyline class="cls-2" points="141.48 203.32 68.77 245.6 32.31 224.41 141.48 160.93"/>
|
||||
<polygon class="cls-3" points="70.74 293.75 181.9 229.13 181.89 182.13 70.74 246.75 70.74 293.75"/>
|
||||
<polygon class="cls-4" points="141.48 160.93 141.48 203.32 159.71 192.72 177.93 182.13 141.48 160.93"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 164.5 141.47 99.88 181.89 123.38 70.74 188 30.32 164.5"/>
|
||||
<polyline class="cls-2" points="141.48 144.57 68.77 186.85 32.31 165.66 141.48 102.18"/>
|
||||
<polygon class="cls-3" points="70.74 235 181.9 170.38 181.89 123.38 70.74 188 70.74 235"/>
|
||||
<polygon class="cls-4" points="141.48 102.18 141.48 144.57 159.7 133.97 177.93 123.38 141.48 102.18"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="121.27 97.57 68.77 128.1 32.31 106.91 121.27 55.18"/>
|
||||
<polygon class="cls-6" points="30.32 105.75 121.26 52.87 161.68 76.38 70.73 129.25 30.32 105.75"/>
|
||||
<polygon class="cls-7" points="10.11 70.5 10.11 340.75 70.75 376 70.74 105.75 10.11 70.5"/>
|
||||
<polygon class="cls-3" points="20.21 170.38 60.63 193.88 60.63 240.88 20.21 217.38 20.21 170.38"/>
|
||||
<polygon class="cls-8" points="0 123.38 40.42 146.88 40.42 193.88 0 170.37 0 123.38"/>
|
||||
<polygon class="cls-5" points="40.42 193.88 60.63 182.13 60.63 135.13 40.42 146.88 40.42 193.88"/>
|
||||
<polygon class="cls-5" points="70.74 176.25 161.68 123.38 161.68 76.38 70.74 129.25 70.74 176.25"/>
|
||||
<polyline class="cls-6" points="60.63 135.13 40.42 146.88 0 123.38 20.21 111.63"/>
|
||||
<polyline class="cls-5" points="58.65 133.97 40.42 144.57 3.97 123.38 22.2 112.78"/>
|
||||
<polygon class="cls-9" points="22.2 112.78 22.2 133.97 40.42 144.57 58.65 133.97 22.2 112.78"/>
|
||||
<polygon class="cls-9" points="121.27 55.18 121.27 97.57 139.49 86.97 157.72 76.37 121.27 55.18"/>
|
||||
<g>
|
||||
<polygon class="cls-10" points="70.73 105.75 192 35.25 192 305.5 70.74 376 70.73 105.75"/>
|
||||
<polygon class="cls-11" points="10.1 70.5 131.37 0 192 35.25 70.73 105.75 10.1 70.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-3" points="20.21 229.12 60.63 252.62 60.63 299.62 20.21 276.12 20.21 229.12"/>
|
||||
<path class="cls-7" d="M33.74,265.64a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.37-4.34-5.85l-1.4-.88-.82-2.4,3.71-2.09a7.93,7.93,0,0,1,1.46-.63v-.06s-.6-.29-1.8-1l-6-3.78v-3.17l12.38,7.72V260l-5,2.65c2.8,2.15,5.54,5.86,5.54,9.38s-2.64,5-7.16,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="20.21 287.87 60.63 311.37 60.63 358.37 20.21 334.87 20.21 287.87"/>
|
||||
<path class="cls-7" d="M41.49,327.94v-12l-4.36-2.35-8.76,8.08v2.26L37.86,329v5.23l3.63,2V331l2.63,1.42v-3.06Zm-3.62-8.25V326l-5.61-3v-.05l4.7-4a5.87,5.87,0,0,0,1-1.32l.06,0A16.49,16.49,0,0,0,37.87,319.69Z"/>
|
||||
<path class="cls-7" d="M32.61,210.69c0-7.57,9.51-3.1,9.51-7.41a5.94,5.94,0,0,0-3.07-4.79c-2.36-1.36-3.65.41-3.65.41l-2.73-3.49s1.87-3.15,6.7-.43c3.56,2,6.57,6.06,6.57,10.2,0,7-9.08,2.71-9.18,6.67l9.5,5.92v3.44l-13.48-8.55A16.93,16.93,0,0,1,32.61,210.69Z"/>
|
||||
<path class="cls-12" d="M13.08,161.89l4.4,2.94,0-11.26c0-.68,0-1.35,0-1.35l-.06,0a1.79,1.79,0,0,1-.88.55l-1.63.46-2.17-3.74L17.88,148l3.22,2.15v17.13l4.4,2.95v3.18l-12.42-8.31Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
|
@ -0,0 +1,95 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376" viewBox="0 0 192 376">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-10, .cls-4 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-8 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-11 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 282 50.53 217.37 10.11 240.87 121.26 305.5 161.68 282"/>
|
||||
<polyline class="cls-2" points="50.52 262.07 123.23 304.35 159.69 283.16 50.52 219.68"/>
|
||||
<polygon class="cls-3" points="121.26 352.5 10.1 287.87 10.11 240.87 121.26 305.5 121.26 352.5"/>
|
||||
<polygon class="cls-4" points="50.52 219.68 50.52 262.07 32.3 251.47 14.07 240.87 50.52 219.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 223.25 50.53 158.63 10.11 182.13 121.26 246.75 161.68 223.25"/>
|
||||
<polyline class="cls-2" points="50.52 203.32 123.23 245.6 159.69 224.41 50.52 160.93"/>
|
||||
<polygon class="cls-3" points="121.26 293.75 10.1 229.13 10.11 182.13 121.26 246.75 121.26 293.75"/>
|
||||
<polygon class="cls-4" points="50.52 160.93 50.52 203.32 32.3 192.72 14.07 182.13 50.52 160.93"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 164.5 50.53 99.88 10.11 123.38 121.26 188 161.68 164.5"/>
|
||||
<polyline class="cls-2" points="50.52 144.57 123.23 186.85 159.69 165.66 50.52 102.18"/>
|
||||
<polygon class="cls-3" points="121.26 235 10.1 170.38 10.11 123.38 121.26 188 121.26 235"/>
|
||||
<polygon class="cls-4" points="50.52 102.18 50.52 144.57 32.3 133.97 14.07 123.38 50.52 102.18"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="70.73 97.57 123.23 128.1 159.69 106.91 70.73 55.18"/>
|
||||
<polygon class="cls-6" points="161.68 105.75 70.74 52.87 30.32 76.38 121.27 129.25 161.68 105.75"/>
|
||||
<polygon class="cls-7" points="181.89 70.5 181.89 340.75 121.25 376 121.26 105.75 181.89 70.5"/>
|
||||
<polygon class="cls-3" points="171.79 170.38 131.37 193.88 131.37 240.88 171.79 217.38 171.79 170.38"/>
|
||||
<polygon class="cls-8" points="192 123.38 151.58 146.88 151.58 193.88 192 170.37 192 123.38"/>
|
||||
<polygon class="cls-5" points="151.58 193.88 131.37 182.13 131.37 135.13 151.58 146.88 151.58 193.88"/>
|
||||
<polygon class="cls-5" points="121.26 176.25 30.32 123.38 30.32 76.38 121.26 129.25 121.26 176.25"/>
|
||||
<polyline class="cls-6" points="131.37 135.13 151.58 146.88 192 123.38 171.79 111.63"/>
|
||||
<polyline class="cls-5" points="133.35 133.97 151.58 144.57 188.03 123.38 169.81 112.78"/>
|
||||
<polygon class="cls-9" points="169.81 112.78 169.81 133.97 151.58 144.57 133.35 133.97 169.81 112.78"/>
|
||||
<polygon class="cls-9" points="70.73 55.18 70.73 97.57 52.51 86.97 34.28 76.37 70.73 55.18"/>
|
||||
<g>
|
||||
<polygon class="cls-10" points="121.27 105.75 0 35.25 0 305.5 121.26 376 121.27 105.75"/>
|
||||
<polygon class="cls-11" points="181.9 70.5 60.63 0 0 35.25 121.27 105.75 181.9 70.5"/>
|
||||
</g>
|
||||
<path class="cls-12" d="M166.87,169.85l4.35-2.48-.05-11.27c0-.68,0-1.38,0-1.38l-.05,0a9.32,9.32,0,0,1-.87,1.63l-1.59,2.44-2.12-1.11,4.95-7.67,3.14-1.75.12,17.05,4.35-2.48,0,3.14-12.29,7Z"/>
|
||||
<path class="cls-7" d="M145.58,219.64c0-7.36,9.32-13.53,9.29-17.54,0-1.76-1.37-2.11-3-1.22-2.32,1.23-3.56,4.3-3.56,4.3l-2.69-.41a15.23,15.23,0,0,1,6.54-7.53c3.47-1.84,6.45-1.24,6.49,2.55.07,6.46-8.86,12.38-8.93,16.26l9.37-5.07,0,3.14-13.34,7.24A13.34,13.34,0,0,1,145.58,219.64Z"/>
|
||||
<g>
|
||||
<polygon class="cls-3" points="171.79 229.12 131.37 252.62 131.37 299.62 171.79 276.12 171.79 229.12"/>
|
||||
<path class="cls-7" d="M147.85,271.1a4.93,4.93,0,0,0,4.55-.35c2.09-1.11,3.6-3.2,3.59-4.93,0-2.13-2-2.11-4.3-.88l-1.38.73-.81-1.47,3.61-6.3c.78-1.35,1.41-2.29,1.41-2.29v-.05s-.58.39-1.75,1l-5.91,3.08v-3.19l12.07-6.27,0,2.3-4.81,8.25c2.75-1,5.46-.47,5.51,3s-2.53,8-7,10.37c-4.28,2.28-6.66.82-6.66.82Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="171.79 287.87 131.37 311.37 131.37 358.37 171.79 334.87 171.79 287.87"/>
|
||||
<path class="cls-7" d="M145.25,330.84l8.51-16.71,4.26-1.91.14,11.92,2.58-1.18,0,3-2.59,1.19.06,5.2-3.6,1.66,0-5.21-9.36,4.29Zm9.34-5.07-.06-6.27a20.14,20.14,0,0,1,.13-2.17l-.06,0a20.39,20.39,0,0,1-1,2.29l-4.56,8.58v.06Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -0,0 +1,97 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376" viewBox="0 0 192 376">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-4, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-4 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 282 141.47 217.37 181.89 240.87 70.74 305.5 30.32 282"/>
|
||||
<polyline class="cls-2" points="141.48 262.06 68.77 304.35 32.31 283.16 141.48 219.68"/>
|
||||
<polygon class="cls-3" points="70.74 352.5 181.9 287.87 181.89 240.87 70.74 305.5 70.74 352.5"/>
|
||||
<polygon class="cls-4" points="141.48 219.68 141.48 262.06 159.71 251.47 177.93 240.87 141.48 219.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 223.25 141.47 158.63 181.89 182.13 70.74 246.75 30.32 223.25"/>
|
||||
<polyline class="cls-2" points="141.48 203.32 68.77 245.6 32.31 224.41 141.48 160.93"/>
|
||||
<polygon class="cls-3" points="70.74 293.75 181.9 229.13 181.89 182.13 70.74 246.75 70.74 293.75"/>
|
||||
<polygon class="cls-4" points="141.48 160.93 141.48 203.32 159.71 192.72 177.93 182.13 141.48 160.93"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="121.27 156.31 68.77 186.85 32.31 165.66 121.27 113.93"/>
|
||||
<polygon class="cls-6" points="30.32 164.5 121.26 111.62 161.68 135.12 70.74 188 30.32 164.5"/>
|
||||
<polygon class="cls-5" points="70.74 235 161.69 182.12 161.68 135.12 70.74 188 70.74 235"/>
|
||||
<polygon class="cls-7" points="121.27 113.93 121.27 156.31 139.5 145.72 157.72 135.12 121.27 113.93"/>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 105.75 141.47 41.12 181.89 64.62 70.74 129.25 30.32 105.75"/>
|
||||
<polyline class="cls-2" points="141.48 85.81 68.77 128.1 32.31 106.91 141.48 43.43"/>
|
||||
<polygon class="cls-3" points="70.74 176.25 181.9 111.62 181.89 64.62 70.74 129.25 70.74 176.25"/>
|
||||
<polygon class="cls-4" points="141.48 43.43 141.48 85.81 159.71 75.22 177.93 64.62 141.48 43.43"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="10.11 70.5 10.12 340.75 70.75 376 70.74 105.75 10.11 70.5"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="70.74 105.75 192 35.25 192 305.5 70.74 376 70.74 105.75"/>
|
||||
<polygon class="cls-10" points="10.11 70.5 131.37 0 192 35.25 70.74 105.75 10.11 70.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-3" points="20.21 229.12 60.63 252.62 60.63 299.62 20.21 276.12 20.21 229.12"/>
|
||||
<path class="cls-8" d="M33.74,265.64a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.37-4.34-5.85l-1.4-.88-.82-2.4,3.71-2.09a7.93,7.93,0,0,1,1.46-.63v-.06s-.6-.29-1.8-1l-6-3.78v-3.17l12.38,7.72V260l-5,2.65c2.8,2.15,5.54,5.86,5.54,9.38s-2.64,5-7.16,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="20.21 111.62 60.63 135.12 60.63 182.12 20.21 158.62 20.21 111.62"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-6" points="60.63 193.88 40.42 205.63 0 182.13 20.21 170.38"/>
|
||||
<polygon class="cls-11" points="0 182.13 40.42 205.63 40.42 252.63 0 229.13 0 182.13"/>
|
||||
<polygon class="cls-5" points="40.42 252.63 60.63 240.88 60.63 193.88 40.42 205.63 40.42 252.63"/>
|
||||
<polyline class="cls-5" points="58.65 192.72 40.42 203.32 3.97 182.13 22.19 171.53"/>
|
||||
<polygon class="cls-7" points="22.19 171.53 22.19 192.72 40.42 203.32 58.65 192.72 22.19 171.53"/>
|
||||
<path class="cls-12" d="M13.39,220.52c0-7.56,9.51-3.1,9.51-7.4a6,6,0,0,0-3.07-4.79c-2.36-1.36-3.65.4-3.65.4l-2.73-3.48s1.87-3.16,6.7-.43c3.56,2,6.57,6.05,6.57,10.19,0,7.05-9.08,2.71-9.18,6.68L27,227.61V231l-13.48-8.55A19,19,0,0,1,13.39,220.52Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="20.21 287.87 60.64 311.37 60.64 358.37 20.21 334.87 20.21 287.87"/>
|
||||
<path class="cls-8" d="M32.29,147.62l4.4,2.95,0-11.26c0-.69,0-1.36,0-1.36l-.06,0a1.72,1.72,0,0,1-.88.55l-1.63.45L32,135.19l5.09-1.49,3.22,2.15V153l4.4,3v3.17l-12.42-8.31Z"/>
|
||||
<path class="cls-8" d="M41.49,327.94v-12l-4.36-2.35-8.76,8.08v2.26L37.86,329v5.23l3.63,2V331l2.63,1.42v-3.06Zm-3.62-8.25V326l-5.61-3v-.05l4.7-4a5.87,5.87,0,0,0,1-1.32l.06,0A16.49,16.49,0,0,0,37.87,319.69Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
|
@ -0,0 +1,100 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376" viewBox="0 0 192 376">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-4, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-4 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 282 50.52 217.37 10.11 240.87 121.26 305.5 161.68 282"/>
|
||||
<polyline class="cls-2" points="50.52 262.06 123.23 304.35 159.69 283.16 50.52 219.68"/>
|
||||
<polygon class="cls-3" points="121.26 352.5 10.1 287.87 10.11 240.87 121.26 305.5 121.26 352.5"/>
|
||||
<polygon class="cls-4" points="50.52 219.68 50.52 262.06 32.29 251.47 14.07 240.87 50.52 219.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 223.25 50.52 158.63 10.11 182.13 121.26 246.75 161.68 223.25"/>
|
||||
<polyline class="cls-2" points="50.52 203.32 123.23 245.6 159.69 224.41 50.52 160.93"/>
|
||||
<polygon class="cls-3" points="121.26 293.75 10.1 229.13 10.11 182.13 121.26 246.75 121.26 293.75"/>
|
||||
<polygon class="cls-4" points="50.52 160.93 50.52 203.32 32.29 192.72 14.07 182.13 50.52 160.93"/>
|
||||
</g>
|
||||
<polyline class="cls-5" points="70.73 156.31 123.23 186.85 159.69 165.66 70.73 113.93"/>
|
||||
<polygon class="cls-6" points="161.68 164.5 70.74 111.62 30.32 135.12 121.26 188 161.68 164.5"/>
|
||||
<polygon class="cls-5" points="121.26 235 30.31 182.12 30.32 135.12 121.26 188 121.26 235"/>
|
||||
<polygon class="cls-7" points="70.73 113.93 70.73 156.31 52.51 145.72 34.28 135.12 70.73 113.93"/>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 105.75 50.52 41.12 10.11 64.62 121.26 129.25 161.68 105.75"/>
|
||||
<polyline class="cls-2" points="50.52 85.81 123.23 128.1 159.69 106.91 50.52 43.43"/>
|
||||
<polygon class="cls-3" points="121.26 176.25 10.1 111.62 10.11 64.62 121.26 129.25 121.26 176.25"/>
|
||||
<polygon class="cls-4" points="50.52 43.43 50.52 85.81 32.29 75.22 14.07 64.62 50.52 43.43"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="181.89 70.5 181.88 340.75 121.25 376 121.26 105.75 181.89 70.5"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="121.26 105.75 0 35.25 0 305.5 121.26 376 121.26 105.75"/>
|
||||
<polygon class="cls-10" points="181.9 70.5 60.63 0 0 35.25 121.26 105.75 181.9 70.5"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-3" points="171.79 229.12 131.37 252.62 131.37 299.62 171.79 276.12 171.79 229.12"/>
|
||||
<path class="cls-8" d="M147.85,271.1a4.92,4.92,0,0,0,4.55-.35c2.09-1.11,3.6-3.2,3.58-4.93,0-2.13-2-2.11-4.29-.88l-1.38.73-.82-1.47,3.62-6.3c.78-1.35,1.41-2.29,1.41-2.29v-.05s-.58.39-1.75,1l-5.92,3.08v-3.19l12.07-6.27,0,2.3-4.81,8.25c2.75-1,5.46-.47,5.5,3s-2.52,8-7,10.37c-4.27,2.28-6.65.82-6.65.82Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="171.79 111.62 131.37 135.12 131.37 182.12 171.79 158.62 171.79 111.62"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-6" points="131.37 193.88 151.58 205.63 192 182.13 171.79 170.38"/>
|
||||
<polygon class="cls-11" points="192 182.13 151.58 205.63 151.58 252.63 192 229.13 192 182.13"/>
|
||||
<polygon class="cls-5" points="151.58 252.63 131.37 240.88 131.37 193.88 151.58 205.63 151.58 252.63"/>
|
||||
<polyline class="cls-5" points="133.35 192.72 151.58 203.32 188.03 182.13 169.81 171.53"/>
|
||||
<polygon class="cls-7" points="169.81 171.53 169.81 192.72 151.58 203.32 133.35 192.72 169.81 171.53"/>
|
||||
<g>
|
||||
<path class="cls-12" d="M165.65,230.28c0-7.37,9.32-13.53,9.29-17.55,0-1.76-1.37-2.1-3-1.21-2.32,1.23-3.57,4.3-3.57,4.3l-2.68-.41a15.23,15.23,0,0,1,6.54-7.54c3.47-1.83,6.45-1.24,6.49,2.56.07,6.45-8.86,12.37-8.93,16.25l9.37-5.07,0,3.15L165.82,232A13.34,13.34,0,0,1,165.65,230.28Z"/>
|
||||
<path class="cls-8" d="M165.65,230.28c0-7.37,9.32-13.53,9.29-17.55,0-1.76-1.37-2.1-3-1.21-2.32,1.23-3.57,4.3-3.57,4.3l-2.68-.41a15.23,15.23,0,0,1,6.54-7.54c3.47-1.83,6.45-1.24,6.49,2.56.07,6.45-8.86,12.37-8.93,16.25l9.37-5.07,0,3.15L165.82,232A13.34,13.34,0,0,1,165.65,230.28Z"/>
|
||||
</g>
|
||||
</g>
|
||||
<path class="cls-8" d="M147.65,155.58,152,153.1l0-11.26c0-.69,0-1.39,0-1.39l-.06,0a9.6,9.6,0,0,1-.86,1.63l-1.59,2.45-2.13-1.11,4.95-7.67,3.15-1.75.12,17.05,4.35-2.48,0,3.14-12.29,7Z"/>
|
||||
<polygon class="cls-3" points="171.78 287.87 131.36 311.37 131.36 358.37 171.78 334.87 171.78 287.87"/>
|
||||
<path class="cls-8" d="M145.25,330.84l8.51-16.71,4.25-1.91.14,11.92,2.59-1.18,0,3-2.59,1.19.06,5.19-3.6,1.66,0-5.21-9.36,4.29Zm9.33-5.07-.05-6.27a21.54,21.54,0,0,1,.12-2.17l-.05,0a19.36,19.36,0,0,1-1,2.29l-4.56,8.58v.06Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
|
@ -0,0 +1,97 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376" viewBox="0 0 192 376">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-4, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-4 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.33 282 141.48 217.38 181.89 240.88 70.74 305.5 30.33 282"/>
|
||||
<polyline class="cls-2" points="141.48 262.07 68.77 304.35 32.32 283.16 141.48 219.68"/>
|
||||
<polygon class="cls-3" points="70.74 352.5 181.9 287.88 181.89 240.88 70.74 305.5 70.74 352.5"/>
|
||||
<polygon class="cls-4" points="141.48 219.68 141.48 262.07 159.71 251.47 177.93 240.88 141.48 219.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline class="cls-5" points="121.26 215.07 68.77 245.6 32.31 224.41 121.26 172.68"/>
|
||||
<polygon class="cls-6" points="30.32 223.25 121.26 170.37 161.68 193.88 70.73 246.75 30.32 223.25"/>
|
||||
<polygon class="cls-5" points="70.74 293.75 161.68 240.88 161.68 193.88 70.74 246.75 70.74 293.75"/>
|
||||
<polygon class="cls-7" points="121.26 172.68 121.26 215.07 139.49 204.47 157.72 193.87 121.26 172.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 164.5 141.47 99.87 181.89 123.37 70.73 188 30.32 164.5"/>
|
||||
<polyline class="cls-2" points="141.47 144.56 68.77 186.85 32.31 165.66 141.47 102.18"/>
|
||||
<polygon class="cls-3" points="70.74 235 181.89 170.37 181.89 123.37 70.74 188 70.74 235"/>
|
||||
<polygon class="cls-4" points="141.47 102.18 141.47 144.56 159.7 133.97 177.93 123.37 141.47 102.18"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="30.32 105.75 141.47 41.12 181.89 64.62 70.73 129.25 30.32 105.75"/>
|
||||
<polyline class="cls-2" points="141.47 85.81 68.77 128.1 32.31 106.91 141.47 43.43"/>
|
||||
<polygon class="cls-3" points="70.74 176.25 181.89 111.62 181.89 64.62 70.74 129.25 70.74 176.25"/>
|
||||
<polygon class="cls-4" points="141.47 43.43 141.47 85.81 159.7 75.22 177.93 64.62 141.47 43.43"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="10.1 70.5 10.11 340.75 70.74 376 70.73 105.75 10.1 70.5"/>
|
||||
<polygon class="cls-3" points="20.21 170.38 60.63 193.88 60.63 240.88 20.21 217.38 20.21 170.38"/>
|
||||
<polygon class="cls-3" points="20.21 111.62 60.63 135.12 60.63 182.12 20.21 158.62 20.21 111.62"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="70.74 105.75 192 35.25 192 305.5 70.74 376 70.74 105.75"/>
|
||||
<polygon class="cls-10" points="10.11 70.5 131.37 0 192 35.25 70.74 105.75 10.11 70.5"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="20.22 287.88 60.64 311.38 60.64 358.38 20.22 334.88 20.22 287.88"/>
|
||||
<path class="cls-8" d="M41.49,327.94v-12l-4.36-2.35-8.76,8.08v2.26L37.86,329v5.23l3.63,2V331l2.63,1.42v-3.06Zm-3.62-8.25V326l-5.61-3v-.05l4.7-4a5.87,5.87,0,0,0,1-1.32l.06,0A16.49,16.49,0,0,0,37.87,319.69Z"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-6" points="60.63 252.62 40.42 264.37 0 240.87 20.21 229.12"/>
|
||||
<polygon class="cls-11" points="0 240.87 40.42 264.37 40.42 311.37 0 287.87 0 240.87"/>
|
||||
<polygon class="cls-5" points="40.42 311.37 60.63 299.62 60.63 252.62 40.42 264.37 40.42 311.37"/>
|
||||
<polyline class="cls-5" points="58.65 251.47 40.42 262.07 3.97 240.87 22.19 230.28"/>
|
||||
<polygon class="cls-7" points="22.19 230.28 22.19 251.47 40.42 262.07 58.65 251.47 22.19 230.28"/>
|
||||
</g>
|
||||
<path class="cls-8" d="M32.29,147.62l4.4,2.95,0-11.26c0-.69,0-1.36,0-1.36l-.06,0a1.72,1.72,0,0,1-.88.55l-1.63.45L32,135.19l5.09-1.49,3.22,2.15V153l4.4,3v3.17l-12.42-8.31Z"/>
|
||||
<path class="cls-12" d="M14.55,279a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.38-4.34-5.86l-1.4-.87-.82-2.4L20,271.93a8,8,0,0,1,1.45-.63v-.06s-.59-.29-1.79-1l-6-3.77v-3.17L26,271v2.32L21,276c2.8,2.14,5.54,5.86,5.54,9.38s-2.63,5-7.15,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
<path class="cls-8" d="M32.61,210.69c0-7.57,9.51-3.1,9.51-7.41a5.94,5.94,0,0,0-3.07-4.79c-2.36-1.36-3.65.41-3.65.41l-2.73-3.49s1.87-3.15,6.7-.43c3.56,2,6.57,6.06,6.57,10.2,0,7-9.08,2.71-9.18,6.67l9.5,5.92v3.44l-13.48-8.55A16.93,16.93,0,0,1,32.61,210.69Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
|
@ -0,0 +1,99 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376" viewBox="0 0 192 376">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1, .cls-12 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-1, .cls-4, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-4 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-7 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.67 282 50.52 217.38 10.11 240.88 121.26 305.5 161.67 282"/>
|
||||
<polyline class="cls-2" points="50.52 262.07 123.23 304.35 159.68 283.16 50.52 219.68"/>
|
||||
<polygon class="cls-3" points="121.26 352.5 10.1 287.88 10.11 240.88 121.26 305.5 121.26 352.5"/>
|
||||
<polygon class="cls-4" points="50.52 219.68 50.52 262.07 32.29 251.47 14.07 240.88 50.52 219.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polyline class="cls-5" points="70.74 215.07 123.23 245.6 159.69 224.41 70.74 172.68"/>
|
||||
<polygon class="cls-6" points="161.68 223.25 70.74 170.37 30.32 193.88 121.27 246.75 161.68 223.25"/>
|
||||
<polygon class="cls-5" points="121.26 293.75 30.32 240.88 30.32 193.88 121.26 246.75 121.26 293.75"/>
|
||||
<polygon class="cls-7" points="70.74 172.68 70.74 215.07 52.51 204.47 34.28 193.87 70.74 172.68"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 164.5 50.53 99.87 10.11 123.37 121.27 188 161.68 164.5"/>
|
||||
<polyline class="cls-2" points="50.53 144.56 123.23 186.85 159.69 165.66 50.53 102.18"/>
|
||||
<polygon class="cls-3" points="121.26 235 10.11 170.37 10.11 123.37 121.26 188 121.26 235"/>
|
||||
<polygon class="cls-4" points="50.53 102.18 50.53 144.56 32.3 133.97 14.07 123.37 50.53 102.18"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-1" points="161.68 105.75 50.53 41.12 10.11 64.62 121.27 129.25 161.68 105.75"/>
|
||||
<polyline class="cls-2" points="50.53 85.81 123.23 128.1 159.69 106.91 50.53 43.43"/>
|
||||
<polygon class="cls-3" points="121.26 176.25 10.11 111.62 10.11 64.62 121.26 129.25 121.26 176.25"/>
|
||||
<polygon class="cls-4" points="50.53 43.43 50.53 85.81 32.3 75.22 14.07 64.62 50.53 43.43"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="181.9 70.5 181.89 340.75 121.26 376 121.27 105.75 181.9 70.5"/>
|
||||
<g>
|
||||
<polygon class="cls-3" points="171.79 170.38 131.37 193.88 131.37 240.88 171.79 217.38 171.79 170.38"/>
|
||||
<path class="cls-8" d="M145.58,219.64c0-7.36,9.32-13.53,9.29-17.54,0-1.76-1.37-2.11-3-1.22-2.31,1.23-3.56,4.31-3.56,4.31l-2.69-.42a15.23,15.23,0,0,1,6.54-7.53c3.47-1.84,6.45-1.24,6.49,2.55.07,6.46-8.86,12.38-8.93,16.26l9.37-5.07,0,3.14-13.34,7.24A13.17,13.17,0,0,1,145.58,219.64Z"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="171.79 111.62 131.37 135.12 131.37 182.12 171.79 158.62 171.79 111.62"/>
|
||||
<path class="cls-8" d="M147.66,155.58,152,153.1l0-11.26c0-.69,0-1.39,0-1.39l0,0a10.31,10.31,0,0,1-.87,1.63l-1.59,2.45-2.12-1.11,5-7.67,3.14-1.75.12,17.05,4.35-2.48,0,3.14-12.29,7Z"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="121.26 105.75 0 35.25 0 305.5 121.26 376 121.26 105.75"/>
|
||||
<polygon class="cls-10" points="181.89 70.5 60.63 0 0 35.25 121.26 105.75 181.89 70.5"/>
|
||||
</g>
|
||||
<polygon class="cls-3" points="171.78 287.88 131.36 311.38 131.36 358.38 171.78 334.88 171.78 287.88"/>
|
||||
<path class="cls-8" d="M145.25,330.84l8.5-16.71,4.26-1.91.14,11.92,2.58-1.18.05,3-2.6,1.19.06,5.19L154.65,334l-.05-5.21-9.35,4.29Zm9.33-5.07-.05-6.26a21.61,21.61,0,0,1,.12-2.18l-.06,0a20.39,20.39,0,0,1-1,2.29l-4.56,8.58v.06Z"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-6" points="131.37 252.62 151.58 264.37 192 240.87 171.79 229.12"/>
|
||||
<polygon class="cls-11" points="192 240.87 151.58 264.37 151.58 311.37 192 287.87 192 240.87"/>
|
||||
<polygon class="cls-5" points="151.58 311.37 131.37 299.62 131.37 252.62 151.58 264.37 151.58 311.37"/>
|
||||
<polyline class="cls-5" points="133.35 251.47 151.58 262.07 188.03 240.87 169.81 230.28"/>
|
||||
<polygon class="cls-7" points="169.81 230.28 169.81 251.47 151.58 262.07 133.35 251.47 169.81 230.28"/>
|
||||
<path class="cls-12" d="M167.44,284.44a4.92,4.92,0,0,0,4.55-.35c2.09-1.11,3.6-3.2,3.58-4.94,0-2.13-2-2.1-4.29-.87l-1.38.72-.82-1.46,3.62-6.31c.77-1.35,1.41-2.28,1.41-2.28v-.06s-.58.39-1.75,1L166.44,273v-3.19l12.07-6.27,0,2.29-4.81,8.26c2.75-1.05,5.46-.48,5.5,3s-2.52,8-7,10.38c-4.27,2.28-6.65.82-6.65.82Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,101 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376.47" viewBox="0 0 192 376.47">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-12, .cls-4 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-7, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-7 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polyline class="cls-1" points="121.26 274.16 68.77 304.73 32.31 283.51 121.26 231.72"/>
|
||||
<polygon class="cls-2" points="30.32 282.35 121.26 229.41 161.68 252.94 70.73 305.88 30.32 282.35"/>
|
||||
<polygon class="cls-1" points="70.74 352.94 161.68 300 161.68 252.94 70.74 305.88 70.74 352.94"/>
|
||||
<polygon class="cls-3" points="121.26 231.72 121.26 274.16 139.49 263.55 157.72 252.94 121.26 231.72"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="30.33 223.53 141.48 158.82 181.89 182.35 70.74 247.06 30.33 223.53"/>
|
||||
<polyline class="cls-5" points="141.48 203.57 68.77 245.91 32.32 224.69 141.48 161.13"/>
|
||||
<polygon class="cls-6" points="70.74 294.12 181.9 229.41 181.89 182.35 70.74 247.06 70.74 294.12"/>
|
||||
<polygon class="cls-7" points="141.48 161.13 141.48 203.57 159.71 192.96 177.93 182.35 141.48 161.13"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="30.32 164.7 141.47 100 181.89 123.53 70.73 188.23 30.32 164.7"/>
|
||||
<polyline class="cls-5" points="141.47 144.74 68.77 187.08 32.31 165.86 141.47 102.31"/>
|
||||
<polygon class="cls-6" points="70.74 235.29 181.89 170.59 181.89 123.53 70.74 188.23 70.74 235.29"/>
|
||||
<polygon class="cls-7" points="141.47 102.31 141.47 144.74 159.7 134.14 177.93 123.53 141.47 102.31"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="30.32 105.88 141.47 41.17 181.89 64.7 70.73 129.41 30.32 105.88"/>
|
||||
<polyline class="cls-5" points="141.47 85.92 68.77 128.26 32.31 107.04 141.47 43.48"/>
|
||||
<polygon class="cls-6" points="70.74 176.47 181.89 111.76 181.89 64.7 70.74 129.41 70.74 176.47"/>
|
||||
<polygon class="cls-7" points="141.47 43.48 141.47 85.92 159.7 75.31 177.93 64.7 141.47 43.48"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="10.1 70.58 10.11 341.17 70.74 376.47 70.73 105.88 10.1 70.58"/>
|
||||
<polygon class="cls-6" points="20.21 170.59 60.63 194.12 60.63 241.18 20.21 217.65 20.21 170.59"/>
|
||||
<polygon class="cls-6" points="20.21 111.76 60.63 135.29 60.63 182.35 20.21 158.82 20.21 111.76"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="70.74 105.88 192 35.29 192 305.88 70.74 376.47 70.74 105.88"/>
|
||||
<polygon class="cls-10" points="10.11 70.59 131.37 0 192 35.29 70.74 105.88 10.11 70.59"/>
|
||||
</g>
|
||||
<polygon class="cls-6" points="20.22 288.23 60.64 311.76 60.64 358.82 20.22 335.29 20.22 288.23"/>
|
||||
<path class="cls-8" d="M46.75,333.53l-9.35-4.3,0,5.22-3.59-1.67.06-5.2-2.6-1.19.05-3,2.58,1.18L34,312.61l4.26,1.91,8.5,16.73Zm-3.82-4.83v-.06l-4.56-8.59a20.17,20.17,0,0,1-1-2.3l-.06,0a21.54,21.54,0,0,1,.12,2.17l0,6.28Z"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-2" points="60.63 311.76 40.42 323.53 0 300 20.21 288.23"/>
|
||||
<polygon class="cls-11" points="0 300 40.42 323.53 40.42 370.59 0 347.06 0 300"/>
|
||||
<polygon class="cls-1" points="40.42 370.59 60.63 358.82 60.63 311.76 40.42 323.53 40.42 370.59"/>
|
||||
<polyline class="cls-1" points="58.65 310.61 40.42 321.22 3.97 300 22.19 289.39"/>
|
||||
<polygon class="cls-3" points="22.19 289.39 22.19 310.61 40.42 321.22 58.65 310.61 22.19 289.39"/>
|
||||
<path class="cls-12" d="M23.23,339.27v-12l-4.36-2.36L10.11,333v2.26l9.5,5.12v5.24l3.63,2v-5.24l2.63,1.43v-3.07ZM19.61,331v6.29l-5.6-3v-.06l4.69-4a5.54,5.54,0,0,0,1-1.32l.06,0A17.65,17.65,0,0,0,19.61,331Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-6" points="20.22 229.41 60.64 252.94 60.64 300 20.22 276.47 20.22 229.41"/>
|
||||
<path class="cls-8" d="M33.74,265.64a16.52,16.52,0,0,0,4.6,4.93c2.12,1.32,3.66,1,3.66-.75,0-2.14-2-4.37-4.34-5.85l-1.4-.88-.82-2.4,3.71-2.09a7.93,7.93,0,0,1,1.46-.63v-.06s-.6-.29-1.8-1l-6-3.78v-3.17l12.38,7.72V260l-5,2.65c2.8,2.15,5.54,5.86,5.54,9.38s-2.64,5-7.16,2.2a22,22,0,0,1-6.72-6.91Z"/>
|
||||
</g>
|
||||
<path class="cls-8" d="M32.29,147.62l4.4,2.95,0-11.26c0-.69,0-1.36,0-1.36l-.06,0a1.72,1.72,0,0,1-.88.55l-1.63.45L32,135.19l5.09-1.49,3.22,2.15V153l4.4,3v3.17l-12.42-8.31Z"/>
|
||||
<path class="cls-8" d="M32.61,210.69c0-7.57,9.51-3.1,9.51-7.41a5.94,5.94,0,0,0-3.07-4.79c-2.36-1.36-3.65.41-3.65.41l-2.73-3.49s1.87-3.15,6.7-.43c3.56,2,6.57,6.06,6.57,10.2,0,7-9.08,2.71-9.18,6.67l9.5,5.92v3.44l-13.48-8.55A16.93,16.93,0,0,1,32.61,210.69Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
|
@ -0,0 +1,103 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="376.47" viewBox="0 0 192 376.47">
|
||||
<defs>
|
||||
<style>
|
||||
.cls-1 {
|
||||
fill: #4b5fef;
|
||||
}
|
||||
|
||||
.cls-2 {
|
||||
fill: #7687ff;
|
||||
}
|
||||
|
||||
.cls-3 {
|
||||
fill: #1b2559;
|
||||
}
|
||||
|
||||
.cls-12, .cls-4 {
|
||||
fill: #fff;
|
||||
}
|
||||
|
||||
.cls-4, .cls-7, .cls-9 {
|
||||
opacity: 0.74;
|
||||
}
|
||||
|
||||
.cls-5 {
|
||||
fill: #b8c2e6;
|
||||
}
|
||||
|
||||
.cls-6 {
|
||||
fill: #d2d8ff;
|
||||
}
|
||||
|
||||
.cls-11, .cls-7 {
|
||||
fill: #5a67ff;
|
||||
}
|
||||
|
||||
.cls-8 {
|
||||
fill: #ebefff;
|
||||
}
|
||||
|
||||
.cls-9 {
|
||||
fill: #ccd8ff;
|
||||
}
|
||||
|
||||
.cls-10 {
|
||||
fill: #dee5fc;
|
||||
opacity: 0.8;
|
||||
}
|
||||
</style>
|
||||
</defs>
|
||||
<g id="Layer_1" data-name="Layer 1">
|
||||
<g>
|
||||
<g>
|
||||
<polyline class="cls-1" points="70.74 274.16 123.23 304.73 159.69 283.51 70.74 231.72"/>
|
||||
<polygon class="cls-2" points="161.68 282.35 70.74 229.41 30.32 252.94 121.27 305.88 161.68 282.35"/>
|
||||
<polygon class="cls-1" points="121.26 352.94 30.32 300 30.32 252.94 121.26 305.88 121.26 352.94"/>
|
||||
<polygon class="cls-3" points="70.74 231.72 70.74 274.16 52.51 263.55 34.28 252.94 70.74 231.72"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="161.67 223.53 50.52 158.82 10.11 182.35 121.26 247.06 161.67 223.53"/>
|
||||
<polyline class="cls-5" points="50.52 203.57 123.23 245.91 159.68 224.69 50.52 161.13"/>
|
||||
<polygon class="cls-6" points="121.26 294.12 10.1 229.41 10.11 182.35 121.26 247.06 121.26 294.12"/>
|
||||
<polygon class="cls-7" points="50.52 161.13 50.52 203.57 32.29 192.96 14.07 182.35 50.52 161.13"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="161.68 164.7 50.53 100 10.11 123.53 121.27 188.23 161.68 164.7"/>
|
||||
<polyline class="cls-5" points="50.53 144.74 123.23 187.08 159.69 165.86 50.53 102.31"/>
|
||||
<polygon class="cls-6" points="121.26 235.29 10.11 170.59 10.11 123.53 121.26 188.23 121.26 235.29"/>
|
||||
<polygon class="cls-7" points="50.53 102.31 50.53 144.74 32.3 134.14 14.07 123.53 50.53 102.31"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-4" points="161.68 105.88 50.53 41.17 10.11 64.7 121.27 129.41 161.68 105.88"/>
|
||||
<polyline class="cls-5" points="50.53 85.92 123.23 128.26 159.69 107.04 50.53 43.48"/>
|
||||
<polygon class="cls-6" points="121.26 176.47 10.11 111.76 10.11 64.7 121.26 129.41 121.26 176.47"/>
|
||||
<polygon class="cls-7" points="50.53 43.48 50.53 85.92 32.3 75.31 14.07 64.7 50.53 43.48"/>
|
||||
</g>
|
||||
<polygon class="cls-8" points="181.9 70.58 181.89 341.17 121.26 376.47 121.27 105.88 181.9 70.58"/>
|
||||
<g>
|
||||
<polygon class="cls-6" points="171.79 170.59 131.37 194.12 131.37 241.18 171.79 217.65 171.79 170.59"/>
|
||||
<path class="cls-8" d="M145.58,219.91c0-7.37,9.32-13.54,9.29-17.56,0-1.77-1.37-2.11-3-1.22-2.31,1.23-3.56,4.31-3.56,4.31l-2.69-.41a15.23,15.23,0,0,1,6.54-7.55c3.47-1.83,6.45-1.24,6.49,2.56.07,6.46-8.86,12.39-8.93,16.28l9.37-5.08,0,3.15-13.34,7.25A13.31,13.31,0,0,1,145.58,219.91Z"/>
|
||||
</g>
|
||||
<polygon class="cls-6" points="171.79 111.76 131.37 135.29 131.37 182.35 171.79 158.82 171.79 111.76"/>
|
||||
<path class="cls-8" d="M147.66,155.77l4.35-2.48L152,142c0-.69,0-1.39,0-1.39l0,0a10.31,10.31,0,0,1-.87,1.63l-1.59,2.45-2.12-1.11,5-7.68,3.14-1.76.12,17.07,4.35-2.48,0,3.15-12.29,7Z"/>
|
||||
<g>
|
||||
<polygon class="cls-9" points="121.26 105.88 0 35.29 0 305.88 121.26 376.47 121.26 105.88"/>
|
||||
<polygon class="cls-10" points="181.89 70.59 60.63 0 0 35.29 121.26 105.88 181.89 70.59"/>
|
||||
</g>
|
||||
<polygon class="cls-6" points="171.78 288.23 131.36 311.76 131.36 358.82 171.78 335.29 171.78 288.23"/>
|
||||
<path class="cls-8" d="M145.25,331.25l8.5-16.73,4.26-1.91.14,11.93,2.58-1.18.05,3-2.6,1.19.06,5.2-3.59,1.67-.05-5.22-9.35,4.3Zm9.33-5.07-.05-6.28a21.54,21.54,0,0,1,.12-2.17l-.06,0a20.17,20.17,0,0,1-1,2.3l-4.56,8.59v.06Z"/>
|
||||
<g id="front-drawerr">
|
||||
<polyline class="cls-2" points="131.37 311.76 151.58 323.53 192 300 171.79 288.23"/>
|
||||
<polygon class="cls-11" points="192 300 151.58 323.53 151.58 370.59 192 347.06 192 300"/>
|
||||
<polygon class="cls-1" points="151.58 370.59 131.37 358.82 131.37 311.76 151.58 323.53 151.58 370.59"/>
|
||||
<polyline class="cls-1" points="133.35 310.61 151.58 321.22 188.03 300 169.81 289.39"/>
|
||||
<polygon class="cls-3" points="169.81 289.39 169.81 310.61 151.58 321.22 133.35 310.61 169.81 289.39"/>
|
||||
<path class="cls-12" d="M165.58,341.32l8.51-16.73,4.25-1.92.14,11.94,2.59-1.18,0,3-2.59,1.19.06,5.2-3.6,1.66,0-5.22-9.36,4.3Zm9.33-5.08,0-6.27a21.61,21.61,0,0,1,.12-2.18l-.06,0a18.3,18.3,0,0,1-1,2.3l-4.56,8.59v.05Z"/>
|
||||
</g>
|
||||
<g>
|
||||
<polygon class="cls-6" points="171.78 229.41 131.36 252.94 131.36 300 171.78 276.47 171.78 229.41"/>
|
||||
<path class="cls-8" d="M147.85,271.44a4.92,4.92,0,0,0,4.55-.35c2.08-1.11,3.6-3.2,3.58-4.94,0-2.14-2-2.11-4.29-.88l-1.38.73-.82-1.47,3.62-6.31c.77-1.35,1.41-2.29,1.41-2.29v-.05s-.59.39-1.76,1L146.85,260v-3.19l12.07-6.28,0,2.29-4.8,8.27c2.75-1.05,5.46-.48,5.5,3s-2.52,8-7,10.38c-4.27,2.29-6.65.83-6.65.83Z"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5 KiB |
6
package-lock.json
generated
|
|
@ -14459,6 +14459,7 @@
|
|||
"from": "git+https://github.com/lamassu/lamassu-coins.git",
|
||||
"requires": {
|
||||
"bech32": "2.0.0",
|
||||
"big-integer": "^1.6.48",
|
||||
"bignumber.js": "^9.0.0",
|
||||
"bitcoinjs-lib": "4.0.3",
|
||||
"bs58check": "^2.0.2",
|
||||
|
|
@ -14474,6 +14475,11 @@
|
|||
"resolved": "https://registry.npmjs.org/bech32/-/bech32-2.0.0.tgz",
|
||||
"integrity": "sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg=="
|
||||
},
|
||||
"big-integer": {
|
||||
"version": "1.6.51",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz",
|
||||
"integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg=="
|
||||
},
|
||||
"bip32": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/bip32/-/bip32-1.0.4.tgz",
|
||||
|
|
|
|||
|
|
@ -1,13 +1,20 @@
|
|||
{
|
||||
"files": {
|
||||
"main.js": "/static/js/main.ff8544f4.chunk.js",
|
||||
"main.js.map": "/static/js/main.ff8544f4.chunk.js.map",
|
||||
"main.js": "/static/js/main.144ef1be.chunk.js",
|
||||
"main.js.map": "/static/js/main.144ef1be.chunk.js.map",
|
||||
"runtime-main.js": "/static/js/runtime-main.5b925903.js",
|
||||
"runtime-main.js.map": "/static/js/runtime-main.5b925903.js.map",
|
||||
"static/js/2.cd718274.chunk.js": "/static/js/2.cd718274.chunk.js",
|
||||
"static/js/2.cd718274.chunk.js.map": "/static/js/2.cd718274.chunk.js.map",
|
||||
"static/js/2.e38b81ec.chunk.js": "/static/js/2.e38b81ec.chunk.js",
|
||||
"static/js/2.e38b81ec.chunk.js.map": "/static/js/2.e38b81ec.chunk.js.map",
|
||||
"index.html": "/index.html",
|
||||
"static/js/2.cd718274.chunk.js.LICENSE.txt": "/static/js/2.cd718274.chunk.js.LICENSE.txt",
|
||||
"static/js/2.e38b81ec.chunk.js.LICENSE.txt": "/static/js/2.e38b81ec.chunk.js.LICENSE.txt",
|
||||
"static/media/3-cassettes-open-1-left.d6d9aa73.svg": "/static/media/3-cassettes-open-1-left.d6d9aa73.svg",
|
||||
"static/media/3-cassettes-open-2-left.a9ee8d4c.svg": "/static/media/3-cassettes-open-2-left.a9ee8d4c.svg",
|
||||
"static/media/3-cassettes-open-3-left.08fed660.svg": "/static/media/3-cassettes-open-3-left.08fed660.svg",
|
||||
"static/media/4-cassettes-open-1-left.7b00c51f.svg": "/static/media/4-cassettes-open-1-left.7b00c51f.svg",
|
||||
"static/media/4-cassettes-open-2-left.b3d9541c.svg": "/static/media/4-cassettes-open-2-left.b3d9541c.svg",
|
||||
"static/media/4-cassettes-open-3-left.e8f1667c.svg": "/static/media/4-cassettes-open-3-left.e8f1667c.svg",
|
||||
"static/media/4-cassettes-open-4-left.bc1a9829.svg": "/static/media/4-cassettes-open-4-left.bc1a9829.svg",
|
||||
"static/media/acceptor-left.f37bcb1a.svg": "/static/media/acceptor-left.f37bcb1a.svg",
|
||||
"static/media/both-filled.7af80d5f.svg": "/static/media/both-filled.7af80d5f.svg",
|
||||
"static/media/carousel-left-arrow.04e38344.svg": "/static/media/carousel-left-arrow.04e38344.svg",
|
||||
|
|
@ -125,7 +132,7 @@
|
|||
},
|
||||
"entrypoints": [
|
||||
"static/js/runtime-main.5b925903.js",
|
||||
"static/js/2.cd718274.chunk.js",
|
||||
"static/js/main.ff8544f4.chunk.js"
|
||||
"static/js/2.e38b81ec.chunk.js",
|
||||
"static/js/main.144ef1be.chunk.js"
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +1 @@
|
|||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="robots" content="noindex"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Lamassu Admin</title></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root" class="root"></div><script>!function(e){function r(r){for(var n,a,l=r[0],i=r[1],f=r[2],c=0,s=[];c<l.length;c++)a=l[c],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var i=t[l];0!==o[i]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/";var l=this["webpackJsonplamassu-admin"]=this["webpackJsonplamassu-admin"]||[],i=l.push.bind(l);l.push=r,l=l.slice();for(var f=0;f<l.length;f++)r(l[f]);var p=i;t()}([])</script><script src="/static/js/2.cd718274.chunk.js"></script><script src="/static/js/main.ff8544f4.chunk.js"></script></body></html>
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"/><link rel="shortcut icon" href="/favicon.ico"/><meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no"/><meta name="robots" content="noindex"/><meta name="theme-color" content="#000000"/><link rel="manifest" href="/manifest.json"/><title>Lamassu Admin</title></head><body><noscript>You need to enable JavaScript to run this app.</noscript><div id="root" class="root"></div><script>!function(e){function r(r){for(var n,a,l=r[0],i=r[1],f=r[2],c=0,s=[];c<l.length;c++)a=l[c],Object.prototype.hasOwnProperty.call(o,a)&&o[a]&&s.push(o[a][0]),o[a]=0;for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n]);for(p&&p(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var i=t[l];0!==o[i]&&(n=!1)}n&&(u.splice(r--,1),e=a(a.s=t[0]))}return e}var n={},o={1:0},u=[];function a(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,a),t.l=!0,t.exports}a.m=e,a.c=n,a.d=function(e,r,t){a.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},a.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},a.t=function(e,r){if(1&r&&(e=a(e)),8&r)return e;if(4&r&&"object"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(a.r(t),Object.defineProperty(t,"default",{enumerable:!0,value:e}),2&r&&"string"!=typeof e)for(var n in e)a.d(t,n,function(r){return e[r]}.bind(null,n));return t},a.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return a.d(r,"a",r),r},a.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},a.p="/";var l=this["webpackJsonplamassu-admin"]=this["webpackJsonplamassu-admin"]||[],i=l.push.bind(l);l.push=r,l=l.slice();for(var f=0;f<l.length;f++)r(l[f]);var p=i;t()}([])</script><script src="/static/js/2.e38b81ec.chunk.js"></script><script src="/static/js/main.144ef1be.chunk.js"></script></body></html>
|
||||