-
Notifications
You must be signed in to change notification settings - Fork 699
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
Synchronise user selections with Quiz Creation State #11783
Synchronise user selections with Quiz Creation State #11783
Conversation
Co-authored-by AllanOXDi <otodi.alllan1@gmail.com>
Add working resource pool logic
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.
In manual testing things work as expected!
Noting that the related issue's "select questions" business will be moved to a separate issue -- so validating that this works properly involved checking the Vue devtools and it all worked as expected, more or less.
Overall, feedback is largely formatting / clean-up releated and suggestions for JSDocs.
The one thing that I'm not sure for the cause of is that we cannot save the quiz, getting Must be a valid UUID
errors for every item in the resource pool -- I think that this may just be a matter of using import { v4 } from 'uuid';
in useQuizCreation
when we generate the section_id
.
Note -- that with @ozer550 out I'll likely take on some of these fixes and force push to the branch so that we can try to get this ready to merge before next iteration.
</SidePanelModal> | ||
<ConfirmCancellationModal | ||
v-if="showConfirmationModal" | ||
:closePanelRoute="closePanelRoute" |
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.
Need to handle the @closeModal
event here (could just be an inline function like @closeModal=() => showConfirmationModal = false
@@ -65,6 +65,7 @@ | |||
<script> | |||
|
|||
import commonCoreStrings from 'kolibri.coreVue.mixins.commonCoreStrings'; | |||
import { injectQuizCreation } from '../../../composables/useQuizCreation'; |
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 like all of the changes on this file can be removed as the injected methods aren't used in this component
* Adds resources to _working_resource_pool | ||
*/ | ||
function addToWorkingResourcePool(resources = []) { | ||
set(_working_resource_pool, [...get(_working_resource_pool), ...resources]); |
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 we should wrap the array here with lodash's uniqWith
and isEqual
alike to:
uniqWith([...get(_working_resource_pool), ...resources], isEqual)
-- this will use the lodash isEqual
function to check equality of the objects in the list (see the conveniently relevant example in the lodash docs).
@@ -445,12 +465,40 @@ export default function useQuizCreation(DEBUG = false) { | |||
} | |||
}); | |||
|
|||
/** | |||
* Adds resources to _working_resource_pool |
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's get the JSDoc types up-to-date here w/ @param
and @affects
entries - the type for the resources
param ought to be QuizExercise[]
} | ||
|
||
/** | ||
* Check if the content is present in working_resource_pool |
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.
JSDoc suggestion:
@param {QuizExercise} content - Check if the content is present...
@returns Boolean
computed: { | ||
isTopicIdSet() { | ||
return this.$route.params.topic_id; | ||
}, | ||
isSelectAllChecked() { | ||
//if all the reosurces in contentList are present in working_resource_pool |
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.
Formatting: reosurces
-> resources
// contentIsInLesson() { | ||
// return ({ id }) => Boolean(this.channels); | ||
// }, |
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 removed
// addableContent() { | ||
// // Content in the topic that can be added if 'Select All' is clicked | ||
// const list = this.contentList.value ? this.contentList.value : this.bookmarksList; | ||
// return list.filter( | ||
// content => !this.contentIsDirectoryKind(content) && !this.contentIsInLesson(content) | ||
// ); | ||
// }, |
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 removed - particularly with the uniqWith/isEqual
suggestion elsewhere in this review in place
// saveResources() { | ||
// this.saveQuiz(); | ||
// }, |
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.
Is this commented out because it is no longer used?
handleSearchTerm(searchTerm) { | ||
const query = { | ||
last_id: this.$route.query.last_id || this.$route.params.topicId, | ||
}; | ||
const lastPage = this.$route.query.last; | ||
if (lastPage) { | ||
query.last = lastPage; | ||
} | ||
this.$router.push({ | ||
name: LessonsPageNames.SELECTION_SEARCH, | ||
params: { | ||
searchTerm, | ||
}, | ||
query, | ||
}); | ||
}, | ||
handleMoreResults() { | ||
this.moreResultsState = 'waiting'; | ||
this.fetchAdditionalSearchResults({ | ||
searchTerm: this.searchTerm, | ||
kind: this.filters.kind, | ||
channelId: this.filters.channel, | ||
currentResults: this.searchResults.results, | ||
}) | ||
.then(() => { | ||
this.moreResultsState = null; | ||
this.moreResultsState; | ||
}) | ||
.catch(() => { | ||
this.moreResultsState = 'error'; | ||
}); | ||
}, | ||
*/ |
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 thought that this had been removed in my last PR -- can we strip out the search business here as it'll be addressed in an upcoming issue.
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 am not seeing anything blocking here, per se - but I think it is worth reflecting on the granularity of each set of state.
One of the ongoing issues that we've had with vuex is that there is one granularity of state - global - and this has caused issues and edge cases where state has not been properly reset, updated etc.
I know that you've tried to preempt that by having a specific state reset function, but if we instead encapsulated the state at a finer level of granularity, then we would be able to pre-empty any of these issues, rather than having to add additional code to fix them.
@@ -558,6 +567,8 @@ | |||
set(this.dragActive, true); | |||
}, | |||
openSelectResources(section_id) { | |||
//initialize workingResourcePool | |||
this.initializeWorkingResourcePool(); |
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.
Is there a reason this couldn't happen within the ResourceSelection component instead?
@@ -382,6 +385,8 @@ | |||
allSections, | |||
activeSection, | |||
inactiveSections, | |||
activeResourcePool, |
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.
Both of these are added, and neither are used.
setup() { | ||
const { | ||
//Computed | ||
resetWorkingResourcePool, |
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 be better to make this component emit an event rather than handle all state clearing and route changing.
@@ -477,8 +548,13 @@ export default function useQuizCreation(DEBUG = false) { | |||
return { | |||
// Methods | |||
saveQuiz, | |||
initializeWorkingResourcePool, |
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 is turning the useQuizCreation
composable into a bit of a catch all again - I think all the state and methods here are at a smaller level of granularity than the useQuizCreation composable is handling.
I think with some judicious work, this could all be instantiated entirely within the ResourceSelection component, or in a separate composable that is only used inside the ResourceSelection 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 think the main issue is handling that the component re-setups each navigation, hence it living in then composable. I think I initially suggested that it live in ResourceSelection but foresaw it being a problem until we fix the coach routing issues
return ExamResource.saveModel({ data: get(_quiz) }); | ||
|
||
// Here we update each section's `resource_pool` to only be the IDs of the resources | ||
const sectionsWithResourcePoolAsIDs = get(allSections).map(section => { |
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.
Couldn't we just always maintain the frontend representation of this the same as the backend, and have a separate representation of the resources that map to these IDs that we populate when we start editing a specific section? (in the proposed separate state management within ResourceSelection that I propose 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 specced it this way so that we have access to all of the Exercise metadata that we've already fetched at hand so we can do the ancestry calculations and get the assessmentids for question enumeration.
This is related to the issue I made and closed yesterday re: updating the serializer to take the object rather than the IDs - but since that's only a concern in the case that we edit a saved quiz (in which case we'd need to fetch the metadata).
I figured that this way reduces our needing to fetch the metadata wherever it is needed here while keeping things roughly in the shape of the backend data - except on the front end we keep the whole object whereas we just send the IDs.
To be honest I'm not entirely sure this needs to be saved at all except for in the case that we permit editing / duplication of quizzes as the 'questions' property has everything needed to render the quiz. The resource_pool is solely used for enumerating the total possible pool of questions the coach can choose from to add to the quiz.
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.
Coming back to this after the weekend, I think that it makes sense to maintain a separate map of the metadata and to keep the list of IDs in the section's data withing the useQuizCreation module.
This would then be easy to extend to accommodate duplication/editing of a quiz or section as we can then populate the initial map with a single API call for the list of node IDs there.
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've addressed the clean-up comments.
I'm going to add a note re: "refactor working resource pool to live in ResourceSelection.vue, rather than useQuizCreation, once rerouting between folders no longer results in remounting the component" to #11741 and we can hopefully aim for it in a planned patch release.
I'm approving & merging now to be sure issues we plan to assign tomorrow can be started.
Summary
References
Solves the first part of #11734
Reviewer guidance
For side Panel:
For working_resource_pool logic
…
Testing checklist
PR process
Reviewer checklist
yarn
andpip
)