-
Notifications
You must be signed in to change notification settings - Fork 0
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
Update Project Household Enrollments table with new designs #989
Conversation
src/modules/hmis/hmisUtil.ts
Outdated
|
||
// TODO @MARTHA discuss - it's probably a bit silly to redefine ranks here, | ||
// see https://github.com/greenriver/hmis-warehouse/blob/1a170c0e869fd3d69880532f86baa104b800d9ed/drivers/hmis/app/graphql/types/hmis_schema/enums/hud.rb#L723-L733 | ||
const hohPriorityMapping: Record<RelationshipToHoH, number> = { |
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.
This is for sorting the household members by their relationship to HoH. This definition of the ordering is redundant with the backend enum definition, so I wanted to discuss whether there's a better way to pass that info to the frontend.
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 don't think it's redundant with the backend. The enum lists out the values which are the HUD numeric values (Eg child = 2) whereas here you're specifying a custom order for displaying household members. It seems correct to me that this would live on the frontend.
return ( | ||
<> | ||
<TableBody | ||
// TODO @martha - discuss these TableBodies to achieve the `rowgroup` role, is it worth it? |
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.
Using the role='rowgroup'
turned out to be a bit complicated because of MUI expectations around usage of the TableBody
, TableRow
and TableCell
components. We can't directly have renderRow
return a <div role='rowgroup'>
which contains all the TableRow
s within it, because MUI expects that TableRow
is a direct child of TableBody
. (Here's a screenshot of what happens:)
Rendering each household as its own tbody
is the best solution I was able to come up with, but I'm not a huge fan -- both because of the messy markup and because of bloating the already complicated GenericTable
api. Let me know if you can think of any better solutions. Or, we could skip using rowgroup
. I think the accessibility is still better than before. We could, for example, give the row header cell additional accessible text specifying the household (HoH name or household ID) that would be read when navigating the screen with a screenreader.
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.
using several tbody
s seems like a fine approach. from mdn,
It's permitted to use more than one per table as long as they are all consecutive. This allows to divide the rows ( elements) in large tables into sections, each of which may be separately formatted if so desired.
That seems like basically what we are doing.
overrideTableBody
prop maybe isn't the clearest as to what it's doing, since it's really omitting the tbody
tag entirely, not overriding it. Maybe another idea is passing TableBodyComponent={React.Fragment}
where the default is TableBodyComponent = TableBody
, then the passed component can be used directly? Either seems OK.
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.
Ok, thank you for validating the overall approach! I like your api suggestion, took a stab at implementing that here: 3586e74
@@ -0,0 +1,26 @@ | |||
import { Card } from '@mui/material'; |
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.
We could add more stories here to test different cases, but I was thinking to leave it as is and create more fleshed-out stories for GenericTable
with 6761, or later. Let me know what you think.
src/modules/projects/components/tables/ProjectHouseholdsTable.tsx
Outdated
Show resolved
Hide resolved
// This should only be used by tables that take over rendering using renderRow and render a `tbody` within their custom render fn | ||
overrideTableBody?: boolean; | ||
injectBelowRows?: ReactNode; // component to inject below all rendered rows, above footer | ||
getTableRowActions?: (record: T) => TableRowActionsType; |
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'm wondering about the decision to make this a prop as opposed to just another column definition, can you say more about that? It does add more complexity to the already-complex GenericTable, so just wanting to think that through.
By a column definition, I mean:
const columns = [
...othercols,
{
key: 'actions',
render: (enrollment) => (
<TableRowActions
record={enrollment}
primaryAction={viewEnrollmentMenuItemConfig(enrollment}
secondaryActions={[viewClientMenuItemConfig(enrollment)]}
/>
),
},
]
...
<GenericTableWithData columns={columns} />
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.
Looking at https://github.com/greenriver/hmis-frontend/pull/998/files, I wonder if this would also give us some more flexibility for use-cases when the action button is more complex. I haven't quite wrapped my head around everything yet, but would something like this simplify the changes in the other PR ?
Definitely an early thought, I'm sure there are things I'm missing about the implementation.
const columns = [
...othercols,
{
key: 'actions',
render: (enrollment) => (
<TableRowActions
record={enrollment}
// use this prop if the primary action is a simple navigation
primaryActionConfig={viewEnrollmentMenuItemConfig(enrollment}
// use this prop if the primary action is more complicated, or if needs some special treatment
renderPrimaryAction={<AssignServiceButton .... />}
// maybe secondary actions are always expected to be navigation
secondaryActionsConfig={[viewClientMenuItemConfig(enrollment)]}
/>
),
},
]
...
<GenericTableWithData columns={columns} />
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 didn't think thoroughly about it, but it was based on the idea that, since this is a new pattern implemented consistently across many tables in the app, we want the common table component to guide usage and force consistency.
Thinking beyond table row actions, the logical conclusion of that train of thought is that all table controls, like search, filter, toggle, add-record button, etc. live as props on the GenericTable. That doesn't seem desirable - it certainly would lead to a bloated GenericTable. But I guess forcing consistency is the one upside. Currently we rely on GenericTable callers to implement search bars and add-one buttons consistently every time, and there are places in the app where we aren't consistent. (For example, search and toggle on enrollments table vs. search on projects/orgs.)
Anyway, I guess those considerations seem out of scope... I don't feel strongly about it and can take a stab at implementing your 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.
quick example of the consistency issue I'm mentioning, as actually applied to table row actions: https://github.com/greenriver/hmis-frontend/blob/martha/6825-hh-member-row/src/components/elements/table/GenericTable.tsx#L259-L261 By moving this out of GenericTable and into a regular column definition, we leave the column header (or lack thereof / accessibility thereof) up to the caller
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've taken a shot at the refactor, I'd like to look at it together tomorrow: https://github.com/greenriver/hmis-frontend/compare/martha/6761-tables...martha/6761-tables-refactor?expand=1
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.
we leave the column header (or lack thereof / accessibility thereof) up to the caller
This seems like something that should be addressed globally for all columns. The ColumnDef has the header
attribute as optional, so any column could be missing a header and become inaccessible.
Looking at how we implement the Header cells:
hmis-frontend/src/components/elements/table/GenericTable.tsx
Lines 225 to 236 in 91e938c
{columns.map((def, i) => ( | |
<HeaderCell | |
key={key(def) || i} | |
sx={{ | |
...(headerCellSx ? headerCellSx(def) : undefined), | |
textAlign: def.textAlign, | |
width: def.width, | |
}} | |
> | |
<strong>{def.header}</strong> | |
</HeaderCell> | |
))} |
it could be modified so that it sets a hidden header if no visible header
is provided:
<HeaderCell>
{def.header ? (
<strong>{def.header}</strong>
) : (
<Box sx={visuallyHidden}>
{def.key || def.someOtherFieldThatsRequiredIfHeaderIsMissing}
</Box>
)}
</HeaderCell>
That might address the concern more widely -- we could add additional attributes to ColumnDef if needed, to ensure that columns always have accessible headers.
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.
good idea, I've left a todo here that I'd like to address in the other PR
src/modules/projects/components/tables/ProjectHouseholdsTable.tsx
Outdated
Show resolved
Hide resolved
Co-authored-by: Gig <[email protected]>
render: 'projectName', | ||
}, | ||
ENROLLMENT_PERIOD_COL, | ||
{ |
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.
Pulled this out to here because this is now the only place where it is being used.
@@ -0,0 +1,59 @@ | |||
import { |
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 pulled this change into here, from the other PR, since it's relevant to the Enrollment tables updated in this PR.
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.
Nice. I never noticed that this was part of the design. It does look like we are missing part of the tooltip contents:
Most accessible text for cells with hover-over interactions should include both cell and tooltip text (2/5/25, 6 days ago’)
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 think this file and RelativeDateDisplay should go in src/components/elements
with the rest of the relative date components. (And hopefully we can consolidate later).
The hmis
module has general hmis-domain-specific components, like HmisField
,HohIndicator
, etc. This one isn't domain specific so I think it goes in src.
src/modules/projects/components/tables/ProjectClientEnrollmentsTable.tsx
Show resolved
Hide resolved
// This should only be used by tables that take over rendering using renderRow and render a `tbody` within their custom render fn | ||
overrideTableBody?: boolean; | ||
injectBelowRows?: ReactNode; // component to inject below all rendered rows, above footer | ||
getTableRowActions?: (record: T) => TableRowActionsType; |
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.
good idea, I've left a todo here that I'd like to address in the other PR
Is this ready for re-review @martha? And can you re-target to 147? thanks! |
@gigxz, yes, I think it's ready for re-review. Thank you! |
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 good!
@@ -0,0 +1,59 @@ | |||
import { |
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.
Nice. I never noticed that this was part of the design. It does look like we are missing part of the tooltip contents:
Most accessible text for cells with hover-over interactions should include both cell and tooltip text (2/5/25, 6 days ago’)
@@ -0,0 +1,59 @@ | |||
import { |
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 think this file and RelativeDateDisplay should go in src/components/elements
with the rest of the relative date components. (And hopefully we can consolidate later).
The hmis
module has general hmis-domain-specific components, like HmisField
,HohIndicator
, etc. This one isn't domain specific so I think it goes in src.
src/modules/hmis/hmisUtil.ts
Outdated
|
||
// TODO @MARTHA discuss - it's probably a bit silly to redefine ranks here, | ||
// see https://github.com/greenriver/hmis-warehouse/blob/1a170c0e869fd3d69880532f86baa104b800d9ed/drivers/hmis/app/graphql/types/hmis_schema/enums/hud.rb#L723-L733 | ||
const hohPriorityMapping: Record<RelationshipToHoH, number> = { |
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 don't think it's redundant with the backend. The enum lists out the values which are the HUD numeric values (Eg child = 2) whereas here you're specifying a custom order for displaying household members. It seems correct to me that this would live on the frontend.
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 good! thanks for your work and iteration!!
@martha merge conflicts might be a pain with this and #998? If you want to hold off on squashing this into main until it contains #998, that would be fine w/ me. (I think that would avoid the conflicts) Another option is a deploy branch, so this can get plenty of review on QA with design (without being tied to regular releases) - lets revisit Monday! |
* Implement Table Actions pattern and default columns * Add random comment * Add storybook for table actions and fix cde story * Implement PR suggestion of moving table row to column def * add todo * Finish refactor to use column def instead of getTableAction * Fix bulk services loading * Provide a visually hidden header when header isnt provided * Keep existing behavior of individual/household assessment viewing * Fix typescript * Add accessible text for RelativeDateDisplay * implement one possible approach for client ID typescript * Remove unnecessary cast
Description
Should be merged into the same release as #998
GH issue: https://github.com/open-path/Green-River/issues/6825
Depends on hmis-warehouse PR: greenriver/hmis-warehouse#5012 This is not a functional dependency, but is needed for spec tests to pass.
This PR
TableRowActions
that will be more widely adopted with https://github.com/open-path/Green-River/issues/6761Type of change
Checklist before requesting review