commit
7736d899a9
|
@ -73,7 +73,8 @@
|
||||||
|
|
||||||
<!-- List of courses. -->
|
<!-- List of courses. -->
|
||||||
<div class="safe-area-padding" *ngIf="hasCourses">
|
<div class="safe-area-padding" *ngIf="hasCourses">
|
||||||
<ion-grid class="ion-no-padding" [class.core-no-grid]="layouts.selected != 'card'">
|
<ion-grid class="ion-no-padding" [class.core-no-grid]="layouts.selected != 'card'"
|
||||||
|
[class.list-item-limited-width]="layouts.selected != 'card'">
|
||||||
<ion-row class="ion-no-padding">
|
<ion-row class="ion-no-padding">
|
||||||
<ion-col *ngFor="let course of filteredCourses" class="ion-no-padding" size="12" size-sm="6" size-md="6" size-lg="4"
|
<ion-col *ngFor="let course of filteredCourses" class="ion-no-padding" size="12" size-sm="6" size-md="6" size-lg="4"
|
||||||
size-xl="3">
|
size-xl="3">
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<core-loading [hideUntil]="loaded" [fullscreen]="false">
|
<core-loading [hideUntil]="loaded" [fullscreen]="false">
|
||||||
<ng-container *ngIf="mainMenuBlock">
|
<ion-list *ngIf="mainMenuBlock" class="core-course-module-list-wrapper">
|
||||||
<ion-item class="ion-text-wrap" *ngIf="mainMenuBlock.summary">
|
<ion-item class="ion-text-wrap" *ngIf="mainMenuBlock.summary">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="mainMenuBlock.summary" [component]="component" [componentId]="siteHomeId" contextLevel="course"
|
<core-format-text [text]="mainMenuBlock.summary" [component]="component" [componentId]="siteHomeId" contextLevel="course"
|
||||||
|
@ -13,5 +13,5 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<core-course-module *ngFor="let module of mainMenuBlock.modules" [module]="module" [section]="mainMenuBlock"></core-course-module>
|
<core-course-module *ngFor="let module of mainMenuBlock.modules" [module]="module" [section]="mainMenuBlock"></core-course-module>
|
||||||
</ng-container>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
<ion-item lines="none" *ngIf="course">
|
<ion-item *ngIf="course">
|
||||||
<ion-label class="ion-text-wrap">
|
<ion-label class="ion-text-wrap">
|
||||||
<h3>
|
<h3>
|
||||||
<span class="sr-only">{{ 'core.courses.aria:coursename' | translate }}</span>
|
<span class="sr-only">{{ 'core.courses.aria:coursename' | translate }}</span>
|
||||||
<core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id"></core-format-text>
|
<core-format-text [text]="course.displayname || course.fullname" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
|
</core-format-text>
|
||||||
</h3>
|
</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item-group *ngFor="let dayEvents of filteredEvents">
|
<ion-item-group *ngFor="let dayEvents of filteredEvents">
|
||||||
<ion-item lines="none">
|
<ion-item>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h4 [class.core-bold]="!course">{{ dayEvents.dayTimestamp * 1000 | coreFormatDate:"strftimedaydate" }}</h4>
|
<h4 [class.core-bold]="!course">{{ dayEvents.dayTimestamp * 1000 | coreFormatDate:"strftimedaydate" }}</h4>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -20,7 +21,7 @@
|
||||||
<ion-col class="addon-block-timeline-activity-main ion-no-padding">
|
<ion-col class="addon-block-timeline-activity-main ion-no-padding">
|
||||||
<ion-row class="ion-justify-content-between ion-align-items-center ion-nowrap ion-no-padding">
|
<ion-row class="ion-justify-content-between ion-align-items-center ion-nowrap ion-no-padding">
|
||||||
<ion-col class="addon-block-timeline-activity-time ion-no-padding">
|
<ion-col class="addon-block-timeline-activity-time ion-no-padding">
|
||||||
<ion-badge color="light">{{event.timesort * 1000 | coreFormatDate:"strftimetime24" }}</ion-badge>
|
<small>{{event.timesort * 1000 | coreFormatDate:"strftimetime24" }}</small>
|
||||||
<core-mod-icon *ngIf="event.iconUrl" [modicon]="event.iconUrl" [componentId]="event.instance"
|
<core-mod-icon *ngIf="event.iconUrl" [modicon]="event.iconUrl" [componentId]="event.instance"
|
||||||
[modname]="event.modulename">
|
[modname]="event.modulename">
|
||||||
</core-mod-icon>
|
</core-mod-icon>
|
||||||
|
@ -52,7 +53,7 @@
|
||||||
</ion-row>
|
</ion-row>
|
||||||
</ion-col>
|
</ion-col>
|
||||||
<ion-col class="addon-block-timeline-activity-action ion-no-padding" *ngIf="event.action?.actionable">
|
<ion-col class="addon-block-timeline-activity-action ion-no-padding" *ngIf="event.action?.actionable">
|
||||||
<ion-button fill="clear" (click)="action($event, event.action.url)" [title]="event.action.name">
|
<ion-button fill="outline" color="medium" (click)="action($event, event.action.url)" [title]="event.action.name">
|
||||||
{{event.action.name}}
|
{{event.action.name}}
|
||||||
<ion-badge slot="end" class="ion-margin-start" *ngIf="event.action.showitemcount">
|
<ion-badge slot="end" class="ion-margin-start" *ngIf="event.action.showitemcount">
|
||||||
{{event.action.itemcount}}
|
{{event.action.itemcount}}
|
||||||
|
@ -73,7 +74,7 @@
|
||||||
<ion-spinner *ngIf="loadingMore" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
<ion-spinner *ngIf="loadingMore" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-item lines="none" *ngIf="empty && course">
|
<ion-item *ngIf="empty && course">
|
||||||
<ion-label class="ion-text-wrap">
|
<ion-label class="ion-text-wrap">
|
||||||
<p>{{'addon.block_timeline.noevents' | translate}}</p>
|
<p>{{'addon.block_timeline.noevents' | translate}}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -13,13 +13,20 @@ h4.core-bold {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
.addon-block-timeline-activity ion-badge {
|
.addon-block-timeline-activity {
|
||||||
@include margin-horizontal(0.25rem, 0.5rem);
|
ion-badge {
|
||||||
}
|
@include margin-horizontal(0.25rem, 0.5rem);
|
||||||
|
}
|
||||||
|
|
||||||
.addon-block-timeline-activity core-mod-icon {
|
small {
|
||||||
--margin-end: 0.5rem;
|
@include margin-horizontal(null, 0.5rem);
|
||||||
--margin-vertical: 0;
|
}
|
||||||
|
|
||||||
|
core-mod-icon {
|
||||||
|
padding: 8px;
|
||||||
|
--margin-end: 0.5rem;
|
||||||
|
--margin-vertical: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.addon-block-timeline-activity-time {
|
.addon-block-timeline-activity-time {
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Custom value. -->
|
<!-- Custom value. -->
|
||||||
<ion-item lines="none" class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'core.custom' | translate }}</p>
|
<p>{{ 'core.custom' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -147,7 +147,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-radio slot="end" [value]="0"></ion-radio>
|
<ion-radio slot="end" [value]="0"></ion-radio>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item lines="none">
|
<ion-item>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'addon.calendar.durationuntil' | translate }}</p>
|
<p>{{ 'addon.calendar.durationuntil' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -159,7 +159,7 @@
|
||||||
[placeholder]="'addon.calendar.durationuntil' | translate" [displayFormat]="dateFormat" display-timezone="utc">
|
[placeholder]="'addon.calendar.durationuntil' | translate" [displayFormat]="dateFormat" display-timezone="utc">
|
||||||
</ion-datetime>
|
</ion-datetime>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item lines="none">
|
<ion-item>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'addon.calendar.durationminutes' | translate }}</p>
|
<p>{{ 'addon.calendar.durationminutes' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -175,7 +175,7 @@
|
||||||
|
|
||||||
<!-- Repeat (for new events). -->
|
<!-- Repeat (for new events). -->
|
||||||
<ng-container *ngIf="!eventId || eventId < 0">
|
<ng-container *ngIf="!eventId || eventId < 0">
|
||||||
<ion-item class="ion-text-wrap divider" lines="none">
|
<ion-item class="ion-text-wrap divider">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.calendar.repeatevent' | translate }}</p>
|
<p class="item-heading">{{ 'addon.calendar.repeatevent' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
</ion-card>
|
</ion-card>
|
||||||
<ion-card *ngIf="plan">
|
<ion-card *ngIf="plan">
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="plan.plan.description" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="plan.plan.description">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>
|
<p>
|
||||||
<core-format-text [text]="plan.plan.description" contextLevel="user" [contextInstanceId]="plan.plan.userid">
|
<core-format-text [text]="plan.plan.description" contextLevel="user" [contextInstanceId]="plan.plan.userid">
|
||||||
|
@ -31,25 +31,25 @@
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.competency.status' | translate }}</p>
|
<p class="item-heading">{{ 'addon.competency.status' | translate }}</p>
|
||||||
<p>{{ plan.plan.statusname }}</p>
|
<p>{{ plan.plan.statusname }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="plan.plan.duedate > 0" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="plan.plan.duedate > 0">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.competency.duedate' | translate }}</p>
|
<p class="item-heading">{{ 'addon.competency.duedate' | translate }}</p>
|
||||||
<p>{{ plan.plan.duedate * 1000 | coreFormatDate }}</p>
|
<p>{{ plan.plan.duedate * 1000 | coreFormatDate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="plan.plan.template" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="plan.plan.template">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ 'addon.competency.template' | translate }}</p>
|
<p class="item-heading">{{ 'addon.competency.template' | translate }}</p>
|
||||||
<p>{{ plan.plan.template.shortname }}</p>
|
<p>{{ plan.plan.template.shortname }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label id="addon-competency-plan-{{plan.plan.id}}-progress">
|
<ion-label id="addon-competency-plan-{{plan.plan.id}}-progress">
|
||||||
<p class="item-heading">{{ 'addon.competency.progress' | translate }}</p>
|
<p class="item-heading">{{ 'addon.competency.progress' | translate }}</p>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -40,11 +40,9 @@
|
||||||
[attr.aria-label]="(favourites.expanded ? 'core.collapse' : 'core.expand') | translate"
|
[attr.aria-label]="(favourites.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||||
[attr.aria-expanded]="favourites.expanded" aria-controls="addon-messages-groupconversations-favourite" role="heading"
|
[attr.aria-expanded]="favourites.expanded" aria-controls="addon-messages-groupconversations-favourite" role="heading"
|
||||||
detail="false">
|
detail="false">
|
||||||
<ion-icon *ngIf="!favourites.expanded" name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
class="expandable-status-icon">
|
[class.expandable-status-icon-expanded]="favourites.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-icon *ngIf="favourites.expanded" name="fas-chevron-down" slot="start" aria-hidden="true"
|
|
||||||
class="expandable-status-icon"></ion-icon>
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.favourites' | translate }} ({{ favourites.count }})</h2>
|
<h2>{{ 'core.favourites' | translate }} ({{ favourites.count }})</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -76,9 +74,8 @@
|
||||||
<ion-item button class="divider ion-text-wrap" (click)="toggle(group)" sticky="true"
|
<ion-item button class="divider ion-text-wrap" (click)="toggle(group)" sticky="true"
|
||||||
[attr.aria-label]="(group.expanded ? 'core.collapse' : 'core.expand') | translate" [attr.aria-expanded]="group.expanded"
|
[attr.aria-label]="(group.expanded ? 'core.collapse' : 'core.expand') | translate" [attr.aria-expanded]="group.expanded"
|
||||||
aria-controls="addon-messages-groupconversations-group" role="heading" detail="false">
|
aria-controls="addon-messages-groupconversations-group" role="heading" detail="false">
|
||||||
<ion-icon *ngIf="!group.expanded" name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
class="expandable-status-icon"></ion-icon>
|
[class.expandable-status-icon-expanded]="group.expanded">
|
||||||
<ion-icon *ngIf="group.expanded" name="fas-chevron-down" slot="start" aria-hidden="true" class="expandable-status-icon">
|
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.messages.groupconversations' | translate }} ({{ group.count }})</h2>
|
<h2>{{ 'addon.messages.groupconversations' | translate }} ({{ group.count }})</h2>
|
||||||
|
@ -111,11 +108,9 @@
|
||||||
[attr.aria-label]="(individual.expanded ? 'core.collapse' : 'core.expand') | translate"
|
[attr.aria-label]="(individual.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||||
[attr.aria-expanded]="individual.expanded" aria-controls="addon-messages-groupconversations-individual" role="heading"
|
[attr.aria-expanded]="individual.expanded" aria-controls="addon-messages-groupconversations-individual" role="heading"
|
||||||
detail="false">
|
detail="false">
|
||||||
<ion-icon *ngIf="!individual.expanded" name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
class="expandable-status-icon">
|
[class.expandable-status-icon-expanded]="individual.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-icon *ngIf="individual.expanded" name="fas-chevron-down" slot="start" aria-hidden="true"
|
|
||||||
class="expandable-status-icon"></ion-icon>
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.messages.individualconversations' | translate }} ({{ individual.count }})</h2>
|
<h2>{{ 'addon.messages.individualconversations' | translate }} ({{ individual.count }})</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<ion-item class="ion-text-wrap" *ngIf="files && files.length && !edit">
|
<ion-item class="ion-text-wrap" *ngIf="files && files.length && !edit">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ plugin.name }}</h2>
|
<h2>{{ plugin.name }}</h2>
|
||||||
<div lines="none">
|
<div>
|
||||||
<core-files [files]="files" [component]="component" [componentId]="assign.cmid" [alwaysDownload]="true"></core-files>
|
<core-files [files]="files" [component]="component" [componentId]="assign.cmid" [alwaysDownload]="true"></core-files>
|
||||||
</div>
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<ng-container *ngIf="displayMode">
|
<ng-container *ngIf="displayMode">
|
||||||
<div lines="none">
|
<div>
|
||||||
<core-files [files]="files" [component]="component" [componentId]="componentId" [alwaysDownload]="true"></core-files>
|
<core-files [files]="files" [component]="component" [componentId]="componentId" [alwaysDownload]="true"></core-files>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
<!-- Activity info. -->
|
<!-- Activity info. -->
|
||||||
<core-course-module-info [module]="module" [description]="forum && forum.type != 'single' && description" [component]="component"
|
<core-course-module-info [module]="module" [description]="forum && forum.type != 'single' && description" [component]="component"
|
||||||
[componentId]="componentId" [courseId]="courseId" [hasDataToSync]="hasOffline || hasOfflineRatings">
|
[componentId]="componentId" [courseId]="courseId" [hasDataToSync]="hasOffline || hasOfflineRatings">
|
||||||
<ion-item lines="none" class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
{{descriptionNote}}
|
{{descriptionNote}}
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<div class="addon-mod_forum-post">
|
<div class="addon-mod_forum-post">
|
||||||
<ng-container *ngIf="!formData.isEditing || !showForm">
|
<ng-container *ngIf="!formData.isEditing || !showForm">
|
||||||
<ion-card-header class="ion-text-wrap ion-no-padding" id="addon-mod_forum-post-{{post.id}}">
|
<ion-card-header class="ion-text-wrap ion-no-padding" id="addon-mod_forum-post-{{post.id}}">
|
||||||
<ion-item class="ion-text-wrap" [class.highlight]="highlight" lines="none">
|
<ion-item class="ion-text-wrap" [class.highlight]="highlight">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<div class="addon-mod-forum-post-title" *ngIf="displaySubject">
|
<div class="addon-mod-forum-post-title" *ngIf="displaySubject">
|
||||||
<h2 class="ion-text-wrap">
|
<h2 class="ion-text-wrap">
|
||||||
|
@ -63,13 +63,13 @@
|
||||||
<core-format-text [component]="component" [componentId]="componentId" [text]="post.message" contextLevel="module"
|
<core-format-text [component]="component" [componentId]="componentId" [text]="post.message" contextLevel="module"
|
||||||
[contextInstanceId]="forum && forum.cmid" [courseId]="courseId">
|
[contextInstanceId]="forum && forum.cmid" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
<div lines="none" *ngIf="post.attachments && post.attachments.length > 0">
|
<div *ngIf="post.attachments && post.attachments.length > 0">
|
||||||
<core-files [files]="post.attachments" [component]="component" [componentId]="componentId" showInline="true">
|
<core-files [files]="post.attachments" [component]="component" [componentId]="componentId" showInline="true">
|
||||||
</core-files>
|
</core-files>
|
||||||
</div>
|
</div>
|
||||||
</ion-card-content>
|
</ion-card-content>
|
||||||
<div class="addon-mod-forum-post-more-info">
|
<div class="addon-mod-forum-post-more-info">
|
||||||
<ion-item class="ion-text-wrap" *ngIf="tagsEnabled && post.tags && post.tags.length > 0" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="tagsEnabled && post.tags && post.tags.length > 0">
|
||||||
<div slot="start">{{ 'core.tag.tags' | translate }}:</div>
|
<div slot="start">{{ 'core.tag.tags' | translate }}:</div>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-tag-list [tags]="post.tags"></core-tag-list>
|
<core-tag-list [tags]="post.tags"></core-tag-list>
|
||||||
|
|
|
@ -34,10 +34,8 @@
|
||||||
<ion-item button class="divider ion-text-wrap" (click)="toggleAdvanced()" detail="false" [attr.aria-expanded]="advanced"
|
<ion-item button class="divider ion-text-wrap" (click)="toggleAdvanced()" detail="false" [attr.aria-expanded]="advanced"
|
||||||
[attr.aria-label]="(advanced ? 'core.hideadvanced' : 'core.showadvanced') | translate" role="heading"
|
[attr.aria-label]="(advanced ? 'core.hideadvanced' : 'core.showadvanced') | translate" role="heading"
|
||||||
aria-controls="addon-mod-forum-new-discussion-advanced">
|
aria-controls="addon-mod-forum-new-discussion-advanced">
|
||||||
<ion-icon *ngIf="!advanced" name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true"
|
<ion-icon name="fas-chevron-right" flip-rtl slot="start" aria-hidden="true" class="expandable-status-icon"
|
||||||
class="expandable-status-icon"></ion-icon>
|
[class.expandable-status-icon-expanded]="advanced"></ion-icon>
|
||||||
<ion-icon *ngIf="advanced" name="fas-chevron-down" slot="start" aria-hidden="true" class="expandable-status-icon">
|
|
||||||
</ion-icon>
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_forum.advanced' | translate }}</h2>
|
<h2>{{ 'addon.mod_forum.advanced' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -46,7 +46,7 @@
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<div *ngIf="entry.attachment" lines="none">
|
<div *ngIf="entry.attachment">
|
||||||
<core-file *ngFor="let file of entry.attachments" [file]="file" [component]="component" [componentId]="componentId">
|
<core-file *ngFor="let file of entry.attachments" [file]="file" [component]="component" [componentId]="componentId">
|
||||||
</core-file>
|
</core-file>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -36,13 +36,13 @@
|
||||||
<!-- Attempt summary. -->
|
<!-- Attempt summary. -->
|
||||||
<ion-card class="addon-mod_h5pactivity-attempt-result-summary">
|
<ion-card class="addon-mod_h5pactivity-attempt-result-summary">
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_h5pactivity.startdate' | translate }}</h2>
|
<h2>{{ 'addon.mod_h5pactivity.startdate' | translate }}</h2>
|
||||||
<p>{{ attempt.timecreated | coreFormatDate:'strftimedatetime' }}</p>
|
<p>{{ attempt.timecreated | coreFormatDate:'strftimedatetime' }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_h5pactivity.completion' | translate }}</h2>
|
<h2>{{ 'addon.mod_h5pactivity.completion' | translate }}</h2>
|
||||||
<p *ngIf="attempt.completion">
|
<p *ngIf="attempt.completion">
|
||||||
|
@ -55,13 +55,13 @@
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_h5pactivity.duration' | translate }}</h2>
|
<h2>{{ 'addon.mod_h5pactivity.duration' | translate }}</h2>
|
||||||
<p>{{ attempt.durationReadable }}</p>
|
<p>{{ attempt.durationReadable }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_h5pactivity.outcome' | translate }}</h2>
|
<h2>{{ 'addon.mod_h5pactivity.outcome' | translate }}</h2>
|
||||||
<p *ngIf="attempt.success !== null && attempt.success">
|
<p *ngIf="attempt.success !== null && attempt.success">
|
||||||
|
@ -77,7 +77,7 @@
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="attempt.maxscore" class="ion-text-wrap" lines="none">
|
<ion-item *ngIf="attempt.maxscore" class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_h5pactivity.totalscore' | translate }}</h2>
|
<h2>{{ 'addon.mod_h5pactivity.totalscore' | translate }}</h2>
|
||||||
<p>{{ 'addon.mod_h5pactivity.score_out_of' | translate:{$a: attempt} }}</p>
|
<p>{{ 'addon.mod_h5pactivity.score_out_of' | translate:{$a: attempt} }}</p>
|
||||||
|
@ -151,7 +151,7 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<!-- Result doesn't support tracking. -->
|
<!-- Result doesn't support tracking. -->
|
||||||
<ion-item class="ion-text-wrap core-warning-item" *ngIf="!result.track" lines="none">
|
<ion-item class="ion-text-wrap core-warning-item" *ngIf="!result.track">
|
||||||
<ion-icon slot="start" name="fas-exclamation-triangle" color="warning" aria-hidden="true"></ion-icon>
|
<ion-icon slot="start" name="fas-exclamation-triangle" color="warning" aria-hidden="true"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
{{ 'addon.mod_h5pactivity.no_compatible_track' | translate:{$a: result.interactiontype} }}
|
{{ 'addon.mod_h5pactivity.no_compatible_track' | translate:{$a: result.interactiontype} }}
|
||||||
|
|
|
@ -69,7 +69,7 @@
|
||||||
<ion-list *ngIf="(lesson && !preventReasons.length) || retakeToReview">
|
<ion-list *ngIf="(lesson && !preventReasons.length) || retakeToReview">
|
||||||
<ng-container *ngIf="retakeToReview">
|
<ng-container *ngIf="retakeToReview">
|
||||||
<!-- A retake was finished in a synchronization, allow reviewing it. -->
|
<!-- A retake was finished in a synchronization, allow reviewing it. -->
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label class="ion-padding-bottom">
|
<ion-label class="ion-padding-bottom">
|
||||||
{{ 'addon.mod_lesson.retakefinishedinsync' | translate }}
|
{{ 'addon.mod_lesson.retakefinishedinsync' | translate }}
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -198,34 +198,34 @@
|
||||||
<ion-card-header class="ion-text-wrap" *ngIf="eolData.gradelesson">
|
<ion-card-header class="ion-text-wrap" *ngIf="eolData.gradelesson">
|
||||||
<ion-card-title>{{ 'addon.mod_lesson.congratulations' | translate }}</ion-card-title>
|
<ion-card-title>{{ 'addon.mod_lesson.congratulations' | translate }}</ion-card-title>
|
||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.notenoughtimespent" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.notenoughtimespent">
|
||||||
<ion-label>{{ eolData.notenoughtimespent.message }}</ion-label>
|
<ion-label>{{ eolData.notenoughtimespent.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.numberofpagesviewed" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.numberofpagesviewed">
|
||||||
<ion-label>{{ eolData.numberofpagesviewed.message }}</ion-label>
|
<ion-label>{{ eolData.numberofpagesviewed.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.youshouldview" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.youshouldview">
|
||||||
<ion-label>{{ eolData.youshouldview.message }}</ion-label>
|
<ion-label>{{ eolData.youshouldview.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.numberofcorrectanswers" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.numberofcorrectanswers">
|
||||||
<ion-label>{{ eolData.numberofcorrectanswers.message }}</ion-label>
|
<ion-label>{{ eolData.numberofcorrectanswers.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.displayscorewithessays" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.displayscorewithessays">
|
||||||
<ion-label [innerHTML]="eolData.displayscorewithessays.message"></ion-label>
|
<ion-label [innerHTML]="eolData.displayscorewithessays.message"></ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="!eolData.displayscorewithessays && eolData.displayscorewithoutessays" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="!eolData.displayscorewithessays && eolData.displayscorewithoutessays">
|
||||||
<ion-label>{{ eolData.displayscorewithoutessays.message }}</ion-label>
|
<ion-label>{{ eolData.displayscorewithoutessays.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.yourcurrentgradeisoutof" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.yourcurrentgradeisoutof">
|
||||||
<ion-label>{{ eolData.yourcurrentgradeisoutof.message }}</ion-label>
|
<ion-label>{{ eolData.yourcurrentgradeisoutof.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.eolstudentoutoftimenoanswers" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.eolstudentoutoftimenoanswers">
|
||||||
<ion-label>{{ eolData.eolstudentoutoftimenoanswers.message }}</ion-label>
|
<ion-label>{{ eolData.eolstudentoutoftimenoanswers.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.welldone" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.welldone">
|
||||||
<ion-label>{{ eolData.welldone.message }}</ion-label>
|
<ion-label>{{ eolData.welldone.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="lesson.progressbar && eolData.progresscompleted" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="lesson.progressbar && eolData.progresscompleted">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<span id="addon-mod_lesson-{{cmId}}-progress-end">
|
<span id="addon-mod_lesson-{{cmId}}-progress-end">
|
||||||
{{ 'addon.mod_lesson.progresscompleted' | translate:{$a: eolData.progresscompleted.value} }}
|
{{ 'addon.mod_lesson.progresscompleted' | translate:{$a: eolData.progresscompleted.value} }}
|
||||||
|
@ -235,14 +235,14 @@
|
||||||
</core-progress-bar>
|
</core-progress-bar>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.displayofgrade" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.displayofgrade">
|
||||||
<ion-label>{{ eolData.displayofgrade.message }}</ion-label>
|
<ion-label>{{ eolData.displayofgrade.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-button *ngIf="eolData.reviewlesson" expand="block" class="ion-text-wrap ion-margin button-no-uppercase"
|
<ion-button *ngIf="eolData.reviewlesson" expand="block" class="ion-text-wrap ion-margin button-no-uppercase"
|
||||||
(click)="reviewLesson(reviewPageId!)">
|
(click)="reviewLesson(reviewPageId!)">
|
||||||
{{ 'addon.mod_lesson.reviewlesson' | translate }}
|
{{ 'addon.mod_lesson.reviewlesson' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="eolData.modattemptsnoteacher" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="eolData.modattemptsnoteacher">
|
||||||
<ion-label>{{ eolData.modattemptsnoteacher.message }}</ion-label>
|
<ion-label>{{ eolData.modattemptsnoteacher.message }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<!-- If activity link was successfully formatted, render the button. -->
|
<!-- If activity link was successfully formatted, render the button. -->
|
||||||
|
@ -252,7 +252,7 @@
|
||||||
[courseId]="courseId">
|
[courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="activityLink && !activityLink.formatted" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="activityLink && !activityLink.formatted">
|
||||||
<!-- Activity link wasn't formatted, render the original link. -->
|
<!-- Activity link wasn't formatted, render the original link. -->
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="activityLink.label" contextLevel="module" [contextInstanceId]="lesson?.coursemodule"
|
<core-format-text [text]="activityLink.label" contextLevel="module" [contextInstanceId]="lesson?.coursemodule"
|
||||||
|
|
|
@ -83,7 +83,7 @@
|
||||||
<ion-card-header class="ion-text-wrap">
|
<ion-card-header class="ion-text-wrap">
|
||||||
<ion-card-title>{{page.qtype}}: {{page.title}}</ion-card-title>
|
<ion-card-title>{{page.qtype}}: {{page.title}}</ion-card-title>
|
||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'addon.mod_lesson.question' | translate }}</h3>
|
<h3 class="item-heading">{{ 'addon.mod_lesson.question' | translate }}</h3>
|
||||||
<p>
|
<p>
|
||||||
|
@ -94,13 +94,12 @@
|
||||||
</p>
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'addon.mod_lesson.answer' | translate }}</h3>
|
<h3 class="item-heading">{{ 'addon.mod_lesson.answer' | translate }}</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none"
|
<ion-item class="ion-text-wrap" *ngIf="!page.answerdata || !page.answerdata.answers || !page.answerdata.answers.length">
|
||||||
*ngIf="!page.answerdata || !page.answerdata.answers || !page.answerdata.answers.length">
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'addon.mod_lesson.didnotanswerquestion' | translate }}</p>
|
<p>{{ 'addon.mod_lesson.didnotanswerquestion' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -108,7 +107,7 @@
|
||||||
<div *ngIf="page.answerdata && page.answerdata.answers && page.answerdata.answers.length"
|
<div *ngIf="page.answerdata && page.answerdata.answers && page.answerdata.answers.length"
|
||||||
class="addon-mod_lesson-answer">
|
class="addon-mod_lesson-answer">
|
||||||
<ng-container *ngFor="let answer of page.answerdata.answers">
|
<ng-container *ngFor="let answer of page.answerdata.answers">
|
||||||
<ion-item lines="none" *ngIf="page.isContent">
|
<ion-item *ngIf="page.isContent">
|
||||||
<ion-label class="ion-text-wrap">
|
<ion-label class="ion-text-wrap">
|
||||||
<ion-grid class="ion-no-padding">
|
<ion-grid class="ion-no-padding">
|
||||||
<!-- Content page, display a button and the content. -->
|
<!-- Content page, display a button and the content. -->
|
||||||
|
@ -151,7 +150,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Short answer or numeric. -->
|
<!-- Short answer or numeric. -->
|
||||||
<ion-item class="ion-text-wrap" *ngIf="answer[0].isText" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="answer[0].isText">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ answer[0].value }}</p>
|
<p>{{ answer[0].value }}</p>
|
||||||
<ion-badge *ngIf="answer[1]" color="dark">
|
<ion-badge *ngIf="answer[1]" color="dark">
|
||||||
|
@ -164,7 +163,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Matching. -->
|
<!-- Matching. -->
|
||||||
<ion-item lines="none" *ngIf="answer[0].isSelect">
|
<ion-item *ngIf="answer[0].isSelect">
|
||||||
<ion-label class="ion-text-wrap">
|
<ion-label class="ion-text-wrap">
|
||||||
<ion-grid class="ion-no-padding">
|
<ion-grid class="ion-no-padding">
|
||||||
<ion-row>
|
<ion-row>
|
||||||
|
@ -191,8 +190,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Essay or couldn't determine. -->
|
<!-- Essay or couldn't determine. -->
|
||||||
<ion-item class="ion-text-wrap" lines="none"
|
<ion-item class="ion-text-wrap" *ngIf="!answer[0].isCheckbox && !answer[0].isText && !answer[0].isSelect">
|
||||||
*ngIf="!answer[0].isCheckbox && !answer[0].isText && !answer[0].isSelect">
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>
|
<p>
|
||||||
<core-format-text [component]="component" [componentId]="lesson?.coursemodule"
|
<core-format-text [component]="component" [componentId]="lesson?.coursemodule"
|
||||||
|
@ -210,7 +208,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="!page.isContent && !page.isQuestion" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="!page.isContent && !page.isQuestion">
|
||||||
<!-- Another page (end of branch, ...). -->
|
<!-- Another page (end of branch, ...). -->
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>
|
<p>
|
||||||
|
@ -227,7 +225,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="page.answerdata.response" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="page.answerdata.response">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'addon.mod_lesson.response' | translate }}</h3>
|
<h3 class="item-heading">{{ 'addon.mod_lesson.response' | translate }}</h3>
|
||||||
<p>
|
<p>
|
||||||
|
|
|
@ -17,7 +17,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 *ngIf="attempt" lines="none">
|
<ion-list *ngIf="attempt">
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_quiz.attemptnumber' | translate }}</h2>
|
<h2>{{ 'addon.mod_quiz.attemptnumber' | translate }}</h2>
|
||||||
|
|
|
@ -31,7 +31,7 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-card-title>
|
</ion-card-title>
|
||||||
</ion-card-header>
|
</ion-card-header>
|
||||||
<ion-list lines="none">
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'addon.mod_quiz.startedon' | translate }}</h2>
|
<h2>{{ 'addon.mod_quiz.startedon' | translate }}</h2>
|
||||||
|
|
|
@ -57,7 +57,7 @@
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="!edit && workshop.overallfeedbackfiles && data.assessment?.feedbackattachmentfiles?.length" lines="none">
|
<ion-item *ngIf="!edit && workshop.overallfeedbackfiles && data.assessment?.feedbackattachmentfiles?.length">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-files [files]="data.assessment?.feedbackattachmentfiles" [component]="component" [componentId]="componentId">
|
<core-files [files]="data.assessment?.feedbackattachmentfiles" [component]="component" [componentId]="componentId">
|
||||||
</core-files>
|
</core-files>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-card *ngFor="let notification of notifications">
|
<ion-card *ngFor="let notification of notifications">
|
||||||
<ion-item class="ion-text-wrap" lines="none" [attr.aria-label]="
|
<ion-item class="ion-text-wrap" [attr.aria-label]="
|
||||||
notification.timeread
|
notification.timeread
|
||||||
? notification.subject
|
? notification.subject
|
||||||
: 'addon.notifications.unreadnotification' | translate: {$a: notification.subject}">
|
: 'addon.notifications.unreadnotification' | translate: {$a: notification.subject}">
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-item class="ion-text-wrap" lines="none" [attr.aria-label]="subject">
|
<ion-item class="ion-text-wrap" [attr.aria-label]="subject">
|
||||||
<core-user-avatar *ngIf="userIdFrom > 0" slot="start" [userId]="userIdFrom" [profileUrl]="profileImageUrlFrom"
|
<core-user-avatar *ngIf="userIdFrom > 0" slot="start" [userId]="userIdFrom" [profileUrl]="profileImageUrlFrom"
|
||||||
[fullname]="userFromFullName">
|
[fullname]="userFromFullName">
|
||||||
<img *ngIf="iconUrl && !modname" [src]="iconUrl" alt="" role="presentation" class="core-avatar-extra">
|
<img *ngIf="iconUrl && !modname" [src]="iconUrl" alt="" role="presentation" class="core-avatar-extra">
|
||||||
|
|
|
@ -107,11 +107,11 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<!-- Phone view -->
|
<!-- Phone view -->
|
||||||
<ion-item class="ion-text-wrap ion-no-margin ion-hide-md-up" lines="none">
|
<ion-item class="ion-text-wrap ion-no-margin ion-hide-md-up">
|
||||||
<p class="item-heading">{{ notification.displayname }}</p>
|
<p class="item-heading">{{ notification.displayname }}</p>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<!-- If notifications enabled, show toggles. If disabled, show "Disabled" instead of toggle. -->
|
<!-- If notifications enabled, show toggles. If disabled, show "Disabled" instead of toggle. -->
|
||||||
<ion-item *ngFor="let state of ['loggedin', 'loggedoff']" class="ion-text-wrap ion-hide-md-up" lines="none">
|
<ion-item *ngFor="let state of ['loggedin', 'loggedoff']" class="ion-text-wrap ion-hide-md-up">
|
||||||
<ion-label class="ion-margin-horizontal">
|
<ion-label class="ion-margin-horizontal">
|
||||||
<p>{{ 'core.settings.' + state | translate }}</p>
|
<p>{{ 'core.settings.' + state | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -148,7 +148,7 @@
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ng-container *ngFor="let notification of component.notifications">
|
<ng-container *ngFor="let notification of component.notifications">
|
||||||
<!-- If notifications enabled, show toggles. If disabled, show "Disabled" instead of toggle. -->
|
<!-- If notifications enabled, show toggles. If disabled, show "Disabled" instead of toggle. -->
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ notification.displayname }}</p>
|
<p>{{ notification.displayname }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<ion-card-header>
|
<ion-card-header>
|
||||||
<p class="ion-text-wrap ion-no-margin">{{ 'addon.storagemanager.courseinfo' | translate }}</p>
|
<p class="ion-text-wrap ion-no-margin">{{ 'addon.storagemanager.courseinfo' | translate }}</p>
|
||||||
<ion-card-title>{{ title }}</ion-card-title>
|
<ion-card-title>{{ title }}</ion-card-title>
|
||||||
<ion-item class="size ion-text-wrap ion-no-padding" lines="none">
|
<ion-item class="size ion-text-wrap ion-no-padding">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totaldownloads' | translate }}</p>
|
<p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totaldownloads' | translate }}</p>
|
||||||
<ion-badge color="light">{{ totalSize | coreBytesToSize }}</ion-badge>
|
<ion-badge color="light">{{ totalSize | coreBytesToSize }}</ion-badge>
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="size ion-text-wrap" lines="none">
|
<ion-item class="size ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 class="ion-text-wrap">{{ 'addon.storagemanager.coursesspaceusage' | translate }}</h2>
|
<h2 class="ion-text-wrap">{{ 'addon.storagemanager.coursesspaceusage' | translate }}</h2>
|
||||||
<ion-badge color="light">{{ totalSize | coreBytesToSize }}</ion-badge>
|
<ion-badge color="light">{{ totalSize | coreBytesToSize }}</ion-badge>
|
||||||
|
|
|
@ -20,9 +20,7 @@
|
||||||
@include safe-area-padding-end(null, 0px);
|
@include safe-area-padding-end(null, 0px);
|
||||||
height: var(--height);
|
height: var(--height);
|
||||||
color: var(--tabs-color);
|
color: var(--tabs-color);
|
||||||
-webkit-filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow)));
|
border-bottom: 1px solid var(--stroke);
|
||||||
filter: drop-shadow(0px 3px 3px rgba(var(--drop-shadow)));
|
|
||||||
border: 0;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-end;
|
align-items: flex-end;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item lines="none" class="core-timer" role="timer" [ngClass]="{'ion-text-center': align == 'center', 'ion-text-end': align == 'right'}">
|
<ion-item class="core-timer" role="timer" [ngClass]="{'ion-text-center': align == 'center', 'ion-text-end': align == 'right'}">
|
||||||
<ion-icon name="fas-clock" slot="start" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-clock" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<span *ngIf="timeLeft && timeLeft > 0 && timerText" class="core-timer-text">{{ timerText }}</span>
|
<span *ngIf="timeLeft && timeLeft > 0 && timerText" class="core-timer-text">{{ timerText }}</span>
|
||||||
|
|
|
@ -0,0 +1,187 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { Directive, ElementRef, Input, OnInit } from '@angular/core';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { Translate } from '@singletons';
|
||||||
|
import { CoreEventLoadingChangedData, CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
|
|
||||||
|
const defaultMaxHeight = 56;
|
||||||
|
const buttonHeight = 44;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Directive to make an element collapsible.
|
||||||
|
*
|
||||||
|
* Example usage:
|
||||||
|
*
|
||||||
|
* <div collapsible-item>
|
||||||
|
*/
|
||||||
|
@Directive({
|
||||||
|
selector: '[collapsible-item]',
|
||||||
|
})
|
||||||
|
export class CoreCollapsibleItemDirective implements OnInit {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Max height in pixels to render the content box. It should be 56 at least to make sense.
|
||||||
|
* Using this parameter will force display: block to calculate height better.
|
||||||
|
* If you want to avoid this use class="inline" at the same time to use display: inline-block.
|
||||||
|
*/
|
||||||
|
@Input('collapsible-item') height: number | string = defaultMaxHeight;
|
||||||
|
|
||||||
|
protected element: HTMLElement;
|
||||||
|
protected toggleExpandEnabled = false;
|
||||||
|
protected expanded = false;
|
||||||
|
protected maxHeight = defaultMaxHeight;
|
||||||
|
protected loadingChangedListener?: CoreEventObserver;
|
||||||
|
|
||||||
|
constructor(el: ElementRef<HTMLElement>) {
|
||||||
|
this.element = el.nativeElement;
|
||||||
|
|
||||||
|
this.element.addEventListener('click', this.elementClicked.bind(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnInit(): void {
|
||||||
|
if (typeof this.height === 'string') {
|
||||||
|
this.maxHeight = this.height === ''
|
||||||
|
? defaultMaxHeight
|
||||||
|
: parseInt(this.height, 10);
|
||||||
|
} else {
|
||||||
|
this.maxHeight = this.height;
|
||||||
|
}
|
||||||
|
this.maxHeight = this.maxHeight < defaultMaxHeight ? defaultMaxHeight : this.maxHeight;
|
||||||
|
|
||||||
|
if (!this.maxHeight || (window.innerWidth > 576 && window.innerHeight > 576)) {
|
||||||
|
// Do not collapse on big screens.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate the height now.
|
||||||
|
this.calculateHeight();
|
||||||
|
setTimeout(() => this.calculateHeight(), 200); // Try again, sometimes the first calculation is wrong.
|
||||||
|
|
||||||
|
this.setExpandButtonEnabled(false);
|
||||||
|
|
||||||
|
// Recalculate the height if a parent core-loading displays the content.
|
||||||
|
this.loadingChangedListener =
|
||||||
|
CoreEvents.on(CoreEvents.CORE_LOADING_CHANGED, (data: CoreEventLoadingChangedData) => {
|
||||||
|
if (data.loaded && CoreDomUtils.closest(this.element.parentElement, '#' + data.uniqueId)) {
|
||||||
|
// The format-text is inside the loading, re-calculate the height.
|
||||||
|
this.calculateHeight();
|
||||||
|
setTimeout(() => this.calculateHeight(), 200);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the height and check if we need to display show more or not.
|
||||||
|
*/
|
||||||
|
protected calculateHeight(): void {
|
||||||
|
// @todo: Work on calculate this height better.
|
||||||
|
if (!this.maxHeight) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove max-height (if any) to calculate the real height.
|
||||||
|
const initialMaxHeight = this.element.style.maxHeight;
|
||||||
|
this.element.style.maxHeight = '';
|
||||||
|
|
||||||
|
const height = CoreDomUtils.getElementHeight(this.element) || 0;
|
||||||
|
|
||||||
|
// Restore the max height now.
|
||||||
|
this.element.style.maxHeight = initialMaxHeight;
|
||||||
|
|
||||||
|
// If cannot calculate height, shorten always.
|
||||||
|
this.setExpandButtonEnabled(!height || height > this.maxHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets if expand button is enabled or not.
|
||||||
|
*
|
||||||
|
* @param enable Wether enable or disable.
|
||||||
|
*/
|
||||||
|
protected setExpandButtonEnabled(enable: boolean): void {
|
||||||
|
this.toggleExpandEnabled = enable;
|
||||||
|
this.element.classList.toggle('collapsible-enabled', enable);
|
||||||
|
|
||||||
|
if (!enable || this.element.querySelector('ion-button.collapsible-toggle')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add expand/collapse buttons
|
||||||
|
const toggleButton = document.createElement('ion-button');
|
||||||
|
toggleButton.classList.add('collapsible-toggle');
|
||||||
|
toggleButton.setAttribute('fill', 'clear');
|
||||||
|
|
||||||
|
const toggleText = document.createElement('span');
|
||||||
|
toggleText.classList.add('collapsible-toggle-text');
|
||||||
|
toggleButton.appendChild(toggleText);
|
||||||
|
|
||||||
|
const expandArrow = document.createElement('span');
|
||||||
|
expandArrow.classList.add('collapsible-toggle-arrow');
|
||||||
|
toggleButton.appendChild(expandArrow);
|
||||||
|
|
||||||
|
this.element.appendChild(toggleButton);
|
||||||
|
|
||||||
|
this.toggleExpand(this.expanded);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Expand or collapse text.
|
||||||
|
*
|
||||||
|
* @param expand Wether expand or collapse text. If undefined, will toggle.
|
||||||
|
*/
|
||||||
|
protected toggleExpand(expand?: boolean): void {
|
||||||
|
if (expand === undefined) {
|
||||||
|
expand = !this.expanded;
|
||||||
|
}
|
||||||
|
this.expanded = expand;
|
||||||
|
this.element.classList.toggle('collapsible-expanded', expand);
|
||||||
|
this.element.classList.toggle('collapsible-collapsed', !expand);
|
||||||
|
this.element.style.maxHeight = expand ? '' : (this.maxHeight + buttonHeight) + 'px';
|
||||||
|
|
||||||
|
const toggleButton = this.element.querySelector('ion-button.collapsible-toggle');
|
||||||
|
const toggleText = toggleButton?.querySelector('.collapsible-toggle-text');
|
||||||
|
if (!toggleButton || !toggleText) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
toggleText.innerHTML = expand ? Translate.instant('core.showless') : Translate.instant('core.showmore');
|
||||||
|
toggleButton.setAttribute('aria-expanded', expand ? 'true' : 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listener to call when the element is clicked.
|
||||||
|
*
|
||||||
|
* @param e Click event.
|
||||||
|
*/
|
||||||
|
protected elementClicked(e: MouseEvent): void {
|
||||||
|
if (e.defaultPrevented) {
|
||||||
|
// Ignore it if the event was prevented by some other listener.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.toggleExpandEnabled) {
|
||||||
|
// Nothing to do on click, just stop.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
this.toggleExpand();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -29,6 +29,7 @@ import { CoreOnResizeDirective } from './on-resize';
|
||||||
import { CoreDownloadFileDirective } from './download-file';
|
import { CoreDownloadFileDirective } from './download-file';
|
||||||
import { CoreCollapsibleHeaderDirective } from './collapsible-header';
|
import { CoreCollapsibleHeaderDirective } from './collapsible-header';
|
||||||
import { CoreSwipeNavigationDirective } from './swipe-navigation';
|
import { CoreSwipeNavigationDirective } from './swipe-navigation';
|
||||||
|
import { CoreCollapsibleItemDirective } from './collapsible-item';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -47,6 +48,7 @@ import { CoreSwipeNavigationDirective } from './swipe-navigation';
|
||||||
CoreDownloadFileDirective,
|
CoreDownloadFileDirective,
|
||||||
CoreCollapsibleHeaderDirective,
|
CoreCollapsibleHeaderDirective,
|
||||||
CoreSwipeNavigationDirective,
|
CoreSwipeNavigationDirective,
|
||||||
|
CoreCollapsibleItemDirective,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
CoreAutoFocusDirective,
|
CoreAutoFocusDirective,
|
||||||
|
@ -64,6 +66,7 @@ import { CoreSwipeNavigationDirective } from './swipe-navigation';
|
||||||
CoreDownloadFileDirective,
|
CoreDownloadFileDirective,
|
||||||
CoreCollapsibleHeaderDirective,
|
CoreCollapsibleHeaderDirective,
|
||||||
CoreSwipeNavigationDirective,
|
CoreSwipeNavigationDirective,
|
||||||
|
CoreCollapsibleItemDirective,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CoreDirectivesModule {}
|
export class CoreDirectivesModule {}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<!-- Only render the block if it's supported. -->
|
<!-- Only render the block if it's supported. -->
|
||||||
<div *ngIf="loaded && componentClass && block.visible" class="{{class}}">
|
<ion-card *ngIf="loaded && componentClass && block.visible" class="{{class}}">
|
||||||
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
|
<core-dynamic-component [component]="componentClass" [data]="data"></core-dynamic-component>
|
||||||
</div>
|
</ion-card>
|
||||||
|
|
|
@ -13,31 +13,32 @@
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label">
|
<ion-list id="core-course-section-selector" role="listbox" aria-labelledby="core-course-section-selector-label">
|
||||||
<ng-container *ngFor="let section of sectionsToRender">
|
<ng-container *ngFor="let section of sectionsToRender">
|
||||||
<ion-item *ngIf="allSectionId == section.id" class="ion-text-wrap 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">
|
(click)="selectSectionOrModule($event, section.id)" button [class.item-current]="selectedId === section.id" detail="false">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<h2>
|
||||||
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</p>
|
</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-container *ngIf="allSectionId != section.id">
|
<ng-container *ngIf="allSectionId != section.id">
|
||||||
<ion-item class="ion-text-wrap divider section" (click)="selectSectionOrModule($event, section.id)" button
|
<ion-item class="divider section" (click)="selectSectionOrModule($event, section.id)" button
|
||||||
[class.item-current]="selectedId === section.id" [class.item-dimmed]="section.visible === 0" detail="false"
|
[class.item-current]="selectedId === section.id" [class.item-dimmed]="section.visible === 0" detail="false"
|
||||||
sticky="true">
|
sticky="true">
|
||||||
<ion-icon *ngIf="section.hasVisibleModules" [name]="section.expanded ? 'fas-chevron-down' : 'fas-chevron-right'"
|
<ion-icon *ngIf="section.hasVisibleModules" name="fas-chevron-right" flip-rtl slot="start"
|
||||||
flip-rtl slot="start" class="expandable-status-icon" (click)="toggleExpand($event, section)"
|
class="expandable-status-icon" (click)="toggleExpand($event, section)"
|
||||||
[attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate"
|
[attr.aria-label]="(section.expanded ? 'core.collapse' : 'core.expand') | translate"
|
||||||
[attr.aria-expanded]="section.expanded" [attr.aria-controls]="'core-course-index-section-' + section.id">
|
[attr.aria-expanded]="section.expanded" [attr.aria-controls]="'core-course-index-section-' + section.id"
|
||||||
|
[class.expandable-status-icon-expanded]="section.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-icon *ngIf="!section.hasVisibleModules" name="" slot="start" aria-hidden="true" class="expandable-status-icon">
|
<ion-icon *ngIf="!section.hasVisibleModules" name="" slot="start" aria-hidden="true" class="expandable-status-icon">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">
|
<h2>
|
||||||
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course?.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</p>
|
</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-badge *ngIf="section.highlighted && highlighted">{{highlighted}}</ion-badge>
|
<ion-badge *ngIf="section.highlighted && highlighted">{{highlighted}}</ion-badge>
|
||||||
<ion-icon name="fas-lock" *ngIf="section.availabilityinfo" slot="end" class="restricted"
|
<ion-icon name="fas-lock" *ngIf="section.availabilityinfo" slot="end" class="restricted"
|
||||||
|
@ -45,8 +46,8 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-container *ngIf="section.expanded">
|
<ng-container *ngIf="section.expanded">
|
||||||
<ng-container *ngFor="let module of section.modules">
|
<ng-container *ngFor="let module of section.modules">
|
||||||
<ion-item [class.item-dimmed]="!module.visible" (click)="selectSectionOrModule($event, section.id, module.id)"
|
<ion-item class="module" [class.item-dimmed]="!module.visible"
|
||||||
button>
|
(click)="selectSectionOrModule($event, section.id, module.id)" button>
|
||||||
<ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined"
|
<ion-icon class="completioninfo completion_none" name="" *ngIf="module.completionStatus === undefined"
|
||||||
slot="start" aria-hidden="true"></ion-icon>
|
slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-icon class="completioninfo completion_incomplete" name="far-circle" *ngIf="module.completionStatus === 0"
|
<ion-icon class="completioninfo completion_incomplete" name="far-circle" *ngIf="module.completionStatus === 0"
|
||||||
|
|
|
@ -16,21 +16,31 @@ ion-icon.completioninfo {
|
||||||
width: 18px;
|
width: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-item::part(native) {
|
ion-item.module::part(native) {
|
||||||
--padding-start: 0;
|
--padding-start: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-icon {
|
ion-item.module ion-icon {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@include padding(12px, 32px, 12px, 16px);
|
@include padding(12px, 16px, 12px, 16px);
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-item.core-course-index-all::part(native) {
|
ion-item.core-course-index-all::part(native) {
|
||||||
--padding-start: 16px;
|
--padding-start: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-item.item-current ion-icon.expandable-status-icon {
|
ion-item.item.item-current {
|
||||||
@include padding(null, null, null, 11px);
|
--background: var(--primary);
|
||||||
|
--color: var(--primary-contrast);
|
||||||
|
border: 0;
|
||||||
|
|
||||||
|
ion-badge {
|
||||||
|
border: 1px solid var(--primary-contrast);
|
||||||
|
}
|
||||||
|
|
||||||
|
::ng-deep ion-icon {
|
||||||
|
color: var(--primary-contrast);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-icon.restricted {
|
ion-icon.restricted {
|
||||||
|
|
|
@ -23,7 +23,6 @@ import { CoreCourseFormatDelegate } from '@features/course/services/format-deleg
|
||||||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||||
import { IonContent } from '@ionic/angular';
|
import { IonContent } from '@ionic/angular';
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
|
||||||
import { ModalController } from '@singletons';
|
import { ModalController } from '@singletons';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,12 +61,11 @@ export class CoreCourseCourseIndexComponent implements OnInit {
|
||||||
}
|
}
|
||||||
|
|
||||||
let completionEnabled = !!this.course.enablecompletion;
|
let completionEnabled = !!this.course.enablecompletion;
|
||||||
if (completionEnabled && 'courseformatoptions' in this.course && this.course.courseformatoptions) {
|
if (completionEnabled && 'completionusertracked' in this.course && this.course.completionusertracked !== undefined) {
|
||||||
const formatOptions = CoreUtils.objectToKeyValueMap(this.course.courseformatoptions, 'name', 'value');
|
completionEnabled = this.course.completionusertracked;
|
||||||
|
}
|
||||||
if (formatOptions) {
|
if (completionEnabled && 'showcompletionconditions' in this.course && this.course.showcompletionconditions !== undefined) {
|
||||||
completionEnabled = !!formatOptions.completionusertracked;
|
completionEnabled = this.course.showcompletionconditions;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const currentSection = await CoreCourseFormatDelegate.getCurrentSection(this.course, this.sections);
|
const currentSection = await CoreCourseFormatDelegate.getCurrentSection(this.course, this.sections);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<core-navbar-buttons slot="end" *ngIf="loaded">
|
<core-navbar-buttons slot="end" *ngIf="loaded">
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item [hidden]="!displayCourseIndex || !sections || !sections.length" [priority]="500"
|
<core-context-menu-item [hidden]="!displayCourseIndex || !sections || !sections.length" [priority]="500"
|
||||||
[content]="'core.course.courseindex' | translate" (action)="openCourseIndex()" iconAction="menu">
|
[content]="'core.course.courseindex' | translate" (action)="openCourseIndex()" iconAction="fas-list-ul">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
@ -66,25 +66,22 @@
|
||||||
<!-- Template to render a section. -->
|
<!-- Template to render a section. -->
|
||||||
<ng-template #sectionTemplate let-section="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="section-wrapper" [id]="section.id">
|
class="core-course-module-list-wrapper" [id]="section.id">
|
||||||
<ion-item-divider class="course-section ion-text-wrap" color="light"
|
<ion-item-divider class="course-section ion-text-wrap" [class.item-dimmed]="section.visible === 0 || section.uservisible === false">
|
||||||
[class.item-dimmed]="section.visible === 0 || section.uservisible === false">
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 *ngIf="section.name">
|
<h2 *ngIf="section.name" class="big">
|
||||||
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</h2>
|
</h2>
|
||||||
<div *ngIf="section.visible === 0 && section.uservisible !== false">
|
<div *ngIf="section.visible === 0 && section.uservisible !== false">
|
||||||
<ion-chip>
|
<ion-badge color="warning">
|
||||||
<ion-icon name="fas-eye-slash" aria-hidden="true"></ion-icon>
|
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||||
<ion-label>{{ 'core.course.hiddenfromstudents' | translate }}</ion-label>
|
</ion-badge>
|
||||||
</ion-chip>
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="section.visible === 0 && section.uservisible === false">
|
<div *ngIf="section.visible === 0 && section.uservisible === false">
|
||||||
<ion-chip>
|
<ion-badge color="warning">
|
||||||
<ion-icon name="fas-eye-slash" aria-hidden="true"></ion-icon>
|
{{ 'core.notavailable' | translate }}
|
||||||
<ion-label>{{ 'core.notavailable' | translate }}</ion-label>
|
</ion-badge>
|
||||||
</ion-chip>
|
|
||||||
</div>
|
</div>
|
||||||
<div *ngIf="section.availabilityinfo">
|
<div *ngIf="section.availabilityinfo">
|
||||||
<ion-chip>
|
<ion-chip>
|
||||||
|
@ -99,7 +96,7 @@
|
||||||
<ion-badge *ngIf="section.highlighted && highlighted" slot="end">{{highlighted}}</ion-badge>
|
<ion-badge *ngIf="section.highlighted && highlighted" slot="end">{{highlighted}}</ion-badge>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" *ngIf="section.summary" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="section.summary">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="section.summary" contextLevel="course" [contextInstanceId]="course.id">
|
<core-format-text [text]="section.summary" contextLevel="course" [contextInstanceId]="course.id">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
|
|
|
@ -10,3 +10,8 @@
|
||||||
flex: 1;
|
flex: 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.course-section {
|
||||||
|
--padding-start: 12px;
|
||||||
|
--inner-padding-end: 12px;
|
||||||
|
}
|
||||||
|
|
|
@ -1,38 +1,63 @@
|
||||||
<div *ngIf="showCompletionConditions && completion && completion.isautomatic" class="core-module-automatic-completion-conditions"
|
<ng-container *ngIf="completion">
|
||||||
role="list" [attr.aria-label]="'core.course.completionrequirements' | translate:{ $a: moduleName }">
|
<ng-container *ngIf="showCompletionConditions && completion.isautomatic">
|
||||||
|
<div *ngIf="mode == 'full'" class="core-module-automatic-completion-conditions" role="list"
|
||||||
|
[attr.aria-label]="'core.course.completionrequirements' | translate:{ $a: moduleName }">
|
||||||
|
|
||||||
<ng-container *ngIf="completion.istrackeduser">
|
<ng-container *ngIf="completion.istrackeduser">
|
||||||
<ng-container *ngFor="let rule of details">
|
<ng-container *ngFor="let rule of details">
|
||||||
<ion-chip *ngIf="rule.statuscomplete" color="success" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
<ion-chip *ngIf="rule.statuscomplete" color="success" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||||
<ion-icon name="fas-check" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-check" [attr.aria-label]="'core.course.completion_automatic:done' | translate "></ion-icon>
|
||||||
<ion-label><strong>{{ 'core.course.completion_automatic:done' | translate }}</strong> {{ rule.rulevalue.description }}
|
<ion-label>
|
||||||
</ion-label>
|
{{ rule.rulevalue.description }}
|
||||||
</ion-chip>
|
</ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
|
||||||
<ion-chip *ngIf="rule.statuscompletefail" color="danger" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
<ion-chip *ngIf="rule.statuscompletefail" color="danger" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||||
<ion-icon name="fas-times" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-times" [attr.aria-label]="'core.course.completion_automatic:failed' | translate "></ion-icon>
|
||||||
<ion-label><strong>{{ 'core.course.completion_automatic:failed' | translate }}</strong> {{ rule.rulevalue.description }}
|
<ion-label>
|
||||||
</ion-label>
|
{{ rule.rulevalue.description }}
|
||||||
</ion-chip>
|
</ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
|
||||||
<ion-chip *ngIf="rule.statusincomplete" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
<ion-chip *ngIf="rule.statusincomplete" color="dark" role="listitem" [attr.aria-label]="rule.accessibleDescription">
|
||||||
|
<ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
{{ rule.rulevalue.description }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
</ng-container>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
<ng-container *ngIf="!completion.istrackeduser">
|
||||||
|
<ion-chip *ngFor="let rule of details" role="listitem">
|
||||||
|
<ion-icon name="fas-edit" [attr.aria-label]="'core.course.completion_automatic:todo' | translate "></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
{{ rule.rulevalue.description }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
</ng-container>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ng-container *ngIf="mode == 'basic' && completion.istrackeduser">
|
||||||
|
<ion-chip class="completioninfo completion_incomplete" *ngIf="completionStatus === 0" color="dark">
|
||||||
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
||||||
<ion-label><strong>{{ 'core.course.completion_automatic:todo' | translate }}</strong> {{ rule.rulevalue.description }}
|
<ion-label>
|
||||||
|
{{ 'core.course.todo' | translate }}
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-chip>
|
</ion-chip>
|
||||||
|
<ion-chip class="completioninfo completion_complete" *ngIf="completionStatus === 1 || completionStatus === 2" color="success">
|
||||||
|
<ion-icon name="fas-check" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>{{'core.course.done' | translate }}</ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
<ion-chip class="completioninfo completion_fail" *ngIf="completionStatus === 3" color="danger">
|
||||||
|
<ion-icon name="fas-times" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>{{'core.course.failed' | translate }}</ion-label>
|
||||||
|
</ion-chip>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="!completion.istrackeduser">
|
|
||||||
<ion-chip *ngFor="let rule of details" role="listitem">
|
|
||||||
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>
|
|
||||||
<strong>{{ 'core.course.completion_automatic:todo' | translate }}</strong> {{ rule.rulevalue.description }}
|
|
||||||
</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</ng-container>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<core-course-module-manual-completion *ngIf="showManualCompletion" [completion]="completion" [moduleName]="moduleName"
|
<core-course-module-manual-completion *ngIf="showManualCompletion" [completion]="completion" [moduleName]="moduleName"
|
||||||
(completionChanged)="completionChanged.emit($event)">
|
(completionChanged)="completionChanged.emit($event)" [mode]="mode">
|
||||||
</core-course-module-manual-completion>
|
</core-course-module-manual-completion>
|
||||||
|
</ng-container>
|
||||||
|
|
|
@ -15,7 +15,12 @@
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, Input } from '@angular/core';
|
||||||
|
|
||||||
import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion';
|
import { CoreCourseModuleCompletionBaseComponent } from '@features/course/classes/module-completion';
|
||||||
import { CoreCourseModuleCompletionStatus, CoreCourseModuleWSRuleDetails } from '@features/course/services/course';
|
import {
|
||||||
|
CoreCourseCompletionMode,
|
||||||
|
CoreCourseModuleCompletionStatus,
|
||||||
|
CoreCourseModuleCompletionTracking,
|
||||||
|
CoreCourseModuleWSRuleDetails,
|
||||||
|
} from '@features/course/services/course';
|
||||||
import { CoreUser } from '@features/user/services/user';
|
import { CoreUser } from '@features/user/services/user';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
|
|
||||||
|
@ -37,9 +42,11 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
||||||
|
|
||||||
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
||||||
@Input() showManualCompletion = false; // Whether to show manual completion.
|
@Input() showManualCompletion = false; // Whether to show manual completion.
|
||||||
|
@Input() mode: CoreCourseCompletionMode = CoreCourseCompletionMode.FULL; // Show full completion status or a basic mode.
|
||||||
|
|
||||||
details?: CompletionRule[];
|
details?: CompletionRule[];
|
||||||
accessibleDescription: string | null = null;
|
accessibleDescription: string | null = null;
|
||||||
|
completionStatus?: CoreCourseModuleCompletionStatus;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
|
@ -49,6 +56,11 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.completionStatus = !this.completion?.istrackeduser ||
|
||||||
|
this.completion.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE
|
||||||
|
? undefined
|
||||||
|
: this.completion.state;
|
||||||
|
|
||||||
// Format rules.
|
// Format rules.
|
||||||
this.details = await Promise.all(this.completion.details.map(async (rule: CompletionRule) => {
|
this.details = await Promise.all(this.completion.details.map(async (rule: CompletionRule) => {
|
||||||
rule.statuscomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE ||
|
rule.statuscomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE ||
|
||||||
|
@ -57,8 +69,8 @@ export class CoreCourseModuleCompletionComponent extends CoreCourseModuleComplet
|
||||||
rule.statusincomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE;
|
rule.statusincomplete = rule.rulevalue.status == CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE;
|
||||||
rule.accessibleDescription = null;
|
rule.accessibleDescription = null;
|
||||||
|
|
||||||
if (this.completion!.overrideby) {
|
if (this.completion?.overrideby) {
|
||||||
const fullName = await CoreUser.getUserFullNameWithDefault(this.completion!.overrideby, this.completion!.courseId);
|
const fullName = await CoreUser.getUserFullNameWithDefault(this.completion.overrideby, this.completion.courseId);
|
||||||
|
|
||||||
const setByData = {
|
const setByData = {
|
||||||
$a: {
|
$a: {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
<ion-item class="ion-text-wrap collapsible-title" lines="none">
|
<ion-item class="ion-text-wrap collapsible-title">
|
||||||
<core-mod-icon slot="start" [modicon]="modicon" [modname]="module.modname" [componentId]="module.instance">
|
<core-mod-icon slot="start" [modicon]="modicon" [modname]="module.modname" [componentId]="module.instance">
|
||||||
</core-mod-icon>
|
</core-mod-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
|
@ -11,7 +11,7 @@
|
||||||
<ng-content select="[title]"></ng-content>
|
<ng-content select="[title]"></ng-content>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" *ngIf="description" lines="none">
|
<ion-item class="ion-text-wrap" *ngIf="description">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
|
<core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
|
||||||
[contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="expandDescription ? null : 120">
|
[contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="expandDescription ? null : 120">
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ng-content select="[description]"></ng-content>
|
<ng-content select="[description]"></ng-content>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap core-module-dates" lines="none" *ngIf="showCompletion && (module.dates?.length ||
|
<ion-item class="ion-text-wrap" *ngIf="showCompletion && (module.dates?.length ||
|
||||||
(module.completiondata && module.completiondata.isautomatic && module.uservisible))">
|
(module.completiondata && module.completiondata.isautomatic && module.uservisible))">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<!-- Activity dates. -->
|
<!-- Activity dates. -->
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
display: block;
|
display: block;
|
||||||
box-shadow: 0px 3px 3px rgba(var(--drop-shadow));
|
|
||||||
margin-bottom: 8px;
|
margin-bottom: 8px;
|
||||||
padding-bottom: 1px; // To allow margins inside.
|
padding-bottom: 1px; // To allow margins inside.
|
||||||
background-color: var(--contrast-background);
|
background-color: var(--contrast-background);
|
||||||
|
@ -17,8 +16,14 @@
|
||||||
align-self: flex-start;
|
align-self: flex-start;
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-module-dates ion-icon {
|
.core-module-dates {
|
||||||
@include margin-horizontal(null, 8px);
|
background: var(--light);
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
padding: 8px;
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
@include margin-horizontal(null, 8px);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
<div *ngIf="completion && !completion.isautomatic" class="core-module-manual-completion">
|
<ng-container *ngIf="completion && !completion.isautomatic">
|
||||||
|
|
||||||
<ng-container *ngIf="completion.istrackeduser">
|
<ng-container *ngIf="completion.istrackeduser">
|
||||||
<ng-container *ngIf="completion.state">
|
<ion-button *ngIf="completion.state" color="success" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)"
|
||||||
<ion-button color="success" fill="outline" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)"
|
class="ion-text-wrap" [class.chip]="mode == 'basic'">
|
||||||
class="ion-text-wrap">
|
<ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-icon name="fas-check" slot="start" aria-hidden="true"></ion-icon>
|
{{ 'core.course.completion_manual:done' | translate }}
|
||||||
{{ 'core.course.completion_manual:done' | translate }}
|
<ion-icon *ngIf="completion?.offline" name="fas-sync" [attr.aria-label]="'core.course.manualcompletionnotsynced' | translate"
|
||||||
</ion-button>
|
slot="end"></ion-icon>
|
||||||
</ng-container>
|
</ion-button>
|
||||||
<ng-container *ngIf="!completion.state">
|
<ion-button *ngIf="!completion.state" color="dark" fill="outline" [attr.aria-label]="accessibleDescription"
|
||||||
<ion-button color="dark" fill="outline" [attr.aria-label]="accessibleDescription" (click)="completionClicked($event)"
|
(click)="completionClicked($event)" class="ion-text-wrap" [class.chip]="mode == 'basic'">
|
||||||
class="ion-text-wrap">
|
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
<ion-icon *ngIf="completion?.offline" name="fas-sync" [attr.aria-label]="'core.course.manualcompletionnotsynced' | translate"
|
||||||
</ion-button>
|
slot="end"></ion-icon>
|
||||||
</ng-container>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="!completion.istrackeduser">
|
<ng-container *ngIf="!completion.istrackeduser">
|
||||||
<ion-button disabled="true" color="dark" fill="outline" class="ion-text-wrap">
|
<ion-button disabled="true" color="dark" fill="outline" class="ion-text-wrap" [class.chip]="mode == 'basic'">
|
||||||
{{ 'core.course.completion_manual:markdone' | translate }}
|
{{ 'core.course.completion_manual:markdone' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</ng-container>
|
||||||
|
|
|
@ -13,8 +13,7 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChange } from '@angular/core';
|
import { Component, EventEmitter, Input, OnChanges, OnDestroy, OnInit, Output, SimpleChange } from '@angular/core';
|
||||||
import { CoreCourseCompletionType } from '@features/course/services/course';
|
import { CoreCourseCompletionMode, CoreCourseCompletionType } from '@features/course/services/course';
|
||||||
|
|
||||||
import { CoreCourseHelper, CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
|
import { CoreCourseHelper, CoreCourseModuleCompletionData } from '@features/course/services/course-helper';
|
||||||
import { CoreUser } from '@features/user/services/user';
|
import { CoreUser } from '@features/user/services/user';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
|
@ -31,6 +30,7 @@ export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChan
|
||||||
|
|
||||||
@Input() completion?: CoreCourseModuleCompletionData; // The completion status.
|
@Input() completion?: CoreCourseModuleCompletionData; // The completion status.
|
||||||
@Input() moduleName?: string; // The name of the module this completion affects.
|
@Input() moduleName?: string; // The name of the module this completion affects.
|
||||||
|
@Input() mode: CoreCourseCompletionMode = CoreCourseCompletionMode.FULL; // Show full completion status or a basic mode.
|
||||||
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when completion changes.
|
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when completion changes.
|
||||||
|
|
||||||
accessibleDescription: string | null = null;
|
accessibleDescription: string | null = null;
|
||||||
|
@ -97,6 +97,9 @@ export class CoreCourseModuleManualCompletionComponent implements OnInit, OnChan
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
await CoreCourseHelper.changeManualCompletion(this.completion, event);
|
await CoreCourseHelper.changeManualCompletion(this.completion, event);
|
||||||
|
|
||||||
// @deprecated MANUAL_COMPLETION_CHANGED is deprecated since 4.0 use COMPLETION_CHANGED instead.
|
// @deprecated MANUAL_COMPLETION_CHANGED is deprecated since 4.0 use COMPLETION_CHANGED instead.
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
display: block;
|
display: block;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 3;
|
z-index: 3;
|
||||||
box-shadow: 0px -3px 3px rgba(var(--drop-shadow));
|
border-top: 1px solid var(--stroke);
|
||||||
|
|
||||||
@include core-transition(all, 200ms);
|
@include core-transition(all, 200ms);
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
<ion-card *ngIf="module.handlerData && module.visibleoncoursepage !== 0">
|
<ion-card *ngIf="module.handlerData && module.visibleoncoursepage !== 0">
|
||||||
<ng-container *ngIf="!module.handlerData.loading">
|
<ng-container *ngIf="!module.handlerData.loading">
|
||||||
<ion-item id="core-course-module-{{module.id}}" detail="false" lines="none"
|
<ion-item id="core-course-module-{{module.id}}" detail="false"
|
||||||
class="ion-text-wrap core-course-module-handler core-module-main-item {{module.handlerData.class}}"
|
class="ion-text-wrap core-course-module-handler core-module-main-item {{module.handlerData.class}}"
|
||||||
(click)="moduleClicked($event)" [attr.aria-label]="module.handlerData.a11yTitle" [ngClass]="{
|
(click)="moduleClicked($event)" [attr.aria-label]="module.handlerData.a11yTitle" [ngClass]="{
|
||||||
'has-module-info': hasInfo,
|
|
||||||
'item-media': module.handlerData.icon,
|
'item-media': module.handlerData.icon,
|
||||||
'item-dimmed': module.visible === 0 || module.uservisible === false
|
'item-dimmed': module.visible === 0 || module.uservisible === false
|
||||||
}" [button]="module.handlerData.action && module.uservisible">
|
}" [button]="module.handlerData.action && module.uservisible">
|
||||||
|
@ -18,26 +17,27 @@
|
||||||
[courseId]="module.course" [attr.aria-label]="module.handlerData.a11yTitle + ', ' + modNameTranslated">
|
[courseId]="module.course" [attr.aria-label]="module.handlerData.a11yTitle + ', ' + modNameTranslated">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</p>
|
</p>
|
||||||
<ion-chip class="completioninfo completion_incomplete" *ngIf="completionStatus === 0">
|
|
||||||
<ion-icon name="fas-edit" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>
|
|
||||||
{{ 'core.course.todo' | translate }}
|
|
||||||
</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
<ion-chip class="completioninfo completion_complete" *ngIf="completionStatus === 1 || completionStatus === 2"
|
|
||||||
color="success">
|
|
||||||
<ion-icon name="fas-check" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>{{'core.course.done' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
<ion-chip class="completioninfo completion_fail" *ngIf="completionStatus === 3" color="danger">
|
|
||||||
<ion-icon name="fas-times" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>{{'core.course.failed' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
|
|
||||||
<ion-chip *ngIf="module.handlerData.extraBadge" [color]="module.handlerData.extraBadgeColor"
|
<div class="core-module-additional-info">
|
||||||
class="ion-text-wrap ion-text-start" [outline]="true">
|
<!-- Basic module completion. -->
|
||||||
<ion-label><span [innerHTML]="module.handlerData.extraBadge"></span></ion-label>
|
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
||||||
</ion-chip>
|
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"
|
||||||
|
[showManualCompletion]="showManualCompletion" (completionChanged)="completionChanged.emit($event)" mode="basic">
|
||||||
|
</core-course-module-completion>
|
||||||
|
|
||||||
|
<ion-chip *ngIf="module.handlerData.extraBadge" [color]="module.handlerData.extraBadgeColor"
|
||||||
|
class="ion-text-wrap ion-text-start" [outline]="true">
|
||||||
|
<ion-label><span [innerHTML]="module.handlerData.extraBadge"></span></ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
|
||||||
|
<!-- Hidden badges -->
|
||||||
|
<ion-badge color="warning" *ngIf="module.visible === 0 && (!section || section.visible)">
|
||||||
|
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||||
|
</ion-badge>
|
||||||
|
<ion-badge color="warning" *ngIf="module.visible !== 0 && module.isStealth">
|
||||||
|
{{ 'core.course.hiddenoncoursepage' | translate }}
|
||||||
|
</ion-badge>
|
||||||
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<!-- Buttons. -->
|
<!-- Buttons. -->
|
||||||
<div slot="end" *ngIf="module.uservisible !== false" class="buttons core-module-buttons"
|
<div slot="end" *ngIf="module.uservisible !== false" class="buttons core-module-buttons"
|
||||||
|
@ -58,61 +58,39 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="hasInfo" id="core-course-module-{{module.id}}-info" detail="false" lines="none"
|
<ion-item *ngIf="hasInfo" id="core-course-module-{{module.id}}-info" detail="false"
|
||||||
class="ion-text-wrap core-course-module-handler core-course-module-info {{module.handlerData.class}}" [ngClass]="{
|
class="ion-text-wrap core-course-module-handler core-course-module-info {{module.handlerData.class}}" [ngClass]="{
|
||||||
'item-media': module.handlerData.icon,
|
'item-media': module.handlerData.icon,
|
||||||
'item-dimmed': module.visible === 0 || module.uservisible === false
|
'item-dimmed': module.visible === 0 || module.uservisible === false
|
||||||
}">
|
}">
|
||||||
<ion-label>
|
<ion-label collapsible-item>
|
||||||
<core-format-text class="core-module-description" *ngIf="module.description" [maxHeight]="80" [text]="module.description"
|
<core-format-text class="core-module-description" *ngIf="module.description" [text]="module.description"
|
||||||
contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
|
contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
|
|
||||||
<!-- Activity dates. -->
|
<!-- Module completion. Only auto conditions-->
|
||||||
<div *ngIf="showActivityDates && module.dates && module.dates.length" class="core-module-dates">
|
|
||||||
<p *ngFor="let date of module.dates">
|
|
||||||
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon><strong>{{ date.label }}</strong> {{ date.timestamp *
|
|
||||||
1000 | coreFormatDate:'strftimedatetime' }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- Module completion. -->
|
|
||||||
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
<core-course-module-completion *ngIf="module.completiondata && module.uservisible" [completion]="module.completiondata"
|
||||||
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions"
|
[moduleName]="module.name" [moduleId]="module.id" [showCompletionConditions]="showCompletionConditions">
|
||||||
[showManualCompletion]="showManualCompletion" (completionChanged)="completionChanged.emit($event)">
|
|
||||||
</core-course-module-completion>
|
</core-course-module-completion>
|
||||||
|
|
||||||
<div *ngIf="module.completiondata?.offline">
|
<div class="core-module-dates-availabilityinfo"
|
||||||
<ion-chip color="warning">
|
*ngIf="(showActivityDates && module.dates && module.dates.length) || module.availabilityinfo">
|
||||||
<ion-icon name="fas-sync" aria-hidden="true"></ion-icon>
|
<!-- Activity dates. -->
|
||||||
<ion-label>{{ 'core.course.manualcompletionnotsynced' | translate }}</ion-label>
|
<div *ngIf="showActivityDates && module.dates && module.dates.length" class="core-module-dates">
|
||||||
</ion-chip>
|
<p *ngFor="let date of module.dates">
|
||||||
</div>
|
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon><strong>{{ date.label }}</strong> {{ date.timestamp
|
||||||
|
*
|
||||||
|
1000 | coreFormatDate:'strftimedatetime' }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Availability -->
|
<!-- Availability info -->
|
||||||
<div *ngIf="module.visible === 0 && (!section || section.visible)">
|
<div *ngIf="module.availabilityinfo" class="core-module-availabilityinfo">
|
||||||
<ion-chip>
|
|
||||||
<ion-icon name="fas-eye-slash" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>{{ 'core.course.hiddenfromstudents' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="module.visible !== 0 && module.isStealth">
|
|
||||||
<ion-chip>
|
|
||||||
<ion-icon name="fas-eye-slash" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>{{ 'core.course.hiddenoncoursepage' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="module.availabilityinfo">
|
|
||||||
<ion-chip class="core-module-availabilityinfo">
|
|
||||||
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
||||||
<ion-label>
|
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
||||||
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
[courseId]="module.course">
|
||||||
[courseId]="module.course">
|
</core-format-text>
|
||||||
</core-format-text>
|
</div>
|
||||||
</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -122,7 +100,7 @@
|
||||||
<!-- Loading. -->
|
<!-- Loading. -->
|
||||||
<ion-item *ngIf="module.handlerData.loading" role="status" class="ion-text-wrap" id="core-course-module-{{module.id}}"
|
<ion-item *ngIf="module.handlerData.loading" role="status" class="ion-text-wrap" id="core-course-module-{{module.id}}"
|
||||||
[attr.aria-label]="module.handlerData.a11yTitle"
|
[attr.aria-label]="module.handlerData.a11yTitle"
|
||||||
[ngClass]="['core-course-module-handler', 'core-module-loading', module.handlerData.class]" detail="false" lines="none">
|
[ngClass]="['core-course-module-handler', 'core-module-loading', module.handlerData.class]" detail="false">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -1,12 +1,16 @@
|
||||||
@import "~theme/globals";
|
@import "~theme/globals";
|
||||||
|
|
||||||
:host {
|
:host {
|
||||||
|
--horizontal-margin: 10px;
|
||||||
|
|
||||||
.item.core-module-main-item {
|
ion-card {
|
||||||
--min-height: 52px;
|
margin-left: var(--horizontal-margin);
|
||||||
|
margin-right: var(--horizontal-margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-module-main-item {
|
ion-item.core-module-main-item {
|
||||||
|
--min-height: 52px;
|
||||||
|
|
||||||
.core-module-buttons,
|
.core-module-buttons,
|
||||||
.buttons.core-module-buttons {
|
.buttons.core-module-buttons {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -31,17 +35,29 @@
|
||||||
.core-module-buttons core-course-module-completion {
|
.core-module-buttons core-course-module-completion {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.core-module-additional-info {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-course-module-info {
|
.core-course-module-info {
|
||||||
ion-badge {
|
.core-module-dates-availabilityinfo {
|
||||||
text-align: start;
|
background: var(--light);
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
padding: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.core-module-dates + .core-module-availabilityinfo {
|
||||||
|
border-top: 1px solid var(--stroke);
|
||||||
|
padding-top: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-module-availabilityinfo {
|
.core-module-availabilityinfo {
|
||||||
font-size: 90%;
|
font-size: 90%;
|
||||||
ul {
|
::ng-deep ul {
|
||||||
margin-block-start: 0.5em;
|
margin-top: 0.5em;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -57,10 +73,6 @@
|
||||||
margin-top: 0px;
|
margin-top: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.core-module-main-item.has-module-info {
|
|
||||||
--inner-border-width: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-module-availabilityinfo ion-icon,
|
.core-module-availabilityinfo ion-icon,
|
||||||
.core-module-dates ion-icon {
|
.core-module-dates ion-icon {
|
||||||
@include margin-horizontal(null, 8px);
|
@include margin-horizontal(null, 8px);
|
||||||
|
|
|
@ -20,7 +20,7 @@ import {
|
||||||
CoreCourseModuleCompletionData,
|
CoreCourseModuleCompletionData,
|
||||||
CoreCourseSection,
|
CoreCourseSection,
|
||||||
} from '@features/course/services/course-helper';
|
} from '@features/course/services/course-helper';
|
||||||
import { CoreCourse, CoreCourseModuleCompletionStatus, CoreCourseModuleCompletionTracking } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate';
|
import { CoreCourseModuleDelegate, CoreCourseModuleHandlerButton } from '@features/course/services/module-delegate';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,7 +47,6 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
hasInfo = false;
|
hasInfo = false;
|
||||||
showLegacyCompletion = false; // Whether to show module completion in the old format.
|
showLegacyCompletion = false; // Whether to show module completion in the old format.
|
||||||
showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
|
showManualCompletion = false; // Whether to show manual completion when completion conditions are disabled.
|
||||||
completionStatus?: CoreCourseModuleCompletionStatus;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being initialized.
|
* Component being initialized.
|
||||||
|
@ -62,20 +61,11 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
|
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
|
||||||
this.completionStatus = this.module.completiondata === undefined ||
|
|
||||||
!this.module.completiondata?.istrackeduser ||
|
|
||||||
this.module.completiondata.tracking == CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE
|
|
||||||
? undefined
|
|
||||||
: this.module.completiondata.state;
|
|
||||||
|
|
||||||
this.hasInfo = !!(
|
this.hasInfo = !!(
|
||||||
this.module.description ||
|
this.module.description ||
|
||||||
(this.showActivityDates && this.module.dates && this.module.dates.length) ||
|
(this.showActivityDates && this.module.dates && this.module.dates.length) ||
|
||||||
(this.module.completiondata &&
|
(this.module.completiondata && this.showCompletionConditions && this.module.completiondata.isautomatic) ||
|
||||||
((this.showManualCompletion && !this.module.completiondata.isautomatic) ||
|
|
||||||
(this.showCompletionConditions && this.module.completiondata.isautomatic))
|
|
||||||
) ||
|
|
||||||
this.module.completiondata?.offline ||
|
|
||||||
(this.module.visible === 0 && (!this.section || this.section.visible)) ||
|
(this.module.visible === 0 && (!this.section || this.section.visible)) ||
|
||||||
(this.module.visible !== 0 && this.module.isStealth) ||
|
(this.module.visible !== 0 && this.module.isStealth) ||
|
||||||
(this.module.availabilityinfo)
|
(this.module.availabilityinfo)
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
<core-navbar-buttons slot="end">
|
<core-navbar-buttons slot="end">
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item [priority]="1800" [content]="'core.course.coursesummary' | translate" (action)="openCourseSummary()"
|
|
||||||
iconAction="fas-info-circle">
|
|
||||||
</core-context-menu-item>
|
|
||||||
<core-context-menu-item *ngFor="let item of courseMenuHandlers" [priority]="item.priority" (action)="openMenuItem(item)"
|
<core-context-menu-item *ngFor="let item of courseMenuHandlers" [priority]="item.priority" (action)="openMenuItem(item)"
|
||||||
[content]="item.data.title | translate" [iconAction]="item.data.icon" [class]="item.data.class">
|
[content]="item.data.title | translate" [iconAction]="item.data.icon" [class]="item.data.class">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
|
|
|
@ -379,16 +379,6 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Open the course summary
|
|
||||||
*/
|
|
||||||
openCourseSummary(): void {
|
|
||||||
CoreNavigator.navigateToSitePath(
|
|
||||||
`/course/${this.course.id}/preview`,
|
|
||||||
{ params: { course: this.course, avoidOpenCourse: true } },
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a menu item registered to the delegate.
|
* Opens a menu item registered to the delegate.
|
||||||
*
|
*
|
||||||
|
|
|
@ -9,29 +9,23 @@
|
||||||
</h1>
|
</h1>
|
||||||
</ion-title>
|
</ion-title>
|
||||||
|
|
||||||
<ion-buttons slot="end"></ion-buttons>
|
<ion-buttons slot="end">
|
||||||
|
<ion-button fill="clear" (click)="openCourseSummary()" [attr.aria-label]="'core.course.coursesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-item lines="full" class="core-format-progress-list ion-text-wrap collapsible-title">
|
<ion-item class="core-format-progress-list ion-text-wrap collapsible-title list-item-limited-width">
|
||||||
<ion-avatar slot="start" class="core-course-thumb" *ngIf="imageThumb">
|
<ion-avatar slot="start" class="core-course-thumb" *ngIf="imageThumb">
|
||||||
<img [src]="imageThumb" core-external-content alt="" />
|
<img [src]="imageThumb" core-external-content alt="" />
|
||||||
</ion-avatar>
|
</ion-avatar>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<ion-row>
|
<p *ngIf="category">
|
||||||
<ion-col>
|
<core-format-text [text]="category" contextLevel="coursecat" [contextInstanceId]="course!.categoryid">
|
||||||
<p *ngIf="category">
|
</core-format-text>
|
||||||
<core-format-text [text]="category" contextLevel="coursecat" [contextInstanceId]="course!.categoryid">
|
</p>
|
||||||
</core-format-text>
|
<h1>{{ title }}</h1>
|
||||||
</p>
|
|
||||||
<h1>{{ title }}</h1>
|
|
||||||
</ion-col>
|
|
||||||
<ion-col size="auto" class="ion-align-self-center">
|
|
||||||
<ion-button fill="clear" (click)="openCourseSummary()" [attr.aria-label]="'core.course.coursesummary' | translate"
|
|
||||||
color="dark">
|
|
||||||
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
|
||||||
</ion-button>
|
|
||||||
</ion-col>
|
|
||||||
</ion-row>
|
|
||||||
<div class="core-course-progress" *ngIf="progress !== undefined">
|
<div class="core-course-progress" *ngIf="progress !== undefined">
|
||||||
<core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress">
|
<core-progress-bar [progress]="progress" a11yText="core.course.aria:sectionprogress">
|
||||||
</core-progress-bar>
|
</core-progress-bar>
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<core-empty-box *ngIf="!sections || !sections.length" icon="fas-box-open" [message]="'core.course.nocontentavailable' | translate">
|
<core-empty-box *ngIf="!sections || !sections.length" icon="fas-box-open" [message]="'core.course.nocontentavailable' | translate">
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
|
|
||||||
<ion-list>
|
<ion-list class="core-course-module-list-wrapper">
|
||||||
<ng-container *ngFor="let section of sections">
|
<ng-container *ngFor="let section of sections">
|
||||||
<ng-container *ngFor="let module of section.modules">
|
<ng-container *ngFor="let module of section.modules">
|
||||||
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section">
|
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section">
|
||||||
|
|
|
@ -27,36 +27,39 @@
|
||||||
<core-course-module-info [module]="module" [courseId]="courseId" [description]="module.description" [component]="module.modname"
|
<core-course-module-info [module]="module" [courseId]="courseId" [description]="module.description" [component]="module.modname"
|
||||||
[componentId]="module.id" [expandDescription]="true">
|
[componentId]="module.id" [expandDescription]="true">
|
||||||
|
|
||||||
<div class="ion-padding" *ngIf="module.handlerData?.extraBadge">
|
<ion-item class="ion-text-wrap" *ngIf="module.handlerData?.extraBadge ||
|
||||||
<ion-chip class="ion-text-wrap ion-text-start" [color]="module.handlerData?.extraBadgeColor">
|
(module.visible === 0 && (!section || section.visible)) ||
|
||||||
<ion-label><span [innerHTML]="module.handlerData?.extraBadge"></span></ion-label>
|
(module.visible !== 0 && module.isStealth) ||
|
||||||
</ion-chip>
|
module.availabilityinfo">
|
||||||
</div>
|
|
||||||
<div class="ion-padding" *ngIf="module.visible === 0 && (!section || section.visible)">
|
|
||||||
<ion-chip class="ion-text-wrap">
|
|
||||||
<ion-icon name="fas-eye-slash" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>{{ 'core.course.hiddenfromstudents' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</div>
|
|
||||||
<div class="ion-padding" *ngIf="module.visible !== 0 && module.isStealth">
|
|
||||||
<ion-chip class="ion-text-wrap">
|
|
||||||
<ion-icon name="fas-eye-slash" aria-hidden="true"></ion-icon>
|
|
||||||
<ion-label>{{ 'core.course.hiddenoncoursepage' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</div>
|
|
||||||
<div class="ion-padding core-module-availabilityinfo" *ngIf="module.availabilityinfo">
|
|
||||||
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
<div class="ion-padding" *ngIf="module.handlerData?.extraBadge">
|
||||||
[courseId]="courseId" class="ion-text-wrap">
|
<ion-chip *ngIf="module.handlerData?.extraBadge" [color]="module.handlerData?.extraBadgeColor"
|
||||||
</core-format-text>
|
class="ion-text-wrap ion-text-start" [outline]="true">
|
||||||
|
<ion-label><span [innerHTML]="module.handlerData?.extraBadge"></span></ion-label>
|
||||||
|
</ion-chip>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Hidden badges -->
|
||||||
|
<div *ngIf="module.visible === 0 && (!section || section.visible)">
|
||||||
|
<ion-badge color="warning">
|
||||||
|
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||||
|
</ion-badge>
|
||||||
|
</div>
|
||||||
|
<div *ngIf="module.visible !== 0 && module.isStealth">
|
||||||
|
<ion-badge color="warning">
|
||||||
|
{{ 'core.course.hiddenoncoursepage' | translate }}
|
||||||
|
</ion-badge>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Availability info -->
|
||||||
|
<div *ngIf="module.availabilityinfo" class="core-module-availabilityinfo">
|
||||||
|
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
||||||
|
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
||||||
|
[courseId]="module.course">
|
||||||
|
</core-format-text>
|
||||||
|
</div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</div>
|
</ion-item>
|
||||||
<div class="ion-padding" *ngIf="module.completiondata?.offline">
|
|
||||||
<ion-chip color="warning" class="ion-text-wrap">
|
|
||||||
<ion-label>{{ 'core.course.manualcompletionnotsynced' | translate }}</ion-label>
|
|
||||||
</ion-chip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<core-course-unsupported-module *ngIf="unsupported" [module]="module" [courseId]="courseId"></core-course-unsupported-module>
|
<core-course-unsupported-module *ngIf="unsupported" [module]="module" [courseId]="courseId"></core-course-unsupported-module>
|
||||||
</core-course-module-info>
|
</core-course-module-info>
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-core-course-module-preview',
|
selector: 'page-core-course-module-preview',
|
||||||
templateUrl: 'module-preview.html',
|
templateUrl: 'module-preview.html',
|
||||||
|
styleUrls: ['module-preview.scss'],
|
||||||
})
|
})
|
||||||
export class CoreCourseModulePreviewPage implements OnInit {
|
export class CoreCourseModulePreviewPage implements OnInit {
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
@import "~theme/globals";
|
||||||
|
|
||||||
|
.core-module-availabilityinfo {
|
||||||
|
background: var(--light);
|
||||||
|
border-radius: var(--small-radius);
|
||||||
|
padding: 8px;
|
||||||
|
font-size: 90%;
|
||||||
|
::ng-deep ul {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-icon {
|
||||||
|
@include margin-horizontal(null, 8px);
|
||||||
|
}
|
||||||
|
}
|
|
@ -76,6 +76,11 @@ export enum CoreCourseCompletionType {
|
||||||
AUTO = 1,
|
AUTO = 1,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum CoreCourseCompletionMode {
|
||||||
|
FULL = 'full',
|
||||||
|
BASIC = 'basic',
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Completion tracking valid values.
|
* Completion tracking valid values.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -12,8 +12,8 @@
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ion-item class="ion-text-wrap" button lines="none" detail="false" (click)="openCourse()"
|
<ion-item class="ion-text-wrap" button detail="false" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname"
|
||||||
[attr.aria-label]="course.displayname || course.fullname" [class.item-disabled]="course.visible == 0">
|
[class.item-disabled]="course.visible == 0">
|
||||||
|
|
||||||
<ng-container *ngIf="layout == 'list' || layout == 'listwithenrol'">
|
<ng-container *ngIf="layout == 'list' || layout == 'listwithenrol'">
|
||||||
<ion-icon *ngIf="!course.courseImage" name="fas-graduation-cap" slot="start" class="course-icon core-course-thumb">
|
<ion-icon *ngIf="!course.courseImage" name="fas-graduation-cap" slot="start" class="course-icon core-course-thumb">
|
||||||
|
|
|
@ -101,6 +101,8 @@ ion-chip {
|
||||||
|
|
||||||
// List layout.
|
// List layout.
|
||||||
ion-card.core-course-list-item {
|
ion-card.core-course-list-item {
|
||||||
|
max-width: var(--list-item--max-width);
|
||||||
|
|
||||||
ion-icon.course-icon {
|
ion-icon.course-icon {
|
||||||
padding: 12px;
|
padding: 12px;
|
||||||
font-size: calc(var(--avatar-size) - 24px);
|
font-size: calc(var(--avatar-size) - 24px);
|
||||||
|
|
|
@ -160,7 +160,7 @@ export class CoreCoursesCourseListItemComponent implements OnInit, OnDestroy, On
|
||||||
|
|
||||||
const tint = CoreColors.lighter(this.course.color, 50);
|
const tint = CoreColors.lighter(this.course.color, 50);
|
||||||
this.element.style.setProperty('--course-color-tint', tint);
|
this.element.style.setProperty('--course-color-tint', tint);
|
||||||
} else {
|
} else if(this.course.colorNumber !== undefined) {
|
||||||
this.element.classList.add('course-color-' + this.course.colorNumber);
|
this.element.classList.add('course-color-' + this.course.colorNumber);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
[style.background-color]="course.color">
|
[style.background-color]="course.color">
|
||||||
<img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt="" />
|
<img *ngIf="course.courseImage" [src]="course.courseImage" core-external-content alt="" />
|
||||||
</div>
|
</div>
|
||||||
<ion-item button lines="none" (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname"
|
<ion-item button (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname" class="core-course-header"
|
||||||
class="core-course-header" [class.item-disabled]="course.visible == 0"
|
[class.item-disabled]="course.visible == 0"
|
||||||
[class.core-course-only-title]="!showAll || progress < 0 && completionUserTracked === false" detail="false">
|
[class.core-course-only-title]="!showAll || progress < 0 && completionUserTracked === false" detail="false">
|
||||||
<ion-label class="ion-text-wrap core-course-title"
|
<ion-label class="ion-text-wrap core-course-title"
|
||||||
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
||||||
|
@ -53,7 +53,7 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</div>
|
</div>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item *ngIf="showAll && progress >= 0 && completionUserTracked !== false" lines="none" class="core-course-progress">
|
<ion-item *ngIf="showAll && progress >= 0 && completionUserTracked !== false" class="core-course-progress">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-progress-bar [progress]="progress" a11yText="core.courses.aria:courseprogress"></core-progress-bar>
|
<core-progress-bar [progress]="progress" a11yText="core.courses.aria:courseprogress"></core-progress-bar>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -25,53 +25,56 @@
|
||||||
<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]="categoriesLoaded">
|
<core-loading [hideUntil]="categoriesLoaded">
|
||||||
<ion-item *ngIf="currentCategory" class="ion-text-wrap">
|
<ion-list class="list-item-limited-width">
|
||||||
<ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.category' | translate"></ion-icon>
|
<ion-item *ngIf="currentCategory" class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.category' | translate"></ion-icon>
|
||||||
<p class="item-heading">
|
|
||||||
<core-format-text [text]="currentCategory.name" contextLevel="coursecat" [contextInstanceId]="currentCategory.id">
|
|
||||||
</core-format-text>
|
|
||||||
</p>
|
|
||||||
<p *ngIf="currentCategory.description">
|
|
||||||
<core-format-text [text]="currentCategory.description" [maxHeight]="120" contextLevel="coursecat"
|
|
||||||
[contextInstanceId]="currentCategory.id"></core-format-text>
|
|
||||||
</p>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
|
|
||||||
<ng-container *ngIf="categories.length > 0">
|
|
||||||
<ion-item-divider>
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.courses.categories' | translate }}</h2>
|
<p class="item-heading">
|
||||||
|
<core-format-text [text]="currentCategory.name" contextLevel="coursecat" [contextInstanceId]="currentCategory.id">
|
||||||
|
</core-format-text>
|
||||||
|
</p>
|
||||||
|
<p *ngIf="currentCategory.description">
|
||||||
|
<core-format-text [text]="currentCategory.description" [maxHeight]="120" contextLevel="coursecat"
|
||||||
|
[contextInstanceId]="currentCategory.id"></core-format-text>
|
||||||
|
</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item>
|
||||||
<section *ngFor="let category of categories">
|
|
||||||
<ion-item button class="ion-text-wrap" (click)="openCategory(category.id)" [attr.aria-label]="category.name" detail="true">
|
<ng-container *ngIf="categories.length > 0">
|
||||||
<ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.category' | translate"></ion-icon>
|
<ion-item-divider>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h2 class="big">{{ 'core.courses.categories' | translate }}</h2>
|
||||||
<core-format-text [text]="category.name" contextLevel="coursecat" [contextInstanceId]="category.id">
|
|
||||||
</core-format-text>
|
|
||||||
</h2>
|
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<ion-badge slot="end" *ngIf="!showOnlyEnrolled && category.coursecount > 0" color="light">
|
</ion-item-divider>
|
||||||
<span aria-hidden="true">{{ category.coursecount }}</span>
|
<ion-card *ngFor="let category of categories">
|
||||||
<span class="sr-only">{{ 'core.courses.therearecourses' | translate:{ $a: category.coursecount } }}</span>
|
<ion-item button class="ion-text-wrap" (click)="openCategory(category.id)" [attr.aria-label]="category.name"
|
||||||
</ion-badge>
|
detail="true">
|
||||||
</ion-item>
|
<ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.category' | translate"></ion-icon>
|
||||||
</section>
|
<ion-label>
|
||||||
</ng-container>
|
<h2>
|
||||||
|
<core-format-text [text]="category.name" contextLevel="coursecat" [contextInstanceId]="category.id">
|
||||||
|
</core-format-text>
|
||||||
|
</h2>
|
||||||
|
</ion-label>
|
||||||
|
<ion-badge slot="end" *ngIf="!showOnlyEnrolled && category.coursecount > 0" color="light">
|
||||||
|
<span aria-hidden="true">{{ category.coursecount }}</span>
|
||||||
|
<span class="sr-only">{{ 'core.courses.therearecourses' | translate:{ $a: category.coursecount } }}</span>
|
||||||
|
</ion-badge>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
<ng-container *ngIf="courses.length > 0">
|
<ng-container *ngIf="courses.length > 0">
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 *ngIf="!showOnlyEnrolled">{{ 'core.courses.courses' | translate }}</h2>
|
<h2 *ngIf="!showOnlyEnrolled" class="big">{{ 'core.courses.courses' | translate }}</h2>
|
||||||
<h2 *ngIf="showOnlyEnrolled">{{ 'core.courses.mycourses' | translate }}</h2>
|
<h2 *ngIf="showOnlyEnrolled" class="big">{{ 'core.courses.mycourses' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled">
|
<core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled">
|
||||||
</core-courses-course-list-item>
|
</core-courses-course-list-item>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
</ion-list>
|
||||||
<core-empty-box *ngIf="!categories.length && !courses.length" icon="fas-graduation-cap"
|
<core-empty-box *ngIf="!categories.length && !courses.length" icon="fas-graduation-cap"
|
||||||
[message]="'core.courses.nocoursesyet' | translate">
|
[message]="'core.courses.nocoursesyet' | translate">
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list>
|
<ion-list class="list-item-limited-width">
|
||||||
<ng-container *ngFor="let block of blocks">
|
<ng-container *ngFor="let block of blocks">
|
||||||
<core-block *ngIf="block.visible" [block]="block" contextLevel="user" [instanceId]="userId"></core-block>
|
<core-block *ngIf="block.visible" [block]="block" contextLevel="user" [instanceId]="userId"></core-block>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -31,7 +31,6 @@ import { CoreBlockDelegate } from '@features/block/services/block-delegate';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-core-courses-dashboard',
|
selector: 'page-core-courses-dashboard',
|
||||||
templateUrl: 'dashboard.html',
|
templateUrl: 'dashboard.html',
|
||||||
styleUrls: ['dashboard.scss'],
|
|
||||||
})
|
})
|
||||||
export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
|
export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,10 @@
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled">
|
<ion-list class="list-item-limited-width">
|
||||||
</core-courses-course-list-item>
|
<core-courses-course-list-item *ngFor="let course of courses" [course]="course" [showDownload]="downloadEnabled">
|
||||||
|
</core-courses-course-list-item>
|
||||||
|
</ion-list>
|
||||||
|
|
||||||
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreCourses($event)" [error]="loadMoreError">
|
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreCourses($event)" [error]="loadMoreError">
|
||||||
</core-infinite-loading>
|
</core-infinite-loading>
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
<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-item class="ion-text-wrap divider" lines="none">
|
<ion-item class="ion-text-wrap divider">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.courses.mycourses' | translate }}</h2>
|
<h2 class="big">{{ 'core.courses.mycourses' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
<div slot="end" class="flex-row">
|
<div slot="end" class="flex-row">
|
||||||
<!-- Download all courses. -->
|
<!-- Download all courses. -->
|
||||||
|
|
|
@ -11,6 +11,11 @@
|
||||||
--internal-loading-inline-min-height: calc(100vh - var(--core-header-toolbar-height) - var(--bottom-tabs-size) - 2px);
|
--internal-loading-inline-min-height: calc(100vh - var(--core-header-toolbar-height) - var(--bottom-tabs-size) - 2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
core-block ::ng-deep ion-card.addon-block-myoverview {
|
||||||
|
--border-width: 0;
|
||||||
|
--background: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
@if ($core-dashboard-logo) {
|
@if ($core-dashboard-logo) {
|
||||||
.in-toolbar h1 .core-header-logo {
|
.in-toolbar h1 .core-header-logo {
|
||||||
max-height: calc(var(--core-header-toolbar-height) - 24px);
|
max-height: calc(var(--core-header-toolbar-height) - 24px);
|
||||||
|
|
|
@ -36,8 +36,8 @@
|
||||||
<td *ngIf="row.itemtype == 'category'" class="core-grades-table-category" [attr.rowspan]="row.rowspan">
|
<td *ngIf="row.itemtype == 'category'" class="core-grades-table-category" [attr.rowspan]="row.rowspan">
|
||||||
</td>
|
</td>
|
||||||
<th class="core-grades-table-gradeitem ion-text-start" [attr.colspan]="row.colspan">
|
<th class="core-grades-table-gradeitem ion-text-start" [attr.colspan]="row.colspan">
|
||||||
<ion-icon *ngIf="row.expandable && showSummary" aria-hidden="true" slot="start"
|
<ion-icon *ngIf="row.expandable && showSummary" aria-hidden="true" slot="start" name="fas-chevron-right"
|
||||||
[name]="row.expanded ? 'fas-chevron-down' : 'fas-chevron-right'" class="expandable-status-icon">
|
class="expandable-status-icon" [class.expandable-status-icon-expanded]="row.expanded">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
<ion-icon *ngIf="row.icon" name="{{row.icon}}" slot="start" [attr.aria-label]="row.iconAlt">
|
<ion-icon *ngIf="row.icon" name="{{row.icon}}" slot="start" [attr.aria-label]="row.iconAlt">
|
||||||
</ion-icon>
|
</ion-icon>
|
||||||
|
|
|
@ -96,6 +96,11 @@
|
||||||
.expandable-status-icon {
|
.expandable-status-icon {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
@include margin-horizontal(0, 2px);
|
@include margin-horizontal(0, 2px);
|
||||||
|
@include core-transition(transform, 200ms);
|
||||||
|
|
||||||
|
&.expandable-status-icon-expanded {
|
||||||
|
transform: var(--rotate-expandable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list>
|
<ion-list class="core-sitelist">
|
||||||
<ng-container *ngIf="accountsList.currentSite">
|
<ion-card *ngIf="accountsList.currentSite">
|
||||||
<ion-item-divider sticky="true">
|
<ion-item-divider sticky="true" class="core-sitelist-sitename">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h2>
|
||||||
<core-format-text [text]="accountsList.currentSite.siteName" clean="true"
|
<core-format-text [text]="accountsList.currentSite.siteName" clean="true"
|
||||||
|
@ -34,7 +34,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
||||||
<ion-item detail="false" class="item-current">
|
<ion-item detail="false">
|
||||||
<ion-avatar slot="start">
|
<ion-avatar slot="start">
|
||||||
<img [src]="accountsList.currentSite.avatar" core-external-content [siteId]="accountsList.currentSite.id"
|
<img [src]="accountsList.currentSite.avatar" core-external-content [siteId]="accountsList.currentSite.id"
|
||||||
alt="{{ 'core.pictureof' | translate:{$a: accountsList.currentSite.fullName} }}"
|
alt="{{ 'core.pictureof' | translate:{$a: accountsList.currentSite.fullName} }}"
|
||||||
|
@ -47,10 +47,10 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ng-container *ngTemplateOutlet="siteList; context: {sites: accountsList.sameSite}"></ng-container>
|
<ng-container *ngTemplateOutlet="siteList; context: {sites: accountsList.sameSite}"></ng-container>
|
||||||
</ng-container>
|
</ion-card>
|
||||||
|
|
||||||
<ng-container *ngFor="let sites of accountsList.otherSites">
|
<ion-card *ngFor="let sites of accountsList.otherSites">
|
||||||
<ion-item-divider sticky="true" *ngIf="sites[0]">
|
<ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h2>
|
||||||
<core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text>
|
<core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text>
|
||||||
|
@ -60,7 +60,7 @@
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
||||||
<ng-container *ngTemplateOutlet="siteList; context: {sites: sites}"></ng-container>
|
<ng-container *ngTemplateOutlet="siteList; context: {sites: sites}"></ng-container>
|
||||||
</ng-container>
|
</ion-card>
|
||||||
|
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
|
|
|
@ -28,6 +28,7 @@ import { ModalController } from '@singletons';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'core-login-sites',
|
selector: 'core-login-sites',
|
||||||
templateUrl: 'sites.html',
|
templateUrl: 'sites.html',
|
||||||
|
styleUrls: ['../../sitelist.scss'],
|
||||||
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
||||||
})
|
})
|
||||||
export class CoreLoginSitesComponent implements OnInit {
|
export class CoreLoginSitesComponent implements OnInit {
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list>
|
<ion-list>
|
||||||
<ng-container *ngIf="!changingPassword">
|
<ng-container *ngIf="!changingPassword">
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.login.forcepasswordchangenotice' | translate }}</h2>
|
<h2>{{ 'core.login.forcepasswordchangenotice' | translate }}</h2>
|
||||||
<p class="ion-padding-top">{{ 'core.login.changepasswordinstructions' | translate }}</p>
|
<p class="ion-padding-top">{{ 'core.login.changepasswordinstructions' | translate }}</p>
|
||||||
|
@ -29,7 +29,7 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-container *ngIf="changingPassword">
|
<ng-container *ngIf="changingPassword">
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'core.login.changepasswordreconnectinstructions' | translate }}</p>
|
<p>{{ 'core.login.changepasswordreconnectinstructions' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
{{ 'core.login.reconnect' | translate }}
|
{{ 'core.login.reconnect' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>{{ 'core.login.changepasswordlogoutinstructions' | translate }}</p>
|
<p>{{ 'core.login.changepasswordlogoutinstructions' | translate }}</p>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -54,7 +54,7 @@
|
||||||
|
|
||||||
<ng-container *ngIf="showScanQR">
|
<ng-container *ngIf="showScanQR">
|
||||||
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>
|
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>
|
||||||
<ion-button expand="block" color="light" class="ion-margin" lines="none" (click)="showInstructionsAndScanQR()">
|
<ion-button expand="block" color="light" class="ion-margin" (click)="showInstructionsAndScanQR()">
|
||||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||||
{{ 'core.scanqr' | translate }}
|
{{ 'core.scanqr' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
@ -68,7 +68,7 @@
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
||||||
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -81,12 +81,12 @@
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
<ion-list *ngIf="canSignup" class="ion-padding-top core-login-sign-up">
|
<ion-list *ngIf="canSignup" class="ion-padding-top core-login-sign-up">
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'core.login.firsttime' | translate }}</h3>
|
<h3 class="item-heading">{{ 'core.login.firsttime' | translate }}</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap" lines="none" *ngIf="authInstructions">
|
<ion-item class="ion-text-wrap" *ngIf="authInstructions">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p>
|
<p>
|
||||||
<core-format-text [text]="authInstructions" [filter]="false"></core-format-text>
|
<core-format-text [text]="authInstructions" [filter]="false"></core-format-text>
|
||||||
|
|
|
@ -232,7 +232,7 @@
|
||||||
</h3>
|
</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'core.considereddigitalminor' | translate }}</h3>
|
<h3 class="item-heading">{{ 'core.considereddigitalminor' | translate }}</h3>
|
||||||
<p>{{ 'core.digitalminor_desc' | translate }}</p>
|
<p>{{ 'core.digitalminor_desc' | translate }}</p>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-list lines="none">
|
<ion-list>
|
||||||
<ion-item class="ion-text-wrap">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>{{ 'core.login.passwordforgotteninstructions2' | translate }}</ion-label>
|
<ion-label>{{ 'core.login.passwordforgotteninstructions2' | translate }}</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -65,7 +65,7 @@
|
||||||
|
|
||||||
<ng-container *ngIf="showScanQR">
|
<ng-container *ngIf="showScanQR">
|
||||||
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>
|
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>
|
||||||
<ion-button expand="block" color="light" class="ion-margin" lines="none" (click)="showInstructionsAndScanQR()">
|
<ion-button expand="block" color="light" class="ion-margin" (click)="showInstructionsAndScanQR()">
|
||||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||||
{{ 'core.scanqr' | translate }}
|
{{ 'core.scanqr' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
@ -80,7 +80,7 @@
|
||||||
|
|
||||||
<!-- Identity providers. -->
|
<!-- Identity providers. -->
|
||||||
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
||||||
<ion-item class="ion-text-wrap" lines="none">
|
<ion-item class="ion-text-wrap">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -42,7 +42,7 @@
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-list [class.hidden]="!hasSites && !enteredSiteUrl" class="core-login-site-list">
|
<ion-list [class.hidden]="!hasSites && !enteredSiteUrl" class="core-login-site-list">
|
||||||
<ion-item lines="none" class="core-login-site-list-title">
|
<ion-item class="core-login-site-list-title">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -73,7 +73,7 @@
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-item *ngIf="siteSelector == 'url'" lines="none">
|
<ion-item *ngIf="siteSelector == 'url'">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<ion-button expand="block" [disabled]="!siteForm.valid" class="ion-text-wrap" type="submit">
|
<ion-button expand="block" [disabled]="!siteForm.valid" class="ion-text-wrap" type="submit">
|
||||||
{{ 'core.login.connect' | translate }}
|
{{ 'core.login.connect' | translate }}
|
||||||
|
@ -85,7 +85,7 @@
|
||||||
<ng-container *ngIf="fixedSites">
|
<ng-container *ngIf="fixedSites">
|
||||||
<!-- Pick the site from a list of fixed sites. -->
|
<!-- Pick the site from a list of fixed sites. -->
|
||||||
<ion-list *ngIf="siteSelector == 'list'">
|
<ion-list *ngIf="siteSelector == 'list'">
|
||||||
<ion-item lines="none">
|
<ion-item>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -101,8 +101,7 @@
|
||||||
|
|
||||||
<ng-container *ngIf="showScanQR && !hasSites && !enteredSiteUrl">
|
<ng-container *ngIf="showScanQR && !hasSites && !enteredSiteUrl">
|
||||||
<div class="ion-text-center ion-padding ion-margin-top">{{ 'core.login.or' | translate }}</div>
|
<div class="ion-text-center ion-padding ion-margin-top">{{ 'core.login.or' | translate }}</div>
|
||||||
<ion-button expand="block" color="light" class="ion-margin" lines="none" (click)="showInstructionsAndScanQR()"
|
<ion-button expand="block" color="light" class="ion-margin" (click)="showInstructionsAndScanQR()" aria-haspopup="dialog">
|
||||||
aria-haspopup="dialog">
|
|
||||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||||
{{ 'core.scanqr' | translate }}
|
{{ 'core.scanqr' | translate }}
|
||||||
</ion-button>
|
</ion-button>
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<core-loading [hideUntil]="loaded">
|
<core-loading [hideUntil]="loaded">
|
||||||
<ion-list>
|
<ion-list class="core-sitelist">
|
||||||
<ng-container *ngFor="let sites of accountsList.otherSites">
|
<ion-card *ngFor="let sites of accountsList.otherSites">
|
||||||
<ion-item-divider sticky="true" *ngIf="sites[0]">
|
<ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>
|
<h2>
|
||||||
<core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text>
|
<core-format-text [text]="sites[0].siteName" clean="true" [siteId]="sites[0].id"></core-format-text>
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
</ion-button>
|
</ion-button>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
</ng-container>
|
</ion-card>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end">
|
<ion-fab slot="fixed" core-fab vertical="bottom" horizontal="end">
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { CoreAnimations } from '@components/animations';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'page-core-login-sites',
|
selector: 'page-core-login-sites',
|
||||||
templateUrl: 'sites.html',
|
templateUrl: 'sites.html',
|
||||||
|
styleUrls: ['../../sitelist.scss'],
|
||||||
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
animations: [CoreAnimations.SLIDE_IN_OUT, CoreAnimations.SHOW_HIDE],
|
||||||
})
|
})
|
||||||
export class CoreLoginSitesPage implements OnInit {
|
export class CoreLoginSitesPage implements OnInit {
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
ion-list.core-sitelist {
|
||||||
|
.core-sitelist-sitename {
|
||||||
|
ion-label {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
border-bottom: 1px solid var(--stroke);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,12 +6,7 @@ core-user-avatar {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
:host-context(ion-toolbar) core-user-avatar ::ng-deep img {
|
:host-context(ion-toolbar) core-user-avatar ::ng-deep img,
|
||||||
padding: 2px !important;
|
|
||||||
border: 1px solid var(--color);
|
|
||||||
}
|
|
||||||
|
|
||||||
:host-context(ion-tab-bar) core-user-avatar ::ng-deep img {
|
:host-context(ion-tab-bar) core-user-avatar ::ng-deep img {
|
||||||
padding: 2px !important;
|
padding: 2px !important;
|
||||||
border: 1px solid var(--color);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ export class CoreMainMenuUserButtonComponent implements OnInit {
|
||||||
|
|
||||||
CoreDomUtils.openSideModal<void>({
|
CoreDomUtils.openSideModal<void>({
|
||||||
component: CoreMainMenuUserMenuComponent,
|
component: CoreMainMenuUserMenuComponent,
|
||||||
cssClass: 'core-modal-lateral-sm',
|
cssClass: 'core-modal-lateral',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
||||||
<ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded" lines="none">
|
<ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
@ -43,7 +43,7 @@
|
||||||
|
|
||||||
<ion-item button *ngFor="let handler of handlers" class="ion-text-wrap" (click)="handlerClicked($event, handler)"
|
<ion-item button *ngFor="let handler of handlers" class="ion-text-wrap" (click)="handlerClicked($event, handler)"
|
||||||
[ngClass]="['core-user-menu-handler', handler.class || '']" [hidden]="handler.hidden"
|
[ngClass]="['core-user-menu-handler', handler.class || '']" [hidden]="handler.hidden"
|
||||||
[attr.aria-label]="handler.title | translate" detail="true" lines="none">
|
[attr.aria-label]="handler.title | translate" detail="true">
|
||||||
<ion-icon *ngIf="handler.icon" [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon>
|
<ion-icon *ngIf="handler.icon" [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<p class="item-heading">{{ handler.title | translate }}</p>
|
<p class="item-heading">{{ handler.title | translate }}</p>
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
ion-tab-bar {
|
ion-tab-bar {
|
||||||
height: var(--menutabbar-size);
|
height: var(--menutabbar-size);
|
||||||
box-shadow: 0px -3px 3px rgba(var(--drop-shadow));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@if ($core-always-show-main-menu) {
|
@if ($core-always-show-main-menu) {
|
||||||
|
@ -83,7 +82,6 @@
|
||||||
height: calc(100% - var(--ion-safe-area-top) - var(--ion-safe-area-bottom));
|
height: calc(100% - var(--ion-safe-area-top) - var(--ion-safe-area-bottom));
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
@include border-end(var(--border));
|
@include border-end(var(--border));
|
||||||
box-shadow: 3px 0 3px rgba(var(--drop-shadow));
|
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
justify-content: flex-start;
|
justify-content: flex-start;
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,7 @@
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
<ion-footer class="ion-no-border">
|
<ion-footer class="ion-no-border">
|
||||||
<ion-item button class="ion-text-wrap ion-text-center core-about-deviceinfo" detail="false" (click)="openPage('deviceinfo')"
|
<ion-item button class="ion-text-wrap ion-text-center core-about-deviceinfo" detail="false" (click)="openPage('deviceinfo')">
|
||||||
lines="none">
|
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ appName }} {{ versionName }}</h2>
|
<h2>{{ appName }} {{ versionName }}</h2>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
</ion-segment>
|
</ion-segment>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
<ion-item class="ion-text-wrap core-settings-general-color-scheme" *ngIf="colorSchemes.length > 0"
|
<ion-item class="ion-text-wrap core-settings-general-color-scheme" *ngIf="colorSchemes.length > 0"
|
||||||
[lines]="selectedScheme=='system' && isAndroid ? 'none' : 'inset'">
|
[lines]="selectedScheme=='system' && isAndroid ? 'none' : ''">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<h2>{{ 'core.settings.colorscheme' | translate }}</h2>
|
<h2>{{ 'core.settings.colorscheme' | translate }}</h2>
|
||||||
<p *ngIf="colorSchemeDisabled" class="text-danger">{{ 'core.settings.forcedsetting' | translate }}</p>
|
<p *ngIf="colorSchemeDisabled" class="text-danger">{{ 'core.settings.forcedsetting' | translate }}</p>
|
||||||
|
|
|
@ -8,7 +8,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]="dataLoaded">
|
<core-loading [hideUntil]="dataLoaded">
|
||||||
<ion-list>
|
<ion-list class="core-course-module-list-wrapper">
|
||||||
<!-- Site home main contents. -->
|
<!-- Site home main contents. -->
|
||||||
<ng-container *ngIf="section && section.hasContent">
|
<ng-container *ngIf="section && section.hasContent">
|
||||||
<ion-item class="ion-text-wrap" *ngIf="section.summary">
|
<ion-item class="ion-text-wrap" *ngIf="section.summary">
|
||||||
|
@ -55,12 +55,14 @@
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
||||||
<ng-template #allCourseList>
|
<ng-template #allCourseList>
|
||||||
<ion-item button class="ion-text-wrap" (click)="openAvailableCourses()" lines="none">
|
<ion-card>
|
||||||
<ion-icon name="fas-graduation-cap" fixed-width slot="start" aria-hidden="true"></ion-icon>
|
<ion-item button class="ion-text-wrap" (click)="openAvailableCourses()">
|
||||||
<ion-label>
|
<ion-icon name="fas-graduation-cap" fixed-width slot="start" aria-hidden="true"></ion-icon>
|
||||||
<h2>{{ 'core.courses.availablecourses' | translate}}</h2>
|
<ion-label>
|
||||||
</ion-label>
|
<h2>{{ 'core.courses.availablecourses' | translate}}</h2>
|
||||||
</ion-item>
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #news>
|
<ng-template #news>
|
||||||
|
@ -69,29 +71,35 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #categories>
|
<ng-template #categories>
|
||||||
<ion-item button class="ion-text-wrap" (click)="openCourseCategories()" lines="none">
|
<ion-card>
|
||||||
<ion-icon name="fas-folder" slot="start" aria-hidden="true"></ion-icon>
|
<ion-item button class="ion-text-wrap" (click)="openCourseCategories()">
|
||||||
<ion-label>
|
<ion-icon name="fas-folder" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<h2>{{ 'core.courses.categories' | translate}}</h2>
|
<ion-label>
|
||||||
</ion-label>
|
<h2>{{ 'core.courses.categories' | translate}}</h2>
|
||||||
</ion-item>
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #enrolledCourseList>
|
<ng-template #enrolledCourseList>
|
||||||
<ion-item button class="ion-text-wrap" (click)="openMyCourses()" lines="none">
|
<ion-card>
|
||||||
<ion-icon name="fas-graduation-cap" fixed-width slot="start" aria-hidden="true">
|
<ion-item button class="ion-text-wrap" (click)="openMyCourses()">
|
||||||
</ion-icon>
|
<ion-icon name="fas-graduation-cap" fixed-width slot="start" aria-hidden="true">
|
||||||
<ion-label>
|
</ion-icon>
|
||||||
<h2>{{ 'core.courses.mycourses' | translate}}</h2>
|
<ion-label>
|
||||||
</ion-label>
|
<h2>{{ 'core.courses.mycourses' | translate}}</h2>
|
||||||
</ion-item>
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
<ng-template #courseSearch>
|
<ng-template #courseSearch>
|
||||||
<ion-item button class="ion-text-wrap" (click)="openSearch()" lines="none">
|
<ion-card>
|
||||||
<ion-icon name="fas-search" slot="start" aria-hidden="true"></ion-icon>
|
<ion-item button class="ion-text-wrap" (click)="openSearch()">
|
||||||
<ion-label>
|
<ion-icon name="fas-search" slot="start" aria-hidden="true"></ion-icon>
|
||||||
<h2>{{ 'core.courses.searchcourses' | translate}}</h2>
|
<ion-label>
|
||||||
</ion-label>
|
<h2>{{ 'core.courses.searchcourses' | translate}}</h2>
|
||||||
</ion-item>
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
</ion-card>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
|
@ -4,14 +4,17 @@ ion-item ion-icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
border-radius: var(--module-icon-radius);
|
border-radius: var(--module-icon-radius);
|
||||||
padding: 0.7rem;
|
padding: 0.7rem;
|
||||||
background-color: $gray-100;
|
background-color: var(--gray-100);
|
||||||
|
color: var(--gray-900);
|
||||||
line-height: var(--size);
|
line-height: var(--size);
|
||||||
--margin-end: 1rem;
|
--margin-end: 1rem;
|
||||||
@include margin-horizontal(null, var(--margin-end));
|
@include margin-horizontal(null, var(--margin-end));
|
||||||
}
|
}
|
||||||
|
|
||||||
core-course-module.core-sitehome-news ::ng-deep ion-card {
|
core-spacer ::ng-deep .item {
|
||||||
--border-width: 0;
|
border-radius: var(--medium-radius);
|
||||||
margin: 0;
|
--horizontal-margin: 10px;
|
||||||
padding: 0;
|
margin-left: var(--horizontal-margin);
|
||||||
|
margin-right: var(--horizontal-margin);
|
||||||
|
width: auto;
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,7 +179,7 @@ core-format-text {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
@include position(null, 10px, 10px, null);
|
@include position(null, 10px, 10px, null);
|
||||||
color: var(--ion-text-color);
|
color: var(--ion-text-color);
|
||||||
border-radius: var(--small-radius);
|
border-radius: var(--huge-radius);
|
||||||
background-color: var(--core-format-text-viewer-icon-background);
|
background-color: var(--core-format-text-viewer-icon-background);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ $background-color-dark-rgb: color-to-rgb-list($background-color-dark) !default;
|
||||||
|
|
||||||
$ion-item-background: $white !default;
|
$ion-item-background: $white !default;
|
||||||
$ion-item-background-rgb: color-to-rgb-list($ion-item-background) !default;
|
$ion-item-background-rgb: color-to-rgb-list($ion-item-background) !default;
|
||||||
$ion-item-background-dark: mix(#ffffff, #000000, 20%) !default; // #333333
|
$ion-item-background-dark: $gray-900 !default;
|
||||||
$ion-item-background-dark-rgb: color-to-rgb-list($ion-item-background-dark) !default;
|
$ion-item-background-dark-rgb: color-to-rgb-list($ion-item-background-dark) !default;
|
||||||
|
|
||||||
$primary: $blue !default;
|
$primary: $blue !default;
|
||||||
|
|
|
@ -184,44 +184,6 @@ ion-app.ios ion-header ion-title {
|
||||||
white-space: normal !important;
|
white-space: normal !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-button core-format-text .core-format-text-content {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
display: block;
|
|
||||||
line-height: 1.2;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-button > * {
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-button.ion-text-wrap {
|
|
||||||
white-space: normal;
|
|
||||||
core-format-text .core-format-text-content {
|
|
||||||
white-space: normal;
|
|
||||||
display: contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
& > * {
|
|
||||||
white-space: normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-button.button-outline {
|
|
||||||
--background: var(--contrast-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-button ion-spinner {
|
|
||||||
--color: inherit !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
ion-button:not(.button-has-icon-only) > ion-icon {
|
|
||||||
min-width: 20px;
|
|
||||||
}
|
|
||||||
|
|
||||||
@each $color-name, $unused in $colors {
|
@each $color-name, $unused in $colors {
|
||||||
.text-#{$color-name},
|
.text-#{$color-name},
|
||||||
p.text-#{$color-name} {
|
p.text-#{$color-name} {
|
||||||
|
@ -293,10 +255,6 @@ ion-icon {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-button.button-small ion-icon.faicon[slot] {
|
|
||||||
font-size: 1.5em !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Buttons.
|
// Buttons.
|
||||||
ion-button,
|
ion-button,
|
||||||
ion-fab-button,
|
ion-fab-button,
|
||||||
|
@ -306,10 +264,58 @@ button,
|
||||||
min-width: var(--a11y-min-target-size);
|
min-width: var(--a11y-min-target-size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-button.button-outline {
|
||||||
|
--border-width: 1px;
|
||||||
|
--background: var(--contrast-background);
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button.button-solid {
|
||||||
|
--box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button core-format-text .core-format-text-content {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
display: block;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button > * {
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button.ion-text-wrap {
|
||||||
|
white-space: normal;
|
||||||
|
core-format-text .core-format-text-content {
|
||||||
|
white-space: normal;
|
||||||
|
display: contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
& > * {
|
||||||
|
white-space: normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button ion-spinner {
|
||||||
|
--color: inherit !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-button:not(.button-has-icon-only):not(.button-small) > ion-icon {
|
||||||
|
min-width: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
ion-button.button.button-clear.button-has-icon-only {
|
ion-button.button.button-clear.button-has-icon-only {
|
||||||
--border-radius: var(--huge-radius);
|
--border-radius: var(--huge-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-button.button.button-solid,
|
||||||
|
ion-button.button.button-outline {
|
||||||
|
--border-radius: var(--small-radius);
|
||||||
|
}
|
||||||
|
|
||||||
// Clear buttons will be black.
|
// Clear buttons will be black.
|
||||||
ion-button.button-clear {
|
ion-button.button-clear {
|
||||||
--primary: var(--primary);
|
--primary: var(--primary);
|
||||||
|
@ -409,8 +415,9 @@ ion-alert {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ionic list.
|
// Ionic list.
|
||||||
ion-list.list-md {
|
ion-list {
|
||||||
padding: 0;
|
padding: 0 !important;
|
||||||
|
--ion-item-background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Safe areas
|
// Safe areas
|
||||||
|
@ -736,6 +743,14 @@ ion-card {
|
||||||
display: inline !important;
|
display: inline !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-list.core-course-module-list-wrapper,
|
||||||
|
.list-item-limited-width,
|
||||||
|
.core-course-module-list-wrapper {
|
||||||
|
max-width: var(--list-item--max-width);
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
ion-toolbar h1 img.core-bar-button-image,
|
ion-toolbar h1 img.core-bar-button-image,
|
||||||
ion-toolbar h1 .core-bar-button-image img {
|
ion-toolbar h1 .core-bar-button-image img {
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
|
@ -861,12 +876,14 @@ ion-badge {
|
||||||
border-radius: var(--big-radius);
|
border-radius: var(--big-radius);
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-chip {
|
ion-chip,
|
||||||
|
ion-button.chip {
|
||||||
line-height: 1.1;
|
line-height: 1.1;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
padding: 4px 8px;
|
|
||||||
min-height: 24px;
|
min-height: 24px;
|
||||||
height: auto;
|
text-transform: none;
|
||||||
|
margin: 4px;
|
||||||
|
font-weight: normal;
|
||||||
|
|
||||||
ion-icon {
|
ion-icon {
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
@ -874,6 +891,18 @@ ion-chip {
|
||||||
@include margin(0, 8px, 0, 0);
|
@include margin(0, 8px, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-label {
|
||||||
|
white-space: normal !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-chip {
|
||||||
|
line-height: 1.1;
|
||||||
|
font-size: 12px;
|
||||||
|
padding: 4px 8px;
|
||||||
|
min-height: 24px;
|
||||||
|
height: auto;
|
||||||
|
|
||||||
&.ion-color {
|
&.ion-color {
|
||||||
background: var(--ion-color-tint);
|
background: var(--ion-color-tint);
|
||||||
&.chip-outline {
|
&.chip-outline {
|
||||||
|
@ -882,10 +911,6 @@ ion-chip {
|
||||||
color: var(--ion-color-base);
|
color: var(--ion-color-base);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-label {
|
|
||||||
white-space: normal !important;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-searchbar {
|
ion-searchbar {
|
||||||
|
@ -1017,6 +1042,20 @@ audio.core-media-adapt-width {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-item {
|
||||||
|
--inner-border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-item.item-lines-full {
|
||||||
|
--inner-border-width: 0px;
|
||||||
|
--border-width: 0 0 1px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-item.item-lines-inset {
|
||||||
|
--inner-border-width: 1px;
|
||||||
|
--border-width: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
// Fake item.
|
// Fake item.
|
||||||
div.fake-ion-item {
|
div.fake-ion-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -1029,7 +1068,6 @@ div.fake-ion-item {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
html.md div.fake-ion-item {
|
html.md div.fake-ion-item {
|
||||||
|
@ -1209,8 +1247,33 @@ ion-item.item-input ion-input.has-focus {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-item-divider {
|
ion-item-divider.item,
|
||||||
|
ion-item.item.divider {
|
||||||
--inner-padding-end: 8px;
|
--inner-padding-end: 8px;
|
||||||
|
min-height: var(--min-height);
|
||||||
|
border-bottom-width: var(--item-divider-border-width);
|
||||||
|
--border-width: var(--item-divider-border-width);
|
||||||
|
--inner-border-width: 0 0 var(--item-divider-border-width) 0;
|
||||||
|
|
||||||
|
ion-label h2,
|
||||||
|
ion-label p.item-heading {
|
||||||
|
font-size: var(--item-divider-font-size);
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.5;
|
||||||
|
}
|
||||||
|
ion-label h2.big {
|
||||||
|
font-size: var(--item-divider-font-size-big);
|
||||||
|
}
|
||||||
|
|
||||||
|
.expandable-status-icon {
|
||||||
|
font-size: 18px;
|
||||||
|
@include core-transition(transform, 200ms);
|
||||||
|
@include margin-horizontal(null, 16px);
|
||||||
|
|
||||||
|
&.expandable-status-icon-expanded {
|
||||||
|
transform: var(--rotate-expandable);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change default outline.
|
// Change default outline.
|
||||||
|
@ -1273,6 +1336,80 @@ ion-grid.core-no-grid > ion-row {
|
||||||
right: 0;
|
right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[collapsible-item] {
|
||||||
|
--collapsible-display-toggle: none;
|
||||||
|
--collapsible-toggle-background: var(--ion-item-background);
|
||||||
|
--collapsible-min-button-height: 44px;
|
||||||
|
|
||||||
|
.collapsible-toggle {
|
||||||
|
display: var(--collapsible-display-toggle);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.collapsible-enabled {
|
||||||
|
--collapsible-display-toggle: block;
|
||||||
|
|
||||||
|
.collapsible-toggle {
|
||||||
|
display: var(--collapsible-display-toggle);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
text-align: center;
|
||||||
|
z-index: 7;
|
||||||
|
text-transform: none;
|
||||||
|
text-align: end;
|
||||||
|
font-size: 14px;
|
||||||
|
background-color: var(--collapsible-toggle-background);
|
||||||
|
color: var(--text-color);
|
||||||
|
margin: 0;
|
||||||
|
|
||||||
|
.collapsible-toggle-arrow {
|
||||||
|
width: var(--a11y-min-target-size);
|
||||||
|
height: var(--a11y-min-target-size);
|
||||||
|
|
||||||
|
background-position: center;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: 14px 14px;
|
||||||
|
@include core-transition(transform, 500ms);
|
||||||
|
|
||||||
|
@include push-arrow-color(626262, true);
|
||||||
|
|
||||||
|
@include darkmode() {
|
||||||
|
@include push-arrow-color(ffffff, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.collapsible-collapsed {
|
||||||
|
overflow: hidden;
|
||||||
|
min-height: calc(var(--collapsible-min-button-height) + 12);
|
||||||
|
|
||||||
|
.collapsible-toggle-arrow {
|
||||||
|
transform: rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:before {
|
||||||
|
content: '';
|
||||||
|
height: 100%;
|
||||||
|
position: absolute;
|
||||||
|
@include position(null, 0, 0, 0);
|
||||||
|
background: -webkit-linear-gradient(top, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 60px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 40px));
|
||||||
|
background: linear-gradient(to bottom, rgba(var(--core-format-text-background-gradient-rgb), 0) calc(100% - 60px), rgba(var(--core-format-text-background-gradient-rgb), 1) calc(100% - 40px));
|
||||||
|
z-index: 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.collapsible-expanded {
|
||||||
|
max-height: none !important;
|
||||||
|
padding-bottom: var(--collapsible-min-button-height); // So the Show less button can fit.
|
||||||
|
|
||||||
|
.collapsible-toggle-arrow {
|
||||||
|
transform: rotate(-90deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ion-header[collapsible] {
|
ion-header[collapsible] {
|
||||||
@include core-transition(all, 500ms);
|
@include core-transition(all, 500ms);
|
||||||
|
|
||||||
|
|
|
@ -76,13 +76,13 @@
|
||||||
--core-progressbar-text-color: var(--gray-100);
|
--core-progressbar-text-color: var(--gray-100);
|
||||||
|
|
||||||
--ion-item-background: #{$ion-item-background-dark};
|
--ion-item-background: #{$ion-item-background-dark};
|
||||||
--ion-item-detail-icon-color: var(--white);
|
--item-divider-background: var(--ion-item-background);
|
||||||
--item-divider-background: var(--gray-800);
|
|
||||||
--item-divider-color: var(--text-color);
|
--item-divider-color: var(--text-color);
|
||||||
--spacer-background: var(--gray-100);
|
--spacer-background: var(--gray-700);
|
||||||
|
|
||||||
--core-combobox-background: var(--ion-item-background);
|
--core-combobox-background: var(--ion-item-background);
|
||||||
--core-combobox-color: var(--white);
|
--core-combobox-color: var(--gray-100);
|
||||||
|
--core-combobox-border-color: var(--stroke);
|
||||||
|
|
||||||
--core-login-background: var(--gray-900);
|
--core-login-background: var(--gray-900);
|
||||||
--core-login-text-color: var(--white);
|
--core-login-text-color: var(--white);
|
||||||
|
|
|
@ -72,6 +72,8 @@
|
||||||
--module-icon-size: 24px;
|
--module-icon-size: 24px;
|
||||||
--module-icon-radius: var(--medium-radius);
|
--module-icon-radius: var(--medium-radius);
|
||||||
|
|
||||||
|
--list-item--max-width: 768px;
|
||||||
|
|
||||||
--ion-background-color: var(--background-color);
|
--ion-background-color: var(--background-color);
|
||||||
--ion-background-color-rgb: #{$background-color-rgb};
|
--ion-background-color-rgb: #{$background-color-rgb};
|
||||||
|
|
||||||
|
@ -120,8 +122,8 @@
|
||||||
|
|
||||||
--core-header-toolbar-button-image-size: var(--a11y-min-target-size);
|
--core-header-toolbar-button-image-size: var(--a11y-min-target-size);
|
||||||
--core-header-toolbar-background: var(--white);
|
--core-header-toolbar-background: var(--white);
|
||||||
--core-header-toolbar-border-width: 3px;
|
--core-header-toolbar-border-width: 1px;
|
||||||
--core-header-toolbar-border-color: var(--brand);
|
--core-header-toolbar-border-color: var(--stroke);
|
||||||
--core-header-toolbar-color: var(--gray-900);
|
--core-header-toolbar-color: var(--gray-900);
|
||||||
--core-header-toolbar-height: 56px;
|
--core-header-toolbar-height: 56px;
|
||||||
html.ios {
|
html.ios {
|
||||||
|
@ -145,6 +147,10 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-header::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
ion-header.header-ios ion-toolbar:last-of-type {
|
ion-header.header-ios ion-toolbar:last-of-type {
|
||||||
--border-width: 0 0 var(--core-header-toolbar-border-width) 0;
|
--border-width: 0 0 var(--core-header-toolbar-border-width) 0;
|
||||||
}
|
}
|
||||||
|
@ -221,20 +227,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
--item-divider-min-height: calc(var(--a11y-min-target-size) + 8px);
|
--item-divider-min-height: calc(var(--a11y-min-target-size) + 8px);
|
||||||
--item-divider-background: var(--light);
|
--item-divider-background: var(--ion-item-background);
|
||||||
--item-divider-color: var(--text-color);
|
--item-divider-color: var(--text-color);
|
||||||
|
--item-divider-border-width: 0px;
|
||||||
|
--item-divider-font-size: 16px;
|
||||||
|
--item-divider-font-size-big: 20px;
|
||||||
ion-item-divider, ion-item.divider {
|
ion-item-divider, ion-item.divider {
|
||||||
--background: var(--item-divider-background);
|
--background: var(--item-divider-background);
|
||||||
--color: var(--item-divider-color);
|
--color: var(--item-divider-color);
|
||||||
--min-height: var(--item-divider-min-height);
|
--min-height: var(--item-divider-min-height);
|
||||||
min-height: var(--min-height);
|
|
||||||
|
|
||||||
.expandable-status-icon {
|
|
||||||
font-size: 18px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
--spacer-background: var(--item-divider-background);
|
--spacer-background: var(--light);
|
||||||
core-spacer {
|
core-spacer {
|
||||||
--item-divider-background: var(--spacer-background);
|
--item-divider-background: var(--spacer-background);
|
||||||
}
|
}
|
||||||
|
@ -298,9 +302,6 @@
|
||||||
|
|
||||||
--drop-shadow: 0, 0, 0, 0.18;
|
--drop-shadow: 0, 0, 0, 0.18;
|
||||||
|
|
||||||
--core-menu-box-shadow-end: -4px 0px 16px rgba(var(--drop-shadow));
|
|
||||||
--core-menu-box-shadow-start: 4px 0px 16px rgba(var(--drop-shadow));
|
|
||||||
|
|
||||||
--core-question-correct-color: var(--success-shade);
|
--core-question-correct-color: var(--success-shade);
|
||||||
--core-question-correct-color-bg: var(--success-tint);
|
--core-question-correct-color-bg: var(--success-tint);
|
||||||
--core-question-incorrect-color: var(--danger);
|
--core-question-incorrect-color: var(--danger);
|
||||||
|
@ -322,6 +323,11 @@
|
||||||
--core-dd-question-radius: 10px;
|
--core-dd-question-radius: 10px;
|
||||||
--core-dd-question-border: var(--medium);
|
--core-dd-question-border: var(--medium);
|
||||||
|
|
||||||
|
--rotate-expandable: rotate(90deg);
|
||||||
|
&[dir=rtl] {
|
||||||
|
--rotate-expandable: rotate(-90deg);
|
||||||
|
}
|
||||||
|
|
||||||
@for $i from 0 to length($core-course-image-background) {
|
@for $i from 0 to length($core-course-image-background) {
|
||||||
--core-course-color-#{$i}: #{nth($core-course-image-background, $i + 1)};
|
--core-course-color-#{$i}: #{nth($core-course-image-background, $i + 1)};
|
||||||
--core-course-color-#{$i}-tint: #{get-color-tint(nth($core-course-image-background, $i + 1))};
|
--core-course-color-#{$i}-tint: #{get-color-tint(nth($core-course-image-background, $i + 1))};
|
||||||
|
|
Loading…
Reference in New Issue