Compare commits
No commits in common. "2d881cb152eb1e0c5c365e6ba0ef3f9768b3c136" and "6e8ad1c41279d5fa548a451d0a9cd6b6c907f68c" have entirely different histories.
2d881cb152
...
6e8ad1c412
@ -21,12 +21,7 @@ const DocumentPrintButton = ({
|
|||||||
disabled = false,
|
disabled = false,
|
||||||
...buttonProps
|
...buttonProps
|
||||||
}) => {
|
}) => {
|
||||||
const {
|
const { fetchObjects } = useContext(ApiServerContext)
|
||||||
fetchObjects,
|
|
||||||
connected,
|
|
||||||
subscribeToObjectUpdates,
|
|
||||||
subscribeToObjectTypeUpdates
|
|
||||||
} = useContext(ApiServerContext)
|
|
||||||
const fetchObjectsRef = useRef(fetchObjects)
|
const fetchObjectsRef = useRef(fetchObjects)
|
||||||
fetchObjectsRef.current = fetchObjects
|
fetchObjectsRef.current = fetchObjects
|
||||||
|
|
||||||
@ -35,40 +30,22 @@ const DocumentPrintButton = ({
|
|||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [newDocumentJobOpen, setNewDocumentJobOpen] = useState(false)
|
const [newDocumentJobOpen, setNewDocumentJobOpen] = useState(false)
|
||||||
|
|
||||||
const subscribedIdsRef = useRef([])
|
|
||||||
const unsubscribesRef = useRef([])
|
|
||||||
const subscribeToObjectTypeUpdatesRef = useRef(null)
|
|
||||||
const updateEventHandlerRef = useRef()
|
|
||||||
|
|
||||||
const { token } = useContext(AuthContext)
|
const { token } = useContext(AuthContext)
|
||||||
|
|
||||||
const subscriptionFilter = useMemo(
|
// Get the model by name
|
||||||
() => ({
|
//const model = getModelByName(type)
|
||||||
|
|
||||||
|
const loadDocumentTemplates = useCallback(async () => {
|
||||||
|
if (!type || token == null) return
|
||||||
|
|
||||||
|
setLoading(true)
|
||||||
|
try {
|
||||||
|
const result = await fetchObjectsRef.current('documentTemplate', {
|
||||||
|
filter: {
|
||||||
objectType: type,
|
objectType: type,
|
||||||
global: false,
|
global: false,
|
||||||
active: true
|
active: true
|
||||||
}),
|
},
|
||||||
[type]
|
|
||||||
)
|
|
||||||
|
|
||||||
const templateMatchesFilter = useCallback(
|
|
||||||
(template) =>
|
|
||||||
template?.objectType === type &&
|
|
||||||
template?.global === false &&
|
|
||||||
template?.active === true,
|
|
||||||
[type]
|
|
||||||
)
|
|
||||||
|
|
||||||
const loadDocumentTemplates = useCallback(
|
|
||||||
async (silent = false) => {
|
|
||||||
if (!type || token == null) return
|
|
||||||
|
|
||||||
if (!silent) {
|
|
||||||
setLoading(true)
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
const result = await fetchObjectsRef.current('documentTemplate', {
|
|
||||||
filter: subscriptionFilter,
|
|
||||||
limit: 100 // Get more templates to show in dropdown
|
limit: 100 // Get more templates to show in dropdown
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -78,16 +55,9 @@ const DocumentPrintButton = ({
|
|||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching document templates:', error)
|
console.error('Error fetching document templates:', error)
|
||||||
} finally {
|
} finally {
|
||||||
if (!silent) {
|
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}, [type, token])
|
||||||
},
|
|
||||||
[type, token, subscriptionFilter]
|
|
||||||
)
|
|
||||||
|
|
||||||
const loadDocumentTemplatesRef = useRef(loadDocumentTemplates)
|
|
||||||
loadDocumentTemplatesRef.current = loadDocumentTemplates
|
|
||||||
|
|
||||||
// Stable key from objectData._id (excludes _isEditing so toggling edit mode doesn't trigger template reload)
|
// Stable key from objectData._id (excludes _isEditing so toggling edit mode doesn't trigger template reload)
|
||||||
const objectKey = useMemo(() => {
|
const objectKey = useMemo(() => {
|
||||||
@ -100,103 +70,6 @@ const DocumentPrintButton = ({
|
|||||||
loadDocumentTemplates()
|
loadDocumentTemplates()
|
||||||
}, [objectKey, token, type, loadDocumentTemplates])
|
}, [objectKey, token, type, loadDocumentTemplates])
|
||||||
|
|
||||||
const updateEventHandler = useCallback(
|
|
||||||
(id, updatedData) => {
|
|
||||||
setDocumentTemplates((prev) => {
|
|
||||||
const existing = prev.find((template) => template._id === id)
|
|
||||||
const merged = existing
|
|
||||||
? { ...existing, ...updatedData }
|
|
||||||
: { _id: id, ...updatedData }
|
|
||||||
|
|
||||||
if (!templateMatchesFilter(merged)) {
|
|
||||||
return prev.filter((template) => template._id !== id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existing) {
|
|
||||||
return prev.map((template) =>
|
|
||||||
template._id === id ? merged : template
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...prev, merged]
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[templateMatchesFilter]
|
|
||||||
)
|
|
||||||
|
|
||||||
updateEventHandlerRef.current = updateEventHandler
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (connected !== true) return
|
|
||||||
|
|
||||||
const unsubscribe = subscribeToObjectTypeUpdates(
|
|
||||||
'documentTemplate',
|
|
||||||
subscriptionFilter,
|
|
||||||
() => loadDocumentTemplatesRef.current(true)
|
|
||||||
)
|
|
||||||
subscribeToObjectTypeUpdatesRef.current = unsubscribe
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (unsubscribe) unsubscribe()
|
|
||||||
if (subscribeToObjectTypeUpdatesRef.current === unsubscribe) {
|
|
||||||
subscribeToObjectTypeUpdatesRef.current = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [connected, subscriptionFilter, subscribeToObjectTypeUpdates])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (connected !== true) return
|
|
||||||
|
|
||||||
const templateIds = documentTemplates.map((template) => template._id).filter(Boolean)
|
|
||||||
|
|
||||||
const newTemplateIds = templateIds.filter(
|
|
||||||
(id) => !subscribedIdsRef.current.includes(id)
|
|
||||||
)
|
|
||||||
|
|
||||||
newTemplateIds.forEach((itemId) => {
|
|
||||||
const unsubscribe = subscribeToObjectUpdates(
|
|
||||||
itemId?.toLowerCase(),
|
|
||||||
'documentTemplate',
|
|
||||||
(updateData) => updateEventHandlerRef.current(itemId, updateData)
|
|
||||||
)
|
|
||||||
subscribedIdsRef.current.push(itemId)
|
|
||||||
if (unsubscribe) {
|
|
||||||
unsubscribesRef.current.push(unsubscribe)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const templateIdsToUnsubscribe = subscribedIdsRef.current.filter(
|
|
||||||
(id) => !templateIds.includes(id)
|
|
||||||
)
|
|
||||||
|
|
||||||
templateIdsToUnsubscribe.forEach((itemId) => {
|
|
||||||
const index = subscribedIdsRef.current.indexOf(itemId)
|
|
||||||
if (index > -1) {
|
|
||||||
subscribedIdsRef.current.splice(index, 1)
|
|
||||||
const unsubscribe = unsubscribesRef.current[index]
|
|
||||||
if (unsubscribe) {
|
|
||||||
unsubscribe()
|
|
||||||
}
|
|
||||||
unsubscribesRef.current.splice(index, 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, [documentTemplates, connected, subscribeToObjectUpdates])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
unsubscribesRef.current.forEach((unsubscribe) => {
|
|
||||||
if (unsubscribe) unsubscribe()
|
|
||||||
})
|
|
||||||
unsubscribesRef.current = []
|
|
||||||
subscribedIdsRef.current = []
|
|
||||||
|
|
||||||
if (subscribeToObjectTypeUpdatesRef.current) {
|
|
||||||
subscribeToObjectTypeUpdatesRef.current()
|
|
||||||
subscribeToObjectTypeUpdatesRef.current = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
// Handle template selection
|
// Handle template selection
|
||||||
const handleTemplateSelect = (template) => {
|
const handleTemplateSelect = (template) => {
|
||||||
setCurrentDocumentTemplate(template)
|
setCurrentDocumentTemplate(template)
|
||||||
@ -205,55 +78,14 @@ const DocumentPrintButton = ({
|
|||||||
// This could open a print dialog, navigate to a print page, etc.
|
// This could open a print dialog, navigate to a print page, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group templates by tag for nested dropdown menu; untagged templates at root
|
// Create dropdown menu items
|
||||||
const menuItems = useMemo(() => {
|
const menuItems = documentTemplates.map((template) => ({
|
||||||
const templatesByTag = new Map()
|
|
||||||
const untaggedTemplates = []
|
|
||||||
|
|
||||||
const toTemplateMenuItem = (template) => ({
|
|
||||||
key: template._id,
|
key: template._id,
|
||||||
label: template.name,
|
label: template.name,
|
||||||
icon: <DocumentTemplateIcon />,
|
icon: <DocumentTemplateIcon />,
|
||||||
onClick: () => handleTemplateSelect(template)
|
onClick: () => handleTemplateSelect(template)
|
||||||
})
|
|
||||||
|
|
||||||
for (const template of documentTemplates) {
|
|
||||||
const templateTags = Array.isArray(template.tags)
|
|
||||||
? template.tags.filter(Boolean)
|
|
||||||
: []
|
|
||||||
|
|
||||||
if (templateTags.length === 0) {
|
|
||||||
untaggedTemplates.push(template)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const tag of templateTags) {
|
|
||||||
const templates = templatesByTag.get(tag) ?? []
|
|
||||||
templates.push(template)
|
|
||||||
templatesByTag.set(tag, templates)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const taggedMenuItems = [...templatesByTag.keys()]
|
|
||||||
.sort((a, b) => a.localeCompare(b))
|
|
||||||
.map((tag) => ({
|
|
||||||
key: tag,
|
|
||||||
label: tag,
|
|
||||||
children: templatesByTag
|
|
||||||
.get(tag)
|
|
||||||
.slice()
|
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
|
||||||
.map(toTemplateMenuItem)
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
const rootUntaggedItems = untaggedTemplates
|
|
||||||
.slice()
|
|
||||||
.sort((a, b) => a.name.localeCompare(b.name))
|
|
||||||
.map(toTemplateMenuItem)
|
|
||||||
|
|
||||||
return [...rootUntaggedItems, ...taggedMenuItems]
|
|
||||||
}, [documentTemplates])
|
|
||||||
|
|
||||||
// If no templates available, show disabled state
|
// If no templates available, show disabled state
|
||||||
if (documentTemplates.length === 0 && !loading) {
|
if (documentTemplates.length === 0 && !loading) {
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -278,11 +278,7 @@ const ObjectProperty = ({
|
|||||||
return (
|
return (
|
||||||
<Tree
|
<Tree
|
||||||
treeData={value}
|
treeData={value}
|
||||||
fieldNames={{
|
fieldNames={{ title: 'title', key: 'value', children: 'children' }}
|
||||||
title: 'title',
|
|
||||||
key: 'value',
|
|
||||||
children: 'children'
|
|
||||||
}}
|
|
||||||
height={320}
|
height={320}
|
||||||
virtual
|
virtual
|
||||||
defaultExpandAll={false}
|
defaultExpandAll={false}
|
||||||
@ -535,8 +531,6 @@ const ObjectProperty = ({
|
|||||||
case 'state': {
|
case 'state': {
|
||||||
if (value && value?.type) {
|
if (value && value?.type) {
|
||||||
return <StateDisplay {...rest} state={value} />
|
return <StateDisplay {...rest} state={value} />
|
||||||
} else if (value && value?.message) {
|
|
||||||
return <Text {...textParams}>{value.message}</Text>
|
|
||||||
} else {
|
} else {
|
||||||
return (
|
return (
|
||||||
<Text type='secondary' {...textParams}>
|
<Text type='secondary' {...textParams}>
|
||||||
|
|||||||
@ -23,13 +23,10 @@ const UserNotifierToggle = memo(({
|
|||||||
toggleUserNotifier,
|
toggleUserNotifier,
|
||||||
editUserNotifier,
|
editUserNotifier,
|
||||||
fetchUserNotifiersForObject,
|
fetchUserNotifiersForObject,
|
||||||
fetchAllUserNotifiersForObject,
|
fetchAllUserNotifiersForObject
|
||||||
connected,
|
|
||||||
subscribeToObjectUpdates,
|
|
||||||
subscribeToObjectTypeUpdates
|
|
||||||
} = useContext(ApiServerContext)
|
} = useContext(ApiServerContext)
|
||||||
const { userProfile, token, authInitialized } = useContext(AuthContext)
|
const { userProfile, token, authInitialized } = useContext(AuthContext)
|
||||||
const [currentUserNotifier, setCurrentUserNotifier] = useState(null)
|
const [isNotifying, setIsNotifying] = useState(false)
|
||||||
const [loading, setLoading] = useState(false)
|
const [loading, setLoading] = useState(false)
|
||||||
const [initialLoad, setInitialLoad] = useState(true)
|
const [initialLoad, setInitialLoad] = useState(true)
|
||||||
const [allNotifiers, setAllNotifiers] = useState([])
|
const [allNotifiers, setAllNotifiers] = useState([])
|
||||||
@ -37,32 +34,8 @@ const UserNotifierToggle = memo(({
|
|||||||
const [popoverLoading, setPopoverLoading] = useState(false)
|
const [popoverLoading, setPopoverLoading] = useState(false)
|
||||||
const [emailTogglingId, setEmailTogglingId] = useState(null)
|
const [emailTogglingId, setEmailTogglingId] = useState(null)
|
||||||
|
|
||||||
const subscribedIdsRef = useRef([])
|
|
||||||
const unsubscribesRef = useRef([])
|
|
||||||
const subscribeToObjectTypeUpdatesRef = useRef(null)
|
|
||||||
const updateEventHandlerRef = useRef()
|
|
||||||
const popoverOpenRef = useRef(popoverOpen)
|
|
||||||
popoverOpenRef.current = popoverOpen
|
|
||||||
|
|
||||||
const objectId = objectData?._id
|
const objectId = objectData?._id
|
||||||
const authReady = Boolean(token && authInitialized)
|
const authReady = Boolean(token && authInitialized)
|
||||||
const isNotifying = Boolean(currentUserNotifier)
|
|
||||||
|
|
||||||
const subscriptionFilter = useMemo(
|
|
||||||
() => ({
|
|
||||||
object: objectId,
|
|
||||||
objectType: type
|
|
||||||
}),
|
|
||||||
[objectId, type]
|
|
||||||
)
|
|
||||||
|
|
||||||
const notifierMatchesFilter = useCallback(
|
|
||||||
(notifier) => {
|
|
||||||
const objectRef = notifier?.object?._id ?? notifier?.object
|
|
||||||
return objectRef === objectId && notifier?.objectType === type
|
|
||||||
},
|
|
||||||
[objectId, type]
|
|
||||||
)
|
|
||||||
|
|
||||||
const apiRef = useRef({
|
const apiRef = useRef({
|
||||||
fetchUserNotifiersForObject,
|
fetchUserNotifiersForObject,
|
||||||
@ -73,196 +46,42 @@ const UserNotifierToggle = memo(({
|
|||||||
fetchAllUserNotifiersForObject
|
fetchAllUserNotifiersForObject
|
||||||
}
|
}
|
||||||
|
|
||||||
const loadNotifierState = useCallback(
|
useEffect(() => {
|
||||||
async (silent = false) => {
|
|
||||||
if (!authReady || !objectId || !type) return
|
if (!authReady || !objectId || !type) return
|
||||||
|
|
||||||
if (!silent) {
|
const loadNotifierState = async () => {
|
||||||
setInitialLoad(true)
|
setInitialLoad(true)
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const { data } = await apiRef.current.fetchUserNotifiersForObject(
|
const { data } = await apiRef.current.fetchUserNotifiersForObject(objectId, type)
|
||||||
objectId,
|
setIsNotifying(data?.length > 0)
|
||||||
type
|
|
||||||
)
|
|
||||||
setCurrentUserNotifier(data?.[0] ?? null)
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching user notifier state:', error)
|
console.error('Error fetching user notifier state:', error)
|
||||||
} finally {
|
} finally {
|
||||||
if (!silent) {
|
|
||||||
setInitialLoad(false)
|
setInitialLoad(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
[authReady, objectId, type]
|
|
||||||
)
|
|
||||||
|
|
||||||
const loadAllNotifiers = useCallback(
|
loadNotifierState()
|
||||||
async (silent = false) => {
|
}, [authReady, objectId, type])
|
||||||
if (!authReady || !objectId || !type) return
|
|
||||||
|
|
||||||
if (!silent) {
|
useEffect(() => {
|
||||||
|
if (!authReady || !objectId || !type || !popoverOpen) return
|
||||||
|
|
||||||
|
const loadAllNotifiers = async () => {
|
||||||
setPopoverLoading(true)
|
setPopoverLoading(true)
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const { data } = await apiRef.current.fetchAllUserNotifiersForObject(
|
const { data } = await apiRef.current.fetchAllUserNotifiersForObject(objectId, type)
|
||||||
objectId,
|
|
||||||
type
|
|
||||||
)
|
|
||||||
setAllNotifiers(data || [])
|
setAllNotifiers(data || [])
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching all user notifiers:', error)
|
console.error('Error fetching all user notifiers:', error)
|
||||||
setAllNotifiers([])
|
setAllNotifiers([])
|
||||||
} finally {
|
} finally {
|
||||||
if (!silent) {
|
|
||||||
setPopoverLoading(false)
|
setPopoverLoading(false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
[authReady, objectId, type]
|
|
||||||
)
|
|
||||||
|
|
||||||
const loadNotifierStateRef = useRef(loadNotifierState)
|
|
||||||
loadNotifierStateRef.current = loadNotifierState
|
|
||||||
|
|
||||||
const loadAllNotifiersRef = useRef(loadAllNotifiers)
|
|
||||||
loadAllNotifiersRef.current = loadAllNotifiers
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
loadNotifierState()
|
|
||||||
}, [loadNotifierState])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!popoverOpen) return
|
|
||||||
loadAllNotifiers()
|
loadAllNotifiers()
|
||||||
}, [popoverOpen, loadAllNotifiers])
|
}, [authReady, objectId, type, popoverOpen])
|
||||||
|
|
||||||
const updateEventHandler = useCallback(
|
|
||||||
(id, updatedData) => {
|
|
||||||
setAllNotifiers((prev) => {
|
|
||||||
const existing = prev.find((notifier) => notifier._id === id)
|
|
||||||
const merged = existing
|
|
||||||
? { ...existing, ...updatedData }
|
|
||||||
: { _id: id, ...updatedData }
|
|
||||||
|
|
||||||
if (!notifierMatchesFilter(merged)) {
|
|
||||||
return prev.filter((notifier) => notifier._id !== id)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (existing) {
|
|
||||||
return prev.map((notifier) =>
|
|
||||||
notifier._id === id ? merged : notifier
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return [...prev, merged]
|
|
||||||
})
|
|
||||||
|
|
||||||
setCurrentUserNotifier((prev) => {
|
|
||||||
if (prev?._id === id) {
|
|
||||||
const merged = { ...prev, ...updatedData }
|
|
||||||
return notifierMatchesFilter(merged) ? merged : null
|
|
||||||
}
|
|
||||||
|
|
||||||
const userRef = updatedData?.user?._id ?? updatedData?.user
|
|
||||||
if (
|
|
||||||
userRef === userProfile?._id &&
|
|
||||||
notifierMatchesFilter({ _id: id, ...updatedData })
|
|
||||||
) {
|
|
||||||
return { _id: id, ...updatedData }
|
|
||||||
}
|
|
||||||
|
|
||||||
return prev
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[notifierMatchesFilter, userProfile?._id]
|
|
||||||
)
|
|
||||||
|
|
||||||
updateEventHandlerRef.current = updateEventHandler
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (connected !== true || !objectId || !type) return
|
|
||||||
|
|
||||||
const unsubscribe = subscribeToObjectTypeUpdates(
|
|
||||||
'userNotifier',
|
|
||||||
subscriptionFilter,
|
|
||||||
() => {
|
|
||||||
loadNotifierStateRef.current(true)
|
|
||||||
if (popoverOpenRef.current) {
|
|
||||||
loadAllNotifiersRef.current(true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
subscribeToObjectTypeUpdatesRef.current = unsubscribe
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if (unsubscribe) unsubscribe()
|
|
||||||
if (subscribeToObjectTypeUpdatesRef.current === unsubscribe) {
|
|
||||||
subscribeToObjectTypeUpdatesRef.current = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [connected, subscriptionFilter, subscribeToObjectTypeUpdates, objectId, type])
|
|
||||||
|
|
||||||
const subscribedNotifierIds = useMemo(() => {
|
|
||||||
const ids = new Set(
|
|
||||||
allNotifiers.map((notifier) => notifier._id).filter(Boolean)
|
|
||||||
)
|
|
||||||
if (currentUserNotifier?._id) {
|
|
||||||
ids.add(currentUserNotifier._id)
|
|
||||||
}
|
|
||||||
return [...ids]
|
|
||||||
}, [allNotifiers, currentUserNotifier])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (connected !== true) return
|
|
||||||
|
|
||||||
const newNotifierIds = subscribedNotifierIds.filter(
|
|
||||||
(id) => !subscribedIdsRef.current.includes(id)
|
|
||||||
)
|
|
||||||
|
|
||||||
newNotifierIds.forEach((itemId) => {
|
|
||||||
const unsubscribe = subscribeToObjectUpdates(
|
|
||||||
itemId?.toLowerCase(),
|
|
||||||
'userNotifier',
|
|
||||||
(updateData) => updateEventHandlerRef.current(itemId, updateData)
|
|
||||||
)
|
|
||||||
subscribedIdsRef.current.push(itemId)
|
|
||||||
if (unsubscribe) {
|
|
||||||
unsubscribesRef.current.push(unsubscribe)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
const notifierIdsToUnsubscribe = subscribedIdsRef.current.filter(
|
|
||||||
(id) => !subscribedNotifierIds.includes(id)
|
|
||||||
)
|
|
||||||
|
|
||||||
notifierIdsToUnsubscribe.forEach((itemId) => {
|
|
||||||
const index = subscribedIdsRef.current.indexOf(itemId)
|
|
||||||
if (index > -1) {
|
|
||||||
subscribedIdsRef.current.splice(index, 1)
|
|
||||||
const unsubscribe = unsubscribesRef.current[index]
|
|
||||||
if (unsubscribe) {
|
|
||||||
unsubscribe()
|
|
||||||
}
|
|
||||||
unsubscribesRef.current.splice(index, 1)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, [subscribedNotifierIds, connected, subscribeToObjectUpdates])
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
return () => {
|
|
||||||
unsubscribesRef.current.forEach((unsubscribe) => {
|
|
||||||
if (unsubscribe) unsubscribe()
|
|
||||||
})
|
|
||||||
unsubscribesRef.current = []
|
|
||||||
subscribedIdsRef.current = []
|
|
||||||
|
|
||||||
if (subscribeToObjectTypeUpdatesRef.current) {
|
|
||||||
subscribeToObjectTypeUpdatesRef.current()
|
|
||||||
subscribeToObjectTypeUpdatesRef.current = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [])
|
|
||||||
|
|
||||||
const handleClick = useCallback(async () => {
|
const handleClick = useCallback(async () => {
|
||||||
if (!authReady || !objectId || !type || loading) return
|
if (!authReady || !objectId || !type || loading) return
|
||||||
@ -270,12 +89,7 @@ const UserNotifierToggle = memo(({
|
|||||||
setLoading(true)
|
setLoading(true)
|
||||||
try {
|
try {
|
||||||
const enabled = await toggleUserNotifier(objectId, type)
|
const enabled = await toggleUserNotifier(objectId, type)
|
||||||
if (enabled) {
|
setIsNotifying(enabled)
|
||||||
const { data } = await fetchUserNotifiersForObject(objectId, type)
|
|
||||||
setCurrentUserNotifier(data?.[0] ?? null)
|
|
||||||
} else {
|
|
||||||
setCurrentUserNotifier(null)
|
|
||||||
}
|
|
||||||
if (popoverOpen) {
|
if (popoverOpen) {
|
||||||
const { data } = await fetchAllUserNotifiersForObject(objectId, type)
|
const { data } = await fetchAllUserNotifiersForObject(objectId, type)
|
||||||
setAllNotifiers(data || [])
|
setAllNotifiers(data || [])
|
||||||
@ -291,7 +105,7 @@ const UserNotifierToggle = memo(({
|
|||||||
} finally {
|
} finally {
|
||||||
setLoading(false)
|
setLoading(false)
|
||||||
}
|
}
|
||||||
}, [authReady, objectId, type, loading, popoverOpen, toggleUserNotifier, fetchUserNotifiersForObject, fetchAllUserNotifiersForObject])
|
}, [authReady, objectId, type, loading, popoverOpen, toggleUserNotifier, fetchAllUserNotifiersForObject])
|
||||||
|
|
||||||
const getUserDisplayName = useCallback((user) => {
|
const getUserDisplayName = useCallback((user) => {
|
||||||
if (!user) return 'Unknown'
|
if (!user) return 'Unknown'
|
||||||
@ -318,11 +132,6 @@ const UserNotifierToggle = memo(({
|
|||||||
n._id === item._id ? { ...n, email: result.email ?? newEmail } : n
|
n._id === item._id ? { ...n, email: result.email ?? newEmail } : n
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
setCurrentUserNotifier((prev) =>
|
|
||||||
prev?._id === item._id
|
|
||||||
? { ...prev, email: result.email ?? newEmail }
|
|
||||||
: prev
|
|
||||||
)
|
|
||||||
message.success(
|
message.success(
|
||||||
(result.email ?? newEmail)
|
(result.email ?? newEmail)
|
||||||
? 'Email notifications enabled'
|
? 'Email notifications enabled'
|
||||||
|
|||||||
@ -2408,8 +2408,8 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
if (!userProfile?._id) return { data: [] }
|
if (!userProfile?._id) return { data: [] }
|
||||||
const result = await fetchObjects('userNotifier', {
|
const result = await fetchObjects('userNotifier', {
|
||||||
filter: {
|
filter: {
|
||||||
user: userProfile._id,
|
'user._id': userProfile._id,
|
||||||
object: objectId,
|
'object._id': objectId,
|
||||||
objectType
|
objectType
|
||||||
},
|
},
|
||||||
limit: 1
|
limit: 1
|
||||||
@ -2420,7 +2420,7 @@ const ApiServerProvider = ({ children }) => {
|
|||||||
const fetchAllUserNotifiersForObject = async (objectId, objectType) => {
|
const fetchAllUserNotifiersForObject = async (objectId, objectType) => {
|
||||||
const result = await fetchObjects('userNotifier', {
|
const result = await fetchObjects('userNotifier', {
|
||||||
filter: {
|
filter: {
|
||||||
object: objectId,
|
'object._id': objectId,
|
||||||
objectType
|
objectType
|
||||||
},
|
},
|
||||||
limit: 100
|
limit: 100
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user