MOBILE-3449 assign: Convert some functions to async/await
parent
88ac2e0c5c
commit
d2db79ebea
|
@ -372,7 +372,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
|
||||||
*
|
*
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected loadData(): Promise<any> {
|
protected async loadData(): Promise<any> {
|
||||||
let isBlind = !!this.blindId;
|
let isBlind = !!this.blindId;
|
||||||
|
|
||||||
this.previousAttempt = undefined;
|
this.previousAttempt = undefined;
|
||||||
|
@ -383,44 +383,34 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
|
||||||
isBlind = false;
|
isBlind = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
// Get the assignment.
|
// Get the assignment.
|
||||||
return this.assignProvider.getAssignment(this.courseId, this.moduleId).then((assign) => {
|
this.assign = await this.assignProvider.getAssignment(this.courseId, this.moduleId);
|
||||||
const time = this.timeUtils.timestamp(),
|
|
||||||
promises = [];
|
|
||||||
|
|
||||||
this.assign = assign;
|
const time = this.timeUtils.timestamp();
|
||||||
|
let promises = [];
|
||||||
|
|
||||||
if (assign.allowsubmissionsfromdate && assign.allowsubmissionsfromdate >= time) {
|
if (this.assign.allowsubmissionsfromdate && this.assign.allowsubmissionsfromdate >= time) {
|
||||||
this.fromDate = this.timeUtils.userDate(assign.allowsubmissionsfromdate * 1000);
|
this.fromDate = this.timeUtils.userDate(this.assign.allowsubmissionsfromdate * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.currentAttempt = 0;
|
this.currentAttempt = 0;
|
||||||
this.maxAttemptsText = this.translate.instant('addon.mod_assign.unlimitedattempts');
|
this.maxAttemptsText = this.translate.instant('addon.mod_assign.unlimitedattempts');
|
||||||
this.blindMarking = this.isSubmittedForGrading && assign.blindmarking && !assign.revealidentities;
|
this.blindMarking = this.isSubmittedForGrading && this.assign.blindmarking && !this.assign.revealidentities;
|
||||||
|
|
||||||
if (!this.blindMarking && this.submitId != this.currentUserId) {
|
if (!this.blindMarking && this.submitId != this.currentUserId) {
|
||||||
promises.push(this.userProvider.getProfile(this.submitId, this.courseId).then((profile) => {
|
promises.push(this.loadSubmissionUserProfile());
|
||||||
this.user = profile;
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if there's any offline data for this submission.
|
// Check if there's any offline data for this submission.
|
||||||
promises.push(this.assignOfflineProvider.getSubmission(assign.id, this.submitId).then((data) => {
|
promises.push(this.loadSubmissionOfflineData());
|
||||||
this.hasOffline = data && data.plugindata && Object.keys(data.plugindata).length > 0;
|
|
||||||
this.submittedOffline = data && data.submitted;
|
await Promise.all(promises);
|
||||||
}).catch(() => {
|
|
||||||
// No offline data found.
|
|
||||||
this.hasOffline = false;
|
|
||||||
this.submittedOffline = false;
|
|
||||||
}));
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
}).then(() => {
|
|
||||||
// Get submission status.
|
// Get submission status.
|
||||||
return this.assignProvider.getSubmissionStatusWithRetry(this.assign, this.submitId, undefined, isBlind);
|
const response = await this.assignProvider.getSubmissionStatusWithRetry(this.assign, this.submitId, undefined, isBlind);
|
||||||
}).then((response) => {
|
|
||||||
|
|
||||||
const promises = [];
|
promises = [];
|
||||||
|
|
||||||
this.submissionStatusAvailable = true;
|
this.submissionStatusAvailable = true;
|
||||||
this.lastAttempt = response.lastattempt;
|
this.lastAttempt = response.lastattempt;
|
||||||
|
@ -452,16 +442,41 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the submission plugins that don't support editing.
|
// Get the submission plugins that don't support editing.
|
||||||
promises.push(this.assignProvider.getUnsupportedEditPlugins(this.userSubmission.plugins).then((list) => {
|
promises.push(this.loadUnsupportedPlugins());
|
||||||
this.unsupportedEditPlugins = list;
|
|
||||||
}));
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}).catch((error) => {
|
} catch (error) {
|
||||||
this.domUtils.showErrorModalDefault(error, 'Error getting assigment data.');
|
this.domUtils.showErrorModalDefault(error, 'Error getting assigment data.');
|
||||||
}).finally(() => {
|
} finally {
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
});
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load profile of submission's user.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadSubmissionUserProfile(): Promise<void> {
|
||||||
|
this.user = await this.userProvider.getProfile(this.submitId, this.courseId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load offline data for the submission (not the submission grade).
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadSubmissionOfflineData(): Promise<void> {
|
||||||
|
try {
|
||||||
|
const data = await this.assignOfflineProvider.getSubmission(this.assign.id, this.submitId);
|
||||||
|
|
||||||
|
this.hasOffline = data && data.plugindata && Object.keys(data.plugindata).length > 0;
|
||||||
|
this.submittedOffline = data && data.submitted;
|
||||||
|
} catch (error) {
|
||||||
|
// No offline data found.
|
||||||
|
this.hasOffline = false;
|
||||||
|
this.submittedOffline = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -624,6 +639,15 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the submission plugins that don't support editing.
|
||||||
|
*
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async loadUnsupportedPlugins(): Promise<void> {
|
||||||
|
this.unsupportedEditPlugins = await this.assignProvider.getUnsupportedEditPlugins(this.userSubmission.plugins);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the submission status name and class.
|
* Set the submission status name and class.
|
||||||
*
|
*
|
||||||
|
|
|
@ -26,7 +26,7 @@ import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
||||||
import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
|
import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
|
||||||
import { CoreSyncBaseProvider } from '@classes/base-sync';
|
import { CoreSyncBaseProvider } from '@classes/base-sync';
|
||||||
import { AddonModAssignProvider, AddonModAssignAssign } from './assign';
|
import { AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission } from './assign';
|
||||||
import { AddonModAssignOfflineProvider } from './assign-offline';
|
import { AddonModAssignOfflineProvider } from './assign-offline';
|
||||||
import { AddonModAssignSubmissionDelegate } from './submission-delegate';
|
import { AddonModAssignSubmissionDelegate } from './submission-delegate';
|
||||||
import { AddonModAssignFeedbackDelegate } from './feedback-delegate';
|
import { AddonModAssignFeedbackDelegate } from './feedback-delegate';
|
||||||
|
@ -134,7 +134,7 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @param force Wether to force sync not depending on last execution.
|
* @param force Wether to force sync not depending on last execution.
|
||||||
* @return Promise resolved if sync is successful, rejected if sync fails.
|
* @return Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
syncAllAssignments(siteId?: string, force?: boolean): Promise<any> {
|
syncAllAssignments(siteId?: string, force?: boolean): Promise<void> {
|
||||||
return this.syncOnSites('all assignments', this.syncAllAssignmentsFunc.bind(this), [force], siteId);
|
return this.syncOnSites('all assignments', this.syncAllAssignmentsFunc.bind(this), [force], siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,26 +145,24 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @param force Wether to force sync not depending on last execution.
|
* @param force Wether to force sync not depending on last execution.
|
||||||
* @param Promise resolved if sync is successful, rejected if sync fails.
|
* @param Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
protected syncAllAssignmentsFunc(siteId?: string, force?: boolean): Promise<any> {
|
protected async syncAllAssignmentsFunc(siteId?: string, force?: boolean): Promise<void> {
|
||||||
// Get all assignments that have offline data.
|
// Get all assignments that have offline data.
|
||||||
return this.assignOfflineProvider.getAllAssigns(siteId).then((assignIds) => {
|
const assignIds = await this.assignOfflineProvider.getAllAssigns(siteId);
|
||||||
// Sync all assignments that haven't been synced for a while.
|
|
||||||
const promises = assignIds.map((assignId) => {
|
// Try to sync all assignments.
|
||||||
const promise = force ? this.syncAssign(assignId, siteId) : this.syncAssignIfNeeded(assignId, siteId);
|
await Promise.all(assignIds.map(async (assignId) => {
|
||||||
|
const data = force ? await this.syncAssign(assignId, siteId) : await this.syncAssignIfNeeded(assignId, siteId);
|
||||||
|
|
||||||
|
if (!data || !data.updated) {
|
||||||
|
// Not updated.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
return promise.then((data) => {
|
|
||||||
if (data && data.updated) {
|
|
||||||
// Sync done. Send event.
|
|
||||||
this.eventsProvider.trigger(AddonModAssignSyncProvider.AUTO_SYNCED, {
|
this.eventsProvider.trigger(AddonModAssignSyncProvider.AUTO_SYNCED, {
|
||||||
assignId: assignId,
|
assignId: assignId,
|
||||||
warnings: data.warnings
|
warnings: data.warnings,
|
||||||
}, siteId);
|
}, siteId);
|
||||||
}
|
}));
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,12 +172,12 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved when the assign is synced or it doesn't need to be synced.
|
* @return Promise resolved when the assign is synced or it doesn't need to be synced.
|
||||||
*/
|
*/
|
||||||
syncAssignIfNeeded(assignId: number, siteId?: string): Promise<void | AddonModAssignSyncResult> {
|
async syncAssignIfNeeded(assignId: number, siteId?: string): Promise<void | AddonModAssignSyncResult> {
|
||||||
return this.isSyncNeeded(assignId, siteId).then((needed) => {
|
const needed = await this.isSyncNeeded(assignId, siteId);
|
||||||
|
|
||||||
if (needed) {
|
if (needed) {
|
||||||
return this.syncAssign(assignId, siteId);
|
return this.syncAssign(assignId, siteId);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,18 +187,9 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved in success.
|
* @return Promise resolved in success.
|
||||||
*/
|
*/
|
||||||
syncAssign(assignId: number, siteId?: string): Promise<AddonModAssignSyncResult> {
|
async syncAssign(assignId: number, siteId?: string): Promise<AddonModAssignSyncResult> {
|
||||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
const promises: Promise<any>[] = [],
|
|
||||||
result: AddonModAssignSyncResult = {
|
|
||||||
warnings: [],
|
|
||||||
updated: false
|
|
||||||
};
|
|
||||||
let assign: AddonModAssignAssign,
|
|
||||||
courseId: number,
|
|
||||||
syncPromise: Promise<any>;
|
|
||||||
|
|
||||||
if (this.isSyncing(assignId, siteId)) {
|
if (this.isSyncing(assignId, siteId)) {
|
||||||
// There's already a sync ongoing for this assign, return the promise.
|
// There's already a sync ongoing for this assign, return the promise.
|
||||||
return this.getOngoingSync(assignId, siteId);
|
return this.getOngoingSync(assignId, siteId);
|
||||||
|
@ -208,79 +197,116 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
|
|
||||||
// Verify that assign isn't blocked.
|
// Verify that assign isn't blocked.
|
||||||
if (this.syncProvider.isBlocked(AddonModAssignProvider.COMPONENT, assignId, siteId)) {
|
if (this.syncProvider.isBlocked(AddonModAssignProvider.COMPONENT, assignId, siteId)) {
|
||||||
this.logger.debug('Cannot sync assign ' + assignId + ' because it is blocked.');
|
this.logger.error('Cannot sync assign ' + assignId + ' because it is blocked.');
|
||||||
|
|
||||||
return Promise.reject(this.translate.instant('core.errorsyncblocked', {$a: this.componentTranslate}));
|
throw new Error(this.translate.instant('core.errorsyncblocked', {$a: this.componentTranslate}));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.debug('Try to sync assign ' + assignId + ' in site ' + siteId);
|
return this.addOngoingSync(assignId, this.performSyncAssign(assignId, siteId), siteId);
|
||||||
|
}
|
||||||
|
|
||||||
// Get offline submissions to be sent.
|
/**
|
||||||
promises.push(this.assignOfflineProvider.getAssignSubmissions(assignId, siteId).catch(() => {
|
* Perform the assign submission.
|
||||||
// No offline data found, return empty array.
|
*
|
||||||
return [];
|
* @param assignId Assign ID.
|
||||||
}));
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise resolved in success.
|
||||||
|
*/
|
||||||
|
protected async performSyncAssign(assignId: number, siteId?: string): Promise<AddonModAssignSyncResult> {
|
||||||
|
|
||||||
// Get offline submission grades to be sent.
|
this.logger.error('Try to sync assign ' + assignId + ' in site ' + siteId);
|
||||||
promises.push(this.assignOfflineProvider.getAssignSubmissionsGrade(assignId, siteId).catch(() => {
|
|
||||||
// No offline data found, return empty array.
|
|
||||||
return [];
|
|
||||||
}));
|
|
||||||
|
|
||||||
// Sync offline logs.
|
const result: AddonModAssignSyncResult = {
|
||||||
promises.push(this.logHelper.syncIfNeeded(AddonModAssignProvider.COMPONENT, assignId, siteId));
|
warnings: [],
|
||||||
|
updated: false,
|
||||||
|
};
|
||||||
|
|
||||||
syncPromise = Promise.all(promises).then((results) => {
|
// Load offline data and sync offline logs.
|
||||||
const submissions = results[0],
|
const promisesResults = await Promise.all([
|
||||||
grades = results[1];
|
this.getOfflineSubmissions(assignId, siteId),
|
||||||
|
this.getOfflineGrades(assignId, siteId),
|
||||||
|
this.logHelper.syncIfNeeded(AddonModAssignProvider.COMPONENT, assignId, siteId),
|
||||||
|
]);
|
||||||
|
|
||||||
|
const submissions = promisesResults[0];
|
||||||
|
const grades = promisesResults[1];
|
||||||
|
|
||||||
if (!submissions.length && !grades.length) {
|
if (!submissions.length && !grades.length) {
|
||||||
// Nothing to sync.
|
// Nothing to sync.
|
||||||
return;
|
await this.utils.ignoreErrors(this.setSyncTime(assignId, siteId));
|
||||||
|
|
||||||
|
return result;
|
||||||
} else if (!this.appProvider.isOnline()) {
|
} else if (!this.appProvider.isOnline()) {
|
||||||
// Cannot sync in offline.
|
// Cannot sync in offline.
|
||||||
return Promise.reject(null);
|
throw new Error(this.translate.instant('core.cannotconnect'));
|
||||||
}
|
}
|
||||||
|
|
||||||
courseId = submissions.length > 0 ? submissions[0].courseid : grades[0].courseid;
|
const courseId = submissions.length > 0 ? submissions[0].courseid : grades[0].courseid;
|
||||||
|
|
||||||
return this.assignProvider.getAssignmentById(courseId, assignId, false, siteId).then((assignData) => {
|
const assign = await this.assignProvider.getAssignmentById(courseId, assignId, false, siteId);
|
||||||
assign = assignData;
|
|
||||||
|
|
||||||
const promises = [];
|
let promises = [];
|
||||||
|
|
||||||
|
promises = promises.concat(submissions.map(async (submission) => {
|
||||||
|
await this.syncSubmission(assign, submission, result.warnings, siteId);
|
||||||
|
|
||||||
submissions.forEach((submission) => {
|
|
||||||
promises.push(this.syncSubmission(assign, submission, result.warnings, siteId).then(() => {
|
|
||||||
result.updated = true;
|
result.updated = true;
|
||||||
}));
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
grades.forEach((grade) => {
|
promises = promises.concat(grades.map(async (grade) => {
|
||||||
promises.push(this.syncSubmissionGrade(assign, grade, result.warnings, courseId, siteId).then(() => {
|
await this.syncSubmissionGrade(assign, grade, result.warnings, courseId, siteId);
|
||||||
|
|
||||||
result.updated = true;
|
result.updated = true;
|
||||||
}));
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}).then(() => {
|
|
||||||
if (result.updated) {
|
if (result.updated) {
|
||||||
// Data has been sent to server. Now invalidate the WS calls.
|
// Data has been sent to server. Now invalidate the WS calls.
|
||||||
return this.assignProvider.invalidateContent(assign.cmid, courseId, siteId).catch(() => {
|
await this.utils.ignoreErrors(this.assignProvider.invalidateContent(assign.cmid, courseId, siteId));
|
||||||
// Ignore errors.
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
// Sync finished, set sync time.
|
// Sync finished, set sync time.
|
||||||
return this.setSyncTime(assignId, siteId).catch(() => {
|
await this.utils.ignoreErrors(this.setSyncTime(assignId, siteId));
|
||||||
// Ignore errors.
|
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
// All done, return the result.
|
// All done, return the result.
|
||||||
return result;
|
return result;
|
||||||
});
|
}
|
||||||
|
|
||||||
return this.addOngoingSync(assignId, syncPromise, siteId);
|
/**
|
||||||
|
* Get offline grades to be sent.
|
||||||
|
*
|
||||||
|
* @param assignId Assign ID.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise with grades.
|
||||||
|
*/
|
||||||
|
protected async getOfflineGrades(assignId: number, siteId: string): Promise<any[]> {
|
||||||
|
try {
|
||||||
|
const submissions = await this.assignOfflineProvider.getAssignSubmissionsGrade(assignId, siteId);
|
||||||
|
|
||||||
|
return submissions;
|
||||||
|
} catch (error) {
|
||||||
|
// No offline data found, return empty array.
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get offline submissions to be sent.
|
||||||
|
*
|
||||||
|
* @param assignId Assign ID.
|
||||||
|
* @param siteId Site ID. If not defined, current site.
|
||||||
|
* @return Promise with submissions.
|
||||||
|
*/
|
||||||
|
protected async getOfflineSubmissions(assignId: number, siteId: string): Promise<any[]> {
|
||||||
|
try {
|
||||||
|
const submissions = await this.assignOfflineProvider.getAssignSubmissions(assignId, siteId);
|
||||||
|
|
||||||
|
return submissions;
|
||||||
|
} catch (error) {
|
||||||
|
// No offline data found, return empty array.
|
||||||
|
return [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -292,83 +318,76 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved if success, rejected otherwise.
|
* @return Promise resolved if success, rejected otherwise.
|
||||||
*/
|
*/
|
||||||
protected syncSubmission(assign: AddonModAssignAssign, offlineData: any, warnings: string[], siteId?: string): Promise<any> {
|
protected async syncSubmission(assign: AddonModAssignAssign, offlineData: any, warnings: string[], siteId?: string)
|
||||||
const userId = offlineData.userid,
|
: Promise<void> {
|
||||||
pluginData = {};
|
|
||||||
let discardError,
|
|
||||||
submission;
|
|
||||||
|
|
||||||
return this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId).then((status) => {
|
const userId = offlineData.userid;
|
||||||
const promises = [];
|
const pluginData = {};
|
||||||
|
|
||||||
submission = this.assignProvider.getSubmissionObjectFromAttempt(assign, status.lastattempt);
|
const status = await this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId);
|
||||||
|
|
||||||
|
const submission = this.assignProvider.getSubmissionObjectFromAttempt(assign, status.lastattempt);
|
||||||
|
|
||||||
if (submission.timemodified != offlineData.onlinetimemodified) {
|
if (submission.timemodified != offlineData.onlinetimemodified) {
|
||||||
// The submission was modified in Moodle, discard the submission.
|
// The submission was modified in Moodle, discard the submission.
|
||||||
discardError = this.translate.instant('addon.mod_assign.warningsubmissionmodified');
|
this.addOfflineDataDeletedWarning(warnings, this.componentTranslate, assign.name,
|
||||||
|
this.translate.instant('addon.mod_assign.warningsubmissionmodified'));
|
||||||
|
|
||||||
return;
|
return this.deleteSubmissionData(assign, submission, offlineData, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
submission.plugins.forEach((plugin) => {
|
try {
|
||||||
promises.push(this.submissionDelegate.preparePluginSyncData(assign, submission, plugin, offlineData, pluginData,
|
// Prepare plugins data.
|
||||||
siteId));
|
await Promise.all(submission.plugins.map(async (plugin) => {
|
||||||
});
|
await this.submissionDelegate.preparePluginSyncData(assign, submission, plugin, offlineData, pluginData, siteId);
|
||||||
|
}));
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
|
||||||
// Now save the submission.
|
// Now save the submission.
|
||||||
let promise;
|
if (Object.keys(pluginData).length > 0) {
|
||||||
|
await this.assignProvider.saveSubmissionOnline(assign.id, pluginData, siteId);
|
||||||
if (!Object.keys(pluginData).length) {
|
|
||||||
// Nothing to save.
|
|
||||||
promise = Promise.resolve();
|
|
||||||
} else {
|
|
||||||
promise = this.assignProvider.saveSubmissionOnline(assign.id, pluginData, siteId);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then(() => {
|
|
||||||
if (assign.submissiondrafts && offlineData.submitted) {
|
if (assign.submissiondrafts && offlineData.submitted) {
|
||||||
// The user submitted the assign manually. Submit it for grading.
|
// The user submitted the assign manually. Submit it for grading.
|
||||||
return this.assignProvider.submitForGradingOnline(assign.id, offlineData.submissionstatement, siteId);
|
await this.assignProvider.submitForGradingOnline(assign.id, offlineData.submissionstatement, siteId);
|
||||||
}
|
}
|
||||||
}).then(() => {
|
|
||||||
// Submission data sent, update cached data. No need to block the user for this.
|
// Submission data sent, update cached data. No need to block the user for this.
|
||||||
this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId);
|
this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId);
|
||||||
});
|
} catch (error) {
|
||||||
}).catch((error) => {
|
if (!error || !this.utils.isWebServiceError(error)) {
|
||||||
if (error && this.utils.isWebServiceError(error)) {
|
// Local error, reject.
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
// A WebService has thrown an error, this means it cannot be submitted. Discard the submission.
|
// A WebService has thrown an error, this means it cannot be submitted. Discard the submission.
|
||||||
discardError = this.textUtils.getErrorMessageFromError(error);
|
this.addOfflineDataDeletedWarning(warnings, this.componentTranslate, assign.name,
|
||||||
} else {
|
this.textUtils.getErrorMessageFromError(error));
|
||||||
// Couldn't connect to server, reject.
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
// Delete the offline data.
|
// Delete the offline data.
|
||||||
return this.assignOfflineProvider.deleteSubmission(assign.id, userId, siteId).then(() => {
|
await this.deleteSubmissionData(assign, submission, offlineData, siteId);
|
||||||
const promises = [];
|
|
||||||
|
|
||||||
submission.plugins.forEach((plugin) => {
|
|
||||||
promises.push(this.submissionDelegate.deletePluginOfflineData(assign, submission, plugin, offlineData, siteId));
|
|
||||||
});
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
if (discardError) {
|
|
||||||
// Submission was discarded, add a warning.
|
|
||||||
const message = this.translate.instant('core.warningofflinedatadeleted', {
|
|
||||||
component: this.componentTranslate,
|
|
||||||
name: assign.name,
|
|
||||||
error: discardError
|
|
||||||
});
|
|
||||||
|
|
||||||
if (warnings.indexOf(message) == -1) {
|
|
||||||
warnings.push(message);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
/**
|
||||||
|
* Delete the submission offline data (not grades).
|
||||||
|
*
|
||||||
|
* @param assign Assign.
|
||||||
|
* @param submission Submission.
|
||||||
|
* @param offlineData Offline data.
|
||||||
|
* @param siteId Site ID.
|
||||||
|
* @return Promise resolved when done.
|
||||||
|
*/
|
||||||
|
protected async deleteSubmissionData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, offlineData: any,
|
||||||
|
siteId?: string): Promise<void> {
|
||||||
|
|
||||||
|
// Delete the offline data.
|
||||||
|
await this.assignOfflineProvider.deleteSubmission(assign.id, offlineData.userid, siteId);
|
||||||
|
|
||||||
|
// Delete plugins data.
|
||||||
|
await Promise.all(submission.plugins.map(async (plugin) => {
|
||||||
|
await this.submissionDelegate.deletePluginOfflineData(assign, submission, plugin, offlineData, siteId);
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -381,34 +400,36 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return Promise resolved if success, rejected otherwise.
|
* @return Promise resolved if success, rejected otherwise.
|
||||||
*/
|
*/
|
||||||
protected syncSubmissionGrade(assign: AddonModAssignAssign, offlineData: any, warnings: string[], courseId: number,
|
protected async syncSubmissionGrade(assign: AddonModAssignAssign, offlineData: any, warnings: string[], courseId: number,
|
||||||
siteId?: string): Promise<any> {
|
siteId?: string): Promise<any> {
|
||||||
|
|
||||||
const userId = offlineData.userid;
|
const userId = offlineData.userid;
|
||||||
let discardError;
|
|
||||||
const syncId = this.getGradeSyncId(assign.id, userId);
|
const syncId = this.getGradeSyncId(assign.id, userId);
|
||||||
|
|
||||||
// Check if this grade sync is blocked.
|
// Check if this grade sync is blocked.
|
||||||
if (this.syncProvider.isBlocked(AddonModAssignProvider.COMPONENT, syncId, siteId)) {
|
if (this.syncProvider.isBlocked(AddonModAssignProvider.COMPONENT, syncId, siteId)) {
|
||||||
this.logger.error(`Cannot sync grade for assign ${assign.id} and user ${userId} because it is blocked.`);
|
this.logger.error(`Cannot sync grade for assign ${assign.id} and user ${userId} because it is blocked.`);
|
||||||
|
|
||||||
return Promise.reject(new Error(this.translate.instant('core.errorsyncblocked',
|
throw new Error(this.translate.instant('core.errorsyncblocked',
|
||||||
{$a: this.translate.instant('addon.mod_assign.syncblockedusercomponent')})));
|
{$a: this.translate.instant('addon.mod_assign.syncblockedusercomponent')}));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId).then((status) => {
|
const status = await this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId);
|
||||||
|
|
||||||
const timemodified = status.feedback && (status.feedback.gradeddate || status.feedback.grade.timemodified);
|
const timemodified = status.feedback && (status.feedback.gradeddate || status.feedback.grade.timemodified);
|
||||||
|
|
||||||
if (timemodified > offlineData.timemodified) {
|
if (timemodified > offlineData.timemodified) {
|
||||||
// The submission grade was modified in Moodle, discard it.
|
// The submission grade was modified in Moodle, discard it.
|
||||||
discardError = this.translate.instant('addon.mod_assign.warningsubmissiongrademodified');
|
this.addOfflineDataDeletedWarning(warnings, this.componentTranslate, assign.name,
|
||||||
|
this.translate.instant('addon.mod_assign.warningsubmissiongrademodified'));
|
||||||
|
|
||||||
return;
|
return this.assignOfflineProvider.deleteSubmissionGrade(assign.id, userId, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If grade has been modified from gradebook, do not use offline.
|
// If grade has been modified from gradebook, do not use offline.
|
||||||
return this.gradesHelper.getGradeModuleItems(courseId, assign.cmid, userId, undefined, siteId, true).then((grades) => {
|
const grades = await this.gradesHelper.getGradeModuleItems(courseId, assign.cmid, userId, undefined, siteId, true);
|
||||||
return this.courseProvider.getModuleBasicGradeInfo(assign.cmid, siteId).then((gradeInfo) => {
|
|
||||||
|
const gradeInfo = await this.courseProvider.getModuleBasicGradeInfo(assign.cmid, siteId);
|
||||||
|
|
||||||
// Override offline grade and outcomes based on the gradebook data.
|
// Override offline grade and outcomes based on the gradebook data.
|
||||||
grades.forEach((grade) => {
|
grades.forEach((grade) => {
|
||||||
|
@ -429,14 +450,14 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
|
||||||
}).then(() => {
|
try {
|
||||||
// Now submit the grade.
|
// Now submit the grade.
|
||||||
return this.assignProvider.submitGradingFormOnline(assign.id, userId, offlineData.grade, offlineData.attemptnumber,
|
await this.assignProvider.submitGradingFormOnline(assign.id, userId, offlineData.grade, offlineData.attemptnumber,
|
||||||
offlineData.addattempt, offlineData.workflowstate, offlineData.applytoall, offlineData.outcomes,
|
offlineData.addattempt, offlineData.workflowstate, offlineData.applytoall, offlineData.outcomes,
|
||||||
offlineData.plugindata, siteId).then(() => {
|
offlineData.plugindata, siteId);
|
||||||
// Grades sent.
|
|
||||||
// Discard grades drafts.
|
// Grades sent. Discard grades drafts.
|
||||||
const promises = [];
|
const promises = [];
|
||||||
if (status.feedback && status.feedback.plugins) {
|
if (status.feedback && status.feedback.plugins) {
|
||||||
status.feedback.plugins.forEach((plugin) => {
|
status.feedback.plugins.forEach((plugin) => {
|
||||||
|
@ -447,34 +468,20 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
|
||||||
// Update cached data.
|
// Update cached data.
|
||||||
promises.push(this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId));
|
promises.push(this.assignProvider.getSubmissionStatus(assign.id, userId, undefined, false, true, true, siteId));
|
||||||
|
|
||||||
return Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}).catch((error) => {
|
} catch (error) {
|
||||||
if (error && this.utils.isWebServiceError(error)) {
|
if (!error || !this.utils.isWebServiceError(error)) {
|
||||||
// The WebService has thrown an error, this means it cannot be submitted. Discard the offline data.
|
// Local error, reject.
|
||||||
discardError = this.textUtils.getErrorMessageFromError(error);
|
throw error;
|
||||||
} else {
|
|
||||||
// Couldn't connect to server, reject.
|
|
||||||
return Promise.reject(error);
|
|
||||||
}
|
}
|
||||||
});
|
|
||||||
});
|
|
||||||
}).then(() => {
|
|
||||||
// Delete the offline data.
|
|
||||||
return this.assignOfflineProvider.deleteSubmissionGrade(assign.id, userId, siteId);
|
|
||||||
}).then(() => {
|
|
||||||
if (discardError) {
|
|
||||||
// Submission grade was discarded, add a warning.
|
|
||||||
const message = this.translate.instant('core.warningofflinedatadeleted', {
|
|
||||||
component: this.componentTranslate,
|
|
||||||
name: assign.name,
|
|
||||||
error: discardError
|
|
||||||
});
|
|
||||||
|
|
||||||
if (warnings.indexOf(message) == -1) {
|
// A WebService has thrown an error, this means it cannot be submitted. Discard the submission.
|
||||||
warnings.push(message);
|
this.addOfflineDataDeletedWarning(warnings, this.componentTranslate, assign.name,
|
||||||
|
this.textUtils.getErrorMessageFromError(error));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
});
|
// Delete the offline data.
|
||||||
|
await this.assignOfflineProvider.deleteSubmissionGrade(assign.id, userId, siteId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -52,6 +52,26 @@ export class CoreSyncBaseProvider {
|
||||||
this.component = component;
|
this.component = component;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add an offline data deleted warning to a list of warnings.
|
||||||
|
*
|
||||||
|
* @param warnings List of warnings.
|
||||||
|
* @param component Component.
|
||||||
|
* @param name Instance name.
|
||||||
|
* @param error Specific error message.
|
||||||
|
*/
|
||||||
|
protected addOfflineDataDeletedWarning(warnings: string[], component: string, name: string, error: string): void {
|
||||||
|
const warning = this.translate.instant('core.warningofflinedatadeleted', {
|
||||||
|
component: component,
|
||||||
|
name: name,
|
||||||
|
error: error,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (warnings.indexOf(warning) == -1) {
|
||||||
|
warnings.push(warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add an ongoing sync to the syncPromises list. On finish the promise will be removed.
|
* Add an ongoing sync to the syncPromises list. On finish the promise will be removed.
|
||||||
*
|
*
|
||||||
|
@ -60,7 +80,7 @@ export class CoreSyncBaseProvider {
|
||||||
* @param siteId Site ID. If not defined, current site.
|
* @param siteId Site ID. If not defined, current site.
|
||||||
* @return The sync promise.
|
* @return The sync promise.
|
||||||
*/
|
*/
|
||||||
addOngoingSync(id: string | number, promise: Promise<any>, siteId?: string): Promise<any> {
|
addOngoingSync<T>(id: string | number, promise: Promise<T>, siteId?: string): Promise<T> {
|
||||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
const uniqueId = this.getUniqueSyncId(id);
|
const uniqueId = this.getUniqueSyncId(id);
|
||||||
|
|
Loading…
Reference in New Issue