Add an API parameter and UI to filter facility list items by status #507
Conversation
I'd like to discuss our options for dealing with the situation where you have filtered the list to see only The solution I am thinking about implementing is to pass the Does this sound like a good plan? |
This makes sense to me. I was thinking about the general problem outside of this particular solution and came up with a similar-ish idea that put the re-fetch-page logic on the frontend. The client "knows" in some way which filter is applied, so if the The potential upside of this is that it would not require adding conditional logic to the API endpoints; a potential downside is that it'd push the re-fetch logic into a React component's If we were to put the conditional logic in the API accept/reject handlers, I think that it'd make sense to have the client have to pass an additional querystring parameter along with page/rowsPerPage/status: something like |
Detecting the change on the client side and making a follow up request is compelling. As I was thinking about implementing that I realized that if the contributor is scrolled to the bottom of a page of 100 results when they approve a pending match, triggering a page refresh will result in scrolling them back to the top of the page. We may be able to work around it by avoiding or updating I think I'll move ahead with the client-side approach. |
I implemented refreshing after approving/rejecting potential matches. Thanks for the design suggestion. It worked out well. This is ready for review. |
fetchListItems(listID, newPage + 1, rowsPerPage, params); | ||
}; | ||
const params = createParamsFromQueryString(search); | ||
if (params.status && params.status.includes('POTENTIAL_MATCH') && items && prevProps.items) { |
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.
Do we have POTENTIAL_MATCH
set as a constant somewhere in the app? If so we could consider checking on the constant value here; if not, we could add one?
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.
Looks like it's set on the facilityListItemStatusChoicesEnum
.
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.
Addressed in fixup ca65c8c
fetchListItems(listID, 1, rowsPerPage, newParams); | ||
}; | ||
|
||
const handleShowAllClicked = () => { |
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.
Now that this is a class component I think it'd make sense to move these functions out of render
and make them class methods. I think they could just be cut and paste, and then callers updated to call them with this.whatever
.
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.
I did some reading and discovered that defining closures inside render
like this is a performance drag because since redefining these functions every time triggers unnessesary rendering. Thanks for suggestion.
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.
Addressed in fixup 02efe99
return Object.freeze({ status }); | ||
return Array.isArray(status) | ||
? Object.freeze({ status }) | ||
: Object.freeze({ status: [status] }); |
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.
Consider updating the test to check for this new outcome.
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.
Added tests in fixup b1e998a
@@ -185,6 +185,22 @@ export const createPaginationOptionsFromQueryString = (qs) => { | |||
}); | |||
}; | |||
|
|||
export const createParamsFromQueryString = (qs) => { |
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.
Consider adding a test for this new function.
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.
Added tests in fixup b1e998a
{tableRows} | ||
<ShowOnly when={listIsEmpty}> | ||
<TableRow> | ||
<TableCell colSpan={5} style={{textAlign: 'center'}}> |
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.
Looks like civicci's seeing a linter error here resolvable by adding a space before and after textAlign: 'center'
.
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.
Addressed in fixup 0aeb695
This is working as expected otherwise! |
bc96f9b
to
b1e998a
Compare
Thanks for the great review. I addressed all of your comments and this is ready for another look. |
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.
👍 I tested this out again with the fixups and everything's working well!
cf2cdcb
to
913ceef
Compare
In a list of thousands of facilities there may only be a few dozen that require the contributor to approve or reject a potential match. Adding a filter by status will allow us to display this subset of list items.
NEW_FACILITY is not a real workflow state. A `FacilityListItem` is considered a NEW_FACILITY when it has a bidirectional relationship with a `Facility`. We want to avoid showing NEW_FACILITY items when filtering by the MATCHED or CONFIRMED_MATCH statuses. To handle all of this we create a set of special case filter statements and compose them together with `status=` statements for the other statuses.
In order to page through a list of facilities filtered by status we need to include a status parameter along with the existing page number and items per page parameters. In addition to passing the new status param to the API we are also updating the pagingation UI to show the filtered count rather than the total list count
Follows the pattern of how page number and items per page changes are handled. Changing the status filter will change the number of possible pages, so we are always resetting the page number to 1.
If you have filtered the list of facility list items by `POTENTIAL_MATCH` and then confirm or reject an item we need to update the current page since the count of items in the `POTENTIAL_MATCH` status is now different. To accomplish this we convert the FacilityListItemsTable from a functional to a class component so we can add logic to `componentDidUpdate` that conditionally triggers a refresh.
Now that people are able to filter the list items, it is possible to have an empty table. Adding a "No matching items" message creates a distinction between the loading and empty states.
Creating closures inside of the `render` function can lead to extraneous rendering.
913ceef
to
79cfddd
Compare
Thanks again for the great feedback. |
Overview
Allow facility list items to be filtered by selecting one or more statuses. It is an uncommon situation in a thousand item list to only have a dozen potential matches. Having a filter makes it dramatically easier to find and act on these items.
Connects #504
Demo
Testing Instructions
./scripts/resetdb
./scripts/processfixtures
c8@example.com
POTENTIAL_MATCH
and approve one of the matches. Verify that the item disappears from the table and the item count is correctly updated.Checklist
fixup!
commits have been squashed