Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ ExamResource.saveModel = jest.fn(() => Promise.resolve({}));
const VALID_EXERCISE_ID = 'af26e1b4f3b94f3e8f4f3b4f3e8f4f3a';

/**
* @param num {number} - The number of questions to create
* @param overrides {object} - Any overrides to apply to the default question
* Generates an array of mock quiz questions.
* @param {number} num - Number of questions to generate.
* @returns {Array} Array of generated quiz question objects.
*/
function generateQuestions(num = 0) {
const qs = [];
Expand All @@ -31,9 +32,10 @@ function generateQuestions(num = 0) {
return qs;
}

/** @param numQuestions {number} - The number of questions to create within the exercise
* @returns {Exercise} - An exercise with the given number of questions
* A helper function to mock an exercise with a given number of questions (for `resource_pool`)
/**
* Generates a mock quiz exercise with the given number of questions.
* @param {number} numQuestions - Number of questions to include in the exercise.
* @returns {object} A mock exercise object with assessmentmetadata.
*/
function generateExercise(numQuestions) {
const assessments = generateQuestions(numQuestions);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { handleApiError } from 'kolibri/utils/appError';

/**
* Fetch sync status for all members of a class.
* @param {string} classId - The classroom ID
* @returns {Promise<Array|Error>} Array of sync status objects, or Error on failure
* @param {string} classId - The classroom ID.
* @returns {Promise<Array|Error>} Array of sync status objects, or Error on failure.
*/
export function fetchClassSyncStatus(classId) {
return UserSyncStatusResource.fetchCollection({
Expand Down
34 changes: 18 additions & 16 deletions kolibri/plugins/coach/frontend/composables/quizCreationSpecs.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
*/

/**
* @typedef {Object} QuizExercise An object referencing an exercise or topic to be used
* within the `QuizSeciton.resource_pool` property.
* @property {string} id Unique ID for this exercise (aka, `exercise_id` elsewhere)
* @property {string} title The resource title
* @property {string} parent The ID of the parent contentnode
* @property {string} content_id The ID for the piece of content
* @property {bool} is_leaf Whether or not this is a leaf node (i.e. an exercise)
* @property {string} kind Exercise or Topic in our case - see: `ContentNodeKinds`
* @typedef {object} QuizExercise An object referencing an exercise or topic to be used
* within the `QuizSection.resource_pool` property.
* @property {string} id Unique ID for this exercise (aka, `exercise_id` elsewhere)
* @property {string} title The resource title
* @property {string} parent The ID of the parent contentnode
* @property {string} content_id The ID for the piece of content
* @property {boolean} is_leaf Whether or not this is a leaf node (i.e. an exercise)
* @property {string} kind Exercise or Topic in our case - see: `ContentNodeKinds`
*/

export const QuizExercise = {
Expand Down Expand Up @@ -53,17 +53,18 @@ function _exercise_id_validator(value) {
}

/**
* @typedef {Object} QuizQuestion A particular question in a Quiz - aka an assessment item
* from an QuizExercise.
* @property {string} item A ** unique ** identifier for this question that is
* @typedef {object} QuizQuestion A particular question in a Quiz - aka an assessment item
* from a QuizExercise.
* @property {string} item A unique identifier for this question that is
* a combination of <exercise_id>:<question_id>
* @property {string} exercise_id The ID of the resource from which the question originates
* @property {string} question_id A *unique* identifier of this particular question within
* @property {string} question_id A unique identifier of this particular question within
* the quiz -- same as the `assessment_item_id`
* @property {string} title A title for the question, editable by the user
* @property {number} counter_in_exercise A number assigned to separate questions which have the
* same exercise title to differentiate them
*/

export const QuizQuestion = {
item: {
type: String,
Expand Down Expand Up @@ -103,11 +104,12 @@ export const QuizQuestion = {
};

/**
* @typedef {Object} QuizSection Defines a single section of the quiz
* @typedef {object} QuizSection Defines a single section of the quiz
* @property {string} section_id A unique ID for the section - this is
* only used on the front-end
* @property {string} section_title The title of the quiz section
* @property {string} description A text blob associated with the section
* @property {string} description A text blob associated with the
* section
* @property {QuizQuestion[]} questions The list of QuizQuestion objects in the
* section
* @property {boolean} learners_see_fixed_order A bool flag indicating whether this
Expand Down Expand Up @@ -143,9 +145,9 @@ function getRandomInt() {
}

/**
* @typedef {Object} Quiz The overall primary Quiz object
* @typedef {object} Quiz The overall primary Quiz object
* @property {string} title The title of the whole quiz
* @property {QuizSection[]} question_sources A list of the QuizSection objects that make up the
* @property {QuizSection[]} question_sources The QuizSection objects that make up the quiz
* @property {number} seed A random number used to seed the randomization
*/
export const Quiz = {
Expand Down
11 changes: 5 additions & 6 deletions kolibri/plugins/coach/frontend/composables/useAttendanceForm.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,15 @@ import useCoreCoach from './useCoreCoach';

/**
* Shared attendance form logic used by both AttendanceNewPage and AttendanceEditPage.
*
* @param {Object} options
* @param {object} options - Options object.
* @param {import('vue').Ref<boolean>|import('vue').ComputedRef<boolean>} options.hasChanges
* Reactive flag indicating whether the form has unsaved changes.
* @param {Function} options.markClean
* Called when the user confirms leaving without saving.
* @param {Function} options.markClean - Called when the user confirms leaving without saving.
* @param {import('vue').Ref<boolean>} options.submitting
* Reactive flag for whether a submit/save is in progress.
* @param {Function} [options.onChange]
* Optional callback fired whenever the attendance map changes (toggle or mark-all).
* @param {Function} [options.onChange] - Optional callback fired whenever the attendance map
* changes (toggle or mark-all).
* @returns {object} Attendance form state and methods.
*/
export default function useAttendanceForm({ hasChanges, markClean, submitting, onChange }) {
const router = useRouter();
Expand Down
13 changes: 6 additions & 7 deletions kolibri/plugins/coach/frontend/composables/useCoachTabs.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ const lastTabsInteraction = reactive({
export function useCoachTabs() {
/**
* Stores an interaction with tabs
*
* @param {String} tabsInterfaceId ID of a tabbed interface interacted with
* @param {String} event An event kind. Available kinds: 'click'
* @param {string} tabsInterfaceId - ID of a tabbed interface interacted with
* @param {string} event - An event kind. Available kinds: 'click'
*/
function saveTabsInteraction(tabsInterfaceId, event) {
lastTabsInteraction.tabsInterfaceId = tabsInterfaceId;
Expand All @@ -56,16 +55,16 @@ export function useCoachTabs() {

/**
* Stores a click interaction with tabs
*
* @param {String} tabsInterfaceId ID of a tabbed interface interacted with
* @param {string} tabsInterfaceId - ID of a tabbed interface interacted with
*/
function saveTabsClick(tabsInterfaceId) {
saveTabsInteraction(tabsInterfaceId, TabsEvents.CLICK);
}

/**
* @param {String} tabsInterfaceId ID of a tabbed interface
* @returns {Boolean} `true` when tabs with the provided ID were
* Returns whether the given tabs interface was clicked recently
* @param {string} tabsInterfaceId - ID of a tabbed interface
* @returns {boolean} `true` when tabs with the provided ID were
* clicked recently
*/
function wereTabsClickedRecently(tabsInterfaceId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,8 @@ const { defaultErrorMessage$ } = coreStrings;
* A composable for managing course session state.
* Handles fetching course session data, course content, active tests, and test history.
* Provides derived state for units and unit phase.
*
* @param {Ref<string>} courseSessionId - The ID of the course session to load
* @returns {Object} Reactive state and methods for managing the course session
* @param {object} courseSessionId - A ref containing the course session ID
* @returns {object} Reactive state and methods for managing the course session
*/
export default function useCourseSession(courseSessionId) {
const { createSnackbar } = useSnackbar();
Expand Down Expand Up @@ -177,7 +176,6 @@ export default function useCourseSession(courseSessionId) {

/**
* Activates a test for the current active unit.
*
* @param {string} testType - Either 'pre' or 'post'
* @returns {Promise} Resolves when the test is activated
*/
Expand Down Expand Up @@ -209,7 +207,6 @@ export default function useCourseSession(courseSessionId) {
/**
* Closes the currently active test.
* Moves the closed test to history and clears activeTest.
*
* @returns {Promise} Resolves when the test is closed
*/
function closeTest() {
Expand Down Expand Up @@ -244,7 +241,6 @@ export default function useCourseSession(courseSessionId) {
/**
* Toggles the active state of the course session.
* Updates the courseSession ref with the new state on success.
*
* @returns {Promise} Resolves with the updated course session
*/
function toggleCourseActive() {
Expand Down
71 changes: 40 additions & 31 deletions kolibri/plugins/coach/frontend/composables/useFetchTree.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,55 +3,61 @@ import { computed, ref } from 'vue';
import ContentNodeResource from 'kolibri-common/apiResources/ContentNodeResource';

/**
* @deftype FetchTreeConfig
* @typedef {import('kolibri-common/apiResources/ContentNodeResource').ContentNode} ContentNode
*/

/**
* @typedef {object} FetchTreeConfig
* @property {computed<string|null|undefined>} topicId - The id of the root node to fetch the
* children for
* @property {Object} [params] - Params to pass to the ContentNodeResource.fetchTree method this
* can include any keys that our API supports for filtering the results.
* Example: { kind_in: [ContentNodeKinds.EXERCISE, ContentNodeKinds.TOPIC] }
* Default: {}
* children for.
* @property {object} [params] - Params to pass to the `ContentNodeResource.fetchTree` method;
* this can include any keys that our API supports for filtering the results. Example:
* `{kind_in: [ContentNodeKinds.EXERCISE, ContentNodeKinds.TOPIC]}`. Default: `{}`.
*/

/**
* An API wrapper for fetching contents by way of the `ContentNodeResource.fetchTree` method
* with specific helper methods for lazily loading more of the contents within a topic.
* @module useFetchTree
* @description An API wrapper for fetching contents by way of the ContentNodeResource.fetchTree
* method with specific helper methods for lazily loading more of the contents within a topic.
* @param {FetchTreeConfig} config - Fetch tree configuration.
* @returns {object} Reactive topic, resources, loading state, and fetch methods.
*/
export default function useFetchTree({ topicId, params = {} } = {}) {
/** Private variables:
* Note that the _ prefix is used here to indicate that these are values that should only be able
* to be mutated within this module and are read-only outside of it. To make changes to these
* values, use the methods provided by this module (or add a method, if needed). */
// Private variables
//
// Note that the _ prefix is used here to indicate that these are values that should only
// be able to be mutated within this module and are read-only outside of it. To make
// changes to these values, use the methods provided by this module (or add a method, if
// needed).

/** @type {ref<ContentNode|null>} The topic node that we are fetching the children for */
const _topic = ref(null);

/** @type {ref<string>} All resources which have been fetched */
/** @type {ref<ContentNode[]>} All resources which have been fetched */
const _resources = ref([]);

/** @type {ref<Boolean>} Whether we are currently fetching/processing the child nodes */
/** @type {ref<boolean>} Whether we are currently fetching/processing the child nodes */
const _loading = ref(false);

/** @type {ref<Object|null>} The params object we pass to the ContentNodeResource fetchTree method
* to fetch the next batch of nodes. Note that the `more` we get from the API will include the
* same parameters as we sent in the first call.
* When null, there are no more to fetch for the current topicId */
/**
* @type {ref<object|null>} The params object we pass to the `ContentNodeResource.fetchTree`
* method to fetch the next batch of nodes. Note that the `more` we get from the API will
* include the same parameters as we sent in the first call. When null, there are no more
* to fetch for the current topicId.
*/
const _moreParams = ref(null);

const hasMore = computed(() => get(_moreParams) !== null);
/**
* @description TODO
*
* @param {Object} params - Params to pass to the ContentNodeResource fetchTree method
* (Default: {})
*
* @affects _resources - The list of resources will be updated with the new list of _resource
* @affects _loading - The loading state will be set to true while the fetch is in progress and
* then set to false when it completes
* Fetches a batch of content nodes under the current topic.
* @param {object} params - Params to pass to the `ContentNodeResource.fetchTree` method
* (default: `{}`).
* @returns {Promise<ContentNode[]>} Resolves with the list of resources fetched.
* @affects _resources - The list of resources will be updated with the new list of resources.
* @affects _loading - The loading state will be set to true while the fetch is in progress
* and then set to false when it completes.
* @affects _moreParams
*
* @returns {Promise<ContentNode[]>} A promise that resolves to the list of resources fetched
**/
*/
async function _fetchNodeTree(params) {
set(_loading, true);

Expand All @@ -74,8 +80,11 @@ export default function useFetchTree({ topicId, params = {} } = {}) {
return _fetchNodeTree(params);
}

/** Fetches the next batch of nodes, which fetchTree will do on its own, but this makes for a
* easier-to-understand API */
/**
* Fetches the next batch of nodes, which fetchTree will do on its own, but this makes
* for an easier-to-understand API.
* @returns {Promise<ContentNode[]>} Resolves with the next batch of resources.
*/
async function fetchMore() {
if (!get(hasMore)) {
return Promise.reject('Tried to call fetchMore when no more ContentNodes are available');
Expand Down
Loading
Loading