commit
						136f50ba37
					
				
							
								
								
									
										19
									
								
								.eslintrc.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								.eslintrc.js
									
									
									
									
									
								
							| @ -15,7 +15,6 @@ const appConfig = { | ||||
|         'eslint:recommended', | ||||
|         'plugin:@typescript-eslint/recommended', | ||||
|         'prettier', | ||||
|         'prettier/@typescript-eslint', | ||||
|         'plugin:@angular-eslint/recommended', | ||||
|         'plugin:promise/recommended', | ||||
|     ], | ||||
| @ -90,7 +89,16 @@ const appConfig = { | ||||
|                 }, | ||||
|             }, | ||||
|         ], | ||||
|         '@typescript-eslint/member-ordering': 'error', | ||||
|         '@typescript-eslint/member-ordering': [ | ||||
|             'error', | ||||
|             { | ||||
|                 default: | ||||
|                 { | ||||
|                     order: 'as-written', | ||||
|                 }, | ||||
| 
 | ||||
|             } | ||||
|         ], | ||||
|         '@typescript-eslint/naming-convention': [ | ||||
|             'error', | ||||
|             { | ||||
| @ -276,6 +284,13 @@ module.exports = { | ||||
|             extends: ['plugin:@angular-eslint/template/recommended'], | ||||
|             rules: { | ||||
|                 'max-len': ['warn', { code: 140 }], | ||||
|                 '@angular-eslint/template/accessibility-valid-aria': 'warn', | ||||
|                 '@angular-eslint/template/accessibility-alt-text': 'error', | ||||
|                 '@angular-eslint/template/accessibility-elements-content': 'error', | ||||
|                 '@angular-eslint/template/accessibility-label-for': 'error', | ||||
|                 '@angular-eslint/template/no-positive-tabindex': 'error', | ||||
|                 '@angular-eslint/template/accessibility-table-scope': 'error', | ||||
|                 '@angular-eslint/template/accessibility-valid-aria': 'error', | ||||
|             }, | ||||
|         }, | ||||
|         { | ||||
|  | ||||
							
								
								
									
										816
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										816
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										28
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								package.json
									
									
									
									
									
								
							| @ -126,11 +126,11 @@ | ||||
|   "devDependencies": { | ||||
|     "@angular-devkit/architect": "^0.1101.2", | ||||
|     "@angular-devkit/build-angular": "~0.1000.0", | ||||
|     "@angular-eslint/builder": "0.5.0-beta.2", | ||||
|     "@angular-eslint/eslint-plugin": "0.5.0-beta.2", | ||||
|     "@angular-eslint/eslint-plugin-template": "0.5.0-beta.2", | ||||
|     "@angular-eslint/schematics": "^0.5.0-beta.2", | ||||
|     "@angular-eslint/template-parser": "0.5.0-beta.2", | ||||
|     "@angular-eslint/builder": "^4.2.0", | ||||
|     "@angular-eslint/eslint-plugin": "^4.2.0", | ||||
|     "@angular-eslint/eslint-plugin-template": "^4.2.0", | ||||
|     "@angular-eslint/schematics": "^4.2.0", | ||||
|     "@angular-eslint/template-parser": "^4.2.0", | ||||
|     "@angular/cli": "~10.0.5", | ||||
|     "@angular/compiler": "~10.0.0", | ||||
|     "@angular/compiler-cli": "~10.0.0", | ||||
| @ -141,17 +141,17 @@ | ||||
|     "@types/faker": "^5.1.3", | ||||
|     "@types/node": "^12.12.64", | ||||
|     "@types/webpack-env": "^1.16.0", | ||||
|     "@typescript-eslint/eslint-plugin": "4.3.0", | ||||
|     "@typescript-eslint/parser": "4.3.0", | ||||
|     "@typescript-eslint/eslint-plugin": "^4.22.0", | ||||
|     "@typescript-eslint/parser": "^4.22.0", | ||||
|     "check-es-compat": "^1.1.1", | ||||
|     "eslint": "^7.21.0", | ||||
|     "eslint-config-prettier": "^6.12.0", | ||||
|     "eslint-plugin-header": "^3.1.0", | ||||
|     "eslint": "^7.25.0", | ||||
|     "eslint-config-prettier": "^8.3.0", | ||||
|     "eslint-plugin-header": "^3.1.1", | ||||
|     "eslint-plugin-import": "^2.22.1", | ||||
|     "eslint-plugin-jest": "^24.1.0", | ||||
|     "eslint-plugin-jsdoc": "^30.6.3", | ||||
|     "eslint-plugin-prefer-arrow": "^1.2.2", | ||||
|     "eslint-plugin-promise": "^4.2.1", | ||||
|     "eslint-plugin-jest": "^24.3.6", | ||||
|     "eslint-plugin-jsdoc": "^32.3.3", | ||||
|     "eslint-plugin-prefer-arrow": "^1.2.3", | ||||
|     "eslint-plugin-promise": "^5.1.0", | ||||
|     "faker": "^5.1.0", | ||||
|     "fs-extra": "^9.1.0", | ||||
|     "gulp": "4.0.2", | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="badge">{{ badge.name }}</ion-title> | ||||
|         <ion-title *ngIf="!badge">{{ 'addon.badges.badges' | translate }}</ion-title> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.badges.badges' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -17,8 +17,8 @@ | ||||
|             </core-empty-box> | ||||
| 
 | ||||
|             <ion-list *ngIf="!badges.empty"  class="ion-no-margin"> | ||||
|                 <ion-item class="ion-text-wrap" *ngFor="let badge of badges.items" [title]="badge.name" | ||||
|                     (click)="badges.select(badge)" [class.core-selected-item]="badges.isSelected(badge)"> | ||||
|                 <ion-item button class="ion-text-wrap" *ngFor="let badge of badges.items" [attr.aria-label]="badge.name" | ||||
|                     (click)="badges.select(badge)" [attr.aria-current]="badges.getItemAriaCurrent(badge)"> | ||||
|                     <ion-avatar slot="start"> | ||||
|                         <img [src]="badge.badgeurl" [alt]="badge.name" core-external-content> | ||||
|                     </ion-avatar> | ||||
|  | ||||
| @ -4,7 +4,8 @@ | ||||
|     </ion-label> | ||||
| </ion-item-divider> | ||||
| <core-loading [hideUntil]="loaded" class="core-loading-center"> | ||||
|     <ion-item class="ion-text-wrap item-media" *ngFor="let entry of entries" detail="false" (click)="gotoCoureListModType(entry)"> | ||||
|     <ion-item class="ion-text-wrap item-media" *ngFor="let entry of entries" detail="false" button | ||||
|         (click)="gotoCoureListModType(entry)"> | ||||
|         <img slot="start" [src]="entry.icon" alt="" role="presentation" class="core-module-icon"> | ||||
|         <ion-label>{{ entry.name }}</ion-label> | ||||
|     </ion-item> | ||||
|  | ||||
| @ -5,8 +5,9 @@ | ||||
|     <!-- Download all courses. --> | ||||
|     <div *ngIf="downloadCoursesEnabled && downloadEnabled && filteredCourses.length > 1 && !showFilter" class="core-button-spinner" | ||||
|         slot="end"> | ||||
|         <ion-button *ngIf="!prefetchCoursesData[selectedFilter].loading" fill="clear" color="dark" (click)="prefetchCourses()"> | ||||
|             <ion-icon [name]="prefetchCoursesData[selectedFilter].icon" slot="icon-only"> | ||||
|         <ion-button *ngIf="!prefetchCoursesData[selectedFilter].loading" fill="clear" color="dark" (click)="prefetchCourses()" | ||||
|             [attr.aria-label]="'core.courses.downloadcourses' | translate"> | ||||
|             <ion-icon [name]="prefetchCoursesData[selectedFilter].icon" slot="icon-only" aria-hidden="true"> | ||||
|             </ion-icon> | ||||
|         </ion-button> | ||||
|         <ion-badge class="core-course-download-courses-progress" *ngIf="prefetchCoursesData[selectedFilter].badge"> | ||||
|  | ||||
| @ -4,9 +4,8 @@ | ||||
|     </ion-label> | ||||
|     <div *ngIf="downloadCoursesEnabled && downloadEnabled && courses && courses.length > 1" class="core-button-spinner" slot="end"> | ||||
|         <ion-button *ngIf="prefetchCoursesData.icon && !prefetchCoursesData.loading" fill="clear" color="dark" | ||||
|             (click)="prefetchCourses()"> | ||||
|             <ion-icon [name]="prefetchCoursesData.icon" slot="icon-only"> | ||||
|             </ion-icon> | ||||
|             (click)="prefetchCourses()" [attr.aria-label]="'core.courses.downloadcourses' | translate"> | ||||
|             <ion-icon [name]="prefetchCoursesData.icon" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|         </ion-button> | ||||
|         <ion-badge class="core-course-download-courses-progress" *ngIf="prefetchCoursesData.badge"> | ||||
|             {{prefetchCoursesData.badge}} | ||||
|  | ||||
| @ -4,9 +4,8 @@ | ||||
|     </ion-label> | ||||
|     <div *ngIf="downloadCoursesEnabled && downloadEnabled && courses && courses.length > 1" class="core-button-spinner" slot="end"> | ||||
|         <ion-button *ngIf="prefetchCoursesData.icon && !prefetchCoursesData.loading" fill="clear" color="dark" | ||||
|             (click)="prefetchCourses()"> | ||||
|             <ion-icon [name]="prefetchCoursesData.icon" slot="icon-only"> | ||||
|             </ion-icon> | ||||
|             (click)="prefetchCourses()" [attr.aria-label]="'core.courses.downloadcourses' | translate"> | ||||
|             <ion-icon [name]="prefetchCoursesData.icon" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|         </ion-button> | ||||
|         <ion-badge class="core-course-download-courses-progress" *ngIf="prefetchCoursesData.badge"> | ||||
|             {{prefetchCoursesData.badge}} | ||||
|  | ||||
| @ -4,9 +4,11 @@ | ||||
|     </ion-item-divider> | ||||
|     <ng-container *ngFor="let event of dayEvents.events"> | ||||
|         <ion-item class="ion-text-wrap core-course-module-handler item-media" detail="false" (click)="action($event, event.url)" | ||||
|             [title]="event.name"> | ||||
|             [attr.aria-label]="event.name" button> | ||||
|             <img slot="start" [src]="event.iconUrl" alt="" role="presentation" *ngIf="event.iconUrl" class="core-module-icon"> | ||||
|             <ion-label> | ||||
|                 <!-- Add the icon title so accessibility tools read it. --> | ||||
|                 <span class="sr-only" *ngIf="event.iconTitle">{{ event.iconTitle }}</span> | ||||
|                 <h2> | ||||
|                     <core-format-text [text]="event.name" contextLevel="module" [contextInstanceId]="event.id" | ||||
|                         [courseId]="event.course && event.course.id"> | ||||
|  | ||||
| @ -103,6 +103,7 @@ export class AddonBlockTimelineEventsComponent implements OnChanges { | ||||
|             return start <= event.timesort; | ||||
|         }).map((event) => { | ||||
|             event.iconUrl = CoreCourse.getModuleIconSrc(event.icon.component); | ||||
|             event.iconTitle = event.modulename && CoreCourse.translateModuleName(event.modulename); | ||||
| 
 | ||||
|             return event; | ||||
|         }); | ||||
| @ -145,6 +146,7 @@ export class AddonBlockTimelineEventsComponent implements OnChanges { | ||||
| 
 | ||||
| type AddonBlockTimelineEvent = AddonCalendarEvent & { | ||||
|     iconUrl?: string; | ||||
|     iconTitle?: string; | ||||
| }; | ||||
| 
 | ||||
| type AddonBlockTimelineEventFilteredEvent = { | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ title | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"></ion-buttons> | ||||
| @ -54,7 +54,7 @@ | ||||
|                             <core-tag-list [tags]="entry.tags"></core-tag-list> | ||||
|                         </ion-label> | ||||
|                     </ion-item> | ||||
|                     <ion-item *ngIf="commentsEnabled" detail> | ||||
|                     <ion-item *ngIf="commentsEnabled" detail="true"> | ||||
|                         <ion-label> | ||||
|                             <core-comments [component]="this.component" [itemId]="entry.id" area="format_blog" | ||||
|                                 [instanceId]="entry.userid" contextLevel="user"> | ||||
| @ -71,7 +71,8 @@ | ||||
|                 <ion-row class="ion-text-center"> | ||||
|                     <ion-col *ngIf="entry.lastmodified > entry.created"> | ||||
|                         <ion-note> | ||||
|                             <ion-icon name="fas-clock"></ion-icon> {{entry.lastmodified | coreTimeAgo}} | ||||
|                             <ion-icon name="fas-clock" | ||||
|                                 [attr.aria-label]="'core.lastmodified' | translate"></ion-icon> {{entry.lastmodified | coreTimeAgo}} | ||||
|                         </ion-note> | ||||
|                     </ion-col> | ||||
|                 </ion-row> | ||||
|  | ||||
| @ -13,16 +13,16 @@ | ||||
|     <ion-grid class="ion-no-padding addon-calendar-navigation"> | ||||
|         <ion-row class="ion-align-items-center"> | ||||
|             <ion-col class="ion-text-start" *ngIf="canNavigate"> | ||||
|                 <ion-button fill="clear" (click)="loadPrevious()" [title]="'core.previous' | translate"> | ||||
|                     <ion-icon name="fas-chevron-left" slot="icon-only"></ion-icon> | ||||
|                 <ion-button fill="clear" (click)="loadPrevious()" [attr.aria-label]="'core.previous' | translate"> | ||||
|                     <ion-icon name="fas-chevron-left" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|             </ion-col> | ||||
|             <ion-col class="ion-text-center addon-calendar-period"> | ||||
|                 <h3>{{ periodName }}</h3> | ||||
|             </ion-col> | ||||
|             <ion-col class="ion-text-end" *ngIf="canNavigate"> | ||||
|                 <ion-button fill="clear" (click)="loadNext()" [title]="'core.next' | translate"> | ||||
|                     <ion-icon name="fas-chevron-right" slot="icon-only"></ion-icon> | ||||
|                 <ion-button fill="clear" (click)="loadNext()" [attr.aria-label]="'core.next' | translate"> | ||||
|                     <ion-icon name="fas-chevron-right" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|             </ion-col> | ||||
|         </ion-row> | ||||
| @ -42,8 +42,8 @@ | ||||
|         <ion-row *ngFor="let week of weeks" class="addon-calendar-week"> | ||||
|             <!-- Empty slots (first week). --> | ||||
|             <ion-col *ngFor="let value of week.prepadding" class="dayblank addon-calendar-day"></ion-col> | ||||
|             <ion-col class="addon-calendar-day ion-text-center" *ngFor="let day of week.days"  (click)="dayClicked(day.mday)" | ||||
|             [ngClass]='{"hasevents": day.hasevents, "today": isCurrentMonth && day.istoday, | ||||
|             <ion-col class="addon-calendar-day ion-text-center" *ngFor="let day of week.days" (click)="dayClicked(day.mday)" | ||||
|                 [ngClass]='{"hasevents": day.hasevents, "today": isCurrentMonth && day.istoday, | ||||
|                 "weekend": day.isweekend, "duration_finish": day.haslastdayofevent}' | ||||
|                 [class.addon-calendar-event-past-day]="isPastMonth || day.ispast"> | ||||
|                 <p class="addon-calendar-day-number"><span>{{ day.mday }}</span></p> | ||||
| @ -55,16 +55,23 @@ | ||||
|                 <!-- In tablet, display list of events. --> | ||||
|                 <div class="ion-hide-md-down addon-calendar-day-events"> | ||||
|                     <ng-container *ngFor="let event of day.filteredEvents | slice:0:4; let index = index"> | ||||
|                         <p *ngIf="index < 3 || day.filteredEvents.length == 4" class="addon-calendar-event" | ||||
|                         (click)="eventClicked(event, $event)" [class.addon-calendar-event-past]="event.ispast"> | ||||
|                         <div role="button" *ngIf="index < 3 || day.filteredEvents.length == 4" class="addon-calendar-event" | ||||
|                             (click)="eventClicked(event, $event)" [class.addon-calendar-event-past]="event.ispast"> | ||||
|                             <span class="calendar_event_type calendar_event_{{event.formattedType}}"></span> | ||||
|                             <ion-icon *ngIf="event.offline && !event.deleted" name="far-clock"></ion-icon> | ||||
|                             <ion-icon *ngIf="event.deleted" name="fas-trash"></ion-icon> | ||||
|                             <ion-icon *ngIf="event.offline && !event.deleted" name="fas-clock" | ||||
|                                 [attr.aria-label]="'core.notsent' | translate"></ion-icon> | ||||
|                             <ion-icon *ngIf="event.deleted" name="fas-trash" [attr.aria-label]="'core.deletedoffline' | translate"> | ||||
|                             </ion-icon> | ||||
|                             <span class="addon-calendar-event-time">{{ event.timestart * 1000 | coreFormatDate: timeFormat }}</span> | ||||
|                             <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" alt="" role="presentation" | ||||
|                                 class="core-module-icon"> | ||||
|                             <!-- Add the icon title so accessibility tools read it. --> | ||||
|                             <span class="sr-only"> | ||||
|                                 {{ 'addon.calendar.type' + event.formattedType | translate }} | ||||
|                                 <span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span> | ||||
|                             </span> | ||||
|                             <span class="addon-calendar-event-name">{{event.name}}</span> | ||||
|                         </p> | ||||
|                         </div> | ||||
|                     </ng-container> | ||||
|                     <p *ngIf="day.filteredEvents.length > 4" class="addon-calendar-day-more"> | ||||
|                         <b>{{ 'core.nummore' | translate:{$a: day.filteredEvents.length - 3} }}</b> | ||||
|  | ||||
| @ -70,6 +70,7 @@ | ||||
|             margin-bottom: 0.6em; | ||||
|             overflow: hidden; | ||||
|             white-space: nowrap; | ||||
|             color: var(--text-color); | ||||
| 
 | ||||
|             &.addon-calendar-event-past { | ||||
|                 opacity: 0.5; | ||||
|  | ||||
| @ -1,6 +1,6 @@ | ||||
| <ion-list> | ||||
|     <ion-item *ngFor="let type of types" class="addon-calendar-event" [ngClass]="['addon-calendar-eventtype-'+type]"> | ||||
|         <ion-icon [name]="typeIcons[type]" slot="start"></ion-icon> | ||||
|         <ion-icon [name]="typeIcons[type]" slot="start" aria-hidden="true"></ion-icon> | ||||
|         <ion-label>{{ 'addon.calendar.' + type + 'events' | translate}}</ion-label> | ||||
|         <ion-toggle [(ngModel)]="filter[type]" (ionChange)="onChange()" slot="end"></ion-toggle> | ||||
|     </ion-item> | ||||
|  | ||||
| @ -4,22 +4,28 @@ | ||||
| 
 | ||||
|     <ion-list *ngIf="filteredEvents && filteredEvents.length"  class="ion-no-margin"> | ||||
|         <ng-container *ngFor="let event of filteredEvents"> | ||||
|             <ion-item class="ion-text-wrap addon-calendar-event" [title]="event.name" (click)="eventClicked(event)" | ||||
|             <ion-item class="ion-text-wrap addon-calendar-event" [attr.aria-label]="event.name" (click)="eventClicked(event)" button | ||||
|                 [ngClass]="['addon-calendar-eventtype-'+event.eventtype]"> | ||||
|                 <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon"> | ||||
|                 <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"> | ||||
|                 <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon" alt="" | ||||
|                     role="presentation"> | ||||
|                 <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start" aria-hidden="true"> | ||||
|                 </ion-icon> | ||||
|                 <ion-label> | ||||
|                     <!-- Add the icon title so accessibility tools read it. --> | ||||
|                     <span class="sr-only"> | ||||
|                         {{ 'addon.calendar.type' + event.formattedType | translate }} | ||||
|                         <span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span> | ||||
|                     </span> | ||||
|                     <h2><core-format-text [text]="event.name" [contextLevel]="event.contextLevel" | ||||
|                         [contextInstanceId]="event.contextInstanceId"></core-format-text></h2> | ||||
|                     <p [innerHTML]="event.formattedtime"></p> | ||||
|                 </ion-label> | ||||
|                 <ion-note *ngIf="event.offline && !event.deleted" slot="end"> | ||||
|                     <ion-icon name="far-clock"></ion-icon> | ||||
|                     <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> | ||||
|                     <span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span> | ||||
|                 </ion-note> | ||||
|                 <ion-note *ngIf="event.deleted" slot="end"> | ||||
|                     <ion-icon name="fas-trash"></ion-icon> | ||||
|                     <ion-icon name="fas-trash" aria-hidden="true"></ion-icon> | ||||
|                     <span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span> | ||||
|                 </ion-note> | ||||
|             </ion-item> | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.calendar.calendarevents' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="openFilter($event)" [attr.aria-label]="'core.filter' | translate"> | ||||
|                 <ion-icon slot="icon-only" name="fas-filter"></ion-icon> | ||||
|                 <ion-icon slot="icon-only" name="fas-filter" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|             <core-context-menu> | ||||
|                 <core-context-menu-item *ngIf="!isCurrentDay" [priority]="900" [content]="'addon.calendar.today' | translate" | ||||
| @ -29,26 +29,26 @@ | ||||
|     <ion-grid class="ion-no-padding safe-area-page"> | ||||
|         <ion-row class="ion-align-items-center"> | ||||
|             <ion-col class="ion-text-start" *ngIf="currentMoment"> | ||||
|                 <ion-button fill="clear" (click)="loadPrevious()" [title]="'addon.calendar.dayprev' | translate"> | ||||
|                     <ion-icon name="fas-chevron-left" slot="icon-only"></ion-icon> | ||||
|                 <ion-button fill="clear" (click)="loadPrevious()" [attr.aria-label]="'addon.calendar.dayprev' | translate"> | ||||
|                     <ion-icon name="fas-chevron-left" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|             </ion-col> | ||||
|             <ion-col class="ion-text-center addon-calendar-period"> | ||||
|                 <h3>{{ periodName }}</h3> | ||||
|             </ion-col> | ||||
|             <ion-col class="ion-text-end" *ngIf="currentMoment"> | ||||
|                 <ion-button fill="clear" (click)="loadNext()" [title]="'addon.calendar.daynext' | translate"> | ||||
|                     <ion-icon name="fas-chevron-right" slot="icon-only"></ion-icon> | ||||
|                 <ion-button fill="clear" (click)="loadNext()" [attr.aria-label]="'addon.calendar.daynext' | translate"> | ||||
|                     <ion-icon name="fas-chevron-right" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|             </ion-col> | ||||
|         </ion-row> | ||||
|     </ion-grid> | ||||
| 
 | ||||
|     <core-loading [hideUntil]="loaded" class="safe-area-page"> | ||||
|         <!-- There is data to be synchronized -->          <!-- There is data to be synchronized --> | ||||
|         <!-- There is data to be synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate:{$a: 'core.day' | translate} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -59,22 +59,28 @@ | ||||
| 
 | ||||
|         <ion-list *ngIf="filteredEvents && filteredEvents.length"  class="ion-no-margin"> | ||||
|             <ng-container *ngFor="let event of filteredEvents"> | ||||
|                 <ion-item class="addon-calendar-event ion-text-wrap" [title]="event.name" (click)="gotoEvent(event.id)" | ||||
|                 [class.item-dimmed]="event.ispast" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]"> | ||||
|                     <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon"> | ||||
|                     <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"> | ||||
|                 <ion-item class="addon-calendar-event ion-text-wrap" [attr.aria-label]="event.name" (click)="gotoEvent(event.id)" | ||||
|                 [class.item-dimmed]="event.ispast" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]" button> | ||||
|                     <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon" alt="" | ||||
|                         role="presentation"> | ||||
|                     <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start" aria-hidden="true"> | ||||
|                     </ion-icon> | ||||
|                     <ion-label> | ||||
|                         <!-- Add the icon title so accessibility tools read it. --> | ||||
|                         <span class="sr-only"> | ||||
|                             {{ 'addon.calendar.type' + event.formattedType | translate }} | ||||
|                             <span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span> | ||||
|                         </span> | ||||
|                         <h2><core-format-text [text]="event.name" [contextLevel]="event.contextLevel" | ||||
|                             [contextInstanceId]="event.contextInstanceId"></core-format-text></h2> | ||||
|                         <p [innerHTML]="event.formattedtime"></p> | ||||
|                     </ion-label> | ||||
|                     <ion-note *ngIf="event.offline && !event.deleted" slot="end"> | ||||
|                         <ion-icon name="far-clock"></ion-icon> | ||||
|                         <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> | ||||
|                         <span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span> | ||||
|                     </ion-note> | ||||
|                     <ion-note *ngIf="event.deleted" slot="end"> | ||||
|                         <ion-icon name="fas-trash"></ion-icon> | ||||
|                         <ion-icon name="fas-trash" aria-hidden="true"></ion-icon> | ||||
|                         <span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span> | ||||
|                     </ion-note> | ||||
|                 </ion-item> | ||||
| @ -85,7 +91,7 @@ | ||||
|     <!-- Create a calendar event. --> | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canCreate && loaded"> | ||||
|         <ion-fab-button (click)="openEdit()" [attr.aria-label]="'addon.calendar.newevent' | translate"> | ||||
|             <ion-icon name="fas-plus"></ion-icon> | ||||
|             <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
| </ion-content> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ title | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -120,9 +120,10 @@ | ||||
|             </ng-container> | ||||
| 
 | ||||
|             <!-- Advanced options. --> | ||||
|             <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()"> | ||||
|                 <ion-icon *ngIf="!advanced" name="fas-caret-right" slot="start"></ion-icon> | ||||
|                 <ion-icon *ngIf="advanced" name="fas-caret-down" slot="start"></ion-icon> | ||||
|             <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()" | ||||
|                 [attr.aria-label]="(advanced ? 'core.showless' : 'core.showmore') | translate" role="button"> | ||||
|                 <ion-icon *ngIf="!advanced" name="fas-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-icon *ngIf="advanced" name="fas-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label> | ||||
|                     <span *ngIf="!advanced">{{ 'core.showmore' | translate }}</span> | ||||
|                     <span *ngIf="advanced">{{ 'core.showless' | translate }}</span> | ||||
| @ -161,14 +162,14 @@ | ||||
|                             <ion-radio slot="end" value="0"></ion-radio> | ||||
|                             <ion-label>{{ 'addon.calendar.durationnone' | translate }}</ion-label> | ||||
|                         </ion-item> | ||||
|                         <ion-item  (click)="selectDuration('1')"> | ||||
|                         <ion-item button (click)="selectDuration('1')"> | ||||
|                             <ion-radio slot="end" value="1"></ion-radio> | ||||
|                             <ion-label>{{ 'addon.calendar.durationuntil' | translate }}</ion-label> | ||||
|                             <ion-datetime formControlName="timedurationuntil" | ||||
|                                 [placeholder]="'addon.calendar.durationuntil' | translate" | ||||
|                                 [displayFormat]="dateFormat" [disabled]="form.controls.duration.value != 1"></ion-datetime> | ||||
|                         </ion-item> | ||||
|                         <ion-item (click)="selectDuration('2')"> | ||||
|                         <ion-item button (click)="selectDuration('2')"> | ||||
|                             <ion-radio slot="end" value="2"></ion-radio> | ||||
|                             <ion-label>{{ 'addon.calendar.durationminutes' | translate }}</ion-label> | ||||
|                             <ion-input type="number" name="timedurationminutes" slot="end" | ||||
|  | ||||
| @ -1,11 +1,16 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="event"> | ||||
|             <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" alt="" role="presentation" class="core-module-icon"> | ||||
|             <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon"></ion-icon> | ||||
|             <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" aria-hidden="true"></ion-icon> | ||||
|             <!-- Add the icon title so accessibility tools read it. --> | ||||
|             <span class="sr-only"> | ||||
|                 {{ 'addon.calendar.type' + event.formattedType | translate }} | ||||
|                 <span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span> | ||||
|             </span> | ||||
|             <core-format-text [text]="event.name" [contextLevel]="event.contextLevel" | ||||
|                 [contextInstanceId]="event.contextInstanceId"></core-format-text> | ||||
|         </ion-title> | ||||
| @ -38,7 +43,7 @@ | ||||
|         <!-- There is data to be synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="hasOffline || (event && event.deleted)"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate:{$a: 'addon.calendar.calendarevent' | translate} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -48,17 +53,21 @@ | ||||
|                 <ion-item class="ion-text-wrap" *ngIf="isSplitViewOn"> | ||||
|                     <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" alt="" role="presentation" | ||||
|                         class="core-module-icon"> | ||||
|                     <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"> | ||||
|                     <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start" aria-hidden="true"> | ||||
|                     </ion-icon> | ||||
|                     <ion-label> | ||||
|                         <span class="sr-only"> | ||||
|                             {{ 'addon.calendar.type' + event.formattedType | translate }} | ||||
|                             <span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span> | ||||
|                         </span> | ||||
|                         <h2>{{ 'addon.calendar.eventname' | translate }}</h2> | ||||
|                         <p> | ||||
|                             <core-format-text [text]="event.name" [contextLevel]="event.contextLevel" | ||||
|                              [contextInstanceId]="event.contextInstanceId"></core-format-text> | ||||
|                                 [contextInstanceId]="event.contextInstanceId"></core-format-text> | ||||
|                         </p> | ||||
|                     </ion-label> | ||||
|                     <ion-note slot="end" *ngIf="event.deleted"> | ||||
|                         <ion-icon name="fas-trash"></ion-icon> {{ 'core.deletedoffline' | translate }} | ||||
|                         <ion-icon name="fas-trash" aria-hidden="true"></ion-icon> {{ 'core.deletedoffline' | translate }} | ||||
|                     </ion-note> | ||||
|                 </ion-item> | ||||
|                 <ion-item> | ||||
| @ -67,7 +76,7 @@ | ||||
|                         <p [innerHTML]="event.formattedtime"></p> | ||||
|                     </ion-label> | ||||
|                     <ion-note slot="end" *ngIf="!isSplitViewOn && event.deleted"> | ||||
|                         <ion-icon name="fas-trash"></ion-icon> {{ 'core.deletedoffline' | translate }} | ||||
|                         <ion-icon name="fas-trash" aria-hidden="true"></ion-icon> {{ 'core.deletedoffline' | translate }} | ||||
|                     </ion-note> | ||||
|                 </ion-item> | ||||
|                 <ion-item> | ||||
| @ -144,9 +153,9 @@ | ||||
|                         <p *ngIf="reminder.time > 0">{{ reminder.time * 1000 | coreFormatDate }}</p> | ||||
|                     </ion-label> | ||||
|                     <ion-button fill="clear" (click)="cancelNotification(reminder.id, $event)" | ||||
|                         [attr.aria-label]=" 'core.delete' | translate" slot="end" | ||||
|                         [attr.aria-label]="'core.delete' | translate" slot="end" | ||||
|                         *ngIf="(reminder.time == -1 ? (event.timestart - defaultTime) : reminder.time) > currentTime!"> | ||||
|                         <ion-icon name="fas-trash" color="danger" slot="icon-only"></ion-icon> | ||||
|                         <ion-icon name="fas-trash" color="danger" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                     </ion-button> | ||||
|                 </ion-item> | ||||
|             </ng-container> | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ (showCalendar ? 'addon.calendar.calendarevents' : 'addon.calendar.upcomingevents') | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="openFilter($event)" [attr.aria-label]="'core.filter' | translate"> | ||||
|                 <ion-icon slot="icon-only" name="fas-filter"></ion-icon> | ||||
|                 <ion-icon slot="icon-only" name="fas-filter" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|             <core-context-menu> | ||||
|                 <core-context-menu-item *ngIf="showCalendar" [priority]="800" | ||||
| @ -33,7 +33,7 @@ | ||||
|     <!-- There is data to be synchronized --> | ||||
|     <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'core.hasdatatosync' | translate:{$a: 'addon.calendar.calendar' | translate} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| @ -49,7 +49,7 @@ | ||||
|     <!-- Create a calendar event. --> | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canCreate"> | ||||
|         <ion-fab-button (click)="openEdit()" [attr.aria-label]="'addon.calendar.newevent' | translate"> | ||||
|             <ion-icon name="fas-plus"></ion-icon> | ||||
|             <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
| </ion-content> | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.calendar.calendarevents' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="openFilter($event)" [attr.aria-label]="'core.filter' | translate"> | ||||
|                 <ion-icon slot="icon-only" name="fas-filter"></ion-icon> | ||||
|                 <ion-icon slot="icon-only" name="fas-filter" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|             <core-context-menu> | ||||
|                 <core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600" | ||||
| @ -28,7 +28,7 @@ | ||||
|             <!-- There is data to be synchronized --> | ||||
|             <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|                 <ion-item> | ||||
|                     <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                     <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label>{{ 'core.hasdatatosync' | translate:{$a: 'addon.calendar.calendar' | translate} }}</ion-label> | ||||
|                 </ion-item> | ||||
|             </ion-card> | ||||
| @ -42,13 +42,21 @@ | ||||
|                     <ion-item-divider *ngIf="event.showDate"> | ||||
|                         <ion-label>{{ event.timestart * 1000 | coreFormatDate: "strftimedayshort" }}</ion-label> | ||||
|                     </ion-item-divider> | ||||
|                     <ion-item class="addon-calendar-event ion-text-wrap" [title]="event.name" (click)="gotoEvent(event.id)" | ||||
|                     [class.core-selected-item]="event.id == eventId" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]"> | ||||
|                         <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon"> | ||||
|                         <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"> | ||||
|                     <ion-item class="addon-calendar-event ion-text-wrap" [attr.aria-label]="event.name" (click)="gotoEvent(event.id)" | ||||
|                         [attr.aria-current]="event.id == eventId ? 'page' : 'false'" | ||||
|                         [ngClass]="['addon-calendar-eventtype-'+event.eventtype]" button> | ||||
|                         <img *ngIf="event.moduleIcon" src="{{event.moduleIcon}}" slot="start" class="core-module-icon" alt="" | ||||
|                             role="presentation"> | ||||
|                         <ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start" | ||||
|                             aria-hidden="true"> | ||||
|                         </ion-icon> | ||||
|                         <ion-label> | ||||
|                             <h2> | ||||
|                                 <!-- Add the icon title so accessibility tools read it. --> | ||||
|                                 <span class="sr-only"> | ||||
|                                     {{ 'addon.calendar.type' + event.formattedType | translate }} | ||||
|                                     <span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span> | ||||
|                                 </span> | ||||
|                                 <core-format-text [text]="event.name" [contextLevel]="event.contextLevel" | ||||
|                                     [contextInstanceId]="event.contextInstanceId"> | ||||
|                                 </core-format-text> | ||||
| @ -64,11 +72,11 @@ | ||||
|                             </p> | ||||
|                         </ion-label> | ||||
|                         <ion-note *ngIf="event.offline && !event.deleted" slot="end"> | ||||
|                             <ion-icon name="far-clock"></ion-icon> | ||||
|                             <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> | ||||
|                             <span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span> | ||||
|                         </ion-note> | ||||
|                         <ion-note *ngIf="event.deleted" slot="end"> | ||||
|                             <ion-icon name="fas-trash"></ion-icon> | ||||
|                             <ion-icon name="fas-trash" aria-hidden="true"></ion-icon> | ||||
|                             <span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span> | ||||
|                         </ion-note> | ||||
|                     </ion-item> | ||||
| @ -82,7 +90,7 @@ | ||||
|         <!-- Create a calendar event. --> | ||||
|         <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canCreate"> | ||||
|             <ion-fab-button (click)="openEdit()" [attr.aria-label]="'addon.calendar.newevent' | translate"> | ||||
|                 <ion-icon name="fas-plus"></ion-icon> | ||||
|                 <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|             </ion-fab-button> | ||||
|         </ion-fab> | ||||
|     </core-split-view> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'core.settings.settings' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
|  | ||||
| @ -189,6 +189,7 @@ export class AddonCalendarHelperProvider { | ||||
|         if (event.modulename) { | ||||
|             eventFormatted.eventIcon = CoreCourse.getModuleIconSrc(event.modulename); | ||||
|             eventFormatted.moduleIcon = eventFormatted.eventIcon; | ||||
|             eventFormatted.iconTitle = CoreCourse.translateModuleName(event.modulename); | ||||
|         } | ||||
| 
 | ||||
|         eventFormatted.formattedType = AddonCalendar.getEventType(event); | ||||
|  | ||||
| @ -2250,6 +2250,7 @@ export type AddonCalendarEventToDisplay = Partial<AddonCalendarCalendarEvent> & | ||||
|     deleted?: boolean; // Calculated in the app. Whether it has been deleted in offline.
 | ||||
|     encodedLocation?: SafeUrl; // Calculated in the app. Sanitized location link.
 | ||||
|     eventIcon?: string; // Calculated in the app. Event icon.
 | ||||
|     iconTitle?: string; | ||||
|     moduleIcon?: string; // Calculated in the app. Module icon.
 | ||||
|     formattedType: string; // Calculated in the app. Formatted type.
 | ||||
|     duration?: number; // Calculated in the app. Duration of offline event.
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ title }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -14,8 +14,8 @@ | ||||
|         <core-loading [hideUntil]="competencies.loaded"> | ||||
|             <ion-list> | ||||
|                 <ion-item class="ion-text-wrap" *ngFor="let competency of competencies.items" | ||||
|                     [title]="competency.competency.shortname" (click)="competencies.select(competency)" | ||||
|                     [class.core-selected-item]="competencies.isSelected(competency)"> | ||||
|                     [attr.aria-label]="competency.competency.shortname" (click)="competencies.select(competency)" | ||||
|                     [attr.aria-current]="competencies.getItemAriaCurrent(competency)" button> | ||||
|                     <ion-label> | ||||
|                         <h2>{{ competency.competency.shortname }} <em>{{competency.competency.idnumber}}</em></h2> | ||||
|                     </ion-label> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="competency"> | ||||
|             {{ competency.competency.competency.shortname }} <small>{{ competency.competency.competency.idnumber }}</small> | ||||
| @ -73,9 +73,9 @@ | ||||
|                     <p *ngIf="coursemodules.length == 0"> | ||||
|                         {{ 'addon.competency.noactivities' | translate }} | ||||
|                     </p> | ||||
|                     <ion-item class="ion-text-wrap" *ngFor="let activity of coursemodules" [href]="activity.url" [title]="activity.name" | ||||
|                         core-link capture="true"> | ||||
|                         <img slot="start" core-external-content [src]="activity.iconurl" alt="" role="presentation" *ngIf="activity.iconurl" | ||||
|                     <ion-item class="ion-text-wrap" *ngFor="let activity of coursemodules" [href]="activity.url" | ||||
|                         [attr.aria-label]="activity.name" core-link capture="true"> | ||||
|                         <img slot="start" core-external-content [src]="activity.iconurl" alt="" *ngIf="activity.iconurl" | ||||
|                             class="core-module-icon"> | ||||
|                         <ion-label> | ||||
|                             <core-format-text [text]="activity.name" contextLevel="module" [contextInstanceId]="activity.id" | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="competency"> | ||||
|             {{ competency.competency.shortname }} <small>{{ competency.competency.idnumber }}</small> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.competency.coursecompetencies' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -56,7 +56,7 @@ | ||||
|         <div *ngIf="competencies"> | ||||
|             <ion-card *ngFor="let competency of competencies.competencies"> | ||||
|                 <ion-item class="ion-text-wrap" (click)="openCompetency(competency.competency.id)" | ||||
|                     [title]="competency.competency.shortname" detail="true"> | ||||
|                     [attr.aria-label]="competency.competency.shortname" detail="true" button> | ||||
|                     <ion-label> | ||||
|                         <h2><strong>{{competency.competency.shortname}} <em>{{competency.competency.idnumber}}</em></strong></h2> | ||||
|                     </ion-label> | ||||
| @ -103,9 +103,9 @@ | ||||
|                             <p *ngIf="competency.coursemodules.length == 0"> | ||||
|                                 {{ 'addon.competency.noactivities' | translate }} | ||||
|                             </p> | ||||
|                             <ion-item class="ion-text-wrap core-course-module-handler item-media" [title]="activity.name" core-link | ||||
|                                 *ngFor="let activity of competency.coursemodules" [href]="activity.url" capture="true"> | ||||
|                                 <img slot="start" [src]="activity.iconurl" core-external-content alt="" role="presentation" | ||||
|                             <ion-item class="ion-text-wrap core-course-module-handler item-media" [attr.aria-label]="activity.name" | ||||
|                                 core-link *ngFor="let activity of competency.coursemodules" [href]="activity.url" capture="true"> | ||||
|                                 <img slot="start" [src]="activity.iconurl" core-external-content alt="" | ||||
|                                     *ngIf="activity.iconurl" class="core-module-icon"> | ||||
|                                 <ion-label> | ||||
|                                     <core-format-text [text]="activity.name" contextLevel="module" [contextInstanceId]="activity.id" | ||||
| @ -120,7 +120,7 @@ | ||||
|                                 {{ 'addon.competency.nouserplanswithcompetency' | translate }} | ||||
|                             </p> | ||||
|                             <ion-item class="ion-text-wrap" *ngFor="let plan of competency.plans" [href]="plan.url" | ||||
|                                 [title]="plan.name" core-link capture="true"> | ||||
|                                 [attr.aria-label]="plan.name" core-link capture="true"> | ||||
|                                 <ion-label> | ||||
|                                    <core-format-text [text]="plan.name" contextLevel="user" [contextInstanceId]="plan.userid"> | ||||
|                                    </core-format-text> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="plan">{{plan.plan.name}}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -75,7 +75,7 @@ | ||||
|                 </ion-item> | ||||
|                 <ion-item class="ion-text-wrap" *ngFor="let competency of plan.competencies" | ||||
|                     (click)="openCompetency(competency.competency.id)" | ||||
|                     [title]="competency.competency.shortname" detail="true"> | ||||
|                     [attr.aria-label]="competency.competency.shortname" detail="true" button> | ||||
|                     <ion-label><h2>{{competency.competency.shortname}} <em>{{competency.competency.idnumber}}</em></h2></ion-label> | ||||
|                     <ion-badge *ngIf="competency.usercompetencyplan" slot="end" | ||||
|                         [color]="competency.usercompetencyplan.proficiency ? 'success' : 'danger'"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.competency.userplans' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -16,8 +16,8 @@ | ||||
| 
 | ||||
|             </core-empty-box> | ||||
|             <ion-list *ngIf="!plans.empty"  class="ion-no-margin"> | ||||
|                 <ion-item class="ion-text-wrap" *ngFor="let plan of plans.items" [title]="plan.name" (click)="plans.select(plan)" | ||||
|                     [class.core-selected-item]="plans.isSelected(plan)"> | ||||
|                 <ion-item class="ion-text-wrap" *ngFor="let plan of plans.items" [attr.aria-label]="plan.name" | ||||
|                     (click)="plans.select(plan)" [attr.aria-current]="plans.getItemAriaCurrent(plan)" button> | ||||
|                     <ion-label> | ||||
|                         <h2>{{ plan.name }}</h2> | ||||
|                         <p *ngIf="plan.duedate > 0"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.coursecompletion.coursecompletion' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -84,7 +84,7 @@ | ||||
| 
 | ||||
|         <ion-card class="core-warning-card" *ngIf="!tracked"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'addon.coursecompletion.nottracked' | translate }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messageoutput_airnotifier.processorsettingsdesc' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <ion-title>{{ 'addon.messages.groupinfo' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon name="fas-times" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-times" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -18,7 +18,7 @@ | ||||
|             <ion-label> | ||||
|                 <div class="large-avatar"> | ||||
|                     <img class="avatar" [src]="conversation!.imageurl" core-external-content [alt]="conversation!.name" | ||||
|                     role="presentation" onError="this.src='assets/img/group-avatar.png'"> | ||||
|                     onError="this.src='assets/img/group-avatar.png'"> | ||||
|                 </div> | ||||
|                 <h2> | ||||
|                     <core-format-text [text]="conversation!.name" contextLevel="system" [contextInstanceId]="0"></core-format-text> | ||||
| @ -33,13 +33,14 @@ | ||||
|         </ion-item> | ||||
| 
 | ||||
|         <ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let member of members" | ||||
|             (click)="closeModal(member.id)" detail> | ||||
|             (click)="closeModal(member.id)" detail="true" button> | ||||
|             <core-user-avatar [user]="member" [linkProfile]="false" [checkOnline]="member.showonlinestatus" slot="start"> | ||||
|             </core-user-avatar> | ||||
|             <ion-label> | ||||
|                 <h2> | ||||
|                     {{ member.fullname }} | ||||
|                     <ion-icon name="fas-user-slash" *ngIf="member.isblocked" [title]="'addon.messages.contactblocked' | translate"> | ||||
|                     <ion-icon name="fas-user-slash" *ngIf="member.isblocked" | ||||
|                         [attr.aria-label]="'addon.messages.contactblocked' | translate"> | ||||
|                     </ion-icon> | ||||
|                 </h2> | ||||
|             </ion-label> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messages.contacts' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
| @ -38,8 +38,8 @@ | ||||
|                         <!-- Don't show deleted users --> | ||||
|                         <ion-item class="ion-text-wrap addon-messages-conversation-item" | ||||
|                             *ngIf="contact.profileimageurl || contact.profileimageurlsmall" | ||||
|                             [title]="contact.fullname" (click)="gotoDiscussion(contact.id)" detail | ||||
|                             [class.core-selected-item]="contact.id == discussionUserId"> | ||||
|                             [attr.aria-label]="contact.fullname" (click)="gotoDiscussion(contact.id)" detail="true" button | ||||
|                             [attr.aria-current]="contact.id == discussionUserId ? 'page' :  'false'"> | ||||
|                             <core-user-avatar [user]="contact" slot="start" [checkOnline]="contact.showonlinestatus"></core-user-avatar> | ||||
|                             <ion-label><h2>{{ contact.fullname }}</h2></ion-label> | ||||
|                         </ion-item> | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messages.contacts' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="gotoSearch()" [attr.aria-label]="'addon.messages.search' | translate"> | ||||
|                 <ion-icon name="fas-search" slot="icon-only"></ion-icon> | ||||
|             <ion-button (click)="gotoSearch()" [attr.aria-label]="'addon.messages.searchcombined' | translate"> | ||||
|                 <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|             <!-- Add an empty context menu so discussion page can add items in split view, otherwise the menu | ||||
|                 disappears in some cases. --> | ||||
| @ -26,9 +26,9 @@ | ||||
|                     </ion-refresher> | ||||
|                     <core-loading [hideUntil]="confirmedLoaded" class="core-loading-center"> | ||||
|                         <ion-list  class="ion-no-margin"> | ||||
|                             <ion-item class="ion-text-wrap addon-messages-conversation-item" | ||||
|                                 *ngFor="let contact of confirmedContacts" [title]="contact.fullname" detail | ||||
|                                 (click)="selectUser(contact.id)" [class.core-selected-item]="contact.id == selectedUserId"> | ||||
|                             <ion-item class="ion-text-wrap addon-messages-conversation-item" (click)="selectUser(contact.id)" button | ||||
|                                 *ngFor="let contact of confirmedContacts" [attr.aria-label]="contact.fullname" detail="true" | ||||
|                                 [attr.aria-current]="contact.id == selectedUserId ? 'page' :  'false'"> | ||||
|                                 <core-user-avatar slot="start" [user]="contact" | ||||
|                                     [checkOnline]="contact.showonlinestatus" [linkProfile]="false"> | ||||
|                                 </core-user-avatar> | ||||
| @ -36,7 +36,8 @@ | ||||
|                                     <h2> | ||||
|                                         <core-format-text [text]="contact.fullname" contextLevel="system" [contextInstanceId]="0"> | ||||
|                                         </core-format-text> | ||||
|                                         <ion-icon *ngIf="contact.isblocked" name="fas-user-slash" slot="end"> | ||||
|                                         <ion-icon *ngIf="contact.isblocked" name="fas-user-slash" slot="end" | ||||
|                                             [attr.aria-label]="'addon.messages.contactblocked' | translate"> | ||||
|                                         </ion-icon> | ||||
|                                     </h2> | ||||
|                                 </ion-label> | ||||
| @ -63,8 +64,8 @@ | ||||
|                     <core-loading [hideUntil]="requestsLoaded" class="core-loading-center"> | ||||
|                         <ion-list  class="ion-no-margin"> | ||||
|                             <ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let request of requests" | ||||
|                                 [title]="request.fullname" (click)="selectUser(request.id)" | ||||
|                                 [class.core-selected-item]="request.id == selectedUserId" detail> | ||||
|                                 [attr.aria-label]="request.fullname" (click)="selectUser(request.id)" button | ||||
|                                 [attr.aria-current]="request.id == selectedUserId ? 'page' :  'false'" detail="true"> | ||||
|                                 <core-user-avatar slot="start" [user]="request" [linkProfile]="false"></core-user-avatar> | ||||
|                                 <ion-label> | ||||
|                                     <core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0"> | ||||
|  | ||||
| @ -1,29 +1,30 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <div class="toolbar-title"> | ||||
|                 <img *ngIf="loaded && !otherMember && conversationImage" class="core-bar-button-image" [src]="conversationImage" | ||||
|                     [alt]="title" onError="this.src='assets/img/group-avatar.png'" core-external-content role="presentation" | ||||
|                     alt="" onError="this.src='assets/img/group-avatar.png'" core-external-content role="presentation" | ||||
|                     [siteId]="siteId || null"> | ||||
|                 <core-user-avatar *ngIf="loaded && otherMember" class="core-bar-button-image" [user]="otherMember" | ||||
|                     [linkProfile]="false" [checkOnline]="otherMember.showonlinestatus" (click)="showInfo && viewInfo()"> | ||||
|                 </core-user-avatar> | ||||
|                 <core-format-text [text]="title" contextLevel="system" [contextInstanceId]="0" | ||||
|                     (click)="showInfo && !isGroup && viewInfo()"></core-format-text> | ||||
|                 <ion-icon *ngIf="conversation && conversation.isfavourite" name="fas-star" [title]="'core.favourites' | translate"> | ||||
|                 <ion-icon *ngIf="conversation && conversation.isfavourite" name="fas-star" | ||||
|                     [attr.aria-label]="'core.favourites' | translate"> | ||||
|                 </ion-icon> | ||||
|                 <ion-icon *ngIf="conversation && conversation.ismuted" name="fas-bell-slash" | ||||
|                     [title]="'addon.messages.mutedconversation' | translate"> | ||||
|                     [attr.aria-label]="'addon.messages.mutedconversation' | translate"> | ||||
|                 </ion-icon> | ||||
|             </div> | ||||
|         </ion-title> | ||||
|         <ion-buttons slot="end"></ion-buttons> | ||||
|     </ion-toolbar> | ||||
|     <core-navbar-buttons slot="end"> | ||||
|         <core-context-menu [aria-label]="'addon.messages.conversationactions' | translate"> | ||||
|         <core-context-menu [attr.aria-label]="'addon.messages.conversationactions' | translate"> | ||||
|             <core-context-menu-item [hidden]="isSelf || !showInfo || isGroup" [priority]="1000" | ||||
|                 [content]="'addon.messages.info' | translate" (action)="viewInfo()" | ||||
|                 iconAction="fas-info-circle"></core-context-menu-item> | ||||
| @ -82,7 +83,7 @@ | ||||
|                 <ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom && message.id == unreadMessageFrom" | ||||
|                     color="light"> | ||||
|                     <ion-label>{{ 'addon.messages.newmessages' | translate }}</ion-label> | ||||
|                     <ion-icon name="arrow-round-down"></ion-icon> | ||||
|                     <ion-icon name="fas-arrow-down" aria-hidden="true"></ion-icon> | ||||
|                 </ion-chip> | ||||
| 
 | ||||
|                 <ion-item class="ion-text-wrap addon-message" (longPress)="copyMessage(message)" | ||||
| @ -99,7 +100,9 @@ | ||||
|                             <div *ngIf="message.showUserData">{{ members[message.useridfrom].fullname }}</div> | ||||
| 
 | ||||
|                             <ion-note *ngIf="!message.pending">{{ message.timecreated | coreFormatDate: "strftimetime" }}</ion-note> | ||||
|                             <ion-note *ngIf="message.pending"><ion-icon name="far-clock"></ion-icon></ion-note> | ||||
|                             <ion-note *ngIf="message.pending"> | ||||
|                                 <ion-icon name="fas-clock" [attr.aria-label]="'core.notsent' | translate "></ion-icon> | ||||
|                             </ion-note> | ||||
|                         </h2> | ||||
| 
 | ||||
|                         <!-- Some messages have <p> and some others don't. Add a <p> so they all have same styles. --> | ||||
| @ -111,7 +114,7 @@ | ||||
|                     <ion-button fill="clear" *ngIf="!message.sending && showDelete" (click)="deleteMessage(message, index)" | ||||
|                         class="addon-messages-delete-button" [@coreSlideInOut]="'fromRight'" | ||||
|                         [attr.aria-label]=" 'addon.messages.deletemessage' | translate" slot="end"> | ||||
|                         <ion-icon name="fas-trash" color="danger" slot="icon-only"></ion-icon> | ||||
|                         <ion-icon name="fas-trash" color="danger" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                     </ion-button> | ||||
| 
 | ||||
|                     <div class="tail" *ngIf="message.showTail"></div> | ||||
| @ -126,7 +129,7 @@ | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="loaded && newMessages > 0"> | ||||
|         <ion-fab-button size="small" (click)="scrollToFirstUnreadMessage()" color="light" | ||||
|         [attr.aria-label]="'addon.messages.newmessages' | translate"> | ||||
|             <ion-icon name="fas-arrow-down"></ion-icon> | ||||
|             <ion-icon name="fas-arrow-down" aria-hidden="true"></ion-icon> | ||||
|             <span class="core-discussion-messages-badge">{{ newMessages }}</span> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messages.messages' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
| @ -26,8 +26,8 @@ | ||||
|             <ion-list   class="ion-no-margin"> | ||||
| 
 | ||||
|                 <ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()" | ||||
|                     [attr.aria-label]="'addon.messages.contacts' | translate" detail> | ||||
|                     <ion-icon name="fas-address-book" slot="start"></ion-icon> | ||||
|                     [attr.aria-label]="'addon.messages.contacts' | translate" detail="true" button> | ||||
|                     <ion-icon name="fas-address-book" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label><h2>{{ 'addon.messages.contacts' | translate }}</h2></ion-label> | ||||
|                 </ion-item> | ||||
| 
 | ||||
| @ -38,9 +38,9 @@ | ||||
|                         </ion-label> | ||||
|                         <ion-note slot="end" class="ion-padding-end"><ion-badge>{{ search.results.length }}</ion-badge></ion-note> | ||||
|                     </ion-item-divider> | ||||
|                     <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" [title]="result.fullname" | ||||
|                         (click)="gotoDiscussion(result.userid, result.messageid)" | ||||
|                         [class.core-selected-item]="result.userid == discussionUserId"> | ||||
|                     <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" button | ||||
|                         [attr.aria-label]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)" | ||||
|                         [attr.aria-current]="result.userid == discussionUserId ? 'page' :  'false'"> | ||||
|                         <core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar> | ||||
|                         <ion-label> | ||||
|                                 <h2>{{ result.fullname }}</h2> | ||||
| @ -50,9 +50,9 @@ | ||||
|                     </ion-item> | ||||
|                 </ng-container> | ||||
|                 <ng-container *ngIf="!search.showResults"> | ||||
|                     <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions" | ||||
|                         [title]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)" | ||||
|                         [class.core-selected-item]="discussion.message!.user == discussionUserId"> | ||||
|                     <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions" button | ||||
|                         [attr.aria-label]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)" | ||||
|                         [attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' :  'false'"> | ||||
|                         <core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar> | ||||
|                         <ion-label> | ||||
|                             <h2>{{ discussion.fullname }}</h2> | ||||
|  | ||||
| @ -1,15 +1,15 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messages.messages' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="gotoSearch()" [attr.aria-label]="'addon.messages.search' | translate"> | ||||
|                 <ion-icon name="fas-search" slot="icon-only"></ion-icon> | ||||
|             <ion-button (click)="gotoSearch()" [attr.aria-label]="'addon.messages.searchcombined' | translate"> | ||||
|                 <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|             <ion-button (click)="gotoSettings()" [attr.aria-label]="'addon.messages.messagepreferences' | translate"> | ||||
|                 <ion-icon name="fas-cog" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-cog" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|             <!-- Add an empty context menu so discussion page can add items in split view, | ||||
|                 otherwise the menu disappears in some cases. --> | ||||
| @ -26,15 +26,17 @@ | ||||
|         <core-loading [hideUntil]="loaded" [message]="loadingMessage"> | ||||
|             <ion-list> | ||||
|                 <ion-item class="ion-text-wrap addon-message-discussion" (click)="gotoContacts()" | ||||
|                     [attr.aria-label]="'addon.messages.contacts' | translate" detail> | ||||
|                     <ion-icon name="fas-address-book" slot="start"></ion-icon> | ||||
|                     [attr.aria-label]="'addon.messages.contacts' | translate" detail="true" button> | ||||
|                     <ion-icon name="fas-address-book" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label><h2>{{ 'addon.messages.contacts' | translate }}</h2></ion-label> | ||||
|                     <ion-badge *ngIf="contactRequestsCount > 0" slot="end">{{contactRequestsCount}}</ion-badge> | ||||
|                 </ion-item> | ||||
|                 <!-- Favourite conversations. --> | ||||
|                 <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggle(favourites)" sticky="true"> | ||||
|                     <ion-icon *ngIf="!favourites.expanded" name="fas-caret-right" slot="start"></ion-icon> | ||||
|                     <ion-icon *ngIf="favourites.expanded" name="fas-caret-down" slot="start"></ion-icon> | ||||
|                 <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggle(favourites)" sticky="true" | ||||
|                     [attr.aria-label]="(favourites.expanded ? 'core.collapse' : 'core.expand') | translate" | ||||
|                     [attr.aria-expanded]="favourites.expanded" role="heading button"> | ||||
|                     <ion-icon *ngIf="!favourites.expanded" name="fas-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-icon *ngIf="favourites.expanded" name="fas-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label>{{ 'core.favourites' | translate }} ({{ favourites.count }})</ion-label> | ||||
|                     <ion-badge slot="end" *ngIf="favourites.unread">{{ favourites.unread }}</ion-badge> | ||||
|                 </ion-item-divider> | ||||
| @ -53,9 +55,11 @@ | ||||
|                 </ion-item> | ||||
| 
 | ||||
|                 <!-- Group conversations. --> | ||||
|                 <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggle(group)" sticky="true"> | ||||
|                     <ion-icon *ngIf="!group.expanded" name="fas-caret-right" slot="start"></ion-icon> | ||||
|                     <ion-icon *ngIf="group.expanded" name="fas-caret-down" slot="start"></ion-icon> | ||||
|                 <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggle(group)" sticky="true" | ||||
|                     [attr.aria-label]="(group.expanded ? 'core.collapse' : 'core.expand') | translate" | ||||
|                     [attr.aria-expanded]="group.expanded" role="heading button"> | ||||
|                     <ion-icon *ngIf="!group.expanded" name="fas-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-icon *ngIf="group.expanded" name="fas-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label>{{ 'addon.messages.groupconversations' | translate }} ({{ group.count }})</ion-label> | ||||
|                     <ion-badge slot="end" *ngIf="group.unread">{{ group.unread }}</ion-badge> | ||||
|                 </ion-item-divider> | ||||
| @ -73,9 +77,11 @@ | ||||
|                     <ion-label><ion-spinner></ion-spinner></ion-label> | ||||
|                 </ion-item> | ||||
| 
 | ||||
|                 <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggle(individual)" sticky="true"> | ||||
|                     <ion-icon *ngIf="!individual.expanded" name="fas-caret-right" slot="start"></ion-icon> | ||||
|                     <ion-icon *ngIf="individual.expanded" name="fas-caret-down" slot="start"></ion-icon> | ||||
|                 <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggle(individual)" sticky="true" | ||||
|                     [attr.aria-label]="(individual.expanded ? 'core.collapse' : 'core.expand') | translate" | ||||
|                     [attr.aria-expanded]="individual.expanded" role="heading button"> | ||||
|                     <ion-icon *ngIf="!individual.expanded" name="fas-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-icon *ngIf="individual.expanded" name="fas-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label>{{ 'addon.messages.individualconversations' | translate }} ({{ individual.count }})</ion-label> | ||||
|                     <ion-badge slot="end" *ngIf="individual.unread">{{ individual.unread }}</ion-badge> | ||||
|                 </ion-item-divider> | ||||
| @ -100,10 +106,10 @@ | ||||
| 
 | ||||
| <!-- Template to render a list of conversations. --> | ||||
| <ng-template #conversationsTemplate let-conversations="conversations"> | ||||
|     <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let conversation of conversations" [title]="conversation.name" | ||||
|         (click)="gotoConversation(conversation.id, conversation.userid)" | ||||
|         [class.core-selected-item]="(conversation.id && conversation.id == selectedConversationId) || | ||||
|             (conversation.userid && conversation.userid == selectedUserId)" | ||||
|     <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let conversation of conversations" button | ||||
|         [attr.aria-label]="conversation.name" (click)="gotoConversation(conversation.id, conversation.userid)" | ||||
|         [attr.aria-current]="((conversation.id && conversation.id == selectedConversationId) || | ||||
|             (conversation.userid && conversation.userid == selectedUserId)) ? 'page': 'false'" | ||||
|         id="addon-message-conversation-{{ conversation.id ? conversation.id : 'user-' + conversation.userid }}"> | ||||
|         <!-- Group conversation image. --> | ||||
|         <ion-avatar slot="start" *ngIf="conversation.type == typeGroup"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messages.searchcombined' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
| @ -42,13 +42,16 @@ | ||||
|         </ion-item-divider> | ||||
| 
 | ||||
