160 lines
4.5 KiB
JavaScript
160 lines
4.5 KiB
JavaScript
import { useQuery, useMutation, gql } from '@apollo/client'
|
|
import * as R from 'ramda'
|
|
import React, { useState, useEffect } from 'react'
|
|
import ActionButton from '../buttons/ActionButton'
|
|
import { H5 } from '../typography'
|
|
import NotificationIconZodiac from '../../styling/icons/menu/notification-zodiac.svg?react'
|
|
import ClearAllIconInverse from '../../styling/icons/stage/spring/empty.svg?react'
|
|
import ClearAllIcon from '../../styling/icons/stage/zodiac/empty.svg?react'
|
|
import ShowUnreadIcon from '../../styling/icons/stage/zodiac/full.svg?react'
|
|
|
|
import NotificationRow from './NotificationRow'
|
|
import classes from './NotificationCenter.module.css'
|
|
|
|
const GET_NOTIFICATIONS = gql`
|
|
query getNotifications {
|
|
notifications {
|
|
id
|
|
type
|
|
detail
|
|
message
|
|
created
|
|
read
|
|
valid
|
|
}
|
|
hasUnreadNotifications
|
|
machines {
|
|
deviceId
|
|
name
|
|
}
|
|
}
|
|
`
|
|
|
|
const TOGGLE_CLEAR_NOTIFICATION = gql`
|
|
mutation toggleClearNotification($id: ID!, $read: Boolean!) {
|
|
toggleClearNotification(id: $id, read: $read) {
|
|
id
|
|
read
|
|
}
|
|
}
|
|
`
|
|
|
|
const CLEAR_ALL_NOTIFICATIONS = gql`
|
|
mutation clearAllNotifications {
|
|
clearAllNotifications {
|
|
id
|
|
}
|
|
}
|
|
`
|
|
|
|
const NotificationCenter = ({
|
|
close,
|
|
hasUnreadProp,
|
|
buttonCoords,
|
|
popperRef,
|
|
refetchHasUnreadHeader,
|
|
}) => {
|
|
const { data, loading } = useQuery(GET_NOTIFICATIONS, {
|
|
pollInterval: 60000,
|
|
})
|
|
const [xOffset, setXoffset] = useState(300)
|
|
|
|
const [showingUnread, setShowingUnread] = useState(false)
|
|
const machines = R.compose(
|
|
R.map(R.prop('name')),
|
|
R.indexBy(R.prop('deviceId')),
|
|
)(R.path(['machines'])(data) ?? [])
|
|
const notifications = R.path(['notifications'])(data) ?? []
|
|
const [hasUnread, setHasUnread] = useState(hasUnreadProp)
|
|
|
|
const [toggleClearNotification] = useMutation(TOGGLE_CLEAR_NOTIFICATION, {
|
|
onError: () => console.error('Error while clearing notification'),
|
|
refetchQueries: () => ['getNotifications'],
|
|
})
|
|
const [clearAllNotifications] = useMutation(CLEAR_ALL_NOTIFICATIONS, {
|
|
onError: () => console.error('Error while clearing all notifications'),
|
|
refetchQueries: () => ['getNotifications'],
|
|
})
|
|
|
|
useEffect(() => {
|
|
setXoffset(popperRef.current.getBoundingClientRect().x)
|
|
if (data && data.hasUnreadNotifications !== hasUnread) {
|
|
refetchHasUnreadHeader()
|
|
setHasUnread(!hasUnread)
|
|
}
|
|
}, [popperRef, data, hasUnread, refetchHasUnreadHeader])
|
|
|
|
const buildNotifications = () => {
|
|
const notificationsToShow =
|
|
!showingUnread || !hasUnread
|
|
? notifications
|
|
: R.filter(R.propEq(false, 'read'))(notifications)
|
|
return notificationsToShow.map(n => {
|
|
return (
|
|
<NotificationRow
|
|
key={n.id}
|
|
id={n.id}
|
|
type={n.type}
|
|
detail={n.detail}
|
|
message={n.message}
|
|
deviceName={machines[n.detail.deviceId]}
|
|
created={n.created}
|
|
read={n.read}
|
|
valid={n.valid}
|
|
toggleClear={() =>
|
|
toggleClearNotification({
|
|
variables: { id: n.id, read: !n.read },
|
|
})
|
|
}
|
|
/>
|
|
)
|
|
})
|
|
}
|
|
|
|
return (
|
|
<>
|
|
<div className={classes.container}>
|
|
<div className={classes.header}>
|
|
<H5 className={classes.headerText}>Notifications</H5>
|
|
<button
|
|
onClick={close}
|
|
className={classes.notificationIcon}
|
|
style={{
|
|
top: buttonCoords?.y ?? 0,
|
|
left: buttonCoords?.x ? buttonCoords.x - xOffset : 0,
|
|
}}>
|
|
<NotificationIconZodiac />
|
|
{hasUnread && <div className={classes.hasUnread} />}
|
|
</button>
|
|
</div>
|
|
<div className={classes.actionButtons}>
|
|
{hasUnread && (
|
|
<ActionButton
|
|
color="primary"
|
|
Icon={ShowUnreadIcon}
|
|
InverseIcon={ClearAllIconInverse}
|
|
className={classes.clearAllButton}
|
|
onClick={() => setShowingUnread(!showingUnread)}>
|
|
{showingUnread ? 'Show all' : 'Show unread'}
|
|
</ActionButton>
|
|
)}
|
|
{hasUnread && (
|
|
<ActionButton
|
|
color="primary"
|
|
Icon={ClearAllIcon}
|
|
InverseIcon={ClearAllIconInverse}
|
|
className={classes.clearAllButton}
|
|
onClick={clearAllNotifications}>
|
|
Mark all as read
|
|
</ActionButton>
|
|
)}
|
|
</div>
|
|
<div className={classes.notificationsList}>
|
|
{!loading && buildNotifications()}
|
|
</div>
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default NotificationCenter
|