-
Notifications
You must be signed in to change notification settings - Fork 38
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
MB-11601 delete shipment #8375
MB-11601 delete shipment #8375
Conversation
|
@@ -60,16 +56,29 @@ export const ShipmentListItem = ({ | |||
<span className={styles.warningText}>{isOverweight ? 'Over weight' : 'Missing weight'}</span> | |||
</div> | |||
)} | |||
{canEdit ? <FontAwesomeIcon icon="pen" className={styles.edit} /> : <div className={styles.noEdit} />} |
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 glad we're getting rid of the icon-only button in favor of text 🎉
<Button className={styles['edit-btn']} onClick={onDeleteClick} type="button"> | ||
Delete | ||
</Button> | ||
<div>|</div> | ||
<Button className={styles['edit-btn']} onClick={onShipmentClick} type="button"> | ||
Edit | ||
</Button> |
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 not 100% sure if we should keep using buttons or not for things that are in effect, just links. It's come up in the past but I don't remember the decision in the end. I've started a thread in #prac-frontend asking if others remember what was decided.
.step-container:last-of-type { | ||
margin-bottom: 0; | ||
} | ||
|
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.
src/pages/MyMove/Review/Review.jsx
Outdated
return { | ||
...ownProps, | ||
canMoveNext: true, // TODO: prevent incomplete PPM submission? | ||
canMoveNext: !!Object.keys(mtoShipments).length, // TODO: prevent incomplete PPM submission? |
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.
Makes next button disabled when we delete the last shipment. We still need to handle the scenarios where a PPM is incomplete
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.
Heads up I removed this property in my PR that's now in master. I did add a selector to return the shipments similar to what you're doing above. Probably just move this logic to inside the component in conjunction with the check for an incomplete PPM.
|
||
await waitFor(() => { | ||
checkShipmentClick('ID-3', 1, SHIPMENT_OPTIONS.NTS); | ||
}); | ||
|
||
userEvent.click(screen.getByRole('button', { name: /^nts-release /i })); | ||
editBtn = queryByRole(screen.getAllByTestId('shipment-list-item-container')[3], 'button', { name: 'Edit' }); | ||
|
||
await waitFor(() => { |
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.
@felipe-lee Is there a reason that we are using await here as opposed just triggering the click and using expects similar to what is done for the deletes below?
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 I had been getting console errors without the awaits, but now I don't remember the exact error. You can try removing it and see if you get them. If not, then feel free to change this up.
useEffect( | ||
() => () => { | ||
// Clear this flash message on unmount (this will happen on navigation or if flash state changes) | ||
clearFlashMessage(flash?.key); | ||
}, | ||
[clearFlashMessage, flash?.key], | ||
); |
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 was changed because the previous implementation made it so that if you modified the message multiple times on the same page it would be cleared on alternating notifications. (eg. If you delete two records on the first you would see a message, but on the second the message would disappear. You would then alternate seeing and not seeing it on subsequent triggers.)
Does anyone have context on the reason for this original implementation? If the comment is correct I think this servers to better mimic that description.
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.
thought: I don't have any context on this.
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 know anything about the initial implementation, but I think having a dependency array in useEffect
is a good practice, and like you said, seems to match what the comment indicates we want, so I think this change is probably for the best.
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.
The changes look good to me, but I would want someone else who has more context of the work to review this.
@@ -40,7 +40,7 @@ describe('Services counselor user', () => { | |||
|
|||
cy.get('[data-testid="modal"]').should('be.visible'); | |||
|
|||
cy.get('[data-testid="modal"] button').contains('Delete shipment').click(); | |||
cy.get('[data-testid="modal"] button').contains('Delete shipment').click({ force: true }); |
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.
Thanks for adding this!
onClose={() => {}} | ||
onSubmit={() => {}} |
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.
Try to define these stories using the newer args pattern so that these props become editable in the Storybook controls panel and you can also use actions so those click events show up in the actions tab too.
display: inline-flex; | ||
flex: 0; | ||
align-items: center; | ||
min-width: auto; | ||
@include u-padding-x(0); | ||
@include u-font('body', 'xs'); | ||
|
||
button { | ||
padding: 12px; |
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 it's good to avoid using pixels and use USWDS tokens whenever possible. You should be able to rewrite this as @include u-padding(1.5)
https://designsystem.digital.gov/design-tokens/spacing-units/
I've been testing and things look very good! One minor issue I see is when you delete all of the shipments on the Review page, the next button is still enabled for you to submit the move. I think if you just combine a check for mtoShipments length with the complete PPM conditional in Review.jsx you can fix that disabling. |
… when no shipments are present
@duncan-truss Yeah I caught this as well when I was working on the cypress tests. I forgot to add this back in when I merged in your code that added the logic for the incomplete PPMs. See commit |
|
||
await waitFor(() => { | ||
checkShipmentClick('ID-3', 1, SHIPMENT_OPTIONS.NTS); | ||
}); | ||
|
||
userEvent.click(screen.getByRole('button', { name: /^nts-release /i })); | ||
editBtn = queryByRole(screen.getAllByTestId('shipment-list-item-container')[3], 'button', { name: 'Edit' }); | ||
|
||
await waitFor(() => { |
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 I had been getting console errors without the awaits, but now I don't remember the exact error. You can try removing it and see if you get them. If not, then feel free to change this up.
src/components/Customer/Review/ShipmentCard/PPMShipmentCard/PPMShipmentCard.test.jsx
Outdated
Show resolved
Hide resolved
if (action.type === 'UPDATE_MTO_SHIPMENTS_ENTITIY') { | ||
return { | ||
...state, | ||
mtoShipments: action.entities['mtoShipments'] || {}, | ||
}; | ||
} |
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.
Let me preface this by saying, I don't know much (i.e. next to nothing) about redux or how all these things tie together. But, looking at the existing code, is there a reason we need the new path for updating MTO shipments? It seems like the ADD_ENTITIES
path is doing the same thing, at least in the end. It's doing a merge of the original and new, but if the new overwrites the whole of mtoShipments
I feel like that should be fine? Again, I could be totally off and if you tried that and it didn't work, then nvm.
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.
ADD_ENTITIES doesn't work because it is doing a merge of the original and new mtoShipments. When we merge it only adds or updates any of the updated or new records (it basically just overrides values in the old with the new if they have the same key or adds entries if the key is new). This means when we delete the original has all of the old values and the new values has one less value. The merge function then doesn't change since the new doesn't have any additional info.
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 it would clarify the purpose some and maybe make it a bit generalized if we called it REPLACE_ENTITY to reflect what it's doing now.
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.
As is, I would be hesitant to call it REPLACE_ENTITY
since this functionality doesn't work at a general level. It currently only works for mtoShipments.
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.
Right, you have it hardcoded to the 'mtoShipments' key, you would need to make that use a param. I don't think it's a must have.
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 started a semi-related thread in #prac-frontend about this and plan on bringing it up at tomorrow's check in.
src/pages/MyMove/Review/Review.jsx
Outdated
@@ -62,7 +62,7 @@ const Review = ({ currentMove, mtoShipments, push, match }) => { | |||
<div className={formStyles.formActions}> | |||
<WizardNavigation | |||
onNextClick={handleNext} | |||
disableNext={!hasCompletedPPMShipments} | |||
disableNext={!hasCompletedPPMShipments || !Object.keys(mtoShipments).length} |
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.
mtoShipments should be an array of objects coming back from the selectMTOShipmentsForCurrentMove selector or assigned to an empty array by default. I don't think calling Object.keys is necessary here.
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 PR works as expected for design.
One call-out: Deleted shipments work as expected on this page, but then at least sometimes appear on the review screen. I think there's an existing ticket to fix that as a separate story, but just a heads-up that that will need to be fixed at some point.
useEffect( | ||
() => () => { | ||
// Clear this flash message on unmount (this will happen on navigation or if flash state changes) | ||
clearFlashMessage(flash?.key); | ||
}, | ||
[clearFlashMessage, flash?.key], | ||
); |
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 know anything about the initial implementation, but I think having a dependency array in useEffect
is a good practice, and like you said, seems to match what the comment indicates we want, so I think this change is probably for the best.
{showDeleteSuccessAlert && ( | ||
<Alert slim type="success"> | ||
The shipment was deleted. | ||
</Alert> | ||
)} | ||
{showDeleteErrorAlert && ( | ||
<Alert slim type="error"> | ||
Something went wrong, and your changes were not saved. Please try again later or contact your counselor. | ||
</Alert> | ||
)} |
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.
Sorry, you might have addressed this somewhere and I missed it, but do we need the separate alerts? Like does <ConnectedFlashMessage />
not work if you're staying on the same page?
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.
It's not actually clear to me when we use Alert
vs ConnectedFlashMessage
. I'd assume and it does generally seem to be the case that ConnectedFlashMessage
was used when the parent had the ConnectedFlashMessage and the child element would just dispatch the action to update the message. Alerts seem to be used when the update is happening within the same component. With the update above we should be able to use ConnectedFlashMessage
if we want.
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 you're right about the general times we use each. I guess I'd opt for, if the page already has <ConnectedFlashMessage/>
to use it, but maybe this is a discussion for FE check in. I'm fine with keeping this as is for now and if we decide to change it, it can be a follow-up later on.
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 started a thread in #prac-frontend about this and plan on bringing it up at tomorrow's check in.
…ing the button wrapper
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.
Found a few prop errors in tests, though hopefully they're easy to fix
@@ -13,7 +13,7 @@ const defaultProps = { | |||
shipmentNumber: 1, | |||
shipmentId: '#ABC123K', | |||
shipmentType: 'HHG', | |||
showEditBtn: false, | |||
showEditAndDeleteBtn: false, |
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.
@@ -9,7 +9,7 @@ import { formatCustomerDate } from 'utils/formatters'; | |||
const defaultProps = { | |||
moveId: 'testMove123', | |||
onEditClick: jest.fn(), | |||
showEditBtn: false, | |||
showEditAndDeleteBtn: false, |
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.
Same comment about the missing onDeleteClick
prop
@@ -11,7 +11,7 @@ const defaultProps = { | |||
onEditClick: jest.fn(), | |||
shipmentId: '#ABC123K', | |||
shipmentType: 'HHG_INTO_NTS_DOMESTIC', | |||
showEditBtn: false, | |||
showEditAndDeleteBtn: false, |
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.
Same comment about the missing onDeleteClick
prop
@@ -109,7 +109,7 @@ describe('Home component', () => { | |||
mtoShipmentId: testProps.mtoShipments[1].id, | |||
}); | |||
|
|||
wrapper.find('ShipmentListItem').at(0).simulate('click'); | |||
wrapper.find('ShipmentListItem').at(0).find('button').at(1).simulate('click'); |
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.
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.
Found a few prop errors in stories
content: 'Some sample description', | ||
submitText: 'YES!', | ||
closeText: 'NO', | ||
onClose: { action: 'close button clicked' }, |
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 getting a prop type error on this:
I think this other story shows an example of actions:
mymove/src/components/Customer/PPMBooking/DateAndLocationForm/DateAndLocationForm.stories.jsx
Lines 46 to 47 in 4322de3
onSubmit: action('submit button clicked'), | |
onBack: action('back button clicked'), |
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.
Ooops, this wasn't supposed to be checked in 😅. As a general note thanks for being thorough and providing references/sources.
<ShipmentList | ||
shipments={[{ id: '0001', shipmentType: SHIPMENT_OPTIONS.PPM }]} | ||
onShipmentClick={() => {}} | ||
onDeleteClick={() => {}} |
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.
@@ -18,6 +22,7 @@ export const Basic = () => ( | |||
{ id: '0003', shipmentType: SHIPMENT_OPTIONS.PPM }, | |||
]} | |||
onShipmentClick={() => {}} | |||
onDeleteClick={() => {}} |
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 one also needs the moveSubmitted
prop
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 given that some things need to discussed at a FE group level, I'm fine with this as is for now. Well pending those prop error fixes, but I don't want to be a blocker on this once you push those fixes up.
Jira ticket for this change
Summary
Is there anything you would like reviewers to give additional scrutiny?
this article explains more about the approach used.
Setup to Run Your Code
💻 You will need to use three separate terminals to test this locally.
Terminal 1
Start the Storybook locally.
Terminal 2
Start the UI locally.
Terminal 3
Start the Go server locally.
Verification Steps for Author
These are to be checked by the author.
Verification Steps for Reviewers
These are to be checked by a reviewer.
Frontend
officeApp
class or custommin-width
styling is used to hide any states the would not be visible to the user.Screenshots