MOBILE-2850 feedback: Prefetch data after syncing feedback

main
Dani Palou 2019-02-26 09:17:49 +01:00
parent 88b5eb7af0
commit 0dd4ac1a22
8 changed files with 145 additions and 65 deletions

View File

@ -77,15 +77,29 @@ export class AddonModFeedbackIndexComponent extends CoreCourseModuleMainActivity
// Listen for form submit events. // Listen for form submit events.
this.submitObserver = this.eventsProvider.on(AddonModFeedbackProvider.FORM_SUBMITTED, (data) => { this.submitObserver = this.eventsProvider.on(AddonModFeedbackProvider.FORM_SUBMITTED, (data) => {
if (this.feedback && data.feedbackId == this.feedback.id) { if (this.feedback && data.feedbackId == this.feedback.id) {
// Go to review attempt if an attempt in this quiz was finished and synced.
this.tabsLoaded['analysis'] = false; this.tabsLoaded['analysis'] = false;
this.tabsLoaded['overview'] = false; this.tabsLoaded['overview'] = false;
this.loaded = false; this.loaded = false;
let promise;
// Prefetch data if needed.
if (!data.offline && this.isPrefetched()) {
promise = this.feedbackSync.prefetchAfterUpdate(this.module, this.courseId).catch(() => {
// Ignore errors.
});
} else {
promise = Promise.resolve();
}
promise.then(() => {
// Load the right tab.
if (data.tab != this.tab) { if (data.tab != this.tab) {
this.tabChanged(data.tab); this.tabChanged(data.tab);
} else { } else {
this.loadContent(true); this.loadContent(true);
} }
});
} }
}, this.siteId); }, this.siteId);
} }

View File

