This repository has been archived by the owner on Aug 9, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(notifier): adds notification channels
- Loading branch information
Showing
6 changed files
with
286 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
69
src/components/organisms/notifier/NotificationChannelCreate.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
121
src/components/organisms/notifier/NotificationChannelsList.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
} |