MOBILE-3947 app: Fix linting errors
parent
dbb3db08ae
commit
93dad58ebe
|
@ -217,7 +217,7 @@
|
|||
<p class="item-heading">{{ relatedBadge.name }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="badge.relatedbadges.length == 0">
|
||||
<ion-item class="ion-text-wrap" *ngIf="badge.relatedbadges.length === 0">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ 'addon.badges.norelated' | translate}}</p>
|
||||
</ion-label>
|
||||
|
@ -237,7 +237,7 @@
|
|||
<p class="item-heading">{{ alignment.targetname }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="badge.alignment.length == 0">
|
||||
<ion-item class="ion-text-wrap" *ngIf="badge.alignment.length === 0">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ 'addon.badges.noalignment' | translate}}</p>
|
||||
</ion-label>
|
||||
|
|
|
@ -99,7 +99,7 @@
|
|||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<core-empty-box *ngIf="filteredCourses.length == 0" image="assets/img/icons/courses.svg">
|
||||
<core-empty-box *ngIf="filteredCourses.length === 0" image="assets/img/icons/courses.svg">
|
||||
<p *ngIf="hasCourses" class="item-heading">
|
||||
{{'addon.block_myoverview.noresult' | translate}}
|
||||
</p>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
</ion-item-divider>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-empty-box *ngIf="courses.length == 0" image="assets/img/icons/courses.svg"
|
||||
<core-empty-box *ngIf="courses.length === 0" image="assets/img/icons/courses.svg"
|
||||
[message]="'addon.block_recentlyaccessedcourses.nocourses' | translate"></core-empty-box>
|
||||
<!-- List of courses. -->
|
||||
<div [hidden]="courses.length === 0" [id]="scrollElementId" class="core-horizontal-scroll"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
</div>
|
||||
</ion-item-divider>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-empty-box *ngIf="courses.length == 0" image="assets/img/icons/courses.svg"
|
||||
<core-empty-box *ngIf="courses.length === 0" image="assets/img/icons/courses.svg"
|
||||
[message]="'addon.block_starredcourses.nocourses' | translate"></core-empty-box>
|
||||
<!-- List of courses. -->
|
||||
<div [hidden]="courses.length === 0" [id]="scrollElementId" class="core-horizontal-scroll"
|
||||
|
|
|
@ -20,10 +20,10 @@
|
|||
<ion-label>{{ 'addon.blog.showonlyyourentries' | translate }}</ion-label>
|
||||
<ion-toggle [(ngModel)]="onlyMyEntries" (ionChange)="onlyMyEntriesToggleChanged(onlyMyEntries)" slot="end"></ion-toggle>
|
||||
</ion-item>
|
||||
<core-empty-box *ngIf="entries && entries.length == 0" icon="far-newspaper" [message]="'addon.blog.noentriesyet' | translate">
|
||||
<core-empty-box *ngIf="entries && entries.length === 0" icon="far-newspaper" [message]="'addon.blog.noentriesyet' | translate">
|
||||
</core-empty-box>
|
||||
<ng-container *ngFor="let entry of entries">
|
||||
<ion-card *ngIf="!onlyMyEntries || entry.userid == currentUserId">
|
||||
<ion-card *ngIf="!onlyMyEntries || entry.userid === currentUserId">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<core-user-avatar [user]="entry.user" slot="start" [courseId]="entry.courseid"></core-user-avatar>
|
||||
<ion-label>
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
<!-- In tablet, display list of events. -->
|
||||
<div class="ion-hide-md-down addon-calendar-day-events" *ngIf="day.filteredEvents">
|
||||
<ng-container *ngFor="let event of day.filteredEvents | slice:0:4; let index = index">
|
||||
<div *ngIf="index < 3 || day.filteredEvents.length == 4" class="addon-calendar-event"
|
||||
<div *ngIf="index < 3 || day.filteredEvents.length === 4" class="addon-calendar-event"
|
||||
[class.addon-calendar-event-past]="event.ispast" (ariaButtonClick)="eventClicked(event, $event)"
|
||||
[tabindex]="activeView ? 0 : -1">
|
||||
<span class="calendar_event_type calendar_event_{{event.formattedType}}"></span>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
<ion-label>
|
||||
<p class="item-heading" [core-mark-required]="true">{{ 'addon.calendar.eventkind' | translate }}</p>
|
||||
</ion-label>
|
||||
<p *ngIf="eventTypes.length == 1" slot="end">{{eventTypes[0].name | translate }}</p>
|
||||
<p *ngIf="eventTypes.length === 1" slot="end">{{eventTypes[0].name | translate }}</p>
|
||||
<ion-select *ngIf="eventTypes.length > 1" formControlName="eventtype" interface="action-sheet"
|
||||
[cancelText]="'core.cancel' | translate" [interfaceOptions]="{header: 'addon.calendar.eventkind' | translate}">
|
||||
<ion-select-option *ngFor="let type of eventTypes" [value]="type.value">
|
||||
|
|
|
@ -86,7 +86,7 @@
|
|||
<ion-item class="ion-text-wrap" *ngIf="coursemodules">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ 'addon.competency.activities' | translate }}</p>
|
||||
<p *ngIf="coursemodules.length == 0">
|
||||
<p *ngIf="coursemodules.length === 0">
|
||||
{{ 'addon.competency.noactivities' | translate }}
|
||||
</p>
|
||||
<ion-item class="ion-text-wrap" *ngFor="let activity of coursemodules" [href]="activity.url"
|
||||
|
@ -130,7 +130,7 @@
|
|||
|
||||
<div *ngIf="competency">
|
||||
<h2 class="ion-margin-horizontal">{{ 'addon.competency.evidence' | translate }}</h2>
|
||||
<p class="ion-margin-horizontal" *ngIf="competency.evidence.length == 0">
|
||||
<p class="ion-margin-horizontal" *ngIf="competency.evidence.length === 0">
|
||||
{{ 'addon.competency.noevidence' | translate }}
|
||||
</p>
|
||||
<ion-card *ngFor="let evidence of competency.evidence">
|
||||
|
|
|
@ -58,7 +58,7 @@
|
|||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
<core-empty-box *ngIf="courseCompetencies && courseCompetencies.statistics.competencycount == 0" icon="fas-award"
|
||||
<core-empty-box *ngIf="courseCompetencies && courseCompetencies.statistics.competencycount === 0" icon="fas-award"
|
||||
message="{{ 'addon.competency.nocompetenciesincourse' | translate }}">
|
||||
</core-empty-box>
|
||||
|
||||
|
@ -121,7 +121,7 @@
|
|||
</div>
|
||||
<div>
|
||||
<p class="item-heading">{{ 'addon.competency.activities' | translate }}</p>
|
||||
<p *ngIf="competency.coursemodules.length == 0">
|
||||
<p *ngIf="competency.coursemodules.length === 0">
|
||||
{{ 'addon.competency.noactivities' | translate }}
|
||||
</p>
|
||||
<ion-item class="ion-text-wrap core-course-module-handler" [attr.aria-label]="activity.name" core-link
|
||||
|
@ -137,7 +137,7 @@
|
|||
</div>
|
||||
<div *ngIf="competency.plans">
|
||||
<p class="item-heading">{{ 'addon.competency.userplans' | translate }}</p>
|
||||
<p *ngIf="competency.plans.length == 0">
|
||||
<p *ngIf="competency.plans.length === 0">
|
||||
{{ 'addon.competency.nouserplanswithcompetency' | translate }}
|
||||
</p>
|
||||
<ion-item class="ion-text-wrap" *ngFor="let plan of competency.plans" [href]="plan.url"
|
||||
|
|
|
@ -75,7 +75,7 @@
|
|||
<ion-card-title>{{ 'addon.competency.learningplancompetencies' | translate }}</ion-card-title>
|
||||
</ion-card-header>
|
||||
<ion-list>
|
||||
<ion-item class="ion-text-wrap" *ngIf="plan.competencycount == 0">
|
||||
<ion-item class="ion-text-wrap" *ngIf="plan.competencycount === 0">
|
||||
<ion-label>
|
||||
<p>{{ 'addon.competency.nocompetencies' | translate }}</p>
|
||||
</ion-label>
|
||||
|
|
|
@ -21,9 +21,10 @@ import { CoreSite } from '@classes/sites/site';
|
|||
import { CoreStatusWithWarningsWSResponse, CoreWSExternalWarning } from '@services/ws';
|
||||
import { makeSingleton } from '@singletons';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { asyncObservable, firstValueFrom } from '@/core/utils/rxjs';
|
||||
import { asyncObservable } from '@/core/utils/rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { CoreSiteWSPreSets, WSObservable } from '@classes/sites/authenticated-site';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
const ROOT_CACHE_KEY = 'mmaCourseCompletion:';
|
||||
|
||||
|
|
|
@ -147,7 +147,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
if (el.hasOwnProperty(name)) {
|
||||
el[name] = value;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if browser/device is supported by Ogv.JS.
|
||||
|
@ -156,7 +156,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static isSupported(): boolean {
|
||||
return OGVCompat.supported('OGVPlayer');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the tech can support the given type.
|
||||
|
@ -166,7 +166,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static canPlayType(type: string): string {
|
||||
return (type.indexOf('/ogg') !== -1 || type.indexOf('/webm')) ? 'maybe' : '';
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the tech can support the given source.
|
||||
|
@ -176,7 +176,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static canPlaySource(srcObj: TechSourceObject): string {
|
||||
return VideoJSOgvJS.canPlayType(srcObj.type);
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the volume can be changed in this browser/device.
|
||||
|
@ -194,7 +194,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
return player.hasOwnProperty('volume');
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the volume can be muted in this browser/device.
|
||||
|
@ -203,7 +203,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static canMuteVolume(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the playback rate can be changed in this browser/device.
|
||||
|
@ -212,7 +212,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static canControlPlaybackRate(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to see if native 'TextTracks' are supported by this browser/device.
|
||||
|
@ -221,7 +221,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static supportsNativeTextTracks(): boolean {
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the fullscreen resize is supported by this browser/device.
|
||||
|
@ -230,7 +230,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static supportsFullscreenResize(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the progress events is supported by this browser/device.
|
||||
|
@ -239,7 +239,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static supportsProgressEvents(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the time update events is supported by this browser/device.
|
||||
|
@ -248,7 +248,7 @@ export class VideoJSOgvJS extends Tech {
|
|||
*/
|
||||
static supportsTimeupdateEvents(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the 'OgvJS' Tech's DOM element.
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
<ion-item class="ion-text-wrap addon-messages-conversation-item"
|
||||
*ngIf="contact.profileimageurl || contact.profileimageurlsmall" [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>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ contact.fullname }}</p>
|
||||
|
|
|
@ -29,7 +29,7 @@
|
|||
<ion-list class="ion-no-margin" *ngIf="confirmedContacts.length">
|
||||
<ion-item class="ion-text-wrap addon-messages-conversation-item" (click)="selectUser(contact.id)" button
|
||||
*ngFor="let contact of confirmedContacts" [attr.aria-label]="contact.fullname" [detail]="true"
|
||||
[attr.aria-current]="contact.id == selectedUserId ? 'page' : 'false'">
|
||||
[attr.aria-current]="contact.id === selectedUserId ? 'page' : 'false'">
|
||||
<core-user-avatar slot="start" [user]="contact" [checkOnline]="contact.showonlinestatus"
|
||||
[linkProfile]="false">
|
||||
</core-user-avatar>
|
||||
|
@ -67,7 +67,7 @@
|
|||
<ion-list class="ion-no-margin" *ngIf="requests.length">
|
||||
<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-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>
|
||||
<ion-label>
|
||||
<core-format-text [text]="request.fullname" contextLevel="system" [contextInstanceId]="0">
|
||||
|
|
|
@ -76,7 +76,7 @@
|
|||
{{ message.timecreated | coreFormatDate: "strftimedayshort" }}
|
||||
</h3>
|
||||
|
||||
<ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom > 0 && message.id == unreadMessageFrom" color="light">
|
||||
<ion-chip class="addon-messages-unreadfrom" *ngIf="unreadMessageFrom > 0 && message.id === unreadMessageFrom" color="light">
|
||||
<ion-label>{{ 'addon.messages.newmessages' | translate }}</ion-label>
|
||||
<ion-icon name="fas-arrow-down" aria-hidden="true"></ion-icon>
|
||||
</ion-chip>
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let result of search.results" button
|
||||
[attr.aria-label]="result.fullname" (click)="gotoDiscussion(result.userid, result.messageid)"
|
||||
[attr.aria-current]="result.userid == discussionUserId ? 'page' : 'false'" [detail]="false">
|
||||
[attr.aria-current]="result.userid === discussionUserId ? 'page' : 'false'" [detail]="false">
|
||||
<core-user-avatar [user]="result" slot="start" [checkOnline]="result.showonlinestatus"></core-user-avatar>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ result.fullname }}</p>
|
||||
|
@ -60,7 +60,7 @@
|
|||
<ng-container *ngIf="!search.showResults">
|
||||
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let discussion of discussions" button
|
||||
[attr.aria-label]="discussion.fullname" (click)="gotoDiscussion(discussion.message!.user)"
|
||||
[attr.aria-current]="discussion.message!.user == discussionUserId ? 'page' : 'false'" [detail]="false">
|
||||
[attr.aria-current]="discussion.message!.user === discussionUserId ? 'page' : 'false'" [detail]="false">
|
||||
<core-user-avatar [user]="discussion" slot="start" checkOnline="false"></core-user-avatar>
|
||||
<ion-label>
|
||||
<div class="flex-row ion-justify-content-between">
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
|
||||
<core-infinite-loading [enabled]="favourites.canLoadMore" (action)="loadMoreConversations(favourites, $event)"
|
||||
[error]="favourites.loadMoreError"></core-infinite-loading>
|
||||
<ion-item class="ion-text-wrap" *ngIf="favourites.conversations && favourites.conversations.length == 0">
|
||||
<ion-item class="ion-text-wrap" *ngIf="favourites.conversations && favourites.conversations.length === 0">
|
||||
<ion-label>
|
||||
<p>{{ 'addon.messages.nofavourites' | translate }}</p>
|
||||
</ion-label>
|
||||
|
@ -94,7 +94,7 @@
|
|||
<!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
|
||||
<core-infinite-loading [enabled]="group.canLoadMore" (action)="loadMoreConversations(group, $event)"
|
||||
[error]="group.loadMoreError"></core-infinite-loading>
|
||||
<ion-item class="ion-text-wrap" *ngIf="group.conversations && group.conversations.length == 0">
|
||||
<ion-item class="ion-text-wrap" *ngIf="group.conversations && group.conversations.length === 0">
|
||||
<ion-label>
|
||||
<p>{{ 'addon.messages.nogroupconversations' | translate }}</p>
|
||||
</ion-label>
|
||||
|
@ -128,7 +128,7 @@
|
|||
<!-- The infinite loading cannot be inside the ng-template, it fails because it doesn't find ion-content. -->
|
||||
<core-infinite-loading [enabled]="individual.canLoadMore" (action)="loadMoreConversations(individual, $event)"
|
||||
[error]="individual.loadMoreError"></core-infinite-loading>
|
||||
<ion-item class="ion-text-wrap" *ngIf="individual.conversations && individual.conversations.length == 0">
|
||||
<ion-item class="ion-text-wrap" *ngIf="individual.conversations && individual.conversations.length === 0">
|
||||
<ion-label>
|
||||
<p>{{ 'addon.messages.noindividualconversations' | translate }}</p>
|
||||
</ion-label>
|
||||
|
@ -150,17 +150,17 @@
|
|||
<ion-item class="ion-text-wrap addon-message-discussion" *ngFor="let conversation of conversations" button [detail]="false"
|
||||
(click)="gotoConversation(conversation.id, conversation.userid)"
|
||||
[attr.aria-current]="((conversation.id &&
|
||||
conversation.id == selectedConversationId) || (conversation.userid && conversation.userid == selectedUserId)) ? 'page': 'false'"
|
||||
conversation.id === selectedConversationId) || (conversation.userid && conversation.userid === selectedUserId)) ? 'page': 'false'"
|
||||
id="addon-message-conversation-{{ conversation.id ? conversation.id : 'user-' + conversation.userid }}"
|
||||
[attr.aria-label]="conversation.name">
|
||||
<!-- Group conversation image. -->
|
||||
<ion-avatar slot="start" *ngIf="conversation.type == typeGroup">
|
||||
<ion-avatar slot="start" *ngIf="conversation.type === typeGroup">
|
||||
<img [src]="conversation.imageurl" [alt]="conversation.name" core-external-content
|
||||
onError="this.src='assets/img/group-avatar.svg'">
|
||||
</ion-avatar>
|
||||
|
||||
<!-- Avatar for individual conversations. -->
|
||||
<core-user-avatar *ngIf="conversation.type != typeGroup" core-user-avatar [user]="conversation.otherUser" [linkProfile]="false"
|
||||
<core-user-avatar *ngIf="conversation.type !== typeGroup" core-user-avatar [user]="conversation.otherUser" [linkProfile]="false"
|
||||
[checkOnline]="conversation.showonlinestatus" slot="start"></core-user-avatar>
|
||||
|
||||
<ion-label>
|
||||
|
@ -189,7 +189,7 @@
|
|||
<span *ngIf="conversation.sentfromcurrentuser" class="addon-message-last-message-user">
|
||||
{{ 'addon.messages.you' | translate }}
|
||||
</span>
|
||||
<span *ngIf="!conversation.sentfromcurrentuser && conversation.type == typeGroup && conversation.members[0]"
|
||||
<span *ngIf="!conversation.sentfromcurrentuser && conversation.type === typeGroup && conversation.members[0]"
|
||||
class="addon-message-last-message-user">{{ conversation.members[0].fullname + ':' }}</span>
|
||||
<core-format-text clean="true" singleLine="true" [text]="conversation.lastmessage" class="addon-message-last-message-text"
|
||||
contextLevel="system" [contextInstanceId]="0"></core-format-text>
|
||||
|
|
|
@ -45,7 +45,7 @@
|
|||
|
||||
<!-- List of results -->
|
||||
<ion-item class="addon-message-discussion ion-text-wrap" *ngFor="let result of item.results" [attr.aria-label]="result.fullname"
|
||||
(click)="openConversation(result)" [attr.aria-current]="result == selectedResult ? 'page' : 'false'" [detail]="true" button>
|
||||
(click)="openConversation(result)" [attr.aria-current]="result === selectedResult ? 'page' : 'false'" [detail]="true" button>
|
||||
<core-user-avatar slot="start" [user]="result" [checkOnline]="true" [linkProfile]="false"></core-user-avatar>
|
||||
<ion-label>
|
||||
<p class="item-heading">
|
||||
|
|
|
@ -45,11 +45,11 @@
|
|||
<ion-item class="ion-text-wrap" *ngIf="currentAttempt && !isGrading">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ 'addon.mod_assign.attemptnumber' | translate }}</p>
|
||||
<p *ngIf="assign!.maxattempts == unlimitedAttempts">
|
||||
<p *ngIf="assign!.maxattempts === unlimitedAttempts">
|
||||
{{ 'addon.mod_assign.outof' | translate :
|
||||
{'$a': {'current': currentAttempt, 'total': maxAttemptsText} } }}
|
||||
</p>
|
||||
<p *ngIf="assign!.maxattempts != unlimitedAttempts">
|
||||
<p *ngIf="assign!.maxattempts !== unlimitedAttempts">
|
||||
{{ 'addon.mod_assign.outof' | translate :
|
||||
{'$a': {'current': currentAttempt, 'total': assign!.maxattempts} } }}
|
||||
</p>
|
||||
|
@ -128,7 +128,7 @@
|
|||
|
||||
<!-- Last modified. -->
|
||||
<ion-item class="ion-text-wrap"
|
||||
*ngIf="userSubmission && userSubmission!.status != statusNew && userSubmission!.timemodified">
|
||||
*ngIf="userSubmission && userSubmission!.status !== statusNew && userSubmission!.timemodified">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ 'addon.mod_assign.timemodified' | translate }}</p>
|
||||
<p>{{ userSubmission!.timemodified * 1000 | coreFormatDate }}</p>
|
||||
|
@ -175,7 +175,7 @@
|
|||
</ion-button>
|
||||
<!-- If no submission or is new, show add submission. -->
|
||||
<ion-button expand="block" class="ion-text-wrap" (click)="goToEdit()" *ngIf="!hasOffline &&
|
||||
(!userSubmission || !userSubmission!.status || userSubmission!.status == statusNew)">
|
||||
(!userSubmission || !userSubmission!.status || userSubmission!.status === statusNew)">
|
||||
<ng-container *ngIf="!assign?.timelimit || userSubmission?.timestarted">
|
||||
{{ 'addon.mod_assign.addsubmission' | translate }}
|
||||
</ng-container>
|
||||
|
@ -184,7 +184,7 @@
|
|||
</ng-container>
|
||||
</ion-button>
|
||||
<!-- If reopened, show addfromprevious and addnewattempt. -->
|
||||
<ng-container *ngIf="!hasOffline && userSubmission?.status == statusReopened">
|
||||
<ng-container *ngIf="!hasOffline && userSubmission?.status === statusReopened">
|
||||
<ion-button *ngIf="!isPreviousAttemptEmpty" expand="block" class="ion-text-wrap"
|
||||
(click)="copyPrevious()">
|
||||
{{ 'addon.mod_assign.addnewattemptfromprevious' | translate }}
|
||||
|
@ -195,8 +195,8 @@
|
|||
</ng-container>
|
||||
<!-- Else show editsubmission. -->
|
||||
<ion-button expand="block" class="ion-text-wrap" *ngIf="!hasOffline && userSubmission &&
|
||||
userSubmission!.status && userSubmission!.status != statusNew &&
|
||||
userSubmission!.status != statusReopened" (click)="goToEdit()">
|
||||
userSubmission!.status && userSubmission!.status !== statusNew &&
|
||||
userSubmission!.status !== statusReopened" (click)="goToEdit()">
|
||||
{{ 'addon.mod_assign.editsubmission' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
|
@ -367,15 +367,15 @@
|
|||
</ion-item>
|
||||
|
||||
<!-- Attempt status. -->
|
||||
<ng-container *ngIf="isGrading && assign!.attemptreopenmethod != attemptReopenMethodNone">
|
||||
<ng-container *ngIf="isGrading && assign!.attemptreopenmethod !== attemptReopenMethodNone">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ 'addon.mod_assign.attemptsettings' | translate }}</p>
|
||||
<p *ngIf="assign!.maxattempts == unlimitedAttempts">
|
||||
<p *ngIf="assign!.maxattempts === unlimitedAttempts">
|
||||
{{ 'addon.mod_assign.outof' | translate :
|
||||
{'$a': {'current': currentAttempt, 'total': maxAttemptsText} } }}
|
||||
</p>
|
||||
<p *ngIf="assign!.maxattempts != unlimitedAttempts">
|
||||
<p *ngIf="assign!.maxattempts !== unlimitedAttempts">
|
||||
{{ 'addon.mod_assign.outof' | translate :
|
||||
{'$a': {'current': currentAttempt, 'total': assign!.maxattempts} } }}
|
||||
</p>
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" [class.item-dimmed]="chapter.hidden" button [detail]="true"
|
||||
(click)="openBook(chapter.id)">
|
||||
<ion-label>
|
||||
<p [class.ion-padding-start]="addPadding && chapter.level == 1 ? true : null">
|
||||
<p [class.ion-padding-start]="addPadding && chapter.level === 1 ? true : null">
|
||||
<span *ngIf="showNumbers" class="addon-mod-book-number">{{chapter.indexNumber}} </span>
|
||||
<span *ngIf="showBullets" class="addon-mod-book-bullet">• </span>
|
||||
<core-format-text [text]="chapter.title" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
<nav>
|
||||
<ion-list>
|
||||
<ion-item class="ion-text-wrap" *ngFor="let chapter of chapters" (click)="loadChapter(chapter.id)"
|
||||
[attr.aria-current]="selected == chapter.id ? 'page' : 'false'" button [class.item-dimmed]="chapter.hidden" [detail]="false">
|
||||
[attr.aria-current]="selected === chapter.id ? 'page' : 'false'" button [class.item-dimmed]="chapter.hidden"
|
||||
[detail]="false">
|
||||
<ion-label>
|
||||
<p [class.ion-padding-start]="addPadding && chapter.level == 1 ? true : null" class="item-heading">
|
||||
<p [class.ion-padding-start]="addPadding && chapter.level === 1 ? true : null" class="item-heading">
|
||||
<span *ngIf="showNumbers" class="addon-mod-book-number">{{chapter.indexNumber}} </span>
|
||||
<span *ngIf="showBullets" class="addon-mod-book-bullet">• </span>
|
||||
<core-format-text [text]="chapter.title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId">
|
||||
|
|
|
@ -12,12 +12,12 @@
|
|||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="usersLoaded">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let user of users" [class.addon-mod-chat-user]="currentUserId != user.id && isOnline">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let user of users" [class.addon-mod-chat-user]="currentUserId !== user.id && isOnline">
|
||||
|
||||
<core-user-avatar [user]="user" slot="start" [linkProfile]="false"></core-user-avatar>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ user.fullname }}</p>
|
||||
<ng-container *ngIf="currentUserId != user.id && isOnline">
|
||||
<ng-container *ngIf="currentUserId !== user.id && isOnline">
|
||||
<ion-button fill="clear" (click)="talkTo(user)">
|
||||
<ion-icon name="fas-comments" slot="start" aria-hidden="true"></ion-icon>
|
||||
{{ 'addon.mod_chat.talk' | translate }}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
</ion-badge>
|
||||
|
||||
<ion-badge class="ion-text-wrap" color="primary"
|
||||
*ngIf="message.userid != currentUserId && message.beep == currentUserId">
|
||||
*ngIf="message.userid !== currentUserId && message.beep === currentUserId">
|
||||
<span>
|
||||
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||
|
|
|
@ -46,7 +46,7 @@
|
|||
</ion-badge>
|
||||
|
||||
<ion-badge class="ion-text-wrap" color="primary"
|
||||
*ngIf="message.userid != currentUserId && message.beep == currentUserId">
|
||||
*ngIf="message.userid !== currentUserId && message.beep === currentUserId">
|
||||
<span>
|
||||
<ion-icon name="fas-bell" aria-hidden="true"></ion-icon>
|
||||
{{ message.timestamp * 1000 | coreFormatDate:"strftimetime" }}
|
||||
|
|
|
@ -42,4 +42,4 @@ export interface AddonModDataActionsMenuItem {
|
|||
text: string;
|
||||
icon: string;
|
||||
action: () => void;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</ng-container>
|
||||
</ion-list>
|
||||
|
||||
<core-empty-box *ngIf="!contents || (contents.files.length + contents.folders.length == 0)" icon="far-folder-open"
|
||||
<core-empty-box *ngIf="!contents || (contents.files.length + contents.folders.length === 0)" icon="far-folder-open"
|
||||
[message]=" 'addon.mod_folder.emptyfilelist' | translate"></core-empty-box>
|
||||
|
||||
</core-loading>
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card-header>
|
||||
<ion-card-content [class]="post.parentid == 0 ? 'ion-padding-top' : ''">
|
||||
<ion-card-content [class]="post.parentid === 0 ? 'ion-padding-top' : ''">
|
||||
<div class="ion-padding-bottom" *ngIf="post.isprivatereply">
|
||||
<ion-note color="danger">{{ 'addon.mod_forum.postisprivatereply' | translate }}</ion-note>
|
||||
</div>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<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">
|
||||
<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">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ sortOrder.label | translate }}</p>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<nav>
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let item of items" (click)="loadItem(item.href)"
|
||||
[attr.aria-current]="selected == item.href ? 'page' : 'false'" button [detail]="false">
|
||||
[attr.aria-current]="selected === item.href ? 'page' : 'false'" button [detail]="false">
|
||||
<ion-label [class.core-bold]="!item.href">
|
||||
<p class="item-heading">
|
||||
<span class="ion-padding-start" *ngFor="let i of getNumberForPadding(item.level)"></span>
|
||||
|
|
|
@ -88,39 +88,39 @@
|
|||
|
||||
<ion-col class="ion-text-center">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.highscore' | translate }}</p>
|
||||
<p *ngIf="overview.highscore != null">
|
||||
<p *ngIf="overview.highscore !== null">
|
||||
{{ 'core.percentagenumber' | translate:{$a: overview.highscore} }}
|
||||
</p>
|
||||
<p *ngIf="overview.highscore == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.highscore === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
|
||||
<ion-col class="ion-text-center">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.lowscore' | translate }}</p>
|
||||
<p *ngIf="overview.lowscore != null">
|
||||
<p *ngIf="overview.lowscore !== null">
|
||||
{{ 'core.percentagenumber' | translate:{$a: overview.lowscore} }}
|
||||
</p>
|
||||
<p *ngIf="overview.lowscore == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.lowscore === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col class="ion-text-center">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.averagetime' | translate }}</p>
|
||||
<p *ngIf="overview.avetime != null && overview.numofattempts">{{ avetimeReadable }}</p>
|
||||
<p *ngIf="overview.avetime == null || !overview.numofattempts">
|
||||
<p *ngIf="overview.avetime !== null && overview.numofattempts">{{ avetimeReadable }}</p>
|
||||
<p *ngIf="overview.avetime === null || !overview.numofattempts">
|
||||
{{ 'addon.mod_lesson.notcompleted' | translate }}
|
||||
</p>
|
||||
</ion-col>
|
||||
|
||||
<ion-col class="ion-text-center">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.hightime' | translate }}</p>
|
||||
<p *ngIf="overview.hightime != null">{{ hightimeReadable }}</p>
|
||||
<p *ngIf="overview.hightime == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.hightime !== null">{{ hightimeReadable }}</p>
|
||||
<p *ngIf="overview.hightime === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
|
||||
<ion-col class="ion-text-center">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.lowtime' | translate }}</p>
|
||||
<p *ngIf="overview.lowtime != null">{{ lowtimeReadable }}</p>
|
||||
<p *ngIf="overview.lowtime == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.lowtime !== null">{{ lowtimeReadable }}</p>
|
||||
<p *ngIf="overview.lowtime === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
@ -138,8 +138,8 @@
|
|||
|
||||
<ion-col [ngClass]="{'ion-text-center': overview.lessonscored}">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.averagetime' | translate }}</p>
|
||||
<p *ngIf="overview.avetime != null && overview.numofattempts">{{ avetimeReadable }}</p>
|
||||
<p *ngIf="overview.avetime == null || !overview.numofattempts">
|
||||
<p *ngIf="overview.avetime !== null && overview.numofattempts">{{ avetimeReadable }}</p>
|
||||
<p *ngIf="overview.avetime === null || !overview.numofattempts">
|
||||
{{ 'addon.mod_lesson.notcompleted' | translate }}
|
||||
</p>
|
||||
</ion-col>
|
||||
|
@ -147,31 +147,31 @@
|
|||
<ion-row>
|
||||
<ion-col class="ion-text-center" *ngIf="overview.lessonscored">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.highscore' | translate }}</p>
|
||||
<p *ngIf="overview.highscore != null">
|
||||
<p *ngIf="overview.highscore !== null">
|
||||
{{ 'core.percentagenumber' | translate:{$a: overview.highscore} }}
|
||||
</p>
|
||||
<p *ngIf="overview.highscore == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.highscore === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
|
||||
<ion-col [ngClass]="{'ion-text-center': overview.lessonscored}">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.hightime' | translate }}</p>
|
||||
<p *ngIf="overview.hightime != null">{{ hightimeReadable }}</p>
|
||||
<p *ngIf="overview.hightime == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.hightime !== null">{{ hightimeReadable }}</p>
|
||||
<p *ngIf="overview.hightime === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row>
|
||||
<ion-col class="ion-text-center" *ngIf="overview.lessonscored">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.lowscore' | translate }}</p>
|
||||
<p *ngIf="overview.lowscore != null">
|
||||
<p *ngIf="overview.lowscore !== null">
|
||||
{{ 'core.percentagenumber' | translate:{$a: overview.lowscore} }}
|
||||
</p>
|
||||
<p *ngIf="overview.lowscore == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.lowscore === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
|
||||
<ion-col [ngClass]="{'ion-text-center': overview.lessonscored}">
|
||||
<p class="item-heading">{{ 'addon.mod_lesson.lowtime' | translate }}</p>
|
||||
<p *ngIf="overview.lowtime != null">{{ lowtimeReadable }}</p>
|
||||
<p *ngIf="overview.lowtime == null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
<p *ngIf="overview.lowtime !== null">{{ lowtimeReadable }}</p>
|
||||
<p *ngIf="overview.lowtime === null">{{ 'addon.mod_lesson.notcompleted' | translate }}</p>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
<div *ngIf="!pageInstance.loadingMenu">
|
||||
<ng-container *ngFor="let page of pageInstance.lessonPages">
|
||||
<ion-item class="ion-text-wrap" *ngIf="page.display && page.displayinmenublock" (click)="loadPage(page.id)"
|
||||
[attr.aria-current]="!pageInstance.eolData && pageInstance.currentPage == page.id ? 'page' : 'false'" button
|
||||
[attr.aria-current]="!pageInstance.eolData && pageInstance.currentPage === page.id ? 'page' : 'false'" button
|
||||
[detail]="true">
|
||||
<ion-label>
|
||||
<core-format-text [text]="page.title" contextLevel="module" [courseId]="pageInstance.courseId"
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<nav>
|
||||
<ion-list>
|
||||
<ion-item button class="ion-text-wrap {{question.stateClass}}" *ngFor="let question of navigation"
|
||||
[attr.aria-current]="!summaryShown && currentPage == question.page ? 'page' : 'false'"
|
||||
[attr.aria-current]="!summaryShown && currentPage === question.page ? 'page' : 'false'"
|
||||
(click)="loadPage(question.page, question.slot)" [detail]="false">
|
||||
|
||||
<ion-label class="ion-text-wrap">
|
||||
|
@ -38,8 +38,8 @@
|
|||
[attr.aria-label]="question.status" slot="end">
|
||||
</ion-icon>
|
||||
<ion-icon *ngIf="question.stateClass === 'core-question-incorrect' ||
|
||||
question.stateClass === 'core-question-notanswered'" name="fas-xmark" color="danger" [attr.aria-label]="question.status"
|
||||
slot="end">
|
||||
question.stateClass === 'core-question-notanswered'" name="fas-xmark" color="danger"
|
||||
[attr.aria-label]="question.status" slot="end">
|
||||
</ion-icon>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
|
|
|
@ -77,7 +77,7 @@
|
|||
{{ 'core.next' | translate }}
|
||||
<ion-icon name="fas-chevron-right" slot="end" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
<ion-button expand="block" (click)="changePage(nextPage)" class="ion-text-wrap" *ngIf="nextPage == -1">
|
||||
<ion-button expand="block" (click)="changePage(nextPage)" class="ion-text-wrap" *ngIf="nextPage === -1">
|
||||
{{ 'core.submit' | translate }}
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
<p class="item-heading">{{ 'addon.mod_scorm.noattemptsallowed' | translate }}</p>
|
||||
</ion-label>
|
||||
<p slot="end">
|
||||
<span *ngIf="scorm.maxattempt == 0">{{ 'core.unlimited' | translate }}</span>
|
||||
<span *ngIf="scorm.maxattempt === 0">{{ 'core.unlimited' | translate }}</span>
|
||||
<span *ngIf="scorm.maxattempt! > 0">{{ scorm.maxattempt }}</span>
|
||||
</p>
|
||||
</ion-item>
|
||||
|
@ -59,8 +59,8 @@
|
|||
<p class="item-heading">{{ 'addon.mod_scorm.gradeforattempt' | translate }} {{attempt.num}}</p>
|
||||
</ion-label>
|
||||
<p slot="end">
|
||||
<span *ngIf="attempt.grade != -1">{{ attempt.gradeFormatted }}</span>
|
||||
<span *ngIf="attempt.grade == -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</span>
|
||||
<span *ngIf="attempt.grade !== -1">{{ attempt.gradeFormatted }}</span>
|
||||
<span *ngIf="attempt.grade === -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</span>
|
||||
</p>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
|
@ -76,8 +76,8 @@
|
|||
</p>
|
||||
</ion-label>
|
||||
<p slot="end">
|
||||
<span *ngIf="attempt.grade != -1">{{ attempt.gradeFormatted }}</span>
|
||||
<span *ngIf="attempt.grade == -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</span>
|
||||
<span *ngIf="attempt.grade !== -1">{{ attempt.gradeFormatted }}</span>
|
||||
<span *ngIf="attempt.grade === -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</span>
|
||||
</p>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="scorm.displayattemptstatus && gradeMethodReadable">
|
||||
|
@ -91,8 +91,8 @@
|
|||
<p class="item-heading">{{ 'addon.mod_scorm.gradereported' | translate }}</p>
|
||||
</ion-label>
|
||||
<p slot="end">
|
||||
<span *ngIf="grade != -1">{{ gradeFormatted }}</span>
|
||||
<span *ngIf="grade == -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</span>
|
||||
<span *ngIf="grade !== -1">{{ gradeFormatted }}</span>
|
||||
<span *ngIf="grade === -1">{{ 'addon.mod_scorm.cannotcalculategrade' | translate }}</span>
|
||||
</p>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="syncTime">
|
||||
|
@ -174,7 +174,7 @@
|
|||
</ng-container>
|
||||
|
||||
<!-- Warning that user doesn't have any more attempts. -->
|
||||
<ion-card *ngIf="!errorMessage && attemptsLeft == 0" class="core-danger-card">
|
||||
<ion-card *ngIf="!errorMessage && attemptsLeft === 0" class="core-danger-card">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p>{{ 'addon.mod_scorm.exceededmaxattempts' | translate }}</p>
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
<ng-container *ngFor="let sco of toc">
|
||||
<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"
|
||||
[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">
|
||||
<ion-icon *ngIf="sco.icon" [name]="sco.icon.icon" [attr.aria-label]="sco.icon.description" slot="start">
|
||||
</ion-icon>
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
class="ion-no-padding ion-text-wrap">
|
||||
<!-- Parent question (Category header) -->
|
||||
<ng-container *ngIf="question.multiArray?.length">
|
||||
<h3 class="ion-padding-horizontal" [class.ion-padding-top]="questionIndex == 1">{{ question.text }}</h3>
|
||||
<h3 class="ion-padding-horizontal" [class.ion-padding-top]="questionIndex === 1">{{ question.text }}</h3>
|
||||
<ion-row class="ion-align-items-center ion-hide-md-down ion-padding">
|
||||
<ion-col size="7" class="ion-padding">{{ 'addon.mod_survey.responses' | translate }}</ion-col>
|
||||
<ion-col size="1" class="ion-text-center option-name"
|
||||
|
@ -81,7 +81,7 @@
|
|||
</ng-container>
|
||||
|
||||
<!-- Single question (don't belong to a category) -->
|
||||
<ng-container *ngIf="(!question.multiArray || question.multiArray.length == 0) && question.parent === 0">
|
||||
<ng-container *ngIf="(!question.multiArray || question.multiArray.length === 0) && question.parent === 0">
|
||||
<ion-row class="ion-align-items-center ion-padding" *ngIf="question.type > 0" [class.even]="isEven">
|
||||
<ion-col size="7">
|
||||
<span id="addon-mod_survey-{{question.name}}" [core-mark-required]="question.required">
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap" *ngFor="let page of letter.pages" (click)="goToPage(page)"
|
||||
[attr.aria-current]="selectedTitle == page.title ? 'page' : 'false'" button [detail]="false">
|
||||
[attr.aria-current]="selectedTitle === page.title ? 'page' : 'false'" button [detail]="false">
|
||||
<ion-icon name="fas-house" slot="start" *ngIf="page.firstpage" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<core-format-text [text]="page.title" contextLevel="module" [contextInstanceId]="moduleId" [courseId]="courseId">
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<p *ngIf="access.canviewallsubmissions && showGrade(assessment.gradinggradeover)" class="core-overriden-grade">
|
||||
{{ 'addon.mod_workshop.gradinggradeof' | translate:{$a: workshop.gradinggrade } }}: {{assessment.gradinggradeover}}
|
||||
</p>
|
||||
<p *ngIf="assessment.weight && assessment.weight != 1">
|
||||
<p *ngIf="assessment.weight && assessment.weight !== 1">
|
||||
{{ 'addon.mod_workshop.weightinfo' | translate:{$a: assessment.weight } }}
|
||||
</p>
|
||||
<ion-badge *ngIf="!assessment.grade" color="danger">{{ 'addon.mod_workshop.notassessed' | translate }}</ion-badge>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
<ion-icon slot="start" name="fas-circle-info" color="info" *ngIf="task.completed === 'info'"
|
||||
[attr.aria-label]="'addon.mod_workshop.taskinfo' | translate">
|
||||
</ion-icon>
|
||||
<ion-icon slot="start" name="fas-circle-check" color="success" *ngIf="task.completed == '1'"
|
||||
<ion-icon slot="start" name="fas-circle-check" color="success" *ngIf="task.completed === '1'"
|
||||
[attr.aria-label]="'addon.mod_workshop.taskdone' | translate">
|
||||
</ion-icon>
|
||||
<ion-label>
|
||||
|
@ -45,7 +45,7 @@
|
|||
</ion-card>
|
||||
|
||||
<!-- Description (setup phase only) -->
|
||||
<ion-card *ngIf="description && workshop && workshop.phase == PHASE_SETUP">
|
||||
<ion-card *ngIf="description && workshop && workshop.phase === PHASE_SETUP">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'core.description' | translate }}</h3>
|
||||
|
@ -92,7 +92,7 @@
|
|||
</ng-container>
|
||||
|
||||
<!-- SUBMISSION PHASE -->
|
||||
<ion-card *ngIf="workshop.phase == PHASE_SUBMISSION && workshop.instructauthors">
|
||||
<ion-card *ngIf="workshop.phase === PHASE_SUBMISSION && workshop.instructauthors">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'addon.mod_workshop.areainstructauthors' | translate }}</h3>
|
||||
|
@ -106,10 +106,10 @@
|
|||
<ion-card *ngIf="canSubmit">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading" *ngIf="workshop.phase != PHASE_CLOSED || !submission">
|
||||
<h3 class="item-heading" *ngIf="workshop.phase !== PHASE_CLOSED || !submission">
|
||||
{{ 'addon.mod_workshop.yoursubmission' | translate }}
|
||||
</h3>
|
||||
<h3 class="item-heading" *ngIf="workshop.phase == PHASE_CLOSED && submission">
|
||||
<h3 class="item-heading" *ngIf="workshop.phase === PHASE_CLOSED && submission">
|
||||
{{ 'addon.mod_workshop.yoursubmissionwithassessments' | translate }}
|
||||
</h3>
|
||||
</ion-label>
|
||||
|
@ -142,7 +142,7 @@
|
|||
|
||||
<!-- ASSESSMENT PHASE -->
|
||||
<ng-container *ngIf="workshop.phase >= PHASE_ASSESSMENT">
|
||||
<ion-card *ngIf="workshop.phase == PHASE_ASSESSMENT && workshop.instructreviewers">
|
||||
<ion-card *ngIf="workshop.phase === PHASE_ASSESSMENT && workshop.instructreviewers">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'addon.mod_workshop.areainstructreviewers' | translate }}</h3>
|
||||
|
@ -178,7 +178,7 @@
|
|||
((grades && grades.length) || (groupInfo && (groupInfo.separateGroups || groupInfo.visibleGroups)))">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading" *ngIf="workshop.phase == PHASE_SUBMISSION">{{ 'addon.mod_workshop.submissionsreport' |
|
||||
<h3 class="item-heading" *ngIf="workshop.phase === PHASE_SUBMISSION">{{ 'addon.mod_workshop.submissionsreport' |
|
||||
translate }}</h3>
|
||||
<h3 class="item-heading" *ngIf="workshop.phase > PHASE_SUBMISSION">{{ 'addon.mod_workshop.gradesreport' | translate }}
|
||||
</h3>
|
||||
|
|
|
@ -13,10 +13,10 @@
|
|||
<ion-content>
|
||||
<ion-list>
|
||||
<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>
|
||||
<h2>{{ phase.title }}</h2>
|
||||
<p class="ion-text-wrap" *ngIf="workshopPhase == phase.code">
|
||||
<p class="ion-text-wrap" *ngIf="workshopPhase === phase.code">
|
||||
{{ 'addon.mod_workshop.userplancurrentphase' | translate }}
|
||||
</p>
|
||||
</ion-label>
|
||||
|
@ -31,13 +31,13 @@
|
|||
<ion-item class="ion-text-wrap" *ngFor="let task of phase.tasks"
|
||||
[class.item-dimmed]="phase.code !== workshopPhase || (task.code === 'submit' && !showSubmit)" (click)="runTask(task)"
|
||||
[detail]="false" button>
|
||||
<ion-icon slot="start" name="far-circle" *ngIf="task.completed == null"
|
||||
<ion-icon slot="start" name="far-circle" *ngIf="task.completed === null"
|
||||
[attr.aria-label]="'addon.mod_workshop.tasktodo' | translate"></ion-icon>
|
||||
<ion-icon slot="start" name="fas-circle-xmark" color="danger" *ngIf="task.completed === ''"
|
||||
[attr.aria-label]="'addon.mod_workshop.taskfail' | translate"></ion-icon>
|
||||
<ion-icon slot="start" name="fas-circle-info" color="info" *ngIf="task.completed === 'info'"
|
||||
[attr.aria-label]="'addon.mod_workshop.taskinfo' | translate"></ion-icon>
|
||||
<ion-icon slot="start" name="fas-circle-check" color="success" *ngIf="task.completed == '1'"
|
||||
<ion-icon slot="start" name="fas-circle-check" color="success" *ngIf="task.completed === '1'"
|
||||
[attr.aria-label]="'addon.mod_workshop.taskdone' | translate"></ion-icon>
|
||||
<ion-label>
|
||||
<p class="item-heading ion-text-wrap">{{task.title}}</p>
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
class="core-overriden-grade">
|
||||
{{ 'addon.mod_workshop.gradinggradeover' | translate }}: {{assessment.gradinggradeover}}
|
||||
</p>
|
||||
<p *ngIf="assessment && assessment.weight && assessment.weight != 1">
|
||||
<p *ngIf="assessment && assessment.weight && assessment.weight !== 1">
|
||||
{{ 'addon.mod_workshop.weightinfo' | translate:{$a: assessment.weight } }}
|
||||
</p>
|
||||
<ion-badge *ngIf="!assessment || !showGrade(assessment.grade)" color="danger">
|
||||
|
|
|
@ -59,7 +59,7 @@
|
|||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<core-empty-box *ngIf="notes && notes.length == 0" icon="fas-receipt" [message]="'addon.notes.nonotes' | translate">
|
||||
<core-empty-box *ngIf="notes && notes.length === 0" icon="fas-receipt" [message]="'addon.notes.nonotes' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<ng-container *ngIf="notes && notes.length > 0">
|
||||
|
|
|
@ -63,9 +63,9 @@
|
|||
[adaptImg]="false">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<ion-badge [color]="section.downloadStatus == statusDownloaded ? 'success' : 'light'"
|
||||
<ion-badge [color]="section.downloadStatus === statusDownloaded ? 'success' : 'light'"
|
||||
*ngIf="!section.calculatingSize && section.totalSize > 0">
|
||||
<ion-icon name="fam-cloud-done" *ngIf="section.downloadStatus == statusDownloaded"
|
||||
<ion-icon name="fam-cloud-done" *ngIf="section.downloadStatus === statusDownloaded"
|
||||
[attr.aria-label]="'core.downloaded' | translate">
|
||||
</ion-icon>{{ section.totalSize | coreBytesToSize }}
|
||||
</ion-badge>
|
||||
|
@ -74,14 +74,14 @@
|
|||
</ion-badge>
|
||||
<!-- Download progress. -->
|
||||
<p *ngIf="downloadEnabled && section.isDownloading">
|
||||
<core-progress-bar [progress]="section.total == 0 ? -1 : section.count / section.total">
|
||||
<core-progress-bar [progress]="section.total === 0 ? -1 : section.count / section.total">
|
||||
</core-progress-bar>
|
||||
</p>
|
||||
</ion-label>
|
||||
<div class="storage-buttons" slot="end"
|
||||
*ngIf="(!section.calculatingSize && section.totalSize > 0) || downloadEnabled">
|
||||
<div *ngIf="downloadEnabled" slot="end" class="core-button-spinner">
|
||||
<core-download-refresh *ngIf="!section.isDownloading && section.downloadStatus != statusDownloaded"
|
||||
<core-download-refresh *ngIf="!section.isDownloading && section.downloadStatus !== statusDownloaded"
|
||||
[status]="section.downloadStatus" [enabled]="true" (action)="prefecthSection(section)"
|
||||
[loading]="section.isDownloading || section.isCalculating" [canTrustDownload]="true">
|
||||
</core-download-refresh>
|
||||
|
@ -116,9 +116,9 @@
|
|||
[contextInstanceId]="module.id" [adaptImg]="false">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<ion-badge [color]="module.downloadStatus == statusDownloaded ? 'success' : 'light'"
|
||||
<ion-badge [color]="module.downloadStatus === statusDownloaded ? 'success' : 'light'"
|
||||
*ngIf="!module.calculatingSize && module.totalSize > 0">
|
||||
<ion-icon name="fam-cloud-done" *ngIf="module.downloadStatus == statusDownloaded"
|
||||
<ion-icon name="fam-cloud-done" *ngIf="module.downloadStatus === statusDownloaded"
|
||||
[attr.aria-label]="'core.downloaded' | translate">
|
||||
</ion-icon>{{ module.totalSize | coreBytesToSize }}
|
||||
</ion-badge>
|
||||
|
@ -129,7 +129,7 @@
|
|||
|
||||
<div class="storage-buttons" slot="end">
|
||||
<core-download-refresh *ngIf="downloadEnabled && module.handlerData?.showDownloadButton &&
|
||||
module.downloadStatus != statusDownloaded" [status]="module.downloadStatus" [enabled]="true"
|
||||
module.downloadStatus !== statusDownloaded" [status]="module.downloadStatus" [enabled]="true"
|
||||
[canTrustDownload]="true" [loading]="module.spinner || module.handlerData.spinner"
|
||||
(action)="prefetchModule(module)">
|
||||
</core-download-refresh>
|
||||
|
|
|
@ -6,10 +6,10 @@
|
|||
[courseId]="courseId" [wsNotFiltered]="true">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p *ngIf="value != '0'">
|
||||
<p *ngIf="value !== '0'">
|
||||
{{ 'core.yes' | translate }}
|
||||
</p>
|
||||
<p *ngIf="value == '0'">
|
||||
<p *ngIf="value === '0'">
|
||||
{{ 'core.no' | translate }}
|
||||
</p>
|
||||
</ion-label>
|
||||
|
|
|
@ -19,7 +19,7 @@ import { ElementController } from './ElementController';
|
|||
*
|
||||
* @todo Remove frame TAG support.
|
||||
*/
|
||||
export type FrameElement = HTMLIFrameElement | HTMLFrameElement | HTMLObjectElement | HTMLEmbedElement;
|
||||
export type FrameElement = HTMLIFrameElement | HTMLObjectElement | HTMLEmbedElement;
|
||||
|
||||
/**
|
||||
* Wrapper class to control the interactivity of a frame element.
|
||||
|
|
|
@ -33,9 +33,8 @@ import { CoreLang, CoreLangFormat } from '@services/lang';
|
|||
import { CoreSites, CoreSitesReadingStrategy } from '@services/sites';
|
||||
import { CoreSilentError } from '../errors/silenterror';
|
||||
import { CorePromisedValue } from '@classes/promised-value';
|
||||
import { Observable, ObservableInput, ObservedValueOf, OperatorFunction, Subject } from 'rxjs';
|
||||
import { Observable, ObservableInput, ObservedValueOf, OperatorFunction, Subject, firstValueFrom } from 'rxjs';
|
||||
import { finalize, map, mergeMap } from 'rxjs/operators';
|
||||
import { firstValueFrom } from '../../utils/rxjs';
|
||||
import { CoreSiteError } from '@classes/errors/siteerror';
|
||||
import { CoreUserAuthenticatedSupportConfig } from '@features/user/classes/support/authenticated-support-config';
|
||||
import { CoreSiteInfo, CoreSiteInfoResponse, CoreSitePublicConfigResponse, CoreUnauthenticatedSite } from './unauthenticated-site';
|
||||
|
@ -1279,7 +1278,7 @@ export class CoreAuthenticatedSite extends CoreUnauthenticatedSite {
|
|||
const ignoreCache = CoreSitesReadingStrategy.ONLY_NETWORK || CoreSitesReadingStrategy.PREFER_NETWORK;
|
||||
if (!ignoreCache && this.publicConfig) {
|
||||
return this.publicConfig;
|
||||
};
|
||||
}
|
||||
|
||||
const method = 'tool_mobile_get_public_config';
|
||||
const cacheId = this.getCacheId(method, {});
|
||||
|
|
|
@ -48,10 +48,10 @@ import {
|
|||
WS_CACHE_TABLE,
|
||||
} from '@services/database/sites';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { firstValueFrom } from '../../utils/rxjs';
|
||||
import { CoreFilepool } from '@services/filepool';
|
||||
import { CoreSiteInfo } from './unauthenticated-site';
|
||||
import { CoreAuthenticatedSite, CoreAuthenticatedSiteOptionalData, CoreSiteWSPreSets, WSObservable } from './authenticated-site';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Class that represents a site (combination of site + user).
|
||||
|
|
|
@ -174,7 +174,7 @@ export class CoreUnauthenticatedSite {
|
|||
options.readingStrategy === CoreSitesReadingStrategy.PREFER_NETWORK;
|
||||
if (!ignoreCache && this.publicConfig) {
|
||||
return this.publicConfig;
|
||||
};
|
||||
}
|
||||
|
||||
if (options.readingStrategy === CoreSitesReadingStrategy.ONLY_CACHE) {
|
||||
throw new CoreError('Cache not available to read public config');
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
<ng-container *ngIf="enabled && !loading">
|
||||
<!-- Download button. -->
|
||||
<ion-button *ngIf="status == statusNotDownloaded" fill="clear" (click)="download($event, false)" @coreShowHideAnimation
|
||||
<ion-button *ngIf="status === statusNotDownloaded" fill="clear" (click)="download($event, false)" @coreShowHideAnimation
|
||||
[attr.aria-label]="(statusTranslatable || 'core.download') | translate">
|
||||
<ion-icon slot="icon-only" name="fas-cloud-arrow-down" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<!-- Refresh button. -->
|
||||
<ion-button *ngIf="status == statusOutdated || (status == statusDownloaded && !canTrustDownload)" fill="clear"
|
||||
<ion-button *ngIf="status === statusOutdated || (status === statusDownloaded && !canTrustDownload)" fill="clear"
|
||||
(click)="download($event, true)" @coreShowHideAnimation [attr.aria-label]="(statusTranslatable || 'core.refresh') | translate">
|
||||
<ion-icon slot="icon-only" name="fam-cloud-refresh" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<!-- Downloaded status icon. -->
|
||||
<ion-icon *ngIf="status == statusDownloaded && canTrustDownload" class="core-icon-downloaded ion-padding-horizontal" color="success"
|
||||
<ion-icon *ngIf="status === statusDownloaded && canTrustDownload" class="core-icon-downloaded ion-padding-horizontal" color="success"
|
||||
name="fam-cloud-done" [attr.aria-label]="(statusTranslatable || 'core.downloaded') | translate" role="status"></ion-icon>
|
||||
|
||||
<ion-spinner *ngIf="status === statusDownloading" @coreShowHideAnimation
|
||||
|
|
|
@ -8,12 +8,12 @@
|
|||
</ion-button>
|
||||
<ion-slides [options]="slidesOpts" [dir]="direction" role="tablist" [attr.aria-label]="description">
|
||||
<ng-container *ngFor="let tab of tabs">
|
||||
<ion-slide *ngIf="tab.id" role="presentation" [id]="tab.id + '-tab'" tabindex="-1" [class.selected]="selected == tab.id"
|
||||
class="{{tab.class}}">
|
||||
<ion-slide *ngIf="tab.id" role="presentation" [id]="tab.id + '-tab'" tabindex="-1"
|
||||
[class.selected]="selected === tab.id" class="{{tab.class}}">
|
||||
<ion-tab-button (ionTabButtonClick)="selectTab(tab.id, $event)" (keydown)="tabAction.keyDown(tab.id, $event)"
|
||||
(keyup)="tabAction.keyUp(tab.id, $event)" [tab]="tab.page" [layout]="layout" role="tab"
|
||||
[attr.aria-controls]="tab.id" [attr.aria-selected]="selected == tab.id"
|
||||
[tabindex]="selected == tab.id ? 0 : -1">
|
||||
[attr.aria-controls]="tab.id" [attr.aria-selected]="selected === tab.id"
|
||||
[tabindex]="selected === tab.id ? 0 : -1">
|
||||
<ion-icon *ngIf="tab.icon" [name]="tab.icon" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ tab.title | translate}}</h2>
|
||||
|
|
|
@ -267,7 +267,7 @@ export enum CoreAutoLogoutType {
|
|||
* then, the user must login again.
|
||||
*/
|
||||
CUSTOM = 2,
|
||||
};
|
||||
}
|
||||
|
||||
export type CoreAutoLogoutConfig = CoreAutoLogoutSessionConfig | CoreAutoLogoutOtherConfig;
|
||||
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</ng-container>
|
||||
</ion-list>
|
||||
|
||||
<core-empty-box *ngIf="blocks.length == 0" icon="fas-table-cells-large" [message]="'core.block.noblocks' | translate">
|
||||
<core-empty-box *ngIf="blocks.length === 0" icon="fas-table-cells-large" [message]="'core.block.noblocks' | translate">
|
||||
</core-empty-box>
|
||||
</core-loading>
|
||||
</ion-content>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
|
||||
<!-- Single section. -->
|
||||
<div *ngIf="selectedSection && selectedSection.id != allSectionsId">
|
||||
<div *ngIf="selectedSection && selectedSection.id !== allSectionsId">
|
||||
<core-dynamic-component [component]="singleSectionComponent" [data]="data">
|
||||
<ng-container *ngTemplateOutlet="sectionTemplate; context: {section: selectedSection}"></ng-container>
|
||||
<core-empty-box *ngIf="!selectedSection.hasContent" icon="fas-table-cells-large"
|
||||
|
@ -18,7 +18,7 @@
|
|||
</div>
|
||||
|
||||
<!-- Multiple sections. -->
|
||||
<div *ngIf="selectedSection && selectedSection.id == allSectionsId">
|
||||
<div *ngIf="selectedSection && selectedSection.id === allSectionsId">
|
||||
<core-dynamic-component [component]="allSectionsComponent" [data]="data">
|
||||
<ng-container *ngFor="let section of sections; index as i">
|
||||
<ng-container *ngIf="i <= lastShownSectionIndex">
|
||||
|
@ -64,7 +64,7 @@
|
|||
|
||||
<!-- Template to render a section. -->
|
||||
<ng-template #sectionTemplate let-section="section">
|
||||
<section *ngIf="!section.hiddenbynumsections && section.id != allSectionsId && section.id != stealthModulesSectionId"
|
||||
<section *ngIf="!section.hiddenbynumsections && section.id !== allSectionsId && section.id !== stealthModulesSectionId"
|
||||
class="core-course-module-list-wrapper" [id]="section.id"
|
||||
[attr.aria-labelledby]="section.name ? 'core-section-name-' + section.id : null">
|
||||
<ion-item-divider class="course-section ion-text-wrap" [class.item-dimmed]="section.visible === 0 || section.uservisible === false">
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<ion-list *ngIf="loaded" id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label">
|
||||
<ng-container *ngFor="let section of sectionsToRender">
|
||||
<ion-item *ngIf="allSectionId == section.id" class="divider core-course-index-all"
|
||||
<ion-item *ngIf="allSectionId === section.id" class="divider core-course-index-all"
|
||||
(click)="selectSectionOrModule($event, section.id)" button [class.item-current]="selectedId === section.id"
|
||||
[detail]="false">
|
||||
<ion-label>
|
||||
|
@ -24,7 +24,7 @@
|
|||
</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ng-container *ngIf="allSectionId != section.id">
|
||||
<ng-container *ngIf="allSectionId !== section.id">
|
||||
<ion-item class="divider section" (click)="selectSectionOrModule($event, section.id)" button
|
||||
[class.item-current]="selectedId === section.id" [class.item-dimmed]="!section.visible"
|
||||
[class.item-hightlighted]="section.highlighted" [detail]="false">
|
||||
|
|
|
@ -49,6 +49,6 @@ export class CoreCourseModuleDescriptionComponent {
|
|||
|
||||
@HostBinding('class.deprecated') get isDeprecated(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@
|
|||
<div class="list-item-limited-width">
|
||||
<ion-item class="ion-text-wrap course-name">
|
||||
<ion-label>
|
||||
<p *ngIf="course.displayname && course.shortname && course.fullname != course.displayname"
|
||||
<p *ngIf="course.displayname && course.shortname && course.fullname !== course.displayname"
|
||||
class="core-course-shortname">
|
||||
<core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id">
|
||||
</core-format-text>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ion-header [collapsible]="(tabsComponent?.selectedIndex == 0 || tabsComponent?.selectedIndex === undefined) && !fullScreenEnabled">
|
||||
<ion-header [collapsible]="(tabsComponent?.selectedIndex === 0 || tabsComponent?.selectedIndex === undefined) && !fullScreenEnabled">
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button [text]="'core.back' | translate"></ion-back-button>
|
||||
|
|
|
@ -53,7 +53,8 @@ import { CoreDatabaseTable } from '@classes/database/database-table';
|
|||
import { CoreDatabaseCachingStrategy } from '@classes/database/database-table-proxy';
|
||||
import { SQLiteDB } from '@classes/sqlitedb';
|
||||
import { CorePlatform } from '@services/platform';
|
||||
import { asyncObservable, firstValueFrom } from '@/core/utils/rxjs';
|
||||
import { asyncObservable } from '@/core/utils/rxjs';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { CoreSiteWSPreSets, WSObservable } from '@classes/sites/authenticated-site';
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@
|
|||
|
||||
<ion-label>
|
||||
<div class="core-course-maininfo">
|
||||
<p *ngIf="course.displayname && course.shortname && course.fullname != course.displayname"
|
||||
<p *ngIf="course.displayname && course.shortname && course.fullname !== course.displayname"
|
||||
class="core-course-shortname core-course-additional-info">
|
||||
<core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id">
|
||||
</core-format-text>
|
||||
|
@ -74,7 +74,7 @@
|
|||
</ion-label>
|
||||
</ion-chip>
|
||||
|
||||
<ion-chip color="info" *ngIf="course.visible == 0"
|
||||
<ion-chip color="info" *ngIf="course.visible === 0"
|
||||
class="core-course-additional-info ion-text-wrap core-course-hidden-message">
|
||||
<ion-label>
|
||||
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||
|
|
|
@ -37,6 +37,6 @@ export class CoreCoursesCourseProgressComponent {
|
|||
|
||||
@HostBinding('class.deprecated') get isDeprecated(): boolean {
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,8 +26,8 @@ import { makeSingleton, Translate } from '@singletons';
|
|||
import { CoreWSExternalFile } from '@services/ws';
|
||||
import { AddonCourseCompletion } from '@addons/coursecompletion/services/coursecompletion';
|
||||
import moment from 'moment-timezone';
|
||||
import { of } from 'rxjs';
|
||||
import { firstValueFrom, zipIncludingComplete } from '@/core/utils/rxjs';
|
||||
import { of, firstValueFrom } from 'rxjs';
|
||||
import { zipIncludingComplete } from '@/core/utils/rxjs';
|
||||
import { catchError, map } from 'rxjs/operators';
|
||||
import { chainRequests, WSObservable } from '@classes/sites/authenticated-site';
|
||||
|
||||
|
|
|
@ -19,8 +19,8 @@ import { makeSingleton } from '@singletons';
|
|||
import { CoreWarningsWSResponse, CoreWSExternalFile, CoreWSExternalWarning } from '@services/ws';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { CoreCourseAnyCourseDataWithExtraInfoAndOptions, CoreCourseWithImageAndColor } from './courses-helper';
|
||||
import { asyncObservable, firstValueFrom, ignoreErrors, zipIncludingComplete } from '@/core/utils/rxjs';
|
||||
import { of } from 'rxjs';
|
||||
import { asyncObservable, ignoreErrors, zipIncludingComplete } from '@/core/utils/rxjs';
|
||||
import { of, firstValueFrom } from 'rxjs';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { AddonEnrolGuest, AddonEnrolGuestInfo } from '@addons/enrol/guest/services/guest';
|
||||
import { AddonEnrolSelf } from '@addons/enrol/self/services/self';
|
||||
|
|
|
@ -20,7 +20,8 @@ import { CoreStatusWithWarningsWSResponse } from '@services/ws';
|
|||
import { makeSingleton } from '@singletons';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { map } from 'rxjs/operators';
|
||||
import { asyncObservable, firstValueFrom } from '@/core/utils/rxjs';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
import { asyncObservable } from '@/core/utils/rxjs';
|
||||
import { CoreSiteWSPreSets, WSObservable } from '@classes/sites/authenticated-site';
|
||||
|
||||
const ROOT_CACHE_KEY = 'CoreCoursesDashboard:';
|
||||
|
|
|
@ -31,7 +31,7 @@ import { CoreEvents, CoreEventSiteData } from '@singletons/events';
|
|||
import { CoreLogger } from '@singletons/logger';
|
||||
import { CoreSite } from '@classes/sites/site';
|
||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||
import { firstValueFrom } from '@/core/utils/rxjs';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Helper service to provide filter functionalities.
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
{{'core.login.onboardingwelcome' | translate}}
|
||||
</h1>
|
||||
|
||||
<div *ngIf="step == 0" class="core-login-onboarding-step">
|
||||
<div *ngIf="step === 0" class="core-login-onboarding-step">
|
||||
<ion-button expand="block" (click)="skip($event)" class="ion-margin-bottom" fill="outline">
|
||||
{{'core.login.onboardingimalearner' | translate}}
|
||||
</ion-button>
|
||||
|
@ -32,7 +32,7 @@
|
|||
</ion-button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="step == 1" class="core-login-onboarding-step">
|
||||
<div *ngIf="step === 1" class="core-login-onboarding-step">
|
||||
<p class="core-login-onboarding-text">
|
||||
{{ 'core.login.onboardingtoconnect' | translate }}
|
||||
</p>
|
||||
|
@ -44,7 +44,7 @@
|
|||
</ion-button>
|
||||
</div>
|
||||
|
||||
<div *ngIf="step == 2" class="core-login-onboarding-step">
|
||||
<div *ngIf="step === 2" class="core-login-onboarding-step">
|
||||
<ul class="core-login-onboarding-text ion-text-start">
|
||||
<li>
|
||||
<ion-icon name="far-circle-check" aria-hidden="true">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-empty-box *ngIf="tabs.length == 0" icon="fas-house" [message]="'core.courses.nocourses' | translate"></core-empty-box>
|
||||
<core-empty-box *ngIf="tabs.length === 0" icon="fas-house" [message]="'core.courses.nocourses' | translate"></core-empty-box>
|
||||
</core-loading>
|
||||
<core-tabs-outlet *ngIf="tabs.length > 0" [hideUntil]="loaded" [tabs]="tabs" (ionChange)="tabSelected()">
|
||||
</core-tabs-outlet>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
<ion-tab-button *ngFor="let tab of tabs" (keydown)="tabAction.keyDown(tab.page, $event)" (keyup)="tabAction.keyUp(tab.page, $event)"
|
||||
[hidden]="!loaded && tab.hide" [tab]="tab.page" [disabled]="tab.hide" layout="label-hide" class="{{tab.class}}"
|
||||
[selected]="tab.page === selectedTab" [tabindex]="selectedTab == tab.page ? 0 : -1" [attr.aria-controls]="tab.id">
|
||||
[selected]="tab.page === selectedTab" [tabindex]="selectedTab === tab.page ? 0 : -1" [attr.aria-controls]="tab.id">
|
||||
<ion-icon class="core-tab-icon" [name]="tab.icon" aria-hidden="true"></ion-icon>
|
||||
<ion-label aria-hidden="true">{{ tab.title | translate }}</ion-label>
|
||||
<ion-badge class="core-tab-badge" *ngIf="tab.badge" aria-hidden="true">{{ tab.badge }}</ion-badge>
|
||||
|
@ -18,7 +18,7 @@
|
|||
</ion-tab-button>
|
||||
|
||||
<ion-tab-button (keydown)="tabAction.keyDown(morePageName, $event)" (keyup)="tabAction.keyUp(morePageName, $event)"
|
||||
[hidden]="!loaded" [tab]="morePageName" layout="label-hide" [tabindex]="selectedTab == morePageName ? 0 : -1"
|
||||
[hidden]="!loaded" [tab]="morePageName" layout="label-hide" [tabindex]="selectedTab === morePageName ? 0 : -1"
|
||||
[attr.aria-controls]="morePageName">
|
||||
<ion-icon class="core-tab-icon" name="ellipsis-horizontal" aria-hidden="true"></ion-icon>
|
||||
<ion-label aria-hidden="true">{{ 'core.more' | translate }}</ion-label>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ion-item class="ion-text-wrap" *ngIf="item && (item!.canrate || item!.rating != null) && !disabled">
|
||||
<ion-item class="ion-text-wrap" *ngIf="item && (item!.canrate || item!.rating !== null) && !disabled">
|
||||
<ion-label>{{ 'core.rating.rating' | translate }}</ion-label>
|
||||
<ion-select class="ion-text-start" [(ngModel)]="rating" (ngModelChange)="userRatingChanged()" interface="action-sheet"
|
||||
[cancelText]="'core.cancel' | translate" [disabled]="!item!.canrate"
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<core-empty-box *ngIf="ratings.length == 0" icon="fas-star-half-stroke" [message]="'core.rating.noratings' | translate">
|
||||
<core-empty-box *ngIf="ratings.length === 0" icon="fas-star-half-stroke" [message]="'core.rating.noratings' | translate">
|
||||
</core-empty-box>
|
||||
</core-loading>
|
||||
</ion-content>
|
||||
|
|
|
@ -264,4 +264,4 @@ export type CoreReportBuilderReportDetailSettingsData = {
|
|||
cardviewVisibleColumns: number;
|
||||
};
|
||||
|
||||
export interface CoreReportBuilderReport extends CoreReportBuilderReportWSResponse {};
|
||||
export interface CoreReportBuilderReport extends CoreReportBuilderReportWSResponse {}
|
||||
|
|
|
@ -16,6 +16,7 @@ import { Component, OnInit } from '@angular/core';
|
|||
import { CoreConstants } from '@/core/constants';
|
||||
import { Http } from '@singletons';
|
||||
import { IonSearchbar } from '@ionic/angular';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Defines license info
|
||||
|
@ -63,7 +64,7 @@ export class CoreSettingsLicensesPage implements OnInit {
|
|||
*/
|
||||
async ngOnInit(): Promise<void> {
|
||||
try {
|
||||
const licenses = await Http.get(this.licensesUrl).toPromise();
|
||||
const licenses = await firstValueFrom(Http.get(this.licensesUrl));
|
||||
this.allLicenses = Object.keys(licenses).map((name) => {
|
||||
const license = licenses[name];
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ import { CoreSite } from '../classes/sites/site';
|
|||
import { CorePlatform } from '@services/platform';
|
||||
import { AddonFilterMultilangHandler } from '@addons/filter/multilang/services/handlers/multilang';
|
||||
import { AddonFilterMultilang2Handler } from '@addons/filter/multilang2/services/handlers/multilang2';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
/*
|
||||
* Service to handle language features, like changing the current language.
|
||||
|
@ -501,7 +502,7 @@ export class CoreLangProvider {
|
|||
responseType: 'json',
|
||||
});
|
||||
|
||||
return <Record<string, string>> await observable.toPromise();
|
||||
return <Record<string, string>> await firstValueFrom(observable);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -65,6 +65,7 @@ import { CoreAutoLogoutType, CoreAutoLogout } from '@features/autologout/service
|
|||
import { CoreCacheManager } from '@services/cache-manager';
|
||||
import { CoreSiteInfo, CoreSiteInfoResponse, CoreSitePublicConfigResponse } from '@classes/sites/unauthenticated-site';
|
||||
import { CoreSiteWSPreSets } from '@classes/sites/authenticated-site';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
export const CORE_SITE_SCHEMAS = new InjectionToken<CoreSiteSchema[]>('CORE_SITE_SCHEMAS');
|
||||
export const CORE_SITE_CURRENT_SITE_ID_CONFIG = 'current_site_id';
|
||||
|
@ -441,7 +442,7 @@ export class CoreSitesProvider {
|
|||
let data: CoreSitesLoginTokenResponse;
|
||||
|
||||
try {
|
||||
data = await Http.post(loginUrl, params).pipe(timeout(CoreWS.getRequestTimeout())).toPromise();
|
||||
data = await firstValueFrom(Http.post(loginUrl, params).pipe(timeout(CoreWS.getRequestTimeout())));
|
||||
} catch (error) {
|
||||
throw new CoreError(
|
||||
this.isLoggedIn()
|
||||
|
|
|
@ -18,7 +18,7 @@ import { HttpResponse, HttpParams, HttpErrorResponse } from '@angular/common/htt
|
|||
import { FileEntry } from '@ionic-native/file/ngx';
|
||||
import { FileUploadOptions, FileUploadResult } from '@ionic-native/file-transfer/ngx';
|
||||
import { Md5 } from 'ts-md5/dist/md5';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable, firstValueFrom } from 'rxjs';
|
||||
import { timeout } from 'rxjs/operators';
|
||||
|
||||
import { CoreNativeToAngularHttpResponse } from '@classes/native-to-angular-http';
|
||||
|
@ -691,7 +691,7 @@ export class CoreWSProvider {
|
|||
const requestUrl = siteUrl + '&wsfunction=' + method;
|
||||
|
||||
// Perform the post request.
|
||||
const promise = Http.post(requestUrl, ajaxData, options).pipe(timeout(this.getRequestTimeout())).toPromise();
|
||||
const promise = firstValueFrom(Http.post(requestUrl, ajaxData, options).pipe(timeout(this.getRequestTimeout())));
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
return promise.then(async (data: any) => {
|
||||
|
@ -1178,7 +1178,7 @@ export class CoreWSProvider {
|
|||
observable = observable.pipe(timeout(angularOptions.timeout));
|
||||
}
|
||||
|
||||
return observable.toPromise();
|
||||
return firstValueFrom(observable);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import { Http } from '@singletons';
|
|||
import { CoreConstants } from '../constants';
|
||||
import { CoreLogger } from './logger';
|
||||
import aliases from '@/assets/fonts/font-awesome/aliases.json';
|
||||
import { firstValueFrom } from 'rxjs';
|
||||
|
||||
/**
|
||||
* Singleton with helper functions for icon management.
|
||||
|
@ -65,8 +66,7 @@ export class CoreIcons {
|
|||
}
|
||||
|
||||
if (!(src in CoreIcons.DEV_ICONS_STATUS)) {
|
||||
CoreIcons.DEV_ICONS_STATUS[src] = Http.get(src, { responseType: 'text' })
|
||||
.toPromise()
|
||||
CoreIcons.DEV_ICONS_STATUS[src] = firstValueFrom(Http.get(src, { responseType: 'text' }))
|
||||
.then(() => true)
|
||||
.catch(() => false);
|
||||
}
|
||||
|
|
|
@ -57,20 +57,20 @@ export class CoreSubscriptions {
|
|||
subscription?.unsubscribe();
|
||||
};
|
||||
|
||||
subscription = subscribable.subscribe(
|
||||
value => {
|
||||
subscription = subscribable.subscribe({
|
||||
next: value => {
|
||||
unsubscribe();
|
||||
runCallback(() => onSuccess(value));
|
||||
},
|
||||
error => {
|
||||
error: error => {
|
||||
unsubscribe();
|
||||
runCallback(() => onError?.(error));
|
||||
},
|
||||
() => {
|
||||
complete: () => {
|
||||
unsubscribe();
|
||||
runCallback(() => onComplete?.());
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
return () => subscription?.unsubscribe();
|
||||
}
|
||||
|
|
|
@ -13,9 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { CoreError } from '@classes/errors/error';
|
||||
import { CoreSubscriptions } from '@singletons/subscriptions';
|
||||
import { BehaviorSubject, Observable, of, OperatorFunction, Subscription } from 'rxjs';
|
||||
import { Observable, of, OperatorFunction, Subscription } from 'rxjs';
|
||||
import { catchError, filter } from 'rxjs/operators';
|
||||
|
||||
/**
|
||||
|
@ -79,27 +77,6 @@ export function asyncObservable<T>(createObservable: () => Promise<Observable<T>
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a Promise resolved with the first value returned from an observable. The difference with toPromise is that
|
||||
* this function returns the value as soon as it's emitted, it doesn't wait until the observable completes.
|
||||
* This function can be removed when the app starts using rxjs v7.
|
||||
*
|
||||
* @param observable Observable.
|
||||
* @returns Promise resolved with the first value returned.
|
||||
*/
|
||||
export function firstValueFrom<T>(observable: Observable<T>): Promise<T> {
|
||||
return new Promise((resolve, reject) => {
|
||||
CoreSubscriptions.once(observable, resolve, reject, () => {
|
||||
// Subscription is completed, check if we can get its value.
|
||||
if (observable instanceof BehaviorSubject) {
|
||||
resolve(observable.getValue());
|
||||
}
|
||||
|
||||
reject(new CoreError('Couldn\'t get first value from observable because it\'s already completed'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Ignore errors from an observable, returning a certain value instead.
|
||||
*
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
import {
|
||||
asyncObservable,
|
||||
firstValueFrom,
|
||||
formControlValue,
|
||||
ignoreErrors,
|
||||
resolved,
|
||||
|
@ -23,7 +22,7 @@ import {
|
|||
} from '@/core/utils/rxjs';
|
||||
import { mock } from '@/testing/utils';
|
||||
import { FormControl } from '@angular/forms';
|
||||
import { BehaviorSubject, Observable, of, Subject } from 'rxjs';
|
||||
import { Observable, of, Subject } from 'rxjs';
|
||||
import { TestScheduler } from 'rxjs/testing';
|
||||
|
||||
describe('RXJS Utils', () => {
|
||||
|
@ -156,35 +155,6 @@ describe('RXJS Utils', () => {
|
|||
});
|
||||
});
|
||||
|
||||
it('firstValueFrom returns first value emitted by an observable', async () => {
|
||||
const subject = new Subject();
|
||||
setTimeout(() => subject.next('foo'), 10);
|
||||
|
||||
await expect(firstValueFrom(subject)).resolves.toEqual('foo');
|
||||
|
||||
// Check that running it again doesn't get last value, it gets the new one.
|
||||
setTimeout(() => subject.next('bar'), 10);
|
||||
await expect(firstValueFrom(subject)).resolves.toEqual('bar');
|
||||
|
||||
// Check we cannot get first value if a subject is already completed.
|
||||
subject.complete();
|
||||
await expect(firstValueFrom(subject)).rejects.toThrow();
|
||||
|
||||
// Check that we get last value when using BehaviourSubject.
|
||||
const behaviorSubject = new BehaviorSubject('baz');
|
||||
await expect(firstValueFrom(behaviorSubject)).resolves.toEqual('baz');
|
||||
|
||||
// Check we get last value even if behaviour subject is completed.
|
||||
behaviorSubject.complete();
|
||||
await expect(firstValueFrom(behaviorSubject)).resolves.toEqual('baz');
|
||||
|
||||
// Check that Promise is rejected if the observable emits an error.
|
||||
const errorSubject = new Subject();
|
||||
setTimeout(() => errorSubject.error('foo error'), 10);
|
||||
|
||||
await expect(firstValueFrom(errorSubject)).rejects.toMatch('foo error');
|
||||
});
|
||||
|
||||
it('ignoreErrors ignores observable errors', (done) => {
|
||||
const subject = new Subject();
|
||||
|
||||
|
|
Loading…
Reference in New Issue