From 33509bfe85c9682951faa9debc4ceb39172cc768 Mon Sep 17 00:00:00 2001 From: "garo (they/them)" <3411715+shrouxm@users.noreply.github.com> Date: Tue, 26 Mar 2024 11:47:19 -0700 Subject: [PATCH] feat: define more types and enums (#359) --- package-lock.json | 4 +-- package.json | 2 +- src/project/projectFragments.ts | 1 - src/project/projectSlice.ts | 20 +++++++++++--- src/selectors.test.ts | 47 +++++++++++++++------------------ src/selectors.ts | 18 ++++++------- src/soilId/soilIdTypes.ts | 17 ++++++++++++ 7 files changed, 66 insertions(+), 43 deletions(-) diff --git a/package-lock.json b/package-lock.json index 079d2ff0..7f19dd51 100644 --- a/package-lock.json +++ b/package-lock.json @@ -13,7 +13,7 @@ "lodash": "^4.17.21", "react": "^18.2.0", "react-redux": "^8.1.3", - "terraso-backend": "github:techmatters/terraso-backend#f19112f", + "terraso-backend": "github:techmatters/terraso-backend#ae60684", "uuid": "^9.0.1" }, "devDependencies": { @@ -13882,7 +13882,7 @@ }, "node_modules/terraso-backend": { "version": "0.1.0", - "resolved": "git+ssh://git@github.com/techmatters/terraso-backend.git#f19112f07c39877076ac1c7ecf0f251beabe3a45" + "resolved": "git+ssh://git@github.com/techmatters/terraso-backend.git#ae6068499327c74e289114f32cf0a3480fa279c1" }, "node_modules/test-exclude": { "version": "6.0.0", diff --git a/package.json b/package.json index 1e302a87..b86d3e2d 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,7 @@ "lodash": "^4.17.21", "react": "^18.2.0", "react-redux": "^8.1.3", - "terraso-backend": "github:techmatters/terraso-backend#f19112f", + "terraso-backend": "github:techmatters/terraso-backend#ae60684", "uuid": "^9.0.1" }, "scripts": { diff --git a/src/project/projectFragments.ts b/src/project/projectFragments.ts index 50c92d65..f8622558 100644 --- a/src/project/projectFragments.ts +++ b/src/project/projectFragments.ts @@ -48,7 +48,6 @@ export const projectData = /* GraphQL */ ` siteInstructions updatedAt archived - measurementUnits membershipList { ...projectMembershipList } diff --git a/src/project/projectSlice.ts b/src/project/projectSlice.ts index c57269d1..46be8d3a 100644 --- a/src/project/projectSlice.ts +++ b/src/project/projectSlice.ts @@ -22,9 +22,9 @@ import { updateUsers, } from 'terraso-client-shared/account/accountSlice'; import { - MeasurementUnits, ProjectAddUserMutationInput, - UserRole, + ProjectManagementProjectPrivacyChoices, + ProjectMembershipProjectRoleChoices, } from 'terraso-client-shared/graphqlSchema/graphql'; import * as projectService from 'terraso-client-shared/project/projectService'; import { setSites, updateSites } from 'terraso-client-shared/site/siteSlice'; @@ -37,10 +37,23 @@ import { export type ProjectMembership = { userId: string; - userRole: UserRole; + userRole: ProjectRole; id: string; }; +export type ProjectRole = ProjectMembershipProjectRoleChoices; +export const PROJECT_ROLES = [ + 'MANAGER', + 'CONTRIBUTOR', + 'VIEWER', +] as const satisfies readonly ProjectRole[]; + +export type ProjectPrivacy = ProjectManagementProjectPrivacyChoices; +export const PROJECT_PRIVACIES = [ + 'PRIVATE', + 'PUBLIC', +] as const satisfies readonly ProjectPrivacy[]; + export type Project = { id: string; name: string; @@ -51,7 +64,6 @@ export type Project = { memberships: Record; sites: SerializableSet; archived: boolean; - measurementUnits: MeasurementUnits; }; interface MembershipKey { diff --git a/src/selectors.test.ts b/src/selectors.test.ts index 9deeb163..c528e526 100644 --- a/src/selectors.test.ts +++ b/src/selectors.test.ts @@ -24,14 +24,11 @@ import { DEFAULT_ENABLED_SOIL_PIT_METHODS, DEPTH_INTERVAL_PRESETS, } from 'terraso-client-shared/constants'; -import { - DepthInterval, - ProjectPrivacy, - UserRole, -} from 'terraso-client-shared/graphqlSchema/graphql'; import { Project, ProjectMembership, + ProjectPrivacy, + ProjectRole, } from 'terraso-client-shared/project/projectSlice'; import { selectProjectMembershipsWithUsers, @@ -42,6 +39,7 @@ import { } from 'terraso-client-shared/selectors'; import { Site } from 'terraso-client-shared/site/siteSlice'; import { + DepthInterval, methodEnabled, methodRequired, ProjectDepthInterval, @@ -91,7 +89,6 @@ const generateProject = ( sites: siteSet, archived: false, memberships: keyBy(memberships, 'id'), - measurementUnits: 'METRIC', siteInstructions: '', }; }; @@ -123,7 +120,7 @@ const generateSite = (args?: { project: Project } | { owner: User }): Site => { return site; }; -const generateMembership = (userId: string, userRole: UserRole) => { +const generateMembership = (userId: string, userRole: ProjectRole) => { return { id: uuidv4(), userId, userRole }; }; @@ -274,7 +271,7 @@ test('can select memberships', () => { const membership: ProjectMembership = { id: uuidv4(), userId: user.id, - userRole: 'manager', + userRole: 'MANAGER', }; const project = generateProject([membership]); const store = createStore(initState([project], [user])); @@ -288,8 +285,8 @@ test('can select memberships', () => { test('can select memberships of specific project', () => { const user = generateUser(); - const membershipA = generateMembership(user.id, 'viewer'); - const membershipB = generateMembership(user.id, 'manager'); + const membershipA = generateMembership(user.id, 'VIEWER'); + const membershipB = generateMembership(user.id, 'MANAGER'); const projectA = generateProject([membershipA]); const projectB = generateProject([membershipB]); const store = createStore(initState([projectA, projectB], [user])); @@ -312,11 +309,11 @@ test('not found project returns empty membership', () => { test('can access all projects with role', () => { const user = generateUser(); - const project1 = generateProject([generateMembership(user.id, 'manager')]); + const project1 = generateProject([generateMembership(user.id, 'MANAGER')]); const project2 = generateProject([ - generateMembership(user.id, 'contributor'), + generateMembership(user.id, 'CONTRIBUTOR'), ]); - const project3 = generateProject([generateMembership(user.id, 'manager')]); + const project3 = generateProject([generateMembership(user.id, 'MANAGER')]); const site1 = generateSite({ project: project1 }); const site2 = generateSite({ project: project2 }); const site3 = generateSite(); @@ -331,7 +328,7 @@ test('can access all projects with role', () => { ); const pairs = selectProjectsWithTransferrableSites( store.getState(), - 'manager', + 'MANAGER', ); expect(pairs).toStrictEqual({ projects: { @@ -352,9 +349,9 @@ test('can access all projects with role', () => { test('select user sites with project role', () => { const user = generateUser(); - const project1 = generateProject([generateMembership(user.id, 'manager')]); + const project1 = generateProject([generateMembership(user.id, 'MANAGER')]); const project2 = generateProject([ - generateMembership(user.id, 'contributor'), + generateMembership(user.id, 'CONTRIBUTOR'), ]); const site1 = generateSite({ project: project1 }); const site2 = generateSite({ project: project2 }); @@ -372,10 +369,10 @@ test('select user sites with project role', () => { const roles = selectSitesAndUserRoles(store.getState()); expect(roles).toStrictEqual({ - [site1.id]: 'manager', - [site2.id]: 'contributor', + [site1.id]: 'MANAGER', + [site2.id]: 'CONTRIBUTOR', [site3.id]: undefined, - [site4.id]: 'contributor', + [site4.id]: 'CONTRIBUTOR', }); }); @@ -385,22 +382,22 @@ test('select user role when site owned', () => { const store = createStore(initState([], [user], [site], user.id)); const siteRole = selectUserRoleSite(store.getState(), site.id); - expect(siteRole).toStrictEqual({ kind: 'site', role: 'owner' }); + expect(siteRole).toStrictEqual({ kind: 'site', role: 'OWNER' }); }); test('select user role in project of site', () => { const user = generateUser(); - const project = generateProject([generateMembership(user.id, 'viewer')]); + const project = generateProject([generateMembership(user.id, 'VIEWER')]); const site = generateSite({ project }); const store = createStore(initState([project], [user], [site], user.id)); const siteRole = selectUserRoleSite(store.getState(), site.id); - expect(siteRole).toStrictEqual({ kind: 'project', role: 'viewer' }); + expect(siteRole).toStrictEqual({ kind: 'project', role: 'VIEWER' }); }); test('select predefined project selector', () => { const user = generateUser(); - const project = generateProject([generateMembership(user.id, 'manager')]); + const project = generateProject([generateMembership(user.id, 'MANAGER')]); const site = generateSite({ project }); const soilData = createSoilData(site); const projectSettings = createProjectSettings(project, { @@ -424,7 +421,7 @@ test('select predefined project selector', () => { test('select predefined project selector with custom preset', () => { const user = generateUser(); - const project = generateProject([generateMembership(user.id, 'manager')]); + const project = generateProject([generateMembership(user.id, 'MANAGER')]); const site = generateSite({ project }); const projectDepthIntervals = [ { depthInterval: { start: 2, end: 3 }, label: 'first' }, @@ -479,7 +476,7 @@ test('select predefined project selector with custom preset', () => { test('overlapping site intervals get the project values of the preset interval', () => { const user = generateUser(); - const project = generateProject([generateMembership(user.id, 'manager')]); + const project = generateProject([generateMembership(user.id, 'MANAGER')]); const site = generateSite({ project }); const projectDepthIntervals = [ diff --git a/src/selectors.ts b/src/selectors.ts index 4edae546..e97c3f64 100644 --- a/src/selectors.ts +++ b/src/selectors.ts @@ -28,16 +28,14 @@ import { DEFAULT_SOIL_DATA, DEPTH_INTERVAL_PRESETS, } from 'terraso-client-shared/constants'; -import { - DepthInterval, - UserRole, -} from 'terraso-client-shared/graphqlSchema/graphql'; import { Project, ProjectMembership, + ProjectRole, } from 'terraso-client-shared/project/projectSlice'; import { compareInterval, + DepthInterval, methodEnabled, methodRequired, overlaps, @@ -82,7 +80,7 @@ export const selectSite = (siteId: string) => (state: SharedState) => const selectSites = (state: SharedState) => state.site.sites; -const selectUserRole = (_state: SharedState, userRole: UserRole) => userRole; +const selectUserRole = (_state: SharedState, userRole: ProjectRole) => userRole; const selectProjectsWithUserRole = createSelector( [selectProjects, selectUserRole], @@ -110,7 +108,7 @@ const createUserRoleMap = ( if (membership) { return [project.id, membership.userRole]; } - }).filter((item): item is [string, UserRole] => item !== undefined), + }).filter((item): item is [string, ProjectRole] => item !== undefined), ); }; @@ -145,7 +143,7 @@ export const selectProjectsWithTransferrableSites = createSelector( Object.keys(project.sites) .filter( siteId => - siteId in project.sites && sitesWithRoles[siteId] === 'manager', + siteId in project.sites && sitesWithRoles[siteId] === 'MANAGER', ) .map(siteId => { const joinedSite = sites[siteId]; @@ -176,8 +174,8 @@ export const selectProjectsWithTransferrableSites = createSelector( // Note on "site" kind: In the future, there will also be site level roles, like manager and viewer // For now we only care if a user owns a site or not. export type SiteUserRole = - | { kind: 'site'; role: 'owner' } - | { kind: 'project'; role: UserRole }; + | { kind: 'site'; role: 'OWNER' } + | { kind: 'project'; role: ProjectRole }; const selectSiteId = (_state: any, siteId: string) => siteId; @@ -189,7 +187,7 @@ export const selectUserRoleSite = createSelector( return null; } if (site.ownerId === userId) { - return { kind: 'site', role: 'owner' }; + return { kind: 'site', role: 'OWNER' }; } if (site.projectId === undefined) { return null; diff --git a/src/soilId/soilIdTypes.ts b/src/soilId/soilIdTypes.ts index 229ff338..17b1ffca 100644 --- a/src/soilId/soilIdTypes.ts +++ b/src/soilId/soilIdTypes.ts @@ -24,6 +24,8 @@ import type { SoilDataNode, SoilIdDepthDependentSoilDataRockFragmentVolumeChoices, SoilIdDepthDependentSoilDataTextureChoices, + SoilIdProjectSoilSettingsDepthIntervalPresetChoices, + SoilIdProjectSoilSettingsMeasurementUnitsChoices, SoilIdSoilDataSurfaceCracksSelectChoices, } from 'terraso-client-shared/graphqlSchema/graphql'; @@ -50,6 +52,12 @@ export const collectionMethods = [ export type SoilPitMethod = (typeof soilPitMethods)[number]; export type CollectionMethod = (typeof collectionMethods)[number]; +export type MeasurementUnit = SoilIdProjectSoilSettingsMeasurementUnitsChoices; +export const MEASUREMENT_UNITS = [ + 'METRIC', + 'IMPERIAL', +] as const satisfies readonly MeasurementUnit[]; + export { DepthInterval }; export type LabelledDepthInterval = { label: string; @@ -115,3 +123,12 @@ export const surfaceCracks = [ 'SURFACE_CRACKING_ONLY', 'DEEP_VERTICAL_CRACKS', ] as const satisfies readonly SurfaceCracks[]; + +export type ProjectDepthIntervalPreset = + SoilIdProjectSoilSettingsDepthIntervalPresetChoices; +export const DEPTH_PRESETS = [ + 'LANDPKS', + 'NRCS', + 'CUSTOM', + 'NONE', +] as const satisfies readonly ProjectDepthIntervalPreset[];