Skip to content

fix(trainsformer): fix adding / removing service dates, days of week#1351

Merged
rudiejd merged 18 commits intomasterfrom
fix/polish-adding-service-dates
Feb 4, 2026
Merged

fix(trainsformer): fix adding / removing service dates, days of week#1351
rudiejd merged 18 commits intomasterfrom
fix/polish-adding-service-dates

Conversation

@rudiejd
Copy link
Member

@rudiejd rudiejd commented Jan 28, 2026

Summary of changes

Asana Ticket: 🏹Service date add / remove bug fix / polish

Problem(s):
Described in the above ticket, but briefly:

  1. sometimes removing / adding service dates resulted in an error to the effect of: cannot replace related %Arrow.Trainsformer.ServiceDate... This typically happens when you are calling put_assoc/put_embed with the results of a previous put_assoc/put_embed/cast_assoc/cast_embed operation, which is not supported. You must call such operations only once per embed/assoc, in order for Ecto to track changes efficiently
  2. Sometimes de-selecting a day of the week is not possible, often in conjunction with adding and removing service dates.

Solution:
After a lot of form reading and researching, I found a great blog from dockyard that describes an approach for handling an association without the need for any JavaScript. Basically, we now use the sort_params / drop_params of Ecto.Changeset.cast_assoc/3 via hidden fields to handle adding / deleting service dates. This prevents us from calling put_change multiple times, fixing (1). I also noticed that I cannot reproduce (2) after implementing this change.

Additionally, I added:

  • a validation to ensure that the start date is before the end date for our service date ranges
  • some CSS to make the icons look different on hover. I can remove this if anyone strongly objects

Reviewer Checklist

  • Meets ticket's acceptance criteria
  • Any new or changed functions have typespecs
  • Tests were added for any new functionality (don't just rely on Codecov)
  • This branch was deployed to the staging environment and is currently running with no unexpected increase in warnings, and no errors or crashes.

@rudiejd rudiejd requested a review from a team as a code owner January 28, 2026 22:40
@rudiejd rudiejd requested review from jzimbel-mbta and removed request for a team January 28, 2026 22:40
@rudiejd rudiejd force-pushed the fix/polish-adding-service-dates branch from 6ac52bf to 7d2c1be Compare January 28, 2026 22:44
@rudiejd
Copy link
Member Author

rudiejd commented Jan 29, 2026

I'm having a really hard time creating an integration test to reproduce this behavior, but you can reproduce manually by adding and deleting a bunch of service dates at the same time for any trainsformer service

Copy link
Member

@jzimbel-mbta jzimbel-mbta left a comment

Choose a reason for hiding this comment

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

Looks good, and wow that's a lot of boilerplate magicked away by an ecto feature 😲

I have some suggestions, but nothing blocking.

end

@spec validate_start_date_before_end_date(Ecto.Changeset.t(any())) :: Ecto.Changeset.t(any())
def validate_start_date_before_end_date(changeset) do
Copy link
Member

Choose a reason for hiding this comment

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

suggestion:
It makes total sense to consolidate this logic, but it feels a little "off" to put a function that makes assumptions about the field names of changeset, and the desired error message, into a very general catch-all module like Util.

Do you think it could make sense to put this in a separate Arrow.Validation module?

I could also see it being helpful to separate the logic that does the Date comparison from the logic that reads/writes to the changeset, but that's probably overkill.

Copy link
Member Author

Choose a reason for hiding this comment

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

yep I can move this to a different module!

Copy link
Member Author

Choose a reason for hiding this comment

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

patch={~p"/disruptions/#{@disruption.id}/trainsformer_export/#{export.id}/edit"}
>
<.icon name="hero-pencil-solid" class="bg-primary" />
<.icon name="hero-pencil-solid" class="bg-primary hover:opacity-40" />
Copy link
Member

Choose a reason for hiding this comment

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

question/suggestion:
This makes the icon's opacity decrease to 40% on hover, right?

Any reason for doing that instead of what seems to be the more standard behavior of (lower opacity while not hovered/focused) -> (higher opacity on hover/focus)?

For example, Tailwind's default styles have elements' opacity increase on hover.

Copy link
Member Author

@rudiejd rudiejd Feb 3, 2026

Choose a reason for hiding this comment

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

happy to do higher opacity! I just thought some sort of visual sign might be nice for the icons.

Copy link
Member Author

Choose a reason for hiding this comment

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

class="btn-sm p-0"
type="button"
phx-click="delete_export"
phx-click="delete_trainsformer_export"
Copy link
Member

Choose a reason for hiding this comment

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

suggestion:
Good catch.

If it wouldn't be too much of a pain, it would also help to rename the delete_export event and its corresponding handle_event clause to delete_hastus_export.

Copy link
Member Author

Choose a reason for hiding this comment

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

can do!

Copy link
Member Author

Choose a reason for hiding this comment

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

@rudiejd rudiejd merged commit 6a838bb into master Feb 4, 2026
5 checks passed
@rudiejd rudiejd deleted the fix/polish-adding-service-dates branch February 4, 2026 20:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants