254 lines
8.6 KiB
TypeScript
254 lines
8.6 KiB
TypeScript
// (C) Copyright 2015 Moodle Pty Ltd.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import { Component, OnInit, Optional } from '@angular/core';
|
|
import { CoreError } from '@classes/errors/error';
|
|
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
|
import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component';
|
|
import { CoreCourseContentsPage } from '@features/course/pages/contents/contents';
|
|
import { IonContent } from '@ionic/angular';
|
|
import { CoreSites } from '@services/sites';
|
|
import { CoreDomUtils } from '@services/utils/dom';
|
|
import { CoreText } from '@singletons/text';
|
|
import { Translate } from '@singletons';
|
|
import { CoreEvents } from '@singletons/events';
|
|
import { getPrefetchHandlerInstance } from '../../services/handlers/prefetch';
|
|
import {
|
|
AddonModSurveySurvey,
|
|
AddonModSurvey,
|
|
AddonModSurveySubmitAnswerData,
|
|
} from '../../services/survey';
|
|
import { AddonModSurveyHelper, AddonModSurveyQuestionFormatted } from '../../services/survey-helper';
|
|
import { AddonModSurveyOffline } from '../../services/survey-offline';
|
|
import {
|
|
AddonModSurveyAutoSyncData,
|
|
AddonModSurveySync,
|
|
AddonModSurveySyncResult,
|
|
} from '../../services/survey-sync';
|
|
import { CoreUtils } from '@services/utils/utils';
|
|
import { ADDON_MOD_SURVEY_AUTO_SYNCED, ADDON_MOD_SURVEY_COMPONENT } from '../../constants';
|
|
import { CoreLoadings } from '@services/loadings';
|
|
|
|
/**
|
|
* Component that displays a survey.
|
|
*/
|
|
@Component({
|
|
selector: 'addon-mod-survey-index',
|
|
templateUrl: 'addon-mod-survey-index.html',
|
|
styleUrl: 'index.scss',
|
|
})
|
|
export class AddonModSurveyIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit {
|
|
|
|
component = ADDON_MOD_SURVEY_COMPONENT;
|
|
pluginName = 'survey';
|
|
|
|
survey?: AddonModSurveySurvey;
|
|
questions: AddonModSurveyQuestionFormatted[] = [];
|
|
answers: Record<string, string> = {};
|
|
|
|
protected currentUserId?: number;
|
|
protected syncEventName = ADDON_MOD_SURVEY_AUTO_SYNCED;
|
|
|
|
constructor(
|
|
protected content?: IonContent,
|
|
@Optional() courseContentsPage?: CoreCourseContentsPage,
|
|
) {
|
|
super('AddonModSurveyIndexComponent', content, courseContentsPage);
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
async ngOnInit(): Promise<void> {
|
|
super.ngOnInit();
|
|
|
|
this.currentUserId = CoreSites.getCurrentSiteUserId();
|
|
|
|
await this.loadContent(false, true);
|
|
}
|
|
|
|
/**
|
|
* Perform the invalidate content function.
|
|
*
|
|
* @returns Resolved when done.
|
|
*/
|
|
protected async invalidateContent(): Promise<void> {
|
|
const promises: Promise<void>[] = [];
|
|
|
|
promises.push(AddonModSurvey.invalidateSurveyData(this.courseId));
|
|
if (this.survey) {
|
|
promises.push(AddonModSurvey.invalidateQuestions(this.survey.id));
|
|
}
|
|
|
|
await Promise.all(promises);
|
|
}
|
|
|
|
/**
|
|
* Compares sync event data with current data to check if refresh content is needed.
|
|
*
|
|
* @param syncEventData Data receiven on sync observer.
|
|
* @returns True if refresh is needed, false otherwise.
|
|
*/
|
|
protected isRefreshSyncNeeded(syncEventData: AddonModSurveyAutoSyncData): boolean {
|
|
if (this.survey && syncEventData.surveyId == this.survey.id && syncEventData.userId == this.currentUserId) {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected async fetchContent(refresh?: boolean, sync = false, showErrors = false): Promise<void> {
|
|
this.survey = await AddonModSurvey.getSurvey(this.courseId, this.module.id);
|
|
|
|
this.description = this.survey.intro;
|
|
this.dataRetrieved.emit(this.survey);
|
|
|
|
if (sync) {
|
|
// Try to synchronize the survey.
|
|
const updated = await this.syncActivity(showErrors);
|
|
if (updated) {
|
|
// Answers were sent, update the survey.
|
|
this.survey = await AddonModSurvey.getSurvey(this.courseId, this.module.id);
|
|
}
|
|
}
|
|
|
|
// Check if there are answers stored in offline.
|
|
this.hasOffline = this.survey.surveydone
|
|
? false
|
|
: await AddonModSurveyOffline.hasAnswers(this.survey.id);
|
|
|
|
if (!this.survey.surveydone && !this.hasOffline) {
|
|
await this.fetchQuestions(this.survey.id);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Convenience function to get survey questions.
|
|
*
|
|
* @param surveyId Survey Id.
|
|
* @returns Promise resolved when done.
|
|
*/
|
|
protected async fetchQuestions(surveyId: number): Promise<void> {
|
|
const questions = await AddonModSurvey.getQuestions(surveyId, { cmId: this.module.id });
|
|
|
|
this.questions = AddonModSurveyHelper.formatQuestions(questions);
|
|
|
|
// Init answers object.
|
|
this.questions.forEach((question) => {
|
|
if (question.name) {
|
|
const isTextArea = question.multiArray && question.multiArray.length === 0 && question.type === 0;
|
|
this.answers[question.name] = question.required ? '-1' : (isTextArea ? '' : '0');
|
|
}
|
|
|
|
if (question.multiArray && !question.multiArray.length && question.parent === 0 && question.type > 0) {
|
|
// Options shown in a select. Remove all HTML.
|
|
question.optionsArray = question.optionsArray?.map((option) => CoreText.cleanTags(option));
|
|
}
|
|
});
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected async logActivity(): Promise<void> {
|
|
if (!this.survey) {
|
|
return; // Shouldn't happen.
|
|
}
|
|
|
|
await CoreUtils.ignoreErrors(AddonModSurvey.logView(this.survey.id));
|
|
|
|
this.analyticsLogEvent('mod_survey_view_survey');
|
|
}
|
|
|
|
/**
|
|
* Check if answers are valid to be submitted.
|
|
*
|
|
* @returns If answers are valid
|
|
*/
|
|
isValidResponse(): boolean {
|
|
return !this.questions.some((question) => question.required && question.name &&
|
|
(question.type === 0 ? this.answers[question.name] == '' : parseInt(this.answers[question.name], 10) === -1));
|
|
}
|
|
|
|
/**
|
|
* Save options selected.
|
|
*/
|
|
async submit(): Promise<void> {
|
|
if (!this.survey) {
|
|
return;
|
|
}
|
|
|
|
let modal: CoreIonLoadingElement | undefined;
|
|
|
|
try {
|
|
await CoreDomUtils.showConfirm(Translate.instant('core.areyousure'));
|
|
|
|
const answers: AddonModSurveySubmitAnswerData[] = [];
|
|
modal = await CoreLoadings.show('core.sending', true);
|
|
|
|
for (const x in this.answers) {
|
|
answers.push({
|
|
key: x,
|
|
value: this.answers[x],
|
|
});
|
|
}
|
|
|
|
const online = await AddonModSurvey.submitAnswers(this.survey.id, this.survey.name, this.courseId, answers);
|
|
|
|
CoreEvents.trigger(CoreEvents.ACTIVITY_DATA_SENT, { module: this.moduleName });
|
|
|
|
if (online && this.isPrefetched()) {
|
|
// The survey is downloaded, update the data.
|
|
try {
|
|
const prefetched = await AddonModSurveySync.prefetchAfterUpdate(
|
|
getPrefetchHandlerInstance(),
|
|
this.module,
|
|
this.courseId,
|
|
);
|
|
|
|
// Update the view.
|
|
prefetched ?
|
|
this.showLoadingAndFetch(false, false) :
|
|
this.showLoadingAndRefresh(false);
|
|
} catch {
|
|
// Prefetch failed, refresh the data.
|
|
this.showLoadingAndRefresh(false);
|
|
}
|
|
} else {
|
|
// Not downloaded, refresh the data.
|
|
this.showLoadingAndRefresh(false);
|
|
}
|
|
} catch (error) {
|
|
CoreDomUtils.showErrorModalDefault(error, 'addon.mod_survey.cannotsubmitsurvey', true);
|
|
} finally {
|
|
modal?.dismiss();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @inheritdoc
|
|
*/
|
|
protected async sync(): Promise<AddonModSurveySyncResult> {
|
|
if (!this.survey) {
|
|
throw new CoreError('Cannot sync without a survey.');
|
|
}
|
|
|
|
return AddonModSurveySync.syncSurvey(this.survey.id, this.currentUserId);
|
|
}
|
|
|
|
}
|