forked from EVOgeek/Vmeda.Online
		
	MOBILE-3915 course: Align icons on course index
This commit is contained in:
		
							parent
							
								
									6b3d39068c
								
							
						
					
					
						commit
						1e2eb7e4fb
					
				| @ -12,9 +12,9 @@ | |||||||
| </ion-header> | </ion-header> | ||||||
| <ion-content> | <ion-content> | ||||||
|     <ion-list id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label"> |     <ion-list id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label"> | ||||||
|         <ng-container *ngFor="let section of sections"> |         <ng-container *ngFor="let section of sectionsToRender"> | ||||||
|             <ion-item *ngIf="allSectionId == section.id" class="ion-text-wrap divider" (click)="selectSection($event, section)" button |             <ion-item *ngIf="allSectionId == section.id" class="ion-text-wrap divider core-course-index-all" | ||||||
|                 [class.item-current]="selectedId === section.id" detail="false"> |                 (click)="selectSectionOrModule($event, section.id)" button [class.item-current]="selectedId === section.id" detail="false"> | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     <p class="item-heading"> |                     <p class="item-heading"> | ||||||
|                         <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id"> |                         <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id"> | ||||||
| @ -22,16 +22,17 @@ | |||||||
|                     </p> |                     </p> | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
|             </ion-item> |             </ion-item> | ||||||
|             <ng-container *ngIf="allSectionId != section.id && !section.hiddenbynumsections && |             <ng-container *ngIf="allSectionId != section.id"> | ||||||
|                     section.id != stealthModulesSectionId && section.uservisible !== false"> |                 <ion-item class="ion-text-wrap divider section" (click)="selectSectionOrModule($event, section.id)" button | ||||||
|                 <ion-item class="ion-text-wrap divider section" (click)="selectSection($event, section)" |                     [class.item-current]="selectedId === section.id" [class.item-dimmed]="section.visible === 0" detail="false" | ||||||
|                     [button]="section.visible !== 0 && section.uservisible !== false" [class.item-current]="selectedId === section.id" |                     sticky="true"> | ||||||
|                     [class.item-dimmed]="section.visible === 0" detail="false" sticky="true"> |                     <ion-icon *ngIf="section.hasVisibleModules" [name]="section.expanded ? 'fas-chevron-down' : 'fas-chevron-right'" | ||||||
|                     <ion-icon [name]="section.expanded ? 'fas-chevron-down' : 'fas-chevron-right'" flip-rtl slot="start" |                         flip-rtl slot="start" class="expandable-status-icon" (click)="toggleExpand($event, section)" | ||||||
|                         class="expandable-status-icon" (click)="toggleExpand($event, section)" |  | ||||||
|                         [attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate" |                         [attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate" | ||||||
|                         [attr.aria-expanded]="section.expanded" [attr.aria-controls]="'core-course-index-section-' + section.id"> |                         [attr.aria-expanded]="section.expanded" [attr.aria-controls]="'core-course-index-section-' + section.id"> | ||||||
|                     </ion-icon> |                     </ion-icon> | ||||||
|  |                     <ion-icon *ngIf="!section.hasVisibleModules" name="" slot="start" aria-hidden="true" class="expandable-status-icon"> | ||||||
|  |                     </ion-icon> | ||||||
|                     <ion-label> |                     <ion-label> | ||||||
|                         <p class="item-heading"> |                         <p class="item-heading"> | ||||||
|                             <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id"> |                             <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id"> | ||||||
| @ -42,37 +43,34 @@ | |||||||
|                     <ion-icon name="fas-lock" *ngIf="section.availabilityinfo" slot="end" class="restricted" |                     <ion-icon name="fas-lock" *ngIf="section.availabilityinfo" slot="end" class="restricted" | ||||||
|                         [attr.aria-label]="'core.restricted' | translate"></ion-icon> |                         [attr.aria-label]="'core.restricted' | translate"></ion-icon> | ||||||
|                 </ion-item> |                 </ion-item> | ||||||
|                 <div [hidden]="!section.expanded" [id]="'core-course-index-section-' + section.id"> |                 <ng-container *ngIf="section.expanded"> | ||||||
|                     <ng-container *ngIf="section.expanded"> |                     <ng-container *ngFor="let module of section.modules"> | ||||||
|                         <ng-container *ngFor="let module of section.modules"> |                         <ion-item [class.item-dimmed]="!module.visible" (click)="selectSectionOrModule($event, section.id, module.id)" | ||||||
|                             <ion-item [class.item-dimmed]="module.visible === 0" |                             button> | ||||||
|                                 *ngIf="module.visibleoncoursepage !== 0 && !module.noviewlink" |                             <ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined" | ||||||
|                                 (click)="selectModule($event, section, module)" button> |                                 slot="start" aria-hidden="true"></ion-icon> | ||||||
|                                 <ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined" |                             <ion-icon class="completioninfo completion_incomplete" name="far-circle" *ngIf="module.completionStatus === 0" | ||||||
|                                     slot="start" aria-hidden="true"></ion-icon> |                                 slot="start" [attr.aria-label]="'core.course.todo' | translate"> | ||||||
|                                 <ion-icon class="completioninfo completion_incomplete" name="far-circle" |                             </ion-icon> | ||||||
|                                     *ngIf="module.completionStatus === 0" slot="start" [attr.aria-label]="'core.course.todo' | translate"> |                             <ion-icon class="completioninfo completion_complete" name="fas-circle" | ||||||
|                                 </ion-icon> |                                 *ngIf="module.completionStatus === 1 || module.completionStatus === 2" color="success" slot="start" | ||||||
|                                 <ion-icon class="completioninfo completion_complete" name="fas-circle" |                                 [attr.aria-label]="'core.course.done' | translate"> | ||||||
|                                     *ngIf="module.completionStatus === 1 || module.completionStatus === 2" color="success" slot="start" |                             </ion-icon> | ||||||
|                                     [attr.aria-label]="'core.course.done' | translate"> |                             <ion-icon class="completioninfo completion_fail" name="fas-circle" *ngIf="module.completionStatus === 3" | ||||||
|                                 </ion-icon> |                                 color="danger" slot="start" [attr.aria-label]="'core.course.failed' | translate"> | ||||||
|                                 <ion-icon class="completioninfo completion_fail" name="fas-circle" *ngIf="module.completionStatus === 3" |                             </ion-icon> | ||||||
|                                     color="danger" slot="start" [attr.aria-label]="'core.course.failed' | translate"> |                             <ion-label> | ||||||
|                                 </ion-icon> |                                 <p class="item-heading"> | ||||||
|                                 <ion-label> |                                     <core-format-text [text]="module.name" contextLevel="module" [contextInstanceId]="module.id" | ||||||
|                                     <p class="item-heading"> |                                         [courseId]="module.course"> | ||||||
|                                         <core-format-text [text]="module.name" contextLevel="module" [contextInstanceId]="module.id" |                                     </core-format-text> | ||||||
|                                             [courseId]="module.courseid"> |                                 </p> | ||||||
|                                         </core-format-text> |                             </ion-label> | ||||||
|                                     </p> |                             <ion-icon name="fas-lock" *ngIf="!module.uservisible" slot="end" class="restricted" | ||||||
|                                 </ion-label> |                                 [attr.aria-label]="'core.restricted' | translate"></ion-icon> | ||||||
|                                 <ion-icon name="fas-lock" *ngIf="module.uservisible === false" slot="end" class="restricted" |                         </ion-item> | ||||||
|                                     [attr.aria-label]="'core.restricted' | translate"></ion-icon> |  | ||||||
|                             </ion-item> |  | ||||||
|                         </ng-container> |  | ||||||
|                     </ng-container> |                     </ng-container> | ||||||
|                 </div> |                 </ng-container> | ||||||
|             </ng-container> |             </ng-container> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|     </ion-list> |     </ion-list> | ||||||
|  | |||||||
| @ -16,18 +16,21 @@ ion-icon.completioninfo { | |||||||
|     width: 18px; |     width: 18px; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-item.section::part(native) { | ion-item::part(native) { | ||||||
|     --padding-start: 0; |     --padding-start: 0; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-icon.expandable-status-icon { | ion-icon { | ||||||
|     margin: 0; |     margin: 0; | ||||||
|     @include padding(12px, 32px, 12px, 16px); |     @include padding(12px, 32px, 12px, 16px); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | ion-item.core-course-index-all::part(native) { | ||||||
|  |     --padding-start: 16px; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| ion-item.item-current ion-icon.expandable-status-icon { | ion-item.item-current ion-icon.expandable-status-icon { | ||||||
|     @include padding(null, null, null, 11px); |     @include padding(null, null, null, 11px); | ||||||
| 
 |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-icon.restricted { | ion-icon.restricted { | ||||||
|  | |||||||
| @ -13,19 +13,18 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; | import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; | ||||||
| 
 |  | ||||||
| import { CoreCourseModuleData, CoreCourseSection } from '@features/course/services/course-helper'; |  | ||||||
| import { | import { | ||||||
|     CoreCourseModuleCompletionStatus, |     CoreCourseModuleCompletionStatus, | ||||||
|     CoreCourseModuleCompletionTracking, |     CoreCourseModuleCompletionTracking, | ||||||
|     CoreCourseProvider, |     CoreCourseProvider, | ||||||
| } from '@features/course/services/course'; | } from '@features/course/services/course'; | ||||||
| import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; | import { CoreCourseSection } from '@features/course/services/course-helper'; | ||||||
| import { CoreUtils } from '@services/utils/utils'; |  | ||||||
| import { ModalController } from '@singletons'; |  | ||||||
| import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; | import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate'; | ||||||
|  | import { CoreCourseAnyCourseData } from '@features/courses/services/courses'; | ||||||
| import { IonContent } from '@ionic/angular'; | import { IonContent } from '@ionic/angular'; | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
|  | import { CoreUtils } from '@services/utils/utils'; | ||||||
|  | import { ModalController } from '@singletons'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * Component to display course index modal. |  * Component to display course index modal. | ||||||
| @ -39,13 +38,13 @@ export class CoreCourseCourseIndexComponent implements OnInit { | |||||||
| 
 | 
 | ||||||
|     @ViewChild(IonContent) content?: IonContent; |     @ViewChild(IonContent) content?: IonContent; | ||||||
| 
 | 
 | ||||||
|     @Input() sections?: CourseIndexSection[]; |     @Input() sections: CoreCourseSection[] = []; | ||||||
|     @Input() selectedId?: number; |     @Input() selectedId?: number; | ||||||
|     @Input() course?: CoreCourseAnyCourseData; |     @Input() course?: CoreCourseAnyCourseData; | ||||||
| 
 | 
 | ||||||
|     stealthModulesSectionId = CoreCourseProvider.STEALTH_MODULES_SECTION_ID; |  | ||||||
|     allSectionId = CoreCourseProvider.ALL_SECTIONS_ID; |     allSectionId = CoreCourseProvider.ALL_SECTIONS_ID; | ||||||
|     highlighted?: string; |     highlighted?: string; | ||||||
|  |     sectionsToRender: CourseIndexSection[] = []; | ||||||
| 
 | 
 | ||||||
|     constructor( |     constructor( | ||||||
|         protected elementRef: ElementRef, |         protected elementRef: ElementRef, | ||||||
| @ -70,29 +69,47 @@ export class CoreCourseCourseIndexComponent implements OnInit { | |||||||
|             return; |             return; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         // Collapse all sections first.
 |  | ||||||
|         this.sections.forEach((section) => section.expanded = false); |  | ||||||
| 
 |  | ||||||
|         const currentSection = await CoreCourseFormatDelegate.getCurrentSection(this.course, this.sections); |         const currentSection = await CoreCourseFormatDelegate.getCurrentSection(this.course, this.sections); | ||||||
|         currentSection.highlighted = true; | 
 | ||||||
|         if (this.selectedId === undefined) { |         if (this.selectedId === undefined) { | ||||||
|             currentSection.expanded = true; |             // Highlight current section if none is selected.
 | ||||||
|             this.selectedId = currentSection.id; |             this.selectedId = currentSection.id; | ||||||
|         } else { |  | ||||||
|             const selectedSection = this.sections.find((section) => section.id == this.selectedId); |  | ||||||
|             if (selectedSection) { |  | ||||||
|                 selectedSection.expanded = true; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         this.sections.forEach((section) => { |         // Clone sections to add information.
 | ||||||
|             section.modules.forEach((module) => { |         this.sectionsToRender = this.sections | ||||||
|                 module.completionStatus = module.completiondata === undefined || |             .filter((section) => !section.hiddenbynumsections && | ||||||
|                     module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE |                 section.id != CoreCourseProvider.STEALTH_MODULES_SECTION_ID && | ||||||
|                     ? undefined |                 section.uservisible !== false) | ||||||
|                     : module.completiondata.state; |             .map((section) => { | ||||||
|  |                 const modules = section.modules | ||||||
|  |                     .filter((module) => module.visibleoncoursepage !== 0 && !module.noviewlink) | ||||||
|  |                     .map((module) => { | ||||||
|  |                         const completionStatus = module.completiondata === undefined || | ||||||
|  |                         module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE | ||||||
|  |                             ? undefined | ||||||
|  |                             : module.completiondata.state; | ||||||
|  | 
 | ||||||
|  |                         return { | ||||||
|  |                             id: module.id, | ||||||
|  |                             name: module.name, | ||||||
|  |                             course: module.course, | ||||||
|  |                             visible: !!module.visible, | ||||||
|  |                             uservisible: !!module.uservisible, | ||||||
|  |                             completionStatus, | ||||||
|  |                         }; | ||||||
|  |                     }); | ||||||
|  | 
 | ||||||
|  |                 return { | ||||||
|  |                     id: section.id, | ||||||
|  |                     name: section.name, | ||||||
|  |                     availabilityinfo: !!section.availabilityinfo, | ||||||
|  |                     expanded: section.id === this.selectedId, | ||||||
|  |                     highlighted: currentSection?.id === section.id, | ||||||
|  |                     hasVisibleModules: modules.length > 0, | ||||||
|  |                     modules: modules, | ||||||
|  |                 }; | ||||||
|             }); |             }); | ||||||
|         }); |  | ||||||
| 
 | 
 | ||||||
|         this.highlighted = CoreCourseFormatDelegate.getSectionHightlightedName(this.course); |         this.highlighted = CoreCourseFormatDelegate.getSectionHightlightedName(this.course); | ||||||
| 
 | 
 | ||||||
| @ -102,7 +119,7 @@ export class CoreCourseCourseIndexComponent implements OnInit { | |||||||
|                 this.content, |                 this.content, | ||||||
|                 '.item.item-current', |                 '.item.item-current', | ||||||
|             ); |             ); | ||||||
|         }, 200); |         }, 300); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -128,39 +145,33 @@ export class CoreCourseCourseIndexComponent implements OnInit { | |||||||
|      * Select a section. |      * Select a section. | ||||||
|      * |      * | ||||||
|      * @param event Event. |      * @param event Event. | ||||||
|      * @param section Selected section object. |      * @param sectionId Selected section id. | ||||||
|  |      * @param moduleId Selected module id, if any. | ||||||
|      */ |      */ | ||||||
|     selectSection(event: Event, section: CoreCourseSection): void { |     selectSectionOrModule(event: Event, sectionId: number, moduleId?: number): void { | ||||||
|         if (section.uservisible !== false) { |         ModalController.dismiss({ event, sectionId, moduleId }); | ||||||
|             ModalController.dismiss({ event, section }); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Select a section and open a module |  | ||||||
|      * |  | ||||||
|      * @param event Event. |  | ||||||
|      * @param section Selected section object. |  | ||||||
|      * @param module Selected module object. |  | ||||||
|      */ |  | ||||||
|     selectModule(event: Event,section: CoreCourseSection, module: CoreCourseModuleData): void { |  | ||||||
|         if (module.uservisible !== false) { |  | ||||||
|             ModalController.dismiss({ event, section, module }); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| type CourseIndexSection = Omit<CoreCourseSection, 'modules'> & { | type CourseIndexSection = { | ||||||
|     highlighted?: boolean; |     id: number; | ||||||
|     expanded?: boolean; |     name: string; | ||||||
|     modules: (CoreCourseModuleData & { |     highlighted: boolean; | ||||||
|  |     expanded: boolean; | ||||||
|  |     hasVisibleModules: boolean; | ||||||
|  |     availabilityinfo: boolean; | ||||||
|  |     modules: { | ||||||
|  |         id: number; | ||||||
|  |         course: number; | ||||||
|  |         visible: boolean; | ||||||
|  |         uservisible: boolean; | ||||||
|         completionStatus?: CoreCourseModuleCompletionStatus; |         completionStatus?: CoreCourseModuleCompletionStatus; | ||||||
|     })[]; |     }[]; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| export type CoreCourseIndexSectionWithModule = { | export type CoreCourseIndexSectionWithModule = { | ||||||
|     event: Event; |     event: Event; | ||||||
|     section: CourseIndexSection; |     sectionId: number; | ||||||
|     module?: CoreCourseModuleData; |     moduleId?: number; | ||||||
| }; | }; | ||||||
|  | |||||||
| @ -69,7 +69,6 @@ | |||||||
|         class="section-wrapper" [id]="section.id"> |         class="section-wrapper" [id]="section.id"> | ||||||
|         <ion-item-divider class="course-section ion-text-wrap" color="light" |         <ion-item-divider class="course-section ion-text-wrap" color="light" | ||||||
|             [class.item-dimmed]="section.visible === 0 || section.uservisible === false"> |             [class.item-dimmed]="section.visible === 0 || section.uservisible === false"> | ||||||
|             <ion-icon name="fas-folder" aria-label="hidden" slot="start"></ion-icon> |  | ||||||
|             <ion-label> |             <ion-label> | ||||||
|                 <h2 *ngIf="section.name"> |                 <h2 *ngIf="section.name"> | ||||||
|                     <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course.id"> |                     <core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course.id"> | ||||||
|  | |||||||
| @ -312,20 +312,33 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|             }, |             }, | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|         if (data) { |         if (!data) { | ||||||
|             this.sectionChanged(data.section); |             return; | ||||||
|             if (data.module) { |  | ||||||
|                 if (!data.module.handlerData) { |  | ||||||
|                     data.module.handlerData = |  | ||||||
|                         await CoreCourseModuleDelegate.getModuleDataFor(data.module.modname, data.module, this.course.id); |  | ||||||
|                 } |  | ||||||
| 
 |  | ||||||
|                 if (data.module.uservisible !== false && data.module.handlerData?.action) { |  | ||||||
|                     data.module.handlerData.action(data.event, data.module, data.module.course); |  | ||||||
|                 } |  | ||||||
|                 this.moduleId = data.module.id; |  | ||||||
|             } |  | ||||||
|         } |         } | ||||||
|  |         const section = this.sections.find((section) => section.id == data.sectionId); | ||||||
|  |         if (!section) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         this.sectionChanged(section); | ||||||
|  | 
 | ||||||
|  |         if (!data.moduleId) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  |         const module = section.modules.find((module) => module.id == data.moduleId); | ||||||
|  |         if (!module) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!module.handlerData) { | ||||||
|  |             module.handlerData = | ||||||
|  |                             await CoreCourseModuleDelegate.getModuleDataFor(module.modname, module, this.course.id); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (module.uservisible !== false && module.handlerData?.action) { | ||||||
|  |             module.handlerData.action(data.event, module, module.course); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.moduleId = data.moduleId; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user