feat: created the search component
style: added spec styles fix: fixed font color on search input style: added box-shadow to the search component feat: added local search functionality to the search component feat: integrated search component into the transactions page feat: allow multiple filter selection on the search component fix: let the user select only one filter for each type feat: added chips for the selected filters on the transactions page feat: added the remove function on the filter chips style: styled items according to spec refactor: simplified search component (moved logic to the outside) feat: added transaction filters to the gql query feat: added a 'clear all filters' button feat: added a filters query feat: added a gql query for the transaction filters fix: fixed the transactions gql query so it haves the same options as the transaction filters feat: added a 'loading' feature to the search box (shown while loading the filters) fix: fetch transactions and filters separately in the transactions page fix: style export fix: packages fix: transaction conflicts
This commit is contained in:
parent
468f2cb28b
commit
852bf7b089
14 changed files with 1343 additions and 888 deletions
30
lib/new-admin/filters.js
Normal file
30
lib/new-admin/filters.js
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
const db = require('../db')
|
||||
const cashInTx = require('../cash-in/cash-in-tx')
|
||||
const { CASH_OUT_TRANSACTION_STATES } = require('../cash-out/cash-out-helper')
|
||||
|
||||
function transaction() {
|
||||
const sql = `select distinct * from (
|
||||
select 'type' as type, 'Cash In' as value union
|
||||
select 'type' as type, 'Cash Out' as value union
|
||||
select 'machine' as type, name as value from devices d inner join cash_in_txs t on d.device_id = t.device_id union
|
||||
select 'machine' as type, name as value from devices d inner join cash_out_txs t on d.device_id = t.device_id union
|
||||
select 'customer' as type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') as value
|
||||
from customers c inner join cash_in_txs t on c.id = t.customer_id
|
||||
where c.id_card_data::json->>'firstName' is not null or c.id_card_data::json->>'lastName' is not null union
|
||||
select 'customer' as type, concat(id_card_data::json->>'firstName', ' ', id_card_data::json->>'lastName') as value
|
||||
from customers c inner join cash_out_txs t on c.id = t.customer_id
|
||||
where c.id_card_data::json->>'firstName' is not null or c.id_card_data::json->>'lastName' is not null union
|
||||
select 'fiat' as type, fiat_code as value from cash_in_txs union
|
||||
select 'fiat' as type, fiat_code as value from cash_out_txs union
|
||||
select 'crypto' as type, crypto_code as value from cash_in_txs union
|
||||
select 'crypto' as type, crypto_code as value from cash_out_txs union
|
||||
select 'address' as type, to_address as value from cash_in_txs union
|
||||
select 'address' as type, to_address as value from cash_in_txs union
|
||||
select 'status' as type, ${cashInTx.TRANSACTION_STATES} as value from cash_in_txs union
|
||||
select 'status' as type, ${CASH_OUT_TRANSACTION_STATES} as value from cash_out_txs
|
||||
) f`
|
||||
|
||||
return db.any(sql)
|
||||
}
|
||||
|
||||
module.exports = { transaction }
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
const DataLoader = require('dataloader')
|
||||
const { parseAsync } = require('json2csv')
|
||||
|
||||
const filters = require('../../filters')
|
||||
const transactions = require('../../services/transactions')
|
||||
const anonymous = require('../../../constants').anonymousCustomer
|
||||
|
||||
|
|
@ -25,14 +26,16 @@ const resolvers = {
|
|||
isAnonymous: parent => (parent.customerId === anonymous.uuid)
|
||||
},
|
||||
Query: {
|
||||
transactions: (...[, { from, until, limit, offset, deviceId }]) =>
|
||||
transactions.batch(from, until, limit, offset, deviceId),
|
||||
transactionsCsv: (...[, { from, until, limit, offset }]) =>
|
||||
transactions.batch(from, until, limit, offset).then(data => parseAsync(data, { fields: txLogFields })),
|
||||
transactions: (...[, { from, until, limit, offset, deviceId, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status }]) =>
|
||||
transactions.batch(from, until, limit, offset, deviceId, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status),
|
||||
transactionsCsv: (...[, { from, until, limit, offset, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status }]) =>
|
||||
transactions.batch(from, until, limit, offset, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status)
|
||||
.then(data => parseAsync(data, {fields: tx_logFields})),
|
||||
transactionCsv: (...[, { id, txClass }]) =>
|
||||
transactions.getTx(id, txClass).then(parseAsync),
|
||||
txAssociatedDataCsv: (...[, { id, txClass }]) =>
|
||||
transactions.getTxAssociatedData(id, txClass).then(parseAsync)
|
||||
transactions.getTxAssociatedData(id, txClass).then(parseAsync),
|
||||
transactionFilters: () => filters.transaction()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,11 +45,17 @@ const typeDef = gql`
|
|||
discount: Int
|
||||
}
|
||||
|
||||
type Filter {
|
||||
type: String
|
||||
value: String
|
||||
}
|
||||
|
||||
type Query {
|
||||
transactions(from: Date, until: Date, limit: Int, offset: Int, deviceId: ID): [Transaction] @auth
|
||||
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int): String @auth
|
||||
transactions(from: Date, until: Date, limit: Int, offset: Int, deviceId: ID, txClass: String, machineName: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String): [Transaction] @auth
|
||||
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int, txClass: String, machineName: String, customerName: String, fiatCode: String, cryptoCode: String, toAddress: String, status: String): String @auth
|
||||
transactionCsv(id: ID, txClass: String): String @auth
|
||||
txAssociatedDataCsv(id: ID, txClass: String): String @auth
|
||||
transactionFilters: [Filter] @auth
|
||||
}
|
||||
`
|
||||
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ const db = require('../../db')
|
|||
const machineLoader = require('../../machine-loader')
|
||||
const tx = require('../../tx')
|
||||
const cashInTx = require('../../cash-in/cash-in-tx')
|
||||
const { REDEEMABLE_AGE } = require('../../cash-out/cash-out-helper')
|
||||
const { REDEEMABLE_AGE, CASH_OUT_TRANSACTION_STATES } = require('../../cash-out/cash-out-helper')
|
||||
|
||||
const NUM_RESULTS = 1000
|
||||
|
||||
|
|
@ -24,7 +24,20 @@ function addNames (txs) {
|
|||
|
||||
const camelize = _.mapKeys(_.camelCase)
|
||||
|
||||
function batch (from = new Date(0).toISOString(), until = new Date().toISOString(), limit = null, offset = 0, id = null) {
|
||||
function batch (
|
||||
from = new Date(0).toISOString(),
|
||||
until = new Date().toISOString(),
|
||||
limit = null,
|
||||
offset = 0,
|
||||
id = null,
|
||||
txClass = null,
|
||||
machineName = null,
|
||||
customerName = null,
|
||||
fiatCode = null,
|
||||
cryptoCode = null,
|
||||
toAddress = null,
|
||||
status = null
|
||||
) {
|
||||
const packager = _.flow(_.flatten, _.orderBy(_.property('created'), ['desc']), _.map(camelize), addNames)
|
||||
|
||||
const cashInSql = `select 'cashIn' as tx_class, txs.*,
|
||||
|
|
@ -32,15 +45,23 @@ function batch (from = new Date(0).toISOString(), until = new Date().toISOString
|
|||
c.id_card_data_number as customer_id_card_data_number,
|
||||
c.id_card_data_expiration as customer_id_card_data_expiration,
|
||||
c.id_card_data as customer_id_card_data,
|
||||
c.name as customer_name,
|
||||
concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') as customer_name,
|
||||
c.front_camera_path as customer_front_camera_path,
|
||||
c.id_card_photo_path as customer_id_card_photo_path,
|
||||
((not txs.send_confirmed) and (txs.created <= now() - interval $1)) as expired
|
||||
from cash_in_txs as txs
|
||||
from (select *, ${cashInTx.TRANSACTION_STATES} as txStatus from cash_in_txs) as txs
|
||||
left outer join customers c on txs.customer_id = c.id
|
||||
inner join devices d on txs.device_id = d.device_id
|
||||
where txs.created >= $2 and txs.created <= $3 ${
|
||||
id !== null ? `and txs.device_id = $6` : ``
|
||||
}
|
||||
id !== null ? `and txs.device_id = $6` : ``
|
||||
}
|
||||
and ($7 is null or $7 = 'Cash In')
|
||||
and ($8 is null or d.name = $8)
|
||||
and ($9 is null or concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') = $9)
|
||||
and ($10 is null or txs.fiat_code = $10)
|
||||
and ($11 is null or txs.crypto_code = $11)
|
||||
and ($12 is null or txs.to_address = $12)
|
||||
and ($13 is null or txs.txStatus = $13)
|
||||
order by created desc limit $4 offset $5`
|
||||
|
||||
const cashOutSql = `select 'cashOut' as tx_class,
|
||||
|
|
@ -50,22 +71,30 @@ function batch (from = new Date(0).toISOString(), until = new Date().toISOString
|
|||
c.id_card_data_number as customer_id_card_data_number,
|
||||
c.id_card_data_expiration as customer_id_card_data_expiration,
|
||||
c.id_card_data as customer_id_card_data,
|
||||
c.name as customer_name,
|
||||
concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') 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) >= $1 as expired
|
||||
from cash_out_txs txs
|
||||
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'
|
||||
left outer join customers c on txs.customer_id = c.id
|
||||
inner join devices d on txs.device_id = d.device_id
|
||||
where txs.created >= $2 and txs.created <= $3 ${
|
||||
id !== null ? `and txs.device_id = $6` : ``
|
||||
}
|
||||
id !== null ? `and txs.device_id = $6` : ``
|
||||
}
|
||||
and ($7 is null or $7 = 'Cash Out')
|
||||
and ($8 is null or d.name = $8)
|
||||
and ($9 is null or concat(c.id_card_data::json->>'firstName', ' ', c.id_card_data::json->>'lastName') = $9)
|
||||
and ($10 is null or txs.fiat_code = $10)
|
||||
and ($11 is null or txs.crypto_code = $11)
|
||||
and ($12 is null or txs.to_address = $12)
|
||||
and ($13 is null or txs.txStatus = $13)
|
||||
order by created desc limit $4 offset $5`
|
||||
|
||||
return Promise.all([
|
||||
db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id]),
|
||||
db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id])
|
||||
db.any(cashInSql, [cashInTx.PENDING_INTERVAL, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status]),
|
||||
db.any(cashOutSql, [REDEEMABLE_AGE, from, until, limit, offset, id, txClass, machineName, customerName, fiatCode, cryptoCode, toAddress, status])
|
||||
])
|
||||
.then(packager)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue