diff --git a/src/addon/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts b/src/addon/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts new file mode 100644 index 000000000..6d0317da2 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/delaybetweenattempts/delaybetweenattempts.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { AddonModQuizAccessDelayBetweenAttemptsHandler } from './providers/handler'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + ], + providers: [ + AddonModQuizAccessDelayBetweenAttemptsHandler + ] +}) +export class AddonModQuizAccessDelayBetweenAttemptsModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessDelayBetweenAttemptsHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/delaybetweenattempts/providers/handler.ts b/src/addon/mod/quiz/accessrules/delaybetweenattempts/providers/handler.ts new file mode 100644 index 000000000..d102e9c52 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/delaybetweenattempts/providers/handler.ts @@ -0,0 +1,52 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; + +/** + * Handler to support delay between attempts access rule. + */ +@Injectable() +export class AddonModQuizAccessDelayBetweenAttemptsHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessDelayBetweenAttempts'; + ruleName = 'quizaccess_delaybetweenattempts'; + + constructor() { + // Nothing to do. + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + return false; + } +} diff --git a/src/addon/mod/quiz/accessrules/ipaddress/ipaddress.module.ts b/src/addon/mod/quiz/accessrules/ipaddress/ipaddress.module.ts new file mode 100644 index 000000000..4a60d8c36 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/ipaddress/ipaddress.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { AddonModQuizAccessIpAddressHandler } from './providers/handler'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + ], + providers: [ + AddonModQuizAccessIpAddressHandler + ] +}) +export class AddonModQuizAccessIpAddressModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessIpAddressHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/ipaddress/providers/handler.ts b/src/addon/mod/quiz/accessrules/ipaddress/providers/handler.ts new file mode 100644 index 000000000..ca2d1f3d0 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/ipaddress/providers/handler.ts @@ -0,0 +1,52 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; + +/** + * Handler to support IP address access rule. + */ +@Injectable() +export class AddonModQuizAccessIpAddressHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessIpAddress'; + ruleName = 'quizaccess_ipaddress'; + + constructor() { + // Nothing to do. + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + return false; + } +} diff --git a/src/addon/mod/quiz/accessrules/numattempts/numattempts.module.ts b/src/addon/mod/quiz/accessrules/numattempts/numattempts.module.ts new file mode 100644 index 000000000..ef194b2e8 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/numattempts/numattempts.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { AddonModQuizAccessNumAttemptsHandler } from './providers/handler'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + ], + providers: [ + AddonModQuizAccessNumAttemptsHandler + ] +}) +export class AddonModQuizAccessNumAttemptsModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessNumAttemptsHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/numattempts/providers/handler.ts b/src/addon/mod/quiz/accessrules/numattempts/providers/handler.ts new file mode 100644 index 000000000..125bb2e8c --- /dev/null +++ b/src/addon/mod/quiz/accessrules/numattempts/providers/handler.ts @@ -0,0 +1,52 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; + +/** + * Handler to support num attempts access rule. + */ +@Injectable() +export class AddonModQuizAccessNumAttemptsHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessNumAttempts'; + ruleName = 'quizaccess_numattempts'; + + constructor() { + // Nothing to do. + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + return false; + } +} diff --git a/src/addon/mod/quiz/accessrules/offlineattempts/component/offlineattempts.html b/src/addon/mod/quiz/accessrules/offlineattempts/component/offlineattempts.html new file mode 100644 index 000000000..fad58a104 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/offlineattempts/component/offlineattempts.html @@ -0,0 +1,4 @@ + +

{{ 'core.settings.synchronization' | translate }}

+

{{ 'addon.mod_quiz.confirmcontinueoffline' | translate:{$a: quiz.syncTimeReadable} }}

+
diff --git a/src/addon/mod/quiz/accessrules/offlineattempts/component/offlineattempts.ts b/src/addon/mod/quiz/accessrules/offlineattempts/component/offlineattempts.ts new file mode 100644 index 000000000..d23fd6927 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/offlineattempts/component/offlineattempts.ts @@ -0,0 +1,42 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Input } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +/** + * Component to render the preflight for offline attempts. + */ +@Component({ + selector: 'addon-mod-quiz-acess-offline-attempts', + templateUrl: 'offlineattempts.html' +}) +export class AddonModQuizAccessOfflineAttemptsComponent implements OnInit { + + @Input() quiz: any; // The quiz the rule belongs to. + @Input() attempt: any; // The attempt being started/continued. + @Input() prefetch: boolean; // Whether the user is prefetching the quiz. + @Input() siteId: string; // Site ID. + @Input() form: FormGroup; // Form where to add the form control. + + constructor(private fb: FormBuilder) { } + + /** + * Component being initialized. + */ + ngOnInit(): void { + // Always set confirmdatasaved to 1. Sending the data means the user accepted. + this.form.addControl('confirmdatasaved', this.fb.control(1)); + } +} diff --git a/src/addon/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts b/src/addon/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts new file mode 100644 index 000000000..5cd1adfcf --- /dev/null +++ b/src/addon/mod/quiz/accessrules/offlineattempts/offlineattempts.module.ts @@ -0,0 +1,46 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonModQuizAccessOfflineAttemptsHandler } from './providers/handler'; +import { AddonModQuizAccessOfflineAttemptsComponent } from './component/offlineattempts'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + AddonModQuizAccessOfflineAttemptsComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + ], + providers: [ + AddonModQuizAccessOfflineAttemptsHandler + ], + exports: [ + AddonModQuizAccessOfflineAttemptsComponent + ], + entryComponents: [ + AddonModQuizAccessOfflineAttemptsComponent + ] +}) +export class AddonModQuizAccessOfflineAttemptsModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessOfflineAttemptsHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/offlineattempts/providers/handler.ts b/src/addon/mod/quiz/accessrules/offlineattempts/providers/handler.ts new file mode 100644 index 000000000..3d5b38a24 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/offlineattempts/providers/handler.ts @@ -0,0 +1,91 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable, Injector } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; +import { AddonModQuizSyncProvider } from '../../../providers/quiz-sync'; +import { AddonModQuizAccessOfflineAttemptsComponent } from '../component/offlineattempts'; + +/** + * Handler to support offline attempts access rule. + */ +@Injectable() +export class AddonModQuizAccessOfflineAttemptsHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessOfflineAttempts'; + ruleName = 'quizaccess_offlineattempts'; + + constructor() { + // Nothing to do. + } + + /** + * Add preflight data that doesn't require user interaction. The data should be added to the preflightData param. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} preflightData Object where to add the preflight data. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} Promise resolved when done if async, void if it's synchronous. + */ + getFixedPreflightData(quiz: any, preflightData: any, attempt?: any, prefetch?: boolean, siteId?: string): void | Promise { + preflightData.confirmdatasaved = 1; + } + + /** + * Return the Component to use to display the access rule preflight. + * Implement this if your access rule requires a preflight check with user interaction. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getPreflightComponent(injector: Injector): any | Promise { + return AddonModQuizAccessOfflineAttemptsComponent; + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + if (prefetch) { + // Don't show the warning if the user is prefetching. + return false; + } + + if (!attempt) { + // User is starting a new attempt, show the warning. + return true; + } + + // Show warning if last sync was a while ago. + return Date.now() - AddonModQuizSyncProvider.SYNC_TIME > quiz.syncTime; + } +} diff --git a/src/addon/mod/quiz/accessrules/openclosedate/openclosedate.module.ts b/src/addon/mod/quiz/accessrules/openclosedate/openclosedate.module.ts new file mode 100644 index 000000000..3c23691b1 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/openclosedate/openclosedate.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { AddonModQuizAccessOpenCloseDateHandler } from './providers/handler'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + ], + providers: [ + AddonModQuizAccessOpenCloseDateHandler + ] +}) +export class AddonModQuizAccessOpenCloseDateModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessOpenCloseDateHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/openclosedate/providers/handler.ts b/src/addon/mod/quiz/accessrules/openclosedate/providers/handler.ts new file mode 100644 index 000000000..b801b0e24 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/openclosedate/providers/handler.ts @@ -0,0 +1,75 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; +import { AddonModQuizProvider } from '../../../providers/quiz'; + +/** + * Handler to support open/close date access rule. + */ +@Injectable() +export class AddonModQuizAccessOpenCloseDateHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessOpenCloseDate'; + ruleName = 'quizaccess_openclosedate'; + + constructor() { + // Nothing to do. + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + return false; + } + + /** + * Whether or not the time left of an attempt should be displayed. + * + * @param {any} attempt The attempt. + * @param {number} endTime The attempt end time (in seconds). + * @param {number} timeNow The current time in seconds. + * @return {boolean} Whether it should be displayed. + */ + shouldShowTimeLeft(attempt: any, endTime: number, timeNow: number): boolean { + // If this is a teacher preview after the close date, do not show the time. + if (attempt.preview && timeNow > endTime) { + return false; + } + + // Show the time left only if it's less than QUIZ_SHOW_TIME_BEFORE_DEADLINE. + if (timeNow > endTime - AddonModQuizProvider.QUIZ_SHOW_TIME_BEFORE_DEADLINE) { + return true; + } + + return false; + } +} diff --git a/src/addon/mod/quiz/accessrules/password/component/password.html b/src/addon/mod/quiz/accessrules/password/component/password.html new file mode 100644 index 000000000..ec2a58f33 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/password/component/password.html @@ -0,0 +1,9 @@ + +

{{ 'addon.mod_quiz.quizpassword' | translate }}

+

{{ 'addon.mod_quiz.requirepasswordmessage' | translate}}

+
+ + + + + diff --git a/src/addon/mod/quiz/accessrules/password/component/password.ts b/src/addon/mod/quiz/accessrules/password/component/password.ts new file mode 100644 index 000000000..6205901e4 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/password/component/password.ts @@ -0,0 +1,42 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Input } from '@angular/core'; +import { FormGroup, FormBuilder } from '@angular/forms'; + +/** + * Component to render the preflight for password. + */ +@Component({ + selector: 'addon-mod-quiz-acess-password', + templateUrl: 'password.html' +}) +export class AddonModQuizAccessPasswordComponent implements OnInit { + + @Input() quiz: any; // The quiz the rule belongs to. + @Input() attempt: any; // The attempt being started/continued. + @Input() prefetch: boolean; // Whether the user is prefetching the quiz. + @Input() siteId: string; // Site ID. + @Input() form: FormGroup; // Form where to add the form control. + + constructor(private fb: FormBuilder) { } + + /** + * Component being initialized. + */ + ngOnInit(): void { + // Add the control for the password. + this.form.addControl('quizpassword', this.fb.control('')); + } +} diff --git a/src/addon/mod/quiz/accessrules/password/password.module.ts b/src/addon/mod/quiz/accessrules/password/password.module.ts new file mode 100644 index 000000000..bfb5b6d95 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/password/password.module.ts @@ -0,0 +1,48 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { CoreComponentsModule } from '@components/components.module'; +import { AddonModQuizAccessPasswordHandler } from './providers/handler'; +import { AddonModQuizAccessPasswordComponent } from './component/password'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + AddonModQuizAccessPasswordComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + CoreComponentsModule + ], + providers: [ + AddonModQuizAccessPasswordHandler + ], + exports: [ + AddonModQuizAccessPasswordComponent + ], + entryComponents: [ + AddonModQuizAccessPasswordComponent + ] +}) +export class AddonModQuizAccessPasswordModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessPasswordHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/password/providers/handler.ts b/src/addon/mod/quiz/accessrules/password/providers/handler.ts new file mode 100644 index 000000000..7280b2e16 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/password/providers/handler.ts @@ -0,0 +1,201 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable, Injector } from '@angular/core'; +import { CoreSitesProvider } from '@providers/sites'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; +import { AddonModQuizAccessPasswordComponent } from '../component/password'; + +/** + * Handler to support password access rule. + */ +@Injectable() +export class AddonModQuizAccessPasswordHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessPassword'; + ruleName = 'quizaccess_password'; + + // Variables for database. + protected PASSWORD_TABLE = 'mod_quiz_access_password'; + protected tableSchema = { + name: this.PASSWORD_TABLE, + columns: [ + { + name: 'id', + type: 'INTEGER', + primaryKey: true + }, + { + name: 'password', + type: 'TEXT' + }, + { + name: 'timemodified', + type: 'INTEGER' + } + ] + }; + + constructor(private sitesProvider: CoreSitesProvider) { + this.sitesProvider.createTableFromSchema(this.tableSchema); + } + + /** + * Add preflight data that doesn't require user interaction. The data should be added to the preflightData param. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} preflightData Object where to add the preflight data. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} Promise resolved when done if async, void if it's synchronous. + */ + getFixedPreflightData(quiz: any, preflightData: any, attempt?: any, prefetch?: boolean, siteId?: string): void | Promise { + if (quiz && quiz.id && typeof preflightData.quizpassword == 'undefined') { + // Try to get a password stored. If it's found, use it. + return this.getPasswordEntry(quiz.id, siteId).then((entry) => { + preflightData.quizpassword = entry.password; + }).catch(() => { + // Don't reject. + }); + } + } + + /** + * Get a password stored in DB. + * + * @param {number} quizId Quiz ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved with the DB entry on success. + */ + protected getPasswordEntry(quizId: number, siteId?: string): Promise { + + return this.sitesProvider.getSite(siteId).then((site) => { + return site.getDb().getRecord(this.PASSWORD_TABLE, {id: quizId}); + }); + } + + /** + * Return the Component to use to display the access rule preflight. + * Implement this if your access rule requires a preflight check with user interaction. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getPreflightComponent(injector: Injector): any | Promise { + return AddonModQuizAccessPasswordComponent; + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + // If there's a password stored don't require the preflight since we'll use the stored one. + return this.getPasswordEntry(quiz.id, siteId).then(() => { + return false; + }).catch(() => { + // Not stored. + return true; + }); + } + + /** + * Function called when the preflight check has passed. This is a chance to record that fact in some way. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} attempt The attempt started/continued. + * @param {any} preflightData Preflight data gathered. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} Promise resolved when done if async, void if it's synchronous. + */ + notifyPreflightCheckPassed(quiz: any, attempt: any, preflightData: any, prefetch?: boolean, siteId?: string) + : void | Promise { + + // The password is right, store it to use it automatically in following executions. + if (quiz && quiz.id && typeof preflightData.quizpassword != 'undefined') { + return this.storePassword(quiz.id, preflightData.quizpassword, siteId); + } + } + + /** + * Function called when the preflight check fails. This is a chance to record that fact in some way. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} attempt The attempt started/continued. + * @param {any} preflightData Preflight data gathered. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {void|Promise} Promise resolved when done if async, void if it's synchronous. + */ + notifyPreflightCheckFailed?(quiz: any, attempt: any, preflightData: any, prefetch?: boolean, siteId?: string) + : void | Promise { + + // The password is wrong, remove it from DB if it's there. + if (quiz && quiz.id) { + return this.removePassword(quiz.id, siteId); + } + } + + /** + * Remove a password from DB. + * + * @param {number} quizId Quiz ID. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + protected removePassword(quizId: number, siteId?: string): Promise { + + return this.sitesProvider.getSite(siteId).then((site) => { + return site.getDb().deleteRecords(this.PASSWORD_TABLE, {id: quizId}); + }); + } + + /** + * Store a password in DB. + * + * @param {number} quizId Quiz ID. + * @param {string} password Password. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {Promise} Promise resolved when done. + */ + protected storePassword(quizId: number, password: string, siteId?: string): Promise { + + return this.sitesProvider.getSite(siteId).then((site) => { + const entry = { + id: quizId, + password: password, + timemodified: Date.now() + }; + + return site.getDb().insertRecord(this.PASSWORD_TABLE, entry); + }); + } +} diff --git a/src/addon/mod/quiz/accessrules/safebrowser/providers/handler.ts b/src/addon/mod/quiz/accessrules/safebrowser/providers/handler.ts new file mode 100644 index 000000000..b5ec88157 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/safebrowser/providers/handler.ts @@ -0,0 +1,52 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; + +/** + * Handler to support safe address access rule. + */ +@Injectable() +export class AddonModQuizAccessSafeBrowserHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessSafeBrowser'; + ruleName = 'quizaccess_safebrowser'; + + constructor() { + // Nothing to do. + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + return false; + } +} diff --git a/src/addon/mod/quiz/accessrules/safebrowser/safebrowser.module.ts b/src/addon/mod/quiz/accessrules/safebrowser/safebrowser.module.ts new file mode 100644 index 000000000..6e326e8cf --- /dev/null +++ b/src/addon/mod/quiz/accessrules/safebrowser/safebrowser.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { AddonModQuizAccessSafeBrowserHandler } from './providers/handler'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + ], + providers: [ + AddonModQuizAccessSafeBrowserHandler + ] +}) +export class AddonModQuizAccessSafeBrowserModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessSafeBrowserHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/securewindow/providers/handler.ts b/src/addon/mod/quiz/accessrules/securewindow/providers/handler.ts new file mode 100644 index 000000000..d5bb5334b --- /dev/null +++ b/src/addon/mod/quiz/accessrules/securewindow/providers/handler.ts @@ -0,0 +1,52 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; + +/** + * Handler to support secure window access rule. + */ +@Injectable() +export class AddonModQuizAccessSecureWindowHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessSecureWindow'; + ruleName = 'quizaccess_securewindow'; + + constructor() { + // Nothing to do. + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + return false; + } +} diff --git a/src/addon/mod/quiz/accessrules/securewindow/securewindow.module.ts b/src/addon/mod/quiz/accessrules/securewindow/securewindow.module.ts new file mode 100644 index 000000000..216f3b8b8 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/securewindow/securewindow.module.ts @@ -0,0 +1,30 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { AddonModQuizAccessSecureWindowHandler } from './providers/handler'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + ], + providers: [ + AddonModQuizAccessSecureWindowHandler + ] +}) +export class AddonModQuizAccessSecureWindowModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessSecureWindowHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/accessrules/timelimit/component/timelimit.html b/src/addon/mod/quiz/accessrules/timelimit/component/timelimit.html new file mode 100644 index 000000000..7535b16b7 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/timelimit/component/timelimit.html @@ -0,0 +1,4 @@ + +

{{ 'addon.mod_quiz.confirmstartheader' | translate }}

+

{{ 'addon.mod_quiz.confirmstart' | translate:{$a: quiz.readableTimeLimit} }}

+
diff --git a/src/addon/mod/quiz/accessrules/timelimit/component/timelimit.ts b/src/addon/mod/quiz/accessrules/timelimit/component/timelimit.ts new file mode 100644 index 000000000..27d19d661 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/timelimit/component/timelimit.ts @@ -0,0 +1,36 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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, Input } from '@angular/core'; +import { FormGroup } from '@angular/forms'; + +/** + * Component to render the preflight for time limit. + */ +@Component({ + selector: 'addon-mod-quiz-acess-time-limit', + templateUrl: 'timelimit.html' +}) +export class AddonModQuizAccessTimeLimitComponent { + + @Input() quiz: any; // The quiz the rule belongs to. + @Input() attempt: any; // The attempt being started/continued. + @Input() prefetch: boolean; // Whether the user is prefetching the quiz. + @Input() siteId: string; // Site ID. + @Input() form: FormGroup; // Form where to add the form control. + + constructor() { + // Nothing to do, we don't need to send anything for time limit. + } +} diff --git a/src/addon/mod/quiz/accessrules/timelimit/providers/handler.ts b/src/addon/mod/quiz/accessrules/timelimit/providers/handler.ts new file mode 100644 index 000000000..8ddc8083d --- /dev/null +++ b/src/addon/mod/quiz/accessrules/timelimit/providers/handler.ts @@ -0,0 +1,79 @@ + +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { Injectable, Injector } from '@angular/core'; +import { AddonModQuizAccessRuleHandler } from '../../../providers/access-rules-delegate'; +import { AddonModQuizAccessTimeLimitComponent } from '../component/timelimit'; + +/** + * Handler to support time limit access rule. + */ +@Injectable() +export class AddonModQuizAccessTimeLimitHandler implements AddonModQuizAccessRuleHandler { + name = 'AddonModQuizAccessTimeLimit'; + ruleName = 'quizaccess_timelimit'; + + constructor() { + // Nothing to do. + } + + /** + * Return the Component to use to display the access rule preflight. + * Implement this if your access rule requires a preflight check with user interaction. + * It's recommended to return the class of the component, but you can also return an instance of the component. + * + * @param {Injector} injector Injector. + * @return {any|Promise} The component (or promise resolved with component) to use, undefined if not found. + */ + getPreflightComponent(injector: Injector): any | Promise { + return AddonModQuizAccessTimeLimitComponent; + } + + /** + * Whether or not the handler is enabled on a site level. + * + * @return {boolean|Promise} True or promise resolved with true if enabled. + */ + isEnabled(): boolean | Promise { + return true; + } + + /** + * Whether the rule requires a preflight check when prefetch/start/continue an attempt. + * + * @param {any} quiz The quiz the rule belongs to. + * @param {any} [attempt] The attempt started/continued. If not supplied, user is starting a new attempt. + * @param {boolean} [prefetch] Whether the user is prefetching the quiz. + * @param {string} [siteId] Site ID. If not defined, current site. + * @return {boolean|Promise} Whether the rule requires a preflight check. + */ + isPreflightCheckRequired(quiz: any, attempt?: any, prefetch?: boolean, siteId?: string): boolean | Promise { + // Warning only required if the attempt is not already started. + return !attempt; + } + + /** + * Whether or not the time left of an attempt should be displayed. + * + * @param {any} attempt The attempt. + * @param {number} endTime The attempt end time (in seconds). + * @param {number} timeNow The current time in seconds. + * @return {boolean} Whether it should be displayed. + */ + shouldShowTimeLeft(attempt: any, endTime: number, timeNow: number): boolean { + // If this is a teacher preview after the time limit expires, don't show the time left. + return !(attempt.preview && timeNow > endTime); + } +} diff --git a/src/addon/mod/quiz/accessrules/timelimit/timelimit.module.ts b/src/addon/mod/quiz/accessrules/timelimit/timelimit.module.ts new file mode 100644 index 000000000..850c2fb49 --- /dev/null +++ b/src/addon/mod/quiz/accessrules/timelimit/timelimit.module.ts @@ -0,0 +1,46 @@ +// (C) Copyright 2015 Martin Dougiamas +// +// 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 { NgModule } from '@angular/core'; +import { CommonModule } from '@angular/common'; +import { IonicModule } from 'ionic-angular'; +import { TranslateModule } from '@ngx-translate/core'; +import { AddonModQuizAccessTimeLimitHandler } from './providers/handler'; +import { AddonModQuizAccessTimeLimitComponent } from './component/timelimit'; +import { AddonModQuizAccessRuleDelegate } from '../../providers/access-rules-delegate'; + +@NgModule({ + declarations: [ + AddonModQuizAccessTimeLimitComponent + ], + imports: [ + CommonModule, + IonicModule, + TranslateModule.forChild(), + ], + providers: [ + AddonModQuizAccessTimeLimitHandler + ], + exports: [ + AddonModQuizAccessTimeLimitComponent + ], + entryComponents: [ + AddonModQuizAccessTimeLimitComponent + ] +}) +export class AddonModQuizAccessTimeLimitModule { + constructor(accessRuleDelegate: AddonModQuizAccessRuleDelegate, handler: AddonModQuizAccessTimeLimitHandler) { + accessRuleDelegate.registerHandler(handler); + } +} diff --git a/src/addon/mod/quiz/quiz.module.ts b/src/addon/mod/quiz/quiz.module.ts index 3c08d7b7c..0745f81b4 100644 --- a/src/addon/mod/quiz/quiz.module.ts +++ b/src/addon/mod/quiz/quiz.module.ts @@ -26,11 +26,31 @@ import { AddonModQuizPrefetchHandler } from './providers/prefetch-handler'; import { AddonModQuizSyncCronHandler } from './providers/sync-cron-handler'; import { AddonModQuizComponentsModule } from './components/components.module'; +// Access rules. +import { AddonModQuizAccessDelayBetweenAttemptsModule } from './accessrules/delaybetweenattempts/delaybetweenattempts.module'; +import { AddonModQuizAccessIpAddressModule } from './accessrules/ipaddress/ipaddress.module'; +import { AddonModQuizAccessNumAttemptsModule } from './accessrules/numattempts/numattempts.module'; +import { AddonModQuizAccessOfflineAttemptsModule } from './accessrules/offlineattempts/offlineattempts.module'; +import { AddonModQuizAccessOpenCloseDateModule } from './accessrules/openclosedate/openclosedate.module'; +import { AddonModQuizAccessPasswordModule } from './accessrules/password/password.module'; +import { AddonModQuizAccessSafeBrowserModule } from './accessrules/safebrowser/safebrowser.module'; +import { AddonModQuizAccessSecureWindowModule } from './accessrules/securewindow/securewindow.module'; +import { AddonModQuizAccessTimeLimitModule } from './accessrules/timelimit/timelimit.module'; + @NgModule({ declarations: [ ], imports: [ - AddonModQuizComponentsModule + AddonModQuizComponentsModule, + AddonModQuizAccessDelayBetweenAttemptsModule, + AddonModQuizAccessIpAddressModule, + AddonModQuizAccessNumAttemptsModule, + AddonModQuizAccessOfflineAttemptsModule, + AddonModQuizAccessOpenCloseDateModule, + AddonModQuizAccessPasswordModule, + AddonModQuizAccessSafeBrowserModule, + AddonModQuizAccessSecureWindowModule, + AddonModQuizAccessTimeLimitModule ], providers: [ AddonModQuizAccessRuleDelegate,