Components
-
Site Information
-
Biomass
-
Water sensors
-
Stress Cams
Source: src/Landing/TaskTimeline/TaskTimeline
Renders Timeline data from PSA Internal WordPress via the WP-JSON API
Source: src/Protocols/Protocols
Renders Protocols data from PSA Internal WordPress via the WP-JSON API
Source: src/ProducerInformation/ProducerInformation.js
Fetches producer information from the OnFarm API and uses material-table to display the information in a table. Some users would be able to use the edit
feature from the table. Users with any of the
const allowEditing = () => {
let permissions = state.userInfo.permissions;
const allowedPermissions = ["edit", "update", "all"];
return permissions.split(",").some((i) => allowedPermissions.includes(i));
};
permissions within the users table in RAW DB, would be able to edit producer information.
The allowEditing
function checks logged in user's permissions and returns a bool
true or false as response.
The table only allows the following fields to be edited:-
- First Name
- Last Name/Org Name
- Phone
Other fields available as read-only are
- Producer ID
- Site Codes
- Years
source: src/SiteInformation/Enrollment/SiteInformation/Enrollment.js
Enrolls new sites for existing farmers
Enrolls/adds new farmer and then enroll site for the farmer
Shows total sites enrolled within a user-specific set of affiliations (from users table in RAW DB)
Component Hierarchy:
Provides a button to enroll new sites and display sites affiliated per user affiliation permissions
-
Wrapper component that is activated when a user clicks on the enroll new site button
-
Lets users search for the existing growers and/or create a new grower record into the Postgres database. Once we have a grower ID, renders the NewSiteInfo component to get site details with the specific grower id
-
values for sites including state, county, address, lat, long, additional contact, notes, etc
> Fetches unused site codes and let users edit default
-
-
EnrollNewSite.propTypes = {
setEnrollNewSite: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
setSaveData: PropTypes.oneOfType([PropTypes.node, PropTypes.func]),
enrollNewSite: PropTypes.bool,
};
Renders a table with contact and location details for sites including site code, grower name, affiliation, county, year, address, latlongs, additional contact, phone number, email and notes.
The component checks if a user has edit permissions, and if they do, it enables the "unenroll" button which replaces any null values for a site in the site-information table in the Postgres database with "-999". Note: This feature might change in future and replaced with a different logic to unenroll a site.
Source: src/SiteInformation/FarmDates/FarmDates.js
The dates component fetches onfarm dates
API to display farm dates in a tabular and calendar view. The calendar view depends on the react-big-calendar
library
FarmDatesDropdown is a nested component within this component, which, on click of the table dropdown, renders another table with subplot
, subsample
and TX
Actual values from the API.
Source: src/Biomass/FarmValues.js
Renders tabular biomass data from the onfarm biomass?subplot=separate
API, with a toggle switch that converts default (kg/ha) values to lbs/ac
Note: This component is unoptimised and significantly slows down rendering on the front-end. Needs further introspection since it's a work in progress
Fetches data from the following endpoints and tries to do a LEFT JOIN
on the response.
const freshRecords = await fetchRecords(
onfarmAPI + `/raw?table=decomp_biomass_fresh`
);
const dryRecords = await fetchRecords(
onfarmAPI + `/raw?table=decomp_biomass_dry`
);
const cnRecords = await fetchRecords(
onfarmAPI + `/raw?table=decomp_biomass_cn`
);
const ashRecords = await fetchRecords(
onfarmAPI + `/raw?table=decomp_biomass_ash`
);
Once the records from these four endpoints are joined together, they are rendered in a material-table
based table.
This is a universal parent component for both, water sensors and stress cams.
Source: src/Devices/WaterSensors/WaterSensors.js
Source: src/Devices/StressCams/StressCams.js
Both the files load relevant device data (based on separate hologram API keys stored in the PHP API) from hologram using a PHP API wrapper to circumvent CORS error from Hologram.
Once all the devices are fetched, they are passed as a prop
to the common child component called DevicesComponent
.
DevicesComponent.propTypes = {
/* show devices or not? depends if user has permissions */
showDevices: PropTypes.bool.isRequired,
/* checks if the API is still trying to fetch devices */
loading: PropTypes.bool.isRequired,
/* an array of device data from hologram */
devices: PropTypes.array.isRequired,
/* Logged in user's info */
userInfo: PropTypes.object,
/* Current active tag to filter devices with, default is 'All'*/
activeTag: PropTypes.string,
/* Is this being rendered for water-sensors or stress-cams */
for: PropTypes.string,
/* From what component has this child component been called */
from: PropTypes.string,
};
DevicesComponent
renders clickable cards from the DataParser
component, which is linked to the <DeviceComponent />
at src/Devices/Device/Device.js
with a dynamic URL based on the specific device.id
from hologram.
The cards from DevicesComponent also let users edit/set nicknames to their devices, the default being the actual device.name
from hologram. Any nickname added/edited is reflected in the RAW database in the hologram_device_names
table.
The <DeviceComponent />
fetches device data and timestamp via device.id
from hologram and renders it in an infinite scroll based table.
The chart view component consists of two components, the parent component called SensorVisuals
is located at src/SensorVisuals/SensorVisuals.js
SensorVisuals
has a child component called FarmCodeCard
located at src/SensorVisuals/Components/FarmCodeCard.js
that renders card based clickable farm codes.
This component fetches the onfarm API endpoint raw?table=site_information
, then renders cards with the data from its child component (FarmCodeCard
), along with a search box to search for codes and year chips to filter codes by year. The default selected year would be the highest year record from the onfarm API.
On click of a card, VisualsByCode
component is rendered by react-router-dom
with the year and code as url parameters. The VisualsByCode
component then fetches multiple onfarm endpoints to render charts via Highcharts and all the individual charts are within the components
folder within the SensorVisuals
directory.
- Renders issues from Github, and on click of the comments button, loads the
<Issue />
component that renders the issue body along with a markdown enabled text editor to add comments to the issue. - The
<SingleIssueBodyBubble />
within the<Issue />
component renders the parent issue body, not the comments. All comments to the issue body are rendered by the<IssueBubbleBody />
component. This abstracts the body vs comment problem with the UI, and the dashboard can then simulate a chat based UI to a user.
The forms component fetches all kobo forms via their API using our in-house CORS wrapper built on top of PHP API, and renders all kobo form names in a stacked horizontal view.
On clicking a form card, the <FormData />
component is rendered, with the _xform_id_string
as a url parameter.
Form submissions are then fetched from the PHP API using the value of _xform_id_string
.
The FormData component also looks up the kobo_passwords
table and filters form results based on the username field, but shows all results for 'All' in users permissions.
Some of the JSX components that are used in multiple places:
- IssueDialog
- AffiliationsChips
- CustomLoader
- YearsChips
- YearsAndAffiliations
Some of the near future changes that I can think of:
- Use TypeScipt along with
ts-lint
instead of the current config (es-lint
withJavaScript
) - Airbnb slyge guide and conventions
- Docker setup and CI/CD workflow
- Using JWT tokens from Auth0 instead on relying on the
.env
file - Migrate from
@auth0/auth0-spa-js
to@auth0/auth0-react
- Decoupling tightly-coupled components and prefer using pure components instead
- Testing
- The .env file is currently located here. Using JWT would be ideal instead.
- The Timeline and Protocols components would work fine until and unless the respective pages are deleted or replaced from the WordPress dashboard, in which case, the hardcoded page ID’s in the URLS would need to be replaced (https://github.com/precision-sustainable-ag/tech-dashboard/blob/5eee5d0cb6d8e7943936439a46186524cfac8539/src/Landing/TaskTimeline/TaskTimeline.js#L15)