Skip to content

Commit 541e892

Browse files
committed
feat: display as read
1 parent e93174e commit 541e892

File tree

13 files changed

+194
-26
lines changed

13 files changed

+194
-26
lines changed

docs/useCases.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ The different use cases currently available in the package are classified below,
9191
- [Notifications](#Notifications)
9292
- [Get All Notifications by User](#get-all-notifications-by-user)
9393
- [Delete Notification](#delete-notification)
94+
- [Get Unread Count](#get-unread-count)
95+
- [Mark As Read](#mark-as-read)
9496
- [Search](#Search)
9597
- [Get Search Services](#get-search-services)
9698

@@ -2143,6 +2145,48 @@ deleteNotification.execute(notificationId: number).then(() => {
21432145

21442146
_See [use case](../src/notifications/domain/useCases/DeleteNotification.ts) implementation_.
21452147

2148+
#### Get Unread Count
2149+
2150+
Returns the number of unread notifications for the current authenticated user.
2151+
2152+
##### Example call:
2153+
2154+
```typescript
2155+
import { getUnreadCount } from '@iqss/dataverse-client-javascript'
2156+
2157+
/* ... */
2158+
2159+
getUnreadCount.execute().then((count: number) => {
2160+
console.log(`You have ${count} unread notifications`)
2161+
})
2162+
2163+
/* ... */
2164+
```
2165+
2166+
_See [use case](../src/notifications/domain/useCases/GetUnreadCount.ts) implementation_.
2167+
2168+
#### Mark As Read
2169+
2170+
Marks a specific notification as read for the current authenticated user. This operation is idempotent - marking an already-read notification as read will not cause an error.
2171+
2172+
##### Example call:
2173+
2174+
```typescript
2175+
import { markAsRead } from '@iqss/dataverse-client-javascript'
2176+
2177+
/* ... */
2178+
2179+
const notificationId = 123
2180+
2181+
markAsRead.execute(notificationId).then(() => {
2182+
console.log('Notification marked as read')
2183+
})
2184+
2185+
/* ... */
2186+
```
2187+
2188+
_See [use case](../src/notifications/domain/useCases/MarkAsRead.ts) implementation_.
2189+
21462190
## Search
21472191

21482192
#### Get Search Services

src/notifications/domain/models/Notification.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ export interface Notification {
4848
subjectText?: string
4949
messageText?: string
5050
sentTimestamp: string
51-
displayAsRead?: boolean
51+
displayAsRead: boolean
5252
installationBrandName?: string
5353
userGuidesBaseUrl?: string
5454
userGuidesVersion?: string

src/notifications/domain/repositories/INotificationsRepository.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,6 @@ import { Notification } from '../models/Notification'
33
export interface INotificationsRepository {
44
getAllNotificationsByUser(inAppNotificationFormat?: boolean): Promise<Notification[]>
55
deleteNotification(notificationId: number): Promise<void>
6+
getUnreadCount(): Promise<number>
7+
markAsRead(notificationId: number): Promise<void>
68
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { INotificationsRepository } from '../repositories/INotificationsRepository'
3+
4+
export class GetUnreadCount implements UseCase<number> {
5+
private notificationsRepository: INotificationsRepository
6+
7+
constructor(notificationsRepository: INotificationsRepository) {
8+
this.notificationsRepository = notificationsRepository
9+
}
10+
11+
async execute(): Promise<number> {
12+
return await this.notificationsRepository.getUnreadCount()
13+
}
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { UseCase } from '../../../core/domain/useCases/UseCase'
2+
import { INotificationsRepository } from '../repositories/INotificationsRepository'
3+
4+
export class MarkAsRead implements UseCase<void> {
5+
private notificationsRepository: INotificationsRepository
6+
7+
constructor(notificationsRepository: INotificationsRepository) {
8+
this.notificationsRepository = notificationsRepository
9+
}
10+
11+
async execute(notificationId: number): Promise<void> {
12+
return await this.notificationsRepository.markAsRead(notificationId)
13+
}
14+
}

src/notifications/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import { NotificationsRepository } from './infra/repositories/NotificationsRepository'
22
import { GetAllNotificationsByUser } from './domain/useCases/GetAllNotificationsByUser'
33
import { DeleteNotification } from './domain/useCases/DeleteNotification'
4+
import { GetUnreadCount } from './domain/useCases/GetUnreadCount'
5+
import { MarkAsRead } from './domain/useCases/MarkAsRead'
46

57
const notificationsRepository = new NotificationsRepository()
68

79
const getAllNotificationsByUser = new GetAllNotificationsByUser(notificationsRepository)
810
const deleteNotification = new DeleteNotification(notificationsRepository)
11+
const getUnreadCount = new GetUnreadCount(notificationsRepository)
12+
const markAsRead = new MarkAsRead(notificationsRepository)
913

10-
export { getAllNotificationsByUser, deleteNotification }
14+
export { getAllNotificationsByUser, deleteNotification, getUnreadCount, markAsRead }
1115

1216
export { Notification, NotificationType, RoleAssignment } from './domain/models/Notification'

src/notifications/infra/repositories/NotificationsRepository.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,23 @@ export class NotificationsRepository extends ApiRepository implements INotificat
2424
return this.doDelete(
2525
this.buildApiEndpoint(this.notificationsResourceName, notificationId.toString())
2626
)
27-
.then(() => {})
27+
.then(() => undefined)
2828
.catch((error) => {
2929
throw error
3030
})
3131
}
32+
33+
public async getUnreadCount(): Promise<number> {
34+
return this.doGet(
35+
this.buildApiEndpoint(this.notificationsResourceName, 'unreadCount'),
36+
true
37+
).then((response) => response.data.data.unreadCount as number)
38+
}
39+
40+
public async markAsRead(notificationId: number): Promise<void> {
41+
return this.doPut(
42+
this.buildApiEndpoint(this.notificationsResourceName, 'markAsRead', notificationId),
43+
{}
44+
).then(() => undefined)
45+
}
3246
}

test/functional/notifications/GetAllNotificationsByUser.test.ts

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,5 @@ describe('execute', () => {
3333
expect(notifications[0]).toHaveProperty('type')
3434
expect(notifications[0]).toHaveProperty('sentTimestamp')
3535
expect(notifications[0]).toHaveProperty('displayAsRead')
36-
expect(notifications[0]).toHaveProperty('roleAssignments')
37-
expect(notifications[0].roleAssignments).toBeDefined()
38-
expect(notifications[0].roleAssignments?.length).toBeGreaterThan(0)
39-
expect(notifications[0].roleAssignments?.[0]).toHaveProperty('roleName', 'Admin')
40-
expect(notifications[0].roleAssignments?.[0]).toHaveProperty('assignee', '@dataverseAdmin')
41-
expect(notifications[0].roleAssignments?.[0]).toHaveProperty('roleId', 1)
42-
expect(notifications[0].roleAssignments?.[0]).toHaveProperty('definitionPointId', 1)
4336
})
4437
})
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { getUnreadCount } from '../../../src/notifications'
2+
3+
describe('GetUnreadCount', () => {
4+
test('should return unread count', async () => {
5+
const unreadCount = await getUnreadCount.execute()
6+
7+
expect(typeof unreadCount).toBe('number')
8+
expect(unreadCount).toBeGreaterThanOrEqual(0)
9+
})
10+
})
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

0 commit comments

Comments
 (0)