forked from CIT/Vmeda.Online
		
	MOBILE-3664 site plugins: Implement pages
This commit is contained in:
		
							parent
							
								
									2040840d79
								
							
						
					
					
						commit
						a4046f5678
					
				@ -43,6 +43,7 @@ import { CoreFilterHelper } from '@features/filter/services/filter-helper';
 | 
			
		||||
import { AddonCalendarOfflineEventDBRecord } from '../../services/database/calendar-offline';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays a form to create/edit an event.
 | 
			
		||||
@ -52,7 +53,7 @@ import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
    templateUrl: 'edit-event.html',
 | 
			
		||||
    styleUrls: ['edit-event.scss'],
 | 
			
		||||
})
 | 
			
		||||
export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
 | 
			
		||||
export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(CoreEditorRichTextEditorComponent) descriptionEditor!: CoreEditorRichTextEditorComponent;
 | 
			
		||||
    @ViewChild('editEventForm') formElement!: ElementRef;
 | 
			
		||||
@ -605,15 +606,17 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if we can leave the page or not.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     * @return Resolved with true if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    async ionViewCanLeave(): Promise<void> {
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (AddonCalendarHelper.hasEventDataChanged(this.form.value, this.originalData)) {
 | 
			
		||||
            // Show confirmation if some data has been modified.
 | 
			
		||||
            await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit'));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        CoreDomUtils.triggerFormCancelledEvent(this.formElement, this.currentSite.getId());
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -56,6 +56,7 @@ import { CoreGroups } from '@services/groups';
 | 
			
		||||
import { CoreSync } from '@services/sync';
 | 
			
		||||
import { AddonModAssignSubmissionPluginComponent } from '../submission-plugin/submission-plugin';
 | 
			
		||||
import { AddonModAssignModuleHandlerService } from '../../services/handlers/module';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component that displays an assignment submission.
 | 
			
		||||
@ -65,7 +66,7 @@ import { AddonModAssignModuleHandlerService } from '../../services/handlers/modu
 | 
			
		||||
    templateUrl: 'addon-mod-assign-submission.html',
 | 
			
		||||
    styleUrls: ['submission.scss'],
 | 
			
		||||
})
 | 
			
		||||
export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
 | 
			
		||||
export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(CoreTabsComponent) tabs!: CoreTabsComponent;
 | 
			
		||||
    @ViewChildren(AddonModAssignSubmissionPluginComponent) submissionComponents!:
 | 
			
		||||
