From 00faf6ed883180f5829e76d1a8039898d5a9c785 Mon Sep 17 00:00:00 2001 From: David Code Howard Date: Wed, 1 Nov 2023 13:34:37 -0400 Subject: [PATCH 1/3] feat: Add new selectors site filter We need to associate sites to user roles. The user role is selected as the user's role in the project to which the site belongs (undefined if the site does not belong to a project). --- src/selectors.test.ts | 25 +++++++++++++++++++++++++ src/selectors.ts | 28 ++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/selectors.test.ts b/src/selectors.test.ts index e021e6a6..f55d6771 100644 --- a/src/selectors.test.ts +++ b/src/selectors.test.ts @@ -14,6 +14,7 @@ import { import { selectProjectMembershipsWithUsers, selectProjectsWithTransferrableSites, + selectSitesAndUserRoles, } from 'terraso-client-shared/selectors'; import { Site } from 'terraso-client-shared/site/siteSlice'; import { SerializableSet } from 'terraso-client-shared/store/utils'; @@ -184,3 +185,27 @@ test('can access all projects with role', () => { unaffiliatedSites: [{ siteId: site3.id, siteName: site3.name }], }); }); + +test('select user sites with project role', () => { + const user = generateUser(); + const project1 = generateProject([generateMembership(user.id, 'manager')]); + const project2 = generateProject([ + generateMembership(user.id, 'contributor'), + ]); + const site1 = generateSite(project1); + const site2 = generateSite(project2); + const site3 = generateSite(); + const site4 = generateSite(project2); + + const store = createStore( + initState([project1, project2], [user], [site1, site2, site3, site4]), + ); + + const roles = selectSitesAndUserRoles(store.getState(), user.id); + expect(roles).toStrictEqual({ + [site1.id]: [site1, 'manager'], + [site2.id]: [site2, 'contributor'], + [site3.id]: [site3, undefined], + [site4.id]: [site4, 'contributor'], + }); +}); diff --git a/src/selectors.ts b/src/selectors.ts index f8253864..843ee17a 100644 --- a/src/selectors.ts +++ b/src/selectors.ts @@ -35,6 +35,34 @@ const selectProjectsWithUserRole = createSelector( ), ); +const selectProjectUserRoles = (state: SharedState, userId: string) => { + return Object.fromEntries( + mapValues(state.project.projects, project => { + const membership = Object.values(project.memberships).find( + ({ userId: membUserId }) => membUserId === userId, + ); + if (membership) { + return [project.id, membership.userRole]; + } + }).filter((item): item is [string, UserRole] => item !== undefined), + ); +}; + +export const selectSitesAndUserRoles = createSelector( + [selectProjectUserRoles, selectSites], + (userRoleMap, sites) => { + return Object.fromEntries( + mapValues(sites, site => { + let role = undefined; + if (site.projectId !== undefined) { + role = userRoleMap[site.projectId]; + } + return [site.id, [site, role]]; + }), + ); + }, +); + export const selectProjectsWithTransferrableSites = createSelector( [selectProjectsWithUserRole, selectSites], (projects, sites) => { From 53b2094bbfb594812049c67596192bfe547a51cf Mon Sep 17 00:00:00 2001 From: David Code Howard Date: Wed, 1 Nov 2023 14:36:01 -0400 Subject: [PATCH 2/3] refactor: Return lookup from selector --- src/selectors.test.ts | 8 ++++---- src/selectors.ts | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/selectors.test.ts b/src/selectors.test.ts index f55d6771..857597ee 100644 --- a/src/selectors.test.ts +++ b/src/selectors.test.ts @@ -203,9 +203,9 @@ test('select user sites with project role', () => { const roles = selectSitesAndUserRoles(store.getState(), user.id); expect(roles).toStrictEqual({ - [site1.id]: [site1, 'manager'], - [site2.id]: [site2, 'contributor'], - [site3.id]: [site3, undefined], - [site4.id]: [site4, 'contributor'], + [site1.id]: 'manager', + [site2.id]: 'contributor', + [site3.id]: undefined, + [site4.id]: 'contributor', }); }); diff --git a/src/selectors.ts b/src/selectors.ts index 843ee17a..3c7f45cc 100644 --- a/src/selectors.ts +++ b/src/selectors.ts @@ -57,7 +57,7 @@ export const selectSitesAndUserRoles = createSelector( if (site.projectId !== undefined) { role = userRoleMap[site.projectId]; } - return [site.id, [site, role]]; + return [site.id, role]; }), ); }, From 97725da6dffef1306ad95d32be77b4195f2f6208 Mon Sep 17 00:00:00 2001 From: David Code Howard Date: Wed, 1 Nov 2023 14:43:30 -0400 Subject: [PATCH 3/3] fix: Return empty object is userId is null --- src/selectors.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/selectors.ts b/src/selectors.ts index 3c7f45cc..b81fd262 100644 --- a/src/selectors.ts +++ b/src/selectors.ts @@ -35,9 +35,12 @@ const selectProjectsWithUserRole = createSelector( ), ); -const selectProjectUserRoles = (state: SharedState, userId: string) => { +const selectProjectUserRoles = (state: SharedState, userId?: string) => { return Object.fromEntries( mapValues(state.project.projects, project => { + if (userId === undefined) { + return {}; + } const membership = Object.values(project.memberships).find( ({ userId: membUserId }) => membUserId === userId, );