|         <!-- List of results --> | ||||
|         <ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [title]="result.fullname" | ||||
|             (click)="openConversation(result)" [class.core-selected-item]="result == selectedResult" detail> | ||||
|         <ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [attr.aria-label]="result.fullname" | ||||
|             (click)="openConversation(result)" [attr.aria-current]="result == selectedResult ? 'page' :  'false'" detail="true" | ||||
|             button> | ||||
|             <core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar> | ||||
|             <ion-label> | ||||
|                 <h2> | ||||
|                     <core-format-text [text]="result.fullname" [highlight]="result.highlightName" [filter]="false"></core-format-text> | ||||
|                     <ion-icon name="fa-ban" *ngIf="result.isblocked" [title]="'addon.messages.contactblocked' | translate"> | ||||
|                     <core-format-text [text]="result.fullname" [highlight]="result.highlightName" [filter]="false"> | ||||
|                     </core-format-text> | ||||
|                     <ion-icon name="fa-ban" *ngIf="result.isblocked" | ||||
|                         [attr.aria-label]="'addon.messages.contactblocked' | translate"> | ||||
|                     </ion-icon> | ||||
|                 </h2> | ||||
|                 <ion-note *ngIf="result.lastmessagedate > 0"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.messages.messages' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <ion-title>{{ plugin.name }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon slot="icon-only" name="fas-times"></ion-icon> | ||||
|                 <ion-icon slot="icon-only" name="fas-times" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
|  | ||||
| @ -49,7 +49,7 @@ | ||||
|     <!-- Assign has something offline. --> | ||||
|     <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| @ -84,7 +84,8 @@ | ||||
|             </ion-item> | ||||
| 
 | ||||
|             <!-- Summary of all submissions. --> | ||||
|             <ion-item class="ion-text-wrap" *ngIf="summary && summary.participantcount" (click)="goToSubmissionList()" detail> | ||||
|             <ion-item class="ion-text-wrap" *ngIf="summary && summary.participantcount" (click)="goToSubmissionList()" detail="true" | ||||
|                 button> | ||||
|                 <ion-label> | ||||
|                     <h2 *ngIf="assign.teamsubmission">{{ 'addon.mod_assign.numberofteams' | translate }}</h2> | ||||
|                     <h2 *ngIf="!assign.teamsubmission">{{ 'addon.mod_assign.numberofparticipants' | translate }}</h2> | ||||
| @ -97,6 +98,7 @@ | ||||
|             <!-- Summary of submissions with draft status. --> | ||||
|             <ion-item class="ion-text-wrap" *ngIf="assign.submissiondrafts && summary && summary.submissionsenabled" | ||||
|                 [detail]="!showNumbers || summary.submissiondraftscount" | ||||
|                 [button]="!showNumbers || summary.submissiondraftscount" | ||||
|                 (click)="goToSubmissionList(submissionStatusDraft, !!summary.submissiondraftscount)"> | ||||
|                 <ion-label><h2>{{ 'addon.mod_assign.numberofdraftsubmissions' | translate }}</h2></ion-label> | ||||
|                 <ion-badge slot="end" *ngIf="showNumbers" color="primary"> | ||||
| @ -107,6 +109,7 @@ | ||||
|             <!-- Summary of submissions with submitted status. --> | ||||
|             <ion-item class="ion-text-wrap" *ngIf="summary && summary.submissionsenabled" | ||||
|                 [detail]="!showNumbers || summary.submissionssubmittedcount" | ||||
|                 [button]="!showNumbers || summary.submissionssubmittedcount" | ||||
|                 (click)="goToSubmissionList(submissionStatusSubmitted, !!summary.submissionssubmittedcount)"> | ||||
|                 <ion-label><h2>{{ 'addon.mod_assign.numberofsubmittedassignments' | translate }}</h2></ion-label> | ||||
|                 <ion-badge slot="end" *ngIf="showNumbers" color="primary"> | ||||
| @ -116,7 +119,7 @@ | ||||
| 
 | ||||
|             <!-- Summary of submissions that need grading. --> | ||||
|             <ion-item class="ion-text-wrap" *ngIf="summary && summary.submissionsenabled && !assign.teamsubmission && showNumbers" | ||||
|                 [detail]="needsGradingAvalaible" | ||||
|                 [detail]="needsGradingAvalaible" [button]="needsGradingAvalaible" | ||||
|                 (click)="goToSubmissionList(needGrading, needsGradingAvalaible)"> | ||||
|                 <ion-label><h2>{{ 'addon.mod_assign.numberofsubmissionsneedgrading' | translate }}</h2></ion-label> | ||||
|                 <ion-badge slot="end" color="primary"> | ||||
| @ -128,7 +131,7 @@ | ||||
|         <!-- Ungrouped users. --> | ||||
|         <ion-card *ngIf="assign.teamsubmission && summary && summary.warnofungroupedusers" class="core-info-card"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-question-circle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-question-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'addon.mod_assign.'+summary.warnofungroupedusers | translate }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| 
 | ||||
|     <!-- User and status of the submission. --> | ||||
|     <ion-item class="ion-text-wrap" *ngIf="!blindMarking && user" core-user-link [userId]="submitId" [courseId]="courseId" | ||||
|         [title]="user!.fullname"> | ||||
|         [attr.aria-label]="user!.fullname"> | ||||
|         <core-user-avatar [user]="user" slot="start"></core-user-avatar> | ||||
|         <ion-label> | ||||
|             <h2>{{ user!.fullname }}</h2> | ||||
| @ -183,7 +183,7 @@ | ||||
|                 <ng-container *ngIf="membersToSubmit && membersToSubmit.length > 0 && !blindMarking"> | ||||
|                     <ng-container *ngFor="let user of membersToSubmit"> | ||||
|                         <ion-item class="ion-text-wrap" core-user-link [userId]="user.id" | ||||
|                             [courseId]="courseId" [title]="user.fullname"> | ||||
|                             [courseId]="courseId" [attr.aria-label]="user.fullname"> | ||||
|                             <core-user-avatar [user]="user" slot="start"></core-user-avatar> | ||||
|                             <ion-label><h2>{{ user.fullname }}</h2></ion-label> | ||||
|                         </ion-item> | ||||
| @ -225,8 +225,9 @@ | ||||
|                         <h2>{{ 'addon.mod_assign.currentgrade' | translate }}</h2> | ||||
|                         <p><core-format-text [text]="feedback!.gradefordisplay" [filter]="false"></core-format-text></p> | ||||
|                     </ion-label> | ||||
|                     <ion-button slot="end" *ngIf="feedback!.advancedgrade" (click)="showAdvancedGrade()"> | ||||
|                         <ion-icon name="fas-search" slot="icon-only"></ion-icon> | ||||
|                     <ion-button slot="end" *ngIf="feedback!.advancedgrade" (click)="showAdvancedGrade()" | ||||
|                         [attr.aria-label]="'core.showadvanced' |translate"> | ||||
|                         <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                     </ion-button> | ||||
|                 </ion-item> | ||||
| 
 | ||||
| @ -328,7 +329,7 @@ | ||||
| 
 | ||||
|                 <!-- Data about the grader (teacher who graded). --> | ||||
|                 <ion-item class="ion-text-wrap" *ngIf="grader" core-user-link [userId]="grader!.id" [courseId]="courseId" | ||||
|                     [title]="grader!.fullname" detail="true"> | ||||
|                     [attr.aria-label]="grader!.fullname" detail="true"> | ||||
|                     <core-user-avatar [user]="grader" slot="start"></core-user-avatar> | ||||
|                     <ion-label> | ||||
|                         <h2>{{ 'addon.mod_assign.gradedby' | translate }}</h2> | ||||
| @ -348,12 +349,12 @@ | ||||
|                 <!-- Warning message if cannot save grades. --> | ||||
|                 <ion-card *ngIf="isGrading && !canSaveGrades" class="core-warning-card"> | ||||
|                     <ion-item> | ||||
|                         <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                         <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                         <ion-label> | ||||
|                             <p>{{ 'addon.mod_assign.cannotgradefromapp' | translate }}</p> | ||||
|                             <ion-button expand="block" *ngIf="gradeUrl" [href]="gradeUrl" core-link > | ||||
|                                 {{ 'core.openinbrowser' | translate }} | ||||
|                                 <ion-icon name="fas-external-link-alt" slot="end"></ion-icon> | ||||
|                                 <ion-icon name="fas-external-link-alt" slot="end" aria-hidden="true"></ion-icon> | ||||
|                             </ion-button> | ||||
|                         </ion-label> | ||||
|                     </ion-item> | ||||
|  | ||||
| @ -11,13 +11,13 @@ | ||||
|     </ion-label> | ||||
|     <div slot="end"> | ||||
|         <div class="ion-text-end"> | ||||
|             <ion-button fill="clear" *ngIf="canEdit" (click)="editComment()" color="dark"> | ||||
|                 <ion-icon name="fas-pen" slot="icon-only"></ion-icon> | ||||
|             <ion-button fill="clear" *ngIf="canEdit" (click)="editComment()" color="dark" | ||||
|                 [attr.aria-label]="'core.edit' | translate"> | ||||
|                 <ion-icon name="fas-pen" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </div> | ||||
|         <ion-note *ngIf="!isSent" color="dark"> | ||||
|             <ion-icon name="far-clock"></ion-icon> | ||||
|             {{ 'core.notsent' | translate }} | ||||
|             <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> {{ 'core.notsent' | translate }} | ||||
|         </ion-note> | ||||
|     </div> | ||||
| </ion-item> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="moduleId"  [courseId]="courseId"> | ||||
| @ -39,8 +39,8 @@ | ||||
|                 </ion-item> | ||||
|                 <!-- List of submissions. --> | ||||
|                 <ng-container *ngFor="let submission of submissions.items"> | ||||
|                     <ion-item class="ion-text-wrap" (click)="submissions.select(submission)" | ||||
|                         [class.core-selected-item]="submissions.isSelected(submission)"> | ||||
|                     <ion-item class="ion-text-wrap" (click)="submissions.select(submission)" button | ||||
|                         [attr.aria-current]="submissions.getItemAriaCurrent(submission)"> | ||||
|                         <core-user-avatar [user]="submission" [linkProfile]="false" slot="start"></core-user-avatar> | ||||
|                         <ion-label> | ||||
|                             <h2 *ngIf="submission.userfullname">{{submission.userfullname}}</h2> | ||||
| @ -75,7 +75,7 @@ | ||||
| 
 | ||||
|                 <ion-card class="ion-text-wrap core-warning-card" *ngIf="!haveAllParticipants"> | ||||
|                     <ion-item> | ||||
|                         <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                         <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                         <ion-label>{{ 'addon.mod_assign.notallparticipantsareshown' | translate }}</ion-label> | ||||
|                     </ion-item> | ||||
|                 </ion-card> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,4 +1,4 @@ | ||||
| <ion-item *ngIf="commentsEnabled" class="ion-text-wrap" (click)="showComments($event)" detail="false"> | ||||
| <ion-item *ngIf="commentsEnabled" class="ion-text-wrap" (click)="showComments($event)" detail="false" button> | ||||
|     <ion-label> | ||||
|         <h2>{{plugin.name}}</h2> | ||||
|         <core-comments contextLevel="module" [instanceId]="assign.cmid" component="assignsubmission_comments" | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <!-- Buttons to add to the header. --> | ||||
| <core-navbar-buttons slot="end"> | ||||
|     <ion-button (click)="showToc()" [attr.aria-label]="'addon.mod_book.toc' | translate" aria-haspopup="true" *ngIf="loaded"> | ||||
|         <ion-icon name="fas-bookmark" slot="icon-only"></ion-icon> | ||||
|         <ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|     </ion-button> | ||||
|     <core-context-menu> | ||||
|         <core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" | ||||
| @ -27,8 +27,10 @@ | ||||
|         contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"></core-course-module-description> | ||||
| 
 | ||||
|     <ion-card class="core-warning-card" *ngIf="warning"> | ||||
|         <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|         <span [innerHTML]="warning"></span> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label><span [innerHTML]="warning"></span></ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| 
 | ||||
|     <div class="ion-padding safe-padding-horizontal"> | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <ion-title>{{ 'addon.mod_book.toc' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon name="fas-times" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-times" slot="icon-only" aria-hidden=true></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -12,7 +12,7 @@ | ||||
|     <nav> | ||||
|         <ion-list> | ||||
|             <ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)" | ||||
|                 [class.core-selected-item]="selected == chapter.id" | ||||
|                 [attr.aria-current]="selected == chapter.id ? 'page' :  'false'" button | ||||
|                 [class.item-dimmed]="chapter.hidden"> | ||||
|                 <ion-label> | ||||
|                     <p [class.ion-padding-left]="addPadding && chapter.level == 1 ? true : null"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -32,7 +32,7 @@ | ||||
| 
 | ||||
|     <ion-card *ngIf="chatInfo" class="core-info-card"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-clock" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-clock" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'addon.mod_chat.sessionstart' | translate:{$a: chatInfo} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_chat.currentusers' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon slot="icon-only" name="fas-times"></ion-icon> | ||||
|                 <ion-icon slot="icon-only" name="fas-times" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -21,11 +21,11 @@ | ||||
|                 <h2>{{ user.fullname }}</h2> | ||||
|                 <ng-container *ngIf="currentUserId != user.id && isOnline"> | ||||
|                     <ion-button fill="clear" (click)="talkTo(user)"> | ||||
|                         <ion-icon name="fas-comments" slot="start"></ion-icon> | ||||
|                         <ion-icon name="fas-comments" slot="start" aria-hidden="true"></ion-icon> | ||||
|                         {{ 'addon.mod_chat.talk' | translate }} | ||||
|                     </ion-button> | ||||
|                     <ion-button fill="clear" (click)="beepTo(user)"> | ||||
|                         <ion-icon name="fas-bell" slot="start"></ion-icon> | ||||
|                         <ion-icon name="fas-bell" slot="start" aria-hidden="true"></ion-icon> | ||||
|                         {{ 'addon.mod_chat.beep' | translate }} | ||||
|                     </ion-button> | ||||
|                 </ng-container> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"> | ||||
| @ -9,7 +9,7 @@ | ||||
|         </ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button *ngIf="loaded" (click)="showChatUsers()" [attr.aria-label]="'core.users' | translate"> | ||||
|                 <ion-icon name="fas-users" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-users" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -26,7 +26,7 @@ | ||||
|                 <div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special"> | ||||
|                     <ion-badge class="ion-text-wrap" color="success" *ngIf="message.system && message.message == 'enter'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-sign-in-alt"></ion-icon> | ||||
|                             <ion-icon name="fas-sign-in-alt" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messageenter' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -34,7 +34,7 @@ | ||||
| 
 | ||||
|                     <ion-badge class="ion-text-wrap" color="danger" *ngIf="message.system && message.message == 'exit'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-sign-out-alt"></ion-icon> | ||||
|                             <ion-icon name="fas-sign-out-alt" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messageexit' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -42,7 +42,7 @@ | ||||
| 
 | ||||
|                     <ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep == 'all'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-bell"></ion-icon> | ||||
|                             <ion-icon name="fas-bell" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messagebeepseveryone' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -51,7 +51,7 @@ | ||||
|                     <ion-badge class="ion-text-wrap" color="primary" | ||||
|                         *ngIf="message.userid != currentUserId && message.beep == currentUserId"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-bell"></ion-icon> | ||||
|                             <ion-icon name="fas-bell" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messagebeepsyou' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -60,7 +60,7 @@ | ||||
|                     <ion-badge class="ion-text-wrap" color="light" | ||||
|                         *ngIf="message.userid == currentUserId && message.beep && message.beep != 'all'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-bell"></ion-icon> | ||||
|                             <ion-icon name="fas-bell" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messageyoubeep' | translate:{$a: message.beepWho} }} | ||||
|                         </span> | ||||
| @ -68,7 +68,7 @@ | ||||
| 
 | ||||
|                     <ion-badge class="ion-text-wrap" color="info" *ngIf="!message.system && !message.beep"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-asterisk"></ion-icon> | ||||
|                             <ion-icon name="fas-asterisk" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             <strong> | ||||
|                                 {{ message.userfullname }} <core-format-text [text]="message.message" contextLevel="module" | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_chat.messages' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -21,7 +21,7 @@ | ||||
|                 <div class="ion-text-center addon-mod_chat-notice" *ngIf="message.special"> | ||||
|                     <ion-badge class="ion-text-wrap" color="success" *ngIf="message.issystem && message.message == 'enter'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-sign-in-alt"></ion-icon> | ||||
|                             <ion-icon name="fas-sign-in-alt" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messageenter' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -29,7 +29,7 @@ | ||||
| 
 | ||||
|                     <ion-badge class="ion-text-wrap" color="danger" *ngIf="message.issystem && message.message == 'exit'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-sign-out-alt"></ion-icon> | ||||
|                             <ion-icon name="fas-sign-out-alt" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messageexit' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -37,7 +37,7 @@ | ||||
| 
 | ||||
|                     <ion-badge class="ion-text-wrap" color="primary" *ngIf="message.beep == 'all'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-bell"></ion-icon> | ||||
|                             <ion-icon name="fas-bell" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messagebeepseveryone' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -46,7 +46,7 @@ | ||||
|                     <ion-badge class="ion-text-wrap" color="primary" | ||||
|                         *ngIf="message.userid != currentUserId && message.beep == currentUserId"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-bell"></ion-icon> | ||||
|                             <ion-icon name="fas-bell" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messagebeepsyou' | translate:{$a: message.userfullname} }} | ||||
|                         </span> | ||||
| @ -55,7 +55,7 @@ | ||||
|                     <ion-badge class="ion-text-wrap" color="light" | ||||
|                         *ngIf="message.userid == currentUserId && message.beep && message.beep != 'all'"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-bell"></ion-icon> | ||||
|                             <ion-icon name="fas-bell" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             {{ 'addon.mod_chat.messageyoubeep' | translate:{$a: message.beepWho} }} | ||||
|                         </span> | ||||
| @ -63,7 +63,7 @@ | ||||
| 
 | ||||
|                     <ion-badge class="ion-text-wrap" color="info" *ngIf="!message.issystem && !message.beep"> | ||||
|                         <span> | ||||
|                             <ion-icon name="fas-asterisk"></ion-icon> | ||||
|                             <ion-icon name="fas-asterisk" aria-hidden="true"></ion-icon> | ||||
|                             {{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }} | ||||
|                             <strong> | ||||
|                                 {{ message.userfullname }} <core-format-text [text]="message.message" contextLevel="module" | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_chat.chatreport' | translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -31,7 +31,7 @@ | ||||
|             </ion-item> | ||||
| 
 | ||||
|             <ion-card *ngFor="let session of sessions.items" (click)="sessions.select(session)" | ||||
|                 [class.core-selected-item]="sessions.isSelected(session)" | ||||
|                 [attr.aria-current]="sessions.getItemAriaCurrent(session)" | ||||
|                 [class.addon-mod-chat-session-show-more]="session.sessionusers.length < session.allsessionusers.length"> | ||||
| 
 | ||||
|                 <ion-item class="ion-text-wrap"> | ||||
|  | ||||
| @ -35,7 +35,7 @@ | ||||
|     <!-- Activity availability messages --> | ||||
|     <ion-card class="core-info-card" *ngIf="choiceNotOpenYet"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label> | ||||
|                 <p *ngIf="options.length">{{ 'addon.mod_choice.previewonly' | translate:{$a: openTimeReadable} }}</p> | ||||
|                 <p *ngIf="!options.length">{{ 'addon.mod_choice.notopenyet' | translate:{$a: openTimeReadable} }}</p> | ||||
| @ -45,7 +45,7 @@ | ||||
| 
 | ||||
|     <ion-card class="core-info-card" *ngIf="choiceClosed"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label> | ||||
|                 <p *ngIf="options.length"> | ||||
|                     {{ 'addon.mod_choice.yourselection' | translate }} | ||||
| @ -61,7 +61,7 @@ | ||||
|     <!-- Choice done in offline but not synchronized --> | ||||
|     <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| @ -69,7 +69,7 @@ | ||||
|     <!-- Inform what will happen with the choices. --> | ||||
|     <ion-card class="core-info-card" *ngIf="canEdit && publishInfo && options.length"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ publishInfo | translate }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| @ -111,7 +111,7 @@ | ||||
|             <ion-row> | ||||
|                 <ion-col size="12" size-lg="5"> | ||||
|                     <ion-item class="ion-text-wrap core-warning-item" *ngIf="hasOffline"> | ||||
|                         <ion-icon slot="start" name="fas-exclamation-triangle" color="warning"></ion-icon> | ||||
|                         <ion-icon slot="start" name="fas-exclamation-triangle" color="warning" aria-hidden="true"></ion-icon> | ||||
|                         <ion-label>{{ 'addon.mod_choice.resultsnotsynced' | translate }}</ion-label> | ||||
|                     </ion-item> | ||||
|                     <ion-item> | ||||
| @ -141,7 +141,7 @@ | ||||
|                             </ion-label> | ||||
|                         </ion-item-divider> | ||||
|                         <ion-item *ngFor="let user of result.userresponses" core-user-link [courseId]="courseId" | ||||
|                             [userId]="user.userid" [title]="user.fullname" class="ion-text-wrap"> | ||||
|                             [userId]="user.userid" [attr.aria-label]="user.fullname" class="ion-text-wrap"> | ||||
|                             <core-user-avatar [user]="user" slot="start" [courseId]="courseId"></core-user-avatar> | ||||
|                             <ion-label><p>{{user.fullname}}</p></ion-label> | ||||
|                         </ion-item> | ||||
| @ -153,7 +153,7 @@ | ||||
| 
 | ||||
|     <ion-card class="core-info-card" *ngIf="!canSeeResults && !choiceNotOpenYet"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label><p>{{ 'addon.mod_choice.noresultsviewable' | translate }}</p></ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,26 +1,26 @@ | ||||
| <ion-button *ngIf="action == 'more'" fill="clear" (click)="viewEntry()" [title]="'addon.mod_data.more' | translate"> | ||||
|     <ion-icon name="fas-search" slot="icon-only"></ion-icon> | ||||
| <ion-button *ngIf="action == 'more'" fill="clear" (click)="viewEntry()" [attr.aria-label]="'addon.mod_data.more' | translate"> | ||||
|     <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
| </ion-button> | ||||
| 
 | ||||
| <ion-button *ngIf="action == 'edit'" fill="clear" (click)="editEntry()"  [title]="'core.edit' | translate"> | ||||
|     <ion-icon name="fas-cog" slot="icon-only"></ion-icon> | ||||
| <ion-button *ngIf="action == 'edit'" fill="clear" (click)="editEntry()"  [attr.aria-label]="'core.edit' | translate"> | ||||
|     <ion-icon name="fas-cog" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
| </ion-button> | ||||
| 
 | ||||
| <ion-button *ngIf="action == 'delete' && !entry.deleted" fill="clear" (click)="deleteEntry()" [title]="'core.delete' | translate"> | ||||
|     <ion-icon name="fas-trash" slot="icon-only"></ion-icon> | ||||
| <ion-button *ngIf="action == 'delete' && !entry.deleted" fill="clear" (click)="deleteEntry()" [attr.aria-label]="'core.delete' | translate"> | ||||
|     <ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
| </ion-button> | ||||
| 
 | ||||
| <ion-button *ngIf="action == 'delete' && entry.deleted" fill="clear" (click)="undoDelete()" [title]="'core.restore' | translate"> | ||||
|     <ion-icon name="fas-undo-alt" slot="icon-only"></ion-icon> | ||||
| <ion-button *ngIf="action == 'delete' && entry.deleted" fill="clear" (click)="undoDelete()" [attr.aria-label]="'core.restore' | translate"> | ||||
|     <ion-icon name="fas-undo-alt" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
| </ion-button> | ||||
| 
 | ||||
