-
Notifications
You must be signed in to change notification settings - Fork 713
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
Fix: Side panel closing confirmation & logic in child component #11862
Fix: Side panel closing confirmation & logic in child component #11862
Conversation
Hi @nucleogenesis I am wondering if clicking outside the side panel should trigger the model? |
I think this can be a separate issue - I have also discovered that if I select a single resource and click save changes it will add a duplicate of that same resource |
@AllanOXDi could you give this another look? I've made a change now so that the SectionEditor also has a working confirmation modal when closing after making changes without saving. |
Build Artifacts
|
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 took another look, and it appears that clicking the 'X' is functioning as intended. However, I observed that selecting a resource and then navigating back using the back icon, until I exit the side panel, does not trigger the modal. I believe there might be a need to update the logic within this method.
https://github.com/nucleogenesis/kolibri/blob/fix--side-panel-closure/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/ResourceSelection.vue#L411
learners_see_fixed_order: learners_see_fixed_order.value, | ||
question_count: question_count.value, | ||
description: description.value, | ||
section_title: section_title.value, |
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.
Renaming these to match the data saved in the quiz data made it easy to compare the values by way of lodash/pick 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.
Might be good to add this as a code comment? Good to clarify that snake_case is being used rather than camelCase to match API data.
@@ -146,6 +145,8 @@ | |||
const { updateSection, activeResourcePool, selectAllQuestions } = injectQuizCreation(); | |||
const showConfirmationModal = ref(false); | |||
|
|||
const prevRoute = ref({ name: PageNames.EXAM_CREATION_ROOT }); |
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 can be set to the SectionEditor during beforeRouteEnter
below if that's the way we get here so that we can always go back there whenever we got to the resource selection from there
@@ -509,13 +505,13 @@ | |||
methods: { | |||
handleReplaceSelection() { | |||
const section_id = get(this.activeSection).section_id; | |||
this.$router.replace({ path: 'new/' + section_id + '/replace-questions' }); | |||
this.$router.push({ path: 'new/' + section_id + '/replace-questions' }); |
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 hadn't noticed this before - but is there a reason to use a path here and below, rather than name
and param
? It feels a little less brittle to do the latter, so if we need to tweak URLs for whatever reason, this remains unchanged.
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! I noticed that in passing yesterday while focused on another part of the code and failed to come back to fix it up. Will fix shortly
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 is something wired happening with this icon and I don't know why https://github.com/nucleogenesis/kolibri/blob/fix--side-panel-closure/kolibri/plugins/coach/assets/src/views/plan/CreateExamPage/ResourceSelection.vue#L14
0330db9
to
abb3db3
Compare
@AllanOXDi the double-button issue will be fixed in a separate PR - I have it noted and will be sure it's resolved |
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!
name: PageNames.QUIZ_SECTION_EDITOR, | ||
path: 'edit', | ||
component: SectionEditor, | ||
}, |
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.
None blocking comment: curious why we had to re-introduce nested routes when Richard suggested not to use 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.
@rtibbles initial note about the nested routes I think was more of a warning as things can get squirrely in the nested routes when not done correctly.
I was motivated to try the nested approach again because of the routing fix that stopped the page reloading on every navigation and because I found it impossible to reliably capture the browser back event before closing the side panel in order to show the confirmation modal before letting the user close the panel... unless each of the pages were their own route because then I could use beforeRoute*
guards within the components.
Previously, I couldn't do beforeRouteLeave
on the side panel components because each route just rendered the same quiz root component so the only place beforeRoute*
stuff worked was on that root component which only would happen when leaving the quiz creation altogether.
With the nested structure, however, I was able to clean up the components' hierarchies in the side panel. The key thing is that because each route is being associated with a specific component, we can block between all of routes by way of the beforeRouteLeave
guard and define that directly in each of the SectionEditor, ResourceSelection, & ReplaceQuestions components themselves. This has the added benefit that they can handle the logic of when they show the modal or not themselves rather than trying to pass values up to the base side panel component.
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 see. Good job and thanks for explaining!
The issue here was that the logic for whether or not the panel should be closed or whether or not we need to show a confirmation modal was initially built into the SectionSidePanel component. This component is a wrapper component and now that the workingResourcePool lives solely within the ResourceSelection component, there is no access to it in the parent. The solution was to pass a prop into each child component which will need to be handled in all of the child components (section edit, question replacement). This prop tells the child that we're trying to close the side panel. This allows each child component then to define its own logic and messaging around confirming the panels closure with the user. This results in the child component also needing to emit two events which tell the SectionSidePanel if the panel should actuall be closed, resulting in the user being returned to the root quiz creation route.
The issue here was that the logic for whether or not the panel should be closed or whether or not we need to show a confirmation modal was initially built into the SectionSidePanel component. This component is a wrapper component and now that the workingResourcePool lives solely within the ResourceSelection component, there is no access to it in the parent. The solution was to pass a prop into each child component which will need to be handled in all of the child components (section edit, question replacement). This prop tells the child that we're trying to close the side panel. This allows each child component then to define its own logic and messaging around confirming the panels closure with the user. This results in the child component also needing to emit two events which tell the SectionSidePanel if the panel should actuall be closed, resulting in the user being returned to the root quiz creation route.
1d2e1af
to
dae568b
Compare
Summary
The issue here was that the logic for whether or not the panel should be closed or whether or not we need to show a confirmation modal was initially built into the SectionSidePanel component. This component is a wrapper component and now that the workingResourcePool lives solely within the ResourceSelection component, there is no access to it in the parent.
The solution was to pass a prop into each child component which will need to be handled in all of the child components (section edit, question replacement). This prop tells the child that we're trying to close the side panel.
This allows each child component then to define its own logic and messaging around confirming the panels closure with the user. This results in the child component also needing to emit two events which tell the SectionSidePanel if the panel should actually be closed, resulting in the user being returned to the root quiz creation route.
Reviewer guidance
Testing
Proceed to add questions to a section
Change your selection (click one resource's checkbox)
Try to close the side panel by the X or by clicking outside of the side panel
See the modal window pops up
When "Cancel" is clicked, you still see the side panel and if you try to close again, you get the confirmation modal again
When "Continue" is clicked, you see the side panel closed
Try this again on the same section by clicking "Options" -> "Edit section" -> "Select resources..." and then make a change to your selection and the same confirmation modal flow as noted above should be done.
The same workflow should present itself when in the SectionEditor