// (C) Copyright 2015 Moodle Pty Ltd. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. import { CoreRoutedItemsManagerSource } from '@classes/items-management/routed-items-manager-source'; import { CoreGroupInfo, CoreGroups } from '@services/groups'; import { AddonModFeedback, AddonModFeedbackProvider, AddonModFeedbackWSAnonAttempt, AddonModFeedbackWSAttempt, AddonModFeedbackWSFeedback, } from '../services/feedback'; import { AddonModFeedbackHelper } from '../services/feedback-helper'; /** * Feedback attempts. */ export class AddonModFeedbackAttemptsSource extends CoreRoutedItemsManagerSource { readonly COURSE_ID: number; readonly CM_ID: number; selectedGroup?: number; identifiable?: AddonModFeedbackWSAttempt[]; identifiableTotal?: number; anonymous?: AddonModFeedbackWSAnonAttempt[]; anonymousTotal?: number; groupInfo?: CoreGroupInfo; protected feedback?: AddonModFeedbackWSFeedback; constructor(courseId: number, cmId: number) { super(); this.COURSE_ID = courseId; this.CM_ID = cmId; } /** * @inheritdoc */ getItemPath(attempt: AddonModFeedbackAttemptItem): string { return attempt.id.toString(); } /** * @inheritdoc */ getPagesLoaded(): number { if (!this.identifiable || !this.anonymous) { return 0; } const pageLength = this.getPageLength(); return Math.ceil(Math.max(this.anonymous.length, this.identifiable.length) / pageLength); } /** * Type guard to infer AddonModFeedbackWSAttempt objects. * * @param discussion Item to check. * @return Whether the item is an identifieable attempt. */ isIdentifiableAttempt(attempt: AddonModFeedbackAttemptItem): attempt is AddonModFeedbackWSAttempt { return 'fullname' in attempt; } /** * Type guard to infer AddonModFeedbackWSAnonAttempt objects. * * @param discussion Item to check. * @return Whether the item is an anonymous attempt. */ isAnonymousAttempt(attempt: AddonModFeedbackAttemptItem): attempt is AddonModFeedbackWSAnonAttempt { return 'number' in attempt; } /** * Invalidate feedback cache. */ async invalidateCache(): Promise { await Promise.all([ CoreGroups.invalidateActivityGroupInfo(this.CM_ID), this.feedback && AddonModFeedback.invalidateResponsesAnalysisData(this.feedback.id), ]); } /** * Load feedback. */ async loadFeedback(): Promise { this.feedback = await AddonModFeedback.getFeedback(this.COURSE_ID, this.CM_ID); this.groupInfo = await CoreGroups.getActivityGroupInfo(this.CM_ID); this.selectedGroup = CoreGroups.validateGroupId(this.selectedGroup, this.groupInfo); } /** * @inheritdoc */ protected getPageLength(): number { return AddonModFeedbackProvider.PER_PAGE; } /** * @inheritdoc */ protected async loadPageItems(page: number): Promise<{ items: AddonModFeedbackAttemptItem[]; hasMoreItems: boolean }> { if (!this.feedback) { throw new Error('Can\'t load attempts without feeback'); } const result = await AddonModFeedbackHelper.getResponsesAnalysis(this.feedback.id, { page, groupId: this.selectedGroup, cmId: this.CM_ID, }); if (page === 0) { this.identifiableTotal = result.totalattempts; this.anonymousTotal = result.totalanonattempts; } const totalItemsLoaded = this.getPageLength() * (page + 1); const pageAttempts: AddonModFeedbackAttemptItem[] = [ ...result.attempts, ...result.anonattempts, ]; return { items: pageAttempts, hasMoreItems: result.totalattempts > totalItemsLoaded || result.totalanonattempts > totalItemsLoaded, }; } /** * @inheritdoc */ protected setItems(attempts: AddonModFeedbackAttemptItem[], hasMoreItems: boolean): void { this.identifiable = attempts.filter(this.isIdentifiableAttempt); this.anonymous = attempts.filter(this.isAnonymousAttempt); super.setItems((this.identifiable as AddonModFeedbackAttemptItem[]).concat(this.anonymous), hasMoreItems); } } /** * Type of items that can be held in the source. */ export type AddonModFeedbackAttemptItem = AddonModFeedbackWSAttempt | AddonModFeedbackWSAnonAttempt;