| <ion-button *ngIf="action == 'approve'" fill="clear" (click)="approveEntry()" [title]="'addon.mod_data.approve' | translate"> | ||||
|     <ion-icon name="fas-thumbs-up" slot="icon-only"></ion-icon> | ||||
| <ion-button *ngIf="action == 'approve'" fill="clear" (click)="approveEntry()" [attr.aria-label]="'addon.mod_data.approve' | translate"> | ||||
|     <ion-icon name="fas-thumbs-up" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
| </ion-button> | ||||
| 
 | ||||
| <ion-button *ngIf="action == 'disapprove'" fill="clear" (click)="disapproveEntry()" | ||||
|     [title]="'addon.mod_data.disapprove' | translate"> | ||||
|     <ion-icon name="far-thumbs-down" slot="icon-only"></ion-icon> | ||||
|     [attr.aria-label]="'addon.mod_data.disapprove' | translate"> | ||||
|     <ion-icon name="far-thumbs-down" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
| </ion-button> | ||||
| 
 | ||||
| <core-comments *ngIf="action == 'comments' && mode == 'list'" contextLevel="module" [instanceId]="database.coursemodule" | ||||
| @ -32,7 +32,7 @@ component="mod_data" [itemId]="entry.id" area="database_entry" [courseId]="datab | ||||
| 
 | ||||
| <a *ngIf="action == 'userpicture'" core-user-link [courseId]="database.course" [userId]="entry.userid" [title]="entry.fullname"> | ||||
|     <img class="avatar-round" [src]="userPicture" [alt]="'core.pictureof' | translate:{$a: entry.fullname}" core-external-content | ||||
|     onError="this.src='assets/img/user-avatar.png'" role="presentation"> | ||||
|     onError="this.src='assets/img/user-avatar.png'"> | ||||
| </a> | ||||
| 
 | ||||
| <a *ngIf="action == 'user' && entry" core-user-link [courseId]="database.course" [userId]="entry.userid" [title]="entry.fullname"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <!-- Buttons to add to the header. --> | ||||
| <core-navbar-buttons slot="end"> | ||||
|     <ion-button *ngIf="canSearch" (click)="showSearch()" [attr.aria-label]="'addon.mod_data.search' | translate"> | ||||
|         <ion-icon name="fas-search" slot="icon-only"></ion-icon> | ||||
|         <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|     </ion-button> | ||||
|     <core-context-menu> | ||||
|         <core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" | ||||
| @ -46,7 +46,7 @@ | ||||
|     <!-- Data done in offline but not synchronized --> | ||||
|     <ion-card class="core-warning-card" *ngIf="hasOffline || hasOfflineRatings"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| @ -66,21 +66,21 @@ | ||||
| 
 | ||||
|     <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableFrom"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'addon.mod_data.notopenyet' | translate:{$a: timeAvailableFromReadable} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| 
 | ||||
|     <ion-card class="core-info-card" *ngIf="!access?.timeavailable && timeAvailableTo"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'addon.mod_data.expired' | translate:{$a: timeAvailableToReadable} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| 
 | ||||
|     <ion-card class="core-info-card" *ngIf="access && access.entrieslefttoview">> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label> | ||||
|                 {{ 'addon.mod_data.entrieslefttoaddtoview' | translate:{$a: {entrieslefttoview: access.entrieslefttoview} } }} | ||||
|             </ion-label> | ||||
| @ -89,7 +89,7 @@ | ||||
| 
 | ||||
|     <ion-card class="core-info-card" *ngIf="access && access.entrieslefttoadd">> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label> | ||||
|                 {{ 'addon.mod_data.entrieslefttoadd' | translate:{$a: {entriesleft: access.entrieslefttoadd} } }} | ||||
|             </ion-label> | ||||
| @ -121,14 +121,14 @@ | ||||
|         <ion-row class="ion-align-items-center"> | ||||
|             <ion-col *ngIf="search.page > 0"> | ||||
|                 <ion-button expand="block" fill="outline" (click)="searchEntries(search.page - 1)"> | ||||
|                     <ion-icon name="fas-chevron-left" slot="start"></ion-icon> | ||||
|                     <ion-icon name="fas-chevron-left" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     {{ 'core.previous' | translate }} | ||||
|                 </ion-button> | ||||
|             </ion-col> | ||||
|             <ion-col *ngIf="hasNextPage"> | ||||
|                 <ion-button expand="block" (click)="searchEntries(search.page + 1)"> | ||||
|                     {{ 'core.next' | translate }} | ||||
|                     <ion-icon name="fas-chevron-right" slot="end"></ion-icon> | ||||
|                     <ion-icon name="fas-chevron-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|                 </ion-button> | ||||
|             </ion-col> | ||||
|         </ion-row> | ||||
| @ -146,6 +146,6 @@ | ||||
| 
 | ||||
| <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canAdd"> | ||||
|     <ion-fab-button (click)="gotoAddEntries()" [attr.aria-label]="'addon.mod_data.addentries' | translate"> | ||||
|         <ion-icon name="fas-plus"></ion-icon> | ||||
|         <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|     </ion-fab-button> | ||||
| </ion-fab> | ||||
|  | ||||
| @ -90,7 +90,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|     entriesRendered = ''; | ||||
|     extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule]; | ||||
| 
 | ||||
