MOBILE-4176 grades: Fix 4.1 layout
Fixes some breaking changes introduced in MDL-75513. The fixes included here are not exhaustive but should take care of the basic scenarios covered by e2e tests. Subsequent fixes will be provided to handle other edge-cases.
This commit is contained in:
		
							parent
							
								
									d0e3ad6ee8
								
							
						
					
					
						commit
						49e0491428
					
				| @ -27,13 +27,18 @@ | ||||
|                 </thead> | ||||
|                 <tbody> | ||||
|                     <ng-container *ngFor="let row of rows"> | ||||
|                         <tr *ngIf="!useLegacyLayout && row.itemtype === 'leader'"> | ||||
|                             <td [attr.rowspan]="row.rowspan" class="core-grades-table-leader"></td> | ||||
|                         </tr> | ||||
|                         <tr [attr.role]="row.expandable && showSummary ? 'button row' : 'row'" | ||||
|                             [attr.tabindex]="row.expandable && showSummary && 0" [attr.aria-expanded]="row.expanded" | ||||
|                             [attr.aria-label]="rowAriaLabel(row)" [attr.aria-controls]="row.detailsid" | ||||
|                             (ariaButtonClick)="row.expandable && showSummary && toggleRow(row)" [class]="row.rowclass" | ||||
|                             [class.core-grades-grade-clickable]="row.expandable && showSummary" [id]="'grade-'+row.id"> | ||||
|                             [class.core-grades-grade-clickable]="row.expandable && showSummary" [id]="'grade-'+row.id" | ||||
|                             *ngIf="useLegacyLayout || row.itemtype !== 'leader'"> | ||||
|                             <ng-container *ngIf="row.itemtype"> | ||||
|                                 <td *ngIf="row.itemtype == 'category'" class="core-grades-table-category" [attr.rowspan]="row.rowspan"> | ||||
|                                 <td *ngIf="!useLegacyLayout && row.itemtype == 'category'" class="core-grades-table-category" | ||||
|                                     [attr.rowspan]="row.rowspan"> | ||||
|                                 </td> | ||||
|                                 <th class="core-grades-table-gradeitem ion-text-start" [attr.colspan]="row.colspan"> | ||||
|                                     <ion-icon *ngIf="row.expandable && showSummary" aria-hidden="true" slot="start" name="fas-chevron-right" | ||||
| @ -48,6 +53,7 @@ | ||||
|                                     </core-mod-icon> | ||||
|                                     <span [innerHTML]="row.gradeitem"></span> | ||||
|                                 </th> | ||||
|                                 <ng-container *ngIf="row.itemtype !== 'category'"> | ||||
|                                     <ng-container *ngFor="let column of columns"> | ||||
|                                         <td *ngIf="column.name !== 'gradeitem' && column.name !== 'feedback' && column.name !== 'grade' && | ||||
|                                         row[column.name] != undefined" [class]="'ion-text-start core-grades-table-' + column.name" | ||||
| @ -67,6 +73,7 @@ | ||||
|                                         </td> | ||||
|                                     </ng-container> | ||||
|                                 </ng-container> | ||||
|                             </ng-container> | ||||
|                         </tr> | ||||
|                         <tr *ngIf="row.expandable" [id]="row.detailsid" [class]="row.rowclass" [hidden]="!row.expanded"> | ||||
|                             <td [attr.colspan]="totalColumnsSpan"> | ||||
|  | ||||
| @ -54,6 +54,7 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy { | ||||
|     rows?: CoreGradesFormattedTableRow[]; | ||||
|     totalColumnsSpan?: number; | ||||
|     withinSplitView?: boolean; | ||||
|     useLegacyLayout?: boolean; // Whether to use the layout before 4.1.
 | ||||
| 
 | ||||
|     protected fetchSuccess = false; | ||||
| 
 | ||||
| @ -68,6 +69,7 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy { | ||||
| 
 | ||||
|             this.expandLabel = Translate.instant('core.expand'); | ||||
|             this.collapseLabel = Translate.instant('core.collapse'); | ||||
|             this.useLegacyLayout = !CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('4.1'); | ||||
| 
 | ||||
|             if (route.snapshot.data.swipeEnabled ?? true) { | ||||
|                 const source = CoreRoutedItemsManagerSourcesTracker.getOrCreateSource(CoreGradesCoursesSource, []); | ||||
| @ -133,11 +135,22 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy { | ||||
| 
 | ||||
|         row.expanded = expand ?? !row.expanded; | ||||
| 
 | ||||
|         let colspan: number = this.columns.length + (row.colspan ?? 0) - 1; | ||||
|         let colspan: number = this.columns.length + (row.colspan ?? 0); | ||||
| 
 | ||||
|         if (this.useLegacyLayout) { | ||||
|             colspan--; | ||||
|         } | ||||
| 
 | ||||
|         for (let i = this.rows.indexOf(row) - 1; i >= 0; i--) { | ||||
|             const previousRow = this.rows[i]; | ||||
| 
 | ||||
|             if (previousRow.expandable || !previousRow.colspan || !previousRow.rowspan || previousRow.colspan !== colspan) { | ||||
|             if ( | ||||
|                 !previousRow.rowspan || | ||||
|                 !previousRow.colspan || | ||||
|                 previousRow.colspan !== colspan || | ||||
|                 (!this.useLegacyLayout && previousRow.itemtype !== 'leader') || | ||||
|                 (this.useLegacyLayout && previousRow.expandable) | ||||
|             ) { | ||||
|                 continue; | ||||
|             } | ||||
| 
 | ||||
|  | ||||
| @ -124,6 +124,14 @@ | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     .core-grades-table-leader { | ||||
|         width: 0; | ||||
|     } | ||||
| 
 | ||||
|     .ion-no-border { | ||||
|         border: 0 !important; | ||||
|     } | ||||
| 
 | ||||
|     .dimmed_text, | ||||
|     .hidden { | ||||
|         opacity: .7; | ||||
|  | ||||
| @ -25,6 +25,7 @@ import { | ||||
|     CoreGradesTable, | ||||
|     CoreGradesTableColumn, | ||||
|     CoreGradesTableItemNameColumn, | ||||
|     CoreGradesTableLeaderColumn, | ||||
|     CoreGradesTableRow, | ||||
| } from '@features/grades/services/grades'; | ||||
| import { CoreTextUtils } from '@services/utils/text'; | ||||
| @ -71,7 +72,8 @@ export class CoreGradesHelperProvider { | ||||
|             let content = String(column.content); | ||||
| 
 | ||||
|             if (name == 'itemname') { | ||||
|                 await this.setRowIcon(row, content); | ||||
|                 this.setRowIconAndType(row, content); | ||||
| 
 | ||||
|                 row.link = this.getModuleLink(content); | ||||
|                 row.rowclass += column.class.indexOf('hidden') >= 0 ? ' hidden' : ''; | ||||
|                 row.rowclass += column.class.indexOf('dimmed_text') >= 0 ? ' dimmed_text' : ''; | ||||
| @ -96,10 +98,23 @@ export class CoreGradesHelperProvider { | ||||
|      * Formats a row from the grades table to be rendered in one table. | ||||
|      * | ||||
|      * @param tableRow JSON object representing row of grades table data. | ||||
|      * @param useLegacyLayout Whether to use the layout before 4.1. | ||||
|      * @return Formatted row object. | ||||
|      */ | ||||
|     protected formatGradeRowForTable(tableRow: CoreGradesTableRow): CoreGradesFormattedTableRow { | ||||
|     protected formatGradeRowForTable(tableRow: CoreGradesTableRow, useLegacyLayout: boolean): CoreGradesFormattedTableRow { | ||||
|         const row: CoreGradesFormattedTableRow = {}; | ||||
| 
 | ||||
|         if (!useLegacyLayout && 'leader' in tableRow) { | ||||
|             const row = { | ||||
|                 itemtype: 'leader', | ||||
|                 rowspan: tableRow.leader?.rowspan, | ||||
|             }; | ||||
| 
 | ||||
|             this.setRowEvenOddClass(row, (tableRow.leader as CoreGradesTableLeaderColumn).class); | ||||
| 
 | ||||
|             return row; | ||||
|         } | ||||
| 
 | ||||
|         for (let name in tableRow) { | ||||
|             const column: CoreGradesTableColumn = tableRow[name]; | ||||
| 
 | ||||
| @ -116,13 +131,13 @@ export class CoreGradesHelperProvider { | ||||
|                 row.colspan = itemNameColumn.colspan; | ||||
|                 row.rowspan = tableRow.leader?.rowspan || 1; | ||||
| 
 | ||||
|                 this.setRowIcon(row, content); | ||||
|                 row.rowclass = itemNameColumn.class.indexOf('leveleven') < 0 ? 'odd' : 'even'; | ||||
|                 this.setRowIconAndType(row, content); | ||||
|                 this.setRowEvenOddClass(row, itemNameColumn.class); | ||||
|                 row.rowclass += itemNameColumn.class.indexOf('hidden') >= 0 ? ' hidden' : ''; | ||||
|                 row.rowclass += itemNameColumn.class.indexOf('dimmed_text') >= 0 ? ' dimmed_text' : ''; | ||||
| 
 | ||||
|                 content = content.replace(/<\/span>/gi, '\n'); | ||||
|                 content = CoreTextUtils.cleanTags(content); | ||||
|                 content = CoreTextUtils.cleanTags(content, true); | ||||
|                 name = 'gradeitem'; | ||||
|             } else if (name === 'grade') { | ||||
|                 // Add the pass/fail class if present.
 | ||||
| @ -202,7 +217,7 @@ export class CoreGradesHelperProvider { | ||||
|             feedback: false, | ||||
|             contributiontocoursetotal: false, | ||||
|         }; | ||||
|         formatted.rows = table.tabledata.map(row => this.formatGradeRowForTable(row)); | ||||
|         formatted.rows = this.formatGradesTableRows(table.tabledata); | ||||
| 
 | ||||
|         // Get a row with some info.
 | ||||
|         let normalRow = formatted.rows.find( | ||||
| @ -234,6 +249,33 @@ export class CoreGradesHelperProvider { | ||||
|         return formatted; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Format table rows. | ||||
|      * | ||||
|      * @param rows Unformatted rows. | ||||
|      * @returns Formatted rows. | ||||
|      */ | ||||
|     protected formatGradesTableRows(rows: CoreGradesTableRow[]): CoreGradesFormattedTableRow[] { | ||||
|         const useLegacyLayout = !CoreSites.getRequiredCurrentSite().isVersionGreaterEqualThan('4.1'); | ||||
|         const formattedRows = rows.map(row => this.formatGradeRowForTable(row, useLegacyLayout)); | ||||
| 
 | ||||
|         if (!useLegacyLayout) { | ||||
|             for (let index = 0; index < formattedRows.length - 1; index++) { | ||||
|                 const row = formattedRows[index]; | ||||
|                 const previousRow = formattedRows[index - 1] ?? null; | ||||
| 
 | ||||
|                 if (row.itemtype !== 'leader') { | ||||
|                     continue; | ||||
|                 } | ||||
| 
 | ||||
|                 row.colspan = previousRow.colspan; | ||||
|                 previousRow.rowclass = `${previousRow.rowclass ?? ''} ion-no-border`.trim(); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return formattedRows; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get course data for grades since they only have courseid. | ||||
|      * | ||||
| @ -474,7 +516,7 @@ export class CoreGradesHelperProvider { | ||||
|         // Find href containing "/mod/xxx/xxx.php".
 | ||||
|         const regex = /href="([^"]*\/mod\/[^"|^/]*\/[^"|^.]*\.php[^"]*)/; | ||||
| 
 | ||||
|         return table.tabledata.filter((row) => { | ||||
|         return this.formatGradesTableRows(table.tabledata.filter((row) => { | ||||
|             if (row.itemname && row.itemname.content) { | ||||
|                 const matches = row.itemname.content.match(regex); | ||||
| 
 | ||||
| @ -486,7 +528,7 @@ export class CoreGradesHelperProvider { | ||||
|             } | ||||
| 
 | ||||
|             return false; | ||||
|         }).map((row) => this.formatGradeRowForTable(row)); | ||||
|         })); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -582,14 +624,25 @@ export class CoreGradesHelperProvider { | ||||
|         return CoreGrades.invalidateCourseGradesItemsData(courseId, userId, groupId, siteId); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Set 'odd' or 'even' classes into a row. | ||||
|      * | ||||
|      * @param row Row. | ||||
|      * @param classes Existing row classes. | ||||
|      */ | ||||
|     protected setRowEvenOddClass(row: CoreGradesFormattedTableRow, classes: string): void { | ||||
|         const level = parseInt(classes.match(/(?:^|\s)level(\d+)(?:$|\s)/)?.[1] ?? '0'); | ||||
| 
 | ||||
|         row.rowclass = `${row.rowclass ?? ''} ${level % 2 === 0 ? 'even' : 'odd'}`.trim(); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Parses the image and sets it to the row. | ||||
|      * | ||||
|      * @param row Formatted grade row object. | ||||
|      * @param text HTML where the image will be rendered. | ||||
|      * @return Row object with the image. | ||||
|      * @param row Row. | ||||
|      * @param text Row content. | ||||
|      */ | ||||
|     protected setRowIcon<T extends CoreGradesFormattedRowCommonData>(row: T, text: string): T { | ||||
|     protected setRowIconAndType(row: CoreGradesFormattedRowCommonData, text: string): void { | ||||
|         text = text.replace('%2F', '/').replace('%2f', '/'); | ||||
|         if (text.indexOf('/agg_mean') > -1) { | ||||
|             row.itemtype = 'agg_mean'; | ||||
| @ -603,7 +656,7 @@ export class CoreGradesHelperProvider { | ||||
|             row.itemtype = 'outcome'; | ||||
|             row.icon = 'fas-tasks'; | ||||
|             row.iconAlt = Translate.instant('core.grades.outcome'); | ||||
|         } else if (text.indexOf('i/folder') > -1 || text.indexOf('fa-folder') > -1) { | ||||
|         } else if (text.indexOf('i/folder') > -1 || text.indexOf('fa-folder') > -1 || text.indexOf('category-content') > -1) { | ||||
|             row.itemtype = 'category'; | ||||
|             row.icon = 'fas-folder'; | ||||
|             row.iconAlt = Translate.instant('core.grades.category'); | ||||
| @ -643,8 +696,6 @@ export class CoreGradesHelperProvider { | ||||
|                 row.iconAlt = Translate.instant('core.unknown'); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return row; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user