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
Reorder Section Dropdowns #35615
Reorder Section Dropdowns #35615
Conversation
Taking a look. For starters, I think your idea to separate your .gitignore changes into a seperate PR is a good one, because it makes it so that if needed this PR can be reverted without reverting changes to the gitignore |
4d30473
to
9c3a352
Compare
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 looks good to me - congrats on your first "real code" 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.
Hooray! Nice work, Charlie. Looks good to me.
onCourseOverview, | ||
includeHidden = true | ||
) { | ||
return state.sectionIds.map(id => ({ | ||
id: parseInt(id, 10), | ||
name: state.sections[id].name, | ||
scriptId: state.sections[id].scriptId, | ||
courseId: state.sections[id].courseId, | ||
isAssigned: | ||
(scriptId !== null && state.sections[id].scriptId === scriptId) || | ||
(courseId !== null && | ||
state.sections[id].courseId === courseId && | ||
onCourseOverview) | ||
})); | ||
return state.sectionIds | ||
.map(id => ({ | ||
...state.sections[id], | ||
isAssigned: | ||
(scriptId !== null && state.sections[id].scriptId === scriptId) || | ||
(courseId !== null && | ||
state.sections[id].courseId === courseId && | ||
onCourseOverview) | ||
})) | ||
.filter(section => includeHidden || !section.hidden) | ||
.sort((a, b) => b.id - a.id); | ||
} |
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 reccomend having a seperate function that filters out hidden sections, rather than including that logic into this sectionsForDropdown function.
Is there an advantage to piggy-backing off of this existing sectionsForDropdown function, rather than writing a seperate helper function for TeacherDashboardHeader, or putting this data munging logic inside of TeacherDashboardHeader itself?
Here are some concerns that lead to this suggestion:
Concern 1.)
I am mildly concerned that we are passing in data with the isAssigned property to TeacherDashboardHeader, but as far as I'm aware not using that property there. Could this make debugging this component slightly more confusing? Data with this property would appear in developer tools when debugging, could that be distracting when debugging issues? Also, having this data but not using has (incredibly minor given the size of the data) performance implications.
Concern 2.)
Could having one function that is used by multiple separate drop-downs increase code complexity over time? TeacherDashboardHeader doesn't need to know about the logic behind isAssigned to work. Our other dropdowns using this function don't need to care about filtering out hidden sections. In the future, if we add another dropdown that needs something special for it, it may not care about either isAssigned or hidden sections. This seems less than ideal since anyone making changes to the dropdown in any of these three components would need to read this one function, and would have to take extra time to understand its complexity.
Concern 3.)
By adding another parameter to an existing function rather than creating a new function that just filters and sorts the data, you're doubling the amount of unit tests you need to fully test this function. Each additional parameter to a function multiplies the number of tests you need to fully test that function by the number of qualitatively different values that input can have. In this case its not so bad because of the specifics of how the function as currently written works (none of the parameters interact with each other) but I still think its worth noting because that could not be the case for this function in the future.
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 raising these concerns @mvkski. the intended advantage of piggy-backing off that existing function was to solve the sorting issue in a single place rather than everywhere we list sections, but it turns out that function was far from the primary method of listing sections in dropdowns that i assumed it to be. given that, i agree that there's no good reason to reuse it in the TeacherDashboardHeader, especially considering the concerns you raised.
digging through potential solutions that would solve the sorting issue in a single place, i determined that the amount of refactoring needed was out of scope for this story and would be better to address as part of our H2 performance improvements. so for now i just applied the simplest (though also least elegant) fix, which was to find everywhere (hopefully) that we present a user-facing list of sections, and call one of two new helper functions in teacherSectionsRedux
. sometimes the sections that we need to sort are in dictionary form, and sometimes they're already in a list, so i factored out the actual sorting into a single function that operates on arrays so that the actual sort order is still only defined in a single place.
as for filtering, i'm not a big fan of the fact that the logical meaning of teacherSections.sections
changes depending on context (sometimes filtered, sometimes not), but again, addressing that is out of scope for this task because we set those sections in so many ways throughout our code. it seems that in general the convention is to handle the filtering on the backend, and the TeacherSectionsHeader is just a special case where we want them filtered for the dropdown but still need the hidden ones in redux in case the selected section is hidden. so rather than creating a helper function for that i just put the filtering right in the component and added a comment about it being a special case.
again, thanks for raising these concerns, because my naive thinking that the sectionsForDropdown
function was the standard access point for listing sections meant that my original PR had missed a number of other dropdowns that needed sorting. let me know what you think of the new approach!
0340bdf
to
78d33dd
Compare
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 looks really good! One change requested: adding back in the hidden mock section in TeacherDashboardHeaderTest.js. Thanks!
6a99027
to
08a50be
Compare
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!
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.
LGTM!
fc04ac7
to
b40f0ed
Compare
…o be consistent with teacher homepage - sort array by *descending* id in `sectionsForDropdown` - updated TeacherDashboardHeader gets sections from `sectionsForDropdown` to be consistent with other section dropdowns - moved filtering of hidden sections into `sectionsForDropdown`
…dHeader` since that function turned out to be far from the only access point for listing sections * reverted to explicitly filtering out hidden section in `TeacherDashboardHeader` (see comment) * added functions to convert a dictionary of sections to sorted array, and to sort and unsorted array of sections * applied sorting to all user-facing lists of sections that i could find (hopefully all!) * removed unused references to `state.teacherSections.sections` encountered along the way
… old section order, and added tests for new sorting functions
…removed mention of ignoring hidden sections in dropdown render test.
b40f0ed
to
6fc8651
Compare
In the teacher dashboard, various dropdown menus were listing sections in different orders. The chosen fix was to have all dropdown menus list them in the same order as the table on the teacher homepage, which means by descending ID (from user's perspective, most recently created at the top). [see here]
The main fix was to explicitly sort by descending ID in
sectionsForDropdown
, which is where most of the dropdowns were getting their data. However, theTeacherDashboardHeader
component was using theteacherSections.sections
object from the redux store, and since the primary goal of this ticket was to standardize section ordering, the solution I chose was to update this component to get its sections from thesectionsForDropdown
function as well, rather than duplicating sorting logic in the component.The
TeacherDashboardHeader
component was explicitly filtering out hidden sections (in other components those were filtered out on the backend), so I moved the filtering intosectionsForDropdown
and addedincludeHidden = true
param so as not to break code that assumes it isn't doing any filtering.Links
Testing story
I have not yet started digging into any of our testing. If there are relevant tests that should be updated or added for this ticket, please let me know.
EDIT: Tests are failing so I'm learning about them now! Hopefully the unit tests will pass with latest commit, but still need to look into UI tests.
Reviewer Checklist: