Skip to content
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

uncap additional expenses and allow delete #5908

Conversation

shacon
Copy link
Contributor

@shacon shacon commented Jul 12, 2024

What github issue is this PR for, if any?

Resolves #5773

What changed, and why?

Allows for adding more than 10 additional expenses and allows for deleting additional expenses from the form
Used this stimulus controller for nested form fields as suggested in the ticket: https://www.stimulus-components.com/docs/stimulus-rails-nested-form/

How is this tested? (please write tests!) 💖💪

Edited the capybara tests that existed with the changes to allow for more than 10 additional expenses.

Also added capybara test for the delete functionality.

This pr does add a javascript controller that resets the indexes on the nested fields generated by the stimulus controller. The capybara tests so end up testing this functionality but if it seems like we want specific javascript tests I can take a stab at those.

Screenshots please :)

Screen Shot 2024-07-23 at 1 15 48 PM Screen Shot 2024-07-23 at 1 14 26 PM

A note on testing locally - this requires a feature flag to be set and for a config to be set on the related Casa Org. Here's what I ran in the rails console to do this:

org =CaseContact.last.casa_case.casa_org

 org.additional_expenses_enabled=true
org.save

Flipper.enable :show_additional_expenses

Feelings gif (optional)

optimistic gif

@github-actions github-actions bot added javascript for use by Github Labeler to mark pull requests that update Javascript code ruby Pull requests that update Ruby code Tests! 🎉💖👏 erb labels Jul 12, 2024
@shacon shacon marked this pull request as ready for review July 13, 2024 19:34
Comment on lines 16 to 35
reindexFields () {
// Reindex fields so that nested parameters come in with consecutive
// indexes starting at 0
const containers = this.element.querySelectorAll('.expense-container')
containers.forEach((container, index) => {
container.querySelectorAll('input, select, textarea').forEach(field => {
const newName = field.name.replace(/\[additional_expenses_attributes\]\[\d+\]/, `[additional_expenses_attributes][${index}]`)
field.name = newName
field.id = newName.replace(/\[/g, '_').replace(/\]/g, '')
})

container.querySelectorAll('label').forEach(label => {
const forAttr = label.getAttribute('for')
if (forAttr) {
const newForAttr = forAttr.replace(/additional_expenses_attributes_\d+/, `additional_expenses_attributes_${index}`)
label.setAttribute('for', newForAttr)
}
})
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if we don't reindex the fields?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need a new controller at all for this. This should be doable 100% in the template and controller. Look at the documentation here.

We already have the component installed, so you can skip the installation step.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially, persisted associations get their ID as their index and new records get the timestamp they were created (line 19). This ensures unique identifiers for every association in the form without needing a reindex.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schoork @elasticspoon thanks! I'll make these changes and push something up by the end of this week

Copy link
Collaborator

@schoork schoork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this looks great, but we don't need the added controller.

Comment on lines 16 to 35
reindexFields () {
// Reindex fields so that nested parameters come in with consecutive
// indexes starting at 0
const containers = this.element.querySelectorAll('.expense-container')
containers.forEach((container, index) => {
container.querySelectorAll('input, select, textarea').forEach(field => {
const newName = field.name.replace(/\[additional_expenses_attributes\]\[\d+\]/, `[additional_expenses_attributes][${index}]`)
field.name = newName
field.id = newName.replace(/\[/g, '_').replace(/\]/g, '')
})

container.querySelectorAll('label').forEach(label => {
const forAttr = label.getAttribute('for')
if (forAttr) {
const newForAttr = forAttr.replace(/additional_expenses_attributes_\d+/, `additional_expenses_attributes_${index}`)
label.setAttribute('for', newForAttr)
}
})
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need a new controller at all for this. This should be doable 100% in the template and controller. Look at the documentation here.

We already have the component installed, so you can skip the installation step.

@@ -113,6 +113,10 @@ legend {
cursor: pointer;
}

.remove-expense-button {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this doable through Bootstrap code?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schoork I can look into that, haven't worked with bootstrap in a long time but I'll check it out

Comment on lines 16 to 35
reindexFields () {
// Reindex fields so that nested parameters come in with consecutive
// indexes starting at 0
const containers = this.element.querySelectorAll('.expense-container')
containers.forEach((container, index) => {
container.querySelectorAll('input, select, textarea').forEach(field => {
const newName = field.name.replace(/\[additional_expenses_attributes\]\[\d+\]/, `[additional_expenses_attributes][${index}]`)
field.name = newName
field.id = newName.replace(/\[/g, '_').replace(/\]/g, '')
})

container.querySelectorAll('label').forEach(label => {
const forAttr = label.getAttribute('for')
if (forAttr) {
const newForAttr = forAttr.replace(/additional_expenses_attributes_\d+/, `additional_expenses_attributes_${index}`)
label.setAttribute('for', newForAttr)
}
})
})
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially, persisted associations get their ID as their index and new records get the timestamp they were created (line 19). This ensures unique identifiers for every association in the form without needing a reindex.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You will be able to remove this file.

@@ -14,6 +14,8 @@ import DismissController from './dismiss_controller'

import CourtOrderFormController from './court_order_form_controller'

import AdditionalExpensesFormController from './additional_expenses_form_controller'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This you can remove.

@@ -34,6 +36,7 @@ application.register('autosave', AutosaveController)
application.register('disable-form', DisableFormController)
application.register('dismiss', DismissController)
application.register('court-order-form', CourtOrderFormController)
application.register('additional-expenses-form', AdditionalExpensesFormController)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove as well.

@@ -42,3 +45,4 @@ application.register('select-all', SelectAllController)
application.register('sidebar', SidebarController)
application.register('sidebar-group', SidebarGroupController)
application.register('truncated-text', TruncatedTextController)
application.register('nested-form', NestedForm)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't able to access the nested form controller until I added this - not sure if there is a more standard way to do this. I realize the rest of the imports in here are all local

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The court_order_form_controller.js uses it, too. But it loads it directly. This is the right thing to do for your use case.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not a huge deal, but I'd say get rid of the a and b. With multiple expenses it becomes confusing.
Screenshot 2024-07-23 at 6 59 24 AM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, just saw this, will take those out

<%= form.number_field :other_expense_amount,
placeholder: "0",
class: "form-control other-expense-amount",
min: "0", max: 1000, step: 0.01 %>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After saving and coming back to edit, I get an expense in the form with only one cent place.
Screenshot 2024-07-23 at 7 01 16 AM

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@schoork added number_with_precision to the field, let me know if this display is ok:
Screen Shot 2024-07-23 at 1 12 11 PM

Copy link
Collaborator

@schoork schoork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great @shacon. One tweak to the way the cost is displayed when editing and good to go!

@shacon
Copy link
Contributor Author

shacon commented Jul 30, 2024

This looks great @shacon. One tweak to the way the cost is displayed when editing and good to go!

thanks @schoork! I made the requested changes and updated the screenshots - let me know if there is anything else I should do on my end.

Copy link
Collaborator

@schoork schoork left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great @shacon! Thanks for the reminder.

@schoork schoork merged commit 0d49402 into rubyforgood:main Jul 30, 2024
19 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
erb javascript for use by Github Labeler to mark pull requests that update Javascript code ruby Pull requests that update Ruby code Tests! 🎉💖👏
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Uncap submissions for Additional Expenses and improve UX
3 participants