@ -252,21 +253,20 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy {
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if the user can leave the view. If there are changes to be saved, it will ask for confirm.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Promise resolved if can leave the view, rejected otherwise.
 | 
			
		||||
     * @return Promise resolved with true if can leave the view, rejected otherwise.
 | 
			
		||||
     */
 | 
			
		||||
    async canLeave(): Promise<void> {
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        // Check if there is data to save.
 | 
			
		||||
        const modified = await this.hasDataToSave();
 | 
			
		||||
 | 
			
		||||
        if (modified) {
 | 
			
		||||
            // Modified, confirm user wants to go back.
 | 
			
		||||
            try {
 | 
			
		||||
                await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit'));
 | 
			
		||||
                await this.discardDrafts();
 | 
			
		||||
            } catch {
 | 
			
		||||
                // Cancelled by the user.
 | 
			
		||||
            }
 | 
			
		||||
            await CoreDomUtils.showConfirm(Translate.instant('core.confirmcanceledit'));
 | 
			
		||||
 | 
			
		||||
            await this.discardDrafts();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -16,6 +16,7 @@ import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from '@angular/co
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { CoreFileUploaderHelper } from '@features/fileuploader/services/fileuploader-helper';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
 | 
			
		||||
import { CoreSync } from '@services/sync';
 | 
			
		||||
@ -44,7 +45,7 @@ import { AddonModAssignSync } from '../../services/assign-sync';
 | 
			
		||||
    selector: 'page-addon-mod-assign-edit',
 | 
			
		||||
    templateUrl: 'edit.html',
 | 
			
		||||
})
 | 
			
		||||
export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
			
		||||
export class AddonModAssignEditPage implements OnInit, OnDestroy, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild('editSubmissionForm') formElement?: ElementRef;
 | 
			
		||||
 | 
			
		||||
@ -92,9 +93,9 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    async ionViewCanLeave(): Promise<void> {
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (this.forceLeave) {
 | 
			
		||||
            return;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check if data has changed.
 | 
			
		||||
@ -107,6 +108,8 @@ export class AddonModAssignEditPage implements OnInit, OnDestroy {
 | 
			
		||||
        AddonModAssignHelper.clearSubmissionPluginTmpData(this.assign!, this.userSubmission, this.getInputData());
 | 
			
		||||
 | 
			
		||||
        CoreDomUtils.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,7 @@
 | 
			
		||||
import { Component, OnInit, ViewChild } from '@angular/core';
 | 
			
		||||
import { ActivatedRoute } from '@angular/router';
 | 
			
		||||
import { CoreCourse } from '@features/course/services/course';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreScreen } from '@services/screen';
 | 
			
		||||
@ -29,7 +30,7 @@ import { AddonModAssign, AddonModAssignAssign } from '../../services/assign';
 | 
			
		||||
    selector: 'page-addon-mod-assign-submission-review',
 | 
			
		||||
    templateUrl: 'submission-review.html',
 | 
			
		||||
})
 | 
			
		||||
export class AddonModAssignSubmissionReviewPage implements OnInit {
 | 
			
		||||
export class AddonModAssignSubmissionReviewPage implements OnInit, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(AddonModAssignSubmissionComponent) submissionComponent?: AddonModAssignSubmissionComponent;
 | 
			
		||||
 | 
			
		||||
@ -71,7 +72,7 @@ export class AddonModAssignSubmissionReviewPage implements OnInit {
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewCanLeave(): boolean | Promise<void> {
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (!this.submissionComponent || this.forceLeave) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
@ -44,6 +44,7 @@ import {
 | 
			
		||||
} from '../../services/quiz';
 | 
			
		||||
import { AddonModQuizAttempt, AddonModQuizHelper } from '../../services/quiz-helper';
 | 
			
		||||
import { AddonModQuizSync } from '../../services/quiz-sync';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that allows attempting a quiz.
 | 
			
		||||
@ -53,7 +54,7 @@ import { AddonModQuizSync } from '../../services/quiz-sync';
 | 
			
		||||
    templateUrl: 'player.html',
 | 
			
		||||
    styleUrls: ['player.scss'],
 | 
			
		||||
})
 | 
			
		||||
export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
			
		||||
export class AddonModQuizPlayerPage implements OnInit, OnDestroy, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(IonContent) content?: IonContent;
 | 
			
		||||
    @ViewChildren(CoreQuestionComponent) questionComponents?: QueryList<CoreQuestionComponent>;
 | 
			
		||||
@ -144,9 +145,9 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    async ionViewCanLeave(): Promise<void> {
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (this.forceLeave || this.quizAborted || !this.questions.length || this.showSummary) {
 | 
			
		||||
            return;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Save answers.
 | 
			
		||||
@ -164,6 +165,8 @@ export class AddonModQuizPlayerPage implements OnInit, OnDestroy {
 | 
			
		||||
        } finally {
 | 
			
		||||
            modal.dismiss();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -31,6 +31,7 @@ import { CoreXAPIModule } from './xapi/xapi.module';
 | 
			
		||||
import { CoreViewerModule } from './viewer/viewer.module';
 | 
			
		||||
import { CoreSearchModule } from './search/search.module';
 | 
			
		||||
import { CoreCommentsModule } from './comments/comments.module';
 | 
			
		||||
import { CoreSitePluginsModule } from './siteplugins/siteplugins.module';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
@ -51,6 +52,7 @@ import { CoreCommentsModule } from './comments/comments.module';
 | 
			
		||||
        CoreH5PModule,
 | 
			
		||||
        CoreViewerModule,
 | 
			
		||||
        CoreCommentsModule,
 | 
			
		||||
        CoreSitePluginsModule,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreFeaturesModule {}
 | 
			
		||||
 | 
			
		||||
@ -12,6 +12,8 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Md5 } from 'ts-md5';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    CoreCourseOptionsHandler,
 | 
			
		||||
    CoreCourseOptionsHandlerData,
 | 
			
		||||
@ -74,10 +76,8 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl
 | 
			
		||||
        return {
 | 
			
		||||
            title: this.title,
 | 
			
		||||
            class: this.handlerSchema.displaydata?.class,
 | 
			
		||||
            page: '@todo CoreSitePluginsCourseOptionComponent',
 | 
			
		||||
            pageParams: {
 | 
			
		||||
                handlerUniqueName: this.name,
 | 
			
		||||
            },
 | 
			
		||||
            page: `siteplugins/${this.name}`,
 | 
			
		||||
            pageParams: {},
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -85,18 +85,19 @@ export class CoreSitePluginsCourseOptionHandler extends CoreSitePluginsBaseHandl
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    getMenuDisplayData(course: CoreCourseAnyCourseDataWithOptions): CoreCourseOptionsMenuHandlerData {
 | 
			
		||||
        const args = {
 | 
			
		||||
            courseid: course.id,
 | 
			
		||||
        };
 | 
			
		||||
        const hash = <string> Md5.hashAsciiStr(JSON.stringify(args));
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            title: this.title,
 | 
			
		||||
            class: this.handlerSchema.displaydata?.class,
 | 
			
		||||
            icon: this.handlerSchema.displaydata?.icon || '',
 | 
			
		||||
            page: '@todo CoreSitePluginsPluginPage',
 | 
			
		||||
            page: `siteplugins/${this.plugin.component}/${this.handlerSchema.method}/${hash}`,
 | 
			
		||||
            pageParams: {
 | 
			
		||||
                title: this.title,
 | 
			
		||||
                component: this.plugin.component,
 | 
			
		||||
                method: this.handlerSchema.method,
 | 
			
		||||
                args: {
 | 
			
		||||
                    courseid: course.id,
 | 
			
		||||
                },
 | 
			
		||||
                args,
 | 
			
		||||
                initResult: this.initResult,
 | 
			
		||||
                ptrEnabled: this.handlerSchema.ptrenabled,
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
@ -47,11 +47,9 @@ export class CoreSitePluginsMainMenuHandler extends CoreSitePluginsBaseHandler i
 | 
			
		||||
            title: this.title,
 | 
			
		||||
            icon: this.handlerSchema.displaydata?.icon || 'fas-question',
 | 
			
		||||
            class: this.handlerSchema.displaydata?.class,
 | 
			
		||||
            page: '@todo CoreSitePluginsPluginPage',
 | 
			
		||||
            page: `siteplugins/${this.plugin.component}/${this.handlerSchema.method}/0`,
 | 
			
		||||
            pageParams: {
 | 
			
		||||
                title: this.title,
 | 
			
		||||
                component: this.plugin.component,
 | 
			
		||||
                method: this.handlerSchema.method,
 | 
			
		||||
                initResult: this.initResult,
 | 
			
		||||
                ptrEnabled: this.handlerSchema.ptrenabled,
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
@ -44,11 +44,9 @@ export class CoreSitePluginsMessageOutputHandler extends CoreSitePluginsBaseHand
 | 
			
		||||
            priority: this.handlerSchema.priority || 0,
 | 
			
		||||
            label: this.title,
 | 
			
		||||
            icon: this.handlerSchema.displaydata?.icon || 'fas-question',
 | 
			
		||||
            page: '@todo CoreSitePluginsPluginPage',
 | 
			
		||||
            page: `siteplugins/${this.plugin.component}/${this.handlerSchema.method}/0`,
 | 
			
		||||
            pageParams: {
 | 
			
		||||
                title: this.title,
 | 
			
		||||
                component: this.plugin.component,
 | 
			
		||||
                method: this.handlerSchema.method,
 | 
			
		||||
                initResult: this.initResult,
 | 
			
		||||
                ptrEnabled: this.handlerSchema.ptrenabled,
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
@ -24,7 +24,7 @@ import {
 | 
			
		||||
    CoreSitePluginsCourseModuleHandlerData,
 | 
			
		||||
    CoreSitePluginsPlugin,
 | 
			
		||||
} from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CoreNavigationOptions } from '@services/navigator';
 | 
			
		||||
import { CoreNavigationOptions, CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
import { CoreSitePluginsBaseHandler } from './base-handler';
 | 
			
		||||
 | 
			
		||||
@ -95,11 +95,13 @@ export class CoreSitePluginsModuleHandler extends CoreSitePluginsBaseHandler imp
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                event.stopPropagation();
 | 
			
		||||
 | 
			
		||||
                // @todo navCtrl.push('CoreSitePluginsModuleIndexPage', {
 | 
			
		||||
                //     title: module.name,
 | 
			
		||||
                //     module: module,
 | 
			
		||||
                //     courseId: courseId
 | 
			
		||||
                // }, options);
 | 
			
		||||
                options = options || {};
 | 
			
		||||
                options.params = {
 | 
			
		||||
                    title: module.name,
 | 
			
		||||
                    module,
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                CoreNavigator.navigateToSitePath(`siteplugins/module/${courseId}/${module.id}`, options);
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -49,11 +49,9 @@ export class CoreSitePluginsSettingsHandler extends CoreSitePluginsBaseHandler i
 | 
			
		||||
            title: this.title,
 | 
			
		||||
            icon: this.handlerSchema.displaydata?.icon,
 | 
			
		||||
            class: this.handlerSchema.displaydata?.class,
 | 
			
		||||
            page: '@todo CoreSitePluginsPluginPage',
 | 
			
		||||
            page: `siteplugins/${this.plugin.component}/${this.handlerSchema.method}/0`,
 | 
			
		||||
            params: {
 | 
			
		||||
                title: this.title,
 | 
			
		||||
                component: this.plugin.component,
 | 
			
		||||
                method: this.handlerSchema.method,
 | 
			
		||||
                initResult: this.initResult,
 | 
			
		||||
                ptrEnabled: this.handlerSchema.ptrenabled,
 | 
			
		||||
            },
 | 
			
		||||
 | 
			
		||||
@ -20,8 +20,10 @@ import {
 | 
			
		||||
} from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CoreUserProfile } from '@features/user/services/user';
 | 
			
		||||
import { CoreUserDelegateService, CoreUserProfileHandler, CoreUserProfileHandlerData } from '@features/user/services/user-delegate';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreUtils, PromiseDefer } from '@services/utils/utils';
 | 
			
		||||
import { Md5 } from 'ts-md5';
 | 
			
		||||
import { CoreSitePluginsBaseHandler } from './base-handler';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -90,17 +92,23 @@ export class CoreSitePluginsUserProfileHandler extends CoreSitePluginsBaseHandle
 | 
			
		||||
                event.preventDefault();
 | 
			
		||||
                event.stopPropagation();
 | 
			
		||||
 | 
			
		||||
                // @todo navCtrl.push('CoreSitePluginsPluginPage', {
 | 
			
		||||
                //     title: this.title,
 | 
			
		||||
                //     component: this.plugin.component,
 | 
			
		||||
                //     method: this.handlerSchema.method,
 | 
			
		||||
                //     args: {
 | 
			
		||||
                //         courseid: courseId,
 | 
			
		||||
                //         userid: user.id
 | 
			
		||||
                //     },
 | 
			
		||||
                //     initResult: this.initResult,
 | 
			
		||||
                //     ptrEnabled: this.handlerSchema.ptrenabled,
 | 
			
		||||
                // });
 | 
			
		||||
                const args = {
 | 
			
		||||
                    courseid: courseId,
 | 
			
		||||
                    userid: user.id,
 | 
			
		||||
                };
 | 
			
		||||
                const hash = <string> Md5.hashAsciiStr(JSON.stringify(args));
 | 
			
		||||
 | 
			
		||||
                CoreNavigator.navigateToSitePath(
 | 
			
		||||
                    `siteplugins/${this.plugin.component}/${this.handlerSchema.method}/${hash}`,
 | 
			
		||||
                    {
 | 
			
		||||
                        params: {
 | 
			
		||||
                            title: this.title,
 | 
			
		||||
                            args,
 | 
			
		||||
                            initResult: this.initResult,
 | 
			
		||||
                            ptrEnabled: this.handlerSchema.ptrenabled,
 | 
			
		||||
                        },
 | 
			
		||||
                    },
 | 
			
		||||
                );
 | 
			
		||||
            },
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -18,7 +18,6 @@ import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreCompileHtmlComponentModule } from '@features/compile/components/compile-html/compile-html.module';
 | 
			
		||||
import { CoreSitePluginsPluginContentComponent } from './plugin-content/plugin-content';
 | 
			
		||||
import { CoreSitePluginsModuleIndexComponent } from './module-index/module-index';
 | 
			
		||||
import { CoreSitePluginsCourseOptionComponent } from './course-option/course-option';
 | 
			
		||||
import { CoreSitePluginsCourseFormatComponent } from './course-format/course-format';
 | 
			
		||||
import { CoreSitePluginsUserProfileFieldComponent } from './user-profile-field/user-profile-field';
 | 
			
		||||
import { CoreSitePluginsQuestionComponent } from './question/question';
 | 
			
		||||
@ -37,7 +36,6 @@ import { CoreSitePluginsOnlyTitleBlockComponent } from './only-title-block/only-
 | 
			
		||||
        CoreSitePluginsModuleIndexComponent,
 | 
			
		||||
        CoreSitePluginsBlockComponent,
 | 
			
		||||
        CoreSitePluginsOnlyTitleBlockComponent,
 | 
			
		||||
        CoreSitePluginsCourseOptionComponent,
 | 
			
		||||
        CoreSitePluginsCourseFormatComponent,
 | 
			
		||||
        CoreSitePluginsUserProfileFieldComponent,
 | 
			
		||||
        CoreSitePluginsQuestionComponent,
 | 
			
		||||
@ -57,7 +55,6 @@ import { CoreSitePluginsOnlyTitleBlockComponent } from './only-title-block/only-
 | 
			
		||||
        CoreSitePluginsModuleIndexComponent,
 | 
			
		||||
        CoreSitePluginsBlockComponent,
 | 
			
		||||
        CoreSitePluginsOnlyTitleBlockComponent,
 | 
			
		||||
        CoreSitePluginsCourseOptionComponent,
 | 
			
		||||
        CoreSitePluginsCourseFormatComponent,
 | 
			
		||||
        CoreSitePluginsUserProfileFieldComponent,
 | 
			
		||||
        CoreSitePluginsQuestionComponent,
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,12 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { OnInit, Component } from '@angular/core';
 | 
			
		||||
import { Md5 } from 'ts-md5';
 | 
			
		||||
 | 
			
		||||
import { CoreBlockBaseComponent } from '@features/block/classes/base-block-component';
 | 
			
		||||
import { CoreBlockDelegate } from '@features/block/services/block-delegate';
 | 
			
		||||
import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CoreSitePlugins, CoreSitePluginsUserHandlerData } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component to render blocks with only a title and link.
 | 
			
		||||
@ -51,18 +53,23 @@ export class CoreSitePluginsOnlyTitleBlockComponent  extends CoreBlockBaseCompon
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // @todo
 | 
			
		||||
        // navCtrl.push('CoreSitePluginsPluginPage', {
 | 
			
		||||
        //     title: this.title,
 | 
			
		||||
        //     component: handler.plugin.component,
 | 
			
		||||
        //     method: handler.handlerSchema.method,
 | 
			
		||||
        //     initResult: handler.initResult,
 | 
			
		||||
        //     args: {
 | 
			
		||||
        //         contextlevel: this.contextLevel,
 | 
			
		||||
        //         instanceid: this.instanceId,
 | 
			
		||||
        //     },
 | 
			
		||||
        //     ptrEnabled: handler.handlerSchema.ptrenabled,
 | 
			
		||||
        // });
 | 
			
		||||
        const args = {
 | 
			
		||||
            contextlevel: this.contextLevel,
 | 
			
		||||
            instanceid: this.instanceId,
 | 
			
		||||
        };
 | 
			
		||||
        const hash = <string> Md5.hashAsciiStr(JSON.stringify(args));
 | 
			
		||||
 | 
			
		||||
        CoreNavigator.navigateToSitePath(
 | 
			
		||||
            `siteplugins/${handler.plugin.component}/${handler.handlerSchema.method}/${hash}`,
 | 
			
		||||
            {
 | 
			
		||||
                params: {
 | 
			
		||||
                    title: this.title,
 | 
			
		||||
                    args,
 | 
			
		||||
                    initResult: handler.initResult,
 | 
			
		||||
                    ptrEnabled: (<CoreSitePluginsUserHandlerData> handler.handlerSchema).ptrenabled,
 | 
			
		||||
                },
 | 
			
		||||
            },
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -13,11 +13,14 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Component, OnInit, Input, Output, EventEmitter, DoCheck, KeyValueDiffers, ViewChild, KeyValueDiffer } from '@angular/core';
 | 
			
		||||
import { Subject } from 'rxjs';
 | 
			
		||||
import { Md5 } from 'ts-md5';
 | 
			
		||||
 | 
			
		||||
import { CoreSiteWSPreSets } from '@classes/site';
 | 
			
		||||
import { CoreCompileHtmlComponent } from '@features/compile/components/compile-html/compile-html';
 | 
			
		||||
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
import { Subject } from 'rxjs';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component to render a site plugin content.
 | 
			
		||||
@ -145,17 +148,21 @@ export class CoreSitePluginsPluginContentComponent implements OnInit, DoCheck {
 | 
			
		||||
            jsData = this.data;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // @todo
 | 
			
		||||
        // this.navCtrl.push('CoreSitePluginsPluginPage', {
 | 
			
		||||
        //     title: title,
 | 
			
		||||
        //     component: component || this.component,
 | 
			
		||||
        //     method: method || this.method,
 | 
			
		||||
        //     args: args,
 | 
			
		||||
        //     initResult: this.initResult,
 | 
			
		||||
        //     jsData: jsData,
 | 
			
		||||
        //     preSets: preSets,
 | 
			
		||||
        //     ptrEnabled: ptrEnabled,
 | 
			
		||||
        // });
 | 
			
		||||
        component = component || this.component;
 | 
			
		||||
        method = method || this.method;
 | 
			
		||||
        args = args || {};
 | 
			
		||||
        const hash = <string> Md5.hashAsciiStr(JSON.stringify(args));
 | 
			
		||||
 | 
			
		||||
        CoreNavigator.navigateToSitePath(`siteplugins/${component}/${method}/${hash}`, {
 | 
			
		||||
            params: {
 | 
			
		||||
                title,
 | 
			
		||||
                args,
 | 
			
		||||
                initResult: this.initResult,
 | 
			
		||||
                jsData,
 | 
			
		||||
                preSets,
 | 
			
		||||
                ptrEnabled,
 | 
			
		||||
            },
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <ion-refresher [disabled]="!ptrEnabled || !content || !content.dataLoaded" (ionRefresh)="refreshData($event.target)">
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!ptrEnabled || !content || !content.dataLoaded"
 | 
			
		||||
        (ionRefresh)="refreshData($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
    <core-site-plugins-plugin-content *ngIf="component && method" [component]="component" [method]="method" [args]="args"
 | 
			
		||||
@ -0,0 +1,45 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CanLeaveGuard } from '@guards/can-leave';
 | 
			
		||||
import { CoreSitePluginsCourseOptionPage } from './course-option';
 | 
			
		||||
import { CoreSitePluginsComponentsModule } from '../../components/components.module';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: '',
 | 
			
		||||
        component: CoreSitePluginsCourseOptionPage,
 | 
			
		||||
        canDeactivate: [CanLeaveGuard],
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module to lazy load the page.
 | 
			
		||||
 */
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreSitePluginsCourseOptionPage,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forChild(routes),
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
        CoreSitePluginsComponentsModule,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [RouterModule],
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsCourseOptionModule {}
 | 
			
		||||
@ -12,27 +12,27 @@
 | 
			
		||||
// See the License for the specific language governing permissions and
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { Component, OnInit, Input, ViewChild } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { Component, OnInit, ViewChild } from '@angular/core';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
import { CoreSitePluginsPluginContentComponent } from '@features/siteplugins/components/plugin-content/plugin-content';
 | 
			
		||||
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { CoreSitePluginsPluginContentComponent } from '../plugin-content/plugin-content';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component that displays the index of a course option site plugin.
 | 
			
		||||
 * Page that displays the index of a course option site plugin.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-site-plugins-course-option',
 | 
			
		||||
    templateUrl: 'core-siteplugins-course-option.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsCourseOptionComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    @Input() courseId?: number;
 | 
			
		||||
    @Input() handlerUniqueName?: string;
 | 
			
		||||
export class CoreSitePluginsCourseOptionPage implements OnInit {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(CoreSitePluginsPluginContentComponent) content?: CoreSitePluginsPluginContentComponent;
 | 
			
		||||
 | 
			
		||||
    courseId?: number;
 | 
			
		||||
    handlerUniqueName?: string;
 | 
			
		||||
    component?: string;
 | 
			
		||||
    method?: string;
 | 
			
		||||
    args?: Record<string, unknown>;
 | 
			
		||||
@ -43,6 +43,9 @@ export class CoreSitePluginsCourseOptionComponent implements OnInit {
 | 
			
		||||
     * Component being initialized.
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.courseId = CoreNavigator.getRouteNumberParam('courseId');
 | 
			
		||||
        this.handlerUniqueName = CoreNavigator.getRouteParam('handlerUniqueName');
 | 
			
		||||
 | 
			
		||||
        if (!this.handlerUniqueName) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@ -75,4 +78,55 @@ export class CoreSitePluginsCourseOptionComponent implements OnInit {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to enter and become the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillEnter(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillEnter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page has fully entered and is now the active page. This event will fire, whether it was the first load or a cached page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidEnter(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewDidEnter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to leave and no longer be the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillLeave(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillLeave');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page has finished leaving and is no longer the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidLeave(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewDidLeave');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to be destroyed and have its elements removed.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillUnload(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillUnload');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if we can leave the page or not.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (!this.content) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        const result = await this.content.callComponentFunction('canLeave');
 | 
			
		||||
 | 
			
		||||
        return result === undefined || result === null ? true : !!result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,19 @@
 | 
			
		||||
<ion-header>
 | 
			
		||||
    <ion-toolbar>
 | 
			
		||||
        <ion-buttons slot="start">
 | 
			
		||||
            <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button>
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
        <ion-title>{{ title }}</ion-title>
 | 
			
		||||
 | 
			
		||||
        <ion-buttons slot="end">
 | 
			
		||||
            <!-- If the site plugin defines some buttons using core-nav-buttons, they will be added here. -->
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!content || !content.ptrEnabled || !content.content || !content.content.dataLoaded"
 | 
			
		||||
        (ionRefresh)="refreshData($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
    <core-site-plugins-module-index [module]="module" [courseId]="courseId" [pageTitle]="title"></core-site-plugins-module-index>
 | 
			
		||||
</ion-content>
 | 
			
		||||
@ -0,0 +1,45 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CanLeaveGuard } from '@guards/can-leave';
 | 
			
		||||
import { CoreSitePluginsModuleIndexPage } from './module-index';
 | 
			
		||||
import { CoreSitePluginsComponentsModule } from '../../components/components.module';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: '',
 | 
			
		||||
        component: CoreSitePluginsModuleIndexPage,
 | 
			
		||||
        canDeactivate: [CanLeaveGuard],
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module to lazy load the page.
 | 
			
		||||
 */
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreSitePluginsModuleIndexPage,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forChild(routes),
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
        CoreSitePluginsComponentsModule,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [RouterModule],
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsModuleIndexPageModule {}
 | 
			
		||||
							
								
								
									
										109
									
								
								src/core/features/siteplugins/pages/module-index/module-index.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/core/features/siteplugins/pages/module-index/module-index.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,109 @@
 | 
			
		||||
// (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, ViewChild } from '@angular/core';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
import { CoreCourseModule } from '@features/course/services/course-helper';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreSitePluginsModuleIndexComponent } from '../../components/module-index/module-index';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page to render the index page of a module site plugin.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'page-core-site-plugins-module-index',
 | 
			
		||||
    templateUrl: 'module-index.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsModuleIndexPage implements OnInit, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(CoreSitePluginsModuleIndexComponent) content?: CoreSitePluginsModuleIndexComponent;
 | 
			
		||||
 | 
			
		||||
    title?: string; // Page title.
 | 
			
		||||
    module?: CoreCourseModule;
 | 
			
		||||
    courseId?: number;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.title = CoreNavigator.getRouteParam('title');
 | 
			
		||||
        this.module = CoreNavigator.getRouteParam('module');
 | 
			
		||||
        this.courseId = CoreNavigator.getRouteNumberParam('courseId');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Refresh the data.
 | 
			
		||||
     *
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    refreshData(refresher: IonRefresher): void {
 | 
			
		||||
        this.content?.doRefresh().finally(() => {
 | 
			
		||||
            refresher.complete();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to enter and become the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillEnter(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillEnter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page has fully entered and is now the active page. This event will fire, whether it was the first load or a cached page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidEnter(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewDidEnter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to leave and no longer be the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillLeave(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillLeave');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page has finished leaving and is no longer the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidLeave(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewDidLeave');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to be destroyed and have its elements removed.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillUnload(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillUnload');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if we can leave the page or not.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (!this.content) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        const result = await this.content.callComponentFunction('canLeave');
 | 
			
		||||
 | 
			
		||||
        return result === undefined || result === null ? true : !!result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -0,0 +1,21 @@
 | 
			
		||||
<ion-header>
 | 
			
		||||
    <ion-toolbar>
 | 
			
		||||
        <ion-buttons slot="start">
 | 
			
		||||
            <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button>
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
        <ion-title *ngIf="title">{{ title | translate }}</ion-title>
 | 
			
		||||
 | 
			
		||||
        <ion-buttons slot="end">
 | 
			
		||||
            <!-- If the site plugin defines some buttons using core-nav-buttons, they will be added here. -->
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <ion-refresher slot="fixed" [disabled]="!ptrEnabled || !content || !content.dataLoaded"
 | 
			
		||||
        (ionRefresh)="refreshData($event.target)">
 | 
			
		||||
        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
			
		||||
    </ion-refresher>
 | 
			
		||||
    <core-site-plugins-plugin-content [component]="component" [method]="method" [args]="args" [preSets]="preSets"
 | 
			
		||||
        [initResult]="initResult" [data]="jsData" [pageTitle]="title">
 | 
			
		||||
    </core-site-plugins-plugin-content>
 | 
			
		||||
</ion-content>
 | 
			
		||||
@ -0,0 +1,45 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CanLeaveGuard } from '@guards/can-leave';
 | 
			
		||||
import { CoreSitePluginsPluginPage } from './plugin-page';
 | 
			
		||||
import { CoreSitePluginsComponentsModule } from '../../components/components.module';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: '',
 | 
			
		||||
        component: CoreSitePluginsPluginPage,
 | 
			
		||||
        canDeactivate: [CanLeaveGuard],
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Module to lazy load the page.
 | 
			
		||||
 */
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreSitePluginsPluginPage,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forChild(routes),
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
        CoreSitePluginsComponentsModule,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [RouterModule],
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsPluginPageModule {}
 | 
			
		||||
							
								
								
									
										120
									
								
								src/core/features/siteplugins/pages/plugin-page/plugin-page.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										120
									
								
								src/core/features/siteplugins/pages/plugin-page/plugin-page.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,120 @@
 | 
			
		||||
// (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, ViewChild } from '@angular/core';
 | 
			
		||||
import { IonRefresher } from '@ionic/angular';
 | 
			
		||||
 | 
			
		||||
import { CoreSiteWSPreSets } from '@classes/site';
 | 
			
		||||
import { CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
 | 
			
		||||
import { CanLeave } from '@guards/can-leave';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { CoreSitePluginsPluginContentComponent } from '../../components/plugin-content/plugin-content';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page to render a site plugin page.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'page-core-site-plugins-plugin',
 | 
			
		||||
    templateUrl: 'plugin-page.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsPluginPage implements OnInit, CanLeave {
 | 
			
		||||
 | 
			
		||||
    @ViewChild(CoreSitePluginsPluginContentComponent) content?: CoreSitePluginsPluginContentComponent;
 | 
			
		||||
 | 
			
		||||
    title?: string; // Page title.
 | 
			
		||||
    component?: string;
 | 
			
		||||
    method?: string;
 | 
			
		||||
    args?: Record<string, unknown>;
 | 
			
		||||
    initResult?: CoreSitePluginsContent | null;
 | 
			
		||||
    jsData?: Record<string, unknown>; // JS variables to pass to the plugin so they can be used in the template or JS.
 | 
			
		||||
    preSets?: CoreSiteWSPreSets; // The preSets for the WS call.
 | 
			
		||||
    ptrEnabled = false;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @inheritdoc
 | 
			
		||||
     */
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.title = CoreNavigator.getRouteParam('title');
 | 
			
		||||
        this.component = CoreNavigator.getRouteParam('component');
 | 
			
		||||
        this.method = CoreNavigator.getRouteParam('method');
 | 
			
		||||
        this.args = CoreNavigator.getRouteParam('args');
 | 
			
		||||
        this.initResult = CoreNavigator.getRouteParam('initResult');
 | 
			
		||||
        this.jsData = CoreNavigator.getRouteParam('jsData');
 | 
			
		||||
        this.preSets = CoreNavigator.getRouteParam('preSets');
 | 
			
		||||
        this.ptrEnabled = !CoreUtils.isFalseOrZero(CoreNavigator.getRouteBooleanParam('ptrEnabled'));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Refresh the data.
 | 
			
		||||
     *
 | 
			
		||||
     * @param refresher Refresher.
 | 
			
		||||
     */
 | 
			
		||||
    refreshData(refresher: IonRefresher): void {
 | 
			
		||||
        this.content?.refreshContent(false).finally(() => {
 | 
			
		||||
            refresher.complete();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to enter and become the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillEnter(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillEnter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page has fully entered and is now the active page. This event will fire, whether it was the first load or a cached page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidEnter(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewDidEnter');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to leave and no longer be the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillLeave(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillLeave');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page has finished leaving and is no longer the active page.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewDidLeave(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewDidLeave');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * The page is about to be destroyed and have its elements removed.
 | 
			
		||||
     */
 | 
			
		||||
    ionViewWillUnload(): void {
 | 
			
		||||
        this.content?.callComponentFunction('ionViewWillUnload');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if we can leave the page or not.
 | 
			
		||||
     *
 | 
			
		||||
     * @return Resolved if we can leave it, rejected if not.
 | 
			
		||||
     */
 | 
			
		||||
    async canLeave(): Promise<boolean> {
 | 
			
		||||
        if (!this.content) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const result = await this.content.callComponentFunction('canLeave');
 | 
			
		||||
 | 
			
		||||
        return result === undefined || result === null ? true : !!result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										32
									
								
								src/core/features/siteplugins/siteplugins-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/core/features/siteplugins/siteplugins-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,32 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: 'module/:courseId/:cmId',
 | 
			
		||||
        loadChildren: () => import('./pages/module-index/module-index.module').then( m => m.CoreSitePluginsModuleIndexPageModule),
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        path: ':component/:method/:hash',
 | 
			
		||||
        loadChildren: () => import('./pages/plugin-page/plugin-page.module').then( m => m.CoreSitePluginsPluginPageModule),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [RouterModule.forChild(routes)],
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsLazyModule {}
 | 
			
		||||
							
								
								
									
										54
									
								
								src/core/features/siteplugins/siteplugins.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/core/features/siteplugins/siteplugins.module.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,54 @@
 | 
			
		||||
// (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 { APP_INITIALIZER, NgModule } from '@angular/core';
 | 
			
		||||
import { Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreCourseIndexRoutingModule } from '@features/course/pages/index/index-routing.module';
 | 
			
		||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
 | 
			
		||||
import { CoreSitePluginsComponentsModule } from './components/components.module';
 | 
			
		||||
import { CoreSitePluginsHelper } from './services/siteplugins-helper';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: 'siteplugins',
 | 
			
		||||
        loadChildren: () => import('@features/siteplugins/siteplugins-lazy.module').then(m => m.CoreSitePluginsLazyModule),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const courseIndexRoutes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: 'siteplugins/:handlerUniqueName',
 | 
			
		||||
        loadChildren: () => import('@features/siteplugins/pages/course-option/course-option.module')
 | 
			
		||||
            .then(m => m.CoreSitePluginsCourseOptionModule),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
        CoreMainMenuTabRoutingModule.forChild(routes),
 | 
			
		||||
        CoreCourseIndexRoutingModule.forChild({ children: courseIndexRoutes }),
 | 
			
		||||
        CoreSitePluginsComponentsModule,
 | 
			
		||||
    ],
 | 
			
		||||
    providers: [
 | 
			
		||||
        {
 | 
			
		||||
            provide: APP_INITIALIZER,
 | 
			
		||||
            multi: true,
 | 
			
		||||
            useValue: () => {
 | 
			
		||||
                CoreSitePluginsHelper.initialize();
 | 
			
		||||
            },
 | 
			
		||||
        },
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreSitePluginsModule {}
 | 
			
		||||
@ -21,6 +21,7 @@ import { CoreTimeAgoPipe } from './time-ago';
 | 
			
		||||
import { CoreBytesToSizePipe } from './bytes-to-size';
 | 
			
		||||
import { CoreDurationPipe } from './duration';
 | 
			
		||||
import { CoreDateDayOrTimePipe } from './date-day-or-time';
 | 
			
		||||
import { CoreToLocaleStringPipe } from './to-locale-string';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
@ -32,6 +33,7 @@ import { CoreDateDayOrTimePipe } from './date-day-or-time';
 | 
			
		||||
        CoreSecondsToHMSPipe,
 | 
			
		||||
        CoreDurationPipe,
 | 
			
		||||
        CoreDateDayOrTimePipe,
 | 
			
		||||
        CoreToLocaleStringPipe,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [],
 | 
			
		||||
    exports: [
 | 
			
		||||
@ -43,6 +45,7 @@ import { CoreDateDayOrTimePipe } from './date-day-or-time';
 | 
			
		||||
        CoreSecondsToHMSPipe,
 | 
			
		||||
        CoreDurationPipe,
 | 
			
		||||
        CoreDateDayOrTimePipe,
 | 
			
		||||
        CoreToLocaleStringPipe,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CorePipesModule {}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										66
									
								
								src/core/pipes/to-locale-string.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/core/pipes/to-locale-string.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,66 @@
 | 
			
		||||
// (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 { Pipe, PipeTransform } from '@angular/core';
 | 
			
		||||
import { CoreTimeUtils } from '@services/utils/time';
 | 
			
		||||
 | 
			
		||||
import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Filter to format a timestamp to a locale string. Timestamp can be in seconds or milliseconds.
 | 
			
		||||
 *
 | 
			
		||||
 * @deprecated since 3.6. Use coreFormatDate instead.
 | 
			
		||||
 */
 | 
			
		||||
@Pipe({
 | 
			
		||||
    name: 'coreToLocaleString',
 | 
			
		||||
})
 | 
			
		||||
export class CoreToLocaleStringPipe implements PipeTransform {
 | 
			
		||||
 | 
			
		||||
    protected logger: CoreLogger;
 | 
			
		||||
 | 
			
		||||
    constructor() {
 | 
			
		||||
        this.logger = CoreLogger.getInstance('CoreToLocaleStringPipe');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Format a timestamp to a locale string.
 | 
			
		||||
     *
 | 
			
		||||
     * @param timestamp The timestamp (can be in seconds or milliseconds).
 | 
			
		||||
     * @return Formatted time.
 | 
			
		||||
     */
 | 
			
		||||
    transform(timestamp: number | string): string {
 | 
			
		||||
        if (typeof timestamp == 'string') {
 | 
			
		||||
            // Convert the value to a number.
 | 
			
		||||
            const numberTimestamp = parseInt(timestamp, 10);
 | 
			
		||||
            if (isNaN(numberTimestamp)) {
 | 
			
		||||
                this.logger.error('Invalid value received', timestamp);
 | 
			
		||||
 | 
			
		||||
                return timestamp;
 | 
			
		||||
            }
 | 
			
		||||
            timestamp = numberTimestamp;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (timestamp < 0) {
 | 
			
		||||
            // Date not valid.
 | 
			
		||||
            return '';
 | 
			
		||||
        }
 | 
			
		||||
        if (timestamp < 100000000000) {
 | 
			
		||||
            // Timestamp is in seconds, convert it to milliseconds.
 | 
			
		||||
            timestamp = timestamp * 1000;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return CoreTimeUtils.userDate(timestamp, 'core.strftimedatetimeshort');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@ -186,15 +186,6 @@ export class CoreUtilsProvider {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Blocks leaving a view.
 | 
			
		||||
     *
 | 
			
		||||
     * @deprecated, use ionViewCanLeave instead.
 | 
			
		||||
     */
 | 
			
		||||
    blockLeaveView(): void {
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if a URL has a redirect.
 | 
			
		||||
     *
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user