feat: change custom SMS instances to SMS notices and all its interfaces
This commit is contained in:
parent
04f4891291
commit
0d5f5167ef
12 changed files with 153 additions and 149 deletions
|
|
@ -20,6 +20,7 @@ const MANUAL = 'manual'
|
|||
|
||||
const CASH_OUT_DISPENSE_READY = 'cash_out_dispense_ready'
|
||||
const CONFIRMATION_CODE = 'sms_code'
|
||||
const RECEIPT = 'sms_receipt'
|
||||
|
||||
const WALLET_SCORE_THRESHOLD = 9
|
||||
|
||||
|
|
@ -37,5 +38,6 @@ module.exports = {
|
|||
CONFIRMATION_CODE,
|
||||
CASH_OUT_MINIMUM_AMOUNT_OF_CASSETTES,
|
||||
CASH_OUT_MAXIMUM_AMOUNT_OF_CASSETTES,
|
||||
WALLET_SCORE_THRESHOLD
|
||||
WALLET_SCORE_THRESHOLD,
|
||||
RECEIPT
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
const _ = require('lodash/fp')
|
||||
const uuid = require('uuid')
|
||||
const db = require('./db')
|
||||
|
||||
const getCustomMessages = () => {
|
||||
const sql = `SELECT * FROM custom_messages ORDER BY created`
|
||||
return db.any(sql).then(res => _.map(
|
||||
it => ({
|
||||
id: it.id,
|
||||
event: _.camelCase(it.event),
|
||||
message: it.message
|
||||
}), res))
|
||||
}
|
||||
|
||||
const createCustomMessage = (event, message) => {
|
||||
const sql = `INSERT INTO custom_messages (id, event, message) VALUES ($1, $2, $3)`
|
||||
return db.none(sql, [uuid.v4(), _.snakeCase(event), message])
|
||||
}
|
||||
|
||||
const editCustomMessage = (id, event, message) => {
|
||||
const sql = `UPDATE custom_messages SET event=$2, message=$3 WHERE id=$1`
|
||||
return db.none(sql, [id, _.snakeCase(event), message])
|
||||
}
|
||||
|
||||
const deleteCustomMessage = id => {
|
||||
const sql = `DELETE FROM custom_messages WHERE id=$1`
|
||||
return db.none(sql, [id])
|
||||
}
|
||||
|
||||
const getCustomMessage = event => {
|
||||
const sql = `SELECT * FROM custom_messages WHERE event=$1 LIMIT 1`
|
||||
return db.oneOrNone(sql, [event])
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getCustomMessages,
|
||||
createCustomMessage,
|
||||
editCustomMessage,
|
||||
deleteCustomMessage,
|
||||
getCustomMessage
|
||||
}
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
const customSms = require('../../../custom-sms')
|
||||
const customSms = require('../../../sms-notices')
|
||||
|
||||
const resolvers = {
|
||||
Query: {
|
||||
customMessages: () => customSms.getCustomMessages()
|
||||
SMSNotices: () => customSms.getSMSNotices()
|
||||
},
|
||||
Mutation: {
|
||||
createCustomMessage: (...[, { event, message }]) => customSms.createCustomMessage(event, message),
|
||||
editCustomMessage: (...[, { id, event, message }]) => customSms.editCustomMessage(id, event, message),
|
||||
deleteCustomMessage: (...[, { id }]) => customSms.deleteCustomMessage(id)
|
||||
editSMSNotice: (...[, { id, event, message }]) => customSms.editSMSNotice(id, event, message),
|
||||
enableSMSNotice: (...[, { id }]) => customSms.enableSMSNotice(id),
|
||||
disableSMSNotice: (...[, { id }]) => customSms.disableSMSNotice(id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,25 +1,29 @@
|
|||
const { gql } = require('apollo-server-express')
|
||||
|
||||
const typeDef = gql`
|
||||
type CustomMessage {
|
||||
type SMSNotice {
|
||||
id: ID!
|
||||
event: CustomMessageEvent!
|
||||
event: SMSNoticeEvent!
|
||||
message: String!
|
||||
messageName: String!
|
||||
enabled: Boolean!
|
||||
allowToggle: Boolean!
|
||||
}
|
||||
|
||||
enum CustomMessageEvent {
|
||||
enum SMSNoticeEvent {
|
||||
smsCode
|
||||
cashOutDispenseReady
|
||||
smsReceipt
|
||||
}
|
||||
|
||||
type Query {
|
||||
customMessages: [CustomMessage] @auth
|
||||
SMSNotices: [SMSNotice] @auth
|
||||
}
|
||||
|
||||
type Mutation {
|
||||
createCustomMessage(event: CustomMessageEvent!, message: String!): CustomMessage @auth
|
||||
editCustomMessage(id: ID!, event: CustomMessageEvent!, message: String!): CustomMessage @auth
|
||||
deleteCustomMessage(id: ID!): CustomMessage @auth
|
||||
editSMSNotice(id: ID!, event: SMSNoticeEvent!, message: String!): SMSNotice @auth
|
||||
enableSMSNotice(id: ID!): SMSNotice @auth
|
||||
disableSMSNotice(id: ID!): SMSNotice @auth
|
||||
}
|
||||
`
|
||||
|
||||
|
|
|
|||
56
lib/sms-notices.js
Normal file
56
lib/sms-notices.js
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
const _ = require('lodash/fp')
|
||||
const uuid = require('uuid')
|
||||
const db = require('./db')
|
||||
|
||||
const getSMSNotices = () => {
|
||||
const sql = `SELECT * FROM sms_notices ORDER BY created`
|
||||
return db.any(sql).then(res => _.map(
|
||||
it => ({
|
||||
id: it.id,
|
||||
event: _.camelCase(it.event),
|
||||
message: it.message,
|
||||
messageName: it.message_name,
|
||||
enabled: it.enabled,
|
||||
allowToggle: it.allow_toggle
|
||||
}), res))
|
||||
}
|
||||
|
||||
const createSMSNotice = (event, messageName, message, enabled, allowToggle) => {
|
||||
const sql = `INSERT INTO sms_notices (id, event, message_name, message${enabled ? `, enabled`: ``}${allowToggle ? `, allowToggle`: ``}) VALUES ($1, $2, $3, $4${enabled ? `, $5`: ``}${allowToggle ? `, $6`: ``})`
|
||||
return db.none(sql, [uuid.v4(), _.snakeCase(event), messageName, message, enabled, allowToggle])
|
||||
}
|
||||
|
||||
const editSMSNotice = (id, event, message) => {
|
||||
const sql = `UPDATE sms_notices SET event=$2, message=$3 WHERE id=$1`
|
||||
return db.none(sql, [id, _.snakeCase(event), message])
|
||||
}
|
||||
|
||||
const deleteSMSNotice = id => {
|
||||
const sql = `DELETE FROM sms_notices WHERE id=$1`
|
||||
return db.none(sql, [id])
|
||||
}
|
||||
|
||||
const getSMSNotice = event => {
|
||||
const sql = `SELECT * FROM sms_notices WHERE event=$1 LIMIT 1`
|
||||
return db.oneOrNone(sql, [event])
|
||||
}
|
||||
|
||||
const enableSMSNotice = id => {
|
||||
const sql = `UPDATE sms_notices SET enabled = true WHERE id=$1 LIMIT 1`
|
||||
return db.oneOrNone(sql, [id])
|
||||
}
|
||||
|
||||
const disableSMSNotice = id => {
|
||||
const sql = `UPDATE sms_notices SET enabled = false WHERE id=$1 LIMIT 1`
|
||||
return db.oneOrNone(sql, [id])
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getSMSNotices,
|
||||
createSMSNotice,
|
||||
editSMSNotice,
|
||||
deleteSMSNotice,
|
||||
getSMSNotice,
|
||||
enableSMSNotice,
|
||||
disableSMSNotice
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ const argv = require('minimist')(process.argv.slice(2))
|
|||
const { utils: coinUtils } = require('lamassu-coins')
|
||||
const _ = require('lodash/fp')
|
||||
|
||||
const customSms = require('./custom-sms')
|
||||
const customSms = require('./sms-notices')
|
||||
|
||||
const getDefaultMessageContent = content => ({
|
||||
smsCode: `Your cryptomat code: ${content.code}`,
|
||||
|
|
|
|||
21
migrations/1643996603839-change-custom-sms-to-notices.js
Normal file
21
migrations/1643996603839-change-custom-sms-to-notices.js
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
var db = require('./db')
|
||||
var smsNotices = require('../lib/sms-notices')
|
||||
|
||||
exports.up = function (next) {
|
||||
var sql = [
|
||||
`ALTER TABLE custom_messages RENAME TO sms_notices`,
|
||||
`ALTER TYPE custom_message_event RENAME TO sms_notice_event`,
|
||||
`ALTER TYPE sms_notice_event ADD VALUE 'sms_receipt'`,
|
||||
`ALTER TABLE sms_notices ADD COLUMN message_name TEXT UNIQUE NOT NULL`,
|
||||
`ALTER TABLE sms_notices ADD COLUMN enabled BOOLEAN NOT NULL DEFAULT true`
|
||||
`ALTER TABLE sms_notices ADD COLUMN allow_toggle BOOLEAN NOT NULL DEFAULT true`
|
||||
]
|
||||
|
||||
db.multi(sql, next)
|
||||
.then(() => smsNotices.createSMSNotice('sms_code', 'SMS confirmation code', 'Your cryptomat code: #code', true, false))
|
||||
.then(() => smsNotices.createSMSNotice('cash_out_dispense_ready', 'Cash is ready', 'Your cash is waiting! Go to the Cryptomat and press Redeem within 24 hours. [#timestamp]', true, false))
|
||||
}
|
||||
|
||||
exports.down = function (next) {
|
||||
next()
|
||||
}
|
||||
|
|
@ -1,15 +1,15 @@
|
|||
import { makeStyles } from '@material-ui/core'
|
||||
import { Form, Formik, Field } from 'formik'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
import React from 'react'
|
||||
import * as Yup from 'yup'
|
||||
|
||||
import ErrorMessage from 'src/components/ErrorMessage'
|
||||
import Modal from 'src/components/Modal'
|
||||
import { Button } from 'src/components/buttons'
|
||||
import { Autocomplete, TextInput } from 'src/components/inputs/formik'
|
||||
import { TextInput } from 'src/components/inputs/formik'
|
||||
|
||||
import styles from './CustomSMS.styles'
|
||||
import styles from './SMSNotices.styles'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
|
|
@ -58,18 +58,9 @@ const prefill = {
|
|||
}
|
||||
}
|
||||
|
||||
const CustomSMSModal = ({
|
||||
showModal,
|
||||
onClose,
|
||||
sms,
|
||||
eventOptions,
|
||||
creationError,
|
||||
submit
|
||||
}) => {
|
||||
const CustomSMSModal = ({ showModal, onClose, sms, creationError, submit }) => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [selectedEvent, setSelectedEvent] = useState(sms?.event)
|
||||
|
||||
const initialValues = {
|
||||
event: !R.isNil(sms) ? sms.event : '',
|
||||
message: !R.isNil(sms) ? sms.message : ''
|
||||
|
|
@ -78,7 +69,7 @@ const CustomSMSModal = ({
|
|||
const validationSchema = Yup.object().shape({
|
||||
event: Yup.string().required('An event is required!'),
|
||||
message:
|
||||
prefill[selectedEvent]?.validator ??
|
||||
prefill[sms?.event]?.validator ??
|
||||
Yup.string()
|
||||
.required('The message content is required!')
|
||||
.trim()
|
||||
|
|
@ -106,7 +97,7 @@ const CustomSMSModal = ({
|
|||
<>
|
||||
{showModal && (
|
||||
<Modal
|
||||
title={!R.isNil(sms) ? `Edit custom SMS` : `Add custom SMS`}
|
||||
title={`Edit SMS notice`}
|
||||
closeOnBackdropClick={true}
|
||||
width={600}
|
||||
height={500}
|
||||
|
|
@ -121,17 +112,7 @@ const CustomSMSModal = ({
|
|||
handleSubmit(values, errors, touched)
|
||||
}>
|
||||
{({ values, errors, touched }) => (
|
||||
<Form id="custom-sms" className={classes.form}>
|
||||
<Field
|
||||
name="event"
|
||||
label="Event"
|
||||
fullWidth
|
||||
onChange={setSelectedEvent(values.event)}
|
||||
options={eventOptions}
|
||||
labelProp="display"
|
||||
valueProp="code"
|
||||
component={Autocomplete}
|
||||
/>
|
||||
<Form id="sms-notice" className={classes.form}>
|
||||
<Field
|
||||
name="message"
|
||||
label="Message content"
|
||||
|
|
@ -148,9 +129,9 @@ const CustomSMSModal = ({
|
|||
)}
|
||||
<Button
|
||||
type="submit"
|
||||
form="custom-sms"
|
||||
form="sms-notice"
|
||||
className={classes.submit}>
|
||||
{!R.isNil(sms) ? `Confirm` : `Create SMS`}
|
||||
Confirm
|
||||
</Button>
|
||||
</div>
|
||||
</Form>
|
||||
|
|
@ -1,65 +1,59 @@
|
|||
import { useQuery, useMutation } from '@apollo/react-hooks'
|
||||
import { makeStyles, Box } from '@material-ui/core'
|
||||
import { makeStyles } from '@material-ui/core'
|
||||
import gql from 'graphql-tag'
|
||||
import * as R from 'ramda'
|
||||
import React, { useState } from 'react'
|
||||
|
||||
import { DeleteDialog } from 'src/components/DeleteDialog'
|
||||
import { Link, IconButton } from 'src/components/buttons'
|
||||
import { IconButton } from 'src/components/buttons'
|
||||
import { Switch } from 'src/components/inputs'
|
||||
import DataTable from 'src/components/tables/DataTable'
|
||||
import { H4 } from 'src/components/typography'
|
||||
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
|
||||
import { ReactComponent as EditIcon } from 'src/styling/icons/action/edit/enabled.svg'
|
||||
|
||||
import styles from './CustomSMS.styles'
|
||||
import CustomSMSModal from './CustomSMSModal'
|
||||
import styles from './SMSNotices.styles'
|
||||
|
||||
const useStyles = makeStyles(styles)
|
||||
|
||||
const GET_CUSTOM_MESSAGES = gql`
|
||||
query customMessages {
|
||||
customMessages {
|
||||
const GET_SMS_NOTICES = gql`
|
||||
query SMSNotices {
|
||||
SMSNotices {
|
||||
id
|
||||
event
|
||||
message
|
||||
messageName
|
||||
enabled
|
||||
allowToggle
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const CREATE_CUSTOM_MESSAGE = gql`
|
||||
mutation createCustomMessage($event: CustomMessageEvent!, $message: String!) {
|
||||
createCustomMessage(event: $event, message: $message) {
|
||||
const EDIT_SMS_NOTICE = gql`
|
||||
mutation editSMSNotice($id: ID!, $event: SMSNoticeEvent!, $message: String!) {
|
||||
editSMSNotice(id: $id, event: $event, message: $message) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const EDIT_CUSTOM_MESSAGE = gql`
|
||||
mutation editCustomMessage(
|
||||
$id: ID!
|
||||
$event: CustomMessageEvent!
|
||||
$message: String!
|
||||
) {
|
||||
editCustomMessage(id: $id, event: $event, message: $message) {
|
||||
const ENABLE_SMS_NOTICE = gql`
|
||||
mutation enableSMSNotice($id: ID!) {
|
||||
enableSMSNotice(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const DELETE_CUSTOM_MESSAGE = gql`
|
||||
mutation deleteCustomMessage($id: ID!) {
|
||||
deleteCustomMessage(id: $id) {
|
||||
const DISABLE_SMS_NOTICE = gql`
|
||||
mutation disableSMSNotice($id: ID!) {
|
||||
disableSMSNotice(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
const EVENT_OPTIONS = [
|
||||
{ code: 'smsCode', display: 'On SMS confirmation code' },
|
||||
{ code: 'cashOutDispenseReady', display: 'Cash out dispense ready' }
|
||||
]
|
||||
|
||||
const CustomSMS = () => {
|
||||
const SMSNotices = () => {
|
||||
const classes = useStyles()
|
||||
|
||||
const [deleteDialog, setDeleteDialog] = useState(false)
|
||||
|
|
@ -68,22 +62,22 @@ const CustomSMS = () => {
|
|||
const [errorMsg, setErrorMsg] = useState('')
|
||||
|
||||
const { data: messagesData, loading: messagesLoading } = useQuery(
|
||||
GET_CUSTOM_MESSAGES
|
||||
GET_SMS_NOTICES
|
||||
)
|
||||
|
||||
const [createMessage] = useMutation(CREATE_CUSTOM_MESSAGE, {
|
||||
const [editMessage] = useMutation(EDIT_SMS_NOTICE, {
|
||||
onError: ({ msg }) => setErrorMsg(msg),
|
||||
refetchQueries: () => ['customMessages']
|
||||
refetchQueries: () => ['SMSNotices']
|
||||
})
|
||||
|
||||
const [editMessage] = useMutation(EDIT_CUSTOM_MESSAGE, {
|
||||
const [enableMessage] = useMutation(ENABLE_SMS_NOTICE, {
|
||||
onError: ({ msg }) => setErrorMsg(msg),
|
||||
refetchQueries: () => ['customMessages']
|
||||
refetchQueries: () => ['SMSNotices']
|
||||
})
|
||||
|
||||
const [deleteMessage] = useMutation(DELETE_CUSTOM_MESSAGE, {
|
||||
const [disableMessage] = useMutation(DISABLE_SMS_NOTICE, {
|
||||
onError: ({ msg }) => setErrorMsg(msg),
|
||||
refetchQueries: () => ['customMessages']
|
||||
refetchQueries: () => ['SMSNotices']
|
||||
})
|
||||
|
||||
const loading = messagesLoading
|
||||
|
|
@ -94,19 +88,15 @@ const CustomSMS = () => {
|
|||
setDeleteDialog(false)
|
||||
}
|
||||
|
||||
const handleOpen = () => {
|
||||
setErrorMsg('')
|
||||
setShowModal(true)
|
||||
}
|
||||
console.log(messagesData)
|
||||
|
||||
const elements = [
|
||||
{
|
||||
header: 'Event',
|
||||
width: 600,
|
||||
header: 'Message name',
|
||||
width: 500,
|
||||
size: 'sm',
|
||||
textAlign: 'left',
|
||||
view: it =>
|
||||
R.find(ite => R.propEq('event', ite.code, it), EVENT_OPTIONS).display
|
||||
view: it => R.prop('messageName', it)
|
||||
},
|
||||
{
|
||||
header: 'Edit',
|
||||
|
|
@ -124,18 +114,20 @@ const CustomSMS = () => {
|
|||
)
|
||||
},
|
||||
{
|
||||
header: 'Delete',
|
||||
header: 'Enable',
|
||||
width: 100,
|
||||
size: 'sm',
|
||||
textAlign: 'center',
|
||||
view: it => (
|
||||
<IconButton
|
||||
<Switch
|
||||
disabled={!it.allowToggle}
|
||||
onClick={() => {
|
||||
setSelectedSMS(it)
|
||||
setDeleteDialog(true)
|
||||
}}>
|
||||
<DeleteIcon />
|
||||
</IconButton>
|
||||
it.enabled
|
||||
? disableMessage({ variables: { id: it.id } })
|
||||
: enableMessage({ variables: { id: it.id } })
|
||||
}}
|
||||
checked={it.enabled}
|
||||
/>
|
||||
)
|
||||
}
|
||||
]
|
||||
|
|
@ -143,21 +135,15 @@ const CustomSMS = () => {
|
|||
return (
|
||||
<>
|
||||
<div className={classes.header}>
|
||||
<H4>Custom SMS message</H4>
|
||||
<Box display="flex" justifyContent="flex-end">
|
||||
<Link color="primary" onClick={() => handleOpen()}>
|
||||
Add custom SMS
|
||||
</Link>
|
||||
</Box>
|
||||
<H4>SMS Notices</H4>
|
||||
</div>
|
||||
{showModal && (
|
||||
<CustomSMSModal
|
||||
showModal={showModal}
|
||||
onClose={handleClose}
|
||||
eventOptions={EVENT_OPTIONS}
|
||||
sms={selectedSMS}
|
||||
creationError={errorMsg}
|
||||
submit={selectedSMS ? editMessage : createMessage}
|
||||
submit={editMessage}
|
||||
/>
|
||||
)}
|
||||
<DeleteDialog
|
||||
|
|
@ -167,22 +153,17 @@ const CustomSMS = () => {
|
|||
}}
|
||||
onConfirmed={() => {
|
||||
handleClose()
|
||||
deleteMessage({
|
||||
variables: {
|
||||
id: selectedSMS.id
|
||||
}
|
||||
})
|
||||
}}
|
||||
errorMessage={errorMsg}
|
||||
/>
|
||||
<DataTable
|
||||
emptyText="No custom SMS so far"
|
||||
emptyText="No SMS notices so far"
|
||||
elements={elements}
|
||||
loading={loading}
|
||||
data={R.path(['customMessages'])(messagesData)}
|
||||
data={R.path(['SMSNotices'])(messagesData)}
|
||||
/>
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
export default CustomSMS
|
||||
export default SMSNotices
|
||||
|
|
@ -16,8 +16,8 @@ import MachineStatus from 'src/pages/Maintenance/MachineStatus'
|
|||
import Notifications from 'src/pages/Notifications/Notifications'
|
||||
import CoinAtmRadar from 'src/pages/OperatorInfo/CoinATMRadar'
|
||||
import ContactInfo from 'src/pages/OperatorInfo/ContactInfo'
|
||||
import CustomSMS from 'src/pages/OperatorInfo/CustomSMS/CustomSMS'
|
||||
import ReceiptPrinting from 'src/pages/OperatorInfo/ReceiptPrinting'
|
||||
import CustomSMS from 'src/pages/OperatorInfo/SMSNotices/SMSNotices'
|
||||
import TermsConditions from 'src/pages/OperatorInfo/TermsConditions'
|
||||
import ServerLogs from 'src/pages/ServerLogs'
|
||||
import Services from 'src/pages/Services/Services'
|
||||
|
|
|
|||
|
|
@ -19,8 +19,8 @@ import MachineStatus from 'src/pages/Maintenance/MachineStatus'
|
|||
import Notifications from 'src/pages/Notifications/Notifications'
|
||||
import CoinAtmRadar from 'src/pages/OperatorInfo/CoinATMRadar'
|
||||
import ContactInfo from 'src/pages/OperatorInfo/ContactInfo'
|
||||
import CustomSMS from 'src/pages/OperatorInfo/CustomSMS/CustomSMS'
|
||||
import ReceiptPrinting from 'src/pages/OperatorInfo/ReceiptPrinting'
|
||||
import CustomSMS from 'src/pages/OperatorInfo/SMSNotices/SMSNotices'
|
||||
import TermsConditions from 'src/pages/OperatorInfo/TermsConditions'
|
||||
import ServerLogs from 'src/pages/ServerLogs'
|
||||
import Services from 'src/pages/Services/Services'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue