diff --git a/lib/compliance-triggers.js b/lib/compliance-triggers.js index 3cfd6a20..0f78c057 100644 --- a/lib/compliance-triggers.js +++ b/lib/compliance-triggers.js @@ -1,7 +1,7 @@ const _ = require('lodash/fp') function getBackwardsCompatibleTriggers (triggers) { - const filtered = _.filter(_.matches({ triggerType: 'amount', cashDirection: 'both' }))(triggers) + const filtered = _.filter(_.matches({ triggerType: 'txAmount', cashDirection: 'both' }))(triggers) const grouped = _.groupBy(_.prop('requirement'))(filtered) return _.mapValues(_.compose(_.get('threshold'), _.minBy('threshold')))(grouped) } diff --git a/lib/customers.js b/lib/customers.js index 126c848d..ff5e0f3c 100644 --- a/lib/customers.js +++ b/lib/customers.js @@ -454,7 +454,7 @@ function getCustomerById (id) { c.id_card_data, c.id_card_data_override, c.id_card_data_expiration, c.id_card_photo_path, c.id_card_photo_override, t.tx_class, t.fiat, t.fiat_code, t.created, row_number() over (partition by c.id order by t.created desc) as rn, - count(0) over (partition by c.id) as total_txs, + sum(case when t.id is not null then 1 else 0 end) over (partition by c.id) as total_txs, sum(t.fiat) over (partition by c.id) as total_spent from customers c left outer join ( select 'cashIn' as tx_class, id, fiat, fiat_code, created, customer_id diff --git a/new-lamassu-admin/package-lock.json b/new-lamassu-admin/package-lock.json index 6716ba43..0389e076 100644 --- a/new-lamassu-admin/package-lock.json +++ b/new-lamassu-admin/package-lock.json @@ -3828,6 +3828,12 @@ "@babel/types": "^7.3.0" } }, + "@types/color-name": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", + "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==", + "dev": true + }, "@types/eslint-visitor-keys": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/@types/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", @@ -6619,6 +6625,12 @@ "node-int64": "^0.4.0" } }, + "btoa": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/btoa/-/btoa-1.2.1.tgz", + "integrity": "sha512-SB4/MIGlsiVkMcHmT+pSmIPoNDoHg+7cMzmt3Uxt628MTz2487DKSqK/fuhFBrkuqrYv5UCEnACpF4dTFNKc/g==", + "dev": true + }, "buffer": { "version": "4.9.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.1.tgz", @@ -11101,6 +11113,15 @@ } } }, + "filelist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz", + "integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==", + "dev": true, + "requires": { + "minimatch": "^3.0.4" + } + }, "filesize": { "version": "3.6.1", "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz", @@ -12719,6 +12740,12 @@ "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE=", "dev": true }, + "is-docker": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.0.0.tgz", + "integrity": "sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==", + "dev": true + }, "is-dom": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz", @@ -13152,6 +13179,26 @@ "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.2.2.tgz", "integrity": "sha512-yynBb1g+RFUPY64fTrFv7nsjRrENBQJaX2UL+2Szc9REFrSNm1rpSXHGzhmAy7a9uv3vlvgBlXnf9RqmPH1/DA==" }, + "jake": { + "version": "10.8.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.8.2.tgz", + "integrity": "sha512-eLpKyrfG3mzvGE2Du8VoPbeSkRry093+tyNjdYaBbJS9v17knImYGNXQCUV0gLxQtF82m3E8iRb/wdSQZLoq7A==", + "dev": true, + "requires": { + "async": "0.9.x", + "chalk": "^2.4.2", + "filelist": "^1.0.1", + "minimatch": "^3.0.4" + }, + "dependencies": { + "async": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz", + "integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0=", + "dev": true + } + } + }, "jest": { "version": "24.9.0", "resolved": "https://registry.npmjs.org/jest/-/jest-24.9.0.tgz", @@ -23640,6 +23687,285 @@ "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", "dev": true }, + "source-map-explorer": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/source-map-explorer/-/source-map-explorer-2.4.2.tgz", + "integrity": "sha512-3ECQLffCFV8QgrTqcmddLkWL4/aQs6ljYfgWCLselo5QtizOfOeUCKnS4rFn7MIrdeZLM6TZrseOtsrWZhWKoQ==", + "dev": true, + "requires": { + "btoa": "^1.2.1", + "chalk": "^3.0.0", + "convert-source-map": "^1.7.0", + "ejs": "^3.0.2", + "escape-html": "^1.0.3", + "glob": "^7.1.6", + "gzip-size": "^5.1.1", + "lodash": "^4.17.15", + "open": "^7.0.3", + "source-map": "^0.7.3", + "temp": "^0.9.1", + "yargs": "^15.3.1" + }, + "dependencies": { + "ansi-regex": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", + "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", + "dev": true + }, + "ansi-styles": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", + "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", + "dev": true, + "requires": { + "@types/color-name": "^1.1.1", + "color-convert": "^2.0.1" + } + }, + "chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "convert-source-map": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", + "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.1" + } + }, + "ejs": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.3.tgz", + "integrity": "sha512-wmtrUGyfSC23GC/B1SMv2ogAUgbQEtDmTIhfqielrG5ExIM9TP4UoYdi90jLF1aTcsWCJNEO0UrgKzP0y3nTSg==", + "dev": true, + "requires": { + "jake": "^10.6.1" + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "dev": true, + "requires": { + "is-docker": "^2.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "open": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/open/-/open-7.0.4.tgz", + "integrity": "sha512-brSA+/yq+b08Hsr4c8fsEW2CRzk1BmfN3SAK/5VCHQ9bdoZJ4qa/+AfR0xHjlbbZUyPkUHs1b8x1RqdyZdkVqQ==", + "dev": true, + "requires": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "source-map": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz", + "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==", + "dev": true + }, + "string-width": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", + "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.0" + } + }, + "strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.0" + } + }, + "supports-color": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz", + "integrity": "sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "y18n": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz", + "integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==", + "dev": true + }, + "yargs": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz", + "integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==", + "dev": true, + "requires": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.1" + } + }, + "yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dev": true, + "requires": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + } + } + } + }, "source-map-resolve": { "version": "0.5.2", "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.2.tgz", @@ -24323,6 +24649,15 @@ } } }, + "temp": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.9.1.tgz", + "integrity": "sha512-WMuOgiua1xb5R56lE0eH6ivpVmg/lq2OHm4+LtT/xtEtPQ+sz6N3bBM6WZ5FvO1lO4IKIOb43qnhoc4qxP5OeA==", + "dev": true, + "requires": { + "rimraf": "~2.6.2" + } + }, "term-size": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/term-size/-/term-size-1.2.0.tgz", diff --git a/new-lamassu-admin/package.json b/new-lamassu-admin/package.json index 0ee85269..6528281c 100644 --- a/new-lamassu-admin/package.json +++ b/new-lamassu-admin/package.json @@ -61,7 +61,8 @@ "prettier": "1.19.1", "prettier-config-standard": "^1.0.1", "react-scripts": "^3.3.0", - "serve": "^11.2.0" + "serve": "^11.2.0", + "source-map-explorer": "^2.4.2" }, "husky": { "hooks": { @@ -78,6 +79,7 @@ "start": "react-scripts start", "fix": "eslint --fix --ext .js,.md,.json src/", "build": "react-scripts build", + "analyze": "source-map-explorer 'build/static/js/*.js'", "test": "react-scripts test", "eject": "react-scripts eject", "storybook": "start-storybook -p 9009 -s public", diff --git a/new-lamassu-admin/src/components/buttons/ActionButton.js b/new-lamassu-admin/src/components/buttons/ActionButton.js index d5229b01..264adac8 100644 --- a/new-lamassu-admin/src/components/buttons/ActionButton.js +++ b/new-lamassu-admin/src/components/buttons/ActionButton.js @@ -8,7 +8,7 @@ const useStyles = makeStyles(styles) const ActionButton = memo( ({ className, Icon, InverseIcon, color, children, ...props }) => { - const classes = useStyles({ color }) + const classes = useStyles() const classNames = { [classes.actionButton]: true, [classes.primary]: color === 'primary', diff --git a/new-lamassu-admin/src/components/layout/TitleSection.js b/new-lamassu-admin/src/components/layout/TitleSection.js index ce84cd4b..85031c06 100644 --- a/new-lamassu-admin/src/components/layout/TitleSection.js +++ b/new-lamassu-admin/src/components/layout/TitleSection.js @@ -1,9 +1,10 @@ -import { makeStyles } from '@material-ui/core' +import { makeStyles, Box } from '@material-ui/core' import classnames from 'classnames' import React from 'react' import ErrorMessage from 'src/components/ErrorMessage' import Title from 'src/components/Title' +import { Label1 } from 'src/components/typography' import styles from './TitleSection.styles' @@ -19,7 +20,14 @@ const TitleSection = ({ className, title, error, labels, children }) => { Failed to save )} -
{labels}
+ + {(labels ?? []).map(({ icon, label }, idx) => ( + +
{icon}
+ {label} +
+ ))} +
{children} ) diff --git a/new-lamassu-admin/src/components/layout/TitleSection.styles.js b/new-lamassu-admin/src/components/layout/TitleSection.styles.js index 397ece50..8df5d97e 100644 --- a/new-lamassu-admin/src/components/layout/TitleSection.styles.js +++ b/new-lamassu-admin/src/components/layout/TitleSection.styles.js @@ -1,5 +1,3 @@ -import { mainStyles } from 'src/pages/Transactions/Transactions.styles' - export default { titleWrapper: { display: 'flex', @@ -13,5 +11,10 @@ export default { error: { marginLeft: 12 }, - headerLabels: mainStyles.headerLabels + icon: { + marginRight: 6 + }, + label: { + marginRight: 24 + } } diff --git a/new-lamassu-admin/src/components/tables/DataTable.js b/new-lamassu-admin/src/components/tables/DataTable.js index 0da307e0..5563088d 100644 --- a/new-lamassu-admin/src/components/tables/DataTable.js +++ b/new-lamassu-admin/src/components/tables/DataTable.js @@ -46,7 +46,7 @@ const Row = ({ } return ( -
+
({ + marginBottom: 30, + minHeight: 200, width, flex: 1, display: 'flex', diff --git a/new-lamassu-admin/src/components/typography/index.js b/new-lamassu-admin/src/components/typography/index.js index b014928a..31648de4 100644 --- a/new-lamassu-admin/src/components/typography/index.js +++ b/new-lamassu-admin/src/components/typography/index.js @@ -53,7 +53,6 @@ function H3({ children, noMargin, className, ...props }) { function H4({ children, noMargin, className, ...props }) { const classes = useStyles() - console.log(className) const classNames = { [classes.h4]: true, [classes.noMargin]: noMargin, diff --git a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js index fa7973b5..0ddb2874 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomerProfile.js +++ b/new-lamassu-admin/src/pages/Customers/CustomerProfile.js @@ -112,9 +112,9 @@ const CustomerProfile = memo(() => { }) const customerData = R.path(['customer'])(customerResponse) ?? [] - - const transactionsData = R.sortWith([R.descend('created')])( - R.path(['transactions'])(customerData) ?? [] + const rawTransactions = R.path(['transactions'])(customerData) ?? [] + const sortedTransactions = R.sort(R.descend(R.prop('cryptoAtoms')))( + rawTransactions ) const blocked = @@ -133,7 +133,7 @@ const CustomerProfile = memo(() => { Customers - Rafael{R.path(['name'])(customerData)} + {R.path(['name'])(customerData) ?? R.path(['phone'])(customerData)}
@@ -171,7 +171,7 @@ const CustomerProfile = memo(() => { />
- + ) }) diff --git a/new-lamassu-admin/src/pages/Customers/CustomersList.js b/new-lamassu-admin/src/pages/Customers/CustomersList.js index fd59f1d5..eb2157e1 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomersList.js +++ b/new-lamassu-admin/src/pages/Customers/CustomersList.js @@ -4,10 +4,11 @@ import moment from 'moment' import * as R from 'ramda' import React from 'react' -import Title from 'src/components/Title' +import TitleSection from 'src/components/layout/TitleSection' import DataTable from 'src/components/tables/DataTable' import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' +import { ifNotNull } from 'src/utils/nullCheck' import styles from './CustomersList.styles' @@ -17,16 +18,16 @@ const CustomersList = ({ data, onClick }) => { const classes = useStyles() const elements = [ - { - header: 'Name', - width: 277, - view: R.path(['name']) - }, { header: 'Phone', width: 186, view: it => parsePhoneNumberFromString(it.phone).formatInternational() }, + { + header: 'Name', + width: 277, + view: R.path(['name']) + }, { header: 'Total TXs', width: 154, @@ -37,47 +38,43 @@ const CustomersList = ({ data, onClick }) => { header: 'Total spent', width: 188, textAlign: 'right', - view: it => `${Number.parseFloat(it.totalSpent)} ${it.lastTxFiatCode}` + view: it => + `${Number.parseFloat(it.totalSpent)} ${it.lastTxFiatCode ?? ''}` }, { header: 'Last active', width: 197, - view: it => moment.utc(it.lastActive).format('YYYY-MM-D') + view: it => + ifNotNull(it.lastActive, moment.utc(it.lastActive).format('YYYY-MM-D')) }, { header: 'Last transaction', width: 198, textAlign: 'right', - view: it => ( - <> - {`${Number.parseFloat(it.lastTxFiat)} ${it.lastTxFiatCode}`} - {it.lastTxClass === 'cashOut' ? ( - - ) : ( - - )} - - ) + view: it => { + const hasLastTx = !R.isNil(it.lastTxFiatCode) + const LastTxIcon = it.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon + const lastIcon = + return ( + <> + {hasLastTx && + `${parseFloat(it.lastTxFiat)} ${it.lastTxFiatCode ?? ''}`} + {hasLastTx && lastIcon} + + ) + } } ] return ( <> -
-
- Customers -
-
-
- - Cash-out -
-
- - Cash-in -
-
-
+ }, + { label: 'Cash-out', icon: } + ]} + /> ) diff --git a/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js b/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js index 45919e70..ee7a51fd 100644 --- a/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js +++ b/new-lamassu-admin/src/pages/Customers/CustomersList.styles.js @@ -75,47 +75,7 @@ export default { alignItems: 'center', justifyContent: 'space-between' }, - idDataCard: { - width: 544, - height: 240 - }, - phoneCard: { - width: 253, - height: 240 - }, - idCardPhotoCard: { - width: 378, - height: 240, - margin: [[32, 0, 0, 0]] - }, - field: { - position: 'relative', - width: 144, - height: 46, - padding: [[0, 4, 4, 0]], - display: 'flex', - flexDirection: 'column', - '& > p:first-child': { - height: 16, - lineHeight: '16px', - paddingLeft: 3, - margin: [[0, 0, 5, 0]] - }, - '& > p:last-child': { - margin: 0, - paddingLeft: 4 - } - }, customerName: { marginBottom: 32 - }, - fieldDisplay: { - whiteSpace: 'nowrap', - overflow: 'hidden', - textOverflow: 'ellipsis' - }, - idCardPhoto: { - maxWidth: 171, - maxHeight: 97 } } diff --git a/new-lamassu-admin/src/pages/Customers/components/CustomerDetails.js b/new-lamassu-admin/src/pages/Customers/components/CustomerDetails.js index 4f704fe7..cbcc95da 100644 --- a/new-lamassu-admin/src/pages/Customers/components/CustomerDetails.js +++ b/new-lamassu-admin/src/pages/Customers/components/CustomerDetails.js @@ -3,19 +3,35 @@ import moment from 'moment' import * as R from 'ramda' import React, { memo } from 'react' -import { H2 } from 'src/components/typography' +import { H2, Label1, P } from 'src/components/typography' import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' - -import { ifNotNull } from '../../../utils/nullCheck' -import styles from '../CustomersList.styles' +import { comet } from 'src/styling/variables' +import { ifNotNull } from 'src/utils/nullCheck' import FrontCameraPhoto from './FrontCameraPhoto' +const styles = { + icon: { + marginRight: 11 + }, + name: { + marginTop: 6 + }, + value: { + height: 16 + }, + label: { + marginBottom: 4, + color: comet + } +} + const useStyles = makeStyles(styles) const CustomerDetails = memo(({ customer }) => { const classes = useStyles() + const LastTxIcon = customer.lastTxClass === 'cashOut' ? TxOutIcon : TxInIcon const elements = [ { @@ -48,13 +64,9 @@ const CustomerDetails = memo(({ customer }) => { value: ifNotNull( customer.lastTxFiat, <> + {`${Number.parseFloat(customer.lastTxFiat)} ${customer.lastTxFiatCode}`} - {customer.lastTxClass === 'cashOut' ? ( - - ) : ( - - )} ) } @@ -65,25 +77,35 @@ const CustomerDetails = memo(({ customer }) => { -
- -

Rafael{R.path(['name'])(customer)}

-
- + +
+

+ {R.path(['name'])(customer) ?? R.path(['phone'])(customer)} +

+
+ {elements.map(({ size, header }, idx) => ( -
+ {header} -
+ ))}
{elements.map(({ size, value }, idx) => ( -
+

{value} -

+

))}
-
+ ) }) diff --git a/new-lamassu-admin/src/pages/Customers/components/Field.js b/new-lamassu-admin/src/pages/Customers/components/Field.js index 42762e12..a1b904a1 100644 --- a/new-lamassu-admin/src/pages/Customers/components/Field.js +++ b/new-lamassu-admin/src/pages/Customers/components/Field.js @@ -1,19 +1,35 @@ import { makeStyles } from '@material-ui/core/styles' +import classnames from 'classnames' import React, { memo } from 'react' import { Info3, Label1 } from 'src/components/typography' +import { comet } from 'src/styling/variables' -import mainStyles from '../CustomersList.styles' +const useStyles = makeStyles({ + field: { + width: 144, + height: 46 + }, + label: { + color: comet, + margin: [[0, 3]] + }, + value: { + whiteSpace: 'nowrap', + overflow: 'hidden', + textOverflow: 'ellipsis', + margin: 0, + paddingLeft: 4 + } +}) -const useStyles = makeStyles(mainStyles) - -const Field = memo(({ label, display }) => { +const Field = memo(({ label, display, className }) => { const classes = useStyles() return ( -
- {label} - {display} +
+ {label} + {display}
) }) diff --git a/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.js b/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.js index 9ace389a..dfae0408 100644 --- a/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.js +++ b/new-lamassu-admin/src/pages/Customers/components/IdCardPhotoCard.js @@ -1,5 +1,5 @@ -import { makeStyles } from '@material-ui/core/styles' -import moment from 'moment' +import { makeStyles, Box } from '@material-ui/core' +// import moment from 'moment' import * as R from 'ramda' import React, { memo } from 'react' @@ -11,11 +11,21 @@ import { import { ReactComponent as CrossedCameraIcon } from 'src/styling/icons/ID/photo/crossed-camera.svg' import { URI } from 'src/utils/apollo' -import mainStyles from '../CustomersList.styles' +// import Field from './Field' -import Field from './Field' - -const useStyles = makeStyles(mainStyles) +const useStyles = makeStyles({ + idCardPhotoCard: { + width: 325, + height: 240, + margin: [[32, 0, 0, 0]] + }, + idCardPhoto: { + maxHeight: 130 + }, + field: { + marginLeft: 14 + } +}) const IdCardPhotoCard = memo(({ customerData, updateCustomer }) => { const classes = useStyles() @@ -29,7 +39,7 @@ const IdCardPhotoCard = memo(({ customerData, updateCustomer }) => { updateCustomer({ idCardPhotoOverride: OVERRIDE_AUTHORIZED }) } reject={() => updateCustomer({ idCardPhotoOverride: OVERRIDE_REJECTED })}> -
+ {customerData.idCardPhotoPath ? ( { ) : ( )} - -
+ /> */} + ) }) diff --git a/new-lamassu-admin/src/pages/Customers/components/IdDataCard.js b/new-lamassu-admin/src/pages/Customers/components/IdDataCard.js index 09db7b76..2a517ef6 100644 --- a/new-lamassu-admin/src/pages/Customers/components/IdDataCard.js +++ b/new-lamassu-admin/src/pages/Customers/components/IdDataCard.js @@ -1,4 +1,4 @@ -import { makeStyles } from '@material-ui/core/styles' +import { makeStyles, Box } from '@material-ui/core' import moment from 'moment' import * as R from 'ramda' import React, { memo } from 'react' @@ -8,16 +8,44 @@ import { OVERRIDE_AUTHORIZED, OVERRIDE_REJECTED } from 'src/pages/Customers/components/propertyCard' - -import mainStyles from '../CustomersList.styles' +import { ifNotNull } from 'src/utils/nullCheck' import Field from './Field' -const useStyles = makeStyles(mainStyles) +const useStyles = makeStyles({ + idDataCard: { + width: 550, + height: 240 + }, + column: { + marginBottom: 7 + } +}) const IdDataCard = memo(({ customerData, updateCustomer }) => { const classes = useStyles() + const idData = R.path(['idCardData'])(customerData) + + const name = R.path(['firstName'])(idData) ?? '' + const lastName = R.path(['lastName'])(idData) ?? '' + + const gender = R.path(['gender'])(idData) + const idNumber = R.path(['documentNumber'])(idData) + const country = R.path(['country'])(idData) + + const rawExpirationDate = R.path(['expirationDate'])(idData) + const expirationDate = ifNotNull( + rawExpirationDate, + moment.utc(rawExpirationDate).format('YYYY-MM-D') + ) + + const rawDob = R.path(['dateOfBirth'])(idData) + const age = ifNotNull( + rawDob, + moment.utc().diff(moment.utc(rawDob).format('YYYY-MM-D'), 'years') + ) + return ( { updateCustomer({ idCardDataOverride: OVERRIDE_AUTHORIZED }) } reject={() => updateCustomer({ idCardDataOverride: OVERRIDE_REJECTED })}> -
-
- - -
-
- - -
-
- - -
+
+ + + + + + + + + +
) diff --git a/new-lamassu-admin/src/pages/Customers/components/PhoneCard.js b/new-lamassu-admin/src/pages/Customers/components/PhoneCard.js index 7d1b1c2c..c5b15a46 100644 --- a/new-lamassu-admin/src/pages/Customers/components/PhoneCard.js +++ b/new-lamassu-admin/src/pages/Customers/components/PhoneCard.js @@ -9,11 +9,14 @@ import { OVERRIDE_REJECTED } from 'src/pages/Customers/components/propertyCard' -import mainStyles from '../CustomersList.styles' - import Field from './Field' -const useStyles = makeStyles(mainStyles) +const useStyles = makeStyles({ + phoneCard: { + width: 300, + height: 240 + } +}) const PhoneCard = memo(({ customerData, updateCustomer }) => { const classes = useStyles() diff --git a/new-lamassu-admin/src/pages/Customers/components/TransactionsList.js b/new-lamassu-admin/src/pages/Customers/components/TransactionsList.js index cfc237ee..7f87c62a 100644 --- a/new-lamassu-admin/src/pages/Customers/components/TransactionsList.js +++ b/new-lamassu-admin/src/pages/Customers/components/TransactionsList.js @@ -1,6 +1,7 @@ import { makeStyles } from '@material-ui/core/styles' import BigNumber from 'bignumber.js' import moment from 'moment' +import * as R from 'ramda' import React from 'react' import DataTable from 'src/components/tables/DataTable' @@ -16,6 +17,7 @@ const useStyles = makeStyles(mainStyles) const TransactionsList = ({ data }) => { const classes = useStyles() + const hasData = !(R.isEmpty(data) || R.isNil(data)) const elements = [ { @@ -77,10 +79,14 @@ const TransactionsList = ({ data }) => { <>
-

All transactions from this customer

+

+ {hasData + ? 'All transactions from this customer' + : 'No transactions so far'} +

- + {hasData && } ) } diff --git a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.js b/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.js index 353d2d72..50f3da68 100644 --- a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.js +++ b/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.js @@ -3,12 +3,12 @@ import { makeStyles } from '@material-ui/core/styles' import classnames from 'classnames' import React, { memo } from 'react' -import { ActionButton } from 'src/components/buttons' +// import { ActionButton } from 'src/components/buttons' import { H3 } from 'src/components/typography' -import { ReactComponent as AuthorizeReversedIcon } from 'src/styling/icons/button/authorize/white.svg' -import { ReactComponent as AuthorizeIcon } from 'src/styling/icons/button/authorize/zodiac.svg' -import { ReactComponent as RejectReversedIcon } from 'src/styling/icons/button/cancel/white.svg' -import { ReactComponent as RejectIcon } from 'src/styling/icons/button/cancel/zodiac.svg' +// import { ReactComponent as AuthorizeReversedIcon } from 'src/styling/icons/button/authorize/white.svg' +// import { ReactComponent as AuthorizeIcon } from 'src/styling/icons/button/authorize/zodiac.svg' +// import { ReactComponent as RejectReversedIcon } from 'src/styling/icons/button/cancel/white.svg' +// import { ReactComponent as RejectIcon } from 'src/styling/icons/button/cancel/zodiac.svg' import { propertyCardStyles } from './PropertyCard.styles' @@ -24,46 +24,48 @@ const PropertyCard = memo( const propertyCardClassNames = { [classes.propertyCard]: true, - [classes.propertyCardPending]: state === OVERRIDE_PENDING, - [classes.propertyCardRejected]: state === OVERRIDE_REJECTED, - [classes.propertyCardAccepted]: state === OVERRIDE_AUTHORIZED + [classes.propertyCardPending]: true + // [classes.propertyCardPending]: state === OVERRIDE_PENDING + // [classes.propertyCardRejected]: state === OVERRIDE_REJECTED, + // [classes.propertyCardAccepted]: state === OVERRIDE_AUTHORIZED } - const label1ClassNames = { - [classes.label1]: true, - [classes.label1Pending]: state === OVERRIDE_PENDING, - [classes.label1Rejected]: state === OVERRIDE_REJECTED, - [classes.label1Accepted]: state === OVERRIDE_AUTHORIZED - } + // const label1ClassNames = { + // [classes.label1]: true, + // [classes.label1Pending]: true + // [classes.label1Pending]: state === OVERRIDE_PENDING + // [classes.label1Rejected]: state === OVERRIDE_REJECTED, + // [classes.label1Accepted]: state === OVERRIDE_AUTHORIZED + // } - const AuthorizeButton = () => ( - authorize()}> - Authorize - - ) + // const AuthorizeButton = () => ( + // authorize()}> + // Authorize + // + // ) - const RejectButton = () => ( - reject()}> - Reject - - ) + // const RejectButton = () => ( + // reject()}> + // Reject + // + // ) - const authorizedAsString = - state === OVERRIDE_PENDING - ? 'Pending' - : state === OVERRIDE_REJECTED - ? 'Rejected' - : 'Accepted' + // const authorizedAsString = + // state === OVERRIDE_PENDING + // ? 'Pending' + // : state === OVERRIDE_REJECTED + // ? 'Rejected' + // : 'Accepted' return (

{title}

-
+ {/*
{authorizedAsString} -
+
*/}
{children} -
+ {/* V2 */} + {/*
{state !== OVERRIDE_AUTHORIZED && AuthorizeButton()} {state !== OVERRIDE_REJECTED && RejectButton()} -
+
*/}
) } diff --git a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js b/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js index e46c12e2..3fb5ff0c 100644 --- a/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js +++ b/new-lamassu-admin/src/pages/Customers/components/propertyCard/PropertyCard.styles.js @@ -48,9 +48,10 @@ const propertyCardStyles = { marginLeft: 12 }, cardProperties: { + display: 'flex', borderRadius: 8, width: '100%', - height: 'calc(100% - 100px)', + height: 'calc(100% - 75px)', padding: [[20]], boxSizing: 'border-box', boxShadow: '0 0 8px 0 rgba(0, 0, 0, 0.04)', diff --git a/new-lamassu-admin/src/styling/icons/button/authorize/white.svg b/new-lamassu-admin/src/styling/icons/button/authorize/white.svg index fe9d27bb..54a67625 100644 --- a/new-lamassu-admin/src/styling/icons/button/authorize/white.svg +++ b/new-lamassu-admin/src/styling/icons/button/authorize/white.svg @@ -1,9 +1,9 @@ - + Created with Sketch. - + diff --git a/new-lamassu-admin/src/styling/icons/button/authorize/zodiac.svg b/new-lamassu-admin/src/styling/icons/button/authorize/zodiac.svg index 85bb8008..805dd29d 100644 --- a/new-lamassu-admin/src/styling/icons/button/authorize/zodiac.svg +++ b/new-lamassu-admin/src/styling/icons/button/authorize/zodiac.svg @@ -1,10 +1,10 @@ - + Created with Sketch. - + diff --git a/new-lamassu-admin/src/styling/icons/button/block/white.svg b/new-lamassu-admin/src/styling/icons/button/block/white.svg index 704d6260..71606bc4 100644 --- a/new-lamassu-admin/src/styling/icons/button/block/white.svg +++ b/new-lamassu-admin/src/styling/icons/button/block/white.svg @@ -1,11 +1,11 @@ - + Created with Sketch. - - + + \ No newline at end of file diff --git a/new-lamassu-admin/src/styling/icons/button/block/zodiac.svg b/new-lamassu-admin/src/styling/icons/button/block/zodiac.svg index 111ee4c4..0d2abcb7 100644 --- a/new-lamassu-admin/src/styling/icons/button/block/zodiac.svg +++ b/new-lamassu-admin/src/styling/icons/button/block/zodiac.svg @@ -1,11 +1,11 @@ - + Created with Sketch. - - + + \ No newline at end of file diff --git a/new-lamassu-admin/src/utils/nullCheck.js b/new-lamassu-admin/src/utils/nullCheck.js index f0780779..a663f023 100644 --- a/new-lamassu-admin/src/utils/nullCheck.js +++ b/new-lamassu-admin/src/utils/nullCheck.js @@ -1,5 +1,7 @@ +import * as R from 'ramda' + const ifNotNull = (value, valueIfNotNull) => { - return value === null ? '' : valueIfNotNull + return R.isNil(value) ? '' : valueIfNotNull } export { ifNotNull } diff --git a/new-lamassu-admin/todo.md b/new-lamassu-admin/todo.md index 1cb62214..a031c8d9 100644 --- a/new-lamassu-admin/todo.md +++ b/new-lamassu-admin/todo.md @@ -4,107 +4,84 @@ Main menu: Overall: - caching the page -- coin dropdown should show all coins - validation is bad rn, negatives being allowed -- input number should only allow numbers - right aligned numbers on all tables - locale based mil separators 1.000 1,000 Cashboxes: -- right aligned number (SAME EVERYWHERE) +- right aligned number + +Locale: +- Only allow one override per machine + +Notifications: +- one of the crypto balance alerts has to be optional because of migration UI: -- replace all the tooltips with new component - tooltip like components should close on esc - saving should be a one time thing. disable buttons so user doesnt spam it - transitions - error handling -- should all (machines/coins/...) be a option on some overrides? - select components - talk with nunu + neal: Hover css for edit buttons + first first cancel later -- filter countries by code as well, US should go to United States -- filter prioritize the start of words(not alphabetically) -- dropdown should have everythihg selected on the top - disable edit on non-everrides => overrides -- remove the broswer default tooltip - +- splash screens and home +- maybe a indication that there's more to search on dropdown +- required signifier on form fields - (required) or * +- USD should show as a suffix (validate all screens) +- stop line breaking on multi select +- input width should be enough to hold values without cutting text +- font sizes could be better +- min height in virtualized table (rows get hidden if not enough height in browser) Machine status: -- legend colors are different from the spec -- action Error/Success indication -- load machine model from l-m -- align popup title with content -- talk with neal to see if the actions should be consistent - font-size of the 'write to confirm' -- reboot icon cut off -- ask neal for the support articles -- stop line breaking on multi select - -Commissions: -- overrides can be tighter. Hide coins already used by the same machine on another line. -- no negative values -- autoselect not getting errored when tabbed out - -Operator Info: -- That should be paginated with routes! - -Terms and Conditions: -- default values are not working properly - -Contact information: -- When the fields are empty, should there be a warning somewhere? Or maybe we could create an exception that if the fields are empty they shouldn't show up -- l-m uses name, email, phone. The rest is just used for the receipt printing for now - -CoinATMRadar: -- We now have photo, should we relay that info? - -Sms/email: -- There's no place to pick a third party provider anymore. (sms.js, email.js) - -Notifications: -- cash out 500 notes max top 500 max bottom -- crypto balance alerts input width (CHECK FOR ALL) - -Locale: -- limit languages -- search crypto per name as well -- show full name on the dropdown - -Machine name: -- Previously we were grabbing that from the config, but since new admin still cant change the name i`m now grabbing it from the db. Possible issues if users change the machine name from the initial one. Investivate alternatives. Migrate: - Need to write config migration. - Rewrite config validate - remove apply defaults -Compliance: -- Reject Address Reuse missing -- Currently admin only handles { type: 'volume', direction: 'both' } -- Sanctions should have more care in customers.js, currently just looking if is active as if old config - -Customers: -- Should add id and make it main part of the table? Name is not common at all - -Logs: -- the new functionality that saves server logs to a db breaks initial install chicken-egg with db-logger - -Downloading (logs and tx): -- They are always downloading from the local data, should be from server - Cash out: -- On off should have a fixed sized so things dont move a lot -- separate text from the first screen -- auto focus on fields after clicking next -- improve spacing around paragraphs -- button is on a wrong place on steps 2 and 3 -- make it a dropdown based on the machine denomimnations settings - ask nuno about zero conf limit -- USD should show as a suffix (validate all screens) -- Splash image for wizard Server: - Takes too long to load. Investigate Review slow internet loading: -- Table should be loaded \ No newline at end of file +- Table should be loaded (we want to load the table with no data) + +3rd party services: +- remove strike +- ask neal anyone uses itbit + +Wallet: +- ask neal and nuno how to handle unconfigured third party services on the table edit + +Operator Info: +- That should be paginated with routes! + +CoinATMRadar: +- relay facephoto info +- we should show the highest amount that requires a requirement + +Customers: +- add status +- cash-in cash-out are reversed + +Sms/email: +- There's no place to pick a third party provider anymore. (sms.js, email.js) neal + nuno + +Machine name: +- update the db with whatever name is on the old config +- where to change name of the mahcines NUNO + NEAL + +Compliance: +- Reject Address Reuse missing (MAKE BLACKLIST SCREEN AND PUT IT THERE) +- Currently admin only handles { type: 'amount', direction: 'both' } +- Sanctions should have more care in customers.js, currently just looking if is active as if old config + + +Ideas + - Transactions could have a link to the customer + - Transactions table on customer should have a link to "transactions"