Skip to content

Commit

Permalink
fix: #2535 Filter invite to show only once per email (#2646)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cuong Vu authored Sep 10, 2020
1 parent 026dbd6 commit 4889a00
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
openDisableMemberModal,
openReinviteModal,
closeReinviteModal,
handleGenerateUniqueDataList,
} from '../members'
import { developerStub } from '@/sagas/__stubs__/developer'
import * as ReactRedux from 'react-redux'
Expand Down Expand Up @@ -65,3 +66,145 @@ describe('Members', () => {
})
})
})

describe('handleGenerateUniqueDataList', () => {
it('should run correctly with pending', () => {
const data = [
{
id: '879551ef-1127-4088-a0cb-40a7a0df188b',
created: '2020-09-09T10:26:10',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engineer',
status: 'pending',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:26:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'pending',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
]
const fn = handleGenerateUniqueDataList(data)
const result = fn()
const expected = [
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:26:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'pending',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
]
expect(result).toEqual(expected)
})

it('should run correctly with active & pending', () => {
const data = [
{
id: '879551ef-1127-4088-a0cb-40a7a0df188b',
created: '2020-09-09T10:26:10',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engineer',
status: 'pending',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:26:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'active',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
]
const fn = handleGenerateUniqueDataList(data)
const result = fn()
const expected = [
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:26:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'active',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
]
expect(result).toEqual(expected)
})

it('should run correctly with active & pending & inactive', () => {
const data = [
{
id: '879551ef-1127-4088-a0cb-40a7a0df188b',
created: '2020-09-09T10:26:10',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engineer',
status: 'pending',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:26:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'active',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:24:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'inactive',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
]
const fn = handleGenerateUniqueDataList(data)
const result = fn()
const expected = [
{
id: 'd42b6362-dbf2-4250-93e1-1e63ee2ebcda',
created: '2020-09-09T10:26:36',
email: '[email protected]',
name: 'cuong',
jobTitle: 'Engin',
status: 'active',
role: 'user',
developerId: '909dcdc1-6657-4a37-a5cc-05acd79d6a47',
agencyCloudAccess: false,
},
]
expect(result).toEqual(expected)
})
})
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { Dispatch } from 'react'
import React, { Dispatch, useMemo } from 'react'
import { MemberModel } from '@reapit/foundations-ts-definitions'
import { FlexContainerBasic, Table, Section, H5 } from '@reapit/elements'
import SetAsAdminModal from './set-as-admin'
import DisableMemberModal from '@/components/ui/disable-member-modal'
Expand All @@ -7,6 +8,7 @@ import { useSelector } from 'react-redux'
import { selectOrganisationMembers, selectOrganisationMembersLoading } from '@/selector/developers'
import InviteMemberModal from '@/components/ui/developer-invite-member-modal'
import { selectCurrentMemberData } from '@/selector/current-member'
import dayjs from 'dayjs'

export const columns = [
{
Expand Down Expand Up @@ -109,6 +111,59 @@ export const openDisableMemberModal = (setSelectedUser, setDisableMemberModalVis
setDisableMemberModalVisible(true)
}

export const PRIORITY_LEVEL = {
active: 4,
inactive: 3,
pending: 2,
rejected: 1,
other: 0,
}

type MemberModelWithAction = MemberModel & { action?: any }

export const handleGenerateUniqueDataList = (data: MemberModelWithAction[]) => () => {
const uniqueHashMapWithEmailKey: { [key: string]: MemberModelWithAction } = data.reduce((accumulator, item) => {
const newAcc = { ...accumulator }
const { email, status, created } = item

if (!email || !status || !created) {
return newAcc
}

if (!accumulator[email]) {
newAcc[email] = item
return newAcc
}

// PRIORITY_LEVEL[status] will be undefined if status is not in the list
// its priority will be 0 in this case
const currentItemPriority = PRIORITY_LEVEL[status] ?? PRIORITY_LEVEL.other
const inHashMapItemPriority = PRIORITY_LEVEL[accumulator[email].status] ?? PRIORITY_LEVEL.other

const currentItemCreated = dayjs(created)
const inHashMapItemCreated = dayjs(accumulator[email].created)

// when already had in hashmap -> check priority to update
// 'active' & 'pending' take over other status
if (currentItemPriority > inHashMapItemPriority) {
newAcc[email] = item
}

// if same priority, newer invite goes first
if (currentItemPriority === inHashMapItemPriority && currentItemCreated.isAfter(inHashMapItemCreated)) {
newAcc[email] = item
}
return newAcc
}, {})

// sort by data so that newer members go first
const sortedDataByDate = Object.values(uniqueHashMapWithEmailKey).sort((a, b) => {
return dayjs(a.created).isAfter(dayjs(b.created)) ? -1 : 0
})

return sortedDataByDate
}

export const Members: React.FC = () => {
const [isSetAdminModalOpen, setIsSetAdminModalOpen] = React.useState<boolean>(false)
const [selectedUser, setSelectedUser] = React.useState<any>(null)
Expand All @@ -132,10 +187,12 @@ export const Members: React.FC = () => {
setDisableMemberModalVisible,
setReInviteModalVisible,
)
const memoizedUniqueDataList = useMemo(handleGenerateUniqueDataList(data), [data])

return (
<Section>
<H5>Members</H5>
<Table scrollable loading={loading} data={data} columns={columns} />
<Table scrollable loading={loading} data={memoizedUniqueDataList} columns={columns} />
<DisableMemberModal
visible={disableMemberModalVisible}
developer={selectedUser}
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/developer-portal/src/tests/badges/badge-lines.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4889a00

Please sign in to comment.