forked from CIT/Vmeda.Online
		
	MOBILE-3752 lint: Remove duplicated spaces
This commit is contained in:
		
							parent
							
								
									5d20d4faa7
								
							
						
					
					
						commit
						2a1e8a44e8
					
				@ -12,11 +12,11 @@
 | 
				
			|||||||
            <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
					            <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
				
			||||||
        </ion-refresher>
 | 
					        </ion-refresher>
 | 
				
			||||||
        <core-loading [hideUntil]="badges.loaded">
 | 
					        <core-loading [hideUntil]="badges.loaded">
 | 
				
			||||||
            <core-empty-box *ngIf="badges.empty"  icon="fas-trophy"
 | 
					            <core-empty-box *ngIf="badges.empty" icon="fas-trophy"
 | 
				
			||||||
                [message]="'addon.badges.nobadges' | translate">
 | 
					                [message]="'addon.badges.nobadges' | translate">
 | 
				
			||||||
            </core-empty-box>
 | 
					            </core-empty-box>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <ion-list *ngIf="!badges.empty"  class="ion-no-margin">
 | 
					            <ion-list *ngIf="!badges.empty" class="ion-no-margin">
 | 
				
			||||||
                <ion-item button class="ion-text-wrap" *ngFor="let badge of badges.items" [attr.aria-label]="badge.name"
 | 
					                <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)">
 | 
					                    (click)="badges.select(badge)" [attr.aria-current]="badges.getItemAriaCurrent(badge)">
 | 
				
			||||||
                    <ion-avatar slot="start">
 | 
					                    <ion-avatar slot="start">
 | 
				
			||||||
 | 
				
			|||||||
