-
Notifications
You must be signed in to change notification settings - Fork 6
Feature 2298 check ins report query parameters #2304
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c22da38
a30c454
bdda5a8
a9a5673
260dbff
44262ea
5a5a7cb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,8 +21,21 @@ import { useEffect } from 'react'; | |
| /** | ||
| * @param {(QPBoolean | QPString)[]} qps - query parameters | ||
| */ | ||
| export const useQueryParameters = qps => { | ||
| export const useQueryParameters = ( | ||
| qps, | ||
| requirements = [], | ||
| processedQPs = null | ||
| ) => { | ||
| // This examines all the query parameters and | ||
| // sets the state value associated with each of them. | ||
| useEffect(() => { | ||
| if (processedQPs?.current) return; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the page supplied a value for |
||
|
|
||
| const haveRequirements = requirements.every(req => | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If |
||
| Array.isArray(req) ? req.length > 0 : req !== null && req !== undefined | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When a required value is an array, the requirement is met when the array is not empty. |
||
| ); | ||
| if (!haveRequirements) return; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the requirements are not met then we cannot processed the query parameters yet. |
||
|
|
||
| const url = new URL(location.href); | ||
| const params = url.searchParams; | ||
| for (const qp of qps) { | ||
|
|
@@ -34,13 +47,21 @@ export const useQueryParameters = qps => { | |
| qp.setter(v || qp.default); | ||
| } | ||
| } | ||
| }, []); | ||
| if (processedQPs) processedQPs.current = true; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the caller supplied this ref, we need to set its value to to |
||
| }, requirements); | ||
|
|
||
| const dependencies = qps.map(qp => qp.value); | ||
|
|
||
| // This updates the query parameters in the URL | ||
| // when their associated state values change. | ||
| useEffect(() => { | ||
| const haveRequirements = requirements.every(req => | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the requirements have not been met then we cannot update the query parameters. |
||
| Array.isArray(req) ? req.length > 0 : req !== null && req !== undefined | ||
| ); | ||
| if (!haveRequirements) return; | ||
|
|
||
| const url = new URL(location.href); | ||
| let newUrl = url.origin + url.pathname; | ||
| const baseUrl = url.origin + url.pathname; | ||
| const params = {}; | ||
|
|
||
| // Add query parameters listed in qps that do not have their default value. | ||
|
|
@@ -55,10 +76,12 @@ export const useQueryParameters = qps => { | |
| if (!qps.some(qp => qp.name === k)) params[k] = v; | ||
| } | ||
|
|
||
| if (Object.keys(params).length) { | ||
| newUrl += '?' + new URLSearchParams(params).toString(); | ||
| const search = Object.keys(params).length | ||
| ? '?' + new URLSearchParams(params).toString() | ||
| : ''; | ||
| if (search !== url.search) { | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Only update the URL if the query parameters have changed. |
||
| history.replaceState(params, '', baseUrl + search); | ||
| } | ||
| history.replaceState(params, '', newUrl); | ||
| }, dependencies); | ||
| }; | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,14 +1,16 @@ | ||
| import React, { useContext, useEffect, useState } from 'react'; | ||
| import React, { useContext, useEffect, useRef, useState } from 'react'; | ||
|
|
||
| import { TextField } from '@mui/material'; | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Minor reordering of imports. |
||
| import Autocomplete from '@mui/material/Autocomplete'; | ||
|
|
||
| import { AppContext } from '../context/AppContext'; | ||
| import CheckinReport from '../components/reports-section/CheckinReport'; | ||
| import { | ||
| selectCheckinPDLS, | ||
| selectTeamMembersWithCheckinPDL | ||
| } from '../context/selectors'; | ||
|
|
||
| import { TextField } from '@mui/material'; | ||
| import Autocomplete from '@mui/material/Autocomplete'; | ||
| import { isArrayPresent } from '../helpers/checks'; | ||
| import { useQueryParameters } from '../helpers/query-parameters'; | ||
|
|
||
| import './CheckinsReportPage.css'; | ||
|
|
||
|
|
@@ -26,6 +28,31 @@ const CheckinsReportPage = () => { | |
| }); | ||
| const [filteredPdls, setFilteredPdls] = useState(pdls); | ||
|
|
||
| const processedQPs = useRef(false); | ||
| useQueryParameters( | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This adds support for the |
||
| [ | ||
| { | ||
| name: 'pdls', | ||
| default: [], | ||
| value: selectedPdls, | ||
| setter(ids) { | ||
| const newPdls = ids.map(id => pdls.find(pdl => pdl.id === id)); | ||
| setSelectedPdls(newPdls); | ||
| }, | ||
| toQP(newPdls) { | ||
| if (isArrayPresent(newPdls)) { | ||
| const ids = newPdls.map(pdl => pdl.id); | ||
| return ids.join(','); | ||
| } else { | ||
| return []; | ||
| } | ||
| } | ||
| } | ||
| ], | ||
| [pdls], | ||
|
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The requirements for processing query parameters for this page are to have entries in the |
||
| processedQPs | ||
| ); | ||
|
|
||
| useEffect(() => { | ||
| if (!pdls) return; | ||
| pdls.map( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some pages require data to be loaded before query parameters can be processed. This page is one of them. We must have an array of all possible PDL objects in order to call
setSelectedPdlswith an array of PDL objects that have ids that match those in thepdlsquery parameter. Support this was extremely difficult and did not increase my love of React. ;-)requirementsis an array of data values that must be set in order to process the query parameters. It defaults to an empty array because most pages do not need this.processedQPsis an object created by a call touseRefin the calling page. It holds a Boolean that indicates whether we have finished processing the query parameters. This can only happen after all therequirementsvalues are present. I'm using a ref because the value needs to be maintained across multiple renders of the page which React loves to do. I'm open to suggestions for other ways to maintain this flag.