forked from CIT/Vmeda.Online
		
	MOBILE-3153 course: Implement Course Index tour
This commit is contained in:
		
							parent
							
								
									c5f6b058db
								
							
						
					
					
						commit
						6d71565d6b
					
				@ -1567,6 +1567,8 @@
 | 
				
			|||||||
  "core.course.startdate": "moodle",
 | 
					  "core.course.startdate": "moodle",
 | 
				
			||||||
  "core.course.thisweek": "format_weeks/currentsection",
 | 
					  "core.course.thisweek": "format_weeks/currentsection",
 | 
				
			||||||
  "core.course.todo": "completion",
 | 
					  "core.course.todo": "completion",
 | 
				
			||||||
 | 
					  "core.course.tour_navigation_course_index_student_content": "tool_usertours",
 | 
				
			||||||
 | 
					  "core.course.tour_navigation_course_index_student_title": "tool_usertours",
 | 
				
			||||||
  "core.course.useactivityonbrowser": "local_moodlemobileapp",
 | 
					  "core.course.useactivityonbrowser": "local_moodlemobileapp",
 | 
				
			||||||
  "core.course.viewcourse": "block_timeline",
 | 
					  "core.course.viewcourse": "block_timeline",
 | 
				
			||||||
  "core.course.warningmanualcompletionmodified": "local_moodlemobileapp",
 | 
					  "core.course.warningmanualcompletionmodified": "local_moodlemobileapp",
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								src/assets/img/user-tours/course-index.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								src/assets/img/user-tours/course-index.svg
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 206 143"><rect x=".5" y="11.017" width="180.187" height="112.617" rx="6.143" fill="#EAF6FF"/><mask id="a" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="6" y="11" width="170" height="113"><rect x="6.106" y="11.017" width="168.975" height="112.917" rx="6.143" fill="#EAF6FF"/></mask><g mask="url(#a)"><rect x="77.78" y="20.627" width="25.627" height="6.407" rx="3.203" fill="#86CBFF"/><rect x="28.529" y="37.444" width="124.129" height="10.411" rx="5.205" fill="#86CBFF"/><path fill-rule="evenodd" clip-rule="evenodd" d="M18.944 46.226a1.793 1.793 0 0 1-2.689.083l-4.859-5.178a1.793 1.793 0 1 1 2.615-2.454l3.533 3.765 3.646-4.05a1.793 1.793 0 0 1 2.665 2.4l-4.75 5.277c-.052.056-.105.108-.161.157Z" fill="#86CBFF"/><rect x="28.827" y="56.309" width="92.653" height="10.238" rx="5.119" fill="#C5E6FF"/><circle cx="17.821" cy="61.172" r="6.911" fill="#C5E6FF"/><rect x="28.827" y="76.537" width="78.32" height="10.238" rx="5.119" fill="#C5E6FF"/><circle cx="17.821" cy="81.4" r="6.911" fill="#C5E6FF"/><rect x="28.827" y="96.764" width="110.569" height="10.238" rx="5.119" fill="#C5E6FF"/><circle cx="17.821" cy="101.628" r="6.911" fill="#C5E6FF"/><rect x="28.827" y="116.992" width="90.605" height="10.238" rx="5.119" fill="#C5E6FF"/><circle cx="17.821" cy="121.855" r="6.911" fill="#C5E6FF"/></g><g filter="url(#b)"><rect x="155.45" y="90.299" width="48.05" height="48.05" rx="24.025" fill="#3880FF"/><path d="M170.466 106.952a1.638 1.638 0 1 0 0 3.276 1.638 1.638 0 0 0 0-3.276ZM174.561 107.362a1.228 1.228 0 1 0 0 2.457h14.742a1.229 1.229 0 1 0 0-2.457h-14.742ZM174.561 113.095a1.229 1.229 0 1 0 0 2.457h14.742a1.228 1.228 0 1 0 0-2.457h-14.742ZM173.332 120.057c0-.679.55-1.229 1.229-1.229h14.742a1.229 1.229 0 1 1 0 2.457h-14.742c-.679 0-1.229-.55-1.229-1.228ZM168.828 114.324a1.638 1.638 0 1 1 3.275 0 1.638 1.638 0 0 1-3.275 0ZM170.466 118.419a1.638 1.638 0 1 0 0 3.275 1.638 1.638 0 0 0 0-3.275Z" fill="#fff"/></g><path d="m166.471 0-11.559 20.02h23.118L166.471 0Zm-2.002 79.282a2.002 2.002 0 1 0 4.004 0h-4.004Zm0-69.844a2.002 2.002 0 1 0 4.004 0h-4.004Zm4.004 7.551a2.002 2.002 0 1 0-4.004 0h4.004Zm-4.004 18.877a2.002 2.002 0 1 0 4.004 0h-4.004Zm4.004 7.55a2.002 2.002 0 1 0-4.004 0h4.004Zm-4.004 18.877a2.002 2.002 0 1 0 4.004 0h-4.004Zm4.004 7.55a2.002 2.002 0 1 0-4.004 0h4.004Zm-4.004-52.854v18.877h4.004V16.989h-4.004Zm0 26.427v18.877h4.004V43.416h-4.004Zm0 26.428v9.438h4.004v-9.438h-4.004Z" fill="#0056B3"/><defs><filter id="b" x="153.266" y="90.299" width="52.418" height="52.418" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB"><feFlood flood-opacity="0" result="BackgroundImageFix"/><feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/><feOffset dy="2.184"/><feGaussianBlur stdDeviation="1.092"/><feComposite in2="hardAlpha" operator="out"/><feColorMatrix values="0 0 0 0 0.120972 0 0 0 0 0.203233 0 0 0 0 0.279167 0 0 0 0.25 0"/><feBlend in2="BackgroundImageFix" result="effect1_dropShadow_319_9155"/><feBlend in="SourceGraphic" in2="effect1_dropShadow_319_9155" result="shape"/></filter></defs></svg>
 | 
				
			||||||
