diff --git a/src/addon/mod/workshop/components/index/index.ts b/src/addon/mod/workshop/components/index/index.ts index ed7555163..4c626f1bd 100644 --- a/src/addon/mod/workshop/components/index/index.ts +++ b/src/addon/mod/workshop/components/index/index.ts @@ -67,6 +67,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity protected obsSubmissionChanged: any; protected obsAssessmentSaved: any; protected appResumeSubscription: any; + protected syncObserver: any; constructor(injector: Injector, private workshopProvider: AddonModWorkshopProvider, @Optional() content: Content, private workshopOffline: AddonModWorkshopOfflineProvider, private groupsProvider: CoreGroupsProvider, @@ -92,6 +93,12 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity this.loaded = false; this.refreshContent(true, false); }); + + // Refresh workshop on sync. + this.syncObserver = this.eventsProvider.on(AddonModWorkshopSyncProvider.AUTO_SYNCED, (data) => { + // Update just when all database is synced. + this.eventReceived(data); + }, this.siteId); } /** @@ -300,7 +307,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity module: this.module, access: this.access, courseId: this.courseId, - submission: this.submission + submissionId: this.submission && this.submission.id }; this.navCtrl.push('AddonModWorkshopEditSubmissionPage', params); diff --git a/src/addon/mod/workshop/lang/en.json b/src/addon/mod/workshop/lang/en.json index 57243db4a..ff7cd8d55 100644 --- a/src/addon/mod/workshop/lang/en.json +++ b/src/addon/mod/workshop/lang/en.json @@ -42,6 +42,7 @@ "submissiongrade": "Grade for submission", "submissiongradeof": "Grade for submission (of {{$a}})", "submissionrequiredcontent": "You need to enter some text or add a file.", + "submissionrequiredtitle": "You need to enter a title.", "submissionsreport": "Workshop submissions report", "submissiontitle": "Title", "switchphase10": "Switch to the setup phase", diff --git a/src/addon/mod/workshop/pages/assessment/assessment.html b/src/addon/mod/workshop/pages/assessment/assessment.html index 2a36c1cc9..704c9671a 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.html +++ b/src/addon/mod/workshop/pages/assessment/assessment.html @@ -20,14 +20,13 @@

{{profile.fullname}}

- -

+

{{ 'addon.mod_workshop.submissiongradeof' | translate:{$a: workshop.grade } }}: {{assessment.grade}}

-

+

{{ 'addon.mod_workshop.gradinggradeof' | translate:{$a: workshop.gradinggrade } }}: {{assessment.gradinggrade}}

-

+

{{ 'addon.mod_workshop.gradinggradeover' | translate }}: {{assessment.gradinggradeover}}

@@ -38,7 +37,7 @@ - +

