Skip to content
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

fix(service-portal): Filtering mailbox documents #16219

Merged
merged 9 commits into from
Oct 25, 2024
1 change: 1 addition & 0 deletions libs/api/domains/documents/src/lib/document.types.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { FileType } from './models/v2/documentContent.model'

export const HEALTH_CATEGORY_ID = '3'
export const LAW_AND_ORDER_CATEGORY_ID = '12'

export class DocumentTypeFilter {
senderName!: string
Expand Down
15 changes: 10 additions & 5 deletions libs/api/domains/documents/src/lib/documentV2.resolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { DocumentV2MarkAllMailAsRead } from './models/v2/markAllMailAsRead.model
import type { Locale } from '@island.is/shared/types'
import { DocumentConfirmActionsInput } from './models/v2/confirmActions.input'
import { DocumentConfirmActions } from './models/v2/confirmActions.model'
import { isDefined } from '@island.is/shared/utils'

const LOG_CATEGORY = 'documents-resolver'

Expand Down Expand Up @@ -95,9 +96,8 @@ export class DocumentResolverV2 {
@CurrentUser() user: User,
): Promise<PaginatedDocuments> {
const ffEnabled = await this.getFeatureFlag()
if (ffEnabled)
return this.documentServiceV2.listDocumentsV3(user.nationalId, input)
return this.documentServiceV2.listDocuments(user.nationalId, input)
if (ffEnabled) return this.documentServiceV2.listDocumentsV3(user, input)
return this.documentServiceV2.listDocuments(user, input)
}

@Scopes(DocumentsScope.main)
Expand All @@ -121,8 +121,13 @@ export class DocumentResolverV2 {
}

@ResolveField('categories', () => [Category])
documentCategories(@CurrentUser() user: User): Promise<Array<Category>> {
return this.documentServiceV2.getCategories(user.nationalId)
async documentCategories(
@CurrentUser() user: User,
): Promise<Array<Category>> {
const categories = await this.documentServiceV2.getCategories(user)
if (!isDefined(categories)) {
return []
} else return categories
}

@ResolveField('senders', () => [Sender])
Expand Down
108 changes: 71 additions & 37 deletions libs/api/domains/documents/src/lib/documentV2.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ import { DocumentsInput } from './models/v2/documents.input'
import { PaperMailPreferences } from './models/v2/paperMailPreferences.model'
import { Sender } from './models/v2/sender.model'
import { FileType } from './models/v2/documentContent.model'
import { HEALTH_CATEGORY_ID } from './document.types'
import { HEALTH_CATEGORY_ID, LAW_AND_ORDER_CATEGORY_ID } from './document.types'
import { Type } from './models/v2/type.model'
import { DownloadServiceConfig } from '@island.is/nest/config'
import { DocumentV2MarkAllMailAsRead } from './models/v2/markAllMailAsRead.model'
import type { User } from '@island.is/auth-nest-tools'
import { AuthDelegationType } from '@island.is/shared/types'
import { getBirthday } from './helpers/getBirthday'
import differceInYears from 'date-fns/differenceInYears'
disaerna marked this conversation as resolved.
Show resolved Hide resolved
import type { Locale } from '@island.is/shared/types'

const LOG_CATEGORY = 'documents-api-v2'
Expand Down Expand Up @@ -152,30 +156,29 @@ export class DocumentServiceV2 {
}

async listDocuments(
nationalId: string,
user: User,
input: DocumentsInput,
): Promise<PaginatedDocuments> {
//If a delegated user is viewing the mailbox, do not return any health related data
//Category is now "1,2,3,...,n"
const { categoryIds, ...restOfInput } = input
let mutableCategoryIds = categoryIds ?? []

if (input.isLegalGuardian) {
if (!mutableCategoryIds.length) {
mutableCategoryIds = (await this.getCategories(nationalId, true)).map(
(c) => c.id,
)
} else {
mutableCategoryIds = mutableCategoryIds.filter(
(c) => c === HEALTH_CATEGORY_ID,
)
if (!mutableCategoryIds.length) {
const filteredCategories = await this.getCategories(user)
if (isDefined(filteredCategories)) {
mutableCategoryIds = filteredCategories.map((c) => c.id)
}
}
// If categoryIds are provided, filter out correct data
else {
const hiddenCategoryIds = this.getHiddenCategoriesIDs(user)
mutableCategoryIds.filter((c) => !hiddenCategoryIds.includes(c))
}

const documents = await this.documentService.getDocumentList({
...restOfInput,
categoryId: mutableCategoryIds.join(),
nationalId,
nationalId: user.nationalId,
})

if (typeof documents?.totalCount !== 'number') {
Expand Down Expand Up @@ -215,30 +218,32 @@ export class DocumentServiceV2 {
}

async listDocumentsV3(
nationalId: string,
user: User,
input: DocumentsInput,
): Promise<PaginatedDocuments> {
//If a delegated user is viewing the mailbox, do not return any health related data
//Category is now "1,2,3,...,n"
const { categoryIds, ...restOfInput } = input
// If no categoryIds are provided, get all categories
let mutableCategoryIds = categoryIds ?? []

if (input.isLegalGuardian) {
if (!mutableCategoryIds.length) {
mutableCategoryIds = (await this.getCategories(nationalId, true)).map(
(c) => c.id,
)
} else {
mutableCategoryIds = mutableCategoryIds.filter(
(c) => c === HEALTH_CATEGORY_ID,
)
if (!mutableCategoryIds.length) {
const filteredCategories = await this.getCategories(user)
if (isDefined(filteredCategories)) {
mutableCategoryIds = filteredCategories.map((c) => c.id)
}
}
// If categoryIds are provided, filter out correct data
else {
const hiddenCategoryIds = this.getHiddenCategoriesIDs(user)
mutableCategoryIds.filter((c) => !hiddenCategoryIds.includes(c))
}

const documents = await this.documentService.getDocumentList({
...restOfInput,
categoryId: mutableCategoryIds.join(),
nationalId,
hiddenCategoryIds: this.getHiddenCategoriesIDs(user).join(),
nationalId: user.nationalId,
})

if (typeof documents?.totalCount !== 'number') {
Expand Down Expand Up @@ -268,7 +273,7 @@ export class DocumentServiceV2 {
.filter(isDefined) ?? []

return {
data: documentData,
data: documentData, // if empty after category filter then return null
totalCount: documents?.totalCount ?? 0,
unreadCount: documents?.unreadCount,
pageInfo: {
Expand All @@ -277,27 +282,32 @@ export class DocumentServiceV2 {
}
}

async getCategories(
nationalId: string,
filterHealth = false,
): Promise<Array<Category>> {
async getCategories(user: User): Promise<Array<Category> | null> {
const categories = await this.documentService.getCustomersCategories(
nationalId,
user.nationalId,
)

return (
const filterOutIds = this.getHiddenCategoriesIDs(user) ?? []

const filteredCategories =
categories.categories
?.map((c) => {
if (!c.id || (filterHealth && c.id === HEALTH_CATEGORY_ID)) {
if (
!c.id ||
(filterOutIds.length > 0 && filterOutIds.includes(c.id))
) {
return null
}
return {
id: c.id,
name: c.name,
} else {
return {
id: c.id,
name: c.name,
}
}
})
.filter(isDefined) ?? []
)
if (filteredCategories.length === 0) return null

return filteredCategories
}

async getTypes(nationalId: string): Promise<Array<Type>> {
Expand Down Expand Up @@ -513,4 +523,28 @@ export class DocumentServiceV2 {

return mapped
}

private getHiddenCategoriesIDs = (user: User) => {
const isDelegated = isDefined(user.delegationType)
if (!isDelegated) return []

const isLegalGuardian = user.delegationType?.includes(
AuthDelegationType.LegalGuardian,
)
const birthdate = getBirthday(user.nationalId)
const childAgeIs16OrOlder = birthdate
? differceInYears(new Date(), birthdate) > 15
: false

// Hide health data if user is a legal guardian and child is 16 or older
const hideHealthData = isLegalGuardian && childAgeIs16OrOlder
// Hide law and order data if user is delegated
// commented out until we have correct category for law and order files
const hideLawAndOrderData = isDelegated

return [
...(hideHealthData ? [HEALTH_CATEGORY_ID] : []),
...(hideLawAndOrderData ? [LAW_AND_ORDER_CATEGORY_ID] : []),
]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,4 @@ export class DocumentsInput {
@IsOptional()
@IsInt()
readonly pageSize?: number

@Field({ nullable: true })
@IsOptional()
@IsBoolean()
isLegalGuardian?: boolean
}
20 changes: 3 additions & 17 deletions libs/auth/react/src/lib/auth/Auth.state.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { User } from '@island.is/shared/types'
import { getBirthday } from '../utils/getBirthday'

export type AuthState =
| 'logged-out'
Expand Down Expand Up @@ -37,20 +36,6 @@ export const initialState: AuthReducerState = {
isAuthenticated: false,
}

// Add dateOfBirth Date object to user profile
const formatUser = (payload: User): User | null => {
const dateOfBirth = getBirthday(payload?.profile?.nationalId)

return {
...payload,
scopes: payload.scopes || [],
profile: {
...payload.profile,
dateOfBirth,
},
}
}

export const reducer = (
state: AuthReducerState,
action: Action,
Expand All @@ -64,15 +49,16 @@ export const reducer = (
case ActionType.SIGNIN_SUCCESS:
return {
...state,
userInfo: formatUser(action.payload),
userInfo: action.payload,

authState: 'logged-in',
isAuthenticated: true,
}
case ActionType.USER_LOADED:
return state.isAuthenticated
? {
...state,
userInfo: formatUser(action.payload),
userInfo: action.payload,
}
: state
case ActionType.SIGNIN_FAILURE:
Expand Down
26 changes: 0 additions & 26 deletions libs/auth/react/src/lib/utils/getBirthday.spec.ts

This file was deleted.

10 changes: 10 additions & 0 deletions libs/clients/documents-v2/src/lib/documentsClientV2.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ export class DocumentsClientV2Service {
* @param input List input object. Example: { dateFrom: undefined, nationalId: '123' }
* @returns List object sanitized of unnecessary values. Example: { nationalId: '123' }
*/

const sanitizeObject = function <T extends { [key: string]: any }>(
obj: T,
): T {
Expand All @@ -43,6 +44,15 @@ export class DocumentsClientV2Service {
return sanitizedObj
}

// If hiddenCats is not empty and categories are empty, the API will return no documents
if (input.hiddenCategoryIds !== '' && input.categoryId === '') {
return {
totalCount: 0,
unreadCount: 0,
documents: [],
}
}

const inputObject = sanitizeObject({
...input,
kennitala: input.nationalId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export type ListDocumentsInputDto = {
dateFrom?: Date
dateTo?: Date
categoryId?: string
hiddenCategoryIds?: string
typeId?: string
subjectContains?: string
archived?: boolean
Expand Down
15 changes: 0 additions & 15 deletions libs/service-portal/documents/src/hooks/useDocumentList.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { useEffect } from 'react'
import { AuthDelegationType } from '@island.is/api/schema'
import { useUserInfo } from '@island.is/auth/react'
import { useDocumentContext } from '../screens/Overview/DocumentContext'
import { useDocumentsV2Query } from '../screens/Overview/Overview.generated'
import differenceInYears from 'date-fns/differenceInYears'

export const pageSize = 10

Expand All @@ -22,17 +19,6 @@ export const useDocumentList = (props?: UseDocumentListProps) => {
setSendersAvailable,
} = useDocumentContext()

const userInfo = useUserInfo()
const isLegal = userInfo.profile.delegationType?.includes(
AuthDelegationType.LegalGuardian,
)
const dateOfBirth = userInfo?.profile.dateOfBirth
let isOver15 = false
if (dateOfBirth) {
isOver15 = differenceInYears(new Date(), dateOfBirth) > 15
}
const hideHealthData = isOver15 && isLegal

const fetchObject = {
input: {
senderNationalId: filterValue.activeSenders,
Expand All @@ -44,7 +30,6 @@ export const useDocumentList = (props?: UseDocumentListProps) => {
opened: filterValue.showUnread ? false : null,
page: page,
pageSize: props?.defaultPageSize ?? pageSize,
isLegalGuardian: hideHealthData,
archived: filterValue.archived,
bookmarked: filterValue.bookmarked,
},
Expand Down
Loading
Loading