-
Notifications
You must be signed in to change notification settings - Fork 717
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
Select resource sidepanel #11511
Closed
AllanOXDi
wants to merge
50
commits into
learningequality:develop
from
AllanOXDi:select-resource-sidepanel
Closed
Select resource sidepanel #11511
Changes from all commits
Commits
Show all changes
50 commits
Select commit
Hold shift + click to select a range
591a93c
set not loading when quiz creator comes up
nucleogenesis c6c2f8e
add DEBUG option to useQuizCreation; bootstrap basic accordion setup
nucleogenesis 29abaca
uuid for test data ID
nucleogenesis 47db90f
remove unneded prop
nucleogenesis 6401cdc
lint
nucleogenesis f9854a2
drag-and-drop scaffolding function & design
nucleogenesis be1a910
styles on the accordion headers
nucleogenesis 47fbd4f
section tabs better design parity w/out regression
nucleogenesis f9a8c76
dragStart event allows dynamic styles when dragging; disallow highlig…
nucleogenesis 8441700
design polish
nucleogenesis b1980dc
helpers for select all checkbox props
nucleogenesis 87064a3
enhanced quiz messages updates
nucleogenesis d1b567a
pass click event through tabswithoverflow; a11y improvements
nucleogenesis 621503d
repoint kds
nucleogenesis b64d29b
edit & delete buttons work for section tabs
nucleogenesis 46614c3
expandcollapse icon;
nucleogenesis 2a85e7d
root page mostly feature complete; polish; a11y updates
nucleogenesis 4449099
handle quiz title field
nucleogenesis f2b5f0e
update link to kds commit/pr
nucleogenesis 21e6893
Ensure [Tab]-nav flow works properly when leaving Options button
nucleogenesis e621f66
not debug by default
nucleogenesis 1ceee06
fix eternal loading state when navigation routes
nucleogenesis 4aa72d2
update kds
nucleogenesis b4f196f
fixed loading failure
AllanOXDi 63239d3
resource sidepanel header added
AllanOXDi 5c97f6d
added search component
AllanOXDi 07b7724
structured the add resource sidepanel
AllanOXDi 827c0b6
adds channel cards to select resource side panel
AllanOXDi 89efc54
added ContentCardList component
AllanOXDi a429f96
fetch resources for content
AllanOXDi 85ee0d2
Optimize bookmark fetching logic for enhance quiz managment
AllanOXDi d992550
sets routes for channel resources
AllanOXDi 85d8b0c
added bookmarked code
AllanOXDi 53512bb
added the bookmark card
AllanOXDi c683194
replaced quizforge data with composable
AllanOXDi 59ab6dd
cleanedup bookmarkicon area
AllanOXDi 8ebe621
add show resourc component
AllanOXDi b14457f
implement content filtering for select resource side panel
AllanOXDi fd7bf8e
displays boomarked resources
AllanOXDi 776ba5c
added the component for the channels
AllanOXDi 75ec4ec
added the component for the channels
AllanOXDi 300b355
added dragging feature
AllanOXDi 81300e4
add bookmarked resources
AllanOXDi 3fc3ba5
can navigate to the first level of the topic tree
AllanOXDi 8fc9dde
removed unused data elements and components
AllanOXDi a389f14
changed structure to only allow contentCardlist component to update
AllanOXDi 5d0e71a
can navigate backwards using the back arrow
AllanOXDi 38687eb
adds topic tree navigation
AllanOXDi 7d62544
added selection breadcrumbs
AllanOXDi eea8aeb
added selection breadcrumbs
AllanOXDi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
198 changes: 198 additions & 0 deletions
198
kolibri/plugins/coach/assets/src/composables/useExerciseResources.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
import { ref, onMounted } from 'kolibri.lib.vueCompositionApi'; | ||
import { ChannelResource, ContentNodeResource, ContentNodeSearchResource } from 'kolibri.resources'; | ||
import { ContentNodeKinds } from 'kolibri.coreVue.vuex.constants'; | ||
import { getContentNodeThumbnail } from 'kolibri.utils.contentNode'; | ||
import { set } from '@vueuse/core'; | ||
// import pickBy from 'lodash/pickBy'; | ||
import uniq from 'lodash/uniq'; | ||
// import store from 'kolibri.coreVue.vuex.store'; | ||
|
||
export function useExerciseResources() { | ||
const resources = ref(null); | ||
const channels = ref([]); | ||
const bookmarks = ref([]); | ||
const channelTopics = ref([]); | ||
const contentList = ref([]); | ||
const ancestors = ref([]); | ||
const currentTopicId = ref(null); | ||
const currentTopic = ref(null); | ||
const currentTopicResource = ref(null); | ||
|
||
function fetchChannelResource() { | ||
ChannelResource.fetchCollection({ params: { has_exercises: true, available: true } }).then( | ||
response => { | ||
set( | ||
channels, | ||
response.map(chnl => { | ||
return { | ||
...chnl, | ||
id: chnl.root, | ||
title: chnl.name, | ||
kind: ContentNodeKinds.CHANNEL, | ||
is_leaf: false, | ||
}; | ||
}) | ||
); | ||
} | ||
); | ||
} | ||
|
||
function fetchBookMarkedResource() { | ||
ContentNodeResource.fetchBookmarks({ params: { limit: 25, available: true } }).then(data => { | ||
bookmarks.value = data.results ? data.results : []; | ||
}); | ||
} | ||
|
||
function _getTopicsWithExerciseDescendants(topicIds = []) { | ||
return new Promise(resolve => { | ||
if (!topicIds.length) { | ||
resolve([]); | ||
return; | ||
} | ||
const topicsNumAssessmentDescendantsPromise = ContentNodeResource.fetchDescendantsAssessments( | ||
topicIds | ||
); | ||
|
||
topicsNumAssessmentDescendantsPromise.then(response => { | ||
const topicsWithExerciseDescendants = []; | ||
response.data.forEach(descendantAssessments => { | ||
if (descendantAssessments.num_assessments > 0) { | ||
topicsWithExerciseDescendants.push({ | ||
id: descendantAssessments.id, | ||
numAssessments: descendantAssessments.num_assessments, | ||
exercises: [], | ||
}); | ||
} | ||
}); | ||
|
||
ContentNodeResource.fetchDescendants( | ||
topicsWithExerciseDescendants.map(topic => topic.id), | ||
{ | ||
descendant_kind: ContentNodeKinds.EXERCISE, | ||
} | ||
).then(response => { | ||
response.data.forEach(exercise => { | ||
channelTopics.value.push(exercise); | ||
const topic = topicsWithExerciseDescendants.find(t => t.id === exercise.ancestor_id); | ||
topic.exercises.push(exercise); | ||
}); | ||
channels.value = channelTopics.value; | ||
resolve(topicsWithExerciseDescendants); | ||
}); | ||
}); | ||
}); | ||
} | ||
|
||
function fetchTopicResource(topicId) { | ||
const topicNodePromise = ContentNodeResource.fetchModel({ id: topicId }); | ||
const childNodesPromise = ContentNodeResource.fetchCollection({ | ||
getParams: { | ||
parent: topicId, | ||
kind_in: [ContentNodeKinds.TOPIC, ContentNodeKinds.EXERCISE], | ||
}, | ||
}); | ||
const loadRequirements = [topicNodePromise, childNodesPromise]; | ||
|
||
return Promise.all(loadRequirements).then(([topicNode, childNodes]) => { | ||
return filterAndAnnotateContentList(childNodes).then(contentList => { | ||
// set(topicId, topicNode.id); | ||
ancestors.value = [...topicNode.ancestors, topicNode]; | ||
return { | ||
...topicNode, | ||
...contentList, | ||
thumbnail: getContentNodeThumbnail(topicNode), | ||
}; | ||
}); | ||
}); | ||
} | ||
|
||
function filterAndAnnotateContentList(childNodes) { | ||
return new Promise(resolve => { | ||
if (childNodes) { | ||
const childTopics = childNodes.filter(({ kind }) => kind === ContentNodeKinds.TOPIC); | ||
const topicIds = childTopics.map(({ id }) => id); | ||
const topicsThatHaveExerciseDescendants = _getTopicsWithExerciseDescendants(topicIds); | ||
topicsThatHaveExerciseDescendants.then(topics => { | ||
const childNodesWithExerciseDescendants = childNodes | ||
.map(childNode => { | ||
const index = topics.findIndex(topic => topic.id === childNode.id); | ||
if (index !== -1) { | ||
return { ...childNode, ...topics[index] }; | ||
} | ||
return childNode; | ||
}) | ||
.filter(childNode => { | ||
if ( | ||
childNode.kind === ContentNodeKinds.TOPIC && | ||
(childNode.numAssessments || 0) < 1 | ||
) { | ||
return false; | ||
} | ||
return true; | ||
}); | ||
contentList.value = childNodesWithExerciseDescendants.map(node => ({ | ||
...node, | ||
thumbnail: getContentNodeThumbnail(node), | ||
})); | ||
channels.value = contentList.value; | ||
resolve(contentList); | ||
}); | ||
} | ||
}); | ||
} | ||
|
||
function showChannelLevel(store, params, query = {}) { | ||
let kinds; | ||
if (query.kind) { | ||
kinds = [query.kind]; | ||
} else { | ||
kinds = [ContentNodeKinds.EXERCISE, ContentNodeKinds.TOPIC]; | ||
} | ||
|
||
ContentNodeSearchResource.fetchCollection({ | ||
getParams: { | ||
search: '', | ||
kind_in: kinds, | ||
// ...pickBy({ channel_id: query.channel }), | ||
}, | ||
}).then(results => { | ||
return filterAndAnnotateContentList(results.results).then(contentList => { | ||
const searchResults = { | ||
...results, | ||
results: contentList, | ||
content_kinds: results.content_kinds.filter(kind => | ||
[ContentNodeKinds.TOPIC, ContentNodeKinds.EXERCISE].includes(kind) | ||
), | ||
contentIdsFetched: uniq(results.results.map(({ content_id }) => content_id)), | ||
}; | ||
|
||
this.channels.value = searchResults.results; | ||
console.log(searchResults.results); | ||
}); | ||
}); | ||
} | ||
|
||
onMounted(() => { | ||
fetchChannelResource(); | ||
fetchBookMarkedResource(); | ||
filterAndAnnotateContentList(); | ||
_getTopicsWithExerciseDescendants([]); | ||
}); | ||
|
||
return { | ||
resources, | ||
channels, | ||
bookmarks, | ||
contentList, | ||
channelTopics, | ||
currentTopicId, | ||
currentTopic, | ||
currentTopicResource, | ||
ancestors, | ||
fetchChannelResource, | ||
filterAndAnnotateContentList, | ||
_getTopicsWithExerciseDescendants, | ||
showChannelLevel, | ||
fetchTopicResource, | ||
}; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
As per our conversation - this is where we could use the new fetchTree method instead, to fetch both the topic and its children in one go.
To limit data, can pass the
depth: 1
getParam to only get the immediate descendants. The only thing to be aware of here is that the return data here is that the children are paginated by default.Can see an example of it in use here:
kolibri/kolibri/plugins/learn/assets/src/views/TopicsPage/index.vue
Line 426 in b423353