diff --git a/src/addon/mod/workshop/pages/assessment/assessment.ts b/src/addon/mod/workshop/pages/assessment/assessment.ts index db38a5f5e..208734b40 100644 --- a/src/addon/mod/workshop/pages/assessment/assessment.ts +++ b/src/addon/mod/workshop/pages/assessment/assessment.ts @@ -43,18 +43,21 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { submission: any; profile: any; courseId: number; - - access: any = {}; + access: any; assessmentId: number; evaluating = false; loaded = false; showGrade: any; evaluateForm: FormGroup; maxGrade: number; - workshop: any = {}; + workshop: any; strategy: any; title: string; - evaluate: any; + evaluate = { + text: '', + grade: -1, + weight: 1 + }; weights = []; evaluateByProfile: any; evaluationGrades: any; @@ -76,10 +79,10 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { protected domUtils: CoreDomUtilsProvider, protected gradesHelper: CoreGradesHelperProvider, protected userProvider: CoreUserProvider) { - this.assessment = navParams.get('assessment') || {}; + this.assessment = navParams.get('assessment'); this.submission = navParams.get('submission') || {}; - this.profile = navParams.get('profile') || {}; - this.courseId = navParams.get('courseId') || null; + this.profile = navParams.get('profile'); + this.courseId = navParams.get('courseId'); this.assessmentId = this.assessment.assessmentid || this.assessment.id; this.workshopId = this.submission.workshopid || null; @@ -96,7 +99,7 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { // Refresh workshop on sync. this.syncObserver = this.eventsProvider.on(AddonModWorkshopSyncProvider.AUTO_SYNCED, (data) => { // Update just when all database is synced. - if (this.workshopId === data.workshopid) { + if (this.workshopId === data.workshopId) { this.loaded = false; this.refreshAllData(); } @@ -166,10 +169,8 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { let defaultGrade, promise; this.assessment = this.workshopHelper.realGradeValue(this.workshop, assessment); - this.evaluate = { - weight: this.assessment.weight, - text: this.assessment.feedbackreviewer - }; + this.evaluate.text = this.assessment.feedbackreviewer || ''; + this.evaluate.weight = this.assessment.weight; if (this.evaluating) { if (accessData.canallocate) { @@ -195,14 +196,14 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { this.hasOffline = true; this.evaluate.weight = offlineAssess.weight; if (accessData.canoverridegrades) { - this.evaluate.text = offlineAssess.feedbacktext; + this.evaluate.text = offlineAssess.feedbacktext || ''; this.evaluate.grade = offlineAssess.gradinggradeover || -1; } }).catch(() => { this.hasOffline = false; // No offline, load online. if (accessData.canoverridegrades) { - this.evaluate.text = this.assessment.feedbackreviewer; + this.evaluate.text = this.assessment.feedbackreviewer || ''; this.evaluate.grade = this.assessment.gradinggradeover || -1; } }); @@ -259,7 +260,7 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { return true; } - if (this.access.canoverridegrades) { + if (this.access && this.access.canoverridegrades) { if (this.originalEvaluation.text != inputData.text) { return true; } @@ -335,7 +336,6 @@ export class AddonModWorkshopAssessmentPage implements OnInit, OnDestroy { // Check if rich text editor is enabled or not. return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { const inputData = this.evaluateForm.value; - inputData.grade = inputData.grade >= 0 ? inputData.grade : ''; if (!rteEnabled) { // Rich text editor not enabled, add some HTML to the message if needed. diff --git a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts index fd83fa272..66fc4d69a 100644 --- a/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts +++ b/src/addon/mod/workshop/pages/edit-submission/edit-submission.ts @@ -40,7 +40,12 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { module: any; courseId: number; access: any; - submission: any; + submission = { + id: 0, + title: '', + content: '', + attachmentfiles: [], + }; loaded = false; component = AddonModWorkshopProvider.COMPONENT; @@ -48,6 +53,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { editForm: FormGroup; // The form group. protected workshopId: number; + protected submissionId: number; protected userId: number; protected originalData: any = {}; protected hasOffline = false; @@ -66,7 +72,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { this.module = navParams.get('module'); this.courseId = navParams.get('courseId'); this.access = navParams.get('access'); - this.submission = navParams.get('submission') || {}; + this.submissionId = navParams.get('submissionId'); this.workshopId = this.module.instance; this.componentId = this.module.id; @@ -127,12 +133,11 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { return this.workshopProvider.getWorkshop(this.courseId, this.module.id).then((workshopData) => { this.workshop = workshopData; - if (this.submission && this.submission.id > 0) { + if (this.submissionId > 0) { this.editing = true; - return this.workshopHelper.getSubmissionById(this.workshopId, this.submission.id).then((submissionData) => { + return this.workshopHelper.getSubmissionById(this.workshopId, this.submissionId).then((submissionData) => { this.submission = submissionData; - this.submission.text = submissionData.content; const canEdit = (this.userId == submissionData.authorid && this.access.cansubmit && this.access.modifyingsubmissionallowed); @@ -155,19 +160,15 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { if (submissionsActions && submissionsActions.length) { this.hasOffline = true; const actions = this.workshopHelper.filterSubmissionActions(submissionsActions, this.editing ? - this.submission.id : false); + this.submission.id : 0); - return this.workshopHelper.applyOfflineData(this.submission, actions).then((offlineSubmission) => { - this.submission.title = offlineSubmission.title; - this.submission.text = offlineSubmission.content; - this.submission.attachmentfiles = offlineSubmission.attachmentfiles; - }); + return this.workshopHelper.applyOfflineData(this.submission, actions); } else { this.hasOffline = false; } }).finally(() => { this.originalData.title = this.submission.title; - this.originalData.content = this.submission.text; + this.originalData.content = this.submission.content; this.originalData.attachmentfiles = []; this.submission.attachmentfiles.forEach((file) => { @@ -295,12 +296,12 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { const inputData = this.getInputData(); if (!inputData.title) { - this.domUtils.showAlert('core.notice', 'core.requireduserdatamissing'); + this.domUtils.showAlertTranslated('core.notice', 'addon.mod_workshop.submissionrequiredtitle'); return Promise.reject(null); } if (!inputData.content) { - this.domUtils.showAlert('core.notice', 'addon.mod_workshop.submissionrequiredcontent'); + this.domUtils.showAlertTranslated('core.notice', 'addon.mod_workshop.submissionrequiredcontent'); return Promise.reject(null); } @@ -309,13 +310,11 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { saveOffline = false; const modal = this.domUtils.showModalLoading('core.sending', true), - submissionId = this.submission && (this.submission.id || this.submission.submissionid) || false; + submissionId = this.submission.id; // Check if rich text editor is enabled or not. return this.domUtils.isRichTextEditorEnabled().then((rteEnabled) => { - if (rteEnabled) { - inputData.content = this.textUtils.restorePluginfileUrls(inputData.content, this.submission.inlinefiles); - } else { + if (!rteEnabled) { // Rich text editor not enabled, add some HTML to the message if needed. inputData.content = this.textUtils.formatHtmlLines(inputData.content); } @@ -323,14 +322,14 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy { // Upload attachments first if any. allowOffline = !inputData.attachmentfiles.length; - return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, submissionId, inputData.attachmentfiles, + return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, inputData.attachmentfiles, this.editing, saveOffline).catch(() => { // Cannot upload them in online, save them in offline. saveOffline = true; allowOffline = true; - return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, submissionId, inputData.attachmentfiles, - this.editing, saveOffline); + return this.workshopHelper.uploadOrStoreSubmissionFiles(this.workshopId, this.submission.id, + inputData.attachmentfiles, this.editing, saveOffline); }); }).then((attachmentsId) => { if (this.editing) { diff --git a/src/addon/mod/workshop/pages/submission/submission.html b/src/addon/mod/workshop/pages/submission/submission.html index 851a1e531..2a48dbbc9 100644 --- a/src/addon/mod/workshop/pages/submission/submission.html +++ b/src/addon/mod/workshop/pages/submission/submission.html @@ -93,7 +93,7 @@
- + diff --git a/src/addon/mod/workshop/pages/submission/submission.ts b/src/addon/mod/workshop/pages/submission/submission.ts index d203dcec4..5e8b24bc4 100644 --- a/src/addon/mod/workshop/pages/submission/submission.ts +++ b/src/addon/mod/workshop/pages/submission/submission.ts @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, OnInit, OnDestroy, Optional } from '@angular/core'; +import { Component, OnInit, OnDestroy, Optional, ViewChild } from '@angular/core'; import { Content, IonicPage, NavParams, NavController } from 'ionic-angular'; import { FormGroup, FormBuilder } from '@angular/forms'; import { TranslateService } from '@ngx-translate/core'; @@ -24,6 +24,7 @@ import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreUserProvider } from '@core/user/providers/user'; import { CoreGradesHelperProvider } from '@core/grades/providers/helper'; +import { AddonModWorkshopAssessmentStrategyComponent } from '../../components/assessment-strategy/assessment-strategy'; import { AddonModWorkshopProvider } from '../../providers/workshop'; import { AddonModWorkshopHelperProvider } from '../../providers/helper'; import { AddonModWorkshopOfflineProvider } from '../../providers/offline'; @@ -39,6 +40,8 @@ import { AddonModWorkshopSyncProvider } from '../../providers/sync'; }) export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { + @ViewChild(AddonModWorkshopAssessmentStrategyComponent) assessmentStrategy: AddonModWorkshopAssessmentStrategyComponent; + module: any; workshop: any; access: any; @@ -69,7 +72,11 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { protected currentUserId: number; protected userId: number; protected siteId: string; - protected originalEvaluation: any = {}; + protected originalEvaluation = { + published: '', + text: '', + grade: '' + }; protected hasOffline = false; protected component = AddonModWorkshopProvider.COMPONENT; protected forceLeave = false; @@ -89,7 +96,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { this.access = navParams.get('access'); this.courseId = navParams.get('courseId'); this.profile = navParams.get('profile'); - this.submissionInfo = navParams.get('submission'); + this.submissionInfo = navParams.get('submission') || {}; this.assessment = navParams.get('assessment') || null; this.title = this.module.name; @@ -135,14 +142,11 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { * @return {boolean|Promise} Resolved if we can leave it, rejected if not. */ ionViewCanLeave(): boolean | Promise { - if (this.forceLeave || !this.canAddFeedback) { + const assessmentHasChanged = this.assessmentStrategy && this.assessmentStrategy.hasDataChanged(); + if (this.forceLeave || (!this.hasEvaluationChanged() && !assessmentHasChanged)) { return true; } - if (!this.hasEvaluationChanged()) { - return Promise.resolve(); - } - // Show confirmation if some data has been modified. return this.domUtils.showConfirm(this.translate.instant('core.confirmcanceledit')); } @@ -155,7 +159,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { module: module, access: this.access, courseid: this.courseId, - submission: this.submission + submissionId: this.submission.id }; this.navCtrl.push('AddonModWorkshopEditSubmissionPage', params); @@ -167,7 +171,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { * @param {any} data Event data received. */ protected eventReceived(data: any): void { - if (this.workshopId === data.workshopid) { + if (this.workshopId === data.workshopId) { this.content && this.content.scrollToTop(); this.loaded = false; @@ -185,6 +189,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { const promises = []; this.submission = submissionData; + this.submission.attachmentfiles = submissionData.attachmentfiles || []; this.submission.submissiongrade = this.submissionInfo && this.submissionInfo.submissiongrade; this.submission.gradinggrade = this.submissionInfo && this.submissionInfo.gradinggrade; this.submission.submissiongradeover = this.submissionInfo && this.submissionInfo.submissiongradeover; @@ -390,8 +395,16 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy { * Save the assessment. */ saveAssessment(): void { - // Call trigger to save. - this.eventsProvider.trigger(AddonModWorkshopProvider.ASSESSMENT_SAVE, undefined, this.siteId); + if (this.assessmentStrategy && this.assessmentStrategy.hasDataChanged()) { + this.assessmentStrategy.saveAssessment().then(() => { + this.forceLeavePage(); + }).catch(() => { + // Error, stay on the page. + }); + } else { + // Nothing to save, just go back. + this.forceLeavePage(); + } } /** diff --git a/src/addon/mod/workshop/providers/workshop.ts b/src/addon/mod/workshop/providers/workshop.ts index ca1889686..cb7757834 100644 --- a/src/addon/mod/workshop/providers/workshop.ts +++ b/src/addon/mod/workshop/providers/workshop.ts @@ -36,7 +36,6 @@ export class AddonModWorkshopProvider { static EXAMPLES_BEFORE_ASSESSMENT: 2; static SUBMISSION_CHANGED = 'addon_mod_workshop_submission_changed'; - static ASSESSMENT_SAVE = 'addon_mod_workshop_assessment_save'; static ASSESSMENT_SAVED = 'addon_mod_workshop_assessment_saved'; static ASSESSMENT_INVALIDATED = 'addon_mod_workshop_assessment_invalidated';