| 
		 After Width: | Height: | Size: 3.1 KiB  | 
@ -28,6 +28,7 @@ import { CoreCourseModuleInfoComponent } from './module-info/module-info';
 | 
				
			|||||||
import { CoreCourseModuleManualCompletionComponent } from './module-manual-completion/module-manual-completion';
 | 
					import { CoreCourseModuleManualCompletionComponent } from './module-manual-completion/module-manual-completion';
 | 
				
			||||||
import { CoreCourseModuleNavigationComponent } from './module-navigation/module-navigation';
 | 
					import { CoreCourseModuleNavigationComponent } from './module-navigation/module-navigation';
 | 
				
			||||||
import { CoreCourseModuleSummaryComponent } from './module-summary/module-summary';
 | 
					import { CoreCourseModuleSummaryComponent } from './module-summary/module-summary';
 | 
				
			||||||
 | 
					import { CoreCourseCourseIndexTourComponent } from './course-index-tour/course-index-tour';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@NgModule({
 | 
					@NgModule({
 | 
				
			||||||
    declarations: [
 | 
					    declarations: [
 | 
				
			||||||
@ -39,6 +40,7 @@ import { CoreCourseModuleSummaryComponent } from './module-summary/module-summar
 | 
				
			|||||||
        CoreCourseModuleInfoComponent,
 | 
					        CoreCourseModuleInfoComponent,
 | 
				
			||||||
        CoreCourseModuleManualCompletionComponent,
 | 
					        CoreCourseModuleManualCompletionComponent,
 | 
				
			||||||
        CoreCourseCourseIndexComponent,
 | 
					        CoreCourseCourseIndexComponent,
 | 
				
			||||||
 | 
					        CoreCourseCourseIndexTourComponent,
 | 
				
			||||||
        CoreCourseTagAreaComponent,
 | 
					        CoreCourseTagAreaComponent,
 | 
				
			||||||
        CoreCourseUnsupportedModuleComponent,
 | 
					        CoreCourseUnsupportedModuleComponent,
 | 
				
			||||||
        CoreCourseModuleNavigationComponent,
 | 
					        CoreCourseModuleNavigationComponent,
 | 
				
			||||||
@ -57,6 +59,7 @@ import { CoreCourseModuleSummaryComponent } from './module-summary/module-summar
 | 
				
			|||||||
        CoreCourseModuleInfoComponent,
 | 
					        CoreCourseModuleInfoComponent,
 | 
				
			||||||
        CoreCourseModuleManualCompletionComponent,
 | 
					        CoreCourseModuleManualCompletionComponent,
 | 
				
			||||||
        CoreCourseCourseIndexComponent,
 | 
					        CoreCourseCourseIndexComponent,
 | 
				
			||||||
 | 
					        CoreCourseCourseIndexTourComponent,
 | 
				
			||||||
        CoreCourseTagAreaComponent,
 | 
					        CoreCourseTagAreaComponent,
 | 
				
			||||||
        CoreCourseUnsupportedModuleComponent,
 | 
					        CoreCourseUnsupportedModuleComponent,
 | 
				
			||||||
        CoreCourseModuleNavigationComponent,
 | 
					        CoreCourseModuleNavigationComponent,
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
<!-- Course Index button. -->
 | 
					<!-- Course Index button. -->
 | 
				
			||||||
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="loaded && displayCourseIndex">
 | 
					<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="loaded && displayCourseIndex">
 | 
				
			||||||
    <ion-fab-button (click)="openCourseIndex()" [attr.aria-label]="'core.course.courseindex' | translate" color="secondary">
 | 
					    <ion-fab-button (click)="openCourseIndex()" (onAppear)="showCourseIndexTour()" [attr.aria-label]="'core.course.courseindex' | translate"
 | 
				
			||||||
 | 
					        color="secondary" #courseIndexFab>
 | 
				
			||||||
        <ion-icon name="fas-list-ul" aria-hidden="true"></ion-icon>
 | 
					        <ion-icon name="fas-list-ul" aria-hidden="true"></ion-icon>
 | 
				
			||||||
        <span class="sr-only">{{'core.course.courseindex' | translate }}</span>
 | 
					        <span class="sr-only">{{'core.course.courseindex' | translate }}</span>
 | 
				
			||||||
    </ion-fab-button>
 | 
					    </ion-fab-button>
 | 
				
			||||||
 | 
				
			|||||||
@ -23,6 +23,7 @@ import {
 | 
				
			|||||||
    QueryList,
 | 
					    QueryList,
 | 
				
			||||||
    Type,
 | 
					    Type,
 | 
				
			||||||
    ElementRef,
 | 
					    ElementRef,
 | 
				
			||||||
 | 
					    ViewChild,
 | 
				
			||||||
} from '@angular/core';
 | 
					} from '@angular/core';
 | 
				
			||||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
					import { CoreDomUtils } from '@services/utils/dom';
 | 
				
			||||||
import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
 | 
					import { CoreDynamicComponent } from '@components/dynamic-component/dynamic-component';
 | 
				
			||||||
@ -44,6 +45,8 @@ import { CoreBlockHelper } from '@features/block/services/block-helper';
 | 
				
			|||||||
import { CoreNavigator } from '@services/navigator';
 | 
					import { CoreNavigator } from '@services/navigator';
 | 
				
			||||||
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
 | 
					import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
 | 
				
			||||||
import { CoreCourseViewedModulesDBRecord } from '@features/course/services/database/course';
 | 
					import { CoreCourseViewedModulesDBRecord } from '@features/course/services/database/course';
 | 
				
			||||||
 | 
					import { CoreUserTours, CoreUserToursAlignment, CoreUserToursSide } from '@features/usertours/services/user-tours';
 | 
				
			||||||
 | 
					import { CoreCourseCourseIndexTourComponent } from '../course-index-tour/course-index-tour';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Component to display course contents using a certain format. If the format isn't found, use default one.
 | 
					 * Component to display course contents using a certain format. If the format isn't found, use default one.
 | 
				
			||||||
@ -71,6 +74,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
 | 
				
			|||||||
    @Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
 | 
					    @Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @ViewChildren(CoreDynamicComponent) dynamicComponents?: QueryList<CoreDynamicComponent>;
 | 
					    @ViewChildren(CoreDynamicComponent) dynamicComponents?: QueryList<CoreDynamicComponent>;
 | 
				
			||||||
 | 
					    @ViewChild('courseIndexFab', { read: ElementRef }) courseIndexFab?: ElementRef<HTMLElement>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // All the possible component classes.
 | 
					    // All the possible component classes.
 | 
				
			||||||
    courseFormatComponent?: Type<unknown>;
 | 
					    courseFormatComponent?: Type<unknown>;
 | 
				
			||||||
@ -160,6 +164,25 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Show Course Index User Tour.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async showCourseIndexTour(): Promise<void> {
 | 
				
			||||||
 | 
					        const nativeButton = this.courseIndexFab?.nativeElement.shadowRoot?.children[0] as HTMLElement;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (!nativeButton) {
 | 
				
			||||||
 | 
					            return;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        await CoreUserTours.showIfPending({
 | 
				
			||||||
 | 
					            id: 'course-index',
 | 
				
			||||||
 | 
					            component: CoreCourseCourseIndexTourComponent,
 | 
				
			||||||
 | 
					            focus: nativeButton,
 | 
				
			||||||
 | 
					            side: CoreUserToursSide.Top,
 | 
				
			||||||
 | 
					            alignment: CoreUserToursAlignment.End,
 | 
				
			||||||
 | 
					        });
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Detect changes on input properties.
 | 
					     * Detect changes on input properties.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					<h2>{{ 'core.course.tour_navigation_course_index_student_title' | translate }}</h2>
 | 
				
			||||||
 | 
					<img src="assets/img/user-tours/course-index.svg" alt="" />
 | 
				
			||||||
 | 
					<p>{{ 'core.course.tour_navigation_course_index_student_content' | translate }}</p>
 | 
				
			||||||
 | 
					<ion-button (click)="dismiss()" expand="block">
 | 
				
			||||||
 | 
					    {{ 'core.endonesteptour' | translate }}
 | 
				
			||||||
 | 
					</ion-button>
 | 
				
			||||||
@ -0,0 +1,15 @@
 | 
				
			|||||||
 | 
					:host {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    h2 {
 | 
				
			||||||
 | 
					        margin-top: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    p {
 | 
				
			||||||
 | 
					        text-align: center;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ion-button {
 | 
				
			||||||
 | 
					        margin: 0;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,35 @@
 | 
				
			|||||||
 | 
					// (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 } from '@angular/core';
 | 
				
			||||||
 | 
					import { CoreUserTours } from '@features/usertours/services/user-tours';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Component showing the User Tour for the Course Index feature.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@Component({
 | 
				
			||||||
 | 
					    selector: 'core-course-course-index-tour',
 | 
				
			||||||
 | 
					    templateUrl: 'course-index-tour.html',
 | 
				
			||||||
 | 
					    styleUrls: ['course-index-tour.scss'],
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					export class CoreCourseCourseIndexTourComponent {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Dismiss the User Tour.
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    async dismiss(): Promise<void> {
 | 
				
			||||||
 | 
					        await CoreUserTours.dismiss();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -54,6 +54,8 @@
 | 
				
			|||||||
    "startdate": "Course start date",
 | 
					    "startdate": "Course start date",
 | 
				
			||||||
    "thisweek": "This week",
 | 
					    "thisweek": "This week",
 | 
				
			||||||
    "todo": "To do",
 | 
					    "todo": "To do",
 | 
				
			||||||
 | 
					    "tour_navigation_course_index_student_content": "Browse through activities and track your progress.",
 | 
				
			||||||
 | 
					    "tour_navigation_course_index_student_title": "Find your way around",
 | 
				
			||||||
    "useactivityonbrowser": "You can still use it using your device's web browser.",
 | 
					    "useactivityonbrowser": "You can still use it using your device's web browser.",
 | 
				
			||||||
    "viewcourse": "View course",
 | 
					    "viewcourse": "View course",
 | 
				
			||||||
    "warningmanualcompletionmodified": "The manual completion of an activity was modified on the site.",
 | 
					    "warningmanualcompletionmodified": "The manual completion of an activity was modified on the site.",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user