@ -338,8 +338,13 @@ export class AddonModFeedbackFormPage implements OnDestroy {
ngOnDestroy(): void { ngOnDestroy(): void {
if (this.submitted) { if (this.submitted) {
const tab = this.submitted == 'analysis' ? 'analysis' : 'overview'; const tab = this.submitted == 'analysis' ? 'analysis' : 'overview';
// If form has been submitted, the info has been already invalidated but we should update index view. // If form has been submitted, the info has been already invalidated but we should update index view.
this.eventsProvider.trigger(AddonModFeedbackProvider.FORM_SUBMITTED, {feedbackId: this.feedback.id, tab: tab}); this.eventsProvider.trigger(AddonModFeedbackProvider.FORM_SUBMITTED, {
feedbackId: this.feedback.id,
tab: tab,
offline: this.completedOffline
});
} }
this.onlineObserver && this.onlineObserver.unsubscribe(); this.onlineObserver && this.onlineObserver.unsubscribe();
} }

View File

@ -20,6 +20,7 @@ import { CoreFilepoolProvider } from '@providers/filepool';
import { CoreAppProvider } from '@providers/app'; import { CoreAppProvider } from '@providers/app';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { AddonModFeedbackOfflineProvider } from './offline'; import { AddonModFeedbackOfflineProvider } from './offline';
import { CoreSiteWSPreSets } from '@classes/site';
/** /**
* Service that provides some features for feedbacks. * Service that provides some features for feedbacks.
@ -215,11 +216,14 @@ export class AddonModFeedbackProvider {
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {number} groupId Group id, 0 means that the function will determine the user group. * @param {number} groupId Group id, 0 means that the function will determine the user group.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {any} [previous] Only for recurrent use. Object with the previous fetched info. * @param {any} [previous] Only for recurrent use. Object with the previous fetched info.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getAllNonRespondents(feedbackId: number, groupId: number, siteId?: string, previous?: any): Promise<any> { getAllNonRespondents(feedbackId: number, groupId: number, ignoreCache?: boolean, siteId?: string, previous?: any)
: Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (typeof previous == 'undefined') { if (typeof previous == 'undefined') {
previous = { previous = {
@ -228,7 +232,7 @@ export class AddonModFeedbackProvider {
}; };
} }
return this.getNonRespondents(feedbackId, groupId, previous.page, siteId).then((response) => { return this.getNonRespondents(feedbackId, groupId, previous.page, ignoreCache, siteId).then((response) => {
if (previous.users.length < response.total) { if (previous.users.length < response.total) {
previous.users = previous.users.concat(response.users); previous.users = previous.users.concat(response.users);
} }
@ -237,7 +241,7 @@ export class AddonModFeedbackProvider {
// Can load more. // Can load more.
previous.page++; previous.page++;
return this.getAllNonRespondents(feedbackId, groupId, siteId, previous); return this.getAllNonRespondents(feedbackId, groupId, ignoreCache, siteId, previous);
} }
previous.total = response.total; previous.total = response.total;
@ -250,11 +254,14 @@ export class AddonModFeedbackProvider {
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {number} groupId Group id, 0 means that the function will determine the user group. * @param {number} groupId Group id, 0 means that the function will determine the user group.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {any} [previous] Only for recurrent use. Object with the previous fetched info. * @param {any} [previous] Only for recurrent use. Object with the previous fetched info.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getAllResponsesAnalysis(feedbackId: number, groupId: number, siteId?: string, previous?: any): Promise<any> { getAllResponsesAnalysis(feedbackId: number, groupId: number, ignoreCache?: boolean, siteId?: string, previous?: any)
: Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (typeof previous == 'undefined') { if (typeof previous == 'undefined') {
previous = { previous = {
@ -264,7 +271,7 @@ export class AddonModFeedbackProvider {
}; };
} }
return this.getResponsesAnalysis(feedbackId, groupId, previous.page, siteId).then((responses) => { return this.getResponsesAnalysis(feedbackId, groupId, previous.page, ignoreCache, siteId).then((responses) => {
if (previous.anonattempts.length < responses.totalanonattempts) { if (previous.anonattempts.length < responses.totalanonattempts) {
previous.anonattempts = previous.anonattempts.concat(responses.anonattempts); previous.anonattempts = previous.anonattempts.concat(responses.anonattempts);
} }
@ -277,7 +284,7 @@ export class AddonModFeedbackProvider {
// Can load more. // Can load more.
previous.page++; previous.page++;
return this.getAllResponsesAnalysis(feedbackId, groupId, siteId, previous); return this.getAllResponsesAnalysis(feedbackId, groupId, ignoreCache, siteId, previous);
} }
previous.totalattempts = responses.totalattempts; previous.totalattempts = responses.totalattempts;
@ -292,15 +299,16 @@ export class AddonModFeedbackProvider {
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {number} [groupId] Group ID. * @param {number} [groupId] Group ID.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the feedback is retrieved. * @return {Promise<any>} Promise resolved when the feedback is retrieved.
*/ */
getAnalysis(feedbackId: number, groupId?: number, siteId?: string): Promise<any> { getAnalysis(feedbackId: number, groupId?: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
feedbackid: feedbackId feedbackid: feedbackId
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getAnalysisDataCacheKey(feedbackId, groupId) cacheKey: this.getAnalysisDataCacheKey(feedbackId, groupId)
}; };
@ -308,6 +316,11 @@ export class AddonModFeedbackProvider {
params['groupid'] = groupId; params['groupid'] = groupId;
} }
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_feedback_get_analysis', params, preSets); return site.read('mod_feedback_get_analysis', params, preSets);
}); });
} }
@ -338,11 +351,12 @@ export class AddonModFeedbackProvider {
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {number} attemptId Attempt id to find. * @param {number} attemptId Attempt id to find.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {any} [previous] Only for recurrent use. Object with the previous fetched info. * @param {any} [previous] Only for recurrent use. Object with the previous fetched info.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getAttempt(feedbackId: number, attemptId: number, siteId?: string, previous?: any): Promise<any> { getAttempt(feedbackId: number, attemptId: number, ignoreCache?: boolean, siteId?: string, previous?: any): Promise<any> {
siteId = siteId || this.sitesProvider.getCurrentSiteId(); siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (typeof previous == 'undefined') { if (typeof previous == 'undefined') {
previous = { previous = {
@ -352,7 +366,7 @@ export class AddonModFeedbackProvider {
}; };
} }
return this.getResponsesAnalysis(feedbackId, 0, previous.page, siteId).then((responses) => { return this.getResponsesAnalysis(feedbackId, 0, previous.page, ignoreCache, siteId).then((responses) => {
let attempt; let attempt;
attempt = responses.attempts.find((attempt) => { attempt = responses.attempts.find((attempt) => {
@ -383,7 +397,7 @@ export class AddonModFeedbackProvider {
// Can load more. Check there. // Can load more. Check there.
previous.page++; previous.page++;
return this.getAttempt(feedbackId, attemptId, siteId, previous); return this.getAttempt(feedbackId, attemptId, ignoreCache, siteId, previous);
} }
// Not found and all loaded. Reject. // Not found and all loaded. Reject.
@ -405,18 +419,24 @@ export class AddonModFeedbackProvider {
* Returns the temporary completion timemodified for the current user. * Returns the temporary completion timemodified for the current user.
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getCurrentCompletedTimeModified(feedbackId: number, siteId?: string): Promise<any> { getCurrentCompletedTimeModified(feedbackId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
feedbackid: feedbackId feedbackid: feedbackId
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getCurrentCompletedTimeModifiedDataCacheKey(feedbackId) cacheKey: this.getCurrentCompletedTimeModifiedDataCacheKey(feedbackId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_feedback_get_current_completed_tmp', params, preSets).then((response) => { return site.read('mod_feedback_get_current_completed_tmp', params, preSets).then((response) => {
if (response && typeof response.feedback != 'undefined' && typeof response.feedback.timemodified != 'undefined') { if (response && typeof response.feedback != 'undefined' && typeof response.feedback.timemodified != 'undefined') {
return response.feedback.timemodified; return response.feedback.timemodified;
@ -552,20 +572,26 @@ export class AddonModFeedbackProvider {
* @param {string} key Name of the property to check. * @param {string} key Name of the property to check.
* @param {any} value Value to search. * @param {any} value Value to search.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [forceCache=false] True to always get the value from cache, false otherwise. Default false. * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<any>} Promise resolved when the feedback is retrieved. * @return {Promise<any>} Promise resolved when the feedback is retrieved.
*/ */
protected getFeedbackDataByKey(courseId: number, key: string, value: any, siteId?: string, forceCache?: boolean): Promise<any> { protected getFeedbackDataByKey(courseId: number, key: string, value: any, siteId?: string, forceCache?: boolean,
ignoreCache?: boolean): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
courseids: [courseId] courseids: [courseId]
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getFeedbackCacheKey(courseId) cacheKey: this.getFeedbackCacheKey(courseId)
}; };
if (forceCache) { if (forceCache) {
preSets['omitExpires'] = true; preSets.omitExpires = true;
} else if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
} }
return site.read('mod_feedback_get_feedbacks_by_courses', params, preSets).then((response) => { return site.read('mod_feedback_get_feedbacks_by_courses', params, preSets).then((response) => {
@ -590,10 +616,11 @@ export class AddonModFeedbackProvider {
* @param {number} cmId Course module ID. * @param {number} cmId Course module ID.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false. * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<any>} Promise resolved when the feedback is retrieved. * @return {Promise<any>} Promise resolved when the feedback is retrieved.
*/ */
getFeedback(courseId: number, cmId: number, siteId?: string, forceCache?: boolean): Promise<any> { getFeedback(courseId: number, cmId: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean): Promise<any> {
return this.getFeedbackDataByKey(courseId, 'coursemodule', cmId, siteId, forceCache); return this.getFeedbackDataByKey(courseId, 'coursemodule', cmId, siteId, forceCache, ignoreCache);
} }
/** /**
@ -603,28 +630,35 @@ export class AddonModFeedbackProvider {
* @param {number} id Feedback ID. * @param {number} id Feedback ID.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false. * @param {boolean} [forceCache] True to always get the value from cache, false otherwise. Default false.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<any>} Promise resolved when the feedback is retrieved. * @return {Promise<any>} Promise resolved when the feedback is retrieved.
*/ */
getFeedbackById(courseId: number, id: number, siteId?: string, forceCache?: boolean): Promise<any> { getFeedbackById(courseId: number, id: number, siteId?: string, forceCache?: boolean, ignoreCache?: boolean): Promise<any> {
return this.getFeedbackDataByKey(courseId, 'id', id, siteId, forceCache); return this.getFeedbackDataByKey(courseId, 'id', id, siteId, forceCache, ignoreCache);
} }
/** /**
* Returns the items (questions) in the given feedback. * Returns the items (questions) in the given feedback.
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getItems(feedbackId: number, siteId?: string): Promise<any> { getItems(feedbackId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
feedbackid: feedbackId feedbackid: feedbackId
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getItemsDataCacheKey(feedbackId) cacheKey: this.getItemsDataCacheKey(feedbackId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_feedback_get_items', params, preSets); return site.read('mod_feedback_get_items', params, preSets);
}); });
} }
@ -645,20 +679,28 @@ export class AddonModFeedbackProvider {
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {number} [groupId=0] Group id, 0 means that the function will determine the user group. * @param {number} [groupId=0] Group id, 0 means that the function will determine the user group.
* @param {number} [page=0] The page of records to return. * @param {number} [page=0] The page of records to return.
* @param {boolean} [ignoreCache] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getNonRespondents(feedbackId: number, groupId: number = 0, page: number = 0, siteId?: string): Promise<any> { getNonRespondents(feedbackId: number, groupId: number = 0, page: number = 0, ignoreCache?: boolean, siteId?: string)
: Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
feedbackid: feedbackId, feedbackid: feedbackId,
groupid: groupId, groupid: groupId,
page: page page: page
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getNonRespondentsDataCacheKey(feedbackId, groupId) cacheKey: this.getNonRespondentsDataCacheKey(feedbackId, groupId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_feedback_get_non_respondents', params, preSets); return site.read('mod_feedback_get_non_respondents', params, preSets);
}); });
} }
@ -725,7 +767,7 @@ export class AddonModFeedbackProvider {
}); });
}).catch(() => { }).catch(() => {
// If getPageItems fail we should calculate it using getItems. // If getPageItems fail we should calculate it using getItems.
return this.getItems(feedbackId, siteId).then((response) => { return this.getItems(feedbackId, false, siteId).then((response) => {
return this.fillValues(feedbackId, response.items, offline, ignoreCache, siteId).then((items) => { return this.fillValues(feedbackId, response.items, offline, ignoreCache, siteId).then((items) => {
// Separate items by pages. // Separate items by pages.
let currentPage = 0; let currentPage = 0;
@ -802,20 +844,26 @@ export class AddonModFeedbackProvider {
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {number} groupId Group id, 0 means that the function will determine the user group. * @param {number} groupId Group id, 0 means that the function will determine the user group.
* @param {number} page The page of records to return. * @param {number} page The page of records to return.
* @param {boolean} [ignoreCache=false] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<any>} Promise resolved when the info is retrieved. * @return {Promise<any>} Promise resolved when the info is retrieved.
*/ */
getResponsesAnalysis(feedbackId: number, groupId: number, page: number, siteId?: string): Promise<any> { getResponsesAnalysis(feedbackId: number, groupId: number, page: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
feedbackid: feedbackId, feedbackid: feedbackId,
groupid: groupId || 0, groupid: groupId || 0,
page: page || 0 page: page || 0
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getResponsesAnalysisDataCacheKey(feedbackId, groupId) cacheKey: this.getResponsesAnalysisDataCacheKey(feedbackId, groupId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return site.read('mod_feedback_get_responses_analysis', params, preSets); return site.read('mod_feedback_get_responses_analysis', params, preSets);
}); });
} }
@ -1037,18 +1085,24 @@ export class AddonModFeedbackProvider {
* Returns if feedback has been completed * Returns if feedback has been completed
* *
* @param {number} feedbackId Feedback ID. * @param {number} feedbackId Feedback ID.
* @param {boolean} [ignoreCache=false] True if it should ignore cached data (it will always fail in offline or server down).
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @return {Promise<boolean>} Promise resolved when the info is retrieved. * @return {Promise<boolean>} Promise resolved when the info is retrieved.
*/ */
isCompleted(feedbackId: number, siteId?: string): Promise<boolean> { isCompleted(feedbackId: number, ignoreCache?: boolean, siteId?: string): Promise<boolean> {
return this.sitesProvider.getSite(siteId).then((site) => { return this.sitesProvider.getSite(siteId).then((site) => {
const params = { const params = {
feedbackid: feedbackId feedbackid: feedbackId
}, },
preSets = { preSets: CoreSiteWSPreSets = {
cacheKey: this.getCompletedDataCacheKey(feedbackId) cacheKey: this.getCompletedDataCacheKey(feedbackId)
}; };
if (ignoreCache) {
preSets.getFromCache = false;
preSets.emergencyCache = false;
}
return this.utils.promiseWorks(site.read('mod_feedback_get_last_completed', params, preSets)); return this.utils.promiseWorks(site.read('mod_feedback_get_last_completed', params, preSets));
}); });
} }

View File

@ -173,19 +173,15 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
*/ */
protected prefetchFeedback(module: any, courseId: number, single: boolean, siteId: string): Promise<any> { protected prefetchFeedback(module: any, courseId: number, single: boolean, siteId: string): Promise<any> {
// Prefetch the feedback data. // Prefetch the feedback data.
return this.feedbackProvider.getFeedback(courseId, module.id).then((feedback) => { return this.feedbackProvider.getFeedback(courseId, module.id, siteId, false, true).then((feedback) => {
const p1 = []; let files = (feedback.pageaftersubmitfiles || []).concat(this.getIntroFilesFromInstance(module, feedback));
p1.push(this.getFiles(module, courseId).then((files) => { return this.feedbackProvider.getFeedbackAccessInformation(feedback.id, false, true, siteId).then((accessData) => {
return this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id);
}));
p1.push(this.feedbackProvider.getFeedbackAccessInformation(feedback.id, false, true, siteId).then((accessData) => {
const p2 = []; const p2 = [];
if (accessData.canedititems || accessData.canviewreports) { if (accessData.canedititems || accessData.canviewreports) {
// Get all groups analysis. // Get all groups analysis.
p2.push(this.feedbackProvider.getAnalysis(feedback.id, undefined, siteId)); p2.push(this.feedbackProvider.getAnalysis(feedback.id, undefined, true, siteId));
p2.push(this.groupsProvider.getActivityGroupInfo(feedback.coursemodule, true, undefined, siteId) p2.push(this.groupsProvider.getActivityGroupInfo(feedback.coursemodule, true, undefined, siteId, true)
.then((groupInfo) => { .then((groupInfo) => {
const p3 = [], const p3 = [],
userIds = []; userIds = [];
@ -194,8 +190,8 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
groupInfo.groups = [{id: 0}]; groupInfo.groups = [{id: 0}];
} }
groupInfo.groups.forEach((group) => { groupInfo.groups.forEach((group) => {
p3.push(this.feedbackProvider.getAnalysis(feedback.id, group.id, siteId)); p3.push(this.feedbackProvider.getAnalysis(feedback.id, group.id, true, siteId));
p3.push(this.feedbackProvider.getAllResponsesAnalysis(feedback.id, group.id, siteId) p3.push(this.feedbackProvider.getAllResponsesAnalysis(feedback.id, group.id, true, siteId)
.then((responses) => { .then((responses) => {
responses.attempts.forEach((attempt) => { responses.attempts.forEach((attempt) => {
userIds.push(attempt.userid); userIds.push(attempt.userid);
@ -203,7 +199,7 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
})); }));
if (!accessData.isanonymous) { if (!accessData.isanonymous) {
p3.push(this.feedbackProvider.getAllNonRespondents(feedback.id, group.id, siteId) p3.push(this.feedbackProvider.getAllNonRespondents(feedback.id, group.id, true, siteId)
.then((responses) => { .then((responses) => {
responses.users.forEach((user) => { responses.users.forEach((user) => {
userIds.push(user.userid); userIds.push(user.userid);
@ -219,7 +215,13 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
})); }));
} }
p2.push(this.feedbackProvider.getItems(feedback.id, siteId)); p2.push(this.feedbackProvider.getItems(feedback.id, true, siteId).then((response) => {
response.items.forEach((item) => {
files = files.concat(item.itemfiles);
});
return this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id);
}));
if (accessData.cancomplete && accessData.cansubmit && !accessData.isempty) { if (accessData.cancomplete && accessData.cansubmit && !accessData.isempty) {
// Send empty data, so it will recover last completed feedback attempt values. // Send empty data, so it will recover last completed feedback attempt values.
@ -234,9 +236,7 @@ export class AddonModFeedbackPrefetchHandler extends CoreCourseActivityPrefetchH
} }
return Promise.all(p2); return Promise.all(p2);
})); });
return Promise.all(p1);
}); });
} }
} }

View File

@ -65,7 +65,7 @@ export class AddonModFeedbackShowEntriesLinkHandler extends CoreContentLinksHand
return this.linkHelper.goInSite(navCtrl, 'AddonModFeedbackRespondentsPage', stateParams, siteId); return this.linkHelper.goInSite(navCtrl, 'AddonModFeedbackRespondentsPage', stateParams, siteId);
} }
return this.feedbackProvider.getAttempt(module.instance, params.showcompleted, siteId).then((attempt) => { return this.feedbackProvider.getAttempt(module.instance, params.showcompleted, true, siteId).then((attempt) => {
stateParams = { stateParams = {
moduleId: module.id, moduleId: module.id,
attempt: attempt, attempt: attempt,

View File

@ -15,7 +15,6 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CoreLoggerProvider } from '@providers/logger'; import { CoreLoggerProvider } from '@providers/logger';
import { CoreSitesProvider } from '@providers/sites'; import { CoreSitesProvider } from '@providers/sites';
import { CoreSyncBaseProvider } from '@classes/base-sync';
import { CoreAppProvider } from '@providers/app'; import { CoreAppProvider } from '@providers/app';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
@ -25,14 +24,17 @@ import { AddonModFeedbackProvider } from './feedback';
import { CoreEventsProvider } from '@providers/events'; import { CoreEventsProvider } from '@providers/events';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreSyncProvider } from '@providers/sync'; import { CoreCourseActivitySyncBaseProvider } from '@core/course/classes/activity-sync';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper'; import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { CoreCourseModulePrefetchDelegate } from '@core/course/providers/module-prefetch-delegate';
import { CoreSyncProvider } from '@providers/sync';
import { AddonModFeedbackPrefetchHandler } from './prefetch-handler';
/** /**
* Service to sync feedbacks. * Service to sync feedbacks.
*/ */
@Injectable() @Injectable()
export class AddonModFeedbackSyncProvider extends CoreSyncBaseProvider { export class AddonModFeedbackSyncProvider extends CoreCourseActivitySyncBaseProvider {
static AUTO_SYNCED = 'addon_mod_feedback_autom_synced'; static AUTO_SYNCED = 'addon_mod_feedback_autom_synced';
protected componentTranslate: string; protected componentTranslate: string;
@ -42,9 +44,11 @@ export class AddonModFeedbackSyncProvider extends CoreSyncBaseProvider {
private eventsProvider: CoreEventsProvider, private feedbackProvider: AddonModFeedbackProvider, private eventsProvider: CoreEventsProvider, private feedbackProvider: AddonModFeedbackProvider,
protected translate: TranslateService, private utils: CoreUtilsProvider, protected textUtils: CoreTextUtilsProvider, protected translate: TranslateService, private utils: CoreUtilsProvider, protected textUtils: CoreTextUtilsProvider,
courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider, courseProvider: CoreCourseProvider, syncProvider: CoreSyncProvider, timeUtils: CoreTimeUtilsProvider,
private logHelper: CoreCourseLogHelperProvider) { private logHelper: CoreCourseLogHelperProvider, prefetchDelegate: CoreCourseModulePrefetchDelegate,
prefetchHandler: AddonModFeedbackPrefetchHandler) {
super('AddonModFeedbackSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate, super('AddonModFeedbackSyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
timeUtils); timeUtils, prefetchDelegate, prefetchHandler);
this.componentTranslate = courseProvider.translateModuleName('feedback'); this.componentTranslate = courseProvider.translateModuleName('feedback');
} }
@ -196,7 +200,7 @@ export class AddonModFeedbackSyncProvider extends CoreSyncBaseProvider {
return Promise.all(promises); return Promise.all(promises);
} }
return this.feedbackProvider.getCurrentCompletedTimeModified(feedbackId, siteId).then((timemodified) => { return this.feedbackProvider.getCurrentCompletedTimeModified(feedbackId, true, siteId).then((timemodified) => {
// Sort by page. // Sort by page.
responses.sort((a, b) => { responses.sort((a, b) => {
return a.page - b.page; return a.page - b.page;
@ -216,8 +220,8 @@ export class AddonModFeedbackSyncProvider extends CoreSyncBaseProvider {
}); });
}).then(() => { }).then(() => {
if (result.updated) { if (result.updated) {
// Data has been sent to server. Now invalidate the WS calls. // Data has been sent to server, update data.
return this.feedbackProvider.invalidateAllFeedbackData(feedbackId, siteId).catch(() => { return this.prefetchAfterUpdate(module, courseId, undefined, siteId).catch(() => {
// Ignore errors. // Ignore errors.
}); });
} }

View File

@ -52,7 +52,7 @@ export class CoreCourseActivitySyncBaseProvider extends CoreSyncBaseProvider {
// Get the module updates to check if the data was updated or not. // Get the module updates to check if the data was updated or not.
return this.prefetchDelegate.getModuleUpdates(module, courseId, true, siteId).then((result) => { return this.prefetchDelegate.getModuleUpdates(module, courseId, true, siteId).then((result) => {
if (result && result.updates) { if (result && result.updates && result.updates.length > 0) {
// Only prefetch if files haven't changed. // Only prefetch if files haven't changed.
const fileChanged = !!result.updates.find((entry) => { const fileChanged = !!result.updates.find((entry) => {
return entry.name.match(regex); return entry.name.match(regex);

View File

@ -147,19 +147,22 @@ export class CoreGroupsProvider {
* @param {boolean} [addAllParts=true] Whether to add the all participants option. Always true for visible groups. * @param {boolean} [addAllParts=true] Whether to add the all participants option. Always true for visible groups.
* @param {number} [userId] User ID. If not defined, use current user. * @param {number} [userId] User ID. If not defined, use current user.
* @param {string} [siteId] Site ID. If not defined, current site. * @param {string} [siteId] Site ID. If not defined, current site.
* @param {boolean} [ignoreCache=false] True if it should ignore cached data (it will always fail in offline or server down).
* @return {Promise<CoreGroupInfo>} Promise resolved with the group info. * @return {Promise<CoreGroupInfo>} Promise resolved with the group info.
*/ */
getActivityGroupInfo(cmId: number, addAllParts: boolean = true, userId?: number, siteId?: string): Promise<CoreGroupInfo> { getActivityGroupInfo(cmId: number, addAllParts: boolean = true, userId?: number, siteId?: string, ignoreCache?: boolean)
: Promise<CoreGroupInfo> {
const groupInfo: CoreGroupInfo = { const groupInfo: CoreGroupInfo = {
groups: [] groups: []
}; };
return this.getActivityGroupMode(cmId, siteId).then((groupMode) => { return this.getActivityGroupMode(cmId, siteId, ignoreCache).then((groupMode) => {
groupInfo.separateGroups = groupMode === CoreGroupsProvider.SEPARATEGROUPS; groupInfo.separateGroups = groupMode === CoreGroupsProvider.SEPARATEGROUPS;
groupInfo.visibleGroups = groupMode === CoreGroupsProvider.VISIBLEGROUPS; groupInfo.visibleGroups = groupMode === CoreGroupsProvider.VISIBLEGROUPS;
if (groupInfo.separateGroups || groupInfo.visibleGroups) { if (groupInfo.separateGroups || groupInfo.visibleGroups) {
return this.getActivityAllowedGroups(cmId, userId, siteId); return this.getActivityAllowedGroups(cmId, userId, siteId, ignoreCache);
} }
return []; return [];