-
Notifications
You must be signed in to change notification settings - Fork 20
775 account page notifications #825
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
ekraffmiller
wants to merge
51
commits into
develop
Choose a base branch
from
775-account-page-notifications
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
e8df50a
feat: add unread notifications count to Header, getTranslatedNotifica…
ekraffmiller 12ba0f0
added Notification translation functions and tests
ekraffmiller 000634f
add call to js-dataverse use case, refactor NotificationsHelper.tsx
ekraffmiller 9e2ccbe
resolve merge conflicts
ekraffmiller ceff9f6
Merge branch 'develop' into 775-account-page-notifications
ekraffmiller eb5f8d7
feat: add NotificationsSection.tsx to Account.tsx
ekraffmiller f4d1757
fix: welcome notification
ekraffmiller a17b0cf
feat: update NavBarDropdown to accept JSX title
ekraffmiller 0830d43
add selection logic for delete/read/unread
ekraffmiller 3a171cd
add Buttons from design system
ekraffmiller f4eba03
use NotificationsContext to share state between Header and Notificati…
ekraffmiller 8015723
add useEffect() to fix timing of fetchNotifications
ekraffmiller de20c3b
remove select checboxes, replace with X icon for marking as read
ekraffmiller e63d60f
show only unread notifications, add useMemo to avoid rerenders.
ekraffmiller 330f3e0
add polling, use lodash.isEqual() to avoid rerenders
ekraffmiller 6493436
fix ingest message, add translations
ekraffmiller 73b9628
update NotificationsSection.spec.tsx
ekraffmiller 1dba4ff
update Header.spec.tsx
ekraffmiller 9c825c6
update LoggedInHeaderActions.spec.tsx
ekraffmiller 3877599
fix tests in NotificationsHelper.spec.ts
ekraffmiller e001685
fix tests in Account.spec.ts
ekraffmiller bb5062c
add timestamp, fix welcome message
ekraffmiller 6ff1949
add NotificationProvider to Account.spec.tsx
ekraffmiller 8f4971c
Account.spec.tsx: notifications tab is enabled
ekraffmiller 41401f9
attempt to fix flaky test
ekraffmiller 7be7804
increase code coverage in NotificationsHelper.spec.ts
ekraffmiller aebb448
resolve merge conflicts
ekraffmiller 4b43ae1
feat: improve badge and add pill prop to design system
g-saracca 0345215
feat: more styles improved
g-saracca bc6e614
resolve merge conflicts
ekraffmiller 4820100
fix: add lodash dependency
ekraffmiller 59c3b49
fix: add lodash-es dependency, add NotificationContext to stories
ekraffmiller a8db8f5
fix: Header.stories.tsx
ekraffmiller 56fcc68
increase test coverage
ekraffmiller 0f4ee30
increase test coverage
ekraffmiller 5d9a468
fix requestFileAccess notification
ekraffmiller 8cad171
display DatasetMentioned notification type with additionalInfo
ekraffmiller 9f7f892
resolve merge conflicts
ekraffmiller 8ab7cd0
call getAllNotificationsByUser() with unreadOnly = true
ekraffmiller 5343c84
display unescaped text in notification translation
ekraffmiller 4b3e4cc
fix: unit test
ekraffmiller e1d5824
fix: display of additionalInfo
ekraffmiller 1609637
at timeout for marking as read
ekraffmiller 20c8fed
remove context, replace with custom hooks and externalStore
ekraffmiller 7ae2c4d
fix NotificationsSection.spec.tsx unit test
ekraffmiller 3f63ae4
fix unit tests
ekraffmiller afdf51c
resolve merge conflicts
ekraffmiller 62b7e3e
fix: increase wait for download in e2e test
ekraffmiller 60c61f0
fix: lint errors, remove debug statements
ekraffmiller 7493817
fix: set user to null after logout
ekraffmiller 9899302
updates from review
ekraffmiller File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or 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 hidden or 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 |
|---|---|---|
|
|
@@ -28,6 +28,10 @@ See [Conventional Commits](https://conventionalcommits.org) for commit guideline | |
| - Fix word wrapping in options list to prevent overflow and ensure long text is displayed correctly. | ||
| - **ButtonGroup:** | ||
| - Fix styles for vertical button groups when using tooltips. | ||
| - **Badge:**: | ||
| - Add `pill` prop to allow pill-shaped badges. | ||
| - Add `dataTestId` prop to facilitate testing. | ||
| - Add `className` prop to allow custom styling. | ||
|
|
||
| # [2.0.2](https://github.com/IQSS/dataverse-frontend/compare/@iqss/[email protected]...@iqss/[email protected]) (2024-06-23) | ||
|
|
||
|
|
||
This file contains hidden or 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
4 changes: 2 additions & 2 deletions
4
packages/design-system/src/lib/components/navbar/navbar-dropdown/NavbarDropdown.tsx
This file contains hidden or 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,27 @@ | ||
| // store/updateFlagStore.ts | ||
| type Listener = () => void | ||
|
|
||
| class NeedsUpdateStore { | ||
| private needsUpdate = false | ||
| private listeners = new Set<Listener>() | ||
|
|
||
| getSnapshot = () => this.needsUpdate | ||
|
|
||
| subscribe = (callback: Listener) => { | ||
| this.listeners.add(callback) | ||
| return () => this.listeners.delete(callback) | ||
| } | ||
|
|
||
| setNeedsUpdate(value: boolean) { | ||
| if (this.needsUpdate !== value) { | ||
| this.needsUpdate = value | ||
| this.emit() | ||
| } | ||
| } | ||
|
|
||
| private emit() { | ||
| this.listeners.forEach((listener) => listener()) | ||
| } | ||
| } | ||
|
|
||
| export const needsUpdateStore = new NeedsUpdateStore() |
This file contains hidden or 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,31 @@ | ||
| // hooks/useNeedsUpdate.ts | ||
| import { useSyncExternalStore } from 'react' | ||
| type Listener = () => void | ||
|
|
||
| class NeedsUpdateStore { | ||
| private needsUpdate = false | ||
| private listeners = new Set<Listener>() | ||
|
|
||
| getSnapshot = () => this.needsUpdate | ||
|
|
||
| subscribe = (callback: Listener) => { | ||
| this.listeners.add(callback) | ||
| return () => this.listeners.delete(callback) | ||
| } | ||
|
|
||
| setNeedsUpdate(value: boolean) { | ||
| if (this.needsUpdate !== value) { | ||
| this.needsUpdate = value | ||
| this.emit() | ||
| } | ||
| } | ||
|
|
||
| private emit() { | ||
| this.listeners.forEach((listener) => listener()) | ||
| } | ||
| } | ||
| const needsUpdateStore = new NeedsUpdateStore() | ||
|
|
||
| export function useNeedsUpdate() { | ||
| return useSyncExternalStore(needsUpdateStore.subscribe, needsUpdateStore.getSnapshot) | ||
| } | ||
This file contains hidden or 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,72 @@ | ||
| import { useCallback, useEffect, useState } from 'react' | ||
| import { useSession } from '@/sections/session/SessionContext' | ||
| import { Notification } from '@/notifications/domain/models/Notification' | ||
| import { NotificationRepository } from '@/notifications/domain/repositories/NotificationRepository' | ||
| import { getAllNotificationsByUser } from '@/notifications/domain/useCases/getAllNotificationsByUser' | ||
|
|
||
| const POLLING_NOTIFICATIONS_INTERVAL_TIME = 30_000 | ||
|
|
||
| export function useNotifications(repository: NotificationRepository) { | ||
| const [notifications, setNotifications] = useState<Notification[]>([]) | ||
| const [isLoading, setIsLoading] = useState(true) | ||
| const [error, setError] = useState<string | null>(null) | ||
| const { user } = useSession() | ||
|
|
||
| const fetchNotifications = useCallback(async () => { | ||
| try { | ||
| const fetched = await getAllNotificationsByUser(repository) | ||
| setError(null) | ||
| setNotifications(fetched) | ||
| } catch (err) { | ||
| const message = err instanceof Error ? err.message : 'Failed to fetch notifications' | ||
| setError(message) | ||
| } finally { | ||
| setIsLoading(false) | ||
| } | ||
| }, [repository]) | ||
|
|
||
| useEffect(() => { | ||
| if (!user) return | ||
|
|
||
| void fetchNotifications() | ||
|
|
||
| const interval = setInterval(() => { | ||
| void fetchNotifications() | ||
| }, POLLING_NOTIFICATIONS_INTERVAL_TIME) | ||
|
|
||
| return () => clearInterval(interval) | ||
| }, [fetchNotifications, user]) | ||
|
|
||
| const markAsRead = async (ids: number[]) => { | ||
| setNotifications((prev) => | ||
| prev.map((n) => (ids.includes(n.id) ? { ...n, displayAsRead: true } : n)) | ||
| ) | ||
| try { | ||
| await Promise.all(ids.map((id) => repository.markNotificationAsRead(id))) | ||
| setError(null) | ||
| } catch (err) { | ||
| const message = err instanceof Error ? err.message : 'Failed to mark as read' | ||
| setError(message) | ||
| } | ||
| } | ||
|
|
||
| const deleteMany = async (ids: number[]) => { | ||
| setNotifications((prev) => prev.filter((n) => !ids.includes(n.id))) | ||
| try { | ||
| await Promise.all(ids.map((id) => repository.deleteNotification(id))) | ||
| setError(null) | ||
| } catch (err) { | ||
| const message = err instanceof Error ? err.message : 'Failed to delete notifications' | ||
| setError(message) | ||
| } | ||
| } | ||
|
|
||
| return { | ||
| notifications, | ||
| isLoading, | ||
| error, | ||
| refetch: fetchNotifications, | ||
| markAsRead, | ||
| deleteMany | ||
| } | ||
| } |
This file contains hidden or 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,39 @@ | ||
| import { useCallback, useEffect, useState } from 'react' | ||
| import { needsUpdateStore } from './needsUpdateStore' | ||
| import { NotificationRepository } from '@/notifications/domain/repositories/NotificationRepository' | ||
| import { User } from '@/users/domain/models/User' | ||
| import { useNeedsUpdate } from '@/notifications/domain/hooks/useNeedsUpdate' | ||
| import { getUnreadNotificationsCount } from '@/notifications/domain/useCases/getUnreadNotificationsCount' | ||
|
|
||
| const POLLING_INTERVAL = 30000 // 30 seconds | ||
ekraffmiller marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| export function useUnreadCount(user: User, notificationRepository: NotificationRepository) { | ||
| const [unreadCount, setUnreadCount] = useState(0) | ||
|
|
||
| const needsUpdate = useNeedsUpdate() | ||
| const fetchUnread = useCallback(async () => { | ||
| if (user) { | ||
ekraffmiller marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| const count = await getUnreadNotificationsCount(notificationRepository) | ||
| setUnreadCount(count) | ||
| } | ||
| needsUpdateStore.setNeedsUpdate(false) | ||
| }, [user, notificationRepository]) | ||
| useEffect(() => { | ||
| if (needsUpdate) { | ||
| void fetchUnread() | ||
| } | ||
| }, [needsUpdate, fetchUnread, notificationRepository]) | ||
| // Polling trigger | ||
| useEffect(() => { | ||
| const interval = setInterval(() => { | ||
| void fetchUnread() | ||
| }, POLLING_INTERVAL) | ||
|
|
||
| return () => clearInterval(interval) | ||
| }, [fetchUnread, notificationRepository]) | ||
|
|
||
| useEffect(() => { | ||
| void fetchUnread() // run once when the component mounts | ||
| }, [fetchUnread]) | ||
|
|
||
| return unreadCount | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about including the
needsUpdateStore.tslogic in this same file?Just saying to avoid one more extra file..