|     jsData? : { | ||||
|     jsData?: { | ||||
|         fields: Record<number, AddonModDataField>; | ||||
|         entries: Record<number, AddonModDataEntry>; | ||||
|         database: AddonModDataData; | ||||
| @ -100,7 +100,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp | ||||
|     }; | ||||
| 
 | ||||
|     // Data for found records translation.
 | ||||
|     foundRecordsTranslationData? : { | ||||
|     foundRecordsTranslationData?: { | ||||
|         num: number; | ||||
|         max: number; | ||||
|         reseturl: string; | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_data.search' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon name="fas-times" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-times" slot="icon-only" aria-hidden=true></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -60,7 +60,7 @@ | ||||
|         </ion-list> | ||||
|         <div class="ion-padding"> | ||||
|             <ion-button expand="block" type="submit"> | ||||
|                 <ion-icon name="fas-search" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-search" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 {{ 'addon.mod_data.search' | translate }} | ||||
|             </ion-button> | ||||
|         </div> | ||||
|  | ||||
| @ -52,7 +52,7 @@ export class AddonModDataSearchComponent implements OnInit { | ||||
|     extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule]; | ||||
| 
 | ||||
|     searchForm: FormGroup; | ||||
|     jsData? : { | ||||
|     jsData?: { | ||||
|         fields: Record<number, AddonModDataField>; | ||||
|         form: FormGroup; | ||||
|         search: CoreFormFields; | ||||
|  | ||||
| @ -13,7 +13,7 @@ | ||||
|         </div> | ||||
|         <div class="addon-data-latlong" *ngIf="locationServicesEnabled"> | ||||
|             <ion-button (click)="getLocation($event)"> | ||||
|                 <ion-icon name="fas-crosshairs" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-crosshairs" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 {{ 'addon.mod_data.mylocation' | translate }} | ||||
|             </ion-button> | ||||
|         </div> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -77,7 +77,7 @@ export class AddonModDataEditPage implements OnInit { | ||||
|     editFormRender = ''; | ||||
|     editForm: FormGroup; | ||||
|     extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule]; | ||||
|     jsData? : { | ||||
|     jsData?: { | ||||
|         fields: Record<number, AddonModDataField>; | ||||
|         database?: AddonModDataData; | ||||
|         contents: AddonModDataEntryFields; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||
| @ -19,7 +19,7 @@ | ||||
|         <!-- Database entries found to be synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="entry && entry.hasOffline"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -66,14 +66,14 @@ | ||||
|             <ion-row class="ion-align-items-center"> | ||||
|                 <ion-col *ngIf="hasPrevious"> | ||||
|                     <ion-button expand="block" fill="outline" (click)="gotoEntry(offset! -1)"> | ||||
|                         <ion-icon name="fas-chevron-left" slot="start"></ion-icon> | ||||
|                         <ion-icon name="fas-chevron-left" slot="start" aria-hidden="true"></ion-icon> | ||||
|                         {{ 'core.previous' | translate }} | ||||
|                     </ion-button> | ||||
|                 </ion-col> | ||||
|                 <ion-col *ngIf="hasNext"> | ||||
|                     <ion-button expand="block" (click)="gotoEntry(offset! + 1)"> | ||||
|                         {{ 'core.next' | translate }} | ||||
|                         <ion-icon name="fas-chevron-right" slot="end"></ion-icon> | ||||
|                         <ion-icon name="fas-chevron-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|                     </ion-button> | ||||
|                 </ion-col> | ||||
|             </ion-row> | ||||
|  | ||||
| @ -78,7 +78,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy { | ||||
|     entryHtml = ''; | ||||
|     siteId: string; | ||||
|     extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule]; | ||||
|     jsData? : { | ||||
|     jsData?: { | ||||
|         fields: Record<number, AddonModDataField>; | ||||
|         entries: Record<number, AddonModDataEntry>; | ||||
|         database: AddonModDataData; | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -68,14 +68,15 @@ | ||||
|                 </ion-select-option> | ||||
|             </ion-select> | ||||
|         </ion-item> | ||||
|         <ion-item class="ion-text-wrap" (click)="openRespondents()" [detail]="access.canviewreports && completedCount > 0"> | ||||
|         <ion-item class="ion-text-wrap" (click)="openRespondents()" [detail]="access.canviewreports && completedCount > 0" | ||||
|             button> | ||||
|             <ion-label> | ||||
|                 <h2>{{ 'addon.mod_feedback.completed_feedbacks' | translate }}</h2> | ||||
|             </ion-label> | ||||
|             <ion-badge slot="end">{{completedCount}}</ion-badge> | ||||
|         </ion-item> | ||||
|         <ion-item class="ion-text-wrap" *ngIf="!access.isanonymous && access.canviewreports" (click)="openNonRespondents()" | ||||
|             detail="true" tappable="true"> | ||||
|             detail="true" button> | ||||
|             <ion-label> | ||||
|                 <h2>{{ 'addon.mod_feedback.show_nonrespondents' | translate }}</h2> | ||||
|             </ion-label> | ||||
| @ -97,21 +98,21 @@ | ||||
|         <!-- Feedback done in offline but not synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| 
 | ||||
|         <ion-card class="core-info-card" *ngIf="access && access.cancomplete && !access.isopen"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-question-circle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-question-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'addon.mod_feedback.feedback_is_not_open' | translate }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| 
 | ||||
|         <ion-card class="core-success-card" *ngIf="access && access.cancomplete && access.isopen && !access.cansubmit"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-check" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'addon.mod_feedback.this_feedback_is_already_submitted' | translate }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -149,7 +150,7 @@ | ||||
|                     <ion-row class="ion-align-items-center"> | ||||
|                         <ion-col> | ||||
|                             <ion-button expand="block" fill="outline" (click)="gotoAnswerQuestions(true)" class="ion-text-wrap"> | ||||
|                                 <ion-icon name="fas-search" slot="start"></ion-icon> | ||||
|                                 <ion-icon name="fas-search" slot="start" aria-hidden="true"></ion-icon> | ||||
|                                 {{ 'addon.mod_feedback.preview' | translate }} | ||||
|                             </ion-button> | ||||
|                         </ion-col> | ||||
| @ -161,7 +162,7 @@ | ||||
|                                 <ng-container *ngIf="goPage"> | ||||
|                                     {{ 'addon.mod_feedback.continue_the_form' | translate }} | ||||
|                                 </ng-container> | ||||
|                                 <ion-icon name="fas-chevron-right" slot="end"></ion-icon> | ||||
|                                 <ion-icon name="fas-chevron-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|                             </ion-button> | ||||
|                         </ion-col> | ||||
|                     </ion-row> | ||||
| @ -180,7 +181,7 @@ | ||||
|         <ng-container *ngIf="access && (access.canedititems || !access.isempty)"> | ||||
|             <ion-card class="core-info-card" *ngIf="warning"> | ||||
|                 <ion-item> | ||||
|                     <ion-icon name="fas-question-circle" slot="start"></ion-icon> | ||||
|                     <ion-icon name="fas-question-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-label>{{ warning }}</ion-label> | ||||
|                 </ion-item> | ||||
|             </ion-card> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <ng-container *ngIf="attempt">{{ attempt.fullname }}</ng-container> | ||||
| @ -15,7 +15,7 @@ | ||||
|     <core-loading [hideUntil]="loaded"> | ||||
|         <ion-list class="ion-no-margin" *ngIf="attempt || anonAttempt"> | ||||
|             <ion-item *ngIf="attempt" class="ion-text-wrap" core-user-link [userId]="attempt.userid" | ||||
|                 [attr.aria-label]=" 'core.user.viewprofile' | translate" [courseId]="attempt.courseid" [title]="attempt.fullname"> | ||||
|                 [attr.aria-label]=" 'core.user.viewprofile' | translate" [courseId]="attempt.courseid"> | ||||
|                 <core-user-avatar [user]="attempt" slot="start"></core-user-avatar> | ||||
|                 <ion-label> | ||||
|                     <h2>{{attempt.fullname}}</h2> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"> | ||||
| @ -59,7 +59,7 @@ | ||||
|                             </ng-container> | ||||
| 
 | ||||
|                             <ion-textarea *ngIf="item.templateName == 'textarea'" [required]="item.required" | ||||
|                                 name="{{item.typ}}_{{item.id}}" [attr.aria-multiline]="true" [(ngModel)]="item.value"> | ||||
|                                 name="{{item.typ}}_{{item.id}}" [(ngModel)]="item.value"> | ||||
|                             </ion-textarea> | ||||
| 
 | ||||
|                             <ion-select *ngIf="item.templateName == 'multichoice-d'" [required]="item.required" | ||||
| @ -106,7 +106,7 @@ | ||||
|                             </core-recaptcha> | ||||
|                             <div *ngIf="!preview && (!item.captcha || offline)" class="core-warning-card"> | ||||
|                                 <ion-item> | ||||
|                                     <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                                     <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                                     <ion-label>{{ 'addon.mod_feedback.captchaofflinewarning' | translate }}</ion-label> | ||||
|                                 </ion-item> | ||||
|                             </div> | ||||
| @ -117,14 +117,14 @@ | ||||
|                     <ion-row class="ion-align-items-center"> | ||||
|                         <ion-col *ngIf="hasPrevPage"> | ||||
|                             <ion-button expand="block" fill="outline" (click)="gotoPage(true)" class="ion-text-wrap"> | ||||
|                                 <ion-icon name="fas-chevron-left" slot="start"></ion-icon> | ||||
|                                 <ion-icon name="fas-chevron-left" slot="start" aria-hidden="true"></ion-icon> | ||||
|                                 {{ 'addon.mod_feedback.previous_page' | translate }} | ||||
|                             </ion-button> | ||||
|                         </ion-col> | ||||
|                         <ion-col *ngIf="hasNextPage"> | ||||
|                             <ion-button expand="block" (click)="gotoPage(false)" class="ion-text-wrap"> | ||||
|                                 {{ 'addon.mod_feedback.next_page' | translate }} | ||||
|                                 <ion-icon name="fas-chevron-right" slot="end"></ion-icon> | ||||
|                                 <ion-icon name="fas-chevron-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|                             </ion-button> | ||||
|                         </ion-col> | ||||
|                         <ion-col *ngIf="!hasNextPage"> | ||||
| @ -139,7 +139,7 @@ | ||||
| 
 | ||||
|         <ion-card class="core-success-card" *ngIf="completed"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-check" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label> | ||||
|                     <p *ngIf="!completionPageContents && !completedOffline"> | ||||
|                         {{ 'addon.mod_feedback.this_feedback_is_already_submitted' | translate }} | ||||
| @ -161,14 +161,14 @@ | ||||
|                 <ion-row class="ion-align-items-center"> | ||||
|                     <ion-col *ngIf="access!.canviewanalysis"> | ||||
|                         <ion-button expand="block" fill="outline" (click)="showAnalysis()" class="ion-text-wrap"> | ||||
|                             <ion-icon name="fas-chart-bar" slot="start"></ion-icon> | ||||
|                             <ion-icon name="fas-chart-bar" slot="start" aria-hidden="true"></ion-icon> | ||||
|                             {{ 'addon.mod_feedback.completed_feedbacks' | translate }} | ||||
|                         </ion-button> | ||||
|                     </ion-col> | ||||
|                     <ion-col *ngIf="hasNextPage"> | ||||
|                         <ion-button expand="block" (click)="continue()" class="ion-text-wrap"> | ||||
|                             {{ 'core.continue' | translate }} | ||||
|                             <ion-icon name="fas-chevron-right" slot="end"></ion-icon> | ||||
|                             <ion-icon name="fas-chevron-right" slot="end" aria-hidden="true"></ion-icon> | ||||
|                         </ion-button> | ||||
|                     </ion-col> | ||||
|                 </ion-row> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_feedback.responses' |translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_feedback.responses' |translate }}</ion-title> | ||||
|     </ion-toolbar> | ||||
| @ -32,8 +32,8 @@ | ||||
|                             {{ 'addon.mod_feedback.non_anonymous_entries' | translate : {$a: responses.responses.total } }} | ||||
|                         </ion-label> | ||||
|                     </ion-item-divider> | ||||
|                     <ion-item *ngFor="let attempt of responses.responses.attempts" class="ion-text-wrap" tappable detail="true" | ||||
|                         (click)="responses.select(attempt)" [class.core-selected-item]="responses.isSelected(attempt)"> | ||||
|                     <ion-item *ngFor="let attempt of responses.responses.attempts" class="ion-text-wrap" button detail="true" | ||||
|                         (click)="responses.select(attempt)" [attr.aria-current]="responses.getItemAriaCurrent(attempt)"> | ||||
|                         <core-user-avatar [user]="attempt" slot="start"></core-user-avatar> | ||||
|                         <ion-label> | ||||
|                             <h2>{{ attempt.fullname }}</h2> | ||||
| @ -57,8 +57,8 @@ | ||||
|                             {{ 'addon.mod_feedback.anonymous_entries' |translate : {$a: responses.anonResponses.total } }} | ||||
|                         </ion-label> | ||||
|                     </ion-item-divider> | ||||
|                     <ion-item *ngFor="let attempt of responses.anonResponses.attempts" class="ion-text-wrap" tappable detail="true" | ||||
|                         (click)="responses.select(attempt)" [class.core-selected-item]="responses.isSelected(attempt)"> | ||||
|                     <ion-item *ngFor="let attempt of responses.anonResponses.attempts" class="ion-text-wrap" button detail="true" | ||||
|                         (click)="responses.select(attempt)" [attr.aria-current]="responses.getItemAriaCurrent(attempt)"> | ||||
|                         <ion-label> | ||||
|                             <h2>{{ 'addon.mod_feedback.response_nr' |translate }}: {{attempt.number}}</h2> | ||||
|                         </ion-label> | ||||
|  | ||||
| @ -32,7 +32,7 @@ | ||||
|     <ion-list *ngIf="subfolder && (subfolder!.files.length + subfolder!.folders.length > 0)"> | ||||
|         <ng-container *ngFor="let folder of subfolder!.folders"> | ||||
|             <ion-item class="item-file" (click)="openFolder(folder)" detail="true" button> | ||||
|                 <ion-icon name="fas-folder" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.folder' | translate"></ion-icon> | ||||
|                 <ion-label> | ||||
|                     <h2>{{folder.filename}}</h2> | ||||
|                 </ion-label> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,35 +1,35 @@ | ||||
| <ion-item class="ion-text-wrap" (click)="setLockState(true)" *ngIf="discussion.canlock && !discussion.locked"> | ||||
|     <ion-icon name="fa-lock" slot="start"></ion-icon> | ||||
|     <ion-icon name="fa-lock" slot="start" aria-hidden="true"></ion-icon> | ||||
|     <ion-label> | ||||
|         <h2>{{ 'addon.mod_forum.lockdiscussion' | translate }}</h2> | ||||
|     </ion-label> | ||||
| </ion-item> | ||||
| <ion-item class="ion-text-wrap" (click)="setLockState(false)" *ngIf="discussion.canlock && discussion.locked"> | ||||
|     <ion-icon name="fa-unlock" slot="start"></ion-icon> | ||||
|     <ion-icon name="fa-unlock" slot="start" aria-hidden="true"></ion-icon> | ||||
|     <ion-label> | ||||
|         <h2>{{ 'addon.mod_forum.unlockdiscussion' | translate }}</h2> | ||||
|     </ion-label> | ||||
| </ion-item> | ||||
| <ion-item class="ion-text-wrap" (click)="setPinState(true)" *ngIf="canPin && !discussion.pinned"> | ||||
|     <ion-icon name="fa-map-pin" slot="start"></ion-icon> | ||||
|     <ion-icon name="fa-map-pin" slot="start" aria-hidden="true"></ion-icon> | ||||
|     <ion-label> | ||||
|         <h2>{{ 'addon.mod_forum.pindiscussion' | translate }}</h2> | ||||
|     </ion-label> | ||||
| </ion-item> | ||||
| <ion-item class="ion-text-wrap" (click)="setPinState(false)" *ngIf="canPin && discussion.pinned"> | ||||
|     <ion-icon name="fa-map-pin" slot="start" class="icon-slash"></ion-icon> | ||||
|     <ion-icon name="fa-map-pin" slot="start" class="icon-slash" aria-hidden="true"></ion-icon> | ||||
|     <ion-label> | ||||
|         <h2>{{ 'addon.mod_forum.unpindiscussion' | translate }}</h2> | ||||
|     </ion-label> | ||||
| </ion-item> | ||||
| <ion-item class="ion-text-wrap" (click)="toggleFavouriteState(true)" *ngIf="discussion.canfavourite && !discussion.starred"> | ||||
|     <ion-icon name="fa-star" slot="start"></ion-icon> | ||||
|     <ion-icon name="fa-star" slot="start" aria-hidden="true"></ion-icon> | ||||
|     <ion-label> | ||||
|         <h2>{{ 'addon.mod_forum.addtofavourites' | translate }}</h2> | ||||
|     </ion-label> | ||||
| </ion-item> | ||||
| <ion-item class="ion-text-wrap" (click)="toggleFavouriteState(false)" *ngIf="discussion.canfavourite && discussion.starred"> | ||||
|     <ion-icon name="fa-star" slot="start" class="icon-slash"></ion-icon> | ||||
|     <ion-icon name="fa-star" slot="start" class="icon-slash" aria-hidden="true"></ion-icon> | ||||
|     <ion-label> | ||||
|         <h2>{{ 'addon.mod_forum.removefromfavourites' | translate }}</h2> | ||||
|     </ion-label> | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <ion-title>{{ 'addon.mod_forum.yourreply' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon name="close" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-times" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -25,9 +25,10 @@ | ||||
|                 (contentChanged)="onMessageChange($event)"> | ||||
|             </core-rich-text-editor> | ||||
|         </ion-item> | ||||
|         <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()"> | ||||
|             <ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start"></ion-icon> | ||||
|             <ion-icon *ngIf="advanced" name="fa-caret-down" slot="start"></ion-icon> | ||||
|         <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()" role="heading button" | ||||
|             [attr.aria-expanded]="advanced" [attr.aria-label]="(advanced ? 'core.hideadvanced' : 'core.showadvanced') | translate"> | ||||
|             <ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-icon *ngIf="advanced" name="fa-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'addon.mod_forum.advanced' | translate }}</ion-label> | ||||
|         </ion-item-divider> | ||||
|         <ng-container *ngIf="advanced"> | ||||
|  | ||||
| @ -50,7 +50,7 @@ | ||||
|         <!-- Forum discussions found to be synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="hasOffline || hasOfflineRatings"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -58,7 +58,7 @@ | ||||
|         <!-- Cut-off date or due date message --> | ||||
|         <ion-card class="core-info-card" *ngIf="availabilityMessage"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-info-circle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ availabilityMessage }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -71,7 +71,7 @@ | ||||
|                 <ion-button *ngIf="sortingAvailable" id="addon-mod-forum-sort-order-button" | ||||
|                     class="core-button-select button-no-uppercase" | ||||
|                     aria-haspopup="true" aria-controls="addon-mod-forum-sort-order-selector" | ||||
|                     [attr.aria-label]="('core.sort' | translate)" [attr.aria-expanded]="sortOrderSelectorExpanded" | ||||
|                     [attr.aria-label]="('core.sort' | translate)" | ||||
|                     (click)="showSortOrderSelector()"> | ||||
|                     <span class="core-button-select-text">{{ selectedSortOrder.label | translate }}</span> | ||||
|                     <div class="select-icon" slot="end"><div class="select-icon-inner"></div></div> | ||||
| @ -80,13 +80,15 @@ | ||||
| 
 | ||||
|             <ion-item *ngFor="let discussion of discussions.items" | ||||
|                 class="addon-mod-forum-discussion" detail="true" | ||||
|                 [lines]="discussion.groupname && 'none'" [class.core-selected-item]="discussions.isSelected(discussion)" | ||||
|                 [lines]="discussion.groupname && 'none'" [attr.aria-current]="discussions.getItemAriaCurrent(discussion)" | ||||
|                 (click)="discussions.select(discussion)"> | ||||
|                 <ion-label> | ||||
|                     <div class="addon-mod-forum-discussion-title"> | ||||
|                         <h2 class="ion-text-wrap"> | ||||
|                             <ion-icon name="fa-map-pin" *ngIf="discussion.pinned"></ion-icon> | ||||
|                             <ion-icon name="fa-star" class="addon-forum-star" *ngIf="!discussion.pinned && discussion.starred"></ion-icon> | ||||
|                             <ion-icon name="fa-map-pin" *ngIf="discussion.pinned" | ||||
|                                 [attr.aria-label]="'addon.mod_forum.discussionpinned' | translate"></ion-icon> | ||||
|                             <ion-icon name="fa-star" class="addon-forum-star" *ngIf="!discussion.pinned && discussion.starred" | ||||
|                                 [attr.aria-label]="'addon.mod_forum.favourites' | translate"></ion-icon> | ||||
|                             <core-format-text | ||||
|                                 [text]="discussion.subject" | ||||
|                                 contextLevel="module" [contextInstanceId]="module && module.id" [courseId]="courseId"> | ||||
| @ -96,7 +98,7 @@ | ||||
|                             fill="clear" color="dark" | ||||
|                             [attr.aria-label]="('core.displayoptions' | translate)" | ||||
|                             (click)="showOptionsMenu($event, discussion)"> | ||||
|                             <ion-icon name="ellipsis-vertical" slot="icon-only"> | ||||
|                             <ion-icon name="ellipsis-vertical" slot="icon-only" aria-hidden="true"> | ||||
|                             </ion-icon> | ||||
|                         </ion-button> | ||||
|                     </div> | ||||
| @ -105,12 +107,15 @@ | ||||
|                         </core-user-avatar> | ||||
|                         <div class="addon-mod-forum-discussion-author"> | ||||
|                             <h3 *ngIf="discussion.userfullname">{{discussion.userfullname}}</h3> | ||||
|                             <p *ngIf="discussion.groupname"><ion-icon name="people"></ion-icon> {{ discussion.groupname }}</p> | ||||
|                             <p *ngIf="discussion.groupname"> | ||||
|                                 <ion-icon name="fas-users" [attr.aria-label]="'addon.mod_forum.group' | translate"> | ||||
|                                 </ion-icon> {{ discussion.groupname }} | ||||
|                             </p> | ||||
|                             <p *ngIf="discussions.isOnlineDiscussion(discussion)"> | ||||
|                                 {{discussion.created * 1000 | coreFormatDate: "strftimerecentfull"}} | ||||
|                             </p> | ||||
|                             <p *ngIf="discussions.isOfflineDiscussion(discussion)"> | ||||
|                                 <ion-icon name="fas-clock"></ion-icon> | ||||
|                                 <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> | ||||
|                                 {{ 'core.notsent' | translate }} | ||||
|                             </p> | ||||
|                         </div> | ||||
| @ -119,7 +124,7 @@ | ||||
|                         class="ion-text-center addon-mod-forum-discussion-more-info"> | ||||
|                         <ion-col class="ion-text-start"> | ||||
|                             <ion-note> | ||||
|                                 <ion-icon name="fas-clock"></ion-icon> {{ 'addon.mod_forum.lastpost' | translate }} | ||||
|                                 <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> {{ 'addon.mod_forum.lastpost' | translate }} | ||||
|                                 <ng-container *ngIf="discussion.timemodified > discussion.created"> | ||||
|                                     {{ discussion.timemodified | coreTimeAgo }} | ||||
|                                 </ng-container> | ||||
| @ -130,7 +135,7 @@ | ||||
|                         </ion-col> | ||||
|                         <ion-col class="ion-text-end"> | ||||
|                             <ion-note> | ||||
|                                 <ion-icon name="fas-comments"></ion-icon> | ||||
|                                 <ion-icon name="fas-comments" aria-hidden="true"></ion-icon> | ||||
|                                 {{ 'addon.mod_forum.numreplies' | translate:{numreplies: discussion.numreplies} }} | ||||
|                                 <ion-badge *ngIf="discussion.numunread" class="ion-text-center" | ||||
|                                     [attr.aria-label]="'addon.mod_forum.unreadpostsnumber' | translate:{ '$a' : discussion.numunread}"> | ||||
| @ -151,7 +156,7 @@ | ||||
| 
 | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="forum && canAddDiscussion"> | ||||
|         <ion-fab-button (click)="openNewDiscussion()" [attr.aria-label]="addDiscussionText"> | ||||
|             <ion-icon name="fas-plus"></ion-icon> | ||||
|             <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
| </core-split-view> | ||||
|  | ||||
| @ -79,7 +79,6 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|     sortingAvailable!: boolean; | ||||
|     sortOrders: AddonModForumSortOrder[] = []; | ||||
|     selectedSortOrder: AddonModForumSortOrder | null = null; | ||||
|     sortOrderSelectorExpanded = false; | ||||
|     canPin = false; | ||||
| 
 | ||||
|     protected syncEventName = AddonModForumSyncProvider.AUTO_SYNCED; | ||||
| @ -635,14 +634,10 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         modal.present(); | ||||
| 
 | ||||
|         this.sortOrderSelectorExpanded = true; | ||||
|         await modal.present(); | ||||
| 
 | ||||
|         const result = await modal.onDidDismiss<AddonModForumSortOrder>(); | ||||
| 
 | ||||
|         this.sortOrderSelectorExpanded = false; | ||||
| 
 | ||||
|         if (result.data && result.data.value != this.selectedSortOrder?.value) { | ||||
|             this.selectedSortOrder = result.data; | ||||
|             this.page = 0; | ||||
| @ -673,7 +668,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|             event, | ||||
|         }); | ||||
| 
 | ||||
|         popover.present(); | ||||
|         await popover.present(); | ||||
| 
 | ||||
|         const result = await popover.onDidDismiss<{ action?: string; value: boolean }>(); | ||||
| 
 | ||||
|  | ||||
| @ -1,12 +1,12 @@ | ||||
| <core-loading [hideUntil]="loaded" class="core-loading-center"> | ||||
|     <ion-item class="ion-text-wrap" (click)="editPost()" *ngIf="offlinePost || (canEdit && isOnline)"> | ||||
|         <ion-icon name="create" slot="start"></ion-icon> | ||||
|         <ion-icon name="fas-pen" slot="start" aria-hidden="true"></ion-icon> | ||||
|         <ion-label> | ||||
|             <h2>{{ 'addon.mod_forum.edit' | translate }}</h2> | ||||
|         </ion-label> | ||||
|     </ion-item> | ||||
|     <ion-item class="ion-text-wrap" (click)="deletePost()" *ngIf="offlinePost || (canDelete && isOnline)"> | ||||
|         <ion-icon name="fas-trash" slot="start"></ion-icon> | ||||
|         <ion-icon name="fas-trash" slot="start" aria-hidden="true"></ion-icon> | ||||
|         <ion-label> | ||||
|             <h2 *ngIf="!offlinePost">{{ 'addon.mod_forum.delete' | translate }}</h2> | ||||
|             <h2 *ngIf="offlinePost">{{ 'core.discard' | translate }}</h2> | ||||
| @ -18,7 +18,7 @@ | ||||
|         </ion-label> | ||||
|     </ion-item> | ||||
|     <ion-item class="ion-text-wrap" [href]="url" *ngIf="url" core-link capture="false"> | ||||
|         <ion-icon name="open" slot="start"></ion-icon> | ||||
|         <ion-icon name="fas-external-link-alt" slot="start" aria-hidden="true"></ion-icon> | ||||
|         <ion-label> | ||||
|             <h2>{{ 'core.openinbrowser' | translate }}</h2> | ||||
|         </ion-label> | ||||
|  | ||||
| @ -4,9 +4,11 @@ | ||||
|             <ion-label> | ||||
|                 <div class="addon-mod-forum-post-title" *ngIf="displaySubject"> | ||||
|                     <h2 class="ion-text-wrap"> | ||||
|                         <ion-icon name="fa-map-pin" *ngIf="discussion && !post.parentid && discussion.pinned"> | ||||
|                         <ion-icon name="fa-map-pin" *ngIf="discussion && !post.parentid && discussion.pinned" | ||||
|                             [attr.aria-label]="'addon.mod_forum.discussionpinned' | translate"> | ||||
|                         </ion-icon> | ||||
|                         <ion-icon name="fa-star" class="addon-forum-star" | ||||
|                             [attr.aria-label]="'addon.mod_forum.favourites' | translate" | ||||
|                             *ngIf="discussion && !post.parentid && !discussion.pinned && discussion.starred"> | ||||
|                         </ion-icon> | ||||
|                         <core-format-text | ||||
| @ -16,13 +18,12 @@ | ||||
|                     </h2> | ||||
|                     <ion-note *ngIf="trackPosts && post.unread" | ||||
|                         class="ion-float-end ion-padding-left ion-text-end" [attr.aria-label]="'addon.mod_forum.unread' | translate"> | ||||
|                         <ion-icon name="fa-circle" color="primary"> | ||||
|                         </ion-icon> | ||||
|                         <ion-icon name="fa-circle" color="primary" aria-hidden="true"></ion-icon> | ||||
|                     </ion-note> | ||||
|                     <ion-button *ngIf="optionsMenuEnabled" | ||||
|                         fill="clear" color="dark" [attr.aria-label]="('core.displayoptions' | translate)" | ||||
|                         (click)="showOptionsMenu($event)"> | ||||
|                         <ion-icon name="ellipsis-vertical" slot="icon-only"> | ||||
|                         <ion-icon name="ellipsis-vertical" slot="icon-only" aria-hidden="true"> | ||||
|                         </ion-icon> | ||||
|                     </ion-button> | ||||
|                 </div> | ||||
| @ -33,23 +34,24 @@ | ||||
|                         <h3 *ngIf="post.author && post.author.fullname">{{post.author.fullname}}</h3> | ||||
|                         <p *ngIf="post.author && post.author.groups"> | ||||
|                             <ng-container *ngFor="let group of post.author.groups"> | ||||
|                                 <ion-icon name="people"></ion-icon> {{ group.name }} | ||||
|                                 <ion-icon name="fas-users" [attr.aria-label]="'addon.mod_forum.group' | translate"> | ||||
|                                 </ion-icon> {{ group.name }} | ||||
|                             </ng-container> | ||||
|                         </p> | ||||
|                         <p *ngIf="post.timecreated">{{post.timecreated * 1000 | coreFormatDate: "strftimerecentfull"}}</p> | ||||
|                         <p *ngIf="!post.timecreated"><ion-icon name="fas-clock"></ion-icon> {{ 'core.notsent' | translate }}</p> | ||||
|                         <p *ngIf="!post.timecreated"> | ||||
|                             <ion-icon name="fas-clock" aria-hidden="true"></ion-icon> {{ 'core.notsent' | translate }} | ||||
|                         </p> | ||||
|                     </div> | ||||
|                     <ng-container *ngIf="!displaySubject"> | ||||
|                         <ion-note *ngIf="trackPosts && post.unread" | ||||
|                             class="ion-float-end ion-padding-left ion-text-end" [attr.aria-label]="'addon.mod_forum.unread' | translate"> | ||||
|                             <ion-icon name="fa-circle" color="primary"> | ||||
|                             </ion-icon> | ||||
|                             <ion-icon name="fa-circle" color="primary" aria-hidden="true"></ion-icon> | ||||
|                         </ion-note> | ||||
|                         <ion-button *ngIf="optionsMenuEnabled" | ||||
|                             fill="clear" color="dark" [attr.aria-label]="('core.displayoptions' | translate)" | ||||
|                             (click)="showOptionsMenu($event)"> | ||||
|                             <ion-icon name="ellipsis-vertical" slot="icon-only"> | ||||
|                             </ion-icon> | ||||
|                             <ion-icon name="ellipsis-vertical" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|                         </ion-button> | ||||
|                     </ng-container> | ||||
|                 </div> | ||||
| @ -92,7 +94,7 @@ | ||||
|                     [attr.aria-controls]="'addon-forum-reply-edit-form-' + uniqueId" | ||||
|                     [attr.aria-expanded]="replyData.replyingTo === post.id" | ||||
|                     (click)="showReplyForm()"> | ||||
|                     <ion-icon name="fa-reply" slot="start"> | ||||
|                     <ion-icon name="fa-reply" slot="start" aria-hidden="true"> | ||||
|                     </ion-icon> {{ 'addon.mod_forum.reply' | translate }} | ||||
|                 </ion-button> | ||||
|             </ion-label> | ||||
| @ -120,12 +122,11 @@ | ||||
|             <ion-checkbox slot="end" [(ngModel)]="replyData.isprivatereply" name="isprivatereply"></ion-checkbox> | ||||
|         </ion-item> | ||||
|         <ng-container *ngIf="forum.id && forum.maxattachments > 0"> | ||||
|             <ion-item-divider class="core-expandable ion-text-wrap" (click)="toggleAdvanced()"> | ||||
|             <ion-item-divider class="core-expandable ion-text-wrap" (click)="toggleAdvanced()" [attr.aria-expanded]="advanced" | ||||
|                 [attr.aria-label]="(advanced ? 'core.hideadvanced' : 'core.showadvanced') |translate" role="button"> | ||||
|                 <ion-label> | ||||
|                     <ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start"> | ||||
|                     </ion-icon> | ||||
|                     <ion-icon *ngIf="advanced" name="fa-caret-down" slot="start"> | ||||
|                     </ion-icon> | ||||
|                     <ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     <ion-icon *ngIf="advanced" name="fa-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|                     {{ 'addon.mod_forum.advanced' | translate }} | ||||
|                 </ion-label> | ||||
|             </ion-item-divider> | ||||
|  | ||||
| @ -228,7 +228,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges | ||||
|             event, | ||||
|         }); | ||||
| 
 | ||||
|         popover.present(); | ||||
|         await popover.present(); | ||||
| 
 | ||||
|         const result = await popover.onDidDismiss<{ action?: string }>(); | ||||
| 
 | ||||
| @ -265,7 +265,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges | ||||
|             backdropDismiss: false, | ||||
|         }); | ||||
| 
 | ||||
|         modal.present(); | ||||
|         await modal.present(); | ||||
| 
 | ||||
|         const result = await modal.onDidDismiss<AddonModForumReply>(); | ||||
|         const data = result.data; | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
|         <ion-title>{{ 'core.sort' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
|             <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate"> | ||||
|                 <ion-icon name="close" slot="icon-only"></ion-icon> | ||||
|                 <ion-icon name="fas-times" slot="icon-only" aria-hidden="true"></ion-icon> | ||||
|             </ion-button> | ||||
|         </ion-buttons> | ||||
|     </ion-toolbar> | ||||
| @ -11,9 +11,9 @@ | ||||
| <ion-content> | ||||
|     <ion-list id="addon-mod-forum-sort-selector" role="menu" aria-labelledby="addon-mod-forum-sort-order-button"> | ||||
|         <ng-container *ngFor="let sortOrder of sortOrders"> | ||||
|             <ion-item class="ion-text-wrap" detail="false" role="menuitem" | ||||
|                 [class.core-selected-item]="selected == sortOrder.value" [attr.aria-label]="sortOrder.label | translate" | ||||
|                 (click)="selectSortOrder(sortOrder)"> | ||||
|             <ion-item class="ion-text-wrap" detail="false" role="combobox" | ||||
|                 [attr.aria-current]="selected == sortOrder.value ? 'page' :  'false'" [attr.aria-label]="sortOrder.label | translate" | ||||
|                 (click)="selectSortOrder(sortOrder)" button aria-haspopup="dialog"> | ||||
|                 <ion-label> | ||||
|                     <h2>{{ sortOrder.label | translate }}</h2> | ||||
|                 </ion-label> | ||||
|  | ||||
| @ -29,6 +29,7 @@ | ||||
|     "errorgetforum": "Error getting forum data.", | ||||
|     "errorgetgroups": "Error getting group settings.", | ||||
|     "errorposttoallgroups": "Could not create new discussion in all groups.", | ||||
|     "favourites": "Starred", | ||||
|     "favouriteupdated": "Your star option has been updated.", | ||||
|     "forumnodiscussionsyet": "There are no discussions yet in this forum.", | ||||
|     "group": "Group", | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="startingPost"> | ||||
|             <core-format-text contextLevel="module" [text]="startingPost.subject" [contextInstanceId]="cmId" [courseId]="courseId"> | ||||
| @ -69,7 +69,7 @@ | ||||
|         <!-- Discussion replies found to be synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="postHasOffline || hasOfflineRatings"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate:{$a: discussionStr} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -77,14 +77,14 @@ | ||||
|         <!-- Cut-off date or due date message --> | ||||
|         <ion-card class="core-info-card" *ngIf="availabilityMessage"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="information-circle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ availabilityMessage }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| 
 | ||||
|         <ion-card class="core-info-card" *ngIf="discussion && discussion.locked"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fa-lock" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fa-lock" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'addon.mod_forum.discussionlocked' | translate }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title>{{ 'addon.mod_forum.addanewdiscussion' | translate }}</ion-title> | ||||
|         <ion-buttons slot="end"> | ||||
| @ -31,11 +31,10 @@ | ||||
|                     (contentChanged)="onMessageChange($event)"> | ||||
|                 </core-rich-text-editor> | ||||
|             </ion-item> | ||||
|             <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()"> | ||||
|                 <ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start"> | ||||
|                 </ion-icon> | ||||
|                 <ion-icon *ngIf="advanced" name="fa-caret-down" slot="start"> | ||||
|                 </ion-icon> | ||||
|             <ion-item-divider class="ion-text-wrap core-expandable" (click)="toggleAdvanced()" [attr.aria-expanded]="advanced" | ||||
|                 [attr.aria-label]="(advanced ? 'core.hideadvanced' : 'core.showadvanced') |translate" role="heading button"> | ||||
|                 <ion-icon *ngIf="!advanced" name="fa-caret-right" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-icon *ngIf="advanced" name="fa-caret-down" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'addon.mod_forum.advanced' | translate }}</ion-label> | ||||
|             </ion-item-divider> | ||||
|             <ng-container *ngIf="advanced"> | ||||
|  | ||||
| @ -2,11 +2,11 @@ | ||||
| <core-navbar-buttons slot="end"> | ||||
|     <ion-button *ngIf="glossary && glossary.browsemodes && glossary.browsemodes.length > 1" (click)="openModePicker($event)" | ||||
|         [attr.aria-label]="'addon.mod_glossary.browsemode' | translate"> | ||||
|         <ion-icon name="fas-sort"></ion-icon> | ||||
|         <ion-icon name="fas-sort" aria-hidden="true"></ion-icon> | ||||
|     </ion-button> | ||||
| 
 | ||||
|     <ion-button *ngIf="glossary" (click)="toggleSearch()" [attr.aria-label]="'addon.mod_glossary.bysearch' | translate"> | ||||
|         <ion-icon name="fas-search"></ion-icon> | ||||
|         <ion-icon name="fas-search" aria-hidden="true"></ion-icon> | ||||
|     </ion-button> | ||||
| 
 | ||||
|     <core-context-menu> | ||||
| @ -57,7 +57,7 @@ | ||||
|         <!-- Has offline data to be synchronized --> | ||||
|         <ion-card class="core-warning-card" *ngIf="hasOffline || hasOfflineRatings"> | ||||
|             <ion-item> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|                 <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|                 <ion-label>{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</ion-label> | ||||
|             </ion-item> | ||||
|         </ion-card> | ||||
| @ -66,8 +66,8 @@ | ||||
|             <ion-item-divider> | ||||
|                 <ion-label>{{ 'addon.mod_glossary.entriestobesynced' | translate }}</ion-label> | ||||
|             </ion-item-divider> | ||||
|             <ion-item *ngFor="let entry of entries.offlineEntries" (click)="entries.select(entry)" detail="false" | ||||
|                 [class.core-selected-item]="entries.isSelected(entry)"> | ||||
|             <ion-item *ngFor="let entry of entries.offlineEntries" (click)="entries.select(entry)" detail="false" button | ||||
|                 [attr.aria-current]="entries.getItemAriaCurrent(entry)"> | ||||
|                 <ion-label> | ||||
|                     <core-format-text [text]="entry.concept" contextLevel="module" [contextInstanceId]="glossary!.coursemodule" | ||||
|                         [courseId]="courseId"> | ||||
| @ -82,7 +82,8 @@ | ||||
|                     {{ getDivider!(entry) }} | ||||
|                 </ion-item-divider> | ||||
| 
 | ||||
|                 <ion-item (click)="entries.select(entry)" [class.core-selected-item]="entries.isSelected(entry)" detail="false"> | ||||
|                 <ion-item button (click)="entries.select(entry)" [attr.aria-current]="entries.getItemAriaCurrent(entry)" | ||||
|                     detail="false"> | ||||
|                     <ion-label> | ||||
|                         <core-format-text [text]="entry.concept" contextLevel="module" [contextInstanceId]="glossary!.coursemodule" | ||||
|                             [courseId]="courseId"> | ||||
| @ -101,7 +102,7 @@ | ||||
| 
 | ||||
|     <ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end" *ngIf="canAdd"> | ||||
|         <ion-fab-button (click)="openNewEntry()" [attr.aria-label]="'addon.mod_glossary.addentry' | translate"> | ||||
|             <ion-icon name="fas-plus"></ion-icon> | ||||
|             <ion-icon name="fas-plus" aria-hidden="true"></ion-icon> | ||||
|         </ion-fab-button> | ||||
|     </ion-fab> | ||||
| </core-split-view> | ||||
|  | ||||
| @ -414,7 +414,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity | ||||
|             event, | ||||
|         }); | ||||
| 
 | ||||
