Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
233 lines
6.7 KiB
JavaScript
233 lines
6.7 KiB
JavaScript
import PropTypes from 'prop-types'
|
|
import { useState, useEffect, useContext } from 'react'
|
|
import { Button, message, Popover, Typography, Space, Flex } from 'antd'
|
|
import { UserOutlined } from '@ant-design/icons'
|
|
import BellIcon from '../../Icons/BellIcon'
|
|
import NewMailIcon from '../../Icons/NewMailIcon'
|
|
import { ApiServerContext } from '../context/ApiServerContext'
|
|
import { AuthContext } from '../context/AuthContext'
|
|
import { LoadingOutlined } from '@ant-design/icons'
|
|
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
|
|
|
|
const { Text } = Typography
|
|
|
|
const UserNotifierToggle = ({
|
|
type,
|
|
objectData,
|
|
disabled = false,
|
|
...buttonProps
|
|
}) => {
|
|
const {
|
|
toggleUserNotifier,
|
|
editUserNotifier,
|
|
fetchUserNotifiersForObject,
|
|
fetchAllUserNotifiersForObject
|
|
} = useContext(ApiServerContext)
|
|
const { userProfile } = useContext(AuthContext)
|
|
const [isNotifying, setIsNotifying] = useState(false)
|
|
const [loading, setLoading] = useState(false)
|
|
const [initialLoad, setInitialLoad] = useState(true)
|
|
const [allNotifiers, setAllNotifiers] = useState([])
|
|
const [popoverOpen, setPopoverOpen] = useState(false)
|
|
const [popoverLoading, setPopoverLoading] = useState(false)
|
|
const [emailTogglingId, setEmailTogglingId] = useState(null)
|
|
|
|
const objectId = objectData?._id
|
|
|
|
useEffect(() => {
|
|
const loadNotifierState = async () => {
|
|
if (!objectId || !type) return
|
|
|
|
setInitialLoad(true)
|
|
try {
|
|
const { data } = await fetchUserNotifiersForObject(objectId, type)
|
|
setIsNotifying(data?.length > 0)
|
|
} catch (error) {
|
|
console.error('Error fetching user notifier state:', error)
|
|
} finally {
|
|
setInitialLoad(false)
|
|
}
|
|
}
|
|
|
|
loadNotifierState()
|
|
}, [objectId, type, fetchUserNotifiersForObject])
|
|
|
|
useEffect(() => {
|
|
const loadAllNotifiers = async () => {
|
|
if (!objectId || !type || !popoverOpen) return
|
|
|
|
setPopoverLoading(true)
|
|
try {
|
|
const { data } = await fetchAllUserNotifiersForObject(objectId, type)
|
|
setAllNotifiers(data || [])
|
|
} catch (error) {
|
|
console.error('Error fetching all user notifiers:', error)
|
|
setAllNotifiers([])
|
|
} finally {
|
|
setPopoverLoading(false)
|
|
}
|
|
}
|
|
|
|
loadAllNotifiers()
|
|
}, [objectId, type, popoverOpen, fetchAllUserNotifiersForObject])
|
|
|
|
const handleClick = async () => {
|
|
if (!objectId || !type || loading) return
|
|
|
|
setLoading(true)
|
|
try {
|
|
const enabled = await toggleUserNotifier(objectId, type)
|
|
setIsNotifying(enabled)
|
|
if (popoverOpen) {
|
|
const { data } = await fetchAllUserNotifiersForObject(objectId, type)
|
|
setAllNotifiers(data || [])
|
|
}
|
|
message.success(
|
|
enabled
|
|
? 'Notifications enabled for this object'
|
|
: 'Notifications disabled for this object'
|
|
)
|
|
} catch (error) {
|
|
console.error('Error toggling user notifier:', error)
|
|
message.error('Failed to update notifications')
|
|
} finally {
|
|
setLoading(false)
|
|
}
|
|
}
|
|
|
|
const getUserDisplayName = (user) => {
|
|
if (!user) return 'Unknown'
|
|
return (
|
|
user.name ||
|
|
user.username ||
|
|
`${user.firstName || ''} ${user.lastName || ''}`.trim() ||
|
|
user.email ||
|
|
'Unknown'
|
|
)
|
|
}
|
|
|
|
const isCurrentUser = (user) => user?._id === userProfile?._id
|
|
|
|
const handleEmailToggle = async (item) => {
|
|
if (!isCurrentUser(item.user) || emailTogglingId) return
|
|
setEmailTogglingId(item._id)
|
|
const newEmail = !item.email
|
|
try {
|
|
const result = await editUserNotifier(item._id, { email: newEmail })
|
|
if (result) {
|
|
setAllNotifiers((prev) =>
|
|
prev.map((n) =>
|
|
n._id === item._id ? { ...n, email: result.email ?? newEmail } : n
|
|
)
|
|
)
|
|
message.success(
|
|
(result.email ?? newEmail)
|
|
? 'Email notifications enabled'
|
|
: 'Email notifications disabled'
|
|
)
|
|
}
|
|
} catch (error) {
|
|
console.error('Error toggling email:', error)
|
|
message.error('Failed to update email notifications')
|
|
} finally {
|
|
setEmailTogglingId(null)
|
|
}
|
|
}
|
|
|
|
const popoverContent = (
|
|
<Flex
|
|
vertical
|
|
justify='center'
|
|
style={{ minWidth: 240, minHeight: 25 }}
|
|
gap={'4px'}
|
|
>
|
|
{popoverLoading ? (
|
|
<Space size={'small'}>
|
|
<LoadingOutlined />
|
|
<Text style={{ margin: 0 }}>Loading, please wait...</Text>
|
|
</Space>
|
|
) : allNotifiers.length === 0 ? (
|
|
<Space size={'small'}>
|
|
<Text style={{ margin: 0 }} type='secondary'>
|
|
<InfoCircleIcon />
|
|
</Text>
|
|
<Text style={{ margin: 0 }} type='secondary'>
|
|
No users subscribed.
|
|
</Text>
|
|
</Space>
|
|
) : (
|
|
<>
|
|
{[...allNotifiers]
|
|
.sort(
|
|
(a, b) =>
|
|
(isCurrentUser(b.user) ? 1 : 0) -
|
|
(isCurrentUser(a.user) ? 1 : 0)
|
|
)
|
|
.map((item) => (
|
|
<Flex key={item._id} justify='space-between' align='center'>
|
|
<Flex align='center' gap={'6px'}>
|
|
<UserOutlined />
|
|
<Text>{getUserDisplayName(item.user)}</Text>
|
|
{isCurrentUser(item.user) && (
|
|
<Text type='secondary'> (you)</Text>
|
|
)}
|
|
</Flex>
|
|
<Space size={'small'}>
|
|
<Button
|
|
type='text'
|
|
icon={
|
|
<NewMailIcon
|
|
style={{
|
|
color: item.email ? 'var(--color-primary)' : undefined
|
|
}}
|
|
/>
|
|
}
|
|
size='small'
|
|
disabled={!isCurrentUser(item.user)}
|
|
loading={emailTogglingId === item._id}
|
|
onClick={() => handleEmailToggle(item)}
|
|
/>
|
|
</Space>
|
|
</Flex>
|
|
))}
|
|
</>
|
|
)}
|
|
</Flex>
|
|
)
|
|
|
|
return (
|
|
<Popover
|
|
content={popoverContent}
|
|
title={null}
|
|
trigger='hover'
|
|
placement='bottomLeft'
|
|
arrow={false}
|
|
open={popoverOpen}
|
|
onOpenChange={setPopoverOpen}
|
|
styles={{ body: { padding: '10px 15px' } }}
|
|
>
|
|
<Button
|
|
{...buttonProps}
|
|
icon={
|
|
<BellIcon
|
|
style={{
|
|
color: isNotifying ? 'var(--color-warning)' : undefined
|
|
}}
|
|
/>
|
|
}
|
|
disabled={disabled || loading || initialLoad}
|
|
loading={loading || !objectId || !type}
|
|
onClick={handleClick}
|
|
/>
|
|
</Popover>
|
|
)
|
|
}
|
|
|
|
UserNotifierToggle.propTypes = {
|
|
type: PropTypes.string.isRequired,
|
|
objectData: PropTypes.object.isRequired,
|
|
disabled: PropTypes.bool
|
|
}
|
|
|
|
export default UserNotifierToggle
|