Skip to content
This repository has been archived by the owner on Aug 9, 2022. It is now read-only.

Commit

Permalink
feat(notifier): adds notification channels
Browse files Browse the repository at this point in the history
  • Loading branch information
vjgene committed May 10, 2021
1 parent a32e88d commit ea40d49
Show file tree
Hide file tree
Showing 6 changed files with 286 additions and 0 deletions.
64 changes: 64 additions & 0 deletions src/components/organisms/notifier/NotificationChannel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React, { FC } from 'react'
import { makeStyles, Theme } from '@material-ui/core/styles'
import Grid from '@material-ui/core/Grid'
import Typography from '@material-ui/core/Typography'
import Box from '@material-ui/core/Box'
import { colors } from '@rsksmart/rif-ui'
import { NotifierChannel } from 'models/marketItems/NotifierItem'
import RemoveButton from 'components/atoms/RemoveButton'

export interface NotificationChannelProps {
className?: string
onRemoveClick: (e: any) => void
channel: NotifierChannel
}

const useStyles = makeStyles((theme: Theme) => ({
innerContainer: {
backgroundColor: colors.gray1,
borderRadius: 5,
padding: theme.spacing(2),
},
leftContent: {
[theme.breakpoints.up('sm')]: {
borderRight: `1px solid ${colors.gray3}`,
},
},
}))

const NotificationChannel: FC<NotificationChannelProps> = ({
className = '', channel, onRemoveClick,
}) => {
const classes = useStyles()

return (
<Grid className={className} container alignItems="center" spacing={2}>
<Grid item xs={9}>
<Grid
container
alignItems="center"
className={classes.innerContainer}
spacing={1}
>
<Grid xs={6} item>
<Typography component="div">
<Box fontWeight="fontWeightMedium" textAlign="center" color={colors.gray5}>
{channel.type}
</Box>
</Typography>
</Grid>
<Grid xs={6} item style={{ display: 'flex', justifyContent: 'space-around', alignItems: 'center' }}>
{channel.destination}
</Grid>
</Grid>
</Grid>
<Grid item xs={3}>
<Grid container direction="row">
<RemoveButton id={channel.type} handleSelect={onRemoveClick} />
</Grid>
</Grid>
</Grid>
)
}

export default NotificationChannel
69 changes: 69 additions & 0 deletions src/components/organisms/notifier/NotificationChannelCreate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import React, { FC } from 'react'
import { makeStyles, Theme } from '@material-ui/core/styles'
import Grid from '@material-ui/core/Grid'
import { NotifierChannel, NotifierChannelType } from 'models/marketItems/NotifierItem'
import { FormControl } from '@material-ui/core'
import Select from '@material-ui/core/Select'
import MenuItem from '@material-ui/core/MenuItem'
import TextField from '@material-ui/core/TextField'
import { SelectRowButton } from 'components/molecules'

export interface NotificationChannelCreateProps {
onChannelChange: (e: any) => void
onDestinationChange: (e: any) => void
notifierChannel: NotifierChannel
channelAdd: () => void
availableChannels: string[]
}

const useStyles = makeStyles((theme: Theme) => ({
formControl: {
margin: theme.spacing(1),
minWidth: 120,
},
select: {
textAlign: 'center',
height: 40,
},
}))

const NotificationChannelCreate: FC<NotificationChannelCreateProps> = ({
notifierChannel, availableChannels, onChannelChange, onDestinationChange, channelAdd,
}) => {
const classes = useStyles()

return (
<Grid container spacing={4} alignItems="center">
<Grid item xs={2} md={2}>
<FormControl variant="outlined" className={classes.formControl}>
<Select
className={classes.select}
id="channel-select"
value={notifierChannel.type}
onChange={onChannelChange}
>
{
availableChannels.map((channelType) => <MenuItem value={channelType}>{channelType}</MenuItem>)
}
</Select>
</FormControl>
</Grid>
<Grid item xs={7} md={7}>
<TextField
onChange={onDestinationChange}
placeholder={NotifierChannelType[notifierChannel.type]}
variant="outlined"
InputProps={{
style: { height: 40 },
}}
/>
</Grid>
<Grid item xs={3} md={3}>
<SelectRowButton id="add-channel" handleSelect={channelAdd} size="large" variant="outlined">Add Channel</SelectRowButton>
</Grid>
</Grid>

)
}

export default NotificationChannelCreate
121 changes: 121 additions & 0 deletions src/components/organisms/notifier/NotificationChannelsList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* eslint-disable @typescript-eslint/no-empty-function */
import {
Grid, makeStyles, Typography,
} from '@material-ui/core'
import React, {
FC, useState,
} from 'react'
import { createStyles, Theme } from '@material-ui/core/styles'
import { NotifierChannel, NotifierChannelType } from 'models/marketItems/NotifierItem'
import RemoveButton from 'components/atoms/RemoveButton'
import { validateEmail, validateURL } from 'utils/validationUtils'
import RoundBtn from 'components/atoms/RoundBtn'
import GridRow from 'components/atoms/GridRow'
import NotificationChannel from 'components/organisms/notifier/NotificationChannel'
import { colors } from '@rsksmart/rif-ui'
import NotificationChannelCreate from 'components/organisms/notifier/NotificationChannelCreate'