|         popover.present(); | ||||
|         await popover.present(); | ||||
| 
 | ||||
|         const result = await popover.onDidDismiss<AddonModGlossaryFetchMode>(); | ||||
| 
 | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="glossary"> | ||||
|             <core-format-text [text]="glossary.name" contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title *ngIf="entry"> | ||||
|             <core-format-text [text]="entry.concept" contextLevel="module" [contextInstanceId]="componentId" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module?.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -39,7 +39,7 @@ | ||||
|     <!-- Offline data stored. --> | ||||
|     <ion-card class="core-warning-card" *ngIf="hasOffline"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label>{{ 'core.hasdatatosync' | translate: {$a: moduleName} }}</ion-label> | ||||
|         </ion-item> | ||||
|     </ion-card> | ||||
| @ -47,7 +47,7 @@ | ||||
|     <!-- Offline disabled. --> | ||||
|     <ion-card class="core-warning-card" *ngIf="!siteCanDownload && playing"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label> | ||||
|                 {{ 'core.h5p.offlinedisabled' | translate }} {{ 'addon.mod_h5pactivity.offlinedisabledwarning' | translate }} | ||||
|             </ion-label> | ||||
| @ -57,7 +57,7 @@ | ||||
|     <!-- Preview mode. --> | ||||
|     <ion-card class="core-warning-card" *ngIf="accessInfo && !trackComponent"> | ||||
|         <ion-item> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start"></ion-icon> | ||||
|             <ion-icon name="fas-exclamation-triangle" slot="start" aria-hidden="true"></ion-icon> | ||||
|             <ion-label> | ||||
|                 {{ 'addon.mod_h5pactivity.previewmode' | translate }} | ||||
|             </ion-label> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text *ngIf="h5pActivity" [text]="h5pActivity.name" contextLevel="module" | ||||
| @ -18,7 +18,7 @@ | ||||
|         <ng-container *ngIf="attempt"> | ||||
|             <!-- Attempt number and user that did the attempt. --> | ||||
|             <ion-item class="ion-text-wrap" *ngIf="user" core-user-link [userId]="user.id" [courseId]="courseId" | ||||
|                 [title]="user.fullname"> | ||||
|                 [attr.aria-label]="user.fullname"> | ||||
|                 <core-user-avatar [user]="user" slot="start" [courseId]="courseId"></core-user-avatar> | ||||
|                 <ion-label> | ||||
|                     <h2>{{ 'addon.mod_h5pactivity.attempt' | translate }} #{{attempt.attempt}}: {{user.fullname}}</h2> | ||||
| @ -63,11 +63,11 @@ | ||||
|                         <ion-label> | ||||
|                             <h2>{{ 'addon.mod_h5pactivity.outcome' | translate }}</h2> | ||||
|                             <p *ngIf="attempt.success !== null && attempt.success" > | ||||
|                                 <ion-icon name="fa-check-circle"></ion-icon> | ||||
|                                 <ion-icon name="fa-check-circle" aria-hidden="true"></ion-icon> | ||||
|                                 {{ 'addon.mod_h5pactivity.attempt_success_pass' | translate }} | ||||
|                             </p> | ||||
|                             <p *ngIf="attempt.success !== null && !attempt.success" > | ||||
|                                 <ion-icon name="far-circle"></ion-icon> | ||||
|                                 <ion-icon name="far-circle" aria-hidden="true"></ion-icon> | ||||
|                                 {{ 'addon.mod_h5pactivity.attempt_success_fail' | translate }} | ||||
|                             </p> | ||||
|                             <p *ngIf="attempt.success === null" > | ||||
| @ -152,7 +152,7 @@ | ||||
| 
 | ||||
|                     <!-- Result doesn't support tracking. --> | ||||
|                     <ion-item class="ion-text-wrap core-warning-item" *ngIf="!result.track" lines="none"> | ||||
|                         <ion-icon slot="start" name="fas-exclamation-triangle" color="warning"></ion-icon> | ||||
|                         <ion-icon slot="start" name="fas-exclamation-triangle" color="warning" aria-hidden="true"></ion-icon> | ||||
|                         <ion-label> | ||||
|                             {{ 'addon.mod_h5pactivity.no_compatible_track' | translate:{$a: result.interactiontype} }} | ||||
|                         </ion-label> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId"> | ||||
|  | ||||
| @ -1,7 +1,7 @@ | ||||
| <ion-header> | ||||
|     <ion-toolbar> | ||||
|         <ion-buttons slot="start"> | ||||
|             <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button> | ||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||
|         </ion-buttons> | ||||
|         <ion-title> | ||||
|             <core-format-text *ngIf="h5pActivity" [text]="h5pActivity.name" contextLevel="module" | ||||
| @ -17,7 +17,7 @@ | ||||
|     <core-loading [hideUntil]="loaded"> | ||||
|         <!-- User viewed. --> | ||||
|         <ion-item class="ion-text-wrap" *ngIf="user && !isCurrentUser" core-user-link [userId]="user.id" [courseId]="courseId" | ||||
|             [title]="user.fullname"> | ||||
|             [attr.aria-label]="user.fullname"> | ||||
|             <core-user-avatar [user]="user" slot="start" [courseId]="courseId"></core-user-avatar> | ||||
|             <ion-label> | ||||
|                 <h2>{{ user.fullname }}</h2> | ||||
|  | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user