commit
b89735eef9
|
@ -13,7 +13,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!badgeLoaded" (ionRefresh)="refreshBadges($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="badgeLoaded">
|
||||
<core-loading [hideUntil]="badgeLoaded" class="list-item-limited-width">
|
||||
<ion-item-group *ngIf="badge">
|
||||
<ion-item class="ion-text-wrap ion-text-center">
|
||||
<ion-label>
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refresh($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-item *ngIf="showMyEntriesToggle">
|
||||
<ion-label>{{ 'addon.blog.showonlyyourentries' | translate }}</ion-label>
|
||||
<ion-toggle [(ngModel)]="onlyMyEntries" (ionChange)="onlyMyEntriesToggleChanged(onlyMyEntries)"></ion-toggle>
|
||||
|
@ -68,7 +68,8 @@
|
|||
</ion-card-content>
|
||||
<div class="ion-text-center ion-margin-bottom" *ngIf="entry.lastmodified > entry.created">
|
||||
<ion-note>
|
||||
<ion-icon name="fas-clock" [attr.aria-label]="'core.lastmodified' | translate"></ion-icon> {{entry.lastmodified |
|
||||
<ion-icon name="fas-clock" [attr.aria-label]="'core.lastmodified' | translate"></ion-icon> {{entry.lastmodified
|
||||
|
|
||||
coreTimeAgo}}
|
||||
</ion-note>
|
||||
</div>
|
||||
|
|
|
@ -18,14 +18,14 @@ import { CoreSharedModule } from '@/core/shared.module';
|
|||
|
||||
import { AddonCalendarCalendarComponent } from './calendar/calendar';
|
||||
import { AddonCalendarUpcomingEventsComponent } from './upcoming-events/upcoming-events';
|
||||
import { AddonCalendarFilterPopoverComponent } from './filter/filter';
|
||||
import { AddonCalendarFilterComponent } from './filter/filter';
|
||||
import { AddonCalendarReminderTimeModalComponent } from './reminder-time-modal/reminder-time-modal';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AddonCalendarCalendarComponent,
|
||||
AddonCalendarUpcomingEventsComponent,
|
||||
AddonCalendarFilterPopoverComponent,
|
||||
AddonCalendarFilterComponent,
|
||||
AddonCalendarReminderTimeModalComponent,
|
||||
],
|
||||
imports: [
|
||||
|
@ -36,7 +36,7 @@ import { AddonCalendarReminderTimeModalComponent } from './reminder-time-modal/r
|
|||
exports: [
|
||||
AddonCalendarCalendarComponent,
|
||||
AddonCalendarUpcomingEventsComponent,
|
||||
AddonCalendarFilterPopoverComponent,
|
||||
AddonCalendarFilterComponent,
|
||||
AddonCalendarReminderTimeModalComponent,
|
||||
],
|
||||
})
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<ion-list>
|
||||
<ion-item *ngFor="let type of types" class="addon-calendar-event" [ngClass]="['addon-calendar-eventtype-'+type]">
|
||||
<ion-icon [name]="typeIcons[type]" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{ 'addon.calendar.' + type + 'events' | translate}}</ion-label>
|
||||
<ion-toggle [(ngModel)]="filter[type]" (ionChange)="onChange()" slot="end"></ion-toggle>
|
||||
</ion-item>
|
||||
<core-spacer *ngIf="filter.course || filter.category || filter.group"></core-spacer>
|
||||
<ng-container *ngIf="filter.course || filter.category || filter.group">
|
||||
<ion-radio-group [(ngModel)]="courseId" (ionChange)="onChange()">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let course of courses">
|
||||
<ion-label>
|
||||
<core-format-text [text]="course.fullname"></core-format-text>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" [value]="course.id"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ng-container>
|
||||
</ion-list>
|
|
@ -0,0 +1,29 @@
|
|||
<ion-header class="no-title">
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
||||
<ion-icon name="fas-times" slot="icon-only" aria-hidden=true></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content [fullscreen]="true">
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let type of types" class="addon-calendar-event" [ngClass]="['addon-calendar-eventtype-'+type]">
|
||||
<ion-icon [name]="typeIcons[type]" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{ 'addon.calendar.' + type + 'events' | translate}}</ion-label>
|
||||
<ion-toggle [(ngModel)]="filter[type]" (ionChange)="onChange()" slot="end"></ion-toggle>
|
||||
</ion-item>
|
||||
<core-spacer *ngIf="filter.course || filter.category || filter.group"></core-spacer>
|
||||
<ng-container *ngIf="filter.course || filter.category || filter.group">
|
||||
<ion-radio-group [(ngModel)]="courseId" (ionChange)="onChange()">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let course of courses">
|
||||
<ion-label>
|
||||
<core-format-text [text]="course.fullname"></core-format-text>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" [value]="course.id"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
</ion-content>
|
|
@ -15,6 +15,7 @@
|
|||
import { Component, Input, OnInit } from '@angular/core';
|
||||
import { CoreEnrolledCourseData } from '@features/courses/services/courses';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { ModalController } from '@singletons';
|
||||
import { CoreEvents } from '@singletons/events';
|
||||
import { AddonCalendarEventType, AddonCalendarProvider } from '../../services/calendar';
|
||||
import { AddonCalendarFilter, AddonCalendarEventIcons } from '../../services/calendar-helper';
|
||||
|
@ -23,11 +24,11 @@ import { AddonCalendarFilter, AddonCalendarEventIcons } from '../../services/cal
|
|||
* Component to display the events filter that includes events types and a list of courses.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'addon-calendar-filter-popover',
|
||||
templateUrl: 'addon-calendar-filter-popover.html',
|
||||
styleUrls: ['../../calendar-common.scss', 'filter-popover.scss'],
|
||||
selector: 'addon-calendar-filter',
|
||||
templateUrl: 'filter.html',
|
||||
styleUrls: ['../../calendar-common.scss', 'filter.scss'],
|
||||
})
|
||||
export class AddonCalendarFilterPopoverComponent implements OnInit {
|
||||
export class AddonCalendarFilterComponent implements OnInit {
|
||||
|
||||
@Input() filter: AddonCalendarFilter = {
|
||||
filtered: false,
|
||||
|
@ -56,7 +57,7 @@ export class AddonCalendarFilterPopoverComponent implements OnInit {
|
|||
}
|
||||
|
||||
/**
|
||||
* Init the component.
|
||||
* @inheritdoc
|
||||
*/
|
||||
ngOnInit(): void {
|
||||
this.courseId = this.filter.courseId || -1;
|
||||
|
@ -80,4 +81,11 @@ export class AddonCalendarFilterPopoverComponent implements OnInit {
|
|||
CoreEvents.trigger(AddonCalendarProvider.FILTER_CHANGED_EVENT, this.filter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close modal.
|
||||
*/
|
||||
closeModal(): void {
|
||||
ModalController.dismiss();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,36 +1,38 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<core-empty-box *ngIf="!filteredEvents || !filteredEvents.length" icon="fas-calendar" [message]="'addon.calendar.noevents' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<ion-list *ngIf="filteredEvents && filteredEvents.length" class="ion-no-margin">
|
||||
<ng-container *ngFor="let event of filteredEvents">
|
||||
<ion-item class="ion-text-wrap addon-calendar-event" [attr.aria-label]="event.name" (click)="eventClicked(event)" button
|
||||
[ngClass]="['addon-calendar-eventtype-'+event.eventtype]" detail="true">
|
||||
<core-mod-icon *ngIf="event.moduleIcon" [modicon]="event.moduleIcon" slot="start" [modname]="event.modulename"
|
||||
[componentId]="event.instance" [showAlt]="false"></core-mod-icon>
|
||||
<ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start" aria-hidden="true">
|
||||
</ion-icon>
|
||||
<ion-label>
|
||||
<!-- Add the icon title so accessibility tools read it. -->
|
||||
<span class="sr-only">
|
||||
{{ 'addon.calendar.type' + event.formattedType | translate }}
|
||||
<span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span>
|
||||
</span>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="event.name" [contextLevel]="event.contextLevel"
|
||||
[contextInstanceId]="event.contextInstanceId"></core-format-text>
|
||||
</p>
|
||||
<p [innerHTML]="event.formattedtime"></p>
|
||||
</ion-label>
|
||||
<ion-note *ngIf="event.offline && !event.deleted" slot="end">
|
||||
<ion-icon name="fas-clock" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span>
|
||||
</ion-note>
|
||||
<ion-note *ngIf="event.deleted" slot="end">
|
||||
<ion-icon name="fas-trash" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
<ion-card>
|
||||
<ion-item class="ion-text-wrap addon-calendar-event" [attr.aria-label]="event.name" (click)="eventClicked(event)" button
|
||||
[ngClass]="['addon-calendar-eventtype-'+event.eventtype]" [detail]="false">
|
||||
<core-mod-icon *ngIf="event.moduleIcon" [modicon]="event.moduleIcon" slot="start" [modname]="event.modulename"
|
||||
[componentId]="event.instance" [showAlt]="false"></core-mod-icon>
|
||||
<ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start" aria-hidden="true">
|
||||
</ion-icon>
|
||||
<ion-label>
|
||||
<!-- Add the icon title so accessibility tools read it. -->
|
||||
<span class="sr-only">
|
||||
{{ 'addon.calendar.type' + event.formattedType | translate }}
|
||||
<span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span>
|
||||
</span>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="event.name" [contextLevel]="event.contextLevel"
|
||||
[contextInstanceId]="event.contextInstanceId"></core-format-text>
|
||||
</p>
|
||||
<p [innerHTML]="event.formattedtime"></p>
|
||||
</ion-label>
|
||||
<ion-note *ngIf="event.offline && !event.deleted" slot="end">
|
||||
<ion-icon name="fas-clock" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span>
|
||||
</ion-note>
|
||||
<ion-note *ngIf="event.deleted" slot="end">
|
||||
<ion-icon name="fas-trash" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<h1>{{ 'addon.calendar.calendarevents' | translate }}</h1>
|
||||
</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button fill="clear" (click)="openFilter($event)" [attr.aria-label]="'core.filter' | translate">
|
||||
<ion-button fill="clear" (click)="openFilter()" [attr.aria-label]="'core.filter' | translate">
|
||||
<ion-icon slot="icon-only" name="fas-filter" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
<core-context-menu>
|
||||
|
@ -50,7 +50,7 @@
|
|||
|
||||
<core-swipe-slides [manager]="manager">
|
||||
<ng-template let-day="item">
|
||||
<core-loading [hideUntil]="day.loaded" class="safe-area-padding">
|
||||
<core-loading [hideUntil]="day.loaded" class="safe-area-padding list-item-limited-width">
|
||||
<!-- There is data to be synchronized -->
|
||||
<ion-card class="core-warning-card" *ngIf="day.hasOffline">
|
||||
<ion-item>
|
||||
|
@ -65,36 +65,39 @@
|
|||
|
||||
<ion-list *ngIf="day.filteredEvents && day.filteredEvents.length" class="ion-no-margin">
|
||||
<ng-container *ngFor="let event of day.filteredEvents">
|
||||
<ion-item class="addon-calendar-event ion-text-wrap" [attr.aria-label]="event.name"
|
||||
(click)="gotoEvent(event.id)" [class.item-dimmed]="event.ispast"
|
||||
[ngClass]="['addon-calendar-eventtype-'+event.eventtype]" button detail="true">
|
||||
<core-mod-icon *ngIf="event.moduleIcon" [modicon]="event.moduleIcon" slot="start" [showAlt]="false"
|
||||
[modname]="event.modulename" [componentId]="event.instance">
|
||||
</core-mod-icon>
|
||||
<ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"
|
||||
aria-hidden="true">
|
||||
</ion-icon>
|
||||
<ion-label>
|
||||
<!-- Add the icon title so accessibility tools read it. -->
|
||||
<span class="sr-only">
|
||||
{{ 'addon.calendar.type' + event.formattedType | translate }}
|
||||
<span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle }}</span>
|
||||
</span>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="event.name" [contextLevel]="event.contextLevel"
|
||||
[contextInstanceId]="event.contextInstanceId"></core-format-text>
|
||||
</p>
|
||||
<p [innerHTML]="event.formattedtime"></p>
|
||||
</ion-label>
|
||||
<ion-note *ngIf="event.offline && !event.deleted" slot="end">
|
||||
<ion-icon name="fas-clock" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span>
|
||||
</ion-note>
|
||||
<ion-note *ngIf="event.deleted" slot="end">
|
||||
<ion-icon name="fas-trash" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
<ion-card>
|
||||
<ion-item class="addon-calendar-event ion-text-wrap" [attr.aria-label]="event.name"
|
||||
(click)="gotoEvent(event.id)" [class.item-dimmed]="event.ispast"
|
||||
[ngClass]="['addon-calendar-eventtype-'+event.eventtype]" button [detail]="false">
|
||||
<core-mod-icon *ngIf="event.moduleIcon" [modicon]="event.moduleIcon" slot="start" [showAlt]="false"
|
||||
[modname]="event.modulename" [componentId]="event.instance">
|
||||
</core-mod-icon>
|
||||
<ion-icon *ngIf="event.eventIcon && !event.moduleIcon" [name]="event.eventIcon" slot="start"
|
||||
aria-hidden="true">
|
||||
</ion-icon>
|
||||
<ion-label>
|
||||
<!-- Add the icon title so accessibility tools read it. -->
|
||||
<span class="sr-only">
|
||||
{{ 'addon.calendar.type' + event.formattedType | translate }}
|
||||
<span class="sr-only" *ngIf="event.moduleIcon && event.iconTitle">{{ event.iconTitle
|
||||
}}</span>
|
||||
</span>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="event.name" [contextLevel]="event.contextLevel"
|
||||
[contextInstanceId]="event.contextInstanceId"></core-format-text>
|
||||
</p>
|
||||
<p [innerHTML]="event.formattedtime"></p>
|
||||
</ion-label>
|
||||
<ion-note *ngIf="event.offline && !event.deleted" slot="end">
|
||||
<ion-icon name="fas-clock" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.notsent' | translate }}</span>
|
||||
</ion-note>
|
||||
<ion-note *ngIf="event.deleted" slot="end">
|
||||
<ion-icon name="fas-trash" aria-hidden="true"></ion-icon>
|
||||
<span class="ion-text-wrap">{{ 'core.deletedoffline' | translate }}</span>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
</core-loading>
|
||||
|
|
|
@ -31,7 +31,7 @@ import { AddonCalendarFilter, AddonCalendarHelper } from '../../services/calenda
|
|||
import { AddonCalendarSync, AddonCalendarSyncProvider } from '../../services/calendar-sync';
|
||||
import { CoreCategoryData, CoreCourses, CoreEnrolledCourseData } from '@features/courses/services/courses';
|
||||
import { CoreCoursesHelper } from '@features/courses/services/courses-helper';
|
||||
import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter';
|
||||
import { AddonCalendarFilterComponent } from '../../components/filter/filter';
|
||||
import moment from 'moment';
|
||||
import { Network, NgZone } from '@singletons';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
|
@ -348,18 +348,15 @@ export class AddonCalendarDayPage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Show the context menu.
|
||||
*
|
||||
* @param event Event.
|
||||
* Show the filter menu.
|
||||
*/
|
||||
async openFilter(event: MouseEvent): Promise<void> {
|
||||
await CoreDomUtils.openPopover({
|
||||
component: AddonCalendarFilterPopoverComponent,
|
||||
async openFilter(): Promise<void> {
|
||||
await CoreDomUtils.openSideModal({
|
||||
component: AddonCalendarFilterComponent,
|
||||
componentProps: {
|
||||
courses: this.manager?.getSource().courses,
|
||||
filter: this.filter,
|
||||
},
|
||||
event,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<h1>{{ (showCalendar ? 'addon.calendar.calendarevents' : 'addon.calendar.upcomingevents') | translate }}</h1>
|
||||
</ion-title>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button fill="clear" (click)="openFilter($event)" [attr.aria-label]="'core.filter' | translate">
|
||||
<ion-button fill="clear" (click)="openFilter()" [attr.aria-label]="'core.filter' | translate">
|
||||
<ion-icon slot="icon-only" name="fas-filter" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
<core-context-menu>
|
||||
|
|
|
@ -29,7 +29,7 @@ import { CoreEnrolledCourseData } from '@features/courses/services/courses';
|
|||
import { ActivatedRoute, Params } from '@angular/router';
|
||||
import { AddonCalendarCalendarComponent } from '../../components/calendar/calendar';
|
||||
import { AddonCalendarUpcomingEventsComponent } from '../../components/upcoming-events/upcoming-events';
|
||||
import { AddonCalendarFilterPopoverComponent } from '../../components/filter/filter';
|
||||
import { AddonCalendarFilterComponent } from '../../components/filter/filter';
|
||||
import { CoreNavigator } from '@services/navigator';
|
||||
import { CoreLocalNotifications } from '@services/local-notifications';
|
||||
import { CoreConstants } from '@/core/constants';
|
||||
|
@ -328,18 +328,15 @@ export class AddonCalendarIndexPage implements OnInit, OnDestroy {
|
|||
}
|
||||
|
||||
/**
|
||||
* Show the context menu.
|
||||
*
|
||||
* @param event Event.
|
||||
* Show the filter menu.
|
||||
*/
|
||||
async openFilter(event: MouseEvent): Promise<void> {
|
||||
await CoreDomUtils.openPopover({
|
||||
component: AddonCalendarFilterPopoverComponent,
|
||||
async openFilter(): Promise<void> {
|
||||
await CoreDomUtils.openSideModal({
|
||||
component: AddonCalendarFilterComponent,
|
||||
componentProps: {
|
||||
courses: this.courses,
|
||||
filter: this.filter,
|
||||
},
|
||||
event,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!competencyLoaded" (ionRefresh)="refreshCompetency($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="competencyLoaded">
|
||||
<core-loading [hideUntil]="competencyLoaded" class="list-item-limited-width">
|
||||
<ion-card *ngIf="user">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<core-user-avatar [user]="user" slot="start"></core-user-avatar>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!competencyLoaded" (ionRefresh)="refreshCompetency($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="competencyLoaded">
|
||||
<core-loading [hideUntil]="competencyLoaded" class="list-item-limited-width">
|
||||
<ion-card *ngIf="competency">
|
||||
<ion-item class="ion-text-wrap" *ngIf="competency.competency.description">
|
||||
<ion-label>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!competencies.loaded" (ionRefresh)="refreshCourseCompetencies($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="competencies.loaded">
|
||||
<core-loading [hideUntil]="competencies.loaded" class="list-item-limited-width">
|
||||
<ion-card *ngIf="!user && courseCompetencies && courseCompetencies.statistics.competencycount > 0">
|
||||
<ng-container *ngIf="courseCompetencies.cangradecompetencies">
|
||||
<ion-item class="ion-text-wrap" *ngIf="courseCompetencies.settings.pushratingstouserplans">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!competencies.loaded" (ionRefresh)="refreshLearningPlan($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="competencies.loaded">
|
||||
<core-loading [hideUntil]="competencies.loaded" class="list-item-limited-width">
|
||||
<ion-card *ngIf="user">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
|
|
|
@ -69,7 +69,8 @@
|
|||
|
||||
<h2 class="sr-only">{{ title }}</h2>
|
||||
|
||||
<ion-list class="addon-messages-discussion-container" [class.addon-messages-discussion-group]="isGroup" [attr.aria-live]="'polite'">
|
||||
<ion-list class="addon-messages-discussion-container list-item-limited-width" [class.addon-messages-discussion-group]="isGroup"
|
||||
[attr.aria-live]="'polite'">
|
||||
<ng-container *ngFor="let message of messages; index as index; last as last">
|
||||
<h3 class="ion-text-center addon-messages-date" *ngIf="message.showDate">
|
||||
{{ message.timecreated | coreFormatDate: "strftimedayshort" }}
|
||||
|
@ -157,7 +158,7 @@
|
|||
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" (click)="confirmContactRequest()">
|
||||
{{ 'addon.messages.acceptandaddcontact' | translate }}
|
||||
</ion-button>
|
||||
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" fill="outline" (click)="declineContactRequest()">
|
||||
<ion-button expand="block" class="ion-text-wrap ion-margin-bottom" color="light" (click)="declineContactRequest()">
|
||||
{{ 'addon.messages.decline' | translate }}
|
||||
</ion-button>
|
||||
</div>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
|
||||
<!-- User and status of the submission. -->
|
||||
<ion-item class="ion-text-wrap" *ngIf="!blindMarking && user" core-user-link [userId]="submitId" [courseId]="courseId"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-page">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-page list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -7,65 +7,66 @@
|
|||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<div class="list-item-limited-width">
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
[courseId]="courseId" [hasDataToSync]="hasOffline">
|
||||
</core-course-module-info>
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
[courseId]="courseId" [hasDataToSync]="hasOffline">
|
||||
</core-course-module-info>
|
||||
|
||||
<!-- Activity availability messages -->
|
||||
<ion-card class="core-info-card" *ngIf="choiceNotOpenYet">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<p *ngIf="options.length">{{ 'addon.mod_choice.previewonly' | translate:{$a: openTimeReadable} }}</p>
|
||||
<p *ngIf="!options.length">{{ 'addon.mod_choice.notopenyet' | translate:{$a: openTimeReadable} }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<ion-card class="core-info-card" *ngIf="choiceClosed">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<p *ngIf="options.length">
|
||||
{{ 'addon.mod_choice.yourselection' | translate }}
|
||||
<core-format-text [text]="options[0].text" contextLevel="module" [contextInstanceId]="module.id" [courseId]="courseId">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p>{{ 'addon.mod_choice.expired' | translate:{$a: closeTimeReadable} }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<!-- Inform what will happen with the choices. -->
|
||||
<ion-card class="core-info-card" *ngIf="canEdit && publishInfo && options.length">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{ publishInfo | translate }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<!-- Choice options -->
|
||||
<ion-card *ngIf="options.length && choice">
|
||||
<ng-container *ngIf="choice.allowmultiple">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let option of options">
|
||||
<!-- Activity availability messages -->
|
||||
<ion-card class="core-info-card" *ngIf="choiceNotOpenYet">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<ng-container *ngTemplateOutlet="optionLabelTemplate; context: {option: option}"></ng-container>
|
||||
<p *ngIf="options.length">{{ 'addon.mod_choice.previewonly' | translate:{$a: openTimeReadable} }}</p>
|
||||
<p *ngIf="!options.length">{{ 'addon.mod_choice.notopenyet' | translate:{$a: openTimeReadable} }}</p>
|
||||
</ion-label>
|
||||
<ion-checkbox slot="end" [(ngModel)]="option.checked" [disabled]="option.disabled || !canEdit"></ion-checkbox>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
<ion-radio-group *ngIf="!choice.allowmultiple" [(ngModel)]="selectedOption.id">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let option of options">
|
||||
<ion-label>
|
||||
<ng-container *ngTemplateOutlet="optionLabelTemplate; context: {option: option}"></ng-container>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" [value]="option.id" [disabled]="option.disabled || !canEdit"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ion-card>
|
||||
</ion-card>
|
||||
|
||||
<ion-card class="core-info-card" *ngIf="choiceClosed">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<p *ngIf="options.length">
|
||||
{{ 'addon.mod_choice.yourselection' | translate }}
|
||||
<core-format-text [text]="options[0].text" contextLevel="module" [contextInstanceId]="module.id"
|
||||
[courseId]="courseId">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p>{{ 'addon.mod_choice.expired' | translate:{$a: closeTimeReadable} }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<!-- Inform what will happen with the choices. -->
|
||||
<ion-card class="core-info-card" *ngIf="canEdit && publishInfo && options.length">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-info-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{ publishInfo | translate }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<!-- Choice options -->
|
||||
<ion-card *ngIf="options.length && choice">
|
||||
<ng-container *ngIf="choice.allowmultiple">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let option of options">
|
||||
<ion-label>
|
||||
<ng-container *ngTemplateOutlet="optionLabelTemplate; context: {option: option}"></ng-container>
|
||||
</ion-label>
|
||||
<ion-checkbox slot="end" [(ngModel)]="option.checked" [disabled]="option.disabled || !canEdit"></ion-checkbox>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
<ion-radio-group *ngIf="!choice.allowmultiple" [(ngModel)]="selectedOption.id">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let option of options">
|
||||
<ion-label>
|
||||
<ng-container *ngTemplateOutlet="optionLabelTemplate; context: {option: option}"></ng-container>
|
||||
</ion-label>
|
||||
<ion-radio slot="end" [value]="option.id" [disabled]="option.disabled || !canEdit"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
</ion-card>
|
||||
</div>
|
||||
<!-- Choice results -->
|
||||
<div *ngIf="canSeeResults && choice">
|
||||
<ion-item-divider>
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -16,7 +16,8 @@
|
|||
(ionRefresh)="refreshDatabase($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="entryLoaded && (isPullingToRefresh || !renderingEntry && !loadingRating && !loadingComments)">
|
||||
<core-loading [hideUntil]="entryLoaded && (isPullingToRefresh || !renderingEntry && !loadingRating && !loadingComments)"
|
||||
class="list-item-limited-width">
|
||||
<!-- Database entries found to be synchronized -->
|
||||
<ion-card class="core-warning-card" *ngIf="entry && entry.hasOffline">
|
||||
<ion-item>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="feedbackLoaded" class="has-spacer">
|
||||
<core-loading [hideUntil]="feedbackLoaded" class="has-spacer list-item-limited-width">
|
||||
<ng-container *ngIf="items && items.length">
|
||||
<ion-list class="ion-no-margin has-spacer">
|
||||
<ion-item class="ion-text-wrap">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info *ngIf="!subfolder" [module]="module" [description]="description" [component]="component"
|
||||
|
|
|
@ -60,7 +60,7 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<core-loading [hideUntil]="discussionLoaded">
|
||||
<core-loading [hideUntil]="discussionLoaded" class="list-item-limited-width">
|
||||
<!-- Discussion replies found to be synchronized -->
|
||||
<ion-card class="core-warning-card" *ngIf="postHasOffline || hasOfflineRatings">
|
||||
<ion-item>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ng-container *ngIf="entry && loaded">
|
||||
<ion-item class="ion-text-wrap" *ngIf="showAuthor">
|
||||
<core-user-avatar [user]="entry" slot="start"></core-user-avatar>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding core-loading-full-height">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
<core-tabs [hideUntil]="!showLoading" [selectedIndex]="selectedTab">
|
||||
<!-- Index/Preview tab. -->
|
||||
<core-tab [title]="'addon.mod_lesson.preview' | translate" (ionSelect)="indexSelected()">
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<!-- Info messages. Only show the first one. -->
|
||||
<ion-card class="core-info-card" *ngIf="lesson && messages?.length">
|
||||
<ion-item class="ion-text-wrap">
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<div *ngIf="student">
|
||||
<!-- Student data. -->
|
||||
<ion-item class="ion-text-wrap" core-user-link [userId]="student.id" [courseId]="courseId" [attr.aria-label]="student.fullname">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="displayDescription && description" [component]="component"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="displayDescription && description" [component]="component"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="doRefresh($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-list *ngIf="attempt">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="loaded" class="has-spacer">
|
||||
<core-loading [hideUntil]="loaded" class="has-spacer list-item-limited-width">
|
||||
<!-- Button to start attempting. -->
|
||||
<ion-button *ngIf="!attempt" expand="block" class="ion-margin" (click)="start()">
|
||||
{{ 'addon.mod_quiz.startattempt' | translate }}
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refreshData($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
|
||||
<!-- Review summary -->
|
||||
<ion-card *ngIf="attempt">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding core-loading-full-height">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding core-loading-full-height list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [courseId]="courseId" [description]="displayDescription && description"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
@ -21,7 +21,7 @@
|
|||
</ion-item>
|
||||
</ion-card>
|
||||
|
||||
<div *ngIf="scorm && !showLoading && !scorm.warningMessage" class="list-item-limited-width">
|
||||
<div *ngIf="scorm && !showLoading && !scorm.warningMessage">
|
||||
<!-- Attempts status. -->
|
||||
<ion-card *ngIf="(scorm.displayattemptstatus || offlineAttempts.length) && !skip">
|
||||
<ion-card-header class="ion-text-wrap">
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding">
|
||||
<core-loading [hideUntil]="!showLoading" class="safe-area-padding list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="survey && !survey.surveydone && !hasOffline && description"
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="displayDescription && description" [component]="component"
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-item class="ion-text-wrap" [detail]="canViewAssessment && !canSelfAssess" (click)="gotoAssessment($event)"
|
||||
[button]="canViewAssessment && !canSelfAssess">
|
||||
<core-user-avatar [user]="profile" slot="start" [courseId]="courseId" [userId]="profile?.id"></core-user-avatar>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
</core-navbar-buttons>
|
||||
|
||||
<!-- Content. -->
|
||||
<core-loading [hideUntil]="!showLoading">
|
||||
<core-loading [hideUntil]="!showLoading" class="list-item-limited-width">
|
||||
|
||||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [hasDataToSync]="hasOffline">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<div *ngIf="!summary">
|
||||
<ion-item class="ion-text-wrap addon-workshop-submission-title">
|
||||
<core-user-avatar [user]="profile" [courseId]="courseId" [userId]="profile?.id" slot="start">
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<core-loading [hideUntil]="notesLoaded">
|
||||
<core-loading [hideUntil]="notesLoaded" class="list-item-limited-width">
|
||||
<ion-item class="ion-text-wrap" *ngIf="user">
|
||||
<core-user-avatar [user]="user" [courseId]="courseId" slot="start" [linkProfile]="false"></core-user-avatar>
|
||||
<ion-label>
|
||||
|
|
|
@ -16,64 +16,67 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="notificationsLoaded">
|
||||
<div class="ion-padding" *ngIf="canMarkAllNotificationsAsRead">
|
||||
<ion-button [disabled]="loadingMarkAllNotificationsAsRead" expand="block" (click)="markAllNotificationsAsRead()" fill="outline">
|
||||
<ion-icon slot="start" name="fas-check" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
|
||||
<ion-spinner slot="start" [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
|
||||
</ion-spinner>
|
||||
{{ 'addon.notifications.markallread' | translate }}
|
||||
</ion-button>
|
||||
</div>
|
||||
<div class="list-item-limited-width">
|
||||
|
||||
<ion-card *ngFor="let notification of notifications">
|
||||
<ion-item class="ion-text-wrap" [attr.aria-label]="
|
||||
<div class="ion-padding" *ngIf="canMarkAllNotificationsAsRead">
|
||||
<ion-button [disabled]="loadingMarkAllNotificationsAsRead" expand="block" (click)="markAllNotificationsAsRead()"
|
||||
fill="outline">
|
||||
<ion-icon slot="start" name="fas-check" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
|
||||
<ion-spinner slot="start" [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
|
||||
</ion-spinner>
|
||||
{{ 'addon.notifications.markallread' | translate }}
|
||||
</ion-button>
|
||||
</div>
|
||||
|
||||
<ion-card *ngFor="let notification of notifications">
|
||||
<ion-item class="ion-text-wrap" [attr.aria-label]="
|
||||
notification.timeread
|
||||
? notification.subject
|
||||
: 'addon.notifications.unreadnotification' | translate: {$a: notification.subject}">
|
||||
<core-user-avatar *ngIf="notification.useridfrom > 0" [user]="notification" slot="start"
|
||||
[profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname"
|
||||
[userId]="notification.useridfrom">
|
||||
<img *ngIf="notification.iconurl && !notification.modname" [src]="notification.iconurl" alt="" role="presentation"
|
||||
class="core-avatar-extra">
|
||||
<core-mod-icon *ngIf="notification.modname" [modicon]="notification.iconurl" [modname]="notification.modname"
|
||||
[showAlt]="false" class="core-avatar-extra">
|
||||
</core-mod-icon>
|
||||
</core-user-avatar>
|
||||
<core-user-avatar *ngIf="notification.useridfrom > 0" [user]="notification" slot="start"
|
||||
[profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname"
|
||||
[userId]="notification.useridfrom">
|
||||
<img *ngIf="notification.iconurl && !notification.modname" [src]="notification.iconurl" alt="" role="presentation"
|
||||
class="core-avatar-extra">
|
||||
<core-mod-icon *ngIf="notification.modname" [modicon]="notification.iconurl" [modname]="notification.modname"
|
||||
[showAlt]="false" class="core-avatar-extra">
|
||||
</core-mod-icon>
|
||||
</core-user-avatar>
|
||||
|
||||
<img *ngIf="notification.useridfrom <= 0 && notification.iconurl" [src]="notification.iconurl" alt="" role="presentation"
|
||||
class="core-notification-icon" slot="start">
|
||||
<img *ngIf="notification.useridfrom <= 0 && notification.iconurl" [src]="notification.iconurl" alt=""
|
||||
role="presentation" class="core-notification-icon" slot="start">
|
||||
|
||||
<ion-label>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="notification.subject" contextLevel="system" [contextInstanceId]="0"
|
||||
[wsNotFiltered]="true">
|
||||
<ion-label>
|
||||
<p class="item-heading">
|
||||
<core-format-text [text]="notification.subject" contextLevel="system" [contextInstanceId]="0"
|
||||
[wsNotFiltered]="true">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p *ngIf="notification.useridfrom > 0">{{ notification.userfromfullname }}</p>
|
||||
</ion-label>
|
||||
<ion-note slot="end" class="ion-float-end ion-text-end">
|
||||
{{ notification.timecreated | coreDateDayOrTime }}
|
||||
<span *ngIf="!notification.timeread">
|
||||
<ion-icon name="fas-circle" color="primary" aria-hidden="true"></ion-icon>
|
||||
</span>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<core-format-text [text]="notification.mobiletext | coreCreateLinks" contextLevel="system" [contextInstanceId]="0"
|
||||
[maxHeight]="120">
|
||||
</core-format-text>
|
||||
</p>
|
||||
<p *ngIf="notification.useridfrom > 0">{{ notification.userfromfullname }}</p>
|
||||
</ion-label>
|
||||
<ion-note slot="end" class="ion-float-end ion-text-end">
|
||||
{{ notification.timecreated | coreDateDayOrTime }}
|
||||
<span *ngIf="!notification.timeread">
|
||||
<ion-icon name="fas-circle" color="primary" aria-hidden="true"></ion-icon>
|
||||
</span>
|
||||
</ion-note>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<core-format-text [text]="notification.mobiletext | coreCreateLinks" contextLevel="system" [contextInstanceId]="0"
|
||||
[maxHeight]="120">
|
||||
</core-format-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<addon-notifications-actions [contextUrl]="notification.contexturl" [courseId]="notification.courseid"
|
||||
[data]="notification.customdata">
|
||||
</addon-notifications-actions>
|
||||
</ion-card>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<addon-notifications-actions [contextUrl]="notification.contexturl" [courseId]="notification.courseid"
|
||||
[data]="notification.customdata">
|
||||
</addon-notifications-actions>
|
||||
</ion-card>
|
||||
</div>
|
||||
|
||||
<core-empty-box *ngIf="!notifications || notifications.length <= 0" icon="far-bell"
|
||||
[message]="'addon.notifications.therearentnotificationsyet' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreNotifications($event)" [error]="loadMoreError">
|
||||
</core-infinite-loading>
|
||||
</core-loading>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
|
||||
<core-loading [hideUntil]="filesLoaded" *ngIf="showPrivateFiles || showSiteFiles">
|
||||
<core-loading [hideUntil]="filesLoaded" *ngIf="showPrivateFiles || showSiteFiles" class="list-item-limited-width">
|
||||
<!-- Allow selecting the files to see: private or site. -->
|
||||
<core-combobox [selection]="root" (onChange)="rootChanged($event)" *ngIf="showPrivateFiles && showSiteFiles && !path">
|
||||
<ion-select-option class="ion-text-wrap" value="my">
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-card class="wholecourse">
|
||||
<ion-card-header>
|
||||
<p class="ion-text-wrap ion-no-margin">{{ 'addon.storagemanager.courseinfo' | translate }}</p>
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<div class="ion-padding-horizontal ion-text-wrap" *ngIf="spaceUsage">
|
||||
<h2>{{ 'addon.storagemanager.alldata' | translate }}</h2>
|
||||
</div>
|
||||
|
|
|
@ -81,6 +81,12 @@
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
&.list-item-limited-width .core-loading-content {
|
||||
max-width: var(--list-item-max-width);
|
||||
margin-left: auto !important;
|
||||
margin-right: auto !important;
|
||||
}
|
||||
|
||||
&.safe-area-padding:not(.core-loading-inline) .core-loading-content,
|
||||
&.safe-area-padding-horizontal:not(.core-loading-inline) .core-loading-content {
|
||||
@include safe-area-padding-horizontal(0px, 0px);
|
||||
|
|
|
@ -38,7 +38,7 @@
|
|||
<core-infinite-loading [enabled]="canLoadMore" position="top" (action)="loadPrevious($event)" [error]="loadMoreError">
|
||||
</core-infinite-loading>
|
||||
|
||||
<ion-list class="addon-messages-discussion-container">
|
||||
<ion-list class="addon-messages-discussion-container list-item-limited-width">
|
||||
<ng-container *ngFor="let comment of comments; index as index; last as last">
|
||||
|
||||
<p class="ion-text-center addon-messages-date" *ngIf="comment.showDate">
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
<ion-item class="ion-text-wrap" *ngFor="let item of items" (click)="openCourse(item.courseId)" [attr.aria-label]="item.courseName" button
|
||||
detail="true">
|
||||
<ion-icon name="fas-graduation-cap" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ item.courseName }}</p>
|
||||
<p *ngIf="item.categoryName">{{ 'core.category' | translate }}: {{ item.categoryName }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-card *ngFor="let item of items">
|
||||
<ion-item class="ion-text-wrap" (click)="openCourse(item.courseId)" [attr.aria-label]="item.courseName" button detail="true">
|
||||
<ion-icon name="fas-graduation-cap" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ item.courseName }}</p>
|
||||
<p *ngIf="item.categoryName">{{ 'core.category' | translate }}: {{ item.categoryName }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
</ion-card>
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="doRefresh($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded" class="has-spacer">
|
||||
<core-loading [hideUntil]="loaded" class="has-spacer list-item-limited-width">
|
||||
<core-course-module-info [module]="module" [courseId]="courseId" [description]="module.description" [component]="module.modname"
|
||||
[componentId]="module.id" [expandDescription]="true" [showAvailabilityInfo]="true">
|
||||
<div class="core-module-additional-info" title>
|
||||
|
|
|
@ -102,7 +102,7 @@ ion-chip {
|
|||
|
||||
// List layout.
|
||||
ion-card.core-course-list-item {
|
||||
max-width: var(--list-item--max-width);
|
||||
max-width: var(--list-item-max-width);
|
||||
|
||||
ion-icon.course-icon {
|
||||
padding: 12px;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-list class="list-item-limited-width">
|
||||
<ng-container *ngIf="!changingPassword">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<core-loading [hideUntil]="pageLoaded">
|
||||
<core-loading [hideUntil]="pageLoaded" class="list-item-limited-width">
|
||||
<div class="ion-text-wrap ion-text-center ion-margin-bottom">
|
||||
<div class="core-login-site-logo">
|
||||
<!-- Show site logo or a default image. -->
|
||||
|
@ -73,7 +73,7 @@
|
|||
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-button fill="outline" *ngFor="let provider of identityProviders" class="ion-text-wrap core-oauth-provider"
|
||||
<ion-button fill="outline" *ngFor="let provider of identityProviders" class="ion-text-wrap ion-margin core-oauth-provider"
|
||||
(click)="oauthClicked(provider)" [attr.aria-label]="provider.name" expand="block">
|
||||
<img [src]="provider.iconurl" alt="" width="32" height="32" slot="start">
|
||||
<ion-label>{{provider.name}}</ion-label>
|
||||
|
|
|
@ -20,228 +20,230 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!settingsLoaded || isMinor" (ionRefresh)="refreshSettings($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<div class="list-item-limited-width">
|
||||
|
||||
<core-loading [hideUntil]="settingsLoaded" *ngIf="!isMinor">
|
||||
<core-loading [hideUntil]="settingsLoaded" *ngIf="!isMinor">
|
||||
|
||||
<!-- Site has an unsupported required field. -->
|
||||
<ion-list *ngIf="!allRequiredSupported">
|
||||
<!-- Site has an unsupported required field. -->
|
||||
<ion-list *ngIf="!allRequiredSupported">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
{{ 'core.login.signuprequiredfieldnotsupported' | translate }}
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-button expand="block" class="ion-margin" [href]="signupUrl" core-link autoLogin="no" [showBrowserWarning]="false">
|
||||
{{ 'core.openinbrowser' | translate }}
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
|
||||
<!-- Age verification. -->
|
||||
<form *ngIf="allRequiredSupported && settingsLoaded && settings && ageDigitalConsentVerification"
|
||||
[formGroup]="ageVerificationForm" (ngSubmit)="verifyAge($event)" #ageForm>
|
||||
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.agelocationverification' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.whatisyourage' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="number" name="age" placeholder="0" formControlName="age" autocapitalize="none" autocorrect="off">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.wheredoyoulive' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-select name="country" formControlName="country" [placeholder]="'core.login.selectacountry' | translate">
|
||||
<ion-select-option value="">{{ 'core.login.selectacountry' | translate }}</ion-select-option>
|
||||
<ion-select-option *ngFor="let country of countries" [value]="country.code">{{country.name}}</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<!-- Submit button. -->
|
||||
<ion-button expand="block" class="ion-margin" type="submit" [disabled]="!ageVerificationForm.valid">
|
||||
{{ 'core.proceed' | translate }}
|
||||
</ion-button>
|
||||
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'core.whyisthisrequired' | translate }}</h3>
|
||||
<p>{{ 'core.explanationdigitalminor' | translate }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</form>
|
||||
|
||||
<!-- Signup form. -->
|
||||
<form *ngIf="allRequiredSupported && settingsLoaded && settings && !ageDigitalConsentVerification" [formGroup]="signupForm"
|
||||
(ngSubmit)="create($event)" #signupFormEl>
|
||||
|
||||
<ion-item class="ion-text-wrap ion-text-center">
|
||||
<ion-label>
|
||||
<!-- If no sitename show big siteurl. -->
|
||||
<p *ngIf="!siteName" class="ion-padding item-heading">{{siteUrl}}</p>
|
||||
<!-- If sitename, show big sitename and small siteurl. -->
|
||||
<p *ngIf="siteName" class="ion-padding item-heading">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</p>
|
||||
<p *ngIf="siteName">{{siteUrl}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<!-- Username and password. -->
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.login.createuserandpass' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.login.username' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username"
|
||||
autocapitalize="none" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls.username" [errorMessages]="usernameErrors"></core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.login.password' | translate }}</span>
|
||||
</ion-label>
|
||||
<core-show-password name="password">
|
||||
<ion-input name="password" type="password" placeholder="{{ 'core.login.password' | translate }}"
|
||||
formControlName="password" [clearOnEdit]="false" autocomplete="new-password" required="true">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
<p *ngIf="settings.passwordpolicy" class="core-input-footnote">
|
||||
{{settings.passwordpolicy}}
|
||||
</p>
|
||||
<core-input-errors [control]="signupForm.controls.password" [errorMessages]="passwordErrors"></core-input-errors>
|
||||
</ion-item>
|
||||
|
||||
<!-- More details. -->
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.login.supplyinfo' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.user.email' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="email" name="email" placeholder="{{ 'core.user.email' | translate }}" formControlName="email"
|
||||
autocapitalize="none" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls.email" [errorMessages]="emailErrors"></core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.user.emailagain' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="email" name="email2" placeholder="{{ 'core.user.emailagain' | translate }}" autocapitalize="none"
|
||||
formControlName="email2" autocorrect="off" [pattern]="escapeMail(signupForm.controls.email.value)">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls.email2" [errorMessages]="email2Errors"></core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item *ngFor="let nameField of settings.namefields" class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.user.' + nameField | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="text" name="nameField" placeholder="{{ 'core.user.' + nameField | translate }}"
|
||||
formControlName="{{nameField}}" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls[nameField]" [errorMessages]="namefieldsErrors![nameField]">
|
||||
</core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">{{ 'core.user.city' | translate }}</ion-label>
|
||||
<ion-input type="text" name="city" placeholder="{{ 'core.user.city' | translate }}" formControlName="city"
|
||||
autocorrect="off">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked" id="core-login-signup-country">{{ 'core.user.country' | translate }}</ion-label>
|
||||
<ion-select name="country" formControlName="country" aria-labelledby="core-login-signup-country"
|
||||
[placeholder]="'core.login.selectacountry' | translate">
|
||||
|
||||
<ion-select-option value="">{{ 'core.login.selectacountry' | translate }}</ion-select-option>
|
||||
<ion-select-option *ngFor="let country of countries" [value]="country.code">{{country.name}}</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<!-- Other categories. -->
|
||||
<ng-container *ngFor="let category of categories">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ category.name }}</p>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<core-user-profile-field *ngFor="let field of category.fields" [field]="field" [edit]="true" [signup]="true"
|
||||
registerAuth="email" [form]="signupForm"></core-user-profile-field>
|
||||
</ng-container>
|
||||
|
||||
<!-- ReCAPTCHA -->
|
||||
<ng-container *ngIf="settings.recaptchapublickey">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3><span [core-mark-required]="true">{{ 'core.login.security_question' | translate }}</span></h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<core-recaptcha [publicKey]="settings.recaptchapublickey" [model]="captcha" [siteUrl]="siteUrl"></core-recaptcha>
|
||||
</ng-container>
|
||||
|
||||
<!-- Site policy (if any). -->
|
||||
<ng-container *ngIf="settings.sitepolicy">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.login.policyagreement' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<a [href]="settings.sitepolicy" core-link capture="false">
|
||||
{{ 'core.login.policyagreementclick' | translate }}
|
||||
</a>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<span [core-mark-required]="true">{{ 'core.login.policyacceptmandatory' | translate }}</span>
|
||||
<core-input-errors [control]="signupForm.controls.policyagreed" [errorMessages]="policyErrors">
|
||||
</core-input-errors>
|
||||
</ion-label>
|
||||
<ion-checkbox slot="end" name="policyagreed" formControlName="policyagreed"></ion-checkbox>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Submit button. -->
|
||||
<ion-button expand="block" class="ion-margin" type="submit">{{ 'core.login.createaccount' | translate }}</ion-button>
|
||||
<!-- Remove this once Ionic fixes this bug: https://github.com/ionic-team/ionic-framework/issues/19368 -->
|
||||
<input type="submit" class="core-submit-hidden-enter" />
|
||||
</form>
|
||||
</core-loading>
|
||||
|
||||
<ion-list *ngIf="allRequiredSupported && isMinor">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 *ngIf="siteName" class="item-heading ion-padding">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
{{ 'core.login.signuprequiredfieldnotsupported' | translate }}
|
||||
<h3 class="item-heading">{{ 'core.considereddigitalminor' | translate }}</h3>
|
||||
<p>{{ 'core.digitalminor_desc' | translate }}</p>
|
||||
<p *ngIf="supportName">{{ supportName }}</p>
|
||||
<p *ngIf="supportEmail">{{ supportEmail }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-button expand="block" class="ion-margin" [href]="signupUrl" core-link autoLogin="no" [showBrowserWarning]="false">
|
||||
<ion-button *ngIf="!supportName && !supportEmail" expand="block" class="ion-margin" (click)="showContactOnSite()">
|
||||
{{ 'core.openinbrowser' | translate }}
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
|
||||
<!-- Age verification. -->
|
||||
<form *ngIf="allRequiredSupported && settingsLoaded && settings && ageDigitalConsentVerification" [formGroup]="ageVerificationForm"
|
||||
(ngSubmit)="verifyAge($event)" #ageForm>
|
||||
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.agelocationverification' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.whatisyourage' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="number" name="age" placeholder="0" formControlName="age" autocapitalize="none" autocorrect="off">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.wheredoyoulive' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-select name="country" formControlName="country" [placeholder]="'core.login.selectacountry' | translate">
|
||||
<ion-select-option value="">{{ 'core.login.selectacountry' | translate }}</ion-select-option>
|
||||
<ion-select-option *ngFor="let country of countries" [value]="country.code">{{country.name}}</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<!-- Submit button. -->
|
||||
<ion-button expand="block" class="ion-margin" type="submit" [disabled]="!ageVerificationForm.valid">
|
||||
{{ 'core.proceed' | translate }}
|
||||
</ion-button>
|
||||
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'core.whyisthisrequired' | translate }}</h3>
|
||||
<p>{{ 'core.explanationdigitalminor' | translate }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</form>
|
||||
|
||||
<!-- Signup form. -->
|
||||
<form *ngIf="allRequiredSupported && settingsLoaded && settings && !ageDigitalConsentVerification" [formGroup]="signupForm"
|
||||
(ngSubmit)="create($event)" #signupFormEl>
|
||||
|
||||
<ion-item class="ion-text-wrap ion-text-center">
|
||||
<ion-label>
|
||||
<!-- If no sitename show big siteurl. -->
|
||||
<p *ngIf="!siteName" class="ion-padding item-heading">{{siteUrl}}</p>
|
||||
<!-- If sitename, show big sitename and small siteurl. -->
|
||||
<p *ngIf="siteName" class="ion-padding item-heading">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</p>
|
||||
<p *ngIf="siteName">{{siteUrl}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<!-- Username and password. -->
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.login.createuserandpass' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.login.username' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="text" name="username" placeholder="{{ 'core.login.username' | translate }}" formControlName="username"
|
||||
autocapitalize="none" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls.username" [errorMessages]="usernameErrors"></core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.login.password' | translate }}</span>
|
||||
</ion-label>
|
||||
<core-show-password name="password">
|
||||
<ion-input name="password" type="password" placeholder="{{ 'core.login.password' | translate }}"
|
||||
formControlName="password" [clearOnEdit]="false" autocomplete="new-password" required="true">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
<p *ngIf="settings.passwordpolicy" class="core-input-footnote">
|
||||
{{settings.passwordpolicy}}
|
||||
</p>
|
||||
<core-input-errors [control]="signupForm.controls.password" [errorMessages]="passwordErrors"></core-input-errors>
|
||||
</ion-item>
|
||||
|
||||
<!-- More details. -->
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.login.supplyinfo' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.user.email' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="email" name="email" placeholder="{{ 'core.user.email' | translate }}" formControlName="email"
|
||||
autocapitalize="none" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls.email" [errorMessages]="emailErrors"></core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.user.emailagain' | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="email" name="email2" placeholder="{{ 'core.user.emailagain' | translate }}" autocapitalize="none"
|
||||
formControlName="email2" autocorrect="off" [pattern]="escapeMail(signupForm.controls.email.value)">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls.email2" [errorMessages]="email2Errors"></core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item *ngFor="let nameField of settings.namefields" class="ion-text-wrap">
|
||||
<ion-label position="stacked">
|
||||
<span core-mark-required="true">{{ 'core.user.' + nameField | translate }}</span>
|
||||
</ion-label>
|
||||
<ion-input type="text" name="nameField" placeholder="{{ 'core.user.' + nameField | translate }}"
|
||||
formControlName="{{nameField}}" autocorrect="off">
|
||||
</ion-input>
|
||||
<core-input-errors [control]="signupForm.controls[nameField]" [errorMessages]="namefieldsErrors![nameField]">
|
||||
</core-input-errors>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked">{{ 'core.user.city' | translate }}</ion-label>
|
||||
<ion-input type="text" name="city" placeholder="{{ 'core.user.city' | translate }}" formControlName="city"
|
||||
autocorrect="off">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label position="stacked" id="core-login-signup-country">{{ 'core.user.country' | translate }}</ion-label>
|
||||
<ion-select name="country" formControlName="country" aria-labelledby="core-login-signup-country"
|
||||
[placeholder]="'core.login.selectacountry' | translate">
|
||||
|
||||
<ion-select-option value="">{{ 'core.login.selectacountry' | translate }}</ion-select-option>
|
||||
<ion-select-option *ngFor="let country of countries" [value]="country.code">{{country.name}}</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
|
||||
<!-- Other categories. -->
|
||||
<ng-container *ngFor="let category of categories">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<p class="item-heading">{{ category.name }}</p>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<core-user-profile-field *ngFor="let field of category.fields" [field]="field" [edit]="true" [signup]="true"
|
||||
registerAuth="email" [form]="signupForm"></core-user-profile-field>
|
||||
</ng-container>
|
||||
|
||||
<!-- ReCAPTCHA -->
|
||||
<ng-container *ngIf="settings.recaptchapublickey">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3><span [core-mark-required]="true">{{ 'core.login.security_question' | translate }}</span></h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<core-recaptcha [publicKey]="settings.recaptchapublickey" [model]="captcha" [siteUrl]="siteUrl"></core-recaptcha>
|
||||
</ng-container>
|
||||
|
||||
<!-- Site policy (if any). -->
|
||||
<ng-container *ngIf="settings.sitepolicy">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3>{{ 'core.login.policyagreement' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<a [href]="settings.sitepolicy" core-link capture="false">
|
||||
{{ 'core.login.policyagreementclick' | translate }}
|
||||
</a>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<span [core-mark-required]="true">{{ 'core.login.policyacceptmandatory' | translate }}</span>
|
||||
<core-input-errors [control]="signupForm.controls.policyagreed" [errorMessages]="policyErrors">
|
||||
</core-input-errors>
|
||||
</ion-label>
|
||||
<ion-checkbox slot="end" name="policyagreed" formControlName="policyagreed"></ion-checkbox>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
|
||||
<!-- Submit button. -->
|
||||
<ion-button expand="block" class="ion-margin" type="submit">{{ 'core.login.createaccount' | translate }}</ion-button>
|
||||
<!-- Remove this once Ionic fixes this bug: https://github.com/ionic-team/ionic-framework/issues/19368 -->
|
||||
<input type="submit" class="core-submit-hidden-enter" />
|
||||
</form>
|
||||
</core-loading>
|
||||
|
||||
<ion-list *ngIf="allRequiredSupported && isMinor">
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 *ngIf="siteName" class="item-heading ion-padding">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</h3>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'core.considereddigitalminor' | translate }}</h3>
|
||||
<p>{{ 'core.digitalminor_desc' | translate }}</p>
|
||||
<p *ngIf="supportName">{{ supportName }}</p>
|
||||
<p *ngIf="supportEmail">{{ supportEmail }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-button *ngIf="!supportName && !supportEmail" expand="block" class="ion-margin" (click)="showContactOnSite()">
|
||||
{{ 'core.openinbrowser' | translate }}
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
|
|
@ -10,37 +10,40 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>{{ 'core.login.passwordforgotteninstructions2' | translate }}</ion-label>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
<ion-card>
|
||||
<form [formGroup]="myForm" (ngSubmit)="resetPassword($event)" #resetPasswordForm>
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h2>{{ 'core.login.searchby' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-radio-group formControlName="field">
|
||||
<ion-item>
|
||||
<ion-label>{{ 'core.login.username' | translate }}</ion-label>
|
||||
<ion-radio slot="end" value="username"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>{{ 'core.user.email' | translate }}</ion-label>
|
||||
<ion-radio slot="end" value="email"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
<ion-item>
|
||||
<ion-label class="sr-only">{{ 'core.login.usernameoremail' | translate }}</ion-label>
|
||||
<ion-input type="text" name="value" placeholder="{{ 'core.login.usernameoremail' | translate }}" formControlName="value"
|
||||
autocapitalize="none" autocorrect="off" [core-auto-focus]="autoFocus">
|
||||
</ion-input>
|
||||
<div class="list-item-limited-width">
|
||||
|
||||
<ion-list>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>{{ 'core.login.passwordforgotteninstructions2' | translate }}</ion-label>
|
||||
</ion-item>
|
||||
<ion-button type="submit" class="ion-margin" expand="block" [disabled]="!myForm.valid">
|
||||
{{ 'core.courses.search' | translate }}
|
||||
</ion-button>
|
||||
</form>
|
||||
</ion-card>
|
||||
</ion-list>
|
||||
<ion-card>
|
||||
<form [formGroup]="myForm" (ngSubmit)="resetPassword($event)" #resetPasswordForm>
|
||||
<ion-item-divider class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h2>{{ 'core.login.searchby' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item-divider>
|
||||
<ion-radio-group formControlName="field">
|
||||
<ion-item>
|
||||
<ion-label>{{ 'core.login.username' | translate }}</ion-label>
|
||||
<ion-radio slot="end" value="username"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item>
|
||||
<ion-label>{{ 'core.user.email' | translate }}</ion-label>
|
||||
<ion-radio slot="end" value="email"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
<ion-item>
|
||||
<ion-label class="sr-only">{{ 'core.login.usernameoremail' | translate }}</ion-label>
|
||||
<ion-input type="text" name="value" placeholder="{{ 'core.login.usernameoremail' | translate }}" formControlName="value"
|
||||
autocapitalize="none" autocorrect="off" [core-auto-focus]="autoFocus">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<ion-button type="submit" class="ion-margin" expand="block" [disabled]="!myForm.valid">
|
||||
{{ 'core.courses.search' | translate }}
|
||||
</ion-button>
|
||||
</form>
|
||||
</ion-card>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
|
|
@ -10,94 +10,96 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding" (keydown)="keyDown($event)" (keyup)="keyUp($event)">
|
||||
<div class="ion-text-wrap ion-text-center ion-margin-bottom" [ngClass]="{'item-avatar-center': showSiteAvatar}">
|
||||
<!-- Show user avatar. -->
|
||||
<img *ngIf="showSiteAvatar" [src]="userAvatar" class="large-avatar" core-external-content [siteId]="siteId"
|
||||
alt="{{ 'core.pictureof' | translate:{$a: userFullName} }}" onError="this.src='assets/img/user-avatar.png'">
|
||||
<div class="list-item-limited-width">
|
||||
<div class="ion-text-wrap ion-text-center ion-margin-bottom" [ngClass]="{'item-avatar-center': showSiteAvatar}">
|
||||
<!-- Show user avatar. -->
|
||||
<img *ngIf="showSiteAvatar" [src]="userAvatar" class="large-avatar" core-external-content [siteId]="siteId"
|
||||
alt="{{ 'core.pictureof' | translate:{$a: userFullName} }}" onError="this.src='assets/img/user-avatar.png'">
|
||||
|
||||
<div class="core-login-site-logo" *ngIf="!showSiteAvatar">
|
||||
<!-- Show site logo or a default image. -->
|
||||
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'" alt="">
|
||||
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation" alt="">
|
||||
<div class="core-login-site-logo" *ngIf="!showSiteAvatar">
|
||||
<!-- Show site logo or a default image. -->
|
||||
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'" alt="">
|
||||
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation" alt="">
|
||||
</div>
|
||||
|
||||
<p *ngIf="siteName" class="ion-padding core-sitename">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</p>
|
||||
<p class="core-siteurl">{{siteUrl}}</p>
|
||||
|
||||
<ion-card *ngIf="!isLoggedOut" class="core-danger-card core-login-reconnect-warning">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-exclamation-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<p>{{ 'core.lostconnection' | translate }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</div>
|
||||
|
||||
<p *ngIf="siteName" class="ion-padding core-sitename">
|
||||
<core-format-text [text]="siteName" [filter]="false"></core-format-text>
|
||||
</p>
|
||||
<p class="core-siteurl">{{siteUrl}}</p>
|
||||
|
||||
<ion-card *ngIf="!isLoggedOut" class="core-danger-card core-login-reconnect-warning">
|
||||
<ion-item>
|
||||
<ion-icon name="fas-exclamation-circle" slot="start" aria-hidden="true"></ion-icon>
|
||||
<form *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
|
||||
<ion-item class="ion-text-wrap core-username item-interactive">
|
||||
<ion-label>
|
||||
<p>{{ 'core.lostconnection' | translate }}</p>
|
||||
<p>{{username}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</div>
|
||||
<form *ngIf="!isOAuth" [formGroup]="credForm" (ngSubmit)="login($event)" class="core-login-form" #reconnectForm>
|
||||
<ion-item class="ion-text-wrap core-username item-interactive">
|
||||
<ion-label>
|
||||
<p>{{username}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item class="ion-margin-bottom">
|
||||
<ion-label class="sr-only">{{ 'core.login.password' | translate }}</ion-label>
|
||||
<core-show-password name="password">
|
||||
<ion-input class="core-ioninput-password" name="password" type="password"
|
||||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
||||
autocomplete="current-password" enterkeyhint="go" required="true">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
<ion-grid class="ion-padding">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<ion-button expand="block" fill="outline" (click)="cancel($event)">
|
||||
{{ 'core.login.cancel' | translate }}
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<ion-button type="submit" expand="block" [disabled]="!credForm.valid">
|
||||
{{ 'core.login.loginbutton' | translate }}
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
<ion-item class="ion-margin-bottom">
|
||||
<ion-label class="sr-only">{{ 'core.login.password' | translate }}</ion-label>
|
||||
<core-show-password name="password">
|
||||
<ion-input class="core-ioninput-password" name="password" type="password"
|
||||
placeholder="{{ 'core.login.password' | translate }}" formControlName="password" [clearOnEdit]="false"
|
||||
autocomplete="current-password" enterkeyhint="go" required="true">
|
||||
</ion-input>
|
||||
</core-show-password>
|
||||
</ion-item>
|
||||
<ion-grid class="ion-padding">
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<ion-button expand="block" fill="outline" (click)="cancel($event)">
|
||||
{{ 'core.login.cancel' | translate }}
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
<ion-col>
|
||||
<ion-button type="submit" expand="block" [disabled]="!credForm.valid">
|
||||
{{ 'core.login.loginbutton' | translate }}
|
||||
</ion-button>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
</ion-grid>
|
||||
|
||||
<ng-container *ngIf="showScanQR">
|
||||
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>
|
||||
<ion-button expand="block" fill="outline" class="ion-margin" (click)="showInstructionsAndScanQR()">
|
||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.scanqr' | translate }}
|
||||
<ng-container *ngIf="showScanQR">
|
||||
<div class="ion-text-center ion-padding">{{ 'core.login.or' | translate }}</div>
|
||||
<ion-button expand="block" fill="outline" class="ion-margin" (click)="showInstructionsAndScanQR()">
|
||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.scanqr' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</form>
|
||||
|
||||
<!-- Forgotten password option. -->
|
||||
<ion-button *ngIf="showForgottenPassword && !isOAuth" expand="block" fill="clear" color="dark"
|
||||
class="core-login-forgotten-password core-button-as-link ion-text-wrap" (click)="forgottenPassword()">
|
||||
{{ 'core.login.forgotten' | translate }}
|
||||
</ion-button>
|
||||
|
||||
<!-- Identity providers. -->
|
||||
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-button fill="outline" *ngFor="let provider of identityProviders" class="ion-text-wrap ion-margin core-oauth-provider"
|
||||
(click)="oauthClicked(provider)" [attr.aria-label]="provider.name" expand="block">
|
||||
<img [src]="provider.iconurl" alt="" width="32" height="32" slot="start">
|
||||
<ion-label>{{provider.name}}</ion-label>
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</form>
|
||||
</ion-list>
|
||||
|
||||
<!-- Forgotten password option. -->
|
||||
<ion-button *ngIf="showForgottenPassword && !isOAuth" expand="block" fill="clear" color="dark"
|
||||
class="core-login-forgotten-password core-button-as-link ion-text-wrap" (click)="forgottenPassword()">
|
||||
{{ 'core.login.forgotten' | translate }}
|
||||
</ion-button>
|
||||
|
||||
<!-- Identity providers. -->
|
||||
<ion-list *ngIf="identityProviders && identityProviders.length" class="ion-padding-top core-login-identity-providers">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h3 class="item-heading">{{ 'core.login.potentialidps' | translate }}</h3>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-button fill="outline" *ngFor="let provider of identityProviders" class="ion-text-wrap core-oauth-provider"
|
||||
(click)="oauthClicked(provider)" [attr.aria-label]="provider.name" expand="block">
|
||||
<img [src]="provider.iconurl" alt="" width="32" height="32" slot="start">
|
||||
<ion-label>{{provider.name}}</ion-label>
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
|
||||
<!-- If OAuth, display cancel button since the form isn't displayed. -->
|
||||
<ion-list *ngIf="isOAuth">
|
||||
<ion-button expand="block" class="ion-margin" fill="outline" (click)="cancel($event)">
|
||||
{{ 'core.login.cancel' | translate }}
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
<!-- If OAuth, display cancel button since the form isn't displayed. -->
|
||||
<ion-list *ngIf="isOAuth">
|
||||
<ion-button expand="block" class="ion-margin" fill="outline" (click)="cancel($event)">
|
||||
{{ 'core.login.cancel' | translate }}
|
||||
</ion-button>
|
||||
</ion-list>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
|
|
@ -16,102 +16,104 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content class="ion-padding">
|
||||
<div class="ion-text-center ion-padding ion-margin-bottom core-login-site-logo" [class.hidden]="hasSites || enteredSiteUrl">
|
||||
<img src="assets/img/login_logo.png" class="avatar-full login-logo" role="presentation" alt="">
|
||||
</div>
|
||||
<form [formGroup]="siteForm" (ngSubmit)="connect($event, siteForm.value.siteUrl)" *ngIf="!fixedSites" #siteFormEl>
|
||||
<!-- Form to input the site URL if there are no fixed sites. -->
|
||||
<ng-container *ngIf="siteSelector == 'url'">
|
||||
<ion-item>
|
||||
<ion-label position="stacked">
|
||||
<h2>{{ 'core.login.siteaddress' | translate }}</h2>
|
||||
</ion-label>
|
||||
<ion-input name="url" type="url" placeholder="{{ 'core.login.siteaddressplaceholder' | translate }}"
|
||||
formControlName="siteUrl" [core-auto-focus]="showKeyboard && !showScanQR">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="siteSelector != 'url'">
|
||||
<ion-item>
|
||||
<ion-label position="stacked">
|
||||
<h2>{{ 'core.login.siteaddress' | translate }}</h2>
|
||||
</ion-label>
|
||||
<ion-input name="url" placeholder="{{ 'core.login.siteaddressplaceholder' | translate }}" formControlName="siteUrl"
|
||||
[core-auto-focus]="showKeyboard && !showScanQR" (ionChange)="searchSite($event, siteForm.value.siteUrl)">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
<div class="list-item-limited-width">
|
||||
<div class="ion-text-center ion-padding ion-margin-bottom core-login-site-logo" [class.hidden]="hasSites || enteredSiteUrl">
|
||||
<img src="assets/img/login_logo.png" class="avatar-full login-logo" role="presentation" alt="">
|
||||
</div>
|
||||
<form [formGroup]="siteForm" (ngSubmit)="connect($event, siteForm.value.siteUrl)" *ngIf="!fixedSites" #siteFormEl>
|
||||
<!-- Form to input the site URL if there are no fixed sites. -->
|
||||
<ng-container *ngIf=" siteSelector=='url'">
|
||||
<ion-item>
|
||||
<ion-label position=" stacked">
|
||||
<h2>{{ 'core.login.siteaddress' | translate }}</h2>
|
||||
</ion-label>
|
||||
<ion-input name="url" type="url" placeholder="{{ 'core.login.siteaddressplaceholder' | translate }}"
|
||||
formControlName="siteUrl" [core-auto-focus]="showKeyboard && !showScanQR">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
<ng-container *ngIf="siteSelector != 'url'">
|
||||
<ion-item>
|
||||
<ion-label position="stacked">
|
||||
<h2>{{ 'core.login.siteaddress' | translate }}</h2>
|
||||
</ion-label>
|
||||
<ion-input name="url" placeholder="{{ 'core.login.siteaddressplaceholder' | translate }}" formControlName="siteUrl"
|
||||
[core-auto-focus]="showKeyboard && !showScanQR" (ionChange)="searchSite($event, siteForm.value.siteUrl)">
|
||||
</ion-input>
|
||||
</ion-item>
|
||||
|
||||
<ion-list [class.hidden]="!hasSites && !enteredSiteUrl" class="core-login-site-list">
|
||||
<ion-item class="core-login-site-list-title">
|
||||
<ion-list [class.hidden]="!hasSites && !enteredSiteUrl" class="core-login-site-list">
|
||||
<ion-item class="core-login-site-list-title">
|
||||
<ion-label>
|
||||
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button *ngIf="enteredSiteUrl" (click)="connect($event, enteredSiteUrl.url)"
|
||||
[attr.aria-label]="'core.login.connect' | translate" detail="true" class="core-login-entered-site">
|
||||
<ion-thumbnail slot="start" aria-hidden="true">
|
||||
<ion-icon name="fas-pen" aria-hidden="true"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<h2 class="ion-text-wrap">{{ 'core.login.yourenteredsite' | translate }}</h2>
|
||||
<p>{{enteredSiteUrl.noProtocolUrl}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<div class="core-login-site-list-found" [class.hidden]="!hasSites" [class.dimmed]="loadingSites">
|
||||
<div *ngIf="loadingSites" class="core-login-site-list-loading">
|
||||
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||
</div>
|
||||
<ng-container *ngFor="let site of sites">
|
||||
<ng-container *ngTemplateOutlet="sitelisting; context: {site: site}"></ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ion-list>
|
||||
|
||||
<div *ngIf="!hasSites && loadingSites" class="core-login-site-nolist-loading">
|
||||
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ion-item *ngIf="siteSelector == 'url'">
|
||||
<ion-label>
|
||||
<ion-button expand="block" [disabled]="!siteForm.valid" class="ion-text-wrap" type="submit">
|
||||
{{ 'core.login.connect' | translate }}
|
||||
</ion-button>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</form>
|
||||
|
||||
<ng-container *ngIf="fixedSites">
|
||||
<!-- Pick the site from a list of fixed sites. -->
|
||||
<ion-list *ngIf="siteSelector == 'list'">
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button *ngIf="enteredSiteUrl" (click)="connect($event, enteredSiteUrl.url)"
|
||||
[attr.aria-label]="'core.login.connect' | translate" detail="true" class="core-login-entered-site">
|
||||
<ion-thumbnail slot="start" aria-hidden="true">
|
||||
<ion-icon name="fas-pen" aria-hidden="true"></ion-icon>
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<h2 class="ion-text-wrap">{{ 'core.login.yourenteredsite' | translate }}</h2>
|
||||
<p>{{enteredSiteUrl.noProtocolUrl}}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<div class="core-login-site-list-found" [class.hidden]="!hasSites" [class.dimmed]="loadingSites">
|
||||
<div *ngIf="loadingSites" class="core-login-site-list-loading">
|
||||
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||
</div>
|
||||
<ng-container *ngFor="let site of sites">
|
||||
<ng-container *ngTemplateOutlet="sitelisting; context: {site: site}"></ng-container>
|
||||
</ng-container>
|
||||
</div>
|
||||
<ion-searchbar *ngIf="fixedSites.length > 4" [(ngModel)]="filter" (ionInput)="filterChanged($event)"
|
||||
(ionCancel)="filterChanged()" [placeholder]="'core.login.findyoursite' | translate">
|
||||
</ion-searchbar>
|
||||
<ng-container *ngFor="let site of filteredSites">
|
||||
<ng-container *ngTemplateOutlet="sitelisting; context: {site: site}"></ng-container>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
|
||||
<div *ngIf="!hasSites && loadingSites" class="core-login-site-nolist-loading">
|
||||
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<ion-item *ngIf="siteSelector == 'url'">
|
||||
<ion-label>
|
||||
<ion-button expand="block" [disabled]="!siteForm.valid" class="ion-text-wrap" type="submit">
|
||||
{{ 'core.login.connect' | translate }}
|
||||
</ion-button>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</form>
|
||||
<ng-container *ngIf="showScanQR && !hasSites && !enteredSiteUrl">
|
||||
<div class="ion-text-center ion-padding ion-margin-top">{{ 'core.login.or' | translate }}</div>
|
||||
<ion-button expand="block" fill="outline" class="ion-margin" (click)="showInstructionsAndScanQR()" aria-haspopup="dialog">
|
||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.scanqr' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="fixedSites">
|
||||
<!-- Pick the site from a list of fixed sites. -->
|
||||
<ion-list *ngIf="siteSelector == 'list'">
|
||||
<ion-item>
|
||||
<ion-label>
|
||||
<h2 class="item-heading">{{ 'core.login.selectsite' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-searchbar *ngIf="fixedSites.length > 4" [(ngModel)]="filter" (ionInput)="filterChanged($event)"
|
||||
(ionCancel)="filterChanged()" [placeholder]="'core.login.findyoursite' | translate">
|
||||
</ion-searchbar>
|
||||
<ng-container *ngFor="let site of filteredSites">
|
||||
<ng-container *ngTemplateOutlet="sitelisting; context: {site: site}"></ng-container>
|
||||
</ng-container>
|
||||
</ion-list>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="showScanQR && !hasSites && !enteredSiteUrl">
|
||||
<div class="ion-text-center ion-padding ion-margin-top">{{ 'core.login.or' | translate }}</div>
|
||||
<ion-button expand="block" fill="outline" class="ion-margin" (click)="showInstructionsAndScanQR()" aria-haspopup="dialog">
|
||||
<ion-icon slot="start" name="fas-qrcode" aria-hidden="true"></ion-icon>
|
||||
{{ 'core.scanqr' | translate }}
|
||||
<!-- Help. -->
|
||||
<ion-button class="ion-margin-top core-login-need-help core-button-as-link ion-text-wrap" (click)="showHelp()"
|
||||
aria-haspopup="dialog" expand="block" fill="clear" color="dark">
|
||||
{{ 'core.needhelp' | translate }}
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
|
||||
<!-- Help. -->
|
||||
<ion-button class="ion-margin-top core-login-need-help core-button-as-link ion-text-wrap" (click)="showHelp()" aria-haspopup="dialog"
|
||||
expand="block" fill="clear" color="dark">
|
||||
{{ 'core.needhelp' | translate }}
|
||||
</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
|
||||
<!-- Template site selector. -->
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
@import "~theme/globals";
|
||||
|
||||
:host {
|
||||
--list-item-max-width: 600px;
|
||||
}
|
||||
|
||||
.item-input:last-child {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
@ -101,12 +105,6 @@
|
|||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
ion-content > * {
|
||||
max-width: 600px;
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
ion-content .core-login-site-logo {
|
||||
margin-top: 20%;
|
||||
&.hidden {
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-list class="core-sitelist">
|
||||
<ion-card *ngFor="let sites of accountsList.otherSites">
|
||||
<ion-item-divider sticky="true" *ngIf="sites[0]" class="core-sitelist-sitename">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-list class="list-item-limited-width">
|
||||
<ion-item button class="ion-text-wrap" (click)="openPage('licenses')" detail="true">
|
||||
<ion-icon name="far-copyright" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>{{ 'core.settings.opensourcelicenses' | translate }}</ion-label>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-list class="list-item-limited-width">
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label>
|
||||
<h2>{{ 'core.settings.textdirection' | translate }}</h2>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-list class="list-item-limited-width">
|
||||
<ion-item *ngIf="showDevOptions" detail="true" (click)="gotoDevOptions()">
|
||||
<ion-icon name="fas-terminal" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label class="ion-text-wrap">
|
||||
|
|
|
@ -10,8 +10,8 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-list class="list-item-limited-width">
|
||||
<ion-item class="ion-text-wrap" lines="none">
|
||||
<ion-label>
|
||||
<h2>{{ 'core.settings.language' | translate }}</h2>
|
||||
</ion-label>
|
||||
|
@ -20,7 +20,7 @@
|
|||
<ion-select-option *ngFor="let entry of languages" [value]="entry.code">{{ entry.name }}</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap core-settings-general-font-size item-interactive">
|
||||
<ion-item class="ion-text-wrap core-settings-general-font-size item-interactive" lines="none">
|
||||
<ion-label>
|
||||
<h2>{{ 'core.settings.fontsize' | translate }}</h2>
|
||||
</ion-label>
|
||||
|
@ -35,8 +35,7 @@
|
|||
</ion-segment-button>
|
||||
</ion-segment>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap core-settings-general-color-scheme" *ngIf="colorSchemes.length > 0"
|
||||
[lines]="selectedScheme=='system' && isAndroid ? 'none' : ''">
|
||||
<ion-item class="ion-text-wrap core-settings-general-color-scheme" *ngIf="colorSchemes.length > 0" lines="none">
|
||||
<ion-label>
|
||||
<h2>{{ 'core.settings.colorscheme' | translate }}</h2>
|
||||
<p *ngIf="colorSchemeDisabled" class="text-danger">{{ 'core.settings.forcedsetting' | translate }}</p>
|
||||
|
@ -47,7 +46,7 @@
|
|||
{{ 'core.settings.colorscheme-' + scheme | translate }}</ion-select-option>
|
||||
</ion-select>
|
||||
</ion-item>
|
||||
<ion-item text-wrap *ngIf="colorSchemes.length > 0 && selectedScheme=='system' && isAndroid">
|
||||
<ion-item text-wrap *ngIf="colorSchemes.length > 0 && selectedScheme=='system' && isAndroid" lines="none">
|
||||
<ion-label>
|
||||
<p>{{ 'core.settings.colorscheme-system-notice' | translate }}</p>
|
||||
</ion-label>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-searchbar [(ngModel)]="textFilter" (ionInput)="filterChanged($event.target)" (ionCancel)="filterChanged($event.target)"
|
||||
[placeholder]="'core.filter' | translate">
|
||||
</ion-searchbar>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
<ion-refresher [disabled]="!loaded" (ionRefresh)="refreshData($event.target)" slot="fixed">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ion-list>
|
||||
<ion-item *ngFor="let site of sites" [class.item-current]="site.id == currentSiteId">
|
||||
<ion-label class="ion-text-wrap">
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<core-loading [hideUntil]="sitesLoaded">
|
||||
<core-loading [hideUntil]="sitesLoaded" class="list-item-limited-width">
|
||||
<ion-list>
|
||||
<ion-item-divider>
|
||||
<ion-label>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
<ion-item class="ion-text-wrap" *ngFor="let item of items" [href]="item.url" core-link [capture]="true">
|
||||
<ion-avatar slot="start" *ngIf="item.avatarUrl">
|
||||
<img [src]="item.avatarUrl" core-external-content alt="" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<core-mod-icon *ngIf="item.iconUrl" [modicon]="item.iconUrl" slot="start" [showAlt]="false">
|
||||
</core-mod-icon>
|
||||
<ion-label>
|
||||
<h2>{{ item.heading }}</h2>
|
||||
<p *ngFor="let text of item.details">{{ text }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-card *ngFor="let item of items">
|
||||
<ion-item class="ion-text-wrap" [href]="item.url" core-link [capture]="true">
|
||||
<ion-avatar slot="start" *ngIf="item.avatarUrl">
|
||||
<img [src]="item.avatarUrl" core-external-content alt="" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<core-mod-icon *ngIf="item.iconUrl" [modicon]="item.iconUrl" slot="start" [showAlt]="false">
|
||||
</core-mod-icon>
|
||||
<ion-label>
|
||||
<h2>{{ item.heading }}</h2>
|
||||
<p *ngFor="let text of item.details">{{ text }}</p>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="refreshData($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="loaded">
|
||||
<core-loading [hideUntil]="loaded" class="list-item-limited-width">
|
||||
<ng-container *ngIf="loaded">
|
||||
<core-dynamic-component [component]="areaComponent" [data]="{items: items}"></core-dynamic-component>
|
||||
</ng-container>
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
<ion-item class="ion-text-wrap" *ngFor="let item of items" core-user-link [userId]="item.user.id">
|
||||
<core-user-avatar [user]="item.user" slot="start"></core-user-avatar>
|
||||
<ion-label>
|
||||
<h2>{{ item.heading }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-card *ngFor="let item of items">
|
||||
<ion-item class="ion-text-wrap" core-user-link [userId]="item.user.id">
|
||||
<core-user-avatar [user]="item.user" slot="start"></core-user-avatar>
|
||||
<ion-label>
|
||||
<h2>{{ item.heading }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
</ion-card>
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!userLoaded" (ionRefresh)="refreshUser($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="userLoaded">
|
||||
<core-loading [hideUntil]="userLoaded" class="list-item-limited-width">
|
||||
<ion-list *ngIf="user">
|
||||
<ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap" lines="full">
|
||||
<core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="!canChangeProfilePicture">
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
<ion-refresher slot="fixed" [disabled]="!userLoaded" (ionRefresh)="refreshUser($event.target)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="userLoaded">
|
||||
<core-loading [hideUntil]="userLoaded" class="list-item-limited-width">
|
||||
<ion-list *ngIf="user && !isDeleted && isEnrolled">
|
||||
<ion-item class="ion-text-center core-user-profile-maininfo ion-text-wrap">
|
||||
<core-user-avatar [user]="user" [userId]="user.id" [linkProfile]="false" [checkOnline]="true">
|
||||
|
|
|
@ -830,7 +830,7 @@ ion-card {
|
|||
ion-list.core-course-module-list-wrapper,
|
||||
.list-item-limited-width,
|
||||
.core-course-module-list-wrapper {
|
||||
max-width: var(--list-item--max-width);
|
||||
max-width: var(--list-item-max-width);
|
||||
margin-left: auto !important;
|
||||
margin-right: auto !important;
|
||||
}
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
--module-icon-size: 24px;
|
||||
--module-icon-radius: var(--medium-radius);
|
||||
|
||||
--list-item--max-width: 768px;
|
||||
--list-item-max-width: 768px;
|
||||
|
||||
--contrast-background: white;
|
||||
|
||||
|
|
Loading…
Reference in New Issue