commit
6dac0af34d
|
@ -583,7 +583,13 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
|
|||
*/
|
||||
protected processAttempt(userFinish?: boolean, timeUp?: boolean, retrying?: boolean): Promise<any> {
|
||||
// Get the answers to send.
|
||||
return this.prepareAnswers().then((answers) => {
|
||||
let promise = Promise.resolve({});
|
||||
|
||||
if (!this.showSummary) {
|
||||
promise = this.prepareAnswers();
|
||||
}
|
||||
|
||||
return promise.then((answers) => {
|
||||
// Send the answers.
|
||||
return this.quizProvider.processAttempt(this.quiz, this.attempt, answers, this.preflightData, userFinish, timeUp,
|
||||
this.offline).catch((error) => {
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CoreQuestionProvider } from '@core/question/providers/question';
|
|||
import { CoreQuestionHandler } from '@core/question/providers/delegate';
|
||||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||
import { AddonQtypeDdMarkerComponent } from '../component/ddmarker';
|
||||
import { CoreWSExternalFile } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Handler to support drag-and-drop markers question type.
|
||||
|
@ -119,9 +120,9 @@ export class AddonQtypeDdMarkerHandler implements CoreQuestionHandler {
|
|||
*
|
||||
* @param question Question.
|
||||
* @param usageId Usage ID.
|
||||
* @return List of URLs.
|
||||
* @return List of files or URLs.
|
||||
*/
|
||||
getAdditionalDownloadableFiles(question: any, usageId: number): string[] {
|
||||
getAdditionalDownloadableFiles(question: any, usageId: number): (string | CoreWSExternalFile)[] {
|
||||
this.questionHelper.extractQuestionScripts(question, usageId);
|
||||
|
||||
if (question.amdArgs && typeof question.amdArgs[1] == 'string') {
|
||||
|
|
|
@ -24,6 +24,7 @@ import { CoreQuestionHandler } from '@core/question/providers/delegate';
|
|||
import { CoreQuestionHelperProvider } from '@core/question/providers/helper';
|
||||
import { CoreQuestion } from '@core/question/providers/question';
|
||||
import { AddonQtypeEssayComponent } from '../component/essay';
|
||||
import { CoreWSExternalFile } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Handler to support essay question type.
|
||||
|
@ -67,6 +68,23 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler {
|
|||
return this.questionHelper.deleteStoredQuestionFiles(question, component, componentId, siteId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of files that needs to be downloaded in addition to the files embedded in the HTML.
|
||||
*
|
||||
* @param question Question.
|
||||
* @param usageId Usage ID.
|
||||
* @return List of files or URLs.
|
||||
*/
|
||||
getAdditionalDownloadableFiles(question: any, usageId: number): (string | CoreWSExternalFile)[] {
|
||||
if (!question.responsefileareas) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return question.responsefileareas.reduce((urlsList, area) => {
|
||||
return urlsList.concat(area.files || []);
|
||||
}, []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the question allows text and/or attachments.
|
||||
*
|
||||
|
@ -165,8 +183,8 @@ export class AddonQtypeEssayHandler implements CoreQuestionHandler {
|
|||
return attachments && attachments.length >= Number(question.settings.attachmentsrequired) ? 1 : 0;
|
||||
}
|
||||
|
||||
return (hasTextAnswer || question.settings.responserequired == '0') &&
|
||||
(attachments && attachments.length > Number(question.settings.attachmentsrequired)) ? 1 : 0;
|
||||
return ((hasTextAnswer || question.settings.responserequired == '0') &&
|
||||
(attachments && attachments.length >= Number(question.settings.attachmentsrequired))) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Component, ViewChild, ElementRef } from '@angular/core';
|
||||
import { Component, ViewChild, ElementRef, OnDestroy } from '@angular/core';
|
||||
import { IonicPage, NavController, NavParams } from 'ionic-angular';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreAppProvider } from '@providers/app';
|
||||
|
@ -25,6 +25,7 @@ import { CoreLoginHelperProvider } from '../../providers/helper';
|
|||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
import { CoreConfigConstants } from '../../../../configconstants';
|
||||
import { CoreCustomURLSchemes } from '@providers/urlschemes';
|
||||
import { Subscription } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Page to enter the user credentials.
|
||||
|
@ -34,7 +35,7 @@ import { CoreCustomURLSchemes } from '@providers/urlschemes';
|
|||
selector: 'page-core-login-credentials',
|
||||
templateUrl: 'credentials.html',
|
||||
})
|
||||
export class CoreLoginCredentialsPage {
|
||||
export class CoreLoginCredentialsPage implements OnDestroy {
|
||||
|
||||
@ViewChild('credentialsForm') formElement: ElementRef;
|
||||
|
||||
|
@ -57,6 +58,7 @@ export class CoreLoginCredentialsPage {
|
|||
protected viewLeft = false;
|
||||
protected siteId: string;
|
||||
protected urlToOpen: string;
|
||||
protected valueChangeSubscription: Subscription;
|
||||
|
||||
constructor(private navCtrl: NavController,
|
||||
navParams: NavParams,
|
||||
|
@ -89,6 +91,28 @@ export class CoreLoginCredentialsPage {
|
|||
} else {
|
||||
this.showScanQR = false;
|
||||
}
|
||||
|
||||
if (appProvider.isIOS()) {
|
||||
// Make iOS auto-fill work. The field that isn't focused doesn't get updated, do it manually.
|
||||
// Debounce it to prevent triggering this function too often when the user is typing.
|
||||
this.valueChangeSubscription = this.credForm.valueChanges.debounceTime(1000).subscribe((changes) => {
|
||||
if (!this.formElement || !this.formElement.nativeElement) {
|
||||
return;
|
||||
}
|
||||
|
||||
const usernameInput = this.formElement.nativeElement.querySelector('input[name="username"]');
|
||||
const passwordInput = this.formElement.nativeElement.querySelector('input[name="password"]');
|
||||
const usernameValue = usernameInput && usernameInput.value;
|
||||
const passwordValue = passwordInput && passwordInput.value;
|
||||
|
||||
if (typeof usernameValue != 'undefined' && usernameValue != changes.username) {
|
||||
this.credForm.get('username').setValue(usernameValue);
|
||||
}
|
||||
if (typeof passwordValue != 'undefined' && passwordValue != changes.password) {
|
||||
this.credForm.get('password').setValue(passwordValue);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -336,4 +360,11 @@ export class CoreLoginCredentialsPage {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Component destroyed.
|
||||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.valueChangeSubscription && this.valueChangeSubscription.unsubscribe();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ import { CoreEventsProvider } from '@providers/events';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDelegate, CoreDelegateHandler } from '@classes/delegate';
|
||||
import { CoreQuestionDefaultHandler } from './default-question-handler';
|
||||
import { CoreWSExternalFile } from '@providers/ws';
|
||||
|
||||
/**
|
||||
* Interface that all question type handlers must implement.
|
||||
|
@ -119,9 +120,9 @@ export interface CoreQuestionHandler extends CoreDelegateHandler {
|
|||
*
|
||||
* @param question Question.
|
||||
* @param usageId Usage ID.
|
||||
* @return List of URLs.
|
||||
* @return List of files or URLs.
|
||||
*/
|
||||
getAdditionalDownloadableFiles?(question: any, usageId: number): string[];
|
||||
getAdditionalDownloadableFiles?(question: any, usageId: number): (string | CoreWSExternalFile)[];
|
||||
|
||||
/**
|
||||
* Clear temporary data after the data has been saved.
|
||||
|
@ -324,9 +325,9 @@ export class CoreQuestionDelegate extends CoreDelegate {
|
|||
*
|
||||
* @param question Question.
|
||||
* @param usageId Usage ID.
|
||||
* @return List of URLs.
|
||||
* @return List of files or URLs.
|
||||
*/
|
||||
getAdditionalDownloadableFiles(question: any, usageId: number): string[] {
|
||||
getAdditionalDownloadableFiles(question: any, usageId: number): (string | CoreWSExternalFile)[] {
|
||||
const type = this.getTypeName(question);
|
||||
|
||||
return this.executeFunctionOnEnabled(type, 'getAdditionalDownloadableFiles', [question, usageId]) || [];
|
||||
|
|
|
@ -590,29 +590,39 @@ export class CoreQuestionHelperProvider {
|
|||
*/
|
||||
prefetchQuestionFiles(question: any, component?: string, componentId?: string | number, siteId?: string, usageId?: number)
|
||||
: Promise<any> {
|
||||
const urls = this.filepoolProvider.extractDownloadableFilesFromHtml(question.html);
|
||||
|
||||
if (!component) {
|
||||
component = CoreQuestionProvider.COMPONENT;
|
||||
componentId = question.number;
|
||||
}
|
||||
|
||||
urls.push(...this.questionDelegate.getAdditionalDownloadableFiles(question, usageId));
|
||||
const files = this.questionDelegate.getAdditionalDownloadableFiles(question, usageId) || [];
|
||||
|
||||
files.push(...this.filepoolProvider.extractDownloadableFilesFromHtml(question.html));
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
const promises = [];
|
||||
const treated = {};
|
||||
|
||||
urls.forEach((url) => {
|
||||
if (!site.canDownloadFiles() && this.urlUtils.isPluginFileUrl(url)) {
|
||||
files.forEach((file) => {
|
||||
const fileUrl = typeof file == 'string' ? file : file.fileurl;
|
||||
const timemodified = (typeof file != 'string' && file.timemodified) || 0;
|
||||
|
||||
if (treated[fileUrl]) {
|
||||
return;
|
||||
}
|
||||
treated[fileUrl] = true;
|
||||
|
||||
if (!site.canDownloadFiles() && this.urlUtils.isPluginFileUrl(fileUrl)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (url.indexOf('theme/image.php') > -1 && url.indexOf('flagged') > -1) {
|
||||
if (fileUrl.indexOf('theme/image.php') > -1 && fileUrl.indexOf('flagged') > -1) {
|
||||
// Ignore flag images.
|
||||
return;
|
||||
}
|
||||
|
||||
promises.push(this.filepoolProvider.addToQueueByUrl(siteId, url, component, componentId));
|
||||
promises.push(this.filepoolProvider.addToQueueByUrl(siteId, fileUrl, component, componentId, timemodified));
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
|
|
Loading…
Reference in New Issue