From 190ea8310f86bfb4db96c0a0bb370e393ad36ea8 Mon Sep 17 00:00:00 2001 From: "Huy Tran (Harry)" Date: Sat, 2 Oct 2021 08:32:17 +1000 Subject: [PATCH] feat: refactoring renaming planters to growers (#163) * feat: refactoring renaming planters to growers * feat: refactoring renaming planters to growers * feat: refactoring renaming planters to growers * feat: refactoring renaming planters to growers * fix: resolves test verify errors * feat: change file name planter to grower * refactor: update remaining planter references Co-authored-by: Nick Charlton --- ...anter.spec.py.js => EditGrower.spec.py.js} | 50 +++---- cypress/component/grower.spec.py.js | 11 ++ cypress/component/planter.spec.py.js | 11 -- cypress/integration/admin.spec.py.js | 4 +- .../{planter.spec.py.js => grower.spec.py.js} | 6 +- cypress/integration/organization.spec.py.js | 4 +- src/api/{planters.js => growers.js} | 38 ++--- src/common/policy.js | 38 ----- src/components/CaptureDetailDialog.js | 9 +- src/components/CaptureTable.js | 2 +- src/components/DashStat.container.js | 22 +-- .../{EditPlanter.js => EditGrower.js} | 104 +++++++------- src/components/Filter.js | 28 ++-- src/components/FilterTop.js | 34 ++--- ...FilterTopPlanter.js => FilterTopGrower.js} | 14 +- .../{PlanterDetail.js => GrowerDetail.js} | 119 ++++++++-------- src/components/{Planters.js => Growers.js} | 130 ++++++++---------- src/components/Home.js | 4 +- src/components/Routers.js | 9 ++ src/components/Verify.js | 44 +++--- src/components/tests/captureDetail.test.js | 4 +- src/components/tests/captures.test.js | 2 +- .../{planters.test.js => growers.test.js} | 66 ++++----- src/components/tests/tags.test.js | 4 +- src/components/tests/verify.test.js | 82 +++++------ src/context/AppContext.js | 16 +-- src/context/GrowerContext.js | 125 +++++++++++++++++ src/context/PlanterContext.js | 125 ----------------- .../{FilterPlanter.js => FilterGrower.js} | 4 +- ...erPlanter.test.js => FilterGrower.test.js} | 10 +- src/models/auth.js | 6 +- 31 files changed, 542 insertions(+), 583 deletions(-) rename cypress/component/{EditPlanter.spec.py.js => EditGrower.spec.py.js} (65%) create mode 100644 cypress/component/grower.spec.py.js delete mode 100644 cypress/component/planter.spec.py.js rename cypress/integration/{planter.spec.py.js => grower.spec.py.js} (89%) rename src/api/{planters.js => growers.js} (77%) delete mode 100644 src/common/policy.js rename src/components/{EditPlanter.js => EditGrower.js} (62%) rename src/components/{FilterTopPlanter.js => FilterTopGrower.js} (96%) rename src/components/{PlanterDetail.js => GrowerDetail.js} (71%) rename src/components/{Planters.js => Growers.js} (70%) rename src/components/tests/{planters.test.js => growers.test.js} (84%) create mode 100644 src/context/GrowerContext.js delete mode 100644 src/context/PlanterContext.js rename src/models/{FilterPlanter.js => FilterGrower.js} (96%) rename src/models/{FilterPlanter.test.js => FilterGrower.test.js} (69%) diff --git a/cypress/component/EditPlanter.spec.py.js b/cypress/component/EditGrower.spec.py.js similarity index 65% rename from cypress/component/EditPlanter.spec.py.js rename to cypress/component/EditGrower.spec.py.js index f2914e047..4ec5c90d2 100644 --- a/cypress/component/EditPlanter.spec.py.js +++ b/cypress/component/EditGrower.spec.py.js @@ -5,20 +5,20 @@ import { Provider } from 'react-redux'; import theme from '../../src/components/common/theme'; import { ThemeProvider } from '@material-ui/core/styles'; import { init } from '@rematch/core'; -import api from '../../src/api/planters'; +import api from '../../src/api/growers'; -import EditPlanter from '../../src/components/EditPlanter'; +import EditGrower from '../../src/components/EditGrower'; -describe('EditPlanter', () => { +describe('EditGrower', () => { let store; beforeEach(() => { store = init({ models: { - planters: { + growers: { state: {}, effects: { - updatePlanter(_payload, _state) {}, + updateGrower(_payload, _state) {}, }, }, organizations: { @@ -42,15 +42,15 @@ describe('EditPlanter', () => { mount( - {}} /> + {}} /> , ); - cy.contains(/Edit Planter/i); + cy.contains(/Edit Grower/i); }); - describe('with valid planter', () => { - const planter = { + describe('with valid grower', () => { + const grower = { id: 12345, imageUrl: 'https://greenstand.org/fileadmin/_processed_/f/e/csm_MVIMG_20200303_103438_be16bc7f80.jpg', @@ -60,40 +60,40 @@ describe('EditPlanter', () => { phone: '+1234567890', }; - let planterSelfies; + let growerSelfies; beforeEach(() => { - planterSelfies = [ + growerSelfies = [ 'https://greenstand.org/fileadmin/_processed_/d/4/csm_little_Jony_bdf756638d.jpg', 'https://greenstand.org/fileadmin/_processed_/9/f/csm_2019.08.12.09.54.39_1ca43554-b139-4ae2-bbc9-c9a37c43e645_IMG_20190812_093641_-1471408775_0bb24d7c21.jpg', 'https://greenstand.org/fileadmin/_processed_/e/3/csm_IMG_0017_3c859de144.jpg', 'https://greenstand.org/fileadmin/_processed_/9/3/csm_PHOTO-2019-08-05-11-50-37_f0d0281499.jpg', ]; - cy.stub(api, 'getPlanterSelfies').returns(planterSelfies); + cy.stub(api, 'getGroerSelfies').returns(growerSelfies); mount( - {}} /> + {}} /> , ); }); - it('should display planter details', () => { - cy.get(`[title="${planter.imageUrl}"]`).should( + it('should display grower details', () => { + cy.get(`[title="${grower.imageUrl}"]`).should( 'have.css', 'background-image', - `url("${planter.imageUrl}")`, + `url("${grower.imageUrl}")`, ); - cy.get('input#firstName').should('have.value', planter.firstName); - cy.get('input#lastName').should('have.value', planter.lastName); - cy.get('input#email').should('have.value', planter.email); - cy.get('input#phone').should('have.value', planter.phone); + cy.get('input#firstName').should('have.value', grower.firstName); + cy.get('input#lastName').should('have.value', grower.lastName); + cy.get('input#email').should('have.value', grower.email); + cy.get('input#phone').should('have.value', grower.phone); }); - it('should display all other planter images', () => { - planterSelfies.forEach((img) => { + it('should display all other grower images', () => { + growerSelfies.forEach((img) => { cy.get(`[title="${img}"]`).should( 'have.css', 'background-image', @@ -108,12 +108,12 @@ describe('EditPlanter', () => { cy.get('button#save').should('be.enabled'); }); - it('should update the planter when Save is clicked', () => { - cy.spy(store.dispatch.planters, 'updatePlanter'); + it('should update the grower when Save is clicked', () => { + cy.spy(store.dispatch.growers, 'updateGrower'); cy.get('input#firstName').type('abc'); cy.get('button#save').then(($button) => { $button[0].click(); - expect(store.dispatch.planters.updatePlanter).to.be.called; + expect(store.dispatch.growers.updateGrower).to.be.called; }); }); }); diff --git a/cypress/component/grower.spec.py.js b/cypress/component/grower.spec.py.js new file mode 100644 index 000000000..fd633eb26 --- /dev/null +++ b/cypress/component/grower.spec.py.js @@ -0,0 +1,11 @@ +import { mount } from 'cypress-react-unit-test'; +import React from 'react'; +import { Grower } from '../../src/components/Growers.js'; + +describe('HelloWorld component', () => { + it('works', () => { + mount(); + // now use standard Cypress commands + cy.contains('ID').should('be.visible'); + }); +}); diff --git a/cypress/component/planter.spec.py.js b/cypress/component/planter.spec.py.js deleted file mode 100644 index e1e869345..000000000 --- a/cypress/component/planter.spec.py.js +++ /dev/null @@ -1,11 +0,0 @@ -import { mount } from 'cypress-react-unit-test' -import React from 'react' -import {Planter} from "../../src/components/Planters.js"; - -describe('HelloWorld component', () => { - it('works', () => { - mount() - // now use standard Cypress commands - cy.contains('ID').should('be.visible') - }) -}) diff --git a/cypress/integration/admin.spec.py.js b/cypress/integration/admin.spec.py.js index 500de8744..ce3b99073 100644 --- a/cypress/integration/admin.spec.py.js +++ b/cypress/integration/admin.spec.py.js @@ -16,7 +16,7 @@ describe('Admin', () => { cy.contains(/verify/i).click(); }); - it('planter', () => { - cy.contains(/planter/i).click(); + it('grower', () => { + cy.contains(/grower/i).click(); }); }); diff --git a/cypress/integration/planter.spec.py.js b/cypress/integration/grower.spec.py.js similarity index 89% rename from cypress/integration/planter.spec.py.js rename to cypress/integration/grower.spec.py.js index a88c6a98e..f1855a5cd 100644 --- a/cypress/integration/planter.spec.py.js +++ b/cypress/integration/grower.spec.py.js @@ -1,4 +1,4 @@ -describe('Planter', () => { +describe('Grower', () => { const pageSize = 24; before(() => { @@ -9,7 +9,7 @@ describe('Planter', () => { cy.contains(/log in/i).click(); // cy.visit('/'); // cy.get('button[title=menu]').click(); - cy.contains(/Planters/i).click({ force: true }); + cy.contains(/Growers/i).click({ force: true }); }); it('Should get id:xxx', () => { @@ -28,7 +28,7 @@ describe('Planter', () => { cy.get('button[title="Previous page"]').should('be.disabled'); }); - it('Should show a full page of planters', () => { + it('Should show a full page of growers', () => { cy.get('.MuiCard-root').should('have.length', pageSize); }); diff --git a/cypress/integration/organization.spec.py.js b/cypress/integration/organization.spec.py.js index 39417fbf0..9cbb86943 100644 --- a/cypress/integration/organization.spec.py.js +++ b/cypress/integration/organization.spec.py.js @@ -12,8 +12,8 @@ describe('Organization', () => { cy.contains('.MuiMenuItem-root', /verify/i).click(); }); - it('planter', () => { - cy.contains('.MuiMenuItem-root', /planter/i).click({ force: true }); + it('grower', () => { + cy.contains('.MuiMenuItem-root', /grower/i).click({ force: true }); }); it.only('tree', () => { diff --git a/src/api/planters.js b/src/api/growers.js similarity index 77% rename from src/api/planters.js rename to src/api/growers.js index c00e845e5..f1b9687a4 100644 --- a/src/api/planters.js +++ b/src/api/growers.js @@ -2,12 +2,12 @@ import { handleResponse, handleError, getOrganization } from './apiUtils'; import { session } from '../models/auth'; export default { - getPlanter(id) { - const planterQuery = `${ + getGrower(id) { + const growerQuery = `${ process.env.REACT_APP_API_ROOT }/api/${getOrganization()}planter/${id}`; - return fetch(planterQuery, { + return fetch(growerQuery, { method: 'GET', headers: { 'content-type': 'application/json', @@ -18,9 +18,9 @@ export default { .catch(handleError); }, - getPlanters({ skip, rowsPerPage, orderBy = 'id', order = 'desc', filter }) { + getGrowers({ skip, rowsPerPage, orderBy = 'id', order = 'desc', filter }) { const where = filter.getWhereObj ? filter.getWhereObj() : {}; - const planterFilter = { + const growerFilter = { where: { ...where, active: true }, order: [`${orderBy} ${order}`], limit: rowsPerPage, @@ -40,7 +40,7 @@ export default { }; const query = `${ process.env.REACT_APP_API_ROOT - }/api/${getOrganization()}planter?filter=${JSON.stringify(planterFilter)}`; + }/api/${getOrganization()}planter?filter=${JSON.stringify(growerFilter)}`; return fetch(query, { headers: { @@ -67,10 +67,10 @@ export default { .catch(handleError); }, - getPlanterRegistrations(planterId) { + getGrowerRegistrations(growerId) { const registrationQuery = `${ process.env.REACT_APP_API_ROOT - }/api/${getOrganization()}planter-registration?filter[where][planterId]=${planterId}`; + }/api/${getOrganization()}planter-registration?filter[where][planterId]=${growerId}`; return fetch(registrationQuery, { method: 'GET', headers: { @@ -82,20 +82,20 @@ export default { .catch(handleError); }, - getPlanterSelfies(planterId) { + getGrowerSelfies(growerId) { const filter = { order: 'timeUpdated DESC', limit: 100, fields: ['planterPhotoUrl'], }; - const planterSelfiesQuery = `${ + const growerSelfiesQuery = `${ process.env.REACT_APP_API_ROOT - }/api/${getOrganization()}planter/${planterId}/selfies/?filter=${JSON.stringify( + }/api/${getOrganization()}planter/${growerId}/selfies/?filter=${JSON.stringify( filter, )}`; - return fetch(planterSelfiesQuery, { + return fetch(growerSelfiesQuery, { method: 'GET', headers: { 'content-type': 'application/json', @@ -116,22 +116,22 @@ export default { .catch(handleError); }, - updatePlanter(planterUpdate) { - if (planterUpdate.organizationId === 'null') { - planterUpdate = { ...planterUpdate, organizationId: null }; + updateGrower(growerUpdate) { + if (growerUpdate.organizationId === 'null') { + growerUpdate = { ...growerUpdate, organizationId: null }; } - const { id } = planterUpdate; - const planterQuery = `${ + const { id } = growerUpdate; + const growerQuery = `${ process.env.REACT_APP_API_ROOT }/api/${getOrganization()}planter/${id}`; - return fetch(planterQuery, { + return fetch(growerQuery, { method: 'PATCH', headers: { 'content-type': 'application/json', Authorization: session.token, }, - body: JSON.stringify(planterUpdate), + body: JSON.stringify(growerUpdate), }) .then(handleResponse) .catch(handleError); diff --git a/src/common/policy.js b/src/common/policy.js deleted file mode 100644 index 57cc13466..000000000 --- a/src/common/policy.js +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Permission policy - * - */ -const policy = { - policies: [ - { - name: 'super_permission', - description: 'Can do anything', - }, - { - name: 'list_tree', - description: 'Can view trees', - }, - { - name: 'approve_tree', - description: 'Can approve/reject trees', - }, - { - name: 'list_planter', - description: 'Can view planters', - }, - { - name: 'manage_planter', - description: 'Can modify planter information', - }, - { - name: 'list_user', - description: 'Can view admin users', - }, - { - name: 'manager_user', - description: 'Can create/modify admin user', - }, - ], -}; - -export default policy; diff --git a/src/components/CaptureDetailDialog.js b/src/components/CaptureDetailDialog.js index 79cd31a11..f008b33ae 100644 --- a/src/components/CaptureDetailDialog.js +++ b/src/components/CaptureDetailDialog.js @@ -180,18 +180,13 @@ function CaptureDetailDialog(props) { Capture Data {[ { - label: 'Planter ID', + label: 'Grower ID', value: capture.planterId, copy: true, link: true, }, { - label: 'Capture UUID', - value: capture.uuid, - copy: true, - }, - { - label: 'Planter Identifier', + label: 'Grower Identifier', value: capture.planterIdentifier, copy: true, }, diff --git a/src/components/CaptureTable.js b/src/components/CaptureTable.js index 84eabd33b..5facd7bc3 100644 --- a/src/components/CaptureTable.js +++ b/src/components/CaptureTable.js @@ -68,7 +68,7 @@ const columns = [ }, { attr: 'planterId', - label: 'Planter ID', + label: 'Grower ID', }, { attr: 'deviceIdentifier', diff --git a/src/components/DashStat.container.js b/src/components/DashStat.container.js index 72b185ae1..1f5a2b1c9 100644 --- a/src/components/DashStat.container.js +++ b/src/components/DashStat.container.js @@ -9,7 +9,7 @@ import LocalOfferOutlinedIcon from '@material-ui/icons/LocalOfferOutlined'; import CheckCircleOutlineOutlinedIcon from '@material-ui/icons/CheckCircleOutlineOutlined'; import PeopleOutlineOutlinedIcon from '@material-ui/icons/PeopleOutlineOutlined'; -import apiPlanters from '../api/planters'; +import apiPlanters from '../api/growers'; import api from '../api/treeTrackerApi'; import FilterModel from '../models/Filter'; @@ -99,35 +99,35 @@ function DashStatVerifiedCaptures(props) { ); } -function DashStatPlanterCount(props) { - const planterFilter = new FilterModel({ +function DashStatGrowerCount(props) { + const growerFilter = new FilterModel({ active: true, }); - const [totalPlanterCount, setTotalPlanterCount] = useState(null); + const [totalGrowerCount, setTotalGrowerCount] = useState(null); - const getTotalPlanterCount = async () => { - const { count } = await apiPlanters.getCount(planterFilter); - setTotalPlanterCount(count); + const getTotalGrowerCount = async () => { + const { count } = await apiPlanters.getCount(growerFilter); + setTotalGrowerCount(count); }; useEffect(() => { - getTotalPlanterCount(); + getTotalGrowerCount(); }, []); return ( ); } export { - DashStatPlanterCount, + DashStatGrowerCount, DashStatVerifiedCaptures, DashStatUnprocessedCaptures, DashStatTotalCaptures, diff --git a/src/components/EditPlanter.js b/src/components/EditGrower.js similarity index 62% rename from src/components/EditPlanter.js rename to src/components/EditGrower.js index ab0827d7d..1e037511f 100644 --- a/src/components/EditPlanter.js +++ b/src/components/EditGrower.js @@ -11,10 +11,10 @@ import { CircularProgress, MenuItem, } from '@material-ui/core'; -import api from '../api/planters'; +import api from '../api/growers'; import ImageScroller from './ImageScroller'; import { AppContext } from '../context/AppContext'; -import { PlanterContext } from '../context/PlanterContext'; +import { GrowerContext } from '../context/GrowerContext'; const useStyle = makeStyles((theme) => ({ container: { @@ -27,58 +27,58 @@ const useStyle = makeStyles((theme) => ({ }, })); -const EditPlanter = (props) => { - // console.log('render: edit planter'); +const EditGrower = (props) => { + // console.log('render: edit grower'); const classes = useStyle(); - const { isOpen, planter, onClose } = props; + const { isOpen, grower, onClose } = props; const appContext = useContext(AppContext); - const planterContext = useContext(PlanterContext); - const [planterImages, setPlanterImages] = useState([]); - const [planterUpdate, setPlanterUpdate] = useState(null); - const [loadingPlanterImages, setLoadingPlanterImages] = useState(false); + const growerContext = useContext(GrowerContext); + const [growerImages, setGrowerImages] = useState([]); + const [growerUpdate, setGrowerUpdate] = useState(null); + const [loadingGrowerImages, setLoadingGrowerImages] = useState(false); const [saveInProgress, setSaveInProgress] = useState(false); useEffect(() => { - async function loadPlanterImages() { - if (planter?.id) { - setLoadingPlanterImages(true); - const selfies = await api.getPlanterSelfies(planter.id); - setLoadingPlanterImages(false); + async function loadGrowerImages() { + if (grower?.id) { + setLoadingGrowerImages(true); + const selfies = await api.getGrowerSelfies(grower.id); + setLoadingGrowerImages(false); - setPlanterImages([ - ...(planter.imageUrl ? [planter.imageUrl] : []), - ...selfies?.filter((img) => img !== planter.imageUrl), + setGrowerImages([ + ...(grower.imageUrl ? [grower.imageUrl] : []), + ...selfies?.filter((img) => img !== grower.imageUrl), ]); } } - setPlanterUpdate(null); - loadPlanterImages(); - }, [planter]); + setGrowerUpdate(null); + loadGrowerImages(); + }, [grower]); - async function updatePlanter(planter) { - await api.updatePlanter(planter); - const updatedPlanter = await api.getPlanter(planter.id); - // only update context if planters have already been downloaded - if (planterContext.planters.length) { - const index = planterContext.planters.findIndex( - (p) => p.id === updatedPlanter.id, + async function updateGrower(grower) { + await api.updateGrower(grower); + const updatedGrower = await api.getGrower(grower.id); + // only update context if growers have already been downloaded + if (growerContext.growers.length) { + const index = growerContext.growers.findIndex( + (p) => p.id === updatedGrower.id, ); if (index >= 0) { - const planters = [...planterContext.planters]; - planters[index] = updatedPlanter; - planterContext.updatePlanters(planters); + const growers = [...growerContext.growers]; + growers[index] = updatedGrower; + growerContext.updateGrowers(growers); } } } async function handleSave() { - if (planterUpdate) { + if (growerUpdate) { setSaveInProgress(true); // TODO handle errors - await updatePlanter({ - id: planter.id, - ...planterUpdate, + await updateGrower({ + id: grower.id, + ...growerUpdate, }); setSaveInProgress(false); } @@ -90,26 +90,26 @@ const EditPlanter = (props) => { } function handleChange(key, val) { - let newPlanter = { ...planterUpdate }; - newPlanter[key] = val; + let newGrower = { ...growerUpdate }; + newGrower[key] = val; - const changed = Object.keys(newPlanter).some((key) => { - return newPlanter[key] !== planter[key]; + const changed = Object.keys(newGrower).some((key) => { + return newGrower[key] !== grower[key]; }); if (changed) { - setPlanterUpdate(newPlanter); + setGrowerUpdate(newGrower); } else { - setPlanterUpdate(null); + setGrowerUpdate(null); } } function getValue(attr) { // Ensure empty strings are not overlooked - if (planterUpdate?.[attr] != null) { - return planterUpdate[attr]; - } else if (planter[attr] != null) { - return planter[attr]; + if (growerUpdate?.[attr] != null) { + return growerUpdate[attr]; + } else if (grower[attr] != null) { + return grower[attr]; } return ''; } @@ -143,16 +143,16 @@ const EditPlanter = (props) => { return ( - Edit Planter + Edit Grower @@ -209,7 +209,7 @@ const EditPlanter = (props) => { onClick={handleSave} variant="contained" color="primary" - disabled={!planterUpdate || saveInProgress} + disabled={!growerUpdate || saveInProgress} > {saveInProgress ? : 'Save'} @@ -218,4 +218,4 @@ const EditPlanter = (props) => { ); }; -export default EditPlanter; +export default EditGrower; diff --git a/src/components/Filter.js b/src/components/Filter.js index aecd0f841..9b5f7ea17 100644 --- a/src/components/Filter.js +++ b/src/components/Filter.js @@ -60,11 +60,11 @@ function Filter(props) { const dateStartDefault = null; const dateEndDefault = null; const [captureId, setCaptureId] = useState(filter?.captureId || ''); - const [planterId, setPlanterId] = useState(filter?.planterId || ''); + const [growerId, setGrowerId] = useState(filter?.planterId || ''); const [deviceIdentifier, setDeviceIdentifier] = useState( filter?.deviceIdentifier || '', ); - const [planterIdentifier, setPlanterIdentifier] = useState( + const [growerIdentifier, setGrowerIdentifier] = useState( filter?.planterIdentifier || '', ); const [status, setStatus] = useState(filter?.status); @@ -96,9 +96,9 @@ function Filter(props) { e.preventDefault(); const filter = new FilterModel(); filter.captureId = captureId; - filter.planterId = planterId; + filter.planterId = growerId; filter.deviceIdentifier = deviceIdentifier; - filter.planterIdentifier = planterIdentifier; + filter.planterIdentifier = growerIdentifier; filter.dateStart = dateStart ? formatDate(dateStart) : undefined; filter.dateEnd = dateEnd ? formatDate(dateEnd) : undefined; filter.approved = approved; @@ -110,9 +110,9 @@ function Filter(props) { function handleClear() { setCaptureId(''); - setPlanterId(''); + setGrowerId(''); setDeviceIdentifier(''); - setPlanterIdentifier(''); + setGrowerIdentifier(''); setDateStart(dateStartDefault); setDateEnd(dateEndDefault); setApproved(); @@ -175,14 +175,14 @@ function Filter(props) { value={captureId} onChange={(e) => setCaptureId(e.target.value)} /> - + setPlanterId(e.target.value)} + value={growerId} + onChange={(e) => setGrowerId(e.target.value)} /> setDeviceIdentifier(e.target.value)} /> - + setPlanterIdentifier(e.target.value)} + value={growerIdentifier} + onChange={(e) => setGrowerIdentifier(e.target.value)} /> setPlanterId(e.target.value)} + value={growerId} + onChange={(e) => setGrowerId(e.target.value)} /> setDeviceId(e.target.value)} /> setPlanterIdentifier(e.target.value)} + htmlFor="grower-identifier" + id="grower-identifier" + label="Grower Identifier" + placeholder="e.g. grower@example.com" + value={growerIdentifier} + onChange={(e) => setGrowerIdentifier(e.target.value)} /> { }; }; -function FilterTopPlanter(props) { +function FilterTopGrower(props) { const { orgList, userHasOrg } = useContext(AppContext); const { classes, filter } = props; const [id, setId] = useState(filter?.id || ''); @@ -115,10 +115,10 @@ function FilterTopPlanter(props) { setId(e.target.value)} onKeyDown={handleEnterPress} @@ -233,4 +233,4 @@ function FilterTopPlanter(props) { ); } -export default withStyles(styles)(FilterTopPlanter); +export default withStyles(styles)(FilterTopGrower); diff --git a/src/components/PlanterDetail.js b/src/components/GrowerDetail.js similarity index 71% rename from src/components/PlanterDetail.js rename to src/components/GrowerDetail.js index b23dfe51a..5b2f3bf7f 100644 --- a/src/components/PlanterDetail.js +++ b/src/components/GrowerDetail.js @@ -11,23 +11,23 @@ import Person from '@material-ui/icons/Person'; import Divider from '@material-ui/core/Divider'; import EditIcon from '@material-ui/icons/Edit'; import Fab from '@material-ui/core/Fab'; -import api from '../api/planters'; +import api from '../api/growers'; import { getDateTimeStringLocale } from '../common/locale'; import { hasPermission, POLICIES } from '../models/auth'; import { AppContext } from '../context/AppContext'; -import { PlanterContext } from '../context/PlanterContext'; -import EditPlanter from './EditPlanter'; +import { GrowerContext } from '../context/GrowerContext'; +import EditGrower from './EditGrower'; import OptimizedImage from './OptimizedImage'; import LinkToWebmap from './common/LinkToWebmap'; -const PLANTER_IMAGE_SIZE = 441; +const GROWER_IMAGE_SIZE = 441; const useStyle = makeStyles((theme) => ({ box: { padding: theme.spacing(4), }, cardMedia: { - height: `${PLANTER_IMAGE_SIZE}px`, + height: `${GROWER_IMAGE_SIZE}px`, }, personBox: { display: 'flex', @@ -52,44 +52,45 @@ const useStyle = makeStyles((theme) => ({ }, imageContainer: { position: 'relative', - height: `${PLANTER_IMAGE_SIZE}px`, + height: `${GROWER_IMAGE_SIZE}px`, }, })); -const PlanterDetail = (props) => { - // console.log('render: planter detail'); +const GrowerDetail = (props) => { + // console.log('render: grower detail'); const classes = useStyle(); - const { planterId } = props; + const { growerId } = props; const appContext = useContext(AppContext); - const planterContext = useContext(PlanterContext); - const [planterRegistrations, setPlanterRegistrations] = useState(null); + const growerContext = useContext(GrowerContext); + const [growerRegistrations, setGrowerRegistrations] = useState(null); const [editDialogOpen, setEditDialogOpen] = useState(false); - const [planter, setPlanter] = useState({}); + const [grower, setGrower] = useState({}); const [deviceIdentifiers, setDeviceIdentifiers] = useState([]); useEffect(() => { - async function loadPlanterDetail() { - if (planter && planter.id !== planterId) { - setPlanter({}); + async function loadGrowerDetail() { + if (grower && grower.id !== growerId) { + setGrower({}); } - if (planterId) { - const match = await getPlanter({ - id: planterId, + if (growerId) { + const match = await getGrower({ + id: growerId, }); - setPlanter(match); + setGrower(match); if ( - !planterRegistrations || - (planterRegistrations.length > 0 && - planterRegistrations[0].planter_id !== planterId) + !growerRegistrations || + (growerRegistrations.length > 0 && + growerRegistrations[0].planter_id !== growerId) ) { - setPlanterRegistrations(null); - api.getPlanterRegistrations(planterId).then((registrations) => { + setGrowerRegistrations(null); + api.getGrowerRegistrations(growerId).then((registrations) => { + console.log('grower registrations: ', registrations); if (registrations && registrations.length) { const sortedRegistrations = registrations.sort((a, b) => a.created_at > b.created_at ? 1 : -1, ); - setPlanterRegistrations(sortedRegistrations); + setGrowerRegistrations(sortedRegistrations); setDeviceIdentifiers( sortedRegistrations .map((reg) => reg.device_identifier) @@ -100,17 +101,17 @@ const PlanterDetail = (props) => { } } } - loadPlanterDetail(); + loadGrowerDetail(); // eslint-disable-next-line - }, [planterId, planterContext.planters]); + }, [growerId, growerContext.growers]); - async function getPlanter(payload) { + async function getGrower(payload) { const { id } = payload; - let planter = planterContext.planters?.find((p) => p.id === id); // Look for a match in the context first - if (!planter) { - planter = await api.getPlanter(id); // Otherwise query the API + let grower = growerContext.growers?.find((p) => p.id === id); // Look for a match in the context first + if (!grower) { + grower = await api.getGrower(id); // Otherwise query the API } - return planter; + return grower; } function handleEditClick() { @@ -126,7 +127,7 @@ const PlanterDetail = (props) => { @@ -135,7 +136,7 @@ const PlanterDetail = (props) => { - Planter Detail + Grower Detail @@ -147,17 +148,17 @@ const PlanterDetail = (props) => { - {planter.imageUrl && ( + {grower.imageUrl && ( )} - {!planter.imageUrl && ( + {!grower.imageUrl && ( @@ -166,10 +167,10 @@ const PlanterDetail = (props) => { )} {hasPermission(appContext.user, [ POLICIES.SUPER_PERMISSION, - POLICIES.MANAGE_PLANTER, + POLICIES.MANAGE_GROWER, ]) && ( handleEditClick()} > @@ -179,49 +180,49 @@ const PlanterDetail = (props) => { - {planter.firstName} {planter.lastName} + {grower.firstName} {grower.lastName} - ID: + ID: Email address - {planter.email || '---'} + {grower.email || '---'} Phone number - {planter.phone || '---'} + {grower.phone || '---'} Person ID - {planter.personId || '---'} + {grower.personId || '---'} Organization - {planter.organization || '---'} + {grower.organization || '---'} Organization ID - {planter.organizationId || '---'} + {grower.organizationId || '---'} Country - {(planterRegistrations && - planterRegistrations + {(growerRegistrations && + growerRegistrations .map((item) => item.country) .filter( (country, i, arr) => @@ -235,11 +236,9 @@ const PlanterDetail = (props) => { Registered - {(planterRegistrations && - planterRegistrations.length > 0 && - getDateTimeStringLocale( - planterRegistrations[0].created_at, - )) || + {(growerRegistrations && + growerRegistrations.length > 0 && + getDateTimeStringLocale(growerRegistrations[0].created_at)) || '---'} @@ -258,13 +257,13 @@ const PlanterDetail = (props) => { - + > ); }; -export default PlanterDetail; +export default GrowerDetail; diff --git a/src/components/Planters.js b/src/components/Growers.js similarity index 70% rename from src/components/Planters.js rename to src/components/Growers.js index d8595513c..857fe8d63 100644 --- a/src/components/Planters.js +++ b/src/components/Growers.js @@ -1,5 +1,5 @@ /* - * Planter page + * Grower page */ import React, { useState, useEffect, useContext } from 'react'; import clsx from 'clsx'; @@ -19,14 +19,14 @@ import IconFilter from '@material-ui/icons/FilterList'; import { selectedHighlightColor, documentTitle } from '../common/variables.js'; import LinkToWebmap from './common/LinkToWebmap'; import Navbar from './Navbar'; -import FilterTopPlanter from './FilterTopPlanter'; +import FilterTopGrower from './FilterTopGrower'; import OptimizedImage from './OptimizedImage'; -import PlanterDetail from './PlanterDetail'; -import { PlanterContext } from '../context/PlanterContext'; +import GrowerDetail from './GrowerDetail'; +import { GrowerContext } from '../context/GrowerContext'; -// const log = require('loglevel').getLogger('../components/Planters'); +// const log = require('loglevel').getLogger('../components/Growers'); -const PLANTER_IMAGE_SIZE = 182; +const GROWER_IMAGE_SIZE = 182; const useStyles = makeStyles((theme) => ({ outer: { @@ -50,19 +50,19 @@ const useStyles = makeStyles((theme) => ({ }, cardContent: { padding: 0, - height: `${PLANTER_IMAGE_SIZE}px`, + height: `${GROWER_IMAGE_SIZE}px`, position: 'relative', }, selected: { border: `2px ${selectedHighlightColor} solid`, }, cardMedia: { - height: `${PLANTER_IMAGE_SIZE}px`, + height: `${GROWER_IMAGE_SIZE}px`, }, cardWrapper: { width: 200, }, - planterCard: { + growerCard: { borderRadius: 16, border: '1px solid rgba(0, 0, 0, 0.12)', boxShadow: 'none', @@ -125,37 +125,29 @@ const useStyles = makeStyles((theme) => ({ }, })); -const Planters = (props) => { - // log.debug('render: Planters...'); +const Growers = (props) => { + // log.debug('render: Growers...'); const classes = useStyles(props); - const planterContext = useContext(PlanterContext); + const growerContext = useContext(GrowerContext); const [isFilterShown, setFilterShown] = useState(false); const [isDetailShown, setDetailShown] = useState(false); - const [planterDetail, setPlanterDetail] = useState({}); + const [growerDetail, setGrowerDetail] = useState({}); /* - * effect to load page when mounted and initialize the title and planter count + * effect to load page when mounted and initialize the title and grower count */ useEffect(() => { - // log.debug('planters mounted', filter); - document.title = `Planters - ${documentTitle}`; + // log.debug('growers mounted', filter); + document.title = `Growers - ${documentTitle}`; }, []); useEffect(() => { - planterContext.load(); - }, [ - planterContext.pageSize, - planterContext.currentPage, - planterContext.filter, - ]); + growerContext.load(); + }, [growerContext.pageSize, growerContext.currentPage, growerContext.filter]); useEffect(() => { - planterContext.getCount(); - }, [ - planterContext.pageSize, - planterContext.currentPage, - planterContext.filter, - ]); + growerContext.getCount(); + }, [growerContext.pageSize, growerContext.currentPage, growerContext.filter]); function handleFilterClick() { if (isFilterShown) { @@ -166,19 +158,19 @@ const Planters = (props) => { } function handlePageChange(e, page) { - planterContext.changeCurrentPage(page); + growerContext.changeCurrentPage(page); } function handleChangePageSize(e, option) { - planterContext.changePageSize(option.props.value); + growerContext.changePageSize(option.props.value); } - function handlePlanterClick(planter) { + function handleGrowerClick(grower) { setDetailShown(true); - setPlanterDetail(planter); + setGrowerDetail(grower); } - const placeholderPlanters = Array(planterContext.pageSize) + const placeholderGrowers = Array(growerContext.pageSize) .fill() .map((_, index) => { return { @@ -187,16 +179,16 @@ const Planters = (props) => { }; }); - let plantersItems = (planterContext.isLoading - ? placeholderPlanters - : planterContext.planters - ).map((planter) => { + let growersItems = (growerContext.isLoading + ? placeholderGrowers + : growerContext.growers + ).map((grower) => { return ( - handlePlanterClick(planter)} - key={planter.id} - planter={planter} - placeholder={planter.placeholder} + handleGrowerClick(grower)} + key={grower.id} + grower={grower} + placeholder={grower.placeholder} /> ); }); @@ -205,12 +197,12 @@ const Planters = (props) => { ); @@ -232,10 +224,10 @@ const Planters = (props) => { ]} > {isFilterShown && ( - planterContext.updateFilter(filter)} - filter={planterContext.filter} + onSubmit={(filter) => growerContext.updateFilter(filter)} + filter={growerContext.filter} onClose={handleFilterClick} /> )} @@ -256,13 +248,13 @@ const Planters = (props) => { className={classes.title} > - Planters + Growers {pagination} - {plantersItems} + {growersItems} @@ -270,46 +262,46 @@ const Planters = (props) => { - setDetailShown(false)} /> ); }; -export function Planter(props) { - const { planter } = props; +export function Grower(props) { + const { grower } = props; const classes = useStyles(props); return (
props.onClick()} className={clsx(classes.cardWrapper)} - key={planter.id} + key={grower.id} > - {planter.imageUrl && ( + {grower.imageUrl && ( )} - {!planter.imageUrl && ( + {!grower.imageUrl && ( @@ -321,13 +313,13 @@ export function Planter(props) { - {planter.firstName} {planter.lastName} + {grower.firstName} {grower.lastName} - ID: + ID: - {planter.organization && ( - Organization: {planter.organization} + {grower.organization && ( + Organization: {grower.organization} )} @@ -336,4 +328,4 @@ export function Planter(props) {
); } -export default Planters; +export default Growers; diff --git a/src/components/Home.js b/src/components/Home.js index 59fddf3fa..eb3aaccbd 100644 --- a/src/components/Home.js +++ b/src/components/Home.js @@ -10,7 +10,7 @@ import { documentTitle } from '../common/variables'; import { AppContext } from '../context/AppContext'; import { hasPermission, POLICIES } from '../models/auth'; import { - DashStatPlanterCount, + DashStatGrowerCount, DashStatTotalCaptures, DashStatUnprocessedCaptures, DashStatVerifiedCaptures, @@ -195,7 +195,7 @@ function Home(props) { {hasPermission(appContext.user, [ POLICIES.SUPER_PERMISSION, POLICIES.LIST_PLANTER, - ]) && } + ]) && } diff --git a/src/components/Routers.js b/src/components/Routers.js index 5264de543..9c3ed55b6 100644 --- a/src/components/Routers.js +++ b/src/components/Routers.js @@ -32,6 +32,15 @@ export default function Routers() { + + {' '} + {/* cater for legacy naming */} + + {appContext.routes.map( ({ linkTo, exact = false, component, disabled }, idx) => ( { isOpen: false, capture: {}, }); - const [planterDetail, setPlanterDetail] = useState({ + const [growerDetail, setGrowerDetail] = useState({ isOpen: false, - planter: {}, + grower: {}, }); const refContainer = useRef(); @@ -218,11 +218,11 @@ const Verify = (props) => { window.open(url, '_blank').opener = null; } - function handlePlanterMapClick(e, planterId) { + function handleGrowerMapClick(e, growerId) { e.stopPropagation(); e.preventDefault(); - log.debug('click on planter:%d', planterId); - const url = `${process.env.REACT_APP_WEBMAP_DOMAIN}/?userid=${planterId}`; + log.debug('click on grower:%d', growerId); + const url = `${process.env.REACT_APP_WEBMAP_DOMAIN}/?userid=${growerId}`; window.open(url, '_blank').opener = null; } @@ -280,19 +280,19 @@ const Verify = (props) => { verifyContext.loadCaptureImages(); } - async function handleShowPlanterDetail(e, capture) { + async function handleShowGrowerDetail(e, capture) { e.preventDefault(); e.stopPropagation(); - setPlanterDetail({ + setGrowerDetail({ isOpen: true, - planterId: capture.planterId, + growerId: capture.planterId, }); } - function handleClosePlanterDetail() { - setPlanterDetail({ + function handleCloseGrowerDetail() { + setGrowerDetail({ isOpen: false, - planterId: null, + growerId: null, }); } @@ -376,9 +376,9 @@ const Verify = (props) => { handleShowPlanterDetail(e, capture)} - aria-label={`Planter details`} - title={`Planter details`} + onClick={(e) => handleShowGrowerDetail(e, capture)} + aria-label={`Grower details`} + title={`Grower details`} > @@ -403,9 +403,9 @@ const Verify = (props) => { variant="link" href={`${process.env.REACT_APP_WEBMAP_DOMAIN}/?userid=${capture.planterId}`} target="_blank" - onClick={(e) => handlePlanterMapClick(e, capture.planterId)} - aria-label={`Planter map`} - title={`Planter map`} + onClick={(e) => handleGrowerMapClick(e, capture.planterId)} + aria-label={`Grower map`} + title={`Grower map`} > @@ -574,10 +574,10 @@ const Verify = (props) => { className={classes.snackbar} /> )} - handleClosePlanterDetail()} + handleCloseGrowerDetail()} /> { const CAPTURE = { id: 0, planterId: 10, - planterIdentifier: 'planter@some.place', + planterIdentifier: 'grower@some.place', deviceIdentifier: 'abcdef123456', approved: true, active: true, @@ -112,7 +112,7 @@ describe('captureDetail', () => { it('loaded captureDetail', () => { // screen.logTestingPlaygroundURL(); - expect(screen.getByText(/planter@some.place/i)); + expect(screen.getByText(/grower@some.place/i)); expect(screen.getByText(/new_tree/i)); expect(screen.getByText(/simple_leaf/i)); }); diff --git a/src/components/tests/captures.test.js b/src/components/tests/captures.test.js index 7754dd17c..aada7964f 100644 --- a/src/components/tests/captures.test.js +++ b/src/components/tests/captures.test.js @@ -159,7 +159,7 @@ describe.skip('Captures', () => { expect(item).toBeInTheDocument(); item = within(table).getByText(/Capture ID/i); expect(item).toBeInTheDocument(); - item = within(table).getByText(/Planter ID/i); + item = within(table).getByText(/Grower ID/i); expect(item).toBeInTheDocument(); item = within(table).getByText(/Payment/i); expect(item).toBeInTheDocument(); diff --git a/src/components/tests/planters.test.js b/src/components/tests/growers.test.js similarity index 84% rename from src/components/tests/planters.test.js rename to src/components/tests/growers.test.js index 8817bfede..aa1b7b382 100644 --- a/src/components/tests/planters.test.js +++ b/src/components/tests/growers.test.js @@ -2,21 +2,21 @@ import React from 'react'; import { BrowserRouter } from 'react-router-dom'; import { act, render, screen, cleanup } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import api from '../../api/planters'; +import api from '../../api/growers'; import theme from '../common/theme'; import { ThemeProvider } from '@material-ui/core/styles'; import { AppProvider } from '../../context/AppContext'; -import { PlanterProvider } from '../../context/PlanterContext'; -import FilterPlanter from '../../models/FilterPlanter'; -import FilterTopPlanter from '../FilterTopPlanter'; -import Planters from '../Planters'; +import { GrowerProvider } from '../../context/GrowerContext'; +import FilterGrower from '../../models/FilterGrower'; +import FilterTopGrower from '../FilterTopGrower'; +import Growers from '../Growers'; import * as loglevel from 'loglevel'; -const log = loglevel.getLogger('../tests/planter.test'); +const log = loglevel.getLogger('../tests/grower.test'); -jest.mock('../../api/planters'); +jest.mock('../../api/growers'); -const PLANTER = { +const GROWER = { id: 1, firstName: 'testFirstName', lastName: 'testLastName', @@ -29,7 +29,7 @@ const PLANTER = { organizationId: 11, }; -const PLANTERS = [ +const GROWERS = [ { id: 1, firstName: 'testFirstName', @@ -77,72 +77,72 @@ const ORGS = [ }, ]; -describe('planters', () => { +describe('growers', () => { let api; - let planterValues; + let growerValues; beforeEach(() => { //mock the api - api = require('../../api/planters').default; + api = require('../../api/growers').default; api.getCount = () => { log.debug('mock getCount'); return Promise.resolve({ count: 2 }); }; - api.getPlanter = () => { - log.debug('mock getPlanter'); - return Promise.resolve(PLANTER); + api.getGrower = () => { + log.debug('mock getGrower'); + return Promise.resolve(GROWER); }; - api.getPlanters = () => { + api.getGrowers = () => { log.debug('mock load'); - return Promise.resolve(PLANTERS); + return Promise.resolve(GROWERS); }; }); describe('with a default context', () => { //{{{ beforeEach(async () => { - planterValues = { - planters: [], + growerValues = { + growers: [], pageSize: 24, count: null, currentPage: 0, - filter: new FilterPlanter(), + filter: new FilterGrower(), isLoading: false, - totalPlanterCount: null, + totalGrowerCount: null, load: () => {}, getCount: () => {}, changePageSize: () => {}, changeCurrentPage: () => {}, - getPlanter: () => {}, - updatePlanter: () => {}, - updatePlanters: () => {}, + getGrower: () => {}, + updateGrower: () => {}, + updateGrowers: () => {}, updateFilter: () => {}, - getTotalPlanterCount: () => {}, + getTotalGrowerCount: () => {}, }; render( - - - + + + , ); - await act(() => api.getPlanters()); + await act(() => api.getGrowers()); await act(() => api.getCount()); }); afterEach(cleanup); - it('renders subcomponents of filter top planter', () => { + it('renders subcomponents of filter top grower', () => { const filter = screen.getByRole('button', { name: /filter/i }); userEvent.click(filter); // screen.logTestingPlaygroundURL(); - expect(screen.getByLabelText('Planter ID')).toBeInTheDocument(); + expect(screen.getByLabelText('Grower ID')).toBeInTheDocument(); expect(screen.getByLabelText('Person ID')).toBeInTheDocument(); @@ -157,7 +157,7 @@ describe('planters', () => { expect(screen.getByLabelText(/phone number/i)).toBeInTheDocument(); }); - it('renders planter page', () => { + it('renders grower page', () => { expect( screen.getByText(/testFirstName testLastName/i), ).toBeInTheDocument(); @@ -175,7 +175,7 @@ describe('planters', () => { expect(screen.getByText('2')).toBeInTheDocument(); expect(screen.getByText('3')).toBeInTheDocument(); - const pageSize = screen.getAllByText(/planters per page:/i); + const pageSize = screen.getAllByText(/growers per page:/i); expect(pageSize).toHaveLength(2); }); }); diff --git a/src/components/tests/tags.test.js b/src/components/tests/tags.test.js index cda95441f..a6779b268 100644 --- a/src/components/tests/tags.test.js +++ b/src/components/tests/tags.test.js @@ -260,14 +260,14 @@ describe('tags', () => { expect(screen.getByLabelText(/end date/i)).toBeInTheDocument(); - expect(screen.getByLabelText('Planter ID')).toBeInTheDocument(); + expect(screen.getByLabelText('Grower ID')).toBeInTheDocument(); expect(screen.getByLabelText(/capture id/i)).toBeInTheDocument(); expect(screen.getByLabelText(/device identifier/i)).toBeInTheDocument(); expect( - screen.getByLabelText(/planter identifier/i), + screen.getByLabelText(/grower identifier/i), ).toBeInTheDocument(); expect(screen.getByLabelText(/species/i)).toBeInTheDocument(); diff --git a/src/components/tests/verify.test.js b/src/components/tests/verify.test.js index 840759536..19d60a8a6 100644 --- a/src/components/tests/verify.test.js +++ b/src/components/tests/verify.test.js @@ -3,15 +3,15 @@ import { BrowserRouter } from 'react-router-dom'; import { act, render, screen, cleanup } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import captureApi from '../../api/treeTrackerApi'; -import planterApi from '../../api/planters'; +import growerApi from '../../api/growers'; import theme from '../common/theme'; import { ThemeProvider } from '@material-ui/core/styles'; import { AppProvider } from '../../context/AppContext'; import { VerifyProvider } from '../../context/VerifyContext'; -import { PlanterProvider } from '../../context/PlanterContext'; +import { GrowerProvider } from '../../context/GrowerContext'; import { SpeciesProvider } from '../../context/SpeciesContext'; import { TagsProvider } from '../../context/TagsContext'; -import FilterPlanter from '../../models/FilterPlanter'; +import FilterGrower from '../../models/FilterGrower'; import FilterModel from '../../models/Filter'; import Verify from '../Verify'; @@ -19,13 +19,13 @@ import * as loglevel from 'loglevel'; const log = loglevel.getLogger('../tests/verify.test'); jest.setTimeout(7000); -jest.mock('../../api/planters'); +jest.mock('../../api/growers'); jest.mock('../../api/treeTrackerApi'); const CAPTURE = { id: 0, planterId: 10, - planterIdentifier: 'planter@some.place', + planterIdentifier: 'grower@some.place', deviceIdentifier: 'abcdef123456', approved: true, active: true, @@ -49,7 +49,7 @@ const CAPTURES = [ id: 10, uuid: '11942400-6617-4c6c-bf5e', planterId: 10, - planterIdentifier: 'planter1@some.place', + planterIdentifier: 'grower1@some.place', deviceIdentifier: '1-abcdef123456', approved: true, active: true, @@ -71,7 +71,7 @@ const CAPTURES = [ id: 20, uuid: '11942400-6617-4c6c-bf5e', planterId: 11, - planterIdentifier: 'planter2@some.place', + planterIdentifier: 'grower2@some.place', deviceIdentifier: '2-abcdef123456', approved: true, active: true, @@ -93,7 +93,7 @@ const CAPTURES = [ id: 30, uuid: '11942400-6617-4c6c-bf5e', planterId: 10, - planterIdentifier: 'planter3@some.place', + planterIdentifier: 'grower3@some.place', deviceIdentifier: '3-abcdef123456', approved: true, active: true, @@ -113,7 +113,7 @@ const CAPTURES = [ }, ]; -const PLANTER = { +const GROWER = { id: 1, firstName: 'testFirstName', lastName: 'testLastName', @@ -126,7 +126,7 @@ const PLANTER = { organizationId: 11, }; -const PLANTERS = [ +const GROWERS = [ { id: 1, firstName: 'testFirstName', @@ -201,31 +201,31 @@ const SPECIES = [ ]; describe('Verify', () => { - let planterApi; + let growerApi; let captureApi; - let planterValues; + let growerValues; let verifyValues; let speciesValues; let tagsValues; beforeEach(() => { - //mock the planters api - planterApi = require('../../api/planters').default; + //mock the growers api + growerApi = require('../../api/growers').default; - planterApi.getCount = () => { + growerApi.getCount = () => { log.debug('mock getCount:'); return Promise.resolve({ count: 2 }); }; - planterApi.getPlanter = () => { - log.debug('mock getPlanter:'); - return Promise.resolve(PLANTER); + growerApi.getGrower = () => { + log.debug('mock getGrower:'); + return Promise.resolve(GROWER); }; - planterApi.getPlanterRegistrations = () => { - log.debug('mock getPlanterRegistrations:'); + growerApi.getGrowerRegistrations = () => { + log.debug('mock getGrowerRegistrations:'); return Promise.resolve([]); }; - planterApi.getPlanterSelfies = (id) => { - log.debug('mock getPlanterSelfies:'); + growerApi.getGrowerSelfies = (id) => { + log.debug('mock getGrowerSelfies:'); return Promise.resolve([ { planterPhotoUrl: '' }, { planterPhotoUrl: '' }, @@ -268,23 +268,23 @@ describe('Verify', () => { describe('with default values', () => { //{{{ beforeEach(async () => { - planterValues = { - planters: PLANTERS, + growerValues = { + growers: GROWERS, pageSize: 24, count: null, currentPage: 0, - filter: new FilterPlanter(), + filter: new FilterGrower(), isLoading: false, - totalPlanterCount: null, + totalGrowerCount: null, load: () => {}, getCount: () => {}, changePageSize: () => {}, changeCurrentPage: () => {}, - getPlanter: () => {}, - updatePlanter: () => {}, - updatePlanters: () => {}, + getGrower: () => {}, + updateGrower: () => {}, + updateGrowers: () => {}, updateFilter: () => {}, - getTotalPlanterCount: () => {}, + getTotalGrowerCount: () => {}, }; verifyValues = { captureImages: CAPTURES, @@ -338,7 +338,7 @@ describe('Verify', () => { - {/* */} + {/* */} @@ -346,7 +346,7 @@ describe('Verify', () => { - {/* */} + {/* */} , @@ -391,23 +391,25 @@ describe('Verify', () => { userEvent.click(captureDetails[0]); // screen.logTestingPlaygroundURL(); expect(screen.getByText(/capture data/i)).toBeInTheDocument(); - expect(screen.getByText(/planter identifier/i)).toBeInTheDocument(); - expect(screen.getByText(/planter1@some.place/i)).toBeInTheDocument(); + expect(screen.getByText(/grower identifier/i)).toBeInTheDocument(); + expect(screen.getByText(/grower1@some.place/i)).toBeInTheDocument(); expect(screen.getByText(/device identifier/i)).toBeInTheDocument(); // expect(screen.getByText(/1 - abcdef123456/i)).toBeInTheDocument(); expect(screen.getByText(/verification status/i)).toBeInTheDocument(); expect(screen.getByText(/token status/i)).toBeInTheDocument(); }); - it('renders planter details', () => { - const planterDetails = screen.getAllByRole('button', { - name: /planter details/i, + it('renders grower details', () => { + const growerDetails = screen.getAllByRole('button', { + name: /grower details/i, }); - expect(planterDetails).toHaveLength(3); - userEvent.click(planterDetails[0]); + expect(growerDetails).toHaveLength(3); + userEvent.click(growerDetails[0]); // screen.logTestingPlaygroundURL(); - expect(screen.getByText(/planter detail/i)).toBeInTheDocument(); + expect(screen.getByText(/country/i)).toBeInTheDocument(); + expect(screen.getByText(/organization ID/i)).toBeInTheDocument(); + expect(screen.getByText(/person ID/i)).toBeInTheDocument(); expect(screen.getByText(/ID:/i)).toBeInTheDocument(); expect(screen.getByText(/email address/i)).toBeInTheDocument(); expect(screen.getByText(/phone number/i)).toBeInTheDocument(); diff --git a/src/context/AppContext.js b/src/context/AppContext.js index 749d88d44..f1c4bb509 100644 --- a/src/context/AppContext.js +++ b/src/context/AppContext.js @@ -3,7 +3,7 @@ import isEqual from 'react-fast-compare'; import axios from 'axios'; import VerifyView from '../views/VerifyView'; -import Planters from '../components/Planters'; +import Growers from '../components/Growers'; import CapturesView from '../views/CapturesView'; import Account from '../components/Account'; import Home from '../components/Home'; @@ -23,7 +23,7 @@ import IconPermIdentity from '@material-ui/icons/PermIdentity'; import CategoryIcon from '@material-ui/icons/Category'; import HomeIcon from '@material-ui/icons/Home'; import CompareIcon from '@material-ui/icons/Compare'; -import { PlanterProvider } from './PlanterContext'; +import { GrowerProvider } from './GrowerContext'; import { session, hasPermission, POLICIES } from '../models/auth'; import api from '../api/treeTrackerApi'; @@ -79,13 +79,13 @@ function getRoutes(user) { ]), }, { - name: 'Planters', - linkTo: '/planters', - component: Planters, + name: 'Growers', + linkTo: '/growers', + component: Growers, icon: IconNaturePeople, disabled: !hasPermission(user, [ POLICIES.SUPER_PERMISSION, - POLICIES.LIST_PLANTER, + POLICIES.LIST_GROWER, ]), }, { @@ -235,10 +235,10 @@ export const AppProvider = (props) => { checkSession(); } - // VerifyProvider and PlanterProvider need to wrap children here so that they are available when needed + // VerifyProvider and GrowerProvider need to wrap children here so that they are available when needed return ( - {props.children} + {props.children} ); }; diff --git a/src/context/GrowerContext.js b/src/context/GrowerContext.js new file mode 100644 index 000000000..950946e10 --- /dev/null +++ b/src/context/GrowerContext.js @@ -0,0 +1,125 @@ +import React, { useState, createContext } from 'react'; +import FilterGrower from '../models/FilterGrower'; +import api from '../api/growers'; +import * as loglevel from 'loglevel'; + +const log = loglevel.getLogger('../context/GrowerContext'); + +export const GrowerContext = createContext({ + growers: [], + pageSize: 24, + count: null, + currentPage: 0, + filter: new FilterGrower(), + isLoading: false, + totalGrowerCount: null, + load: () => {}, + getCount: () => {}, + changePageSize: () => {}, + changeCurrentPage: () => {}, + getGrower: () => {}, + updateGrower: () => {}, + updateGrowers: () => {}, + updateFilter: () => {}, + getTotalGrowerCount: () => {}, +}); + +export function GrowerProvider(props) { + const [growers, setGrowers] = useState([]); + const [pageSize, setPageSize] = useState(24); + const [count, setCount] = useState(null); + const [currentPage, setCurrentPage] = useState(0); + const [filter, setFilter] = useState(new FilterGrower()); + const [isLoading, setIsLoading] = useState(false); + const [totalGrowerCount, setTotalGrowerCount] = useState(null); + + // EVENT HANDLERS + + const changePageSize = async (pageSize) => { + setPageSize(pageSize); + }; + + const changeCurrentPage = async (currentPage) => { + setCurrentPage(currentPage); + }; + + const updateGrowers = (growers) => { + setGrowers(growers); + }; + + const load = async () => { + log.debug('load growers'); + setIsLoading(true); + const pageNumber = currentPage; + const growers = await api.getGrowers({ + skip: pageNumber * pageSize, + rowsPerPage: pageSize, + filter, + }); + setGrowers(growers); + setIsLoading(false); + }; + + const getCount = async () => { + const { count } = await api.getCount({ filter }); + setCount(count); + }; + + const getGrower = async (payload) => { + const { id } = payload; + // Look for a match in the local state first + let grower = growers.find((p) => p.id === id); + if (!grower) { + // Otherwise query the API + grower = await api.getGrower(id); + } + return grower; + }; + + const updateGrower = async (payload) => { + await api.updateGrower(payload); + const updatedGrower = await api.getGrower(payload.id); + const index = growers.findIndex((p) => p.id === updatedGrower.id); + if (index >= 0) { + const growers = Object.assign([], growers, { + [index]: updatedGrower, + }); + setGrowers(growers); + } + }; + + const updateFilter = async (filter) => { + setCurrentPage(0); + setFilter(filter); + }; + + const getTotalGrowerCount = async () => { + const { count } = await api.getCount({}); + setTotalGrowerCount(count); + }; + + const value = { + growers, + pageSize, + count, + currentPage, + filter, + isLoading, + totalGrowerCount, + load, + getCount, + changePageSize, + changeCurrentPage, + getGrower, + updateGrower, + updateGrowers, + updateFilter, + getTotalGrowerCount, + }; + + return ( + + {props.children} + + ); +} diff --git a/src/context/PlanterContext.js b/src/context/PlanterContext.js deleted file mode 100644 index 1aba22dc4..000000000 --- a/src/context/PlanterContext.js +++ /dev/null @@ -1,125 +0,0 @@ -import React, { useState, createContext } from 'react'; -import FilterPlanter from '../models/FilterPlanter'; -import api from '../api/planters'; -import * as loglevel from 'loglevel'; - -const log = loglevel.getLogger('../context/PlanterContext'); - -export const PlanterContext = createContext({ - planters: [], - pageSize: 24, - count: null, - currentPage: 0, - filter: new FilterPlanter(), - isLoading: false, - totalPlanterCount: null, - load: () => {}, - getCount: () => {}, - changePageSize: () => {}, - changeCurrentPage: () => {}, - getPlanter: () => {}, - updatePlanter: () => {}, - updatePlanters: () => {}, - updateFilter: () => {}, - getTotalPlanterCount: () => {}, -}); - -export function PlanterProvider(props) { - const [planters, setPlanters] = useState([]); - const [pageSize, setPageSize] = useState(24); - const [count, setCount] = useState(null); - const [currentPage, setCurrentPage] = useState(0); - const [filter, setFilter] = useState(new FilterPlanter()); - const [isLoading, setIsLoading] = useState(false); - const [totalPlanterCount, setTotalPlanterCount] = useState(null); - - // EVENT HANDLERS - - const changePageSize = async (pageSize) => { - setPageSize(pageSize); - }; - - const changeCurrentPage = async (currentPage) => { - setCurrentPage(currentPage); - }; - - const updatePlanters = (planters) => { - setPlanters(planters); - }; - - const load = async () => { - log.debug('load planters'); - setIsLoading(true); - const pageNumber = currentPage; - const planters = await api.getPlanters({ - skip: pageNumber * pageSize, - rowsPerPage: pageSize, - filter, - }); - setPlanters(planters); - setIsLoading(false); - }; - - const getCount = async () => { - const { count } = await api.getCount({ filter }); - setCount(Number(count)); - }; - - const getPlanter = async (payload) => { - const { id } = payload; - // Look for a match in the local state first - let planter = planters.find((p) => p.id === id); - if (!planter) { - // Otherwise query the API - planter = await api.getPlanter(id); - } - return planter; - }; - - const updatePlanter = async (payload) => { - await api.updatePlanter(payload); - const updatedPlanter = await api.getPlanter(payload.id); - const index = planters.findIndex((p) => p.id === updatedPlanter.id); - if (index >= 0) { - const planters = Object.assign([], planters, { - [index]: updatedPlanter, - }); - setPlanters(planters); - } - }; - - const updateFilter = async (filter) => { - setCurrentPage(0); - setFilter(filter); - }; - - const getTotalPlanterCount = async () => { - const { count } = await api.getCount({}); - setTotalPlanterCount(count); - }; - - const value = { - planters, - pageSize, - count, - currentPage, - filter, - isLoading, - totalPlanterCount, - load, - getCount, - changePageSize, - changeCurrentPage, - getPlanter, - updatePlanter, - updatePlanters, - updateFilter, - getTotalPlanterCount, - }; - - return ( - - {props.children} - - ); -} diff --git a/src/models/FilterPlanter.js b/src/models/FilterGrower.js similarity index 96% rename from src/models/FilterPlanter.js rename to src/models/FilterGrower.js index 918b93306..d6f04790f 100644 --- a/src/models/FilterPlanter.js +++ b/src/models/FilterGrower.js @@ -1,7 +1,7 @@ import { stringToSearchRegExp } from '../utilities'; -/** - * A simple model for planter filter +/* + * A simple model for grower filter */ export const ALL_ORGANIZATIONS = 'ALL_ORGANIZATIONS'; diff --git a/src/models/FilterPlanter.test.js b/src/models/FilterGrower.test.js similarity index 69% rename from src/models/FilterPlanter.test.js rename to src/models/FilterGrower.test.js index af2391e06..83d30eb5c 100644 --- a/src/models/FilterPlanter.test.js +++ b/src/models/FilterGrower.test.js @@ -2,13 +2,13 @@ import React from 'react'; import ReactDOM from 'react-dom'; import { render, screen } from '@testing-library/react'; import { AppContext, AppProvider } from '../context/AppContext'; -import FilterPlanter from './FilterPlanter'; +import Filter from './FilterGrower'; -describe.skip('FilterPlanter, with initial filter values', () => { - let filterPlanter; +describe.skip('FilterGrower, with initial filter values', () => { + let filterGrower; beforeEach(() => { - filterPlanter = new FilterPlanter({ + filterGrower = new Filter({ personId: 1, firstName: 'fn', lastName: 'ln', @@ -17,7 +17,7 @@ describe.skip('FilterPlanter, with initial filter values', () => { }); it('getWhereObj() should be: ', () => { - expect(filterPlanter.getWhereObj()).toEqual( + expect(filterGrower.getWhereObj()).toEqual( expect.objectContaining({ firstName: { ilike: 'fn' }, id: 1, diff --git a/src/models/auth.js b/src/models/auth.js index 4d6569c57..d511f64ae 100644 --- a/src/models/auth.js +++ b/src/models/auth.js @@ -1,7 +1,7 @@ const PERMISSIONS = { ADMIN: 1, TREE_AUDIT: 2, - PLANTER: 3, + GROWER: 3, }; const POLICIES = { @@ -10,8 +10,8 @@ const POLICIES = { MANAGER_USER: 'manager_user', LIST_TREE: 'list_tree', APPROVE_TREE: 'approve_tree', - LIST_PLANTER: 'list_planter', - MANAGE_PLANTER: 'manage_planter', + LIST_GROWER: 'list_planter', + MANAGE_GROWER: 'manage_planter', }; function hasPermission(user, p) {