@ -327,8 +327,8 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Helper function to help with filter values.
 | 
					     * Helper function to help with filter values.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  showCondition     If true, filter will be shown.
 | 
					     * @param showCondition     If true, filter will be shown.
 | 
				
			||||||
     * @param  disabledCondition If true, and showCondition is also met, it will be shown as disabled.
 | 
					     * @param disabledCondition If true, and showCondition is also met, it will be shown as disabled.
 | 
				
			||||||
     * @return                   show / disabled / hidden value.
 | 
					     * @return                   show / disabled / hidden value.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected getShowFilterValue(showCondition: boolean, disabledCondition: boolean): string {
 | 
					    protected getShowFilterValue(showCondition: boolean, disabledCondition: boolean): string {
 | 
				
			||||||
@ -507,7 +507,7 @@ export class AddonBlockMyOverviewComponent extends CoreBlockBaseComponent implem
 | 
				
			|||||||
        courses.forEach((course) => {
 | 
					        courses.forEach((course) => {
 | 
				
			||||||
            if (course.hidden) {
 | 
					            if (course.hidden) {
 | 
				
			||||||
                this.courses.hidden.push(course);
 | 
					                this.courses.hidden.push(course);
 | 
				
			||||||
            } else  {
 | 
					            } else {
 | 
				
			||||||
                this.courses.all.push(course);
 | 
					                this.courses.all.push(course);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                if ((course.enddate && course.enddate < today) || course.completed) {
 | 
					                if ((course.enddate && course.enddate < today) || course.completed) {
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@ import { CoreBlockBaseHandler } from '@features/block/classes/base-block-handler
 | 
				
			|||||||
import { makeSingleton } from '@singletons';
 | 
					import { makeSingleton } from '@singletons';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Block  handler.
 | 
					 * Block handler.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
@Injectable({ providedIn: 'root' })
 | 
					@Injectable({ providedIn: 'root' })
 | 
				
			||||||
export class AddonBlockMyOverviewHandlerService extends CoreBlockBaseHandler {
 | 
					export class AddonBlockMyOverviewHandlerService extends CoreBlockBaseHandler {
 | 
				
			||||||
 | 
				
			|||||||
@ -3,8 +3,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    .addon-calendar-navigation {
 | 
					    .addon-calendar-navigation {
 | 
				
			||||||
        padding-top: 5px;
 | 
					        padding-top: 5px;
 | 
				
			||||||
        padding-left:  10px;
 | 
					        padding-left: 10px;
 | 
				
			||||||
        padding-right:  10px;
 | 
					        padding-right: 10px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .addon-calendar-months {
 | 
					    .addon-calendar-months {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
    <core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="fas-calendar" [message]="'addon.calendar.noevents' | translate">
 | 
					    <core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="fas-calendar" [message]="'addon.calendar.noevents' | translate">
 | 
				
			||||||
    </core-empty-box>
 | 
					    </core-empty-box>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <ion-list *ngIf="filteredEvents && filteredEvents.length"  class="ion-no-margin">
 | 
					    <ion-list *ngIf="filteredEvents && filteredEvents.length" class="ion-no-margin">
 | 
				
			||||||
        <ng-container *ngFor="let event of filteredEvents">
 | 
					        <ng-container *ngFor="let event of filteredEvents">
 | 
				
			||||||
            <ion-item class="ion-text-wrap addon-calendar-event" [attr.aria-label]="event.name" (click)="eventClicked(event)" button
 | 
					            <ion-item class="ion-text-wrap addon-calendar-event" [attr.aria-label]="event.name" (click)="eventClicked(event)" button
 | 
				
			||||||
                [ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
 | 
					                [ngClass]="['addon-calendar-eventtype-'+event.eventtype]">
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
                <core-context-menu-item *ngIf="!isCurrentDay" [priority]="900" [content]="'addon.calendar.today' | translate"
 | 
					                <core-context-menu-item *ngIf="!isCurrentDay" [priority]="900" [content]="'addon.calendar.today' | translate"
 | 
				
			||||||
                    iconAction="fas-calendar-day" (action)="goToCurrentDay()">
 | 
					                    iconAction="fas-calendar-day" (action)="goToCurrentDay()">
 | 
				
			||||||
                </core-context-menu-item>
 | 
					                </core-context-menu-item>
 | 
				
			||||||
                <core-context-menu-item [hidden]="!loaded || !hasOffline || !isOnline"  [priority]="400"
 | 
					                <core-context-menu-item [hidden]="!loaded || !hasOffline || !isOnline" [priority]="400"
 | 
				
			||||||
                    [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(undefined, $event)"
 | 
					                    [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(undefined, $event)"
 | 
				
			||||||
                    [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					                    [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
                </core-context-menu-item>
 | 
					                </core-context-menu-item>
 | 
				
			||||||
@ -57,7 +57,7 @@
 | 
				
			|||||||
            [message]="'addon.calendar.noevents' | translate">
 | 
					            [message]="'addon.calendar.noevents' | translate">
 | 
				
			||||||
        </core-empty-box>
 | 
					        </core-empty-box>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <ion-list *ngIf="filteredEvents && filteredEvents.length"  class="ion-no-margin">
 | 
					        <ion-list *ngIf="filteredEvents && filteredEvents.length" class="ion-no-margin">
 | 
				
			||||||
            <ng-container *ngFor="let event of filteredEvents">
 | 
					            <ng-container *ngFor="let event of filteredEvents">
 | 
				
			||||||
                <ion-item class="addon-calendar-event ion-text-wrap" [attr.aria-label]="event.name" (click)="gotoEvent(event.id)"
 | 
					                <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>
 | 
					                [class.item-dimmed]="event.ispast" [ngClass]="['addon-calendar-eventtype-'+event.eventtype]" button>
 | 
				
			||||||
 | 
				
			|||||||
@ -531,7 +531,7 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy, CanLeave {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    await AddonCalendarHelper.refreshAfterChangeEvent(result.event, numberOfRepetitions);
 | 
					                    await AddonCalendarHelper.refreshAfterChangeEvent(result.event, numberOfRepetitions);
 | 
				
			||||||
                } catch  {
 | 
					                } catch {
 | 
				
			||||||
                    // Ignore errors.
 | 
					                    // Ignore errors.
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
				
			|||||||
@ -145,7 +145,7 @@
 | 
				
			|||||||
                </ion-label>
 | 
					                </ion-label>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
            <ng-container *ngFor="let reminder of reminders">
 | 
					            <ng-container *ngFor="let reminder of reminders">
 | 
				
			||||||
                <ion-item  *ngIf="reminder.time > 0 || defaultTime > 0" class="ion-text-wrap"
 | 
					                <ion-item *ngIf="reminder.time > 0 || defaultTime > 0" class="ion-text-wrap"
 | 
				
			||||||
                    [class.item-dimmed]="(reminder.time == -1 ? (event.timestart - defaultTime) : reminder.time) <= currentTime!">
 | 
					                    [class.item-dimmed]="(reminder.time == -1 ? (event.timestart - defaultTime) : reminder.time) <= currentTime!">
 | 
				
			||||||
                    <ion-label>
 | 
					                    <ion-label>
 | 
				
			||||||
                        <p *ngIf="reminder.time == -1">
 | 
					                        <p *ngIf="reminder.time == -1">
 | 
				
			||||||
 | 
				
			|||||||
@ -343,8 +343,8 @@ export class AddonCalendarEventPage implements OnInit, OnDestroy {
 | 
				
			|||||||
            const minute = Math.floor(currentTime / 60) * 60;
 | 
					            const minute = Math.floor(currentTime / 60) * 60;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Check if the notification time is in the same minute as we are, so the notification is triggered.
 | 
					            // Check if the notification time is in the same minute as we are, so the notification is triggered.
 | 
				
			||||||
            if (notificationTime >=  minute && notificationTime < minute + 60) {
 | 
					            if (notificationTime >= minute && notificationTime < minute + 60) {
 | 
				
			||||||
                notificationTime  = currentTime + 1;
 | 
					                notificationTime = currentTime + 1;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            await AddonCalendar.addEventReminder(this.event, notificationTime);
 | 
					            await AddonCalendar.addEventReminder(this.event, notificationTime);
 | 
				
			||||||
 | 
				
			|||||||
@ -18,7 +18,7 @@
 | 
				
			|||||||
                <core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600"
 | 
					                <core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600"
 | 
				
			||||||
                [content]="'core.settings.settings' | translate" (action)="openSettings()" iconAction="fas-cogs">
 | 
					                [content]="'core.settings.settings' | translate" (action)="openSettings()" iconAction="fas-cogs">
 | 
				
			||||||
                </core-context-menu-item>
 | 
					                </core-context-menu-item>
 | 
				
			||||||
                <core-context-menu-item [hidden]="!loaded || !hasOffline || !isOnline"  [priority]="400"
 | 
					                <core-context-menu-item [hidden]="!loaded || !hasOffline || !isOnline" [priority]="400"
 | 
				
			||||||
                [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(undefined, $event, true)"
 | 
					                [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(undefined, $event, true)"
 | 
				
			||||||
                [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
 | 
					                [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
 | 
				
			||||||
            </core-context-menu>
 | 
					            </core-context-menu>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
                <core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600"
 | 
					                <core-context-menu-item [hidden]="!notificationsEnabled" [priority]="600"
 | 
				
			||||||
                [content]="'core.settings.settings' | translate" (action)="openSettings()" iconAction="fas-cogs">
 | 
					                [content]="'core.settings.settings' | translate" (action)="openSettings()" iconAction="fas-cogs">
 | 
				
			||||||
            </core-context-menu-item>
 | 
					            </core-context-menu-item>
 | 
				
			||||||
                <core-context-menu-item [hidden]="!eventsLoaded || !hasOffline || !isOnline"  [priority]="400"
 | 
					                <core-context-menu-item [hidden]="!eventsLoaded || !hasOffline || !isOnline" [priority]="400"
 | 
				
			||||||
                [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(undefined, $event, true)"
 | 
					                [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(undefined, $event, true)"
 | 
				
			||||||
                [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
 | 
					                [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
 | 
				
			||||||
            </core-context-menu>
 | 
					            </core-context-menu>
 | 
				
			||||||
@ -37,7 +37,7 @@
 | 
				
			|||||||
                [message]="'addon.calendar.noevents' | translate">
 | 
					                [message]="'addon.calendar.noevents' | translate">
 | 
				
			||||||
            </core-empty-box>
 | 
					            </core-empty-box>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <ion-list *ngIf="filteredEvents && filteredEvents.length"  class="ion-no-margin">
 | 
					            <ion-list *ngIf="filteredEvents && filteredEvents.length" class="ion-no-margin">
 | 
				
			||||||
                <ng-container *ngFor="let event of filteredEvents">
 | 
					                <ng-container *ngFor="let event of filteredEvents">
 | 
				
			||||||
                    <ion-item-divider *ngIf="event.showDate">
 | 
					                    <ion-item-divider *ngIf="event.showDate">
 | 
				
			||||||
                        <ion-label><h2>{{ event.timestart * 1000 | coreFormatDate: "strftimedayshort" }}</h2></ion-label>
 | 
					                        <ion-label><h2>{{ event.timestart * 1000 | coreFormatDate: "strftimedayshort" }}</h2></ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -476,7 +476,7 @@ export class AddonCalendarHelperProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const categoryId = filter.categoryId ? Number(filter.categoryId) : undefined;
 | 
					        const categoryId = filter.categoryId ? Number(filter.categoryId) : undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return  events.filter((event) => filter[event.formattedType] &&
 | 
					        return events.filter((event) => filter[event.formattedType] &&
 | 
				
			||||||
                this.shouldDisplayEvent(event, categories, courseId, categoryId));
 | 
					                this.shouldDisplayEvent(event, categories, courseId, categoryId));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -203,7 +203,7 @@ export class AddonCalendarSyncProvider extends CoreSyncBaseProvider<AddonCalenda
 | 
				
			|||||||
                        id: event.id,
 | 
					                        id: event.id,
 | 
				
			||||||
                        repeatid: event.repeatid,
 | 
					                        repeatid: event.repeatid,
 | 
				
			||||||
                        timestart: event.timestart,
 | 
					                        timestart: event.timestart,
 | 
				
			||||||
                        repeated:  data?.repeat ? (event as AddonCalendarEvent).eventcount || 1 : 1,
 | 
					                        repeated: data?.repeat ? (event as AddonCalendarEvent).eventcount || 1 : 1,
 | 
				
			||||||
                    });
 | 
					                    });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    return;
 | 
					                    return;
 | 
				
			||||||
 | 
				
			|||||||
@ -577,7 +577,7 @@ export class AddonCalendarProvider {
 | 
				
			|||||||
            value = site.getStoredConfig('calendar_lookahead');
 | 
					            value = site.getStoredConfig('calendar_lookahead');
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return  parseInt(value as string, 10);
 | 
					        return parseInt(value as string, 10);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -1595,7 +1595,7 @@ export class AddonCalendarProvider {
 | 
				
			|||||||
     * @param siteId ID of the site the event belongs to. If not defined, use current site.
 | 
					     * @param siteId ID of the site the event belongs to. If not defined, use current site.
 | 
				
			||||||
     * @return Promise resolved when stored.
 | 
					     * @return Promise resolved when stored.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    async storeEventInLocalDb(event:  AddonCalendarGetEventsEvent | AddonCalendarCalendarEvent, siteId?: string): Promise<void> {
 | 
					    async storeEventInLocalDb(event: AddonCalendarGetEventsEvent | AddonCalendarCalendarEvent, siteId?: string): Promise<void> {
 | 
				
			||||||
        const site = await CoreSites.getSite(siteId);
 | 
					        const site = await CoreSites.getSite(siteId);
 | 
				
			||||||
        siteId = site.getId();
 | 
					        siteId = site.getId();
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
@ -1775,7 +1775,7 @@ export const AddonCalendar = makeSingleton(AddonCalendarProvider);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Data returned by calendar's events_exporter.
 | 
					 * Data returned by calendar's events_exporter.
 | 
				
			||||||
 *  Data returned by core_calendar_get_action_events_by_course and core_calendar_get_action_events_by_timesort WS.
 | 
					 * Data returned by core_calendar_get_action_events_by_course and core_calendar_get_action_events_by_timesort WS.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export type AddonCalendarEvents = {
 | 
					export type AddonCalendarEvents = {
 | 
				
			||||||
    events: AddonCalendarEvent[]; // Events.
 | 
					    events: AddonCalendarEvent[]; // Events.
 | 
				
			||||||
@ -1912,7 +1912,7 @@ export type AddonCalendarEventBase = {
 | 
				
			|||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Data returned by calendar's event_exporter.  Don't confuse it with AddonCalendarCalendarEvent.
 | 
					 * Data returned by calendar's event_exporter. Don't confuse it with AddonCalendarCalendarEvent.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export type AddonCalendarEvent = AddonCalendarEventBase & {
 | 
					export type AddonCalendarEvent = AddonCalendarEventBase & {
 | 
				
			||||||
    url: string; // Url.
 | 
					    url: string; // Url.
 | 
				
			||||||
 | 
				
			|||||||
@ -98,7 +98,7 @@
 | 
				
			|||||||
                    <ion-badge slot="end" color="success" *ngIf="userCompetency.proficiency">
 | 
					                    <ion-badge slot="end" color="success" *ngIf="userCompetency.proficiency">
 | 
				
			||||||
                        {{ 'core.yes' | translate }}
 | 
					                        {{ 'core.yes' | translate }}
 | 
				
			||||||
                    </ion-badge>
 | 
					                    </ion-badge>
 | 
				
			||||||
                    <ion-badge  slot="end" color="danger" *ngIf="!userCompetency.proficiency">
 | 
					                    <ion-badge slot="end" color="danger" *ngIf="!userCompetency.proficiency">
 | 
				
			||||||
                        {{ 'core.no' | translate }}
 | 
					                        {{ 'core.no' | translate }}
 | 
				
			||||||
                    </ion-badge>
 | 
					                    </ion-badge>
 | 
				
			||||||
                </ion-item>
 | 
					                </ion-item>
 | 
				
			||||||
@ -112,8 +112,8 @@
 | 
				
			|||||||
        </ion-card>
 | 
					        </ion-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div *ngIf="competency">
 | 
					        <div *ngIf="competency">
 | 
				
			||||||
            <h3  class="ion-margin-horizontal">{{ 'addon.competency.evidence' | translate }}</h3>
 | 
					            <h3 class="ion-margin-horizontal">{{ 'addon.competency.evidence' | translate }}</h3>
 | 
				
			||||||
            <p  class="ion-margin-horizontal" *ngIf="competency.evidence.length == 0">
 | 
					            <p class="ion-margin-horizontal" *ngIf="competency.evidence.length == 0">
 | 
				
			||||||
                {{ 'addon.competency.noevidence' | translate }}
 | 
					                {{ 'addon.competency.noevidence' | translate }}
 | 
				
			||||||
            </p>
 | 
					            </p>
 | 
				
			||||||
            <ion-card *ngFor="let evidence of competency.evidence">
 | 
					            <ion-card *ngFor="let evidence of competency.evidence">
 | 
				
			||||||
@ -128,7 +128,7 @@
 | 
				
			|||||||
                <ion-item class="ion-text-wrap">
 | 
					                <ion-item class="ion-text-wrap">
 | 
				
			||||||
                    <ion-label>
 | 
					                    <ion-label>
 | 
				
			||||||
                        <p><ion-badge color="dark">{{ evidence.gradename }}</ion-badge></p>
 | 
					                        <p><ion-badge color="dark">{{ evidence.gradename }}</ion-badge></p>
 | 
				
			||||||
                        <p  class="ion-margin-top" *ngIf="evidence.description">{{ evidence.description }}</p>
 | 
					                        <p class="ion-margin-top" *ngIf="evidence.description">{{ evidence.description }}</p>
 | 
				
			||||||
                        <blockquote *ngIf="evidence.note">{{ evidence.note }}</blockquote>
 | 
					                        <blockquote *ngIf="evidence.note">{{ evidence.note }}</blockquote>
 | 
				
			||||||
                    </ion-label>
 | 
					                    </ion-label>
 | 
				
			||||||
                </ion-item>
 | 
					                </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -40,7 +40,7 @@
 | 
				
			|||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
        </ion-card>
 | 
					        </ion-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <h3  class="ion-margin-horizontal" *ngIf="competencies && competencies.statistics.competencycount > 0">
 | 
					        <h3 class="ion-margin-horizontal" *ngIf="competencies && competencies.statistics.competencycount > 0">
 | 
				
			||||||
            {{ 'addon.competency.coursecompetencies' | translate }}
 | 
					            {{ 'addon.competency.coursecompetencies' | translate }}
 | 
				
			||||||
        </h3>
 | 
					        </h3>
 | 
				
			||||||
        <ion-card *ngIf="user">
 | 
					        <ion-card *ngIf="user">
 | 
				
			||||||
 | 
				
			|||||||
@ -15,7 +15,7 @@
 | 
				
			|||||||
            <core-empty-box *ngIf="plans.empty" icon="fas-route" [message]="'addon.competency.noplanswerecreated' | translate">
 | 
					            <core-empty-box *ngIf="plans.empty" icon="fas-route" [message]="'addon.competency.noplanswerecreated' | translate">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            </core-empty-box>
 | 
					            </core-empty-box>
 | 
				
			||||||
            <ion-list *ngIf="!plans.empty"  class="ion-no-margin">
 | 
					            <ion-list *ngIf="!plans.empty" class="ion-no-margin">
 | 
				
			||||||
                <ion-item class="ion-text-wrap" *ngFor="let plan of plans.items" [attr.aria-label]="plan.name"
 | 
					                <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>
 | 
					                    (click)="plans.select(plan)" [attr.aria-current]="plans.getItemAriaCurrent(plan)" button>
 | 
				
			||||||
                    <ion-label>
 | 
					                    <ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -53,7 +53,7 @@
 | 
				
			|||||||
:host-context([dir=rtl]) {
 | 
					:host-context([dir=rtl]) {
 | 
				
			||||||
    .addon-messages-conversation-item,
 | 
					    .addon-messages-conversation-item,
 | 
				
			||||||
    .addon-message-discussion {
 | 
					    .addon-message-discussion {
 | 
				
			||||||
        h2  ion-icon {
 | 
					        h2 ion-icon {
 | 
				
			||||||
            margin-right: 2px;
 | 
					            margin-right: 2px;
 | 
				
			||||||
            margin-left: 0;
 | 
					            margin-left: 0;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
				
			|||||||
@ -28,7 +28,7 @@
 | 
				
			|||||||
            <core-empty-box *ngIf="!hasContacts && searchString != ''" icon="fas-address-book"
 | 
					            <core-empty-box *ngIf="!hasContacts && searchString != ''" icon="fas-address-book"
 | 
				
			||||||
                [message]="'addon.messages.nousersfound' | translate"></core-empty-box>
 | 
					                [message]="'addon.messages.nousersfound' | translate"></core-empty-box>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            <ion-list *ngFor="let contactType of contactTypes"  class="ion-no-margin">
 | 
					            <ion-list *ngFor="let contactType of contactTypes" class="ion-no-margin">
 | 
				
			||||||
                <ng-container *ngIf="contacts[contactType] && (contacts[contactType].length > 0 || contactType === searchType)">
 | 
					                <ng-container *ngIf="contacts[contactType] && (contacts[contactType].length > 0 || contactType === searchType)">
 | 
				
			||||||
                    <ion-item-divider>
 | 
					                    <ion-item-divider>
 | 
				
			||||||
                        <ion-label><h2>{{ 'addon.messages.type_' + contactType | translate }}</h2></ion-label>
 | 
					                        <ion-label><h2>{{ 'addon.messages.type_' + contactType | translate }}</h2></ion-label>
 | 
				
			||||||
@ -39,7 +39,7 @@
 | 
				
			|||||||
                        <ion-item class="ion-text-wrap addon-messages-conversation-item"
 | 
					                        <ion-item class="ion-text-wrap addon-messages-conversation-item"
 | 
				
			||||||
                            *ngIf="contact.profileimageurl || contact.profileimageurlsmall"
 | 
					                            *ngIf="contact.profileimageurl || contact.profileimageurlsmall"
 | 
				
			||||||
                            [attr.aria-label]="contact.fullname" (click)="gotoDiscussion(contact.id)" detail="true" button
 | 
					                            [attr.aria-label]="contact.fullname" (click)="gotoDiscussion(contact.id)" detail="true" button
 | 
				
			||||||
                            [attr.aria-current]="contact.id == discussionUserId ? 'page' :  'false'">
 | 
					                            [attr.aria-current]="contact.id == discussionUserId ? 'page' : 'false'">
 | 
				
			||||||
                            <core-user-avatar [user]="contact" slot="start" [checkOnline]="contact.showonlinestatus"></core-user-avatar>
 | 
					                            <core-user-avatar [user]="contact" slot="start" [checkOnline]="contact.showonlinestatus"></core-user-avatar>
 | 
				
			||||||
                            <ion-label><h2>{{ contact.fullname }}</h2></ion-label>
 | 
					                            <ion-label><h2>{{ contact.fullname }}</h2></ion-label>
 | 
				
			||||||
                        </ion-item>
 | 
					                        </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -25,10 +25,10 @@
 | 
				
			|||||||
                        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
					                        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
				
			||||||
                    </ion-refresher>
 | 
					                    </ion-refresher>
 | 
				
			||||||
                    <core-loading [hideUntil]="confirmedLoaded" class="core-loading-center">
 | 
					                    <core-loading [hideUntil]="confirmedLoaded" class="core-loading-center">
 | 
				
			||||||
                        <ion-list  class="ion-no-margin">
 | 
					                        <ion-list class="ion-no-margin">
 | 
				
			||||||
                            <ion-item class="ion-text-wrap addon-messages-conversation-item" (click)="selectUser(contact.id)" button
 | 
					                            <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"
 | 
					                                *ngFor="let contact of confirmedContacts" [attr.aria-label]="contact.fullname" detail="true"
 | 
				
			||||||
                                [attr.aria-current]="contact.id == selectedUserId ? 'page' :  'false'">
 | 
					                                [attr.aria-current]="contact.id == selectedUserId ? 'page' : 'false'">
 | 
				
			||||||
                                <core-user-avatar slot="start" [user]="contact"
 | 
					                                <core-user-avatar slot="start" [user]="contact"
 | 
				
			||||||
                                    [checkOnline]="contact.showonlinestatus" [linkProfile]="false">
 | 
					                                    [checkOnline]="contact.showonlinestatus" [linkProfile]="false">
 | 
				
			||||||
                                </core-user-avatar>
 | 
					                                </core-user-avatar>
 | 
				
			||||||
@ -62,10 +62,10 @@
 | 
				
			|||||||
                        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
					                        <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
				
			||||||
                    </ion-refresher>
 | 
					                    </ion-refresher>
 | 
				
			||||||
                    <core-loading [hideUntil]="requestsLoaded" class="core-loading-center">
 | 
					                    <core-loading [hideUntil]="requestsLoaded" class="core-loading-center">
 | 
				
			||||||
                        <ion-list  class="ion-no-margin">
 | 
					                        <ion-list class="ion-no-margin">
 | 
				
			||||||
                            <ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let request of requests"
 | 
					                            <ion-item class="ion-text-wrap addon-messages-conversation-item" *ngFor="let request of requests"
 | 
				
			||||||
                                [attr.aria-label]="request.fullname" (click)="selectUser(request.id)" button
 | 
					                                [attr.aria-label]="request.fullname" (click)="selectUser(request.id)" button
 | 
				
			||||||
                                [attr.aria-current]="request.id == selectedUserId ? 'page' :  'false'" detail="true">
 | 
					                                [attr.aria-current]="request.id == selectedUserId ? 'page' : 'false'" detail="true">
 | 
				
			||||||
                                <core-user-avatar slot="start" [user]="request" [linkProfile]="false"></core-user-avatar>
 | 
					                                <core-user-avatar slot="start" [user]="request" [linkProfile]="false"></core-user-avatar>
 | 
				
			||||||
                                <ion-label>
 | 
					                                <ion-label>
 | 
				
			||||||
                                    <core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0">
 | 
					                                    <core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0">
 | 
				
			||||||
 | 
				
			|||||||
@ -411,7 +411,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
 | 
				
			|||||||
            // Fetch messages. Invalidate the cache before fetching.
 | 
					            // Fetch messages. Invalidate the cache before fetching.
 | 
				
			||||||
            if (this.groupMessagingEnabled) {
 | 
					            if (this.groupMessagingEnabled) {
 | 
				
			||||||
                await AddonMessages.invalidateConversationMessages(this.conversationId!);
 | 
					                await AddonMessages.invalidateConversationMessages(this.conversationId!);
 | 
				
			||||||
                messages =  await this.getConversationMessages(this.pagesLoaded);
 | 
					                messages = await this.getConversationMessages(this.pagesLoaded);
 | 
				
			||||||
            } else {
 | 
					            } else {
 | 
				
			||||||
                await AddonMessages.invalidateDiscussionCache(this.userId!);
 | 
					                await AddonMessages.invalidateDiscussionCache(this.userId!);
 | 
				
			||||||
                messages = await this.getDiscussionMessages(this.pagesLoaded);
 | 
					                messages = await this.getDiscussionMessages(this.pagesLoaded);
 | 
				
			||||||
 | 
				
			|||||||
@ -40,7 +40,7 @@
 | 
				
			|||||||
                    </ion-item-divider>
 | 
					                    </ion-item-divider>
 | 
				
			||||||
                    <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" button
 | 
					                    <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-label]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)"
 | 
				
			||||||
                        [attr.aria-current]="result.userid == discussionUserId ? 'page' :  'false'">
 | 
					                        [attr.aria-current]="result.userid == discussionUserId ? 'page' : 'false'">
 | 
				
			||||||
                        <core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar>
 | 
					                        <core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar>
 | 
				
			||||||
                        <ion-label>
 | 
					                        <ion-label>
 | 
				
			||||||
                                <h2>{{ result.fullname }}</h2>
 | 
					                                <h2>{{ result.fullname }}</h2>
 | 
				
			||||||
@ -52,7 +52,7 @@
 | 
				
			|||||||
                <ng-container *ngIf="!search.showResults">
 | 
					                <ng-container *ngIf="!search.showResults">
 | 
				
			||||||
                    <ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions" button
 | 
					                    <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-label]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)"
 | 
				
			||||||
                        [attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' :  'false'">
 | 
					                        [attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' : 'false'">
 | 
				
			||||||
                        <core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar>
 | 
					                        <core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar>
 | 
				
			||||||
                        <ion-label>
 | 
					                        <ion-label>
 | 
				
			||||||
                            <h2>{{ discussion.fullname }}</h2>
 | 
					                            <h2>{{ discussion.fullname }}</h2>
 | 
				
			||||||
 | 
				
			|||||||
@ -67,7 +67,7 @@ export class AddonMessagesDiscussions35Page implements OnInit, OnDestroy {
 | 
				
			|||||||
        protected route: ActivatedRoute,
 | 
					        protected route: ActivatedRoute,
 | 
				
			||||||
    ) {
 | 
					    ) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.search.loading =  Translate.instant('core.searching');
 | 
					        this.search.loading = Translate.instant('core.searching');
 | 
				
			||||||
        this.loadingMessages = Translate.instant('core.loading');
 | 
					        this.loadingMessages = Translate.instant('core.loading');
 | 
				
			||||||
        this.siteId = CoreSites.getCurrentSiteId();
 | 
					        this.siteId = CoreSites.getCurrentSiteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@
 | 
				
			|||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <core-split-view>
 | 
					    <core-split-view>
 | 
				
			||||||
        <core-search-box (onSubmit)="search($event)" (onClear)="clearSearch()" [disabled]="disableSearch" autocorrect="off"
 | 
					        <core-search-box (onSubmit)="search($event)" (onClear)="clearSearch()" [disabled]="disableSearch" autocorrect="off"
 | 
				
			||||||
            [spellcheck]="false" [autoFocus]="true" [lengthCheck]="1"  searchArea="AddonMessagesSearch"></core-search-box>
 | 
					            [spellcheck]="false" [autoFocus]="true" [lengthCheck]="1" searchArea="AddonMessagesSearch"></core-search-box>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <core-loading [hideUntil]="!displaySearching" [message]="'core.searching' | translate">
 | 
					        <core-loading [hideUntil]="!displaySearching" [message]="'core.searching' | translate">
 | 
				
			||||||
            <ion-list *ngIf="displayResults">
 | 
					            <ion-list *ngIf="displayResults">
 | 
				
			||||||
@ -43,7 +43,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        <!-- List of results -->
 | 
					        <!-- List of results -->
 | 
				
			||||||
        <ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [attr.aria-label]="result.fullname"
 | 
					        <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"
 | 
					            (click)="openConversation(result)" [attr.aria-current]="result == selectedResult ? 'page' : 'false'" detail="true"
 | 
				
			||||||
            button>
 | 
					            button>
 | 
				
			||||||
            <core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar>
 | 
					            <core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar>
 | 
				
			||||||
            <ion-label>
 | 
					            <ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -83,7 +83,7 @@
 | 
				
			|||||||
                        <ng-container *ngIf="!groupMessagingEnabled">
 | 
					                        <ng-container *ngIf="!groupMessagingEnabled">
 | 
				
			||||||
                            <!-- Tablet view -->
 | 
					                            <!-- Tablet view -->
 | 
				
			||||||
                            <ion-row class="ion-text-wrap ion-hide-md-down ion-align-items-center">
 | 
					                            <ion-row class="ion-text-wrap ion-hide-md-down ion-align-items-center">
 | 
				
			||||||
                                <ion-col  class="ion-margin-horizontal">{{ processor.displayname }}</ion-col>
 | 
					                                <ion-col class="ion-margin-horizontal">{{ processor.displayname }}</ion-col>
 | 
				
			||||||
                                <ion-col size="2" class="ion-text-center" *ngFor="let state of ['loggedin', 'loggedoff']">
 | 
					                                <ion-col size="2" class="ion-text-center" *ngFor="let state of ['loggedin', 'loggedoff']">
 | 
				
			||||||
                                    <!-- If notifications not disabled, show toggle. -->
 | 
					                                    <!-- If notifications not disabled, show toggle. -->
 | 
				
			||||||
                                    <ion-spinner [hidden]="preferences.disableall ||
 | 
					                                    <ion-spinner [hidden]="preferences.disableall ||
 | 
				
			||||||
 | 
				
			|||||||
@ -86,7 +86,7 @@ export type AddonMessagesOfflineMessagesDBRecord = {
 | 
				
			|||||||
    deviceoffline: number; // If message was stored because device was offline.
 | 
					    deviceoffline: number; // If message was stored because device was offline.
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type  AddonMessagesOfflineConversationMessagesDBRecord = {
 | 
					export type AddonMessagesOfflineConversationMessagesDBRecord = {
 | 
				
			||||||
    conversationid: number;
 | 
					    conversationid: number;
 | 
				
			||||||
    text: string;
 | 
					    text: string;
 | 
				
			||||||
    timecreated: number;
 | 
					    timecreated: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -1165,7 +1165,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
            canLoadMore: false,
 | 
					            canLoadMore: false,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const preSets: CoreSiteWSPreSets =  {
 | 
					        const preSets: CoreSiteWSPreSets = {
 | 
				
			||||||
            cacheKey: this.getCacheKeyForDiscussion(userId),
 | 
					            cacheKey: this.getCacheKeyForDiscussion(userId),
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        const params: AddonMessagesGetMessagesWSParams = {
 | 
					        const params: AddonMessagesGetMessagesWSParams = {
 | 
				
			||||||
@ -2012,7 +2012,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * Returns whether or not we can mark all messages as read.
 | 
					     * Returns whether or not we can mark all messages as read.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return If related WS is available on current site.
 | 
					     * @return If related WS is available on current site.
 | 
				
			||||||
     * @since  3.2
 | 
					     * @since 3.2
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    isMarkAllMessagesReadEnabled(): boolean {
 | 
					    isMarkAllMessagesReadEnabled(): boolean {
 | 
				
			||||||
        return CoreSites.wsAvailableInCurrentSite('core_message_mark_all_conversation_messages_as_read') ||
 | 
					        return CoreSites.wsAvailableInCurrentSite('core_message_mark_all_conversation_messages_as_read') ||
 | 
				
			||||||
@ -2023,7 +2023,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * Returns whether or not we can count unread messages.
 | 
					     * Returns whether or not we can count unread messages.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return True if enabled, false otherwise.
 | 
					     * @return True if enabled, false otherwise.
 | 
				
			||||||
     * @since  3.2
 | 
					     * @since 3.2
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    isMessageCountEnabled(): boolean {
 | 
					    isMessageCountEnabled(): boolean {
 | 
				
			||||||
        return CoreSites.wsAvailableInCurrentSite('core_message_get_unread_conversations_count');
 | 
					        return CoreSites.wsAvailableInCurrentSite('core_message_get_unread_conversations_count');
 | 
				
			||||||
@ -2033,7 +2033,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * Returns whether or not the message preferences are enabled for the current site.
 | 
					     * Returns whether or not the message preferences are enabled for the current site.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @return True if enabled, false otherwise.
 | 
					     * @return True if enabled, false otherwise.
 | 
				
			||||||
     * @since  3.2
 | 
					     * @since 3.2
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    isMessagePreferencesEnabled(): boolean {
 | 
					    isMessagePreferencesEnabled(): boolean {
 | 
				
			||||||
        return CoreSites.wsAvailableInCurrentSite('core_message_get_user_message_preferences');
 | 
					        return CoreSites.wsAvailableInCurrentSite('core_message_get_user_message_preferences');
 | 
				
			||||||
@ -2100,7 +2100,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Returns whether or not we can search messages.
 | 
					     * Returns whether or not we can search messages.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @since  3.2
 | 
					     * @since 3.2
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    isSearchMessagesEnabled(): boolean {
 | 
					    isSearchMessagesEnabled(): boolean {
 | 
				
			||||||
        return CoreSites.wsAvailableInCurrentSite('core_message_data_for_messagearea_search_messages');
 | 
					        return CoreSites.wsAvailableInCurrentSite('core_message_data_for_messagearea_search_messages');
 | 
				
			||||||
@ -2167,7 +2167,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
            conversationid: conversationId,
 | 
					            conversationid: conversationId,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const preSets: CoreSiteWSPreSets =  {
 | 
					        const preSets: CoreSiteWSPreSets = {
 | 
				
			||||||
            responseExpected: false,
 | 
					            responseExpected: false,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2187,7 +2187,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
            useridfrom: userIdFrom,
 | 
					            useridfrom: userIdFrom,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const preSets: CoreSiteWSPreSets =  {
 | 
					        const preSets: CoreSiteWSPreSets = {
 | 
				
			||||||
            typeExpected: 'boolean',
 | 
					            typeExpected: 'boolean',
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -2834,7 +2834,7 @@ export class AddonMessagesProvider {
 | 
				
			|||||||
     * @param discussions List of discussions.
 | 
					     * @param discussions List of discussions.
 | 
				
			||||||
     * @param siteId Site ID. If not defined, current site.
 | 
					     * @param siteId Site ID. If not defined, current site.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected storeUsersFromDiscussions(discussions:  { [userId: number]: AddonMessagesDiscussion }, siteId?: string): void {
 | 
					    protected storeUsersFromDiscussions(discussions: { [userId: number]: AddonMessagesDiscussion }, siteId?: string): void {
 | 
				
			||||||
        const users: CoreUserBasicData[] = [];
 | 
					        const users: CoreUserBasicData[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for (const userId in discussions) {
 | 
					        for (const userId in discussions) {
 | 
				
			||||||
@ -3377,7 +3377,7 @@ export type AddonMessagesMarkMessageReadResult = {
 | 
				
			|||||||
 * Result of WS core_message_send_instant_messages.
 | 
					 * Result of WS core_message_send_instant_messages.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
export type AddonMessagesSendInstantMessagesMessage = {
 | 
					export type AddonMessagesSendInstantMessagesMessage = {
 | 
				
			||||||
    msgid: number; // Test this to know if it succeeds:  id of the created message if it succeeded, -1 when failed.
 | 
					    msgid: number; // Test this to know if it succeeds: i of the created message if it succeeded, -1 when failed.
 | 
				
			||||||
    clientmsgid?: string; // Your own id for the message.
 | 
					    clientmsgid?: string; // Your own id for the message.
 | 
				
			||||||
    errormessage?: string; // Error message - if it failed.
 | 
					    errormessage?: string; // Error message - if it failed.
 | 
				
			||||||
    text?: string; // @since 3.6. The text of the message.
 | 
					    text?: string; // @since 3.6. The text of the message.
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
					            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
				
			||||||
            [closeOnClick]="false">
 | 
					            [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -601,7 +601,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
 | 
				
			|||||||
            disabled: false,
 | 
					            disabled: false,
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        this.originalGrades =  {
 | 
					        this.originalGrades = {
 | 
				
			||||||
            addAttempt: false,
 | 
					            addAttempt: false,
 | 
				
			||||||
            applyToAll: false,
 | 
					            applyToAll: false,
 | 
				
			||||||
            outcomes: {},
 | 
					            outcomes: {},
 | 
				
			||||||
@ -613,7 +613,7 @@ export class AddonModAssignSubmissionComponent implements OnInit, OnDestroy, Can
 | 
				
			|||||||
            // If we have data about the grader, get its profile.
 | 
					            // If we have data about the grader, get its profile.
 | 
				
			||||||
            if (feedback.grade && feedback.grade.grader > 0) {
 | 
					            if (feedback.grade && feedback.grade.grader > 0) {
 | 
				
			||||||
                try {
 | 
					                try {
 | 
				
			||||||
                    this.grader =  await CoreUser.getProfile(feedback.grade.grader, this.courseId);
 | 
					                    this.grader = await CoreUser.getProfile(feedback.grade.grader, this.courseId);
 | 
				
			||||||
                } catch {
 | 
					                } catch {
 | 
				
			||||||
                    // Ignore errors.
 | 
					                    // Ignore errors.
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@
 | 
				
			|||||||
            <ion-back-button [text]="'core.back' | translate"></ion-back-button>
 | 
					            <ion-back-button [text]="'core.back' | translate"></ion-back-button>
 | 
				
			||||||
        </ion-buttons>
 | 
					        </ion-buttons>
 | 
				
			||||||
        <ion-title>
 | 
					        <ion-title>
 | 
				
			||||||
            <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="moduleId"  [courseId]="courseId">
 | 
					            <core-format-text [text]="title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId">
 | 
				
			||||||
            </core-format-text>
 | 
					            </core-format-text>
 | 
				
			||||||
        </ion-title>
 | 
					        </ion-title>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -54,7 +54,7 @@ export class AddonModAssignSubmissionListPage implements AfterViewInit, OnDestro
 | 
				
			|||||||
    assign?: AddonModAssignAssign; // Assignment.
 | 
					    assign?: AddonModAssignAssign; // Assignment.
 | 
				
			||||||
    submissions: AddonModAssignSubmissionListManager; // List of submissions
 | 
					    submissions: AddonModAssignSubmissionListManager; // List of submissions
 | 
				
			||||||
    loaded = false; // Whether data has been loaded.
 | 
					    loaded = false; // Whether data has been loaded.
 | 
				
			||||||
    haveAllParticipants  = true; // Whether all participants have been loaded.
 | 
					    haveAllParticipants = true; // Whether all participants have been loaded.
 | 
				
			||||||
    groupId = 0; // Group ID to show.
 | 
					    groupId = 0; // Group ID to show.
 | 
				
			||||||
    courseId!: number; // Course ID the assignment belongs to.
 | 
					    courseId!: number; // Course ID the assignment belongs to.
 | 
				
			||||||
    moduleId!: number; // Module ID the submission belongs to.
 | 
					    moduleId!: number; // Module ID the submission belongs to.
 | 
				
			||||||
 | 
				
			|||||||
@ -37,7 +37,7 @@ export class AddonModAssignSubmissionReviewPage implements OnInit, CanLeave {
 | 
				
			|||||||
    title = ''; // Title to display.
 | 
					    title = ''; // Title to display.
 | 
				
			||||||
    moduleId!: number; // Module ID the submission belongs to.
 | 
					    moduleId!: number; // Module ID the submission belongs to.
 | 
				
			||||||
    courseId!: number; // Course ID the assignment belongs to.
 | 
					    courseId!: number; // Course ID the assignment belongs to.
 | 
				
			||||||
    submitId!: number; //  User that did the submission.
 | 
					    submitId!: number; // User that did the submission.
 | 
				
			||||||
    blindId?: number; // Blinded user ID (if it's blinded).
 | 
					    blindId?: number; // Blinded user ID (if it's blinded).
 | 
				
			||||||
    loaded = false; // Whether data has been loaded.
 | 
					    loaded = false; // Whether data has been loaded.
 | 
				
			||||||
    canSaveGrades = false; // Whether the user can save grades.
 | 
					    canSaveGrades = false; // Whether the user can save grades.
 | 
				
			||||||
 | 
				
			|||||||
@ -464,7 +464,7 @@ export class AddonModAssignSyncProvider extends CoreCourseActivitySyncBaseProvid
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        // Override offline grade and outcomes based on the gradebook data.
 | 
					        // Override offline grade and outcomes based on the gradebook data.
 | 
				
			||||||
        grades.forEach((grade: CoreGradesFormattedItem | CoreGradesFormattedRow) => {
 | 
					        grades.forEach((grade: CoreGradesFormattedItem | CoreGradesFormattedRow) => {
 | 
				
			||||||
            if ('gradedategraded' in  grade && (grade.gradedategraded || 0) >= offlineData.timemodified) {
 | 
					            if ('gradedategraded' in grade && (grade.gradedategraded || 0) >= offlineData.timemodified) {
 | 
				
			||||||
                if (!grade.outcomeid && !grade.scaleid) {
 | 
					                if (!grade.outcomeid && !grade.scaleid) {
 | 
				
			||||||
                    if (gradeInfo && gradeInfo.scale) {
 | 
					                    if (gradeInfo && gradeInfo.scale) {
 | 
				
			||||||
                        offlineData.grade = this.getSelectedScaleId(gradeInfo.scale, grade.grade || '');
 | 
					                        offlineData.grade = this.getSelectedScaleId(gradeInfo.scale, grade.grade || '');
 | 
				
			||||||
 | 
				
			|||||||
@ -90,7 +90,7 @@ export class AddonModAssignProvider {
 | 
				
			|||||||
    static readonly SUBMITTED_FOR_GRADING_EVENT = 'addon_mod_assign_submitted_for_grading';
 | 
					    static readonly SUBMITTED_FOR_GRADING_EVENT = 'addon_mod_assign_submitted_for_grading';
 | 
				
			||||||
    static readonly GRADED_EVENT = 'addon_mod_assign_graded';
 | 
					    static readonly GRADED_EVENT = 'addon_mod_assign_graded';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    protected gradingOfflineEnabled: {[siteId: string]: boolean}  = {};
 | 
					    protected gradingOfflineEnabled: {[siteId: string]: boolean} = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Check if the user can submit in offline. This should only be used if submissionStatus.lastattempt.cansubmit cannot
 | 
					     * Check if the user can submit in offline. This should only be used if submissionStatus.lastattempt.cansubmit cannot
 | 
				
			||||||
@ -1302,7 +1302,7 @@ export class AddonModAssignProvider {
 | 
				
			|||||||
            );
 | 
					            );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            return true;
 | 
					            return true;
 | 
				
			||||||
        } catch (error)  {
 | 
					        } catch (error) {
 | 
				
			||||||
            if (error && !CoreUtils.isWebServiceError(error)) {
 | 
					            if (error && !CoreUtils.isWebServiceError(error)) {
 | 
				
			||||||
                // Couldn't connect to server, store in offline.
 | 
					                // Couldn't connect to server, store in offline.
 | 
				
			||||||
                return storeOffline();
 | 
					                return storeOffline();
 | 
				
			||||||
 | 
				
			|||||||
@ -79,7 +79,7 @@ export class AddonModAssignSubmissionFileComponent extends AddonModAssignSubmiss
 | 
				
			|||||||
                // No offline data, get the online files.
 | 
					                // No offline data, get the online files.
 | 
				
			||||||
                this.files = AddonModAssign.getSubmissionPluginAttachments(this.plugin);
 | 
					                this.files = AddonModAssign.getSubmissionPluginAttachments(this.plugin);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        } finally  {
 | 
					        } finally {
 | 
				
			||||||
            CoreFileSession.setFiles(this.component, this.assign.id, this.files);
 | 
					            CoreFileSession.setFiles(this.component, this.assign.id, this.files);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
    <nav>
 | 
					    <nav>
 | 
				
			||||||
        <ion-list>
 | 
					        <ion-list>
 | 
				
			||||||
            <ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)"
 | 
					            <ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)"
 | 
				
			||||||
                [attr.aria-current]="selected == chapter.id ? 'page' :  'false'" button
 | 
					                [attr.aria-current]="selected == chapter.id ? 'page' : 'false'" button
 | 
				
			||||||
                [class.item-dimmed]="chapter.hidden">
 | 
					                [class.item-dimmed]="chapter.hidden">
 | 
				
			||||||
                <ion-label>
 | 
					                <ion-label>
 | 
				
			||||||
                    <p [class.ion-padding-left]="addPadding && chapter.level == 1 ? true : null">
 | 
					                    <p [class.ion-padding-left]="addPadding && chapter.level == 1 ? true : null">
 | 
				
			||||||
 | 
				
			|||||||
@ -33,8 +33,8 @@ export class AddonModBookIndexLinkHandlerService extends CoreContentLinksModuleI
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the mod params necessary to open an activity.
 | 
					     * Get the mod params necessary to open an activity.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  url      The URL to treat.
 | 
					     * @param url      The URL to treat.
 | 
				
			||||||
     * @param  params   The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
 | 
					     * @param params   The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
 | 
				
			||||||
     * @return List of params to pass to navigateToModule / navigateToModuleByInstance.
 | 
					     * @return List of params to pass to navigateToModule / navigateToModuleByInstance.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getPageParams(url: string, params: Record<string, string>): Params {
 | 
					    getPageParams(url: string, params: Record<string, string>): Params {
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
					            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
				
			||||||
            [closeOnClick]="false">
 | 
					            [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -201,7 +201,7 @@ export class AddonModChatChatPage implements OnInit, OnDestroy {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get the user fullname for a beep.
 | 
					     * Get the user fullname for a beep.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  id User Id before parsing.
 | 
					     * @param id User Id before parsing.
 | 
				
			||||||
     * @return User fullname.
 | 
					     * @return User fullname.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async getUserFullname(id: string): Promise<string> {
 | 
					    protected async getUserFullname(id: string): Promise<string> {
 | 
				
			||||||
 | 
				
			|||||||
@ -120,7 +120,7 @@ export class AddonModChatSessionMessagesPage implements OnInit {
 | 
				
			|||||||
            return user.fullname;
 | 
					            return user.fullname;
 | 
				
			||||||
        } catch {
 | 
					        } catch {
 | 
				
			||||||
            // Error getting profile.
 | 
					            // Error getting profile.
 | 
				
			||||||
            return  id;
 | 
					            return id;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -109,7 +109,7 @@ export class AddonModChatHelperProvider {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Check if the date should be displayed between messages (when the day changes at midnight for example).
 | 
					     * Check if the date should be displayed between messages (when the day changes at midnight for example).
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param message  New message object.
 | 
					     * @param message New message object.
 | 
				
			||||||
     * @param prevMessage Previous message object.
 | 
					     * @param prevMessage Previous message object.
 | 
				
			||||||
     * @return True if messages are from diferent days, false othetwise.
 | 
					     * @return True if messages are from diferent days, false othetwise.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
					        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
				
			||||||
 | 
				
			|||||||
@ -346,7 +346,7 @@ export class AddonModChoiceProvider {
 | 
				
			|||||||
    async invalidateOptions(choiceId: number, siteId?: string): Promise<void> {
 | 
					    async invalidateOptions(choiceId: number, siteId?: string): Promise<void> {
 | 
				
			||||||
        const site = await CoreSites.getSite(siteId);
 | 
					        const site = await CoreSites.getSite(siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await  site.invalidateWsCacheForKey(this.getChoiceOptionsCacheKey(choiceId));
 | 
					        await site.invalidateWsCacheForKey(this.getChoiceOptionsCacheKey(choiceId));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
@ -359,7 +359,7 @@ export class AddonModChoiceProvider {
 | 
				
			|||||||
    async invalidateResults(choiceId: number, siteId?: string): Promise<void> {
 | 
					    async invalidateResults(choiceId: number, siteId?: string): Promise<void> {
 | 
				
			||||||
        const site = await CoreSites.getSite(siteId);
 | 
					        const site = await CoreSites.getSite(siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await  site.invalidateWsCacheForKey(this.getChoiceResultsCacheKey(choiceId));
 | 
					        await site.invalidateWsCacheForKey(this.getChoiceResultsCacheKey(choiceId));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,7 @@
 | 
				
			|||||||
    <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon>
 | 
					    <ion-icon name="fas-search" slot="icon-only" aria-hidden="true"></ion-icon>
 | 
				
			||||||
</ion-button>
 | 
					</ion-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<ion-button *ngIf="action == 'edit'" fill="clear" (click)="editEntry()"  [attr.aria-label]="'core.edit' | translate">
 | 
					<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-icon name="fas-cog" slot="icon-only" aria-hidden="true"></ion-icon>
 | 
				
			||||||
</ion-button>
 | 
					</ion-button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -27,8 +27,8 @@
 | 
				
			|||||||
component="mod_data" [itemId]="entry.id" area="database_entry" [courseId]="database.course">
 | 
					component="mod_data" [itemId]="entry.id" area="database_entry" [courseId]="database.course">
 | 
				
			||||||
</core-comments>
 | 
					</core-comments>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<span *ngIf="action == 'timeadded'">{{ entry.timecreated * 1000 |  coreFormatDate }}</span>
 | 
					<span *ngIf="action == 'timeadded'">{{ entry.timecreated * 1000 | coreFormatDate }}</span>
 | 
				
			||||||
<span *ngIf="action == 'timemodified'">{{ entry.timemodified * 1000 |  coreFormatDate }}</span>
 | 
					<span *ngIf="action == 'timemodified'">{{ entry.timemodified * 1000 | coreFormatDate }}</span>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<a *ngIf="action == 'userpicture'" core-user-link [courseId]="database.course" [userId]="entry.userid" [title]="entry.fullname">
 | 
					<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
 | 
					    <img class="avatar-round" [src]="userPicture" [alt]="'core.pictureof' | translate:{$a: entry.fullname}" core-external-content
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
            [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon"
 | 
					            [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon"
 | 
				
			||||||
            [closeOnClick]="false">
 | 
					            [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline"  [priority]="600"
 | 
					        <core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="600"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
					            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
				
			||||||
            [closeOnClick]="false">
 | 
					            [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -87,7 +87,7 @@ export class AddonModDataIndexComponent extends CoreCourseModuleMainActivityComp
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    hasNextPage = false;
 | 
					    hasNextPage = false;
 | 
				
			||||||
    entriesRendered = '';
 | 
					    entriesRendered = '';
 | 
				
			||||||
    extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule];
 | 
					    extraImports: Type<unknown>[] = [AddonModDataComponentsCompileModule];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    jsData?: {
 | 
					    jsData?: {
 | 
				
			||||||
        fields: Record<number, AddonModDataField>;
 | 
					        fields: Record<number, AddonModDataField>;
 | 
				
			||||||
 | 
				
			|||||||
@ -17,7 +17,7 @@
 | 
				
			|||||||
        <ion-toggle [(ngModel)]="search.searchingAdvanced"></ion-toggle>
 | 
					        <ion-toggle [(ngModel)]="search.searchingAdvanced"></ion-toggle>
 | 
				
			||||||
    </ion-item>
 | 
					    </ion-item>
 | 
				
			||||||
    <form (ngSubmit)="searchEntries($event)" [formGroup]="searchForm" #searchFormEl>
 | 
					    <form (ngSubmit)="searchEntries($event)" [formGroup]="searchForm" #searchFormEl>
 | 
				
			||||||
        <ion-list  class="ion-no-margin">
 | 
					        <ion-list class="ion-no-margin">
 | 
				
			||||||
            <ion-item [hidden]="search.searchingAdvanced">
 | 
					            <ion-item [hidden]="search.searchingAdvanced">
 | 
				
			||||||
                <ion-label></ion-label>
 | 
					                <ion-label></ion-label>
 | 
				
			||||||
                <ion-input type="text" placeholder="{{ 'addon.mod_data.search' | translate}}"
 | 
					                <ion-input type="text" placeholder="{{ 'addon.mod_data.search' | translate}}"
 | 
				
			||||||
 | 
				
			|||||||
@ -49,7 +49,7 @@ export class AddonModDataSearchComponent implements OnInit {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    advancedSearch = '';
 | 
					    advancedSearch = '';
 | 
				
			||||||
    advancedIndexed: CoreFormFields = {};
 | 
					    advancedIndexed: CoreFormFields = {};
 | 
				
			||||||
    extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule];
 | 
					    extraImports: Type<unknown>[] = [AddonModDataComponentsCompileModule];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    searchForm: FormGroup;
 | 
					    searchForm: FormGroup;
 | 
				
			||||||
    jsData?: {
 | 
					    jsData?: {
 | 
				
			||||||
 | 
				
			|||||||
@ -93,7 +93,7 @@ export class AddonModDataFieldDateHandlerService implements AddonModDataFieldHan
 | 
				
			|||||||
            {
 | 
					            {
 | 
				
			||||||
                fieldid: field.id,
 | 
					                fieldid: field.id,
 | 
				
			||||||
                subfield: 'year',
 | 
					                subfield: 'year',
 | 
				
			||||||
                value:  date[0],
 | 
					                value: date[0],
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                fieldid: field.id,
 | 
					                fieldid: field.id,
 | 
				
			||||||
 | 
				
			|||||||
@ -78,14 +78,14 @@ export class AddonModDataFieldFileHandlerService implements AddonModDataFieldHan
 | 
				
			|||||||
     * @inheritdoc
 | 
					     * @inheritdoc
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getFieldEditFiles(field: AddonModDataField): CoreFileEntry[] {
 | 
					    getFieldEditFiles(field: AddonModDataField): CoreFileEntry[] {
 | 
				
			||||||
        return CoreFileSession.getFiles(AddonModDataProvider.COMPONENT,  field.dataid + '_' + field.id);
 | 
					        return CoreFileSession.getFiles(AddonModDataProvider.COMPONENT, field.dataid + '_' + field.id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * @inheritdoc
 | 
					     * @inheritdoc
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    hasFieldDataChanged(field: AddonModDataField, inputData: CoreFormFields, originalFieldData: AddonModDataEntryField): boolean {
 | 
					    hasFieldDataChanged(field: AddonModDataField, inputData: CoreFormFields, originalFieldData: AddonModDataEntryField): boolean {
 | 
				
			||||||
        const files = CoreFileSession.getFiles(AddonModDataProvider.COMPONENT,  field.dataid + '_' + field.id) || [];
 | 
					        const files = CoreFileSession.getFiles(AddonModDataProvider.COMPONENT, field.dataid + '_' + field.id) || [];
 | 
				
			||||||
        let originalFiles = (originalFieldData && originalFieldData.files) || [];
 | 
					        let originalFiles = (originalFieldData && originalFieldData.files) || [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (originalFiles.length) {
 | 
					        if (originalFiles.length) {
 | 
				
			||||||
 | 
				
			|||||||
@ -146,7 +146,7 @@ export class AddonModDataFieldLatlongComponent extends AddonModDataFieldPluginCo
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        CoreDomUtils.showErrorModalDefault(error,  'Error getting location');
 | 
					        CoreDomUtils.showErrorModalDefault(error, 'Error getting location');
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -133,7 +133,7 @@ export class AddonModDataFieldPictureComponent extends AddonModDataFieldPluginCo
 | 
				
			|||||||
                }
 | 
					                }
 | 
				
			||||||
            }, 1);
 | 
					            }, 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            this.width  = CoreDomUtils.formatPixelsSize(this.field.param1);
 | 
					            this.width = CoreDomUtils.formatPixelsSize(this.field.param1);
 | 
				
			||||||
            this.height = CoreDomUtils.formatPixelsSize(this.field.param2);
 | 
					            this.height = CoreDomUtils.formatPixelsSize(this.field.param2);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,7 @@ export class AddonModDataFieldPictureHandlerService implements AddonModDataField
 | 
				
			|||||||
     * @inheritdoc
 | 
					     * @inheritdoc
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    getFieldEditFiles(field: AddonModDataField): CoreFileEntry[] {
 | 
					    getFieldEditFiles(field: AddonModDataField): CoreFileEntry[] {
 | 
				
			||||||
        return CoreFileSession.getFiles(AddonModDataProvider.COMPONENT,  field.dataid + '_' + field.id);
 | 
					        return CoreFileSession.getFiles(AddonModDataProvider.COMPONENT, field.dataid + '_' + field.id);
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -76,7 +76,7 @@ export class AddonModDataEditPage implements OnInit {
 | 
				
			|||||||
    groupInfo?: CoreGroupInfo;
 | 
					    groupInfo?: CoreGroupInfo;
 | 
				
			||||||
    editFormRender = '';
 | 
					    editFormRender = '';
 | 
				
			||||||
    editForm: FormGroup;
 | 
					    editForm: FormGroup;
 | 
				
			||||||
    extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule];
 | 
					    extraImports: Type<unknown>[] = [AddonModDataComponentsCompileModule];
 | 
				
			||||||
    jsData?: {
 | 
					    jsData?: {
 | 
				
			||||||
        fields: Record<number, AddonModDataField>;
 | 
					        fields: Record<number, AddonModDataField>;
 | 
				
			||||||
        database?: AddonModDataData;
 | 
					        database?: AddonModDataData;
 | 
				
			||||||
 | 
				
			|||||||
@ -77,7 +77,7 @@ export class AddonModDataEntryPage implements OnInit, OnDestroy {
 | 
				
			|||||||
    showComments = false;
 | 
					    showComments = false;
 | 
				
			||||||
    entryHtml = '';
 | 
					    entryHtml = '';
 | 
				
			||||||
    siteId: string;
 | 
					    siteId: string;
 | 
				
			||||||
    extraImports: Type<unknown>[]  = [AddonModDataComponentsCompileModule];
 | 
					    extraImports: Type<unknown>[] = [AddonModDataComponentsCompileModule];
 | 
				
			||||||
    jsData?: {
 | 
					    jsData?: {
 | 
				
			||||||
        fields: Record<number, AddonModDataField>;
 | 
					        fields: Record<number, AddonModDataField>;
 | 
				
			||||||
        entries: Record<number, AddonModDataEntry>;
 | 
					        entries: Record<number, AddonModDataEntry>;
 | 
				
			||||||
 | 
				
			|||||||
@ -399,7 +399,7 @@ export class AddonModDataHelperProvider {
 | 
				
			|||||||
        database: AddonModDataData,
 | 
					        database: AddonModDataData,
 | 
				
			||||||
        accessInfo: AddonModDataGetDataAccessInformationWSResponse,
 | 
					        accessInfo: AddonModDataGetDataAccessInformationWSResponse,
 | 
				
			||||||
        entry: AddonModDataEntry,
 | 
					        entry: AddonModDataEntry,
 | 
				
			||||||
    ):  Record<AddonModDataAction, boolean> {
 | 
					    ): Record<AddonModDataAction, boolean> {
 | 
				
			||||||
        return {
 | 
					        return {
 | 
				
			||||||
            add: false, // Not directly used on entries.
 | 
					            add: false, // Not directly used on entries.
 | 
				
			||||||
            more: true,
 | 
					            more: true,
 | 
				
			||||||
@ -719,7 +719,7 @@ export class AddonModDataHelperProvider {
 | 
				
			|||||||
                // Ignore errors.
 | 
					                // Ignore errors.
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            CoreEvents.trigger(AddonModDataProvider.ENTRY_CHANGED, { dataId, entryId,  deleted: true }, siteId);
 | 
					            CoreEvents.trigger(AddonModDataProvider.ENTRY_CHANGED, { dataId, entryId, deleted: true }, siteId);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            CoreDomUtils.showToast('addon.mod_data.recorddeleted', true, 3000);
 | 
					            CoreDomUtils.showToast('addon.mod_data.recorddeleted', true, 3000);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -481,7 +481,7 @@ export type AddonModDataSyncResult = {
 | 
				
			|||||||
    updated: boolean; // Whether some data was sent to the server or offline data was updated.
 | 
					    updated: boolean; // Whether some data was sent to the server or offline data was updated.
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export type AddonModDataAutoSyncData =  {
 | 
					export type AddonModDataAutoSyncData = {
 | 
				
			||||||
    dataId: number;
 | 
					    dataId: number;
 | 
				
			||||||
    warnings: string[];
 | 
					    warnings: string[];
 | 
				
			||||||
    entryId?: number;
 | 
					    entryId?: number;
 | 
				
			||||||
 | 
				
			|||||||
@ -635,7 +635,7 @@ export class AddonModDataProvider {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get  access information for a given database.
 | 
					     * Get access information for a given database.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param dataId Data ID.
 | 
					     * @param dataId Data ID.
 | 
				
			||||||
     * @param options Other options.
 | 
					     * @param options Other options.
 | 
				
			||||||
@ -1304,7 +1304,7 @@ type AddonModDataDeleteEntryWSParams = {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
type AddonModDataUpdateEntryWSParams = {
 | 
					type AddonModDataUpdateEntryWSParams = {
 | 
				
			||||||
    entryid: number; // The entry record id.
 | 
					    entryid: number; // The entry record id.
 | 
				
			||||||
    data: AddonModDataEntryWSField[];  // The fields data to be updated.
 | 
					    data: AddonModDataEntryWSField[]; // The fields data to be updated.
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
					        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
				
			||||||
 | 
				
			|||||||
@ -38,7 +38,7 @@
 | 
				
			|||||||
                        <ion-label>
 | 
					                        <ion-label>
 | 
				
			||||||
                            <h2 *ngIf="item.name" [core-mark-required]="item.required">
 | 
					                            <h2 *ngIf="item.name" [core-mark-required]="item.required">
 | 
				
			||||||
                                <span *ngIf="feedback!.autonumbering && item.itemnumber">{{item.itemnumber}}. </span>
 | 
					                                <span *ngIf="feedback!.autonumbering && item.itemnumber">{{item.itemnumber}}. </span>
 | 
				
			||||||
                                <core-format-text  [component]="component" [componentId]="cmId" [text]="item.name"
 | 
					                                <core-format-text [component]="component" [componentId]="cmId" [text]="item.name"
 | 
				
			||||||
                                    contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
 | 
					                                    contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
 | 
				
			||||||
                                </core-format-text>
 | 
					                                </core-format-text>
 | 
				
			||||||
                            </h2>
 | 
					                            </h2>
 | 
				
			||||||
 | 
				
			|||||||
@ -75,7 +75,7 @@
 | 
				
			|||||||
                            [required]="item.required" name="{{item.typ}}_{{item.id}}">
 | 
					                            [required]="item.required" name="{{item.typ}}_{{item.id}}">
 | 
				
			||||||
                            <ion-item *ngFor="let option of item.choices">
 | 
					                            <ion-item *ngFor="let option of item.choices">
 | 
				
			||||||
                                <ion-label>
 | 
					                                <ion-label>
 | 
				
			||||||
                                    <core-format-text  [component]="component" [componentId]="cmId"
 | 
					                                    <core-format-text [component]="component" [componentId]="cmId"
 | 
				
			||||||
                                        [text]="option.label" contextLevel="module" [contextInstanceId]="cmId"
 | 
					                                        [text]="option.label" contextLevel="module" [contextInstanceId]="cmId"
 | 
				
			||||||
                                        [wsNotFiltered]="true" [courseId]="courseId">
 | 
					                                        [wsNotFiltered]="true" [courseId]="courseId">
 | 
				
			||||||
                                    </core-format-text>
 | 
					                                    </core-format-text>
 | 
				
			||||||
@ -146,7 +146,7 @@
 | 
				
			|||||||
                        {{ 'addon.mod_feedback.feedback_submitted_offline' | translate }}
 | 
					                        {{ 'addon.mod_feedback.feedback_submitted_offline' | translate }}
 | 
				
			||||||
                    </p>
 | 
					                    </p>
 | 
				
			||||||
                    <p *ngIf="completionPageContents">
 | 
					                    <p *ngIf="completionPageContents">
 | 
				
			||||||
                        <core-format-text  [component]="component" componentId="componentId" [text]="completionPageContents"
 | 
					                        <core-format-text [component]="component" componentId="componentId" [text]="completionPageContents"
 | 
				
			||||||
                            contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
 | 
					                            contextLevel="module" [contextInstanceId]="cmId" [courseId]="courseId">
 | 
				
			||||||
                        </core-format-text>
 | 
					                        </core-format-text>
 | 
				
			||||||
                    </p>
 | 
					                    </p>
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
            <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
					            <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
 | 
				
			||||||
        </ion-refresher>
 | 
					        </ion-refresher>
 | 
				
			||||||
        <core-loading [hideUntil]="loaded">
 | 
					        <core-loading [hideUntil]="loaded">
 | 
				
			||||||
            <ion-list  class="ion-no-margin">
 | 
					            <ion-list class="ion-no-margin">
 | 
				
			||||||
                <ion-item class="ion-text-wrap" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)">
 | 
					                <ion-item class="ion-text-wrap" *ngIf="groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)">
 | 
				
			||||||
                    <ion-label id="addon-feedback-groupslabel">
 | 
					                    <ion-label id="addon-feedback-groupslabel">
 | 
				
			||||||
                        <ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
 | 
					                        <ng-container *ngIf="groupInfo.separateGroups">{{'core.groupsseparate' | translate }}</ng-container>
 | 
				
			||||||
 | 
				
			|||||||
@ -117,7 +117,7 @@ export class AddonModFeedbackHelperProvider {
 | 
				
			|||||||
                    if (itemData.typ == 'multichoice' || itemData.typ == 'multichoicerated') {
 | 
					                    if (itemData.typ == 'multichoice' || itemData.typ == 'multichoicerated') {
 | 
				
			||||||
                        value = itemData.value || 0;
 | 
					                        value = itemData.value || 0;
 | 
				
			||||||
                    } else if (this.isNumericItem(itemData)) {
 | 
					                    } else if (this.isNumericItem(itemData)) {
 | 
				
			||||||
                        value = itemData.value || itemData.value  == 0 ? itemData.value : '';
 | 
					                        value = itemData.value || itemData.value == 0 ? itemData.value : '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (value != '') {
 | 
					                        if (value != '') {
 | 
				
			||||||
                            if ((itemData.rangefrom != '' && value < itemData.rangefrom) ||
 | 
					                            if ((itemData.rangefrom != '' && value < itemData.rangefrom) ||
 | 
				
			||||||
@ -126,7 +126,7 @@ export class AddonModFeedbackHelperProvider {
 | 
				
			|||||||
                            }
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
                    } else {
 | 
					                    } else {
 | 
				
			||||||
                        value = itemData.value || itemData.value  == 0 ? itemData.value : '';
 | 
					                        value = itemData.value || itemData.value == 0 ? itemData.value : '';
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    answered = !!value;
 | 
					                    answered = !!value;
 | 
				
			||||||
 | 
				
			|||||||
@ -511,7 +511,7 @@ export class AddonModFeedbackProvider {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Get  access information for a given feedback.
 | 
					     * Get access information for a given feedback.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param feedbackId Feedback ID.
 | 
					     * @param feedbackId Feedback ID.
 | 
				
			||||||
     * @param options Other options.
 | 
					     * @param options Other options.
 | 
				
			||||||
 | 
				
			|||||||
@ -255,7 +255,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges
 | 
				
			|||||||
            componentProps: {
 | 
					            componentProps: {
 | 
				
			||||||
                post: this.post,
 | 
					                post: this.post,
 | 
				
			||||||
                component: this.component,
 | 
					                component: this.component,
 | 
				
			||||||
                componentId:  this.componentId,
 | 
					                componentId: this.componentId,
 | 
				
			||||||
                forum: this.forum,
 | 
					                forum: this.forum,
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            backdropDismiss: false,
 | 
					            backdropDismiss: false,
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
    <ion-list id="addon-mod-forum-sort-selector" role="listbox" aria-labelledby="addon-mod-forum-sort-order-label">
 | 
					    <ion-list id="addon-mod-forum-sort-selector" role="listbox" aria-labelledby="addon-mod-forum-sort-order-label">
 | 
				
			||||||
        <ng-container *ngFor="let sortOrder of sortOrders">
 | 
					        <ng-container *ngFor="let sortOrder of sortOrders">
 | 
				
			||||||
            <ion-item class="ion-text-wrap" detail="false" role="combobox"
 | 
					            <ion-item class="ion-text-wrap" detail="false" role="combobox"
 | 
				
			||||||
                [attr.aria-current]="selected == sortOrder.value ? 'page' :  'false'" [attr.aria-label]="sortOrder.label | translate"
 | 
					                [attr.aria-current]="selected == sortOrder.value ? 'page' : 'false'" [attr.aria-label]="sortOrder.label | translate"
 | 
				
			||||||
                (click)="selectSortOrder(sortOrder)" button aria-haspopup="dialog">
 | 
					                (click)="selectSortOrder(sortOrder)" button aria-haspopup="dialog">
 | 
				
			||||||
                <ion-label>
 | 
					                <ion-label>
 | 
				
			||||||
                    <h2>{{ sortOrder.label | translate }}</h2>
 | 
					                    <h2>{{ sortOrder.label | translate }}</h2>
 | 
				
			||||||
 | 
				
			|||||||
@ -89,7 +89,7 @@
 | 
				
			|||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
        </ion-card>
 | 
					        </ion-card>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        <div *ngIf="startingPost"  class="ion-margin-bottom">
 | 
					        <div *ngIf="startingPost" class="ion-margin-bottom">
 | 
				
			||||||
            <addon-mod-forum-post
 | 
					            <addon-mod-forum-post
 | 
				
			||||||
                [post]="startingPost" [discussion]="discussion" [courseId]="courseId" [highlight]="true"
 | 
					                [post]="startingPost" [discussion]="discussion" [courseId]="courseId" [highlight]="true"
 | 
				
			||||||
                [discussionId]="discussionId" [component]="component" [componentId]="cmId"
 | 
					                [discussionId]="discussionId" [component]="component" [componentId]="cmId"
 | 
				
			||||||
 | 
				
			|||||||
@ -531,9 +531,9 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Convenience function to load discussion.
 | 
					     * Convenience function to load discussion.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  forumId Forum ID.
 | 
					     * @param forumId Forum ID.
 | 
				
			||||||
     * @param  cmId Forum cmid.
 | 
					     * @param cmId Forum cmid.
 | 
				
			||||||
     * @param  discussionId Discussion ID.
 | 
					     * @param discussionId Discussion ID.
 | 
				
			||||||
     * @return Promise resolved when done.
 | 
					     * @return Promise resolved when done.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected async loadDiscussion(forumId: number, cmId: number, discussionId: number): Promise<void> {
 | 
					    protected async loadDiscussion(forumId: number, cmId: number, discussionId: number): Promise<void> {
 | 
				
			||||||
 | 
				
			|||||||
@ -465,7 +465,7 @@ export class AddonModForumNewDiscussionPage implements OnInit, OnDestroy, CanLea
 | 
				
			|||||||
    async add(): Promise<void> {
 | 
					    async add(): Promise<void> {
 | 
				
			||||||
        const forumName = this.forum.name;
 | 
					        const forumName = this.forum.name;
 | 
				
			||||||
        const subject = this.newDiscussion.subject;
 | 
					        const subject = this.newDiscussion.subject;
 | 
				
			||||||
        let  message = this.newDiscussion.message || '';
 | 
					        let message = this.newDiscussion.message || '';
 | 
				
			||||||
        const pin = this.newDiscussion.pin;
 | 
					        const pin = this.newDiscussion.pin;
 | 
				
			||||||
        const attachments = this.newDiscussion.files;
 | 
					        const attachments = this.newDiscussion.files;
 | 
				
			||||||
        const discTimecreated = this.timeCreated || Date.now();
 | 
					        const discTimecreated = this.timeCreated || Date.now();
 | 
				
			||||||
 | 
				
			|||||||
@ -145,7 +145,7 @@ export class AddonModForumModuleHandlerService implements CoreCourseModuleHandle
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        data.extraBadge =  Translate.instant('core.loading');
 | 
					        data.extraBadge = Translate.instant('core.loading');
 | 
				
			||||||
        data.extraBadgeColor = 'light';
 | 
					        data.extraBadgeColor = 'light';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await CoreUtils.ignoreErrors(AddonModForum.invalidateForumData(courseId));
 | 
					        await CoreUtils.ignoreErrors(AddonModForum.invalidateForumData(courseId));
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
    <nav>
 | 
					    <nav>
 | 
				
			||||||
        <ion-list>
 | 
					        <ion-list>
 | 
				
			||||||
            <ion-item *ngFor="let item of items" (click)="loadItem(item.href)"
 | 
					            <ion-item *ngFor="let item of items" (click)="loadItem(item.href)"
 | 
				
			||||||
                [attr.aria-current]="selected == item.href ? 'page' :  'false'" button>
 | 
					                [attr.aria-current]="selected == item.href ? 'page' : 'false'" button>
 | 
				
			||||||
                <ion-label [class.core-bold]="!item.href">
 | 
					                <ion-label [class.core-bold]="!item.href">
 | 
				
			||||||
                    <span class="ion-padding-left" *ngFor="let i of getNumberForPadding(item.level)"></span>{{item.title}}
 | 
					                    <span class="ion-padding-left" *ngFor="let i of getNumberForPadding(item.level)"></span>{{item.title}}
 | 
				
			||||||
                </ion-label>
 | 
					                </ion-label>
 | 
				
			||||||
 | 
				
			|||||||
@ -144,7 +144,7 @@ export class AddonModImscpProvider {
 | 
				
			|||||||
     * @return Cache key.
 | 
					     * @return Cache key.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected getImscpDataCacheKey(courseId: number): string {
 | 
					    protected getImscpDataCacheKey(courseId: number): string {
 | 
				
			||||||
        return ROOT_CACHE_KEY +  'imscp:' + courseId;
 | 
					        return ROOT_CACHE_KEY + 'imscp:' + courseId;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
					        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
				
			||||||
 | 
				
			|||||||
@ -195,7 +195,7 @@ export class AddonModLessonIndexComponent extends CoreCourseModuleMainActivityCo
 | 
				
			|||||||
                        this.preventReasons = [preventReason!];
 | 
					                        this.preventReasons = [preventReason!];
 | 
				
			||||||
                        lessonReady = false;
 | 
					                        lessonReady = false;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                } else  {
 | 
					                } else {
 | 
				
			||||||
                    // Lesson cannot be started.
 | 
					                    // Lesson cannot be started.
 | 
				
			||||||
                    this.preventReasons = [preventReason!];
 | 
					                    this.preventReasons = [preventReason!];
 | 
				
			||||||
                    lessonReady = false;
 | 
					                    lessonReady = false;
 | 
				
			||||||
 | 
				
			|||||||
@ -884,7 +884,7 @@ export class AddonModLessonProvider {
 | 
				
			|||||||
                // Answer found.
 | 
					                // Answer found.
 | 
				
			||||||
                result.correctanswer = this.isAnswerCorrect(lesson, pageData.page!.id, answer, pageIndex);
 | 
					                result.correctanswer = this.isAnswerCorrect(lesson, pageData.page!.id, answer, pageIndex);
 | 
				
			||||||
                result.newpageid = answer.jumpto || 0;
 | 
					                result.newpageid = answer.jumpto || 0;
 | 
				
			||||||
                result.response  = answer.response || '';
 | 
					                result.response = answer.response || '';
 | 
				
			||||||
                result.studentanswer = result.userresponse = answer.answer || '';
 | 
					                result.studentanswer = result.userresponse = answer.answer || '';
 | 
				
			||||||
                break;
 | 
					                break;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
@ -3195,7 +3195,7 @@ export class AddonModLessonProvider {
 | 
				
			|||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let nAttempts: number | undefined;
 | 
					        let nAttempts: number | undefined;
 | 
				
			||||||
        result.attemptsremaining  = 0;
 | 
					        result.attemptsremaining = 0;
 | 
				
			||||||
        result.maxattemptsreached = false;
 | 
					        result.maxattemptsreached = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if (result.noanswer) {
 | 
					        if (result.noanswer) {
 | 
				
			||||||
@ -3902,7 +3902,7 @@ export type AddonModLessonGetPagesWSResponse = {
 | 
				
			|||||||
 */
 | 
					 */
 | 
				
			||||||
export type AddonModLessonGetPagesPageWSData = {
 | 
					export type AddonModLessonGetPagesPageWSData = {
 | 
				
			||||||
    page: AddonModLessonPageWSData; // Page fields.
 | 
					    page: AddonModLessonPageWSData; // Page fields.
 | 
				
			||||||
    answerids: number[]; // List of answers ids (empty for content pages in  Moodle 1.9).
 | 
					    answerids: number[]; // List of answers ids (empty for content pages in Moodle 1.9).
 | 
				
			||||||
    jumps: number[]; // List of possible page jumps.
 | 
					    jumps: number[]; // List of possible page jumps.
 | 
				
			||||||
    filescount: number; // The total number of files attached to the page.
 | 
					    filescount: number; // The total number of files attached to the page.
 | 
				
			||||||
    filessizetotal: number; // The total size of the files.
 | 
					    filessizetotal: number; // The total size of the files.
 | 
				
			||||||
 | 
				
			|||||||
@ -119,7 +119,7 @@ export class AddonModLtiModuleHandlerService implements CoreCourseModuleHandler
 | 
				
			|||||||
        const siteId = CoreSites.getCurrentSiteId();
 | 
					        const siteId = CoreSites.getCurrentSiteId();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        try {
 | 
					        try {
 | 
				
			||||||
            await CoreFilepool.downloadUrl(siteId,  icon, false, AddonModLtiProvider.COMPONENT, module.id);
 | 
					            await CoreFilepool.downloadUrl(siteId, icon, false, AddonModLtiProvider.COMPONENT, module.id);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            // Get the internal URL.
 | 
					            // Get the internal URL.
 | 
				
			||||||
            const url = await CoreFilepool.getSrcByUrl(siteId, icon, AddonModLtiProvider.COMPONENT, module.id);
 | 
					            const url = await CoreFilepool.getSrcByUrl(siteId, icon, AddonModLtiProvider.COMPONENT, module.id);
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
					        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
				
			||||||
 | 
				
			|||||||
@ -176,7 +176,7 @@ export class AddonModQuizHelperProvider {
 | 
				
			|||||||
            throw new CoreCanceledError();
 | 
					            throw new CoreCanceledError();
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return  modalData;
 | 
					        return modalData;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    /**
 | 
					    /**
 | 
				
			||||||
 | 
				
			|||||||
@ -2042,7 +2042,7 @@ export type AddonModQuizAttemptWSData = {
 | 
				
			|||||||
    timefinish?: number; // Time when the attempt was submitted. 0 if the attempt has not been submitted yet.
 | 
					    timefinish?: number; // Time when the attempt was submitted. 0 if the attempt has not been submitted yet.
 | 
				
			||||||
    timemodified?: number; // Last modified time.
 | 
					    timemodified?: number; // Last modified time.
 | 
				
			||||||
    timemodifiedoffline?: number; // Last modified time via webservices.
 | 
					    timemodifiedoffline?: number; // Last modified time via webservices.
 | 
				
			||||||
    timecheckstate?: number; // Next time quiz cron should check attempt for state changes.  NULL means never check.
 | 
					    timecheckstate?: number; // Next time quiz cron should check attempt for state changes. NULL means never check.
 | 
				
			||||||
    sumgrades?: number | null; // Total marks for this attempt.
 | 
					    sumgrades?: number | null; // Total marks for this attempt.
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" (action)="doRefresh(null, $event, true)"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					            [content]="'core.settings.synchronizenow' | translate" [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
					        <core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)"
 | 
				
			||||||
 | 
				
			|||||||
@ -31,7 +31,7 @@
 | 
				
			|||||||
            <ng-container *ngFor="let sco of toc">
 | 
					            <ng-container *ngFor="let sco of toc">
 | 
				
			||||||
                <ion-item *ngIf="sco.isvisible" class="ion-text-wrap" [detail]="sco.prereq && sco.launch"
 | 
					                <ion-item *ngIf="sco.isvisible" class="ion-text-wrap" [detail]="sco.prereq && sco.launch"
 | 
				
			||||||
                    [ngClass]="'core-padding-' + sco.level + ' addon-mod_scorm-type-' + sco.scormtype"
 | 
					                    [ngClass]="'core-padding-' + sco.level + ' addon-mod_scorm-type-' + sco.scormtype"
 | 
				
			||||||
                    [attr.aria-current]="selected == sco.id ? 'page' :  'false'" (click)="loadSco(sco)"
 | 
					                    [attr.aria-current]="selected == sco.id ? 'page' : 'false'" (click)="loadSco(sco)"
 | 
				
			||||||
                    [disabled]="!sco.prereq || !sco.launch ? true : null" [button]="sco.prereq && sco.launch">
 | 
					                    [disabled]="!sco.prereq || !sco.launch ? true : null" [button]="sco.prereq && sco.launch">
 | 
				
			||||||
                    <ion-icon *ngIf="sco.icon" [name]="sco.icon.icon" [attr.aria-label]="sco.icon.description" slot="start">
 | 
					                    <ion-icon *ngIf="sco.icon" [name]="sco.icon.icon" [attr.aria-label]="sco.icon.description" slot="start">
 | 
				
			||||||
                    </ion-icon>
 | 
					                    </ion-icon>
 | 
				
			||||||
 | 
				
			|||||||
@ -893,7 +893,7 @@ export class AddonModScormProvider {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        const data = await this.getScormUserData(scormId, attempt, userDataOptions);
 | 
					        const data = await this.getScormUserData(scormId, attempt, userDataOptions);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const trackDataBySCO: Record<string, Record<string, AddonModScormDataValue>>  = {};
 | 
					        const trackDataBySCO: Record<string, Record<string, AddonModScormDataValue>> = {};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        // First populate trackDataBySCO to index by SCO identifier.
 | 
					        // First populate trackDataBySCO to index by SCO identifier.
 | 
				
			||||||
        // We want the full list first because it's needed by evalPrerequisites.
 | 
					        // We want the full list first because it's needed by evalPrerequisites.
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)"
 | 
					            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)"
 | 
				
			||||||
            [iconAction]="syncIcon" [closeOnClick]="false">
 | 
					            [iconAction]="syncIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -21,7 +21,7 @@
 | 
				
			|||||||
                    <ion-label><h2>{{ letter.label }}</h2></ion-label>
 | 
					                    <ion-label><h2>{{ letter.label }}</h2></ion-label>
 | 
				
			||||||
                </ion-item-divider>
 | 
					                </ion-item-divider>
 | 
				
			||||||
                <ion-item class="ion-text-wrap" *ngFor="let page of letter.pages" (click)="goToPage(page)"
 | 
					                <ion-item class="ion-text-wrap" *ngFor="let page of letter.pages" (click)="goToPage(page)"
 | 
				
			||||||
                    [attr.aria-current]="selectedTitle == page.title ? 'page' :  'false'" button>
 | 
					                    [attr.aria-current]="selectedTitle == page.title ? 'page' : 'false'" button>
 | 
				
			||||||
                    <ion-icon name="fas-home" slot="start" *ngIf="page.firstpage" aria-hidden="true"></ion-icon>
 | 
					                    <ion-icon name="fas-home" slot="start" *ngIf="page.firstpage" aria-hidden="true"></ion-icon>
 | 
				
			||||||
                    <ion-label>
 | 
					                    <ion-label>
 | 
				
			||||||
                        <core-format-text [text]="page.title" contextLevel="module" [contextInstanceId]="moduleId"
 | 
					                        <core-format-text [text]="page.title" contextLevel="module" [contextInstanceId]="moduleId"
 | 
				
			||||||
 | 
				
			|||||||
@ -6,7 +6,7 @@
 | 
				
			|||||||
        <ion-item class="ion-text-wrap" *ngFor="let subwiki of group.subwikis" (click)="openSubwiki(subwiki)"
 | 
					        <ion-item class="ion-text-wrap" *ngFor="let subwiki of group.subwikis" (click)="openSubwiki(subwiki)"
 | 
				
			||||||
            [attr.disabled]="!subwiki.canedit && subwiki.id <= 0"
 | 
					            [attr.disabled]="!subwiki.canedit && subwiki.id <= 0"
 | 
				
			||||||
            [button]="subwiki.canedit || subwiki.id > 0"
 | 
					            [button]="subwiki.canedit || subwiki.id > 0"
 | 
				
			||||||
            [attr.aria-current]="isSubwikiSelected(subwiki) ? 'page' :  'false'" detail="false">
 | 
					            [attr.aria-current]="isSubwikiSelected(subwiki) ? 'page' : 'false'" detail="false">
 | 
				
			||||||
            <ion-label>{{ subwiki.name }}</ion-label>
 | 
					            <ion-label>{{ subwiki.name }}</ion-label>
 | 
				
			||||||
            <ion-icon *ngIf="isSubwikiSelected(subwiki)" name="fas-check" slot="end" aria-hidden="true"></ion-icon>
 | 
					            <ion-icon *ngIf="isSubwikiSelected(subwiki)" name="fas-check" slot="end" aria-hidden="true"></ion-icon>
 | 
				
			||||||
        </ion-item>
 | 
					        </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -115,7 +115,7 @@ export class AddonModWorkshopAssessmentStrategyAccumulativeHandlerService implem
 | 
				
			|||||||
        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
					        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
				
			||||||
        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
					        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
				
			||||||
    ): Promise<CoreFormFields> {
 | 
					    ): Promise<CoreFormFields> {
 | 
				
			||||||
        const data: CoreFormFields =  {};
 | 
					        const data: CoreFormFields = {};
 | 
				
			||||||
        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
					        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
				
			||||||
        let hasErrors = false;
 | 
					        let hasErrors = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -135,7 +135,7 @@ export class AddonModWorkshopAssessmentStrategyAccumulativeHandlerService implem
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
 | 
					                data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
 | 
				
			||||||
                data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
 | 
					                data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
 | 
				
			||||||
                data['weight__idx_' + idx] = parseInt(field.weight, 10) ||  0;
 | 
					                data['weight__idx_' + idx] = parseInt(field.weight, 10) || 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -94,7 +94,7 @@ export class AddonModWorkshopAssessmentStrategyCommentsHandlerService implements
 | 
				
			|||||||
        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
					        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
				
			||||||
        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
					        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
				
			||||||
    ): Promise<CoreFormFields> {
 | 
					    ): Promise<CoreFormFields> {
 | 
				
			||||||
        const data: CoreFormFields =  {};
 | 
					        const data: CoreFormFields = {};
 | 
				
			||||||
        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
					        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
				
			||||||
        let hasErrors = false;
 | 
					        let hasErrors = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -66,7 +66,7 @@ export class AddonModWorkshopAssessmentStrategyNumErrorsHandlerService implement
 | 
				
			|||||||
            originalValues[n] = {};
 | 
					            originalValues[n] = {};
 | 
				
			||||||
            originalValues[n].peercomment = form.current[n].peercomment || '';
 | 
					            originalValues[n].peercomment = form.current[n].peercomment || '';
 | 
				
			||||||
            originalValues[n].number = field.number; // eslint-disable-line id-blacklist
 | 
					            originalValues[n].number = field.number; // eslint-disable-line id-blacklist
 | 
				
			||||||
            originalValues[n].grade  = form.current[n].grade || '';
 | 
					            originalValues[n].grade = form.current[n].grade || '';
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return originalValues;
 | 
					        return originalValues;
 | 
				
			||||||
@ -98,7 +98,7 @@ export class AddonModWorkshopAssessmentStrategyNumErrorsHandlerService implement
 | 
				
			|||||||
        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
					        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
				
			||||||
        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
					        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
				
			||||||
    ): Promise<CoreFormFields> {
 | 
					    ): Promise<CoreFormFields> {
 | 
				
			||||||
        const data: CoreFormFields =  {};
 | 
					        const data: CoreFormFields = {};
 | 
				
			||||||
        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
					        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
				
			||||||
        let hasErrors = false;
 | 
					        let hasErrors = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -118,7 +118,7 @@ export class AddonModWorkshopAssessmentStrategyNumErrorsHandlerService implement
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
 | 
					                data['gradeid__idx_' + idx] = parseInt(form.current[idx].gradeid, 10) || 0;
 | 
				
			||||||
                data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
 | 
					                data['dimensionid__idx_' + idx] = parseInt(field.dimensionid, 10);
 | 
				
			||||||
                data['weight__idx_' + idx] = parseInt(field.weight, 10) ||  0;
 | 
					                data['weight__idx_' + idx] = parseInt(field.weight, 10) || 0;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        });
 | 
					        });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -94,7 +94,7 @@ export class AddonModWorkshopAssessmentStrategyRubricHandlerService implements A
 | 
				
			|||||||
        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
					        currentValues: AddonModWorkshopGetAssessmentFormFieldsParsedData[],
 | 
				
			||||||
        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
					        form: AddonModWorkshopGetAssessmentFormDefinitionData,
 | 
				
			||||||
    ): Promise<CoreFormFields> {
 | 
					    ): Promise<CoreFormFields> {
 | 
				
			||||||
        const data: CoreFormFields =  {};
 | 
					        const data: CoreFormFields = {};
 | 
				
			||||||
        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
					        const errors: AddonModWorkshopAssessmentStrategyFieldErrors = {};
 | 
				
			||||||
        let hasErrors = false;
 | 
					        let hasErrors = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -13,7 +13,7 @@
 | 
				
			|||||||
        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
					        <core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate"
 | 
				
			||||||
            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
					            (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline"  [priority]="600"
 | 
					        <core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600"
 | 
				
			||||||
            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
					            [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon"
 | 
				
			||||||
            [closeOnClick]="false">
 | 
					            [closeOnClick]="false">
 | 
				
			||||||
        </core-context-menu-item>
 | 
					        </core-context-menu-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@
 | 
				
			|||||||
<ion-content>
 | 
					<ion-content>
 | 
				
			||||||
    <ion-list>
 | 
					    <ion-list>
 | 
				
			||||||
        <ng-container *ngFor="let phase of phases">
 | 
					        <ng-container *ngFor="let phase of phases">
 | 
				
			||||||
            <ion-item-divider [attr.aria-current]="workshopPhase == phase.code ? 'page' :  'false'">
 | 
					            <ion-item-divider [attr.aria-current]="workshopPhase == phase.code ? 'page' : 'false'">
 | 
				
			||||||
                <ion-label>
 | 
					                <ion-label>
 | 
				
			||||||
                    <h2>{{ phase.title }}</h2>
 | 
					                    <h2>{{ phase.title }}</h2>
 | 
				
			||||||
                    <p class="ion-text-wrap" *ngIf="workshopPhase == phase.code">
 | 
					                    <p class="ion-text-wrap" *ngIf="workshopPhase == phase.code">
 | 
				
			||||||
 | 
				
			|||||||
@ -32,7 +32,7 @@
 | 
				
			|||||||
                    </span>
 | 
					                    </span>
 | 
				
			||||||
                </ion-label>
 | 
					                </ion-label>
 | 
				
			||||||
                <core-rich-text-editor [control]="editForm.controls['content']" name="content"
 | 
					                <core-rich-text-editor [control]="editForm.controls['content']" name="content"
 | 
				
			||||||
                    [placeholder]="'addon.mod_workshop.submissioncontent' | translate"  name="content" [component]="component"
 | 
					                    [placeholder]="'addon.mod_workshop.submissioncontent' | translate" name="content" [component]="component"
 | 
				
			||||||
                    [componentId]="componentId" [autoSave]="true" contextLevel="module" [contextInstanceId]="module.id"
 | 
					                    [componentId]="componentId" [autoSave]="true" contextLevel="module" [contextInstanceId]="module.id"
 | 
				
			||||||
                    elementId="content_editor" [draftExtraParams]="editorExtraParams"></core-rich-text-editor>
 | 
					                    elementId="content_editor" [draftExtraParams]="editorExtraParams"></core-rich-text-editor>
 | 
				
			||||||
            </ion-item>
 | 
					            </ion-item>
 | 
				
			||||||
 | 
				
			|||||||
@ -61,7 +61,7 @@ export class AddonModWorkshopEditSubmissionPage implements OnInit, OnDestroy, Ca
 | 
				
			|||||||
    component = AddonModWorkshopProvider.COMPONENT;
 | 
					    component = AddonModWorkshopProvider.COMPONENT;
 | 
				
			||||||
    componentId!: number;
 | 
					    componentId!: number;
 | 
				
			||||||
    editForm: FormGroup; // The form group.
 | 
					    editForm: FormGroup; // The form group.
 | 
				
			||||||
    editorExtraParams:  Record<string, unknown> = {}; // Extra params to identify the draft.
 | 
					    editorExtraParams: Record<string, unknown> = {}; // Extra params to identify the draft.
 | 
				
			||||||
    workshop?: AddonModWorkshopData;
 | 
					    workshop?: AddonModWorkshopData;
 | 
				
			||||||
    textAvailable = false;
 | 
					    textAvailable = false;
 | 
				
			||||||
    textRequired = false;
 | 
					    textRequired = false;
 | 
				
			||||||
 | 
				
			|||||||
@ -362,7 +362,7 @@ export class AddonModWorkshopSubmissionPage implements OnInit, OnDestroy, CanLea
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Parse assessment to be shown.
 | 
					     * Parse assessment to be shown.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  assessment Original assessment.
 | 
					     * @param assessment Original assessment.
 | 
				
			||||||
     * @return Parsed assessment.
 | 
					     * @return Parsed assessment.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    protected parseAssessment(
 | 
					    protected parseAssessment(
 | 
				
			||||||
 | 
				
			|||||||
@ -483,7 +483,7 @@ export class AddonModWorkshopHelperProvider {
 | 
				
			|||||||
        actions.forEach((action) => {
 | 
					        actions.forEach((action) => {
 | 
				
			||||||
            switch (action.action) {
 | 
					            switch (action.action) {
 | 
				
			||||||
                case AddonModWorkshopAction.ADD:
 | 
					                case AddonModWorkshopAction.ADD:
 | 
				
			||||||
                case  AddonModWorkshopAction.UPDATE:
 | 
					                case AddonModWorkshopAction.UPDATE:
 | 
				
			||||||
                    submission!.title = action.title;
 | 
					                    submission!.title = action.title;
 | 
				
			||||||
                    submission!.content = action.content;
 | 
					                    submission!.content = action.content;
 | 
				
			||||||
                    submission!.title = action.title;
 | 
					                    submission!.title = action.title;
 | 
				
			||||||
@ -492,7 +492,7 @@ export class AddonModWorkshopHelperProvider {
 | 
				
			|||||||
                    submission!.offline = true;
 | 
					                    submission!.offline = true;
 | 
				
			||||||
                    attachmentsId = action.attachmentsid as CoreFileUploaderStoreFilesResult;
 | 
					                    attachmentsId = action.attachmentsid as CoreFileUploaderStoreFilesResult;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
                case  AddonModWorkshopAction.DELETE:
 | 
					                case AddonModWorkshopAction.DELETE:
 | 
				
			||||||
                    submission!.deleted = true;
 | 
					                    submission!.deleted = true;
 | 
				
			||||||
                    submission!.submissionmodified = action.timemodified / 1000;
 | 
					                    submission!.submissionmodified = action.timemodified / 1000;
 | 
				
			||||||
                    break;
 | 
					                    break;
 | 
				
			||||||
 | 
				
			|||||||
@ -125,7 +125,7 @@ export class AddonNotesListPage implements OnInit, OnDestroy {
 | 
				
			|||||||
        } finally {
 | 
					        } finally {
 | 
				
			||||||
            let canDelete = this.notes && this.notes.length > 0;
 | 
					            let canDelete = this.notes && this.notes.length > 0;
 | 
				
			||||||
            if (canDelete && this.type == 'personal') {
 | 
					            if (canDelete && this.type == 'personal') {
 | 
				
			||||||
                canDelete = !!this.notes.find((note) =>  note.usermodified == this.currentUserId);
 | 
					                canDelete = !!this.notes.find((note) => note.usermodified == this.currentUserId);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            this.canDeleteNotes = canDelete;
 | 
					            this.canDeleteNotes = canDelete;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -452,7 +452,7 @@ export class AddonQtypeDdMarkerQuestion {
 | 
				
			|||||||
    /**
 | 
					    /**
 | 
				
			||||||
     * Make proportional position of the point.
 | 
					     * Make proportional position of the point.
 | 
				
			||||||
     *
 | 
					     *
 | 
				
			||||||
     * @param  point Point coordinates.
 | 
					     * @param point Point coordinates.
 | 
				
			||||||
     * @return Converted point.
 | 
					     * @return Converted point.
 | 
				
			||||||
     */
 | 
					     */
 | 
				
			||||||
    makePointProportional(point: AddonQtypeDdMarkerQuestionPoint): AddonQtypeDdMarkerQuestionPoint {
 | 
					    makePointProportional(point: AddonQtypeDdMarkerQuestionPoint): AddonQtypeDdMarkerQuestionPoint {
 | 
				
			||||||
 | 
				
			|||||||
@ -140,7 +140,7 @@
 | 
				
			|||||||
        div.draghomes img.target {
 | 
					        div.draghomes img.target {
 | 
				
			||||||
            position: absolute;
 | 
					            position: absolute;
 | 
				
			||||||
            left: -7px; /* This must be half the size of the target image, minus 0.5. */
 | 
					            left: -7px; /* This must be half the size of the target image, minus 0.5. */
 | 
				
			||||||
            top: -7px;  /* In other words, this works for a 15x15 cross-hair. */
 | 
					            top: -7px; /* In other words, this works for a 15x15 cross-hair. */
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        div.dragitems div.draghome img.target,
 | 
					        div.dragitems div.draghome img.target,
 | 
				
			||||||
        div.draghomes div.marker img.target {
 | 
					        div.draghomes div.marker img.target {
 | 
				
			||||||
 | 
				
			|||||||
@ -12,7 +12,7 @@
 | 
				
			|||||||
    <!-- Checkbox for multiple choice. -->
 | 
					    <!-- Checkbox for multiple choice. -->
 | 
				
			||||||
    <ng-container *ngIf="multiQuestion.multi">
 | 
					    <ng-container *ngIf="multiQuestion.multi">
 | 
				
			||||||
        <ion-item class="ion-text-wrap" *ngFor="let option of multiQuestion.options">
 | 
					        <ion-item class="ion-text-wrap" *ngFor="let option of multiQuestion.options">
 | 
				
			||||||
            <ion-label [color]='(option.isCorrect === 1 ? "success": "") +  (option.isCorrect === 0 ? "danger": "")'>
 | 
					            <ion-label [color]='(option.isCorrect === 1 ? "success": "") + (option.isCorrect === 0 ? "danger": "")'>
 | 
				
			||||||
                <core-format-text [component]="component" [componentId]="componentId" [text]="option.text"
 | 
					                <core-format-text [component]="component" [componentId]="componentId" [text]="option.text"
 | 
				
			||||||
                    [contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId">
 | 
					                    [contextLevel]="contextLevel" [contextInstanceId]="contextInstanceId" [courseId]="courseId">
 | 
				
			||||||
                </core-format-text>
 | 
					                </core-format-text>
 | 
				
			||||||
 | 
				
			|||||||
@ -132,7 +132,7 @@ export class AddonStorageManagerCourseStoragePage implements OnInit {
 | 
				
			|||||||
            return;
 | 
					            return;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const modules: AddonStorageManagerModule[]  = [];
 | 
					        const modules: AddonStorageManagerModule[] = [];
 | 
				
			||||||
        section.modules.forEach((module) => {
 | 
					        section.modules.forEach((module) => {
 | 
				
			||||||
            if (module.totalSize && module.totalSize > 0) {
 | 
					            if (module.totalSize && module.totalSize > 0) {
 | 
				
			||||||
                modules.push(module);
 | 
					                modules.push(module);
 | 
				
			||||||
 | 
				
			|||||||
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