const useStyles = makeStyles((theme: Theme) => createStyles({

plansList: {
marginTop: theme.spacing(2),
borderTop: `1px solid ${colors.gray3}`,
padding: theme.spacing(3, 0),
},

}))

type Props =
{
channels: string[] | undefined
}

const NotificationChannelsList: FC<Props> = ({ channels }) => {
const [notifierChannel, setChannel] = useState<NotifierChannel>({
type: channels ? channels[0] : '',
destination: '',
})
const [addedChannels, setChannels] = useState<Array<NotifierChannel>>([])
const [destination, setDestination] = useState<string>('')
const handleChange = (e) => setChannel({
destination: e.target.value as string,
type: notifierChannel.type,
})
const classes = useStyles()

if (!channels) {
return <Grid />
}
const availableChannels: Array<string> = channels.map((ch) => (NotifierChannelType[ch] ? ch : ''))

const validate = (channel: NotifierChannel) => {
if (channel.destination) {
if (channel.type === 'API') {
return validateURL(channel.destination)
}

if (channel.type === 'EMAIL') {
return validateEmail(channel.destination)
}
}
return false
}

const addChannel = () => {
notifierChannel.destination = destination

if (!validate(notifierChannel)) {
return
}
const index = addedChannels.findIndex((ch) => ch.type === notifierChannel.type)

if (index === -1) addedChannels.push(notifierChannel)
else addedChannels[index].destination = destination
const newChannels = [...addedChannels]
setChannels(newChannels)
}

const removeChannel = (e): void => {
const newChannels = addedChannels.filter((i) => i.type !== e.currentTarget.id)
setChannels(newChannels)
}

const collection = addedChannels.map((channel) => ({
type: channel.type,
destination: channel.destination,
actions: <RemoveButton id={channel.type} handleSelect={removeChannel} />,
}))

return (
<Grid>
<Typography gutterBottom variant="h6" color="primary">
Notification Channels
</Typography>
<Typography gutterBottom color="secondary" variant="body2">
Select the channel that you want to receive your notification through
</Typography>
<NotificationChannelCreate
notifierChannel={notifierChannel}
availableChannels={availableChannels}
onDestinationChange={(e) => setDestination(e.currentTarget.value)}
onChannelChange={handleChange}
channelAdd={addChannel}
/>
<Grid className={classes.plansList} item xs={12}>
<Grid alignItems="center" container spacing={2}>
{
collection.map((channel) => <NotificationChannel channel={channel} onRemoveClick={removeChannel} />)
}
</Grid>
</Grid>
<br />
<br />
<GridRow justify="center" spacing={2}>
<RoundBtn type="submit">
Submit
</RoundBtn>
</GridRow>
</Grid>
)
}
export default NotificationChannelsList
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import TableContainer from '@material-ui/core/TableContainer'
import { Item } from 'models/Market'
import RemoveButton from 'components/atoms/RemoveButton'
import Tooltip from '@material-ui/core/Tooltip'
import NotificationChannelsList from 'components/organisms/notifier/NotificationChannelsList'

const eventHeaders = {
name: 'Name',
Expand Down Expand Up @@ -109,6 +110,9 @@ const NotifierOffersSelectedPage: FC = () => {
<Button variant="outlined" color="primary" rounded>
+ Add Notification Events
</Button>
<br />
<br />
<NotificationChannelsList {...{ channels: order?.item.channels }} />
</CenteredPageTemplate>
)
}
Expand Down
10 changes: 10 additions & 0 deletions src/models/marketItems/NotifierItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,13 @@ export type NotifierSubscriptionItem = Item & Omit<SubscriptionDTO, 'hash' | 'pr
price: Big
token: SupportedToken
}

export enum NotifierChannelType {
API = 'Enter api destination',
EMAIL = 'Enter your email'
}

export type NotifierChannel = {
type: string
destination: string
}
18 changes: 18 additions & 0 deletions src/utils/validationUtils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export const validateURL = (_url: string): boolean => {
let url
try {
url = new URL(_url)
} catch (_) {
return false
}
return url.protocol === 'http:' || url.protocol === 'https:'
}

export const validateEmail = (emails: string): boolean => {
const re = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/
let valid = true
emails.split(';').forEach((email) => {
if (re.test(String(email).toLowerCase()) === false) valid = false
})
return valid
}

0 comments on commit ea40d49

Please sign in to comment.