MOBILE-3109 assign: Add return types to assign

main
Dani Palou 2019-09-06 09:25:30 +02:00
parent 346c8a42ff
commit 7fc1c96b03
26 changed files with 728 additions and 239 deletions

View File

@ -15,6 +15,7 @@
import { Injector } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { AddonModAssignFeedbackHandler } from '../providers/feedback-delegate';
import { AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin } from '../providers/assign';
/**
* Base handler for feedback plugins.
@ -48,7 +49,7 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param plugin The plugin object.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin): any | Promise<any> {
// Nothing to do.
}
@ -74,7 +75,8 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return [];
}
@ -84,7 +86,7 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param plugin The plugin object.
* @return The plugin name.
*/
getPluginName(plugin: any): string {
getPluginName(plugin: AddonModAssignPlugin): string {
// Check if there's a translated string for the plugin.
const translationId = 'addon.mod_assign_feedback_' + plugin.type + '.pluginname',
translation = this.translate.instant(translationId);
@ -109,7 +111,8 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param inputData Data entered by the user for the feedback.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged(assign: any, submission: any, plugin: any, inputData: any): boolean | Promise<boolean> {
hasDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, userId: number): boolean | Promise<boolean> {
return false;
}
@ -144,7 +147,8 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise<any> {
prefetch(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any> {
return Promise.resolve();
}
@ -158,7 +162,8 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareFeedbackData(assignId: number, userId: number, plugin: any, pluginData: any, siteId?: string): void | Promise<any> {
prepareFeedbackData(assignId: number, userId: number, plugin: AddonModAssignPlugin, pluginData: any,
siteId?: string): void | Promise<any> {
// Nothing to do.
}
@ -172,7 +177,8 @@ export class AddonModAssignBaseFeedbackHandler implements AddonModAssignFeedback
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
saveDraft(assignId: number, userId: number, plugin: any, data: any, siteId?: string): void | Promise<any> {
saveDraft(assignId: number, userId: number, plugin: AddonModAssignPlugin, data: any, siteId?: string)
: void | Promise<any> {
// Nothing to do.
}
}

View File

@ -15,6 +15,7 @@
import { Injector } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import { AddonModAssignSubmissionHandler } from '../providers/submission-delegate';
import { AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin } from '../providers/assign';
/**
* Base handler for submission plugins.
@ -38,7 +39,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @return Boolean or promise resolved with boolean: whether it can be edited in offline.
*/
canEditOffline(assign: any, submission: any, plugin: any): boolean | Promise<boolean> {
canEditOffline(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin): boolean | Promise<boolean> {
return false;
}
@ -50,7 +52,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @param inputData Data entered by the user for the submission.
*/
clearTmpData(assign: any, submission: any, plugin: any, inputData: any): void {
clearTmpData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): void {
// Nothing to do.
}
@ -65,7 +68,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
copySubmissionData(assign: any, plugin: any, pluginData: any, userId?: number, siteId?: string): void | Promise<any> {
copySubmissionData(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin, pluginData: any,
userId?: number, siteId?: string): void | Promise<any> {
// Nothing to do.
}
@ -79,7 +83,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
deleteOfflineData(assign: any, submission: any, plugin: any, offlineData: any, siteId?: string): void | Promise<any> {
deleteOfflineData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, siteId?: string): void | Promise<any> {
// Nothing to do.
}
@ -92,7 +97,7 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param edit Whether the user is editing.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin, edit?: boolean): any | Promise<any> {
// Nothing to do.
}
@ -106,7 +111,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return [];
}
@ -116,7 +122,7 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @return The plugin name.
*/
getPluginName(plugin: any): string {
getPluginName(plugin: AddonModAssignPlugin): string {
// Check if there's a translated string for the plugin.
const translationId = 'addon.mod_assign_submission_' + plugin.type + '.pluginname',
translation = this.translate.instant(translationId);
@ -139,7 +145,7 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @return The size (or promise resolved with size).
*/
getSizeForCopy(assign: any, plugin: any): number | Promise<number> {
getSizeForCopy(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin): number | Promise<number> {
return 0;
}
@ -147,10 +153,12 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* Get the size of data (in bytes) this plugin will send to add or edit a submission.
*
* @param assign The assignment.
* @param submission The submission.
* @param plugin The plugin object.
* @return The size (or promise resolved with size).
*/
getSizeForEdit(assign: any, plugin: any): number | Promise<number> {
getSizeForEdit(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): number | Promise<number> {
return 0;
}
@ -163,7 +171,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param inputData Data entered by the user for the submission.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged(assign: any, submission: any, plugin: any, inputData: any): boolean | Promise<boolean> {
hasDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): boolean | Promise<boolean> {
return false;
}
@ -194,7 +203,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise<any> {
prefetch?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any> {
return Promise.resolve();
}
@ -211,7 +221,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSubmissionData?(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean,
prepareSubmissionData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): void | Promise<any> {
// Nothing to do.
}
@ -228,8 +239,8 @@ export class AddonModAssignBaseSubmissionHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSyncData?(assign: any, submission: any, plugin: any, offlineData: any, pluginData: any, siteId?: string)
: void | Promise<any> {
prepareSyncData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, pluginData: any, siteId?: string): void | Promise<any> {
// Nothing to do.
}
}

View File

@ -14,14 +14,15 @@
import { Input } from '@angular/core';
import { ModalController } from 'ionic-angular';
import { AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin } from '../providers/assign';
/**
* Base class for component to render a feedback plugin.
*/
export class AddonModAssignFeedbackPluginComponentBase {
@Input() assign: any; // The assignment.
@Input() submission: any; // The submission.
@Input() plugin: any; // The plugin object.
@Input() assign: AddonModAssignAssign; // The assignment.
@Input() submission: AddonModAssignSubmission; // The submission.
@Input() plugin: AddonModAssignPlugin; // The plugin object.
@Input() userId: number; // The user ID of the submission.
@Input() configs: any; // The configs for the plugin.
@Input() canEdit: boolean; // Whether the user can edit.

View File

@ -13,15 +13,16 @@
// limitations under the License.
import { Input } from '@angular/core';
import { AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin } from '../providers/assign';
/**
* Base class for component to render a submission plugin.
*/
export class AddonModAssignSubmissionPluginComponent {
@Input() assign: any; // The assignment.
@Input() submission: any; // The submission.
@Input() plugin: any; // The plugin object.
@Input() configs: any; // The configs for the plugin.
@Input() assign: AddonModAssignAssign; // The assignment.
@Input() submission: AddonModAssignSubmission; // The submission.
@Input() plugin: AddonModAssignPlugin; // The plugin object.
@Input() configs: {[name: string]: string}; // The configs for the plugin.
@Input() edit: boolean; // Whether the user is editing.
@Input() allowOffline: boolean; // Whether to allow offline.

View File

@ -13,7 +13,9 @@
// limitations under the License.
import { Component, Input, OnInit, Injector, ViewChild } from '@angular/core';
import { AddonModAssignProvider } from '../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../providers/assign';
import { AddonModAssignHelperProvider } from '../../providers/helper';
import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate';
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
@ -28,9 +30,9 @@ import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-comp
export class AddonModAssignFeedbackPluginComponent implements OnInit {
@ViewChild(CoreDynamicComponent) dynamicComponent: CoreDynamicComponent;
@Input() assign: any; // The assignment.
@Input() submission: any; // The submission.
@Input() plugin: any; // The plugin object.
@Input() assign: AddonModAssignAssign; // The assignment.
@Input() submission: AddonModAssignSubmission; // The submission.
@Input() plugin: AddonModAssignPlugin; // The plugin object.
@Input() userId: number; // The user ID of the submission.
@Input() canEdit: boolean | string; // Whether the user can edit.
@Input() edit: boolean | string; // Whether the user is editing.

View File

@ -17,7 +17,7 @@ import { Content, NavController } from 'ionic-angular';
import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups';
import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
import { AddonModAssignProvider } from '../../providers/assign';
import { AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmissionGradingSummary } from '../../providers/assign';
import { AddonModAssignHelperProvider } from '../../providers/helper';
import { AddonModAssignOfflineProvider } from '../../providers/assign-offline';
import { AddonModAssignSyncProvider } from '../../providers/assign-sync';
@ -36,13 +36,13 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
component = AddonModAssignProvider.COMPONENT;
moduleName = 'assign';
assign: any; // The assign object.
assign: AddonModAssignAssign; // The assign object.
canViewAllSubmissions: boolean; // Whether the user can view all submissions.
canViewOwnSubmission: boolean; // Whether the user can view their own submission.
timeRemaining: string; // Message about time remaining to submit.
lateSubmissions: string; // Message about late submissions.
showNumbers = true; // Whether to show number of submissions with each status.
summary: any; // The summary.
summary: AddonModAssignSubmissionGradingSummary; // The grading summary.
needsGradingAvalaible: boolean; // Whether we can see the submissions that need grading.
groupInfo: CoreGroupInfo = {
@ -153,7 +153,7 @@ export class AddonModAssignIndexComponent extends CoreCourseModuleMainActivityCo
this.assign = assignData;
this.dataRetrieved.emit(this.assign);
this.description = this.assign.intro || this.description;
this.description = this.assign.intro;
if (sync) {
// Try to synchronize the assign.

View File

@ -13,7 +13,9 @@
// limitations under the License.
import { Component, Input, OnInit, Injector, ViewChild } from '@angular/core';
import { AddonModAssignProvider } from '../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../providers/assign';
import { AddonModAssignHelperProvider } from '../../providers/helper';
import { AddonModAssignSubmissionDelegate } from '../../providers/submission-delegate';
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
@ -28,9 +30,9 @@ import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-comp
export class AddonModAssignSubmissionPluginComponent implements OnInit {
@ViewChild(CoreDynamicComponent) dynamicComponent: CoreDynamicComponent;
@Input() assign: any; // The assignment.
@Input() submission: any; // The submission.
@Input() plugin: any; // The plugin object.
@Input() assign: AddonModAssignAssign; // The assignment.
@Input() submission: AddonModAssignSubmission; // The submission.
@Input() plugin: AddonModAssignPlugin; // The plugin object.
@Input() edit: boolean | string; // Whether the user is editing.
@Input() allowOffline: boolean | string; // Whether to allow offline.

View File

@ -29,7 +29,10 @@ import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreFileUploaderHelperProvider } from '@core/fileuploader/providers/helper';
import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
import { CoreUserProvider } from '@core/user/providers/user';
import { AddonModAssignProvider } from '../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmissionFeedback, AddonModAssignSubmission,
AddonModAssignSubmissionAttempt, AddonModAssignSubmissionPreviousAttempt, AddonModAssignPlugin
} from '../../providers/assign';
import { AddonModAssignHelperProvider } from '../../providers/helper';
import { AddonModAssignOfflineProvider } from '../../providers/assign-offline';
import { CoreTabsComponent } from '@components/tabs/tabs';
@ -55,11 +58,11 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
loaded: boolean; // Whether data has been loaded.
selectedTab: number; // Tab selected on start.
assign: any; // The assignment the submission belongs to.
userSubmission: any; // The submission object.
assign: AddonModAssignAssign; // The assignment the submission belongs to.
userSubmission: AddonModAssignSubmission; // The submission object.
isSubmittedForGrading: boolean; // Whether the submission has been submitted for grading.
submitModel: any = {}; // Model where to store the data to submit (for grading).
feedback: any; // The feedback.
feedback: AddonModAssignSubmissionFeedbackFormatted; // The feedback.
hasOffline: boolean; // Whether there is offline data.
submittedOffline: boolean; // Whether it was submitted in offline.
fromDate: string; // Readable date when the assign started accepting submissions.
@ -67,7 +70,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
maxAttemptsText: string; // The text for maximum attempts.
blindMarking: boolean; // Whether blind marking is enabled.
user: any; // The user.
lastAttempt: any; // The last attempt.
lastAttempt: AddonModAssignSubmissionAttemptFormatted; // The last attempt.
membersToSubmit: any[]; // Team members that need to submit the assignment.
canSubmit: boolean; // Whether the user can submit for grading.
canEdit: boolean; // Whether the user can edit the submission.
@ -77,7 +80,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
gradingStatusTranslationId: string; // Key of the text to display for the grading status.
gradingColor: string; // Color to apply to the grading status.
workflowStatusTranslationId: string; // Key of the text to display for the workflow status.
submissionPlugins: string[]; // List of submission plugins names.
submissionPlugins: AddonModAssignPlugin[]; // List of submission plugins.
timeRemaining: string; // Message about time remaining.
timeRemainingClass: string; // Class to apply to time remaining message.
statusTranslated: string; // Status.
@ -99,7 +102,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
protected siteId: string; // Current site ID.
protected currentUserId: number; // Current user ID.
protected previousAttempt: any; // The previous attempt.
protected previousAttempt: AddonModAssignSubmissionPreviousAttempt; // The previous attempt.
protected submissionStatusAvailable: boolean; // Whether we were able to retrieve the submission status.
protected originalGrades: any = {}; // Object with the original grade data, to check for changes.
protected isDestroyed: boolean; // Whether the component has been destroyed.
@ -209,7 +212,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
return this.goToEdit();
}
const previousSubmission = this.assignProvider.getSubmissionObjectFromAttempt(this.assign, this.previousAttempt);
const previousSubmission = this.previousAttempt.submission;
let modal = this.domUtils.showModalLoading();
this.assignHelper.getSubmissionSizeForCopy(this.assign, previousSubmission).catch(() => {
@ -303,7 +306,8 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
}
if (this.feedback && this.feedback.plugins) {
return this.assignHelper.hasFeedbackDataChanged(this.assign, this.submitId, this.feedback).catch(() => {
return this.assignHelper.hasFeedbackDataChanged(this.assign, this.userSubmission, this.feedback, this.submitId)
.catch(() => {
// Error ocurred, consider there are no changes.
return false;
});
@ -438,7 +442,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
// Check if there's any unsupported plugin for editing.
if (!this.userSubmission || !this.userSubmission.plugins) {
// Submission not created yet, we have to use assign configs to detect the plugins used.
this.userSubmission = {};
this.userSubmission = this.assignHelper.createEmptySubmission();
this.userSubmission.plugins = this.assignHelper.getPluginsEnabled(this.assign, 'assignsubmission');
}
@ -461,7 +465,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
* @param feedback The feedback data from the submission status.
* @return Promise resolved when done.
*/
protected loadFeedback(feedback: any): Promise<any> {
protected loadFeedback(feedback: AddonModAssignSubmissionFeedback): Promise<any> {
this.grade = {
method: false,
grade: false,
@ -571,7 +575,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
if (!this.feedback || !this.feedback.plugins) {
// Feedback plugins not present, we have to use assign configs to detect the plugins used.
this.feedback = {};
this.feedback = this.assignHelper.createEmptyFeedback();
this.feedback.plugins = this.assignHelper.getPluginsEnabled(this.assign, 'assignfeedback');
}
@ -885,7 +889,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
// Show error if submission statement should be shown but it couldn't be retrieved.
this.showErrorStatementEdit = submissionStatementMissing && !this.assign.submissiondrafts &&
this.submitId == this.currentUserId;
this.showErrorStatementSubmit = submissionStatementMissing && this.assign.submissiondrafts;
this.showErrorStatementSubmit = submissionStatementMissing && !!this.assign.submissiondrafts;
this.userSubmission = this.assignProvider.getSubmissionObjectFromAttempt(this.assign, response.lastattempt);
@ -954,3 +958,17 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
}
}
}
/**
* Submission attempt with some calculated data.
*/
type AddonModAssignSubmissionAttemptFormatted = AddonModAssignSubmissionAttempt & {
submissiongroupname?: string; // Calculated in the app. Group name the attempt belongs to.
};
/**
* Feedback of an assign submission with some calculated data.
*/
type AddonModAssignSubmissionFeedbackFormatted = AddonModAssignSubmissionFeedback & {
advancedgrade?: boolean; // Calculated in the app. Whether it uses advanced grading.
};

View File

@ -16,7 +16,9 @@
import { Injectable, Injector } from '@angular/core';
import { CoreSitesProvider } from '@providers/sites';
import { CoreTextUtilsProvider } from '@providers/utils/text';
import { AddonModAssignProvider } from '../../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline';
import { AddonModAssignFeedbackHandler } from '../../../providers/feedback-delegate';
import { AddonModAssignFeedbackCommentsComponent } from '../component/comments';
@ -50,14 +52,14 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
}
/**
* Return the Component to use to display the plugin data, either in read or in edit mode.
* Return the Component to use to display the plugin data.
* It's recommended to return the class of the component, but you can also return an instance of the component.
*
* @param injector Injector.
* @param plugin The plugin object.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin): any | Promise<any> {
return AddonModAssignFeedbackCommentsComponent;
}
@ -101,7 +103,8 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return this.assignProvider.getSubmissionPluginAttachments(plugin);
}
@ -135,7 +138,9 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
* @param userId User ID of the submission.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged(assign: any, submission: any, plugin: any, inputData: any, userId: number): boolean | Promise<boolean> {
hasDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, userId: number): boolean | Promise<boolean> {
// Get it from plugin or offline.
return this.assignOfflineProvider.getSubmissionGrade(assign.id, userId).catch(() => {
// No offline data found.
@ -191,7 +196,9 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareFeedbackData(assignId: number, userId: number, plugin: any, pluginData: any, siteId?: string): void | Promise<any> {
prepareFeedbackData(assignId: number, userId: number, plugin: AddonModAssignPlugin, pluginData: any,
siteId?: string): void | Promise<any> {
const draft = this.getDraft(assignId, userId, siteId);
if (draft) {
@ -212,7 +219,9 @@ export class AddonModAssignFeedbackCommentsHandler implements AddonModAssignFeed
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
saveDraft(assignId: number, userId: number, plugin: any, data: any, siteId?: string): void | Promise<any> {
saveDraft(assignId: number, userId: number, plugin: AddonModAssignPlugin, data: any, siteId?: string)
: void | Promise<any> {
if (data) {
this.drafts[this.getDraftId(assignId, userId, siteId)] = data;
}

View File

@ -14,7 +14,9 @@
// limitations under the License.
import { Injectable, Injector } from '@angular/core';
import { AddonModAssignProvider } from '../../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../../providers/assign';
import { AddonModAssignFeedbackHandler } from '../../../providers/feedback-delegate';
import { AddonModAssignFeedbackEditPdfComponent } from '../component/editpdf';
@ -29,14 +31,14 @@ export class AddonModAssignFeedbackEditPdfHandler implements AddonModAssignFeedb
constructor(private assignProvider: AddonModAssignProvider) { }
/**
* Return the Component to use to display the plugin data, either in read or in edit mode.
* Return the Component to use to display the plugin data.
* It's recommended to return the class of the component, but you can also return an instance of the component.
*
* @param injector Injector.
* @param plugin The plugin object.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin): any | Promise<any> {
return AddonModAssignFeedbackEditPdfComponent;
}
@ -50,7 +52,8 @@ export class AddonModAssignFeedbackEditPdfHandler implements AddonModAssignFeedb
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return this.assignProvider.getSubmissionPluginAttachments(plugin);
}

View File

@ -14,7 +14,9 @@
// limitations under the License.
import { Injectable, Injector } from '@angular/core';
import { AddonModAssignProvider } from '../../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../../providers/assign';
import { AddonModAssignFeedbackHandler } from '../../../providers/feedback-delegate';
import { AddonModAssignFeedbackFileComponent } from '../component/file';
@ -29,14 +31,14 @@ export class AddonModAssignFeedbackFileHandler implements AddonModAssignFeedback
constructor(private assignProvider: AddonModAssignProvider) { }
/**
* Return the Component to use to display the plugin data, either in read or in edit mode.
* Return the Component to use to display the plugin data.
* It's recommended to return the class of the component, but you can also return an instance of the component.
*
* @param injector Injector.
* @param plugin The plugin object.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin): any | Promise<any> {
return AddonModAssignFeedbackFileComponent;
}
@ -50,7 +52,8 @@ export class AddonModAssignFeedbackFileHandler implements AddonModAssignFeedback
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return this.assignProvider.getSubmissionPluginAttachments(plugin);
}

View File

@ -17,6 +17,9 @@ import { IonicPage, ViewController, NavParams } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegate';
import {
AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../providers/assign';
/**
* Modal that allows editing a feedback plugin.
@ -28,9 +31,9 @@ import { AddonModAssignFeedbackDelegate } from '../../providers/feedback-delegat
})
export class AddonModAssignEditFeedbackModalPage {
@Input() assign: any; // The assignment.
@Input() submission: any; // The submission.
@Input() plugin: any; // The plugin object.
@Input() assign: AddonModAssignAssign; // The assignment.
@Input() submission: AddonModAssignSubmission; // The submission.
@Input() plugin: AddonModAssignPlugin; // The plugin object.
@Input() userId: number; // The user ID of the submission.
protected forceLeave = false; // To allow leaving the page without checking for changes.
@ -99,8 +102,8 @@ export class AddonModAssignEditFeedbackModalPage {
* @return Promise resolved with boolean: whether the data has changed.
*/
protected hasDataChanged(): Promise<boolean> {
return this.feedbackDelegate.hasPluginDataChanged(this.assign, this.userId, this.plugin, this.getInputData(), this.userId)
.catch(() => {
return this.feedbackDelegate.hasPluginDataChanged(this.assign, this.submission, this.plugin, this.getInputData(),
this.userId).catch(() => {
// Ignore errors.
return true;
});

View File

@ -20,7 +20,7 @@ import { CoreSitesProvider } from '@providers/sites';
import { CoreSyncProvider } from '@providers/sync';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreFileUploaderHelperProvider } from '@core/fileuploader/providers/helper';
import { AddonModAssignProvider } from '../../providers/assign';
import { AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission } from '../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../providers/assign-offline';
import { AddonModAssignSyncProvider } from '../../providers/assign-sync';
import { AddonModAssignHelperProvider } from '../../providers/helper';
@ -35,9 +35,9 @@ import { AddonModAssignHelperProvider } from '../../providers/helper';
})
export class AddonModAssignEditPage implements OnInit, OnDestroy {
title: string; // Title to display.
assign: any; // Assignment.
assign: AddonModAssignAssign; // Assignment.
courseId: number; // Course ID the assignment belongs to.
userSubmission: any; // The user submission.
userSubmission: AddonModAssignSubmission; // The user submission.
allowOffline: boolean; // Whether offline is allowed.
submissionStatement: string; // The submission statement.
submissionStatementAccepted: boolean; // Whether submission statement is accepted.
@ -129,7 +129,7 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
const userSubmission = this.assignProvider.getSubmissionObjectFromAttempt(this.assign, response.lastattempt);
// Check if the user can edit it in offline.
return this.assignHelper.canEditSubmissionOffline(this.assign, userSubmission).then((canEditOffline) => {
return this.assignHelper.canEditSubmissionOffline(this.assign, userSubmission).then((canEditOffline): any => {
if (canEditOffline) {
return response;
}
@ -301,7 +301,7 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
} else {
// Try to send it to server.
promise = this.assignProvider.saveSubmission(this.assign.id, this.courseId, pluginData, this.allowOffline,
this.userSubmission.timemodified, this.assign.submissiondrafts, this.userId);
this.userSubmission.timemodified, !!this.assign.submissiondrafts, this.userId);
}
return promise.then(() => {

View File

@ -19,9 +19,11 @@ import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreGroupsProvider, CoreGroupInfo } from '@providers/groups';
import { AddonModAssignProvider } from '../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignGrade, AddonModAssignSubmission
} from '../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../providers/assign-offline';
import { AddonModAssignHelperProvider } from '../../providers/helper';
import { AddonModAssignHelperProvider, AddonModAssignSubmissionFormatted } from '../../providers/helper';
import { CoreSplitViewComponent } from '@components/split-view/split-view';
/**
@ -36,7 +38,7 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
@ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent;
title: string; // Title to display.
assign: any; // Assignment.
assign: AddonModAssignAssign; // Assignment.
submissions: any[]; // List of submissions
loaded: boolean; // Whether data has been loaded.
haveAllParticipants: boolean; // Whether all participants have been loaded.
@ -53,7 +55,7 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
protected courseId: number; // Course ID the assignment belongs to.
protected selectedStatus: string; // The status to see.
protected gradedObserver; // Observer to refresh data when a grade changes.
protected submissionsData: any;
protected submissionsData: {canviewsubmissions: boolean, submissions?: AddonModAssignSubmission[]};
constructor(navParams: NavParams, protected sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider,
protected domUtils: CoreDomUtilsProvider, protected translate: TranslateService,
@ -161,14 +163,14 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
!this.assign.markingworkflow ? this.assignProvider.getAssignmentGrades(this.assign.id) : Promise.resolve(null),
];
return Promise.all(promises).then(([submissions, grades]) => {
return Promise.all(promises).then(([submissions, grades]: [AddonModAssignSubmissionFormatted[], AddonModAssignGrade[]]) => {
// Filter the submissions to get only the ones with the right status and add some extra data.
const getNeedGrading = this.selectedStatus == AddonModAssignProvider.NEED_GRADING,
searchStatus = getNeedGrading ? AddonModAssignProvider.SUBMISSION_STATUS_SUBMITTED : this.selectedStatus,
promises = [],
showSubmissions = [];
submissions.forEach((submission) => {
submissions.forEach((submission: AddonModAssignSubmissionForList) => {
if (!searchStatus || searchStatus == submission.status) {
promises.push(this.assignOfflineProvider.getSubmissionGrade(this.assign.id, submission.userid).catch(() => {
// Ignore errors.
@ -213,7 +215,7 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
submission.statusTranslated = this.translate.instant('addon.mod_assign.submissionstatus_' +
submission.status);
} else {
submission.statusTranslated = false;
submission.statusTranslated = '';
}
if (notSynced) {
@ -224,7 +226,7 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
submission.gradingStatusTranslationId =
this.assignProvider.getSubmissionGradingStatusTranslationId(submission.gradingstatus);
} else {
submission.gradingStatusTranslationId = false;
submission.gradingStatusTranslationId = '';
}
showSubmissions.push(submission);
@ -299,3 +301,13 @@ export class AddonModAssignSubmissionListPage implements OnInit, OnDestroy {
this.gradedObserver && this.gradedObserver.off();
}
}
/**
* Calculated data for an assign submission.
*/
type AddonModAssignSubmissionForList = AddonModAssignSubmissionFormatted & {
statusColor?: string; // Calculated in the app. Color of the submission status.
gradingColor?: string; // Calculated in the app. Color of the submission grading status.
statusTranslated?: string; // Calculated in the app. Translated text of the submission status.
gradingStatusTranslationId?: string; // Calculated in the app. Key of the text of the submission grading status.
};

View File

@ -17,7 +17,7 @@ import { IonicPage, NavController, NavParams } from 'ionic-angular';
import { CoreAppProvider } from '@providers/app';
import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreCourseProvider } from '@core/course/providers/course';
import { AddonModAssignProvider } from '../../providers/assign';
import { AddonModAssignProvider, AddonModAssignAssign } from '../../providers/assign';
import { AddonModAssignSubmissionComponent } from '../../components/submission/submission';
/**
@ -40,7 +40,7 @@ export class AddonModAssignSubmissionReviewPage implements OnInit {
loaded: boolean; // Whether data has been loaded.
canSaveGrades: boolean; // Whether the user can save grades.
protected assign: any; // The assignment the submission belongs to.
protected assign: AddonModAssignAssign; // The assignment the submission belongs to.
protected blindMarking: boolean; // Whether it uses blind marking.
protected forceLeave = false; // To allow leaving the page without checking for changes.

View File

@ -26,7 +26,7 @@ import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
import { CoreSyncBaseProvider } from '@classes/base-sync';
import { AddonModAssignProvider } from './assign';
import { AddonModAssignProvider, AddonModAssignAssign } from './assign';
import { AddonModAssignOfflineProvider } from './assign-offline';
import { AddonModAssignSubmissionDelegate } from './submission-delegate';
@ -169,14 +169,14 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
syncAssign(assignId: number, siteId?: string): Promise<AddonModAssignSyncResult> {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
const promises = [],
const promises: Promise<any>[] = [],
result: AddonModAssignSyncResult = {
warnings: [],
updated: false
};
let assign,
courseId,
syncPromise;
let assign: AddonModAssignAssign,
courseId: number,
syncPromise: Promise<any>;
if (this.isSyncing(assignId, siteId)) {
// There's already a sync ongoing for this assign, return the promise.
@ -269,7 +269,7 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved if success, rejected otherwise.
*/
protected syncSubmission(assign: any, offlineData: any, warnings: string[], siteId?: string): Promise<any> {
protected syncSubmission(assign: AddonModAssignAssign, offlineData: any, warnings: string[], siteId?: string): Promise<any> {
const userId = offlineData.userid,
pluginData = {};
let discardError,
@ -358,8 +358,8 @@ export class AddonModAssignSyncProvider extends CoreSyncBaseProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved if success, rejected otherwise.
*/
protected syncSubmissionGrade(assign: any, offlineData: any, warnings: string[], courseId: number, siteId?: string)
: Promise<any> {
protected syncSubmissionGrade(assign: AddonModAssignAssign, offlineData: any, warnings: string[], courseId: number,
siteId?: string): Promise<any> {
const userId = offlineData.userid;
let discardError;

View File

@ -27,6 +27,7 @@ import { AddonModAssignSubmissionDelegate } from './submission-delegate';
import { AddonModAssignOfflineProvider } from './assign-offline';
import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
import { CoreInterceptor } from '@classes/interceptor';
import { CoreWSExternalWarning, CoreWSExternalFile } from '@providers/ws';
/**
* Service that provides some functions for assign.
@ -123,7 +124,7 @@ export class AddonModAssignProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the assignment.
*/
getAssignment(courseId: number, cmId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
getAssignment(courseId: number, cmId: number, ignoreCache?: boolean, siteId?: string): Promise<AddonModAssignAssign> {
return this.getAssignmentByField(courseId, 'cmid', cmId, ignoreCache, siteId);
}
@ -138,7 +139,7 @@ export class AddonModAssignProvider {
* @return Promise resolved when the assignment is retrieved.
*/
protected getAssignmentByField(courseId: number, key: string, value: any, ignoreCache?: boolean, siteId?: string)
: Promise<any> {
: Promise<AddonModAssignAssign> {
return this.sitesProvider.getSite(siteId).then((site) => {
const params = {
@ -161,7 +162,7 @@ export class AddonModAssignProvider {
delete params.includenotenrolledcourses;
return site.read('mod_assign_get_assignments', params, preSets);
}).then((response) => {
}).then((response: AddonModAssignGetAssignmentsResult): any => {
// Search the assignment to return.
if (response.courses && response.courses.length) {
const assignments = response.courses[0].assignments;
@ -187,7 +188,7 @@ export class AddonModAssignProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the assignment.
*/
getAssignmentById(courseId: number, id: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
getAssignmentById(courseId: number, id: number, ignoreCache?: boolean, siteId?: string): Promise<AddonModAssignAssign> {
return this.getAssignmentByField(courseId, 'id', id, ignoreCache, siteId);
}
@ -225,7 +226,9 @@ export class AddonModAssignProvider {
preSets.emergencyCache = false;
}
return site.read('mod_assign_get_user_mappings', params, preSets).then((response) => {
return site.read('mod_assign_get_user_mappings', params, preSets)
.then((response: AddonModAssignGetUserMappingsResult): any => {
// Search the user.
if (response.assignments && response.assignments.length) {
if (!userId || userId < 0) {
@ -271,7 +274,7 @@ export class AddonModAssignProvider {
* @param siteId Site ID. If not defined, current site.
* @return Resolved with requested info when done.
*/
getAssignmentGrades(assignId: number, ignoreCache?: boolean, siteId?: string): Promise<any> {
getAssignmentGrades(assignId: number, ignoreCache?: boolean, siteId?: string): Promise<AddonModAssignGrade[]> {
return this.sitesProvider.getSite(siteId).then((site) => {
const params = {
assignmentids: [assignId]
@ -285,7 +288,7 @@ export class AddonModAssignProvider {
preSets.emergencyCache = false;
}
return site.read('mod_assign_get_grades', params, preSets).then((response) => {
return site.read('mod_assign_get_grades', params, preSets).then((response: AddonModAssignGetGradesResult): any => {
// Search the assignment.
if (response.assignments && response.assignments.length) {
const assignment = response.assignments[0];
@ -294,7 +297,7 @@ export class AddonModAssignProvider {
return assignment.grades;
}
} else if (response.warnings && response.warnings.length) {
if (response.warnings[0].warningcode == 3) {
if (response.warnings[0].warningcode == '3') {
// No grades found.
return [];
}
@ -362,7 +365,9 @@ export class AddonModAssignProvider {
* @param attempt Attempt.
* @return Submission object or null.
*/
getSubmissionObjectFromAttempt(assign: any, attempt: any): any {
getSubmissionObjectFromAttempt(assign: AddonModAssignAssign, attempt: AddonModAssignSubmissionAttempt)
: AddonModAssignSubmission {
if (!attempt) {
return null;
}
@ -432,7 +437,7 @@ export class AddonModAssignProvider {
* @return Promise resolved when done.
*/
getSubmissions(assignId: number, ignoreCache?: boolean, siteId?: string)
: Promise<{canviewsubmissions: boolean, submissions?: any[]}> {
: Promise<{canviewsubmissions: boolean, submissions?: AddonModAssignSubmission[]}> {
return this.sitesProvider.getSite(siteId).then((site) => {
const params = {
@ -448,9 +453,11 @@ export class AddonModAssignProvider {
preSets.emergencyCache = false;
}
return site.read('mod_assign_get_submissions', params, preSets).then((response): any => {
return site.read('mod_assign_get_submissions', params, preSets)
.then((response: AddonModAssignGetSubmissionsResult): any => {
// Check if we can view submissions, with enough permissions.
if (response.warnings.length > 0 && response.warnings[0].warningcode == 1) {
if (response.warnings.length > 0 && response.warnings[0].warningcode == '1') {
return {canviewsubmissions: false};
}
@ -489,7 +496,7 @@ export class AddonModAssignProvider {
* @return Promise always resolved with the user submission status.
*/
getSubmissionStatus(assignId: number, userId?: number, groupId?: number, isBlind?: boolean, filter: boolean = true,
ignoreCache?: boolean, siteId?: string): Promise<any> {
ignoreCache?: boolean, siteId?: string): Promise<AddonModAssignGetSubmissionStatusResult> {
userId = userId || 0;
@ -540,7 +547,7 @@ export class AddonModAssignProvider {
* @return Promise always resolved with the user submission status.
*/
getSubmissionStatusWithRetry(assign: any, userId?: number, groupId?: number, isBlind?: boolean, filter: boolean = true,
ignoreCache?: boolean, siteId?: string): Promise<any> {
ignoreCache?: boolean, siteId?: string): Promise<AddonModAssignGetSubmissionStatusResult> {
return this.getSubmissionStatus(assign.id, userId, groupId, isBlind, filter, ignoreCache, siteId).then((response) => {
const userSubmission = this.getSubmissionObjectFromAttempt(assign, response.lastattempt);
@ -630,7 +637,9 @@ export class AddonModAssignProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the list of participants and summary of submissions.
*/
listParticipants(assignId: number, groupId?: number, ignoreCache?: boolean, siteId?: string): Promise<any[]> {
listParticipants(assignId: number, groupId?: number, ignoreCache?: boolean, siteId?: string)
: Promise<AddonModAssignParticipant[]> {
groupId = groupId || 0;
return this.sitesProvider.getSite(siteId).then((site) => {
@ -1051,14 +1060,14 @@ export class AddonModAssignProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when saved, rejected otherwise.
*/
saveSubmissionOnline(assignId: number, pluginData: any, siteId?: string): Promise<any> {
saveSubmissionOnline(assignId: number, pluginData: any, siteId?: string): Promise<void> {
return this.sitesProvider.getSite(siteId).then((site) => {
const params = {
assignmentid: assignId,
plugindata: pluginData
};
return site.write('mod_assign_save_submission', params).then((warnings) => {
return site.write('mod_assign_save_submission', params).then((warnings: CoreWSExternalWarning[]) => {
if (warnings && warnings.length) {
// The WebService returned warnings, reject.
return Promise.reject(warnings[0]);
@ -1120,14 +1129,14 @@ export class AddonModAssignProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when submitted, rejected otherwise.
*/
submitForGradingOnline(assignId: number, acceptStatement: boolean, siteId?: string): Promise<any> {
submitForGradingOnline(assignId: number, acceptStatement: boolean, siteId?: string): Promise<void> {
return this.sitesProvider.getSite(siteId).then((site) => {
const params = {
assignmentid: assignId,
acceptsubmissionstatement: acceptStatement ? 1 : 0
};
return site.write('mod_assign_submit_for_grading', params).then((warnings) => {
return site.write('mod_assign_submit_for_grading', params).then((warnings: CoreWSExternalWarning[]) => {
if (warnings && warnings.length) {
// The WebService returned warnings, reject.
return Promise.reject(warnings[0]);
@ -1169,7 +1178,10 @@ export class AddonModAssignProvider {
return this.isGradingOfflineEnabled(siteId).then((enabled) => {
if (!enabled) {
return this.submitGradingFormOnline(assignId, userId, grade, attemptNumber, addAttempt, workflowState,
applyToAll, outcomes, pluginData, siteId);
applyToAll, outcomes, pluginData, siteId).then(() => {
return true;
});
}
if (!this.appProvider.isOnline()) {
@ -1212,7 +1224,7 @@ export class AddonModAssignProvider {
* @return Promise resolved when submitted, rejected otherwise.
*/
submitGradingFormOnline(assignId: number, userId: number, grade: number, attemptNumber: number, addAttempt: boolean,
workflowState: string, applyToAll: boolean, outcomes: any, pluginData: any, siteId?: string): Promise<any> {
workflowState: string, applyToAll: boolean, outcomes: any, pluginData: any, siteId?: string): Promise<void | null> {
return this.sitesProvider.getSite(siteId).then((site) => {
userId = userId || site.getUserId();
@ -1243,7 +1255,7 @@ export class AddonModAssignProvider {
jsonformdata: JSON.stringify(serialized)
};
return site.write('mod_assign_submit_grading_form', params).then((warnings) => {
return site.write('mod_assign_submit_grading_form', params).then((warnings: CoreWSExternalWarning[]) => {
if (warnings && warnings.length) {
// The WebService returned warnings, reject.
return Promise.reject(warnings[0]);
@ -1271,3 +1283,285 @@ export class AddonModAssignProvider {
});
}
}
/**
* Assign data returned by mod_assign_get_assignments.
*/
export type AddonModAssignAssign = {
id: number; // Assignment id.
cmid: number; // Course module id.
course: number; // Course id.
name: string; // Assignment name.
nosubmissions: number; // No submissions.
submissiondrafts: number; // Submissions drafts.
sendnotifications: number; // Send notifications.
sendlatenotifications: number; // Send notifications.
sendstudentnotifications: number; // Send student notifications (default).
duedate: number; // Assignment due date.
allowsubmissionsfromdate: number; // Allow submissions from date.
grade: number; // Grade type.
timemodified: number; // Last time assignment was modified.
completionsubmit: number; // If enabled, set activity as complete following submission.
cutoffdate: number; // Date after which submission is not accepted without an extension.
gradingduedate?: number; // @since 3.3. The expected date for marking the submissions.
teamsubmission: number; // If enabled, students submit as a team.
requireallteammemberssubmit: number; // If enabled, all team members must submit.
teamsubmissiongroupingid: number; // The grouping id for the team submission groups.
blindmarking: number; // If enabled, hide identities until reveal identities actioned.
hidegrader?: number; // @since 3.7. If enabled, hide grader to student.
revealidentities: number; // Show identities for a blind marking assignment.
attemptreopenmethod: string; // Method used to control opening new attempts.
maxattempts: number; // Maximum number of attempts allowed.
markingworkflow: number; // Enable marking workflow.
markingallocation: number; // Enable marking allocation.
requiresubmissionstatement: number; // Student must accept submission statement.
preventsubmissionnotingroup?: number; // @since 3.2. Prevent submission not in group.
submissionstatement?: string; // @since 3.2. Submission statement formatted.
submissionstatementformat?: number; // @since 3.2. Submissionstatement format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
configs: AddonModAssignConfig[]; // Configuration settings.
intro?: string; // Assignment intro, not allways returned because it deppends on the activity configuration.
introformat?: number; // Intro format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
introfiles?: CoreWSExternalFile[]; // @since 3.2.
introattachments?: CoreWSExternalFile[];
};
/**
* Config setting in an assign.
*/
export type AddonModAssignConfig = {
id?: number; // Assign_plugin_config id.
assignment?: number; // Assignment id.
plugin: string; // Plugin.
subtype: string; // Subtype.
name: string; // Name.
value: string; // Value.
};
/**
* Grade of an assign, returned by mod_assign_get_grades.
*/
export type AddonModAssignGrade = {
id: number; // Grade id.
assignment?: number; // Assignment id.
userid: number; // Student id.
attemptnumber: number; // Attempt number.
timecreated: number; // Grade creation time.
timemodified: number; // Grade last modified time.
grader: number; // Grader, -1 if grader is hidden.
grade: string; // Grade.
gradefordisplay?: string; // Grade rendered into a format suitable for display.
};
/**
* Assign submission returned by mod_assign_get_submissions.
*/
export type AddonModAssignSubmission = {
id: number; // Submission id.
userid: number; // Student id.
attemptnumber: number; // Attempt number.
timecreated: number; // Submission creation time.
timemodified: number; // Submission last modified time.
status: string; // Submission status.
groupid: number; // Group id.
assignment?: number; // Assignment id.
latest?: number; // Latest attempt.
plugins?: AddonModAssignPlugin[]; // Plugins.
gradingstatus?: string; // @since 3.2. Grading status.
};
/**
* Assign plugin.
*/
export type AddonModAssignPlugin = {
type: string; // Submission plugin type.
name: string; // Submission plugin name.
fileareas?: { // Fileareas.
area: string; // File area.
files?: CoreWSExternalFile[];
}[];
editorfields?: { // Editorfields.
name: string; // Field name.
description: string; // Field description.
text: string; // Field value.
format: number; // Text format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
}[];
};
/**
* Grading summary of an assign submission.
*/
export type AddonModAssignSubmissionGradingSummary = {
participantcount: number; // Number of users who can submit.
submissiondraftscount: number; // Number of submissions in draft status.
submissionsenabled: boolean; // Whether submissions are enabled or not.
submissionssubmittedcount: number; // Number of submissions in submitted status.
submissionsneedgradingcount: number; // Number of submissions that need grading.
warnofungroupedusers: string; // Whether we need to warn people about groups.
};
/**
* Attempt of an assign submission.
*/
export type AddonModAssignSubmissionAttempt = {
submission?: AddonModAssignSubmission; // Submission info.
teamsubmission?: AddonModAssignSubmission; // Submission info.
submissiongroup?: number; // The submission group id (for group submissions only).
submissiongroupmemberswhoneedtosubmit?: number[]; // List of users who still need to submit (for group submissions only).
submissionsenabled: boolean; // Whether submissions are enabled or not.
locked: boolean; // Whether new submissions are locked.
graded: boolean; // Whether the submission is graded.
canedit: boolean; // Whether the user can edit the current submission.
caneditowner?: boolean; // @since 3.2. Whether the owner of the submission can edit it.
cansubmit: boolean; // Whether the user can submit.
extensionduedate: number; // Extension due date.
blindmarking: boolean; // Whether blind marking is enabled.
gradingstatus: string; // Grading status.
usergroups: number[]; // User groups in the course.
};
/**
* Previous attempt of an assign submission.
*/
export type AddonModAssignSubmissionPreviousAttempt = {
attemptnumber: number; // Attempt number.
submission?: AddonModAssignSubmission; // Submission info.
grade?: AddonModAssignGrade; // Grade information.
feedbackplugins?: AddonModAssignPlugin[]; // Feedback info.
};
/**
* Feedback of an assign submission.
*/
export type AddonModAssignSubmissionFeedback = {
grade: AddonModAssignGrade; // Grade information.
gradefordisplay: string; // Grade rendered into a format suitable for display.
gradeddate: number; // The date the user was graded.
plugins?: AddonModAssignPlugin[]; // Plugins info.
};
/**
* Participant returned by mod_assign_list_participants.
*/
export type AddonModAssignParticipant = {
id: number; // ID of the user.
username?: string; // The username.
firstname?: string; // The first name(s) of the user.
lastname?: string; // The family name of the user.
fullname: string; // The fullname of the user.
email?: string; // Email address.
address?: string; // Postal address.
phone1?: string; // Phone 1.
phone2?: string; // Phone 2.
icq?: string; // Icq number.
skype?: string; // Skype id.
yahoo?: string; // Yahoo id.
aim?: string; // Aim id.
msn?: string; // Msn number.
department?: string; // Department.
institution?: string; // Institution.
idnumber?: string; // The idnumber of the user.
interests?: string; // User interests (separated by commas).
firstaccess?: number; // First access to the site (0 if never).
lastaccess?: number; // Last access to the site (0 if never).
suspended?: boolean; // @since 3.2. Suspend user account, either false to enable user login or true to disable it.
description?: string; // User profile description.
descriptionformat?: number; // Int format (1 = HTML, 0 = MOODLE, 2 = PLAIN or 4 = MARKDOWN).
city?: string; // Home city of the user.
url?: string; // URL of the user.
country?: string; // Home country code of the user, such as AU or CZ.
profileimageurlsmall?: string; // User image profile URL - small version.
profileimageurl?: string; // User image profile URL - big version.
customfields?: { // User custom fields (also known as user profile fields).
type: string; // The type of the custom field - text field, checkbox...
value: string; // The value of the custom field.
name: string; // The name of the custom field.
shortname: string; // The shortname of the custom field - to be able to build the field class in the code.
}[];
preferences?: { // Users preferences.
name: string; // The name of the preferences.
value: string; // The value of the preference.
}[];
recordid?: number; // @since 3.7. Record id.
groups?: { // User groups.
id: number; // Group id.
name: string; // Group name.
description: string; // Group description.
}[];
roles?: { // User roles.
roleid: number; // Role id.
name: string; // Role name.
shortname: string; // Role shortname.
sortorder: number; // Role sortorder.
}[];
enrolledcourses?: { // Courses where the user is enrolled - limited by which courses the user is able to see.
id: number; // Id of the course.
fullname: string; // Fullname of the course.
shortname: string; // Shortname of the course.
}[];
submitted: boolean; // Have they submitted their assignment.
requiregrading: boolean; // Is their submission waiting for grading.
grantedextension?: boolean; // @since 3.3. Have they been granted an extension.
groupid?: number; // For group assignments this is the group id.
groupname?: string; // For group assignments this is the group name.
};
/**
* Result of WS mod_assign_get_assignments.
*/
export type AddonModAssignGetAssignmentsResult = {
courses: { // List of courses.
id: number; // Course id.
fullname: string; // Course full name.
shortname: string; // Course short name.
timemodified: number; // Last time modified.
assignments: AddonModAssignAssign[]; // Assignment info.
}[];
warnings?: CoreWSExternalWarning[];
};
/**
* Result of WS mod_assign_get_user_mappings.
*/
export type AddonModAssignGetUserMappingsResult = {
assignments: { // List of assign user mapping data.
assignmentid: number; // Assignment id.
mappings: {
id: number; // User mapping id.
userid: number; // Student id.
}[];
}[];
warnings?: CoreWSExternalWarning[];
};
/**
* Result of WS mod_assign_get_grades.
*/
export type AddonModAssignGetGradesResult = {
assignments: { // List of assignment grade information.
assignmentid: number; // Assignment id.
grades: AddonModAssignGrade[];
}[];
warnings?: CoreWSExternalWarning[];
};
/**
* Result of WS mod_assign_get_submissions.
*/
export type AddonModAssignGetSubmissionsResult = {
assignments: { // Assignment submissions.
assignmentid: number; // Assignment id.
submissions: AddonModAssignSubmission[];
}[];
warnings?: CoreWSExternalWarning[];
};
/**
* Result of WS mod_assign_get_submission_status.
*/
export type AddonModAssignGetSubmissionStatusResult = {
gradingsummary?: AddonModAssignSubmissionGradingSummary; // Grading information.
lastattempt?: AddonModAssignSubmissionAttempt; // Last attempt information.
feedback?: AddonModAssignSubmissionFeedback; // Feedback for the last attempt.
previousattempts?: AddonModAssignSubmissionPreviousAttempt[]; // List all the previous attempts did by the user.
warnings?: CoreWSExternalWarning[];
};

View File

@ -18,6 +18,7 @@ import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
import { AddonModAssignDefaultFeedbackHandler } from './default-feedback-handler';
import { AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin } from './assign';
/**
* Interface that all feedback handlers must implement.
@ -47,7 +48,7 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param plugin The plugin object.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent?(injector: Injector, plugin: any): any | Promise<any>;
getComponent?(injector: Injector, plugin: AddonModAssignPlugin): any | Promise<any>;
/**
* Return the draft saved data of the feedback plugin.
@ -69,7 +70,8 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles?(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]>;
getPluginFiles?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]>;
/**
* Get a readable name to use for the plugin.
@ -77,7 +79,7 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param plugin The plugin object.
* @return The plugin name.
*/
getPluginName?(plugin: any): string;
getPluginName?(plugin: AddonModAssignPlugin): string;
/**
* Check if the feedback data has changed for this plugin.
@ -89,7 +91,8 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param userId User ID of the submission.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged?(assign: any, submission: any, plugin: any, inputData: any, userId: number): boolean | Promise<boolean>;
hasDataChanged?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, userId: number): boolean | Promise<boolean>;
/**
* Check whether the plugin has draft data stored.
@ -111,7 +114,8 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch?(assign: any, submission: any, plugin: any, siteId?: string): Promise<any>;
prefetch?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any>;
/**
* Prepare and add to pluginData the data to send to the server based on the draft data saved.
@ -123,7 +127,8 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareFeedbackData?(assignId: number, userId: number, plugin: any, pluginData: any, siteId?: string): void | Promise<any>;
prepareFeedbackData?(assignId: number, userId: number, plugin: AddonModAssignPlugin, pluginData: any,
siteId?: string): void | Promise<any>;
/**
* Save draft data of the feedback plugin.
@ -135,7 +140,8 @@ export interface AddonModAssignFeedbackHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
saveDraft?(assignId: number, userId: number, plugin: any, data: any, siteId?: string): void | Promise<any>;
saveDraft?(assignId: number, userId: number, plugin: AddonModAssignPlugin, data: any, siteId?: string)
: void | Promise<any>;
}
/**
@ -160,7 +166,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
discardPluginFeedbackData(assignId: number, userId: number, plugin: any, siteId?: string): Promise<any> {
discardPluginFeedbackData(assignId: number, userId: number, plugin: AddonModAssignPlugin, siteId?: string)
: Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'discardDraft', [assignId, userId, siteId]));
}
@ -171,7 +178,7 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param plugin The plugin object.
* @return Promise resolved with the component to use, undefined if not found.
*/
getComponentForPlugin(injector: Injector, plugin: any): Promise<any> {
getComponentForPlugin(injector: Injector, plugin: AddonModAssignPlugin): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getComponent', [injector, plugin]));
}
@ -184,7 +191,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the draft data.
*/
getPluginDraftData(assignId: number, userId: number, plugin: any, siteId?: string): Promise<any> {
getPluginDraftData(assignId: number, userId: number, plugin: AddonModAssignPlugin, siteId?: string)
: Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getDraft', [assignId, userId, siteId]));
}
@ -198,7 +206,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the files.
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any[]> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getPluginFiles', [assign, submission, plugin, siteId]));
}
@ -208,7 +217,7 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param plugin Plugin to get the name for.
* @return Human readable name.
*/
getPluginName(plugin: any): string {
getPluginName(plugin: AddonModAssignPlugin): string {
return this.executeFunctionOnEnabled(plugin.type, 'getPluginName', [plugin]);
}
@ -222,7 +231,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param userId User ID of the submission.
* @return Promise resolved with true if data has changed, resolved with false otherwise.
*/
hasPluginDataChanged(assign: any, submission: any, plugin: any, inputData: any, userId: number): Promise<boolean> {
hasPluginDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, userId: number): Promise<boolean> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'hasDataChanged',
[assign, submission, plugin, inputData, userId]));
}
@ -236,7 +246,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with true if it has draft data.
*/
hasPluginDraftData(assignId: number, userId: number, plugin: any, siteId?: string): Promise<boolean> {
hasPluginDraftData(assignId: number, userId: number, plugin: AddonModAssignPlugin, siteId?: string)
: Promise<boolean> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'hasDraftData', [assignId, userId, siteId]));
}
@ -259,7 +270,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise<any> {
prefetch(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, plugin: AddonModAssignPlugin,
siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'prefetch', [assign, submission, plugin, siteId]));
}
@ -273,7 +285,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when data has been gathered.
*/
preparePluginFeedbackData(assignId: number, userId: number, plugin: any, pluginData: any, siteId?: string): Promise<any> {
preparePluginFeedbackData(assignId: number, userId: number, plugin: AddonModAssignPlugin, pluginData: any,
siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'prepareFeedbackData',
[assignId, userId, plugin, pluginData, siteId]));
@ -289,7 +302,8 @@ export class AddonModAssignFeedbackDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when data has been saved.
*/
saveFeedbackDraft(assignId: number, userId: number, plugin: any, inputData: any, siteId?: string): Promise<any> {
saveFeedbackDraft(assignId: number, userId: number, plugin: AddonModAssignPlugin, inputData: any,
siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'saveDraft',
[assignId, userId, plugin, inputData, siteId]));
}

View File

@ -21,7 +21,10 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
import { AddonModAssignFeedbackDelegate } from './feedback-delegate';
import { AddonModAssignSubmissionDelegate } from './submission-delegate';
import { AddonModAssignProvider } from './assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignParticipant,
AddonModAssignSubmissionFeedback
} from './assign';
import { AddonModAssignOfflineProvider } from './assign-offline';
/**
@ -46,7 +49,7 @@ export class AddonModAssignHelperProvider {
* @param submission Submission.
* @return Whether it can be edited offline.
*/
canEditSubmissionOffline(assign: any, submission: any): Promise<boolean> {
canEditSubmissionOffline(assign: AddonModAssignAssign, submission: AddonModAssignSubmission): Promise<boolean> {
if (!submission) {
return Promise.resolve(false);
}
@ -81,7 +84,7 @@ export class AddonModAssignHelperProvider {
* @param submission Submission to clear the data for.
* @param inputData Data entered in the submission form.
*/
clearSubmissionPluginTmpData(assign: any, submission: any, inputData: any): void {
clearSubmissionPluginTmpData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, inputData: any): void {
submission.plugins.forEach((plugin) => {
this.submissionDelegate.clearTmpData(assign, submission, plugin, inputData);
});
@ -95,7 +98,7 @@ export class AddonModAssignHelperProvider {
* @param previousSubmission Submission to copy.
* @return Promise resolved when done.
*/
copyPreviousAttempt(assign: any, previousSubmission: any): Promise<any> {
copyPreviousAttempt(assign: AddonModAssignAssign, previousSubmission: AddonModAssignSubmission): Promise<any> {
const pluginData = {},
promises = [];
@ -112,6 +115,36 @@ export class AddonModAssignHelperProvider {
});
}
/**
* Create an empty feedback object.
*
* @return Feedback.
*/
createEmptyFeedback(): AddonModAssignSubmissionFeedback {
return {
grade: undefined,
gradefordisplay: undefined,
gradeddate: undefined
};
}
/**
* Create an empty submission object.
*
* @return Submission.
*/
createEmptySubmission(): AddonModAssignSubmissionFormatted {
return {
id: undefined,
userid: undefined,
attemptnumber: undefined,
timecreated: undefined,
timemodified: undefined,
status: undefined,
groupid: undefined
};
}
/**
* Delete stored submission files for a plugin. See storeSubmissionFiles.
*
@ -136,7 +169,9 @@ export class AddonModAssignHelperProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
discardFeedbackPluginData(assignId: number, userId: number, feedback: any, siteId?: string): Promise<any> {
discardFeedbackPluginData(assignId: number, userId: number, feedback: AddonModAssignSubmissionFeedback,
siteId?: string): Promise<any> {
const promises = [];
feedback.plugins.forEach((plugin) => {
@ -155,7 +190,9 @@ export class AddonModAssignHelperProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the list of participants and summary of submissions.
*/
getParticipants(assign: any, groupId?: number, ignoreCache?: boolean, siteId?: string): Promise<any[]> {
getParticipants(assign: AddonModAssignAssign, groupId?: number, ignoreCache?: boolean, siteId?: string)
: Promise<AddonModAssignParticipant[]> {
groupId = groupId || 0;
siteId = siteId || this.sitesProvider.getCurrentSiteId();
@ -167,7 +204,7 @@ export class AddonModAssignHelperProvider {
// If no participants returned and all groups specified, get participants by groups.
return this.groupsProvider.getActivityGroupInfo(assign.cmid, false, undefined, siteId).then((info) => {
const promises = [],
participants = {};
participants: {[id: number]: AddonModAssignParticipant} = {};
info.groups.forEach((userGroup) => {
promises.push(this.assignProvider.listParticipants(assign.id, userGroup.id, ignoreCache, siteId)
@ -194,8 +231,8 @@ export class AddonModAssignHelperProvider {
* @param type Name of the subplugin.
* @return Object containing all configurations of the subplugin selected.
*/
getPluginConfig(assign: any, subtype: string, type: string): any {
const configs = {};
getPluginConfig(assign: AddonModAssignAssign, subtype: string, type: string): {[name: string]: string} {
const configs: {[name: string]: string} = {};
assign.configs.forEach((config) => {
if (config.subtype == subtype && config.plugin == type) {
@ -213,7 +250,7 @@ export class AddonModAssignHelperProvider {
* @param subtype Subtype name (assignsubmission or assignfeedback)
* @return List of enabled plugins for the assign.
*/
getPluginsEnabled(assign: any, subtype: string): any[] {
getPluginsEnabled(assign: AddonModAssignAssign, subtype: string): any[] {
const enabled = [];
assign.configs.forEach((config) => {
@ -250,7 +287,7 @@ export class AddonModAssignHelperProvider {
* @param previousSubmission Submission to copy.
* @return Promise resolved with the size.
*/
getSubmissionSizeForCopy(assign: any, previousSubmission: any): Promise<number> {
getSubmissionSizeForCopy(assign: AddonModAssignAssign, previousSubmission: AddonModAssignSubmission): Promise<number> {
const promises = [];
let totalSize = 0;
@ -273,7 +310,8 @@ export class AddonModAssignHelperProvider {
* @param inputData Data entered in the submission form.
* @return Promise resolved with the size.
*/
getSubmissionSizeForEdit(assign: any, submission: any, inputData: any): Promise<number> {
getSubmissionSizeForEdit(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, inputData: any): Promise<number> {
const promises = [];
let totalSize = 0;
@ -298,14 +336,14 @@ export class AddonModAssignHelperProvider {
* @param siteId Site id (empty for current site).
* @return Promise always resolved. Resolve param is the formatted submissions.
*/
getSubmissionsUserData(assign: any, submissions: any[], groupId?: number, ignoreCache?: boolean, siteId?: string):
Promise<any[]> {
return this.getParticipants(assign, groupId).then((participants) => {
getSubmissionsUserData(assign: AddonModAssignAssign, submissions: AddonModAssignSubmissionFormatted[], groupId?: number,
ignoreCache?: boolean, siteId?: string): Promise<AddonModAssignSubmissionFormatted[]> {
return this.getParticipants(assign, groupId).then((parts) => {
const blind = assign.blindmarking && !assign.revealidentities;
const promises = [];
const result = [];
participants = this.utils.arrayToObject(participants, 'id');
const result: AddonModAssignSubmissionFormatted[] = [];
const participants: {[id: number]: AddonModAssignParticipant} = this.utils.arrayToObject(parts, 'id');
submissions.forEach((submission) => {
submission.submitid = submission.userid > 0 ? submission.userid : submission.blindid;
@ -356,10 +394,10 @@ export class AddonModAssignHelperProvider {
return Promise.all(promises).then(() => {
// Create a submission for each participant left in the list (the participants already treated were removed).
this.utils.objectToArray(participants).forEach((participant) => {
const submission: any = {
submitid: participant.id
};
this.utils.objectToArray(participants).forEach((participant: AddonModAssignParticipant) => {
const submission = this.createEmptySubmission();
submission.submitid = participant.id;
if (!blind) {
submission.userid = participant.id;
@ -390,17 +428,20 @@ export class AddonModAssignHelperProvider {
* Check if the feedback data has changed for a certain submission and assign.
*
* @param assign Assignment.
* @param userId User Id.
* @param submission The submission.
* @param feedback Feedback data.
* @param userId The user ID.
* @return Promise resolved with true if data has changed, resolved with false otherwise.
*/
hasFeedbackDataChanged(assign: any, userId: number, feedback: any): Promise<boolean> {
hasFeedbackDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
feedback: AddonModAssignSubmissionFeedback, userId: number): Promise<boolean> {
const promises = [];
let hasChanged = false;
feedback.plugins.forEach((plugin) => {
promises.push(this.prepareFeedbackPluginData(assign.id, userId, feedback).then((inputData) => {
return this.feedbackDelegate.hasPluginDataChanged(assign, userId, plugin, inputData, userId).then((changed) => {
return this.feedbackDelegate.hasPluginDataChanged(assign, submission, plugin, inputData, userId).then((changed) => {
if (changed) {
hasChanged = true;
}
@ -423,7 +464,9 @@ export class AddonModAssignHelperProvider {
* @param inputData Data entered in the submission form.
* @return Promise resolved with true if data has changed, resolved with false otherwise.
*/
hasSubmissionDataChanged(assign: any, submission: any, inputData: any): Promise<boolean> {
hasSubmissionDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, inputData: any)
: Promise<boolean> {
const promises = [];
let hasChanged = false;
@ -451,7 +494,9 @@ export class AddonModAssignHelperProvider {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with plugin data to send to server.
*/
prepareFeedbackPluginData(assignId: number, userId: number, feedback: any, siteId?: string): Promise<any> {
prepareFeedbackPluginData(assignId: number, userId: number, feedback: AddonModAssignSubmissionFeedback, siteId?: string)
: Promise<any> {
const pluginData = {},
promises = [];
@ -473,7 +518,9 @@ export class AddonModAssignHelperProvider {
* @param offline True to prepare the data for an offline submission, false otherwise.
* @return Promise resolved with plugin data to send to server.
*/
prepareSubmissionPluginData(assign: any, submission: any, inputData: any, offline?: boolean): Promise<any> {
prepareSubmissionPluginData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, inputData: any,
offline?: boolean): Promise<any> {
const pluginData = {},
promises = [];
@ -553,3 +600,16 @@ export class AddonModAssignHelperProvider {
}
}
}
/**
* Assign submission with some calculated data.
*/
export type AddonModAssignSubmissionFormatted = AddonModAssignSubmission & {
blindid?: number; // Calculated in the app. Blindid of the user that did the submission.
submitid?: number; // Calculated in the app. Userid or blindid of the user that did the submission.
userfullname?: string; // Calculated in the app. Full name of the user that did the submission.
userprofileimageurl?: string; // Calculated in the app. Avatar of the user that did the submission.
manyGroups?: boolean; // Calculated in the app. Whether the user belongs to more than 1 group.
noGroups?: boolean; // Calculated in the app. Whether the user doesn't belong to any group.
groupname?: string; // Calculated in the app. Name of the group the submission belongs to.
};

View File

@ -26,8 +26,8 @@ import { CoreCourseProvider } from '@core/course/providers/course';
import { CoreCourseHelperProvider } from '@core/course/providers/helper';
import { CoreGradesHelperProvider } from '@core/grades/providers/helper';
import { CoreUserProvider } from '@core/user/providers/user';
import { AddonModAssignProvider } from './assign';
import { AddonModAssignHelperProvider } from './helper';
import { AddonModAssignProvider, AddonModAssignGetSubmissionStatusResult, AddonModAssignSubmission } from './assign';
import { AddonModAssignHelperProvider, AddonModAssignSubmissionFormatted } from './helper';
import { AddonModAssignSyncProvider } from './assign-sync';
import { AddonModAssignFeedbackDelegate } from './feedback-delegate';
import { AddonModAssignSubmissionDelegate } from './submission-delegate';
@ -106,7 +106,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
if (data.canviewsubmissions) {
// Teacher, get all submissions.
return this.assignHelper.getSubmissionsUserData(assign, data.submissions, 0, false, siteId)
.then((submissions) => {
.then((submissions: AddonModAssignSubmissionFormatted[]) => {
const promises = [];
@ -161,9 +161,10 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
return this.assignProvider.getSubmissionStatusWithRetry(assign, submitId, undefined, blindMarking, true, false, siteId)
.then((response) => {
const promises = [];
let userSubmission: AddonModAssignSubmission;
if (response.lastattempt) {
const userSubmission = this.assignProvider.getSubmissionObjectFromAttempt(assign, response.lastattempt);
userSubmission = this.assignProvider.getSubmissionObjectFromAttempt(assign, response.lastattempt);
if (userSubmission && userSubmission.plugins) {
// Add submission plugin files.
userSubmission.plugins.forEach((plugin) => {
@ -175,7 +176,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
if (response.feedback && response.feedback.plugins) {
// Add feedback plugin files.
response.feedback.plugins.forEach((plugin) => {
promises.push(this.feedbackDelegate.getPluginFiles(assign, response, plugin, siteId));
promises.push(this.feedbackDelegate.getPluginFiles(assign, userSubmission, plugin, siteId));
});
}
@ -303,7 +304,7 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
groupInfo.groups.forEach((group) => {
groupProms.push(this.assignHelper.getSubmissionsUserData(assign, data.submissions, group.id, true, siteId)
.then((submissions) => {
.then((submissions: AddonModAssignSubmissionFormatted[]) => {
const subPromises = [];
@ -327,7 +328,8 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
}
// Prefetch the submission of the current user even if it does not exist, this will be create it.
if (!data.submissions || !data.submissions.find((subm) => subm.submitid == userId)) {
if (!data.submissions ||
!data.submissions.find((subm: AddonModAssignSubmissionFormatted) => subm.submitid == userId)) {
subPromises.push(this.assignProvider.getSubmissionStatusWithRetry(assign, userId, group.id,
false, true, true, siteId).then((subm) => {
return this.prefetchSubmission(assign, courseId, moduleId, subm, userId, siteId);
@ -385,15 +387,16 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when prefetched, rejected otherwise.
*/
protected prefetchSubmission(assign: any, courseId: number, moduleId: number, submission: any, userId?: number,
siteId?: string): Promise<any> {
protected prefetchSubmission(assign: any, courseId: number, moduleId: number,
submission: AddonModAssignGetSubmissionStatusResult, userId?: number, siteId?: string): Promise<any> {
const promises = [],
blindMarking = assign.blindmarking && !assign.revealidentities;
let userIds = [];
let userIds = [],
userSubmission: AddonModAssignSubmission;
if (submission.lastattempt) {
const userSubmission = this.assignProvider.getSubmissionObjectFromAttempt(assign, submission.lastattempt);
userSubmission = this.assignProvider.getSubmissionObjectFromAttempt(assign, submission.lastattempt);
// Get IDs of the members who need to submit.
if (!blindMarking && submission.lastattempt.submissiongroupmemberswhoneedtosubmit) {
@ -440,10 +443,10 @@ export class AddonModAssignPrefetchHandler extends CoreCourseActivityPrefetchHan
if (submission.feedback.plugins) {
submission.feedback.plugins.forEach((plugin) => {
// Prefetch the plugin WS data.
promises.push(this.feedbackDelegate.prefetch(assign, submission, plugin, siteId));
promises.push(this.feedbackDelegate.prefetch(assign, userSubmission, plugin, siteId));
// Prefetch the plugin files.
promises.push(this.feedbackDelegate.getPluginFiles(assign, submission, plugin, siteId).then((files) => {
promises.push(this.feedbackDelegate.getPluginFiles(assign, userSubmission, plugin, siteId).then((files) => {
return this.filepoolProvider.addFilesToQueue(siteId, files, this.component, module.id);
}).catch(() => {
// Ignore errors.

View File

@ -18,6 +18,7 @@ import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
import { AddonModAssignDefaultSubmissionHandler } from './default-submission-handler';
import { AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin } from './assign';
/**
* Interface that all submission handlers must implement.
@ -39,7 +40,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param plugin The plugin object.
* @return Boolean or promise resolved with boolean: whether it can be edited in offline.
*/
canEditOffline?(assign: any, submission: any, plugin: any): boolean | Promise<boolean>;
canEditOffline?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin): boolean | Promise<boolean>;
/**
* Should clear temporary data for a cancelled submission.
@ -49,7 +51,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param plugin The plugin object.
* @param inputData Data entered by the user for the submission.
*/
clearTmpData?(assign: any, submission: any, plugin: any, inputData: any): void;
clearTmpData?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): void;
/**
* This function will be called when the user wants to create a new submission based on the previous one.
@ -62,7 +65,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
copySubmissionData?(assign: any, plugin: any, pluginData: any, userId?: number, siteId?: string): void | Promise<any>;
copySubmissionData?(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin, pluginData: any,
userId?: number, siteId?: string): void | Promise<any>;
/**
* Delete any stored data for the plugin and submission.
@ -74,7 +78,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
deleteOfflineData?(assign: any, submission: any, plugin: any, offlineData: any, siteId?: string): void | Promise<any>;
deleteOfflineData?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, siteId?: string): void | Promise<any>;
/**
* Return the Component to use to display the plugin data, either in read or in edit mode.
@ -85,7 +90,7 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param edit Whether the user is editing.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent?(injector: Injector, plugin: any, edit?: boolean): any | Promise<any>;
getComponent?(injector: Injector, plugin: AddonModAssignPlugin, edit?: boolean): any | Promise<any>;
/**
* Get files used by this plugin.
@ -97,7 +102,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles?(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]>;
getPluginFiles?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]>;
/**
* Get a readable name to use for the plugin.
@ -105,7 +111,7 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param plugin The plugin object.
* @return The plugin name.
*/
getPluginName?(plugin: any): string;
getPluginName?(plugin: AddonModAssignPlugin): string;
/**
* Get the size of data (in bytes) this plugin will send to copy a previous submission.
@ -114,7 +120,7 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param plugin The plugin object.
* @return The size (or promise resolved with size).
*/
getSizeForCopy?(assign: any, plugin: any): number | Promise<number>;
getSizeForCopy?(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin): number | Promise<number>;
/**
* Get the size of data (in bytes) this plugin will send to add or edit a submission.
@ -125,7 +131,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param inputData Data entered by the user for the submission.
* @return The size (or promise resolved with size).
*/
getSizeForEdit?(assign: any, submission: any, plugin: any, inputData: any): number | Promise<number>;
getSizeForEdit?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): number | Promise<number>;
/**
* Check if the submission data has changed for this plugin.
@ -136,7 +143,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param inputData Data entered by the user for the submission.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged?(assign: any, submission: any, plugin: any, inputData: any): boolean | Promise<boolean>;
hasDataChanged?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): boolean | Promise<boolean>;
/**
* Whether or not the handler is enabled for edit on a site level.
@ -155,7 +163,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch?(assign: any, submission: any, plugin: any, siteId?: string): Promise<any>;
prefetch?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any>;
/**
* Prepare and add to pluginData the data to send to the server based on the input data.
@ -170,8 +179,9 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSubmissionData?(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): void | Promise<any>;
prepareSubmissionData?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): void | Promise<any>;
/**
* Prepare and add to pluginData the data to send to the server based on the offline data stored.
@ -185,8 +195,8 @@ export interface AddonModAssignSubmissionHandler extends CoreDelegateHandler {
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSyncData?(assign: any, submission: any, plugin: any, offlineData: any, pluginData: any, siteId?: string)
: void | Promise<any>;
prepareSyncData?(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, pluginData: any, siteId?: string): void | Promise<any>;
}
/**
@ -210,7 +220,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param plugin The plugin object.
* @return Promise resolved with boolean: whether it can be edited in offline.
*/
canPluginEditOffline(assign: any, submission: any, plugin: any): Promise<boolean> {
canPluginEditOffline(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin): Promise<boolean> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'canEditOffline', [assign, submission, plugin]));
}
@ -222,7 +233,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param plugin The plugin object.
* @param inputData Data entered by the user for the submission.
*/
clearTmpData(assign: any, submission: any, plugin: any, inputData: any): void {
clearTmpData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): void {
return this.executeFunctionOnEnabled(plugin.type, 'clearTmpData', [assign, submission, plugin, inputData]);
}
@ -236,7 +248,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when the data has been copied.
*/
copyPluginSubmissionData(assign: any, plugin: any, pluginData: any, userId?: number, siteId?: string): void | Promise<any> {
copyPluginSubmissionData(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin, pluginData: any,
userId?: number, siteId?: string): void | Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'copySubmissionData',
[assign, plugin, pluginData, userId, siteId]));
}
@ -251,7 +264,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
deletePluginOfflineData(assign: any, submission: any, plugin: any, offlineData: any, siteId?: string): Promise<any> {
deletePluginOfflineData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'deleteOfflineData',
[assign, submission, plugin, offlineData, siteId]));
}
@ -264,7 +278,7 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param edit Whether the user is editing.
* @return Promise resolved with the component to use, undefined if not found.
*/
getComponentForPlugin(injector: Injector, plugin: any, edit?: boolean): Promise<any> {
getComponentForPlugin(injector: Injector, plugin: AddonModAssignPlugin, edit?: boolean): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getComponent', [injector, plugin, edit]));
}
@ -278,7 +292,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved with the files.
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any[]> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getPluginFiles', [assign, submission, plugin, siteId]));
}
@ -288,7 +303,7 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param plugin Plugin to get the name for.
* @return Human readable name.
*/
getPluginName(plugin: any): string {
getPluginName(plugin: AddonModAssignPlugin): string {
return this.executeFunctionOnEnabled(plugin.type, 'getPluginName', [plugin]);
}
@ -299,7 +314,7 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param plugin The plugin object.
* @return Promise resolved with size.
*/
getPluginSizeForCopy(assign: any, plugin: any): Promise<number> {
getPluginSizeForCopy(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin): Promise<number> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getSizeForCopy', [assign, plugin]));
}
@ -312,7 +327,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param inputData Data entered by the user for the submission.
* @return Promise resolved with size.
*/
getPluginSizeForEdit(assign: any, submission: any, plugin: any, inputData: any): Promise<number> {
getPluginSizeForEdit(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): Promise<number> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'getSizeForEdit',
[assign, submission, plugin, inputData]));
}
@ -326,7 +342,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param inputData Data entered by the user for the submission.
* @return Promise resolved with true if data has changed, resolved with false otherwise.
*/
hasPluginDataChanged(assign: any, submission: any, plugin: any, inputData: any): Promise<boolean> {
hasPluginDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): Promise<boolean> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'hasDataChanged',
[assign, submission, plugin, inputData]));
}
@ -360,7 +377,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise<any> {
prefetch(assign: AddonModAssignAssign, submission: AddonModAssignSubmission, plugin: AddonModAssignPlugin,
siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'prefetch', [assign, submission, plugin, siteId]));
}
@ -377,8 +395,9 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when data has been gathered.
*/
preparePluginSubmissionData(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): Promise<any> {
preparePluginSubmissionData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, pluginData: any, offline?: boolean, userId?: number,
siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'prepareSubmissionData',
[assign, submission, plugin, inputData, pluginData, offline, userId, siteId]));
@ -395,8 +414,8 @@ export class AddonModAssignSubmissionDelegate extends CoreDelegate {
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when data has been gathered.
*/
preparePluginSyncData(assign: any, submission: any, plugin: any, offlineData: any, pluginData: any, siteId?: string)
: Promise<any> {
preparePluginSyncData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, pluginData: any, siteId?: string): Promise<any> {
return Promise.resolve(this.executeFunctionOnEnabled(plugin.type, 'prepareSyncData',
[assign, submission, plugin, offlineData, pluginData, siteId]));

View File

@ -17,6 +17,9 @@ import { Injectable, Injector } from '@angular/core';
import { CoreCommentsProvider } from '@core/comments/providers/comments';
import { AddonModAssignSubmissionHandler } from '../../../providers/submission-delegate';
import { AddonModAssignSubmissionCommentsComponent } from '../component/comments';
import {
AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../../providers/assign';
/**
* Handler for comments submission plugin.
@ -38,7 +41,8 @@ export class AddonModAssignSubmissionCommentsHandler implements AddonModAssignSu
* @param plugin The plugin object.
* @return Boolean or promise resolved with boolean: whether it can be edited in offline.
*/
canEditOffline(assign: any, submission: any, plugin: any): boolean | Promise<boolean> {
canEditOffline(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin): boolean | Promise<boolean> {
// This plugin is read only, but return true to prevent blocking the edition.
return true;
}
@ -52,7 +56,7 @@ export class AddonModAssignSubmissionCommentsHandler implements AddonModAssignSu
* @param edit Whether the user is editing.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin, edit?: boolean): any | Promise<any> {
return edit ? undefined : AddonModAssignSubmissionCommentsComponent;
}
@ -84,7 +88,9 @@ export class AddonModAssignSubmissionCommentsHandler implements AddonModAssignSu
* @param siteId Site ID. If not defined, current site.
* @return Promise resolved when done.
*/
prefetch(assign: any, submission: any, plugin: any, siteId?: string): Promise<any> {
prefetch(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): Promise<any> {
return this.commentsProvider.getComments('module', assign.cmid, 'assignsubmission_comments', submission.id,
'submission_comments', 0, siteId).catch(() => {
// Fail silently (Moodle < 3.1.1, 3.2)

View File

@ -21,7 +21,9 @@ import { CoreSitesProvider } from '@providers/sites';
import { CoreWSProvider } from '@providers/ws';
import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreFileUploaderProvider } from '@core/fileuploader/providers/fileuploader';
import { AddonModAssignProvider } from '../../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline';
import { AddonModAssignHelperProvider } from '../../../providers/helper';
import { AddonModAssignSubmissionHandler } from '../../../providers/submission-delegate';
@ -53,7 +55,8 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @return Boolean or promise resolved with boolean: whether it can be edited in offline.
*/
canEditOffline(assign: any, submission: any, plugin: any): boolean | Promise<boolean> {
canEditOffline(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin): boolean | Promise<boolean> {
// This plugin doesn't use Moodle filters, it can be edited in offline.
return true;
}
@ -66,7 +69,8 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @param inputData Data entered by the user for the submission.
*/
clearTmpData(assign: any, submission: any, plugin: any, inputData: any): void {
clearTmpData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): void {
const files = this.fileSessionProvider.getFiles(AddonModAssignProvider.COMPONENT, assign.id);
// Clear the files in session for this assign.
@ -87,7 +91,9 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
copySubmissionData(assign: any, plugin: any, pluginData: any, userId?: number, siteId?: string): void | Promise<any> {
copySubmissionData(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin, pluginData: any,
userId?: number, siteId?: string): void | Promise<any> {
// We need to re-upload all the existing files.
const files = this.assignProvider.getSubmissionPluginAttachments(plugin);
@ -105,7 +111,7 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param edit Whether the user is editing.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin, edit?: boolean): any | Promise<any> {
return AddonModAssignSubmissionFileComponent;
}
@ -119,7 +125,9 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
deleteOfflineData(assign: any, submission: any, plugin: any, offlineData: any, siteId?: string): void | Promise<any> {
deleteOfflineData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, siteId?: string): void | Promise<any> {
return this.assignHelper.deleteStoredSubmissionFiles(assign.id, AddonModAssignSubmissionFileHandler.FOLDER_NAME,
submission.userid, siteId).catch(() => {
// Ignore errors, maybe the folder doesn't exist.
@ -136,7 +144,8 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return this.assignProvider.getSubmissionPluginAttachments(plugin);
}
@ -147,7 +156,7 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param plugin The plugin object.
* @return The size (or promise resolved with size).
*/
getSizeForCopy(assign: any, plugin: any): number | Promise<number> {
getSizeForCopy(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin): number | Promise<number> {
const files = this.assignProvider.getSubmissionPluginAttachments(plugin),
promises = [];
let totalSize = 0;
@ -177,7 +186,8 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param inputData Data entered by the user for the submission.
* @return The size (or promise resolved with size).
*/
getSizeForEdit(assign: any, submission: any, plugin: any, inputData: any): number | Promise<number> {
getSizeForEdit(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): number | Promise<number> {
const siteId = this.sitesProvider.getCurrentSiteId();
// Check if there's any change.
@ -232,7 +242,9 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param inputData Data entered by the user for the submission.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged(assign: any, submission: any, plugin: any, inputData: any): boolean | Promise<boolean> {
hasDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): boolean | Promise<boolean> {
// Check if there's any offline data.
return this.assignOfflineProvider.getSubmission(assign.id, submission.userid).catch(() => {
// No offline data found.
@ -299,7 +311,8 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSubmissionData(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean,
prepareSubmissionData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): void | Promise<any> {
if (this.hasDataChanged(assign, submission, plugin, inputData)) {
@ -330,8 +343,8 @@ export class AddonModAssignSubmissionFileHandler implements AddonModAssignSubmis
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSyncData(assign: any, submission: any, plugin: any, offlineData: any, pluginData: any, siteId?: string)
: void | Promise<any> {
prepareSyncData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, pluginData: any, siteId?: string): void | Promise<any> {
const filesData = offlineData && offlineData.plugindata && offlineData.plugindata.files_filemanager;
if (filesData) {

View File

@ -10,7 +10,7 @@
<!-- Edit -->
<div *ngIf="edit && loaded">
<ion-item-divider text-wrap>{{ plugin.name }}</ion-item-divider>
<ion-item text-wrap *ngIf="configs.wordlimitenabled && words >= 0">
<ion-item text-wrap *ngIf="wordLimitEnabled && words >= 0">
<h2>{{ 'addon.mod_assign.wordlimit' | translate }}</h2>
<p>{{ 'core.numwords' | translate: {'$a': words + ' / ' + configs.wordlimit} }}</p>
</ion-item>

View File

@ -34,6 +34,7 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
component = AddonModAssignProvider.COMPONENT;
text: string;
loaded: boolean;
wordLimitEnabled: boolean;
protected wordCountTimeout: any;
protected element: HTMLElement;
@ -61,9 +62,7 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
// No offline data found, return online text.
return this.assignProvider.getSubmissionPluginText(this.plugin);
}).then((text) => {
// We receive them as strings, convert to int.
this.configs.wordlimit = parseInt(this.configs.wordlimit, 10);
this.configs.wordlimitenabled = parseInt(this.configs.wordlimitenabled, 10);
this.wordLimitEnabled = !!parseInt(this.configs.wordlimitenabled, 10);
// Set the text.
this.text = text;
@ -85,7 +84,7 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
}
// Calculate initial words.
if (this.configs.wordlimitenabled) {
if (this.wordLimitEnabled) {
this.words = this.textUtils.countWords(text);
}
}).finally(() => {
@ -100,7 +99,7 @@ export class AddonModAssignSubmissionOnlineTextComponent extends AddonModAssignS
*/
onChange(text: string): void {
// Count words if needed.
if (this.configs.wordlimitenabled) {
if (this.wordLimitEnabled) {
// Cancel previous wait.
clearTimeout(this.wordCountTimeout);

View File

@ -18,7 +18,9 @@ import { TranslateService } from '@ngx-translate/core';
import { CoreSitesProvider } from '@providers/sites';
import { CoreWSProvider } from '@providers/ws';
import { CoreTextUtilsProvider } from '@providers/utils/text';
import { AddonModAssignProvider } from '../../../providers/assign';
import {
AddonModAssignProvider, AddonModAssignAssign, AddonModAssignSubmission, AddonModAssignPlugin
} from '../../../providers/assign';
import { AddonModAssignOfflineProvider } from '../../../providers/assign-offline';
import { AddonModAssignHelperProvider } from '../../../providers/helper';
import { AddonModAssignSubmissionHandler } from '../../../providers/submission-delegate';
@ -46,7 +48,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param plugin The plugin object.
* @return Boolean or promise resolved with boolean: whether it can be edited in offline.
*/
canEditOffline(assign: any, submission: any, plugin: any): boolean | Promise<boolean> {
canEditOffline(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin): boolean | Promise<boolean> {
// This plugin uses Moodle filters, it cannot be edited in offline.
return false;
}
@ -62,7 +65,9 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
copySubmissionData(assign: any, plugin: any, pluginData: any, userId?: number, siteId?: string): void | Promise<any> {
copySubmissionData(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin, pluginData: any,
userId?: number, siteId?: string): void | Promise<any> {
const text = this.assignProvider.getSubmissionPluginText(plugin, true),
files = this.assignProvider.getSubmissionPluginAttachments(plugin);
let promise;
@ -93,7 +98,7 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param edit Whether the user is editing.
* @return The component (or promise resolved with component) to use, undefined if not found.
*/
getComponent(injector: Injector, plugin: any, edit?: boolean): any | Promise<any> {
getComponent(injector: Injector, plugin: AddonModAssignPlugin, edit?: boolean): any | Promise<any> {
return AddonModAssignSubmissionOnlineTextComponent;
}
@ -107,7 +112,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param siteId Site ID. If not defined, current site.
* @return The files (or promise resolved with the files).
*/
getPluginFiles(assign: any, submission: any, plugin: any, siteId?: string): any[] | Promise<any[]> {
getPluginFiles(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, siteId?: string): any[] | Promise<any[]> {
return this.assignProvider.getSubmissionPluginAttachments(plugin);
}
@ -118,7 +124,7 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param plugin The plugin object.
* @return The size (or promise resolved with size).
*/
getSizeForCopy(assign: any, plugin: any): number | Promise<number> {
getSizeForCopy(assign: AddonModAssignAssign, plugin: AddonModAssignPlugin): number | Promise<number> {
const text = this.assignProvider.getSubmissionPluginText(plugin, true),
files = this.assignProvider.getSubmissionPluginAttachments(plugin),
promises = [];
@ -153,7 +159,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param inputData Data entered by the user for the submission.
* @return The size (or promise resolved with size).
*/
getSizeForEdit(assign: any, submission: any, plugin: any, inputData: any): number | Promise<number> {
getSizeForEdit(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): number | Promise<number> {
const text = this.assignProvider.getSubmissionPluginText(plugin, true);
return text.length;
@ -182,7 +189,9 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param inputData Data entered by the user for the submission.
* @return Boolean (or promise resolved with boolean): whether the data has changed.
*/
hasDataChanged(assign: any, submission: any, plugin: any, inputData: any): boolean | Promise<boolean> {
hasDataChanged(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any): boolean | Promise<boolean> {
// Get the original text from plugin or offline.
return this.assignOfflineProvider.getSubmission(assign.id, submission.userid).catch(() => {
// No offline data found.
@ -234,7 +243,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSubmissionData(assign: any, submission: any, plugin: any, inputData: any, pluginData: any, offline?: boolean,
prepareSubmissionData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, inputData: any, pluginData: any, offline?: boolean,
userId?: number, siteId?: string): void | Promise<any> {
let text = this.getTextToSubmit(plugin, inputData);
@ -274,8 +284,8 @@ export class AddonModAssignSubmissionOnlineTextHandler implements AddonModAssign
* @param siteId Site ID. If not defined, current site.
* @return If the function is async, it should return a Promise resolved when done.
*/
prepareSyncData(assign: any, submission: any, plugin: any, offlineData: any, pluginData: any, siteId?: string)
: void | Promise<any> {
prepareSyncData(assign: AddonModAssignAssign, submission: AddonModAssignSubmission,
plugin: AddonModAssignPlugin, offlineData: any, pluginData: any, siteId?: string): void | Promise<any> {
const textData = offlineData && offlineData.plugindata && offlineData.plugindata.onlinetext_editor;
if (textData) {