commit
4e210350e5
|
@ -22,7 +22,7 @@ const THRESHOLD = .15; // % of the scroll element height that must be close to t
|
||||||
* Component to show a infinite loading trigger and spinner while more data is being loaded.
|
* Component to show a infinite loading trigger and spinner while more data is being loaded.
|
||||||
*
|
*
|
||||||
* Usage:
|
* Usage:
|
||||||
* <core-infinite-loading [action]="loadingAction" [enabled]="dataLoaded"></core-inifinite-loading>
|
* <core-infinite-loading [action]="loadingAction" [enabled]="dataLoaded"></core-infinite-loading>
|
||||||
*/
|
*/
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'core-infinite-loading',
|
selector: 'core-infinite-loading',
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
<div *ngIf="selectedSection && selectedSection.id == allSectionsId">
|
<div *ngIf="selectedSection && selectedSection.id == allSectionsId">
|
||||||
<core-dynamic-component [component]="allSectionsComponent" [data]="data">
|
<core-dynamic-component [component]="allSectionsComponent" [data]="data">
|
||||||
<ng-container *ngFor="let section of sections; index as i">
|
<ng-container *ngFor="let section of sections; index as i">
|
||||||
<ng-container *ngIf="i <= showSectionId">
|
<ng-container *ngIf="i <= lastShownSectionIndex">
|
||||||
<ng-container *ngTemplateOutlet="sectionTemplate; context: {section: section}"></ng-container>
|
<ng-container *ngTemplateOutlet="sectionTemplate; context: {section: section}"></ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
|
@ -70,7 +70,7 @@ import { CoreBlockSideBlocksComponent } from '@features/block/components/side-bl
|
||||||
})
|
})
|
||||||
export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
|
|
||||||
static readonly LOAD_MORE_ACTIVITIES = 20; // How many activities should load each time showMoreActivities is called.
|
static readonly LOAD_MORE_ACTIVITIES = 10; // How many activities should load each time showMoreActivities is called.
|
||||||
|
|
||||||
@Input() course!: CoreCourseAnyCourseData; // The course to render.
|
@Input() course!: CoreCourseAnyCourseData; // The course to render.
|
||||||
@Input() sections: CoreCourseSectionToDisplay[] = []; // List of course sections.
|
@Input() sections: CoreCourseSectionToDisplay[] = []; // List of course sections.
|
||||||
|
@ -89,7 +89,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
allSectionsComponent?: Type<unknown>;
|
allSectionsComponent?: Type<unknown>;
|
||||||
|
|
||||||
canLoadMore = false;
|
canLoadMore = false;
|
||||||
showSectionId = 0;
|
lastShownSectionIndex = 0;
|
||||||
data: Record<string, unknown> = {}; // Data to pass to the components.
|
data: Record<string, unknown> = {}; // Data to pass to the components.
|
||||||
courseIndexTour: CoreUserTourDirectiveOptions = {
|
courseIndexTour: CoreUserTourDirectiveOptions = {
|
||||||
id: 'course-index',
|
id: 'course-index',
|
||||||
|
@ -514,8 +514,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
} else {
|
} else {
|
||||||
this.previousSection = undefined;
|
this.previousSection = undefined;
|
||||||
this.nextSection = undefined;
|
this.nextSection = undefined;
|
||||||
this.canLoadMore = false;
|
this.lastShownSectionIndex = -1;
|
||||||
this.showSectionId = 0;
|
|
||||||
this.showMoreActivities();
|
this.showMoreActivities();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,40 +593,22 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
||||||
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
||||||
*/
|
*/
|
||||||
showMoreActivities(infiniteComplete?: () => void): void {
|
showMoreActivities(infiniteComplete?: () => void): void {
|
||||||
this.canLoadMore = false;
|
|
||||||
|
|
||||||
const sections = this.sections || [];
|
|
||||||
let modulesLoaded = 0;
|
let modulesLoaded = 0;
|
||||||
let i: number;
|
while (this.lastShownSectionIndex < this.sections.length - 1 &&
|
||||||
for (i = this.showSectionId + 1; i < sections.length; i++) {
|
modulesLoaded < CoreCourseFormatComponent.LOAD_MORE_ACTIVITIES) {
|
||||||
if (!sections[i].hasContent || !sections[i].modules) {
|
this.lastShownSectionIndex++;
|
||||||
|
|
||||||
|
if (!this.sections[this.lastShownSectionIndex].hasContent || !this.sections[this.lastShownSectionIndex].modules) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
modulesLoaded += sections[i].modules.reduce((total, module) =>
|
modulesLoaded += this.sections[this.lastShownSectionIndex].modules.reduce((total, module) =>
|
||||||
!CoreCourseHelper.isModuleStealth(module, sections[i]) ? total + 1 : total, 0);
|
!CoreCourseHelper.isModuleStealth(module, this.sections[this.lastShownSectionIndex]) ? total + 1 : total, 0);
|
||||||
|
|
||||||
if (modulesLoaded >= CoreCourseFormatComponent.LOAD_MORE_ACTIVITIES) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this.showSectionId = i;
|
this.canLoadMore = this.lastShownSectionIndex < this.sections.length - 1;
|
||||||
this.canLoadMore = i < sections.length;
|
|
||||||
|
|
||||||
if (this.canLoadMore) {
|
infiniteComplete?.();
|
||||||
// Check if any of the following sections have any content.
|
|
||||||
let thereAreMore = false;
|
|
||||||
for (i++; i < sections.length; i++) {
|
|
||||||
if (sections[i].hasContent && sections[i].modules && sections[i].modules?.length > 0) {
|
|
||||||
thereAreMore = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.canLoadMore = thereAreMore;
|
|
||||||
}
|
|
||||||
|
|
||||||
infiniteComplete && infiniteComplete();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
{{ 'core.course.hiddenfromstudents' | translate }}
|
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
<ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap">
|
<ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap">
|
||||||
<ion-icon name="fas-low-vision" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-eye-low-vision" aria-hidden="true"></ion-icon>
|
||||||
{{ 'core.course.hiddenoncoursepage' | translate }}
|
{{ 'core.course.hiddenoncoursepage' | translate }}
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
</div>
|
</div>
|
||||||
|
@ -80,14 +80,14 @@
|
||||||
|
|
||||||
|
|
||||||
<!-- Description and restrictions -->
|
<!-- Description and restrictions -->
|
||||||
<div *ngIf="module.description || module.availabilityinfo" id="activity-{{module.id}}-collapsible"
|
<div *ngIf="module.description || (showAvailability && module.availabilityinfo)" id="activity-{{module.id}}-collapsible"
|
||||||
class="ion-text-wrap activity-description-availabilityinfo activity-extra" [collapsible-item]="64">
|
class="ion-text-wrap activity-description-availabilityinfo activity-extra" [collapsible-item]="64">
|
||||||
<core-format-text class="core-module-description" *ngIf="module.description" [text]="module.description"
|
<core-format-text class="core-module-description" *ngIf="module.description" [text]="module.description"
|
||||||
contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
|
contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
|
|
||||||
<!-- Availability info -->
|
<!-- Availability info -->
|
||||||
<div *ngIf="module.availabilityinfo" class="core-module-availabilityinfo">
|
<div *ngIf="showAvailability && module.availabilityinfo" class="core-module-availabilityinfo">
|
||||||
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
||||||
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id"
|
||||||
[courseId]="module.course">
|
[courseId]="module.course">
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="module.handlerData.extraBadge" class="ion-text-wrap activity-extrabadges activity-extra"
|
<div *ngIf="showExtra && module.handlerData.extraBadge" class="ion-text-wrap activity-extrabadges activity-extra"
|
||||||
[innerHTML]="module.handlerData.extraBadge"></div>
|
[innerHTML]="module.handlerData.extraBadge"></div>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,11 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
@Input() showActivityDates = false; // Whether to show activity dates.
|
@Input() showActivityDates = false; // Whether to show activity dates.
|
||||||
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
@Input() showCompletionConditions = false; // Whether to show activity completion conditions.
|
||||||
@Input() showLegacyCompletion?: boolean; // Whether to show module completion in the old format.
|
@Input() showLegacyCompletion?: boolean; // Whether to show module completion in the old format.
|
||||||
|
@Input() showCompletion = true; // Whether to show module completion.
|
||||||
|
@Input() showAvailability = true; // Whether to show module availability.
|
||||||
|
@Input() showExtra = true; // Whether to show extra badges.
|
||||||
|
@Input() showDownloadStatus = true; // Whether to show download status.
|
||||||
|
@Input() showIndentation = true; // Whether to show indentation
|
||||||
@Input() isLastViewed = false; // Whether it's the last module viewed in a course.
|
@Input() isLastViewed = false; // Whether it's the last module viewed in a course.
|
||||||
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
|
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>(); // Notify when module completion changes.
|
||||||
@HostBinding('class.indented') indented = false;
|
@HostBinding('class.indented') indented = false;
|
||||||
|
@ -70,14 +75,24 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
const site = CoreSites.getRequiredCurrentSite();
|
const site = CoreSites.getRequiredCurrentSite();
|
||||||
const enableIndentation = await CoreCourse.isCourseIndentationEnabled(site, this.module.course);
|
|
||||||
|
|
||||||
this.indented = enableIndentation && this.module.indent > 0;
|
if (this.showIndentation && this.module.indent > 0) {
|
||||||
|
this.indented = await CoreCourse.isCourseIndentationEnabled(site, this.module.course);
|
||||||
|
} else {
|
||||||
|
this.indented = false;
|
||||||
|
}
|
||||||
this.modNameTranslated = CoreCourse.translateModuleName(this.module.modname, this.module.modplural);
|
this.modNameTranslated = CoreCourse.translateModuleName(this.module.modname, this.module.modplural);
|
||||||
this.showLegacyCompletion = this.showLegacyCompletion ??
|
if (this.showCompletion) {
|
||||||
CoreConstants.CONFIG.uselegacycompletion ??
|
this.showLegacyCompletion = this.showLegacyCompletion ??
|
||||||
!site.isVersionGreaterEqualThan('3.11');
|
CoreConstants.CONFIG.uselegacycompletion ??
|
||||||
this.checkShowCompletion();
|
!site.isVersionGreaterEqualThan('3.11');
|
||||||
|
this.checkShowCompletion();
|
||||||
|
} else {
|
||||||
|
this.showLegacyCompletion = false;
|
||||||
|
this.showCompletionConditions = false;
|
||||||
|
this.showManualCompletion = false;
|
||||||
|
this.hasCompletion = false;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.module.handlerData) {
|
if (!this.module.handlerData) {
|
||||||
return;
|
return;
|
||||||
|
@ -86,7 +101,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
||||||
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
|
this.module.handlerData.a11yTitle = this.module.handlerData.a11yTitle ?? this.module.handlerData.title;
|
||||||
this.moduleHasView = CoreCourse.moduleHasView(this.module);
|
this.moduleHasView = CoreCourse.moduleHasView(this.module);
|
||||||
|
|
||||||
if (this.module.handlerData?.showDownloadButton) {
|
if (this.showDownloadStatus && this.module.handlerData.showDownloadButton) {
|
||||||
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.module.course);
|
const status = await CoreCourseModulePrefetchDelegate.getModuleStatus(this.module, this.module.course);
|
||||||
this.updateModuleStatus(status);
|
this.updateModuleStatus(status);
|
||||||
|
|
||||||
|
|
|
@ -298,7 +298,7 @@ export class CoreCourseContentsPage implements OnInit, OnDestroy, CoreRefreshCon
|
||||||
await this.loadData(true, true);
|
await this.loadData(true, true);
|
||||||
} finally {
|
} finally {
|
||||||
// Do not call doRefresh on the format component if the refresher is defined in the format component
|
// Do not call doRefresh on the format component if the refresher is defined in the format component
|
||||||
// to prevent an inifinite loop.
|
// to prevent an infinite loop.
|
||||||
if (this.displayRefresher && this.formatComponent) {
|
if (this.displayRefresher && this.formatComponent) {
|
||||||
await CoreUtils.ignoreErrors(this.formatComponent.doRefresh(refresher));
|
await CoreUtils.ignoreErrors(this.formatComponent.doRefresh(refresher));
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,24 @@
|
||||||
</core-empty-box>
|
</core-empty-box>
|
||||||
|
|
||||||
<ion-list class="core-course-module-list-wrapper">
|
<ion-list class="core-course-module-list-wrapper">
|
||||||
<ng-container *ngFor="let section of sections">
|
<ng-container *ngFor="let section of sections; index as i">
|
||||||
<ng-container *ngFor="let module of section.modules">
|
<ng-container *ngIf="i <= lastShownSectionIndex">
|
||||||
<core-course-module *ngIf="module.visibleoncoursepage !== 0" [module]="module" [section]="section">
|
<ion-item-divider class="course-section ion-text-wrap" *ngIf="section.name">
|
||||||
</core-course-module>
|
<ion-label>
|
||||||
|
<h2>
|
||||||
|
<core-format-text [text]="section.name" contextLevel="course" [contextInstanceId]="courseId">
|
||||||
|
</core-format-text>
|
||||||
|
</h2>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item-divider>
|
||||||
|
<ng-container *ngFor="let module of section.modules">
|
||||||
|
<core-course-module [module]="module" [section]="section" [showActivityDates]="false" [showAvailability]="false"
|
||||||
|
[showExtra]="false" [showDownloadStatus]="false" [showCompletion]="false" [showIndentation]="false">
|
||||||
|
</core-course-module>
|
||||||
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
<core-infinite-loading [enabled]="canLoadMore" (action)="showMoreActivities($event)"></core-infinite-loading>
|
||||||
</core-loading>
|
</core-loading>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -34,10 +34,14 @@ import { CoreAnalytics, CoreAnalyticsEventType } from '@services/analytics';
|
||||||
})
|
})
|
||||||
export class CoreCourseListModTypePage implements OnInit {
|
export class CoreCourseListModTypePage implements OnInit {
|
||||||
|
|
||||||
|
private static readonly PAGE_LENGTH = 10; // How many activities should load each time showMoreActivities is called.
|
||||||
|
|
||||||
sections: CoreCourseSection[] = [];
|
sections: CoreCourseSection[] = [];
|
||||||
title = '';
|
title = '';
|
||||||
loaded = false;
|
loaded = false;
|
||||||
courseId?: number;
|
courseId = 0;
|
||||||
|
canLoadMore = false;
|
||||||
|
lastShownSectionIndex = -1;
|
||||||
|
|
||||||
protected modName?: string;
|
protected modName?: string;
|
||||||
protected archetypes: Record<string, number> = {}; // To speed up the check of modules.
|
protected archetypes: Record<string, number> = {}; // To speed up the check of modules.
|
||||||
|
@ -64,9 +68,16 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
* @inheritdoc
|
* @inheritdoc
|
||||||
*/
|
*/
|
||||||
async ngOnInit(): Promise<void> {
|
async ngOnInit(): Promise<void> {
|
||||||
this.title = CoreNavigator.getRouteParam('title') || '';
|
try {
|
||||||
this.courseId = CoreNavigator.getRouteNumberParam('courseId');
|
this.title = CoreNavigator.getRouteParam('title') || '';
|
||||||
this.modName = CoreNavigator.getRouteParam('modName');
|
this.courseId = CoreNavigator.getRequiredRouteParam('courseId');
|
||||||
|
this.modName = CoreNavigator.getRequiredRouteParam('modName');
|
||||||
|
} catch (error) {
|
||||||
|
CoreDomUtils.showErrorModal(error);
|
||||||
|
CoreNavigator.back();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.fetchData();
|
await this.fetchData();
|
||||||
|
@ -77,8 +88,6 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the data.
|
* Fetches the data.
|
||||||
*
|
|
||||||
* @returns Resolved when done.
|
|
||||||
*/
|
*/
|
||||||
protected async fetchData(): Promise<void> {
|
protected async fetchData(): Promise<void> {
|
||||||
if (!this.courseId) {
|
if (!this.courseId) {
|
||||||
|
@ -90,12 +99,14 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
let sections = await CoreCourse.getSections(this.courseId, false, true);
|
let sections = await CoreCourse.getSections(this.courseId, false, true);
|
||||||
|
|
||||||
sections = sections.filter((section) => {
|
sections = sections.filter((section) => {
|
||||||
if (!section.modules) {
|
if (!section.modules.length || section.hiddenbynumsections) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
section.modules = section.modules.filter((mod) => {
|
section.modules = section.modules.filter((mod) => {
|
||||||
if (!CoreCourseHelper.canUserViewModule(mod, section) || !CoreCourse.moduleHasView(mod)) {
|
if (!CoreCourseHelper.canUserViewModule(mod, section) ||
|
||||||
|
!CoreCourse.moduleHasView(mod) ||
|
||||||
|
mod.visibleoncoursepage === 0) {
|
||||||
// Ignore this module.
|
// Ignore this module.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -110,11 +121,11 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.archetypes[mod.modname] == CoreConstants.MOD_ARCHETYPE_RESOURCE) {
|
if (this.archetypes[mod.modname] === CoreConstants.MOD_ARCHETYPE_RESOURCE) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (mod.modname == this.modName) {
|
} else if (mod.modname === this.modName) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -125,19 +136,39 @@ export class CoreCourseListModTypePage implements OnInit {
|
||||||
const result = await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId);
|
const result = await CoreCourseHelper.addHandlerDataForModules(sections, this.courseId);
|
||||||
|
|
||||||
this.sections = result.sections;
|
this.sections = result.sections;
|
||||||
|
|
||||||
|
this.lastShownSectionIndex = -1;
|
||||||
|
this.showMoreActivities();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'Error getting data');
|
CoreDomUtils.showErrorModalDefault(error, 'Error getting data');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show more activities.
|
||||||
|
*
|
||||||
|
* @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading.
|
||||||
|
*/
|
||||||
|
showMoreActivities(infiniteComplete?: () => void): void {
|
||||||
|
let modulesLoaded = 0;
|
||||||
|
while (this.lastShownSectionIndex < this.sections.length - 1 && modulesLoaded < CoreCourseListModTypePage.PAGE_LENGTH) {
|
||||||
|
this.lastShownSectionIndex++;
|
||||||
|
|
||||||
|
modulesLoaded += this.sections[this.lastShownSectionIndex].modules.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.canLoadMore = this.lastShownSectionIndex < this.sections.length - 1;
|
||||||
|
|
||||||
|
infiniteComplete?.();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Refresh the data.
|
* Refresh the data.
|
||||||
*
|
*
|
||||||
* @param refresher Refresher.
|
* @param refresher Refresher.
|
||||||
* @returns Promise resolved when done.
|
|
||||||
*/
|
*/
|
||||||
async refreshData(refresher: IonRefresher): Promise<void> {
|
async refreshData(refresher: IonRefresher): Promise<void> {
|
||||||
await CoreUtils.ignoreErrors(CoreCourse.invalidateSections(this.courseId || 0));
|
await CoreUtils.ignoreErrors(CoreCourse.invalidateSections(this.courseId));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await this.fetchData();
|
await this.fetchData();
|
||||||
|
|
|
@ -40,7 +40,7 @@
|
||||||
{{ 'core.course.hiddenfromstudents' | translate }}
|
{{ 'core.course.hiddenfromstudents' | translate }}
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
<ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap">
|
<ion-badge color="secondary" *ngIf="module.visible !== 0 && module.isStealth" class="ion-text-wrap">
|
||||||
<ion-icon name="fas-low-vision" aria-hidden="true"></ion-icon>
|
<ion-icon name="fas-eye-low-vision" aria-hidden="true"></ion-icon>
|
||||||
{{ 'core.course.hiddenoncoursepage' | translate }}
|
{{ 'core.course.hiddenoncoursepage' | translate }}
|
||||||
</ion-badge>
|
</ion-badge>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -85,20 +85,20 @@ Feature: Test basic usage of one course in app
|
||||||
And I press "OK" in the app
|
And I press "OK" in the app
|
||||||
And I wait loading to finish in the app
|
And I wait loading to finish in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test external name" in the app
|
And I should find "Test external name" in the app
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
|
|
||||||
Scenario: Guest access
|
Scenario: Guest access
|
||||||
Given I entered the course "Course 1" as "teacher1" in the app
|
Given I entered the course "Course 1" as "teacher1" in the app
|
||||||
|
@ -122,16 +122,16 @@ Feature: Test basic usage of one course in app
|
||||||
|
|
||||||
When I press "View course" "ion-button" in the app
|
When I press "View course" "ion-button" in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
|
|
|
@ -83,25 +83,33 @@ Feature: Test basic usage of one course in app
|
||||||
Scenario: View course contents
|
Scenario: View course contents
|
||||||
When I entered the course "Course 1" as "student1" in the app
|
When I entered the course "Course 1" as "student1" in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test external name" in the app
|
And I should find "Test external name" in the app
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
|
|
||||||
When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue"
|
When I set "page-core-course-index .core-course-thumb" styles to "background" "lightblue"
|
||||||
And I set "page-core-course-index .core-course-thumb img" styles to "display" "none"
|
And I set "page-core-course-index .core-course-thumb img" styles to "display" "none"
|
||||||
Then the UI should match the snapshot
|
Then the UI should match the snapshot
|
||||||
|
|
||||||
|
# Test infinite scroll on course
|
||||||
|
When I scroll to "Test workshop name" in the app
|
||||||
|
Then I should find "Web links" in the app
|
||||||
|
And I should find "Test glossary" in the app
|
||||||
|
|
||||||
|
# Test Collapsible header
|
||||||
|
And the UI should match the snapshot
|
||||||
|
|
||||||
When I press "Choice course 1" in the app
|
When I press "Choice course 1" in the app
|
||||||
Then the header should be "Choice course 1" in the app
|
Then the header should be "Choice course 1" in the app
|
||||||
|
|
||||||
|
@ -161,20 +169,20 @@ Feature: Test basic usage of one course in app
|
||||||
Scenario: View section contents
|
Scenario: View section contents
|
||||||
When I entered the course "Course 1" as "student1" in the app
|
When I entered the course "Course 1" as "student1" in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test external name" in the app
|
And I should find "Test external name" in the app
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
|
|
||||||
When I press "Course index" in the app
|
When I press "Course index" in the app
|
||||||
And I press "General" in the app
|
And I press "General" in the app
|
||||||
|
@ -337,20 +345,20 @@ Feature: Test basic usage of one course in app
|
||||||
Scenario: Navigation between sections using the bottom arrows
|
Scenario: Navigation between sections using the bottom arrows
|
||||||
When I entered the course "Course 1" as "student1" in the app
|
When I entered the course "Course 1" as "student1" in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test external name" in the app
|
And I should find "Test external name" in the app
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
|
|
||||||
When I press "Course index" in the app
|
When I press "Course index" in the app
|
||||||
And I press "General" in the app
|
And I press "General" in the app
|
||||||
|
@ -425,20 +433,20 @@ Feature: Test basic usage of one course in app
|
||||||
And I press "OK" in the app
|
And I press "OK" in the app
|
||||||
And I wait loading to finish in the app
|
And I wait loading to finish in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test external name" in the app
|
And I should find "Test external name" in the app
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
|
|
||||||
Scenario: View blocks on drawer
|
Scenario: View blocks on drawer
|
||||||
Given the following "blocks" exist:
|
Given the following "blocks" exist:
|
||||||
|
@ -447,20 +455,20 @@ Feature: Test basic usage of one course in app
|
||||||
| activity_modules | Course | C1 | course-view-* | site-pre | |
|
| activity_modules | Course | C1 | course-view-* | site-pre | |
|
||||||
And I entered the course "Course 1" as "student1" in the app
|
And I entered the course "Course 1" as "student1" in the app
|
||||||
Then the header should be "Course 1" in the app
|
Then the header should be "Course 1" in the app
|
||||||
|
And I should find "Test forum name" in the app
|
||||||
|
And I should find "Test wiki name" in the app
|
||||||
And I should find "Choice course 1" in the app
|
And I should find "Choice course 1" in the app
|
||||||
And I should find "assignment" in the app
|
And I should find "assignment" in the app
|
||||||
And I should find "Test forum name" in the app
|
|
||||||
And I should find "Test chat name" in the app
|
|
||||||
And I should find "Web links" in the app
|
|
||||||
And I should find "Test external name" in the app
|
And I should find "Test external name" in the app
|
||||||
And I should find "Test feedback name" in the app
|
|
||||||
And I should find "Test glossary" in the app
|
|
||||||
And I should find "Quiz 1" in the app
|
|
||||||
And I should find "Test survey name" in the app
|
And I should find "Test survey name" in the app
|
||||||
And I should find "Test wiki name" in the app
|
And I should find "Test chat name" in the app
|
||||||
And I should find "Test lesson name" in the app
|
And I should find "Quiz 1" in the app
|
||||||
And I should find "Test scorm name" in the app
|
And I should find "Test scorm name" in the app
|
||||||
|
And I should find "Test feedback name" in the app
|
||||||
|
And I should find "Test lesson name" in the app
|
||||||
And I should find "Test workshop name" in the app
|
And I should find "Test workshop name" in the app
|
||||||
|
And I should not find "Web links" in the app
|
||||||
|
And I should not find "Test glossary" in the app
|
||||||
Then I press "Open block drawer" in the app
|
Then I press "Open block drawer" in the app
|
||||||
And I should find "HTML title test" in the app
|
And I should find "HTML title test" in the app
|
||||||
And I should find "body test" in the app
|
And I should find "body test" in the app
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 34 KiB |
Binary file not shown.
After Width: | Height: | Size: 38 KiB |
|
@ -1898,10 +1898,12 @@ ion-popover {
|
||||||
&.md {
|
&.md {
|
||||||
margin-top: 2px;
|
margin-top: 2px;
|
||||||
margin-bottom: 2px;
|
margin-bottom: 2px;
|
||||||
}
|
|
||||||
// Never show backdrop on popovers
|
// Never show backdrop on popovers on Android
|
||||||
ion-backdrop {
|
// @todo Apply box shadow on ios and make it transparent too. The main problem is the box arrow.
|
||||||
background: transparent;
|
ion-backdrop {
|
||||||
|
background: transparent;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue