|
@ -11,10 +11,10 @@
|
|||
<!-- Activity info. -->
|
||||
<core-course-module-info [module]="module" [description]="description" [component]="component" [componentId]="componentId"
|
||||
[courseId]="courseId" [hasDataToSync]="hasOffline" (completionChanged)="onCompletionChange()">
|
||||
<ion-list inset="true" description *ngIf="assign && assign.introattachments?.length && !assign.submissionattachments">
|
||||
<div description *ngIf="assign && assign.introattachments?.length && !assign.submissionattachments">
|
||||
<core-file *ngFor="let file of assign.introattachments" [file]="file" [component]="component" [componentId]="componentId">
|
||||
</core-file>
|
||||
</ion-list>
|
||||
</div>
|
||||
</core-course-module-info>
|
||||
|
||||
<!-- User can view all submissions (teacher). -->
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
<ion-list *ngIf="contents && (contents.files.length + contents.folders.length > 0)">
|
||||
<ng-container *ngFor="let folder of contents.folders">
|
||||
<ion-item class="item-file" (click)="openFolder(folder)" detail="true" button>
|
||||
<ion-item class="ion-text-wrap item-file item-directory" (click)="openFolder(folder)" detail="true" button>
|
||||
<ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.folder' | translate"></ion-icon>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{folder.filename}}</p>
|
||||
|
|
|
@ -54,6 +54,7 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
|||
if (this.subfolder) {
|
||||
this.description = this.folderInstance ? this.folderInstance.intro : this.module.description;
|
||||
this.contents = this.subfolder;
|
||||
this.sortFilesAndFolders();
|
||||
|
||||
this.showLoading = false;
|
||||
|
||||
|
@ -88,6 +89,30 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
|||
|
||||
this.description = this.folderInstance ? this.folderInstance.intro : this.module.description;
|
||||
this.contents = AddonModFolderHelper.formatContents(contents);
|
||||
this.sortFilesAndFolders();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sort files and folders alphabetically.
|
||||
*/
|
||||
protected sortFilesAndFolders(): void {
|
||||
if (!this.contents) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.contents.folders.sort((a, b) => {
|
||||
const compareA = a.filename.toLowerCase();
|
||||
const compareB = b.filename.toLowerCase();
|
||||
|
||||
return compareA.localeCompare(compareB);
|
||||
});
|
||||
|
||||
this.contents.files.sort((a, b) => {
|
||||
const compareA = a.filename.toLowerCase();
|
||||
const compareB = b.filename.toLowerCase();
|
||||
|
||||
return compareA.localeCompare(compareB);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -40,6 +40,8 @@ ion-item {
|
|||
div.core-notification-icon,
|
||||
core-mod-icon.core-notification-icon {
|
||||
padding: 8px;
|
||||
max-width: var(--core-avatar-size);
|
||||
max-height: var(--core-avatar-size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -37,10 +37,8 @@
|
|||
<!-- List of files. -->
|
||||
<ion-list *ngIf="files && files.length > 0">
|
||||
<ng-container *ngFor="let file of files">
|
||||
<ion-item button *ngIf="file.isdir" class="item-file" (click)="openFolder(file)" detail="true">
|
||||
<ion-thumbnail slot="start">
|
||||
<img [src]="file.imgPath" alt="" role="presentation">
|
||||
</ion-thumbnail>
|
||||
<ion-item button *ngIf="file.isdir" class="ion-text-wrap item-file item-directory" (click)="openFolder(file)" detail="true">
|
||||
<ion-icon name="fas-folder" slot="start" [attr.aria-label]="'core.folder' | translate"></ion-icon>
|
||||
<ion-label>{{file.filename}}</ion-label>
|
||||
</ion-item>
|
||||
<core-file *ngIf="!file.isdir" [file]="file" [component]="component" [componentId]="file.contextid"></core-file>
|
||||
|
|
Before Width: | Height: | Size: 3.8 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.0 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.3 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.8 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.7 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.2 KiB |
After Width: | Height: | Size: 539 B |
After Width: | Height: | Size: 543 B |
Before Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 888 B |
Before Width: | Height: | Size: 5.7 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 3.2 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.5 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.4 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 4.5 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.9 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 4.9 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.2 KiB |
After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.2 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 3.6 KiB |
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 4.6 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 888 B |
Before Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 5.3 KiB |
After Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 4.1 KiB |
After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.8 KiB |
After Width: | Height: | Size: 1.1 KiB |
|
@ -1,11 +1,15 @@
|
|||
<ion-card class="card-file">
|
||||
<ion-item *ngIf="file" button class="ion-text-wrap item-file" (click)="download($event, true)" detail="false">
|
||||
<ion-thumbnail slot="start">
|
||||
<img [src]="fileIcon" alt="" role="presentation" />
|
||||
</ion-thumbnail>
|
||||
<ion-label>
|
||||
<p class="item-heading">{{fileName}}</p>
|
||||
<p *ngIf="fileSizeReadable">{{ fileSizeReadable }}</p>
|
||||
<p *ngIf="showTime">{{ timemodified * 1000 | coreFormatDate }}</p>
|
||||
<p *ngIf="fileSizeReadable || showTime">
|
||||
<ng-container *ngIf="fileSizeReadable">{{ fileSizeReadable }}</ng-container>
|
||||
<ng-container *ngIf="fileSizeReadable && showTime"> · </ng-container>
|
||||
<ng-container *ngIf="showTime">{{ timemodified * 1000 | coreFormatDate }}</ng-container>
|
||||
</p>
|
||||
</ion-label>
|
||||
<div slot="end" class="flex-row">
|
||||
<core-download-refresh [status]="state" [enabled]="canDownload" [loading]="isDownloading" [canTrustDownload]="!alwaysDownload"
|
||||
|
@ -16,9 +20,10 @@
|
|||
<ion-icon slot="icon-only" [name]="openButtonIcon" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<ion-button fill="clear" *ngIf="!isDownloading && canDelete" (click)="delete($event)" [attr.aria-label]="'core.delete' | translate"
|
||||
color="danger">
|
||||
<ion-button fill="clear" *ngIf="!isDownloading && canDelete" (click)="delete($event)"
|
||||
[attr.aria-label]="'core.delete' | translate" color="danger">
|
||||
<ion-icon slot="icon-only" name="fas-trash" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
|
|
|
@ -1,15 +1,19 @@
|
|||
<form (ngSubmit)="changeName(newFileName, $event)" #nameForm>
|
||||
<ion-card class="card-file">
|
||||
<ion-item class="ion-text-wrap item-file" (click)="openFile($event)" button detail="false">
|
||||
<ion-thumbnail slot="start">
|
||||
<img [src]="fileIcon" [alt]="fileExtension" role="presentation" />
|
||||
</ion-thumbnail>
|
||||
|
||||
<ion-label>
|
||||
<ion-label *ngIf="!editMode">
|
||||
<!-- File name and edit button (if editable). -->
|
||||
<p class="item-heading" *ngIf="!editMode">{{fileName}}</p>
|
||||
<p class="item-heading">{{fileName}}</p>
|
||||
<!-- More data about the file. -->
|
||||
<p *ngIf="size && !editMode">{{ size }}</p>
|
||||
<p *ngIf="timemodified && !editMode">{{ timemodified }}</p>
|
||||
<p *ngIf="size || timemodified">
|
||||
<ng-container *ngIf="size">{{ size }}</ng-container>
|
||||
<ng-container *ngIf="size && timemodified"> · </ng-container>
|
||||
<ng-container *ngIf="timemodified">{{ timemodified }}</ng-container>
|
||||
</p>
|
||||
</ion-label>
|
||||
|
||||
<!-- Form to edit the file's name. -->
|
||||
|
@ -23,19 +27,22 @@
|
|||
</ion-button>
|
||||
|
||||
<ng-container *ngIf="manage">
|
||||
<ion-button *ngIf="editMode" fill="clear" [attr.aria-label]="'core.save' | translate" color="success" type="submit"
|
||||
(click)="changeName(newFileName, $event)">
|
||||
<ion-icon name="fas-check" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<ion-button *ngIf="!editMode" fill="clear" [core-suppress-events] (onClick)="activateEdit($event)"
|
||||
[attr.aria-label]="'core.edit' | translate">
|
||||
<ion-icon name="fas-pen" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<ion-button *ngIf="editMode" fill="clear" [attr.aria-label]="'core.save' | translate" color="success" type="submit">
|
||||
<ion-icon name="fas-check" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
|
||||
<ion-button fill="clear" (click)="deleteFile($event)" [attr.aria-label]="'core.delete' | translate" color="danger">
|
||||
<ion-button *ngIf="!editMode" fill="clear" (click)="deleteFile($event)" [attr.aria-label]="'core.delete' | translate"
|
||||
color="danger">
|
||||
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||
</ion-button>
|
||||
</ng-container>
|
||||
</div>
|
||||
</ion-item>
|
||||
</ion-card>
|
||||
</form>
|
||||
|
|
|
@ -56,7 +56,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
timemodified?: string;
|
||||
newFileName = '';
|
||||
editMode = false;
|
||||
relativePath?: string;
|
||||
relativePath = '';
|
||||
isIOS = false;
|
||||
openButtonIcon = '';
|
||||
openButtonLabel = '';
|
||||
|
@ -112,7 +112,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
* @param isOpenButton Whether the open button was clicked.
|
||||
*/
|
||||
async openFile(e: Event, isOpenButton = false): Promise<void> {
|
||||
if (this.editMode) {
|
||||
if (this.editMode || !this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
return;
|
||||
}
|
||||
|
||||
if (!CoreFileHelper.isOpenableInApp(this.file!)) {
|
||||
if (!CoreFileHelper.isOpenableInApp(this.file)) {
|
||||
try {
|
||||
await CoreFileHelper.showConfirmOpenUnsupportedFile();
|
||||
} catch (error) {
|
||||
|
@ -139,7 +139,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
options.iOSOpenFileAction = this.defaultIsOpenWithPicker ? OpenFileAction.OPEN : OpenFileAction.OPEN_WITH;
|
||||
}
|
||||
|
||||
CoreUtils.openFile(this.file!.toURL(), options);
|
||||
CoreUtils.openFile(this.file.toURL(), options);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -148,11 +148,15 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
* @param e Click event.
|
||||
*/
|
||||
activateEdit(e: Event): void {
|
||||
if (!this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.editMode = true;
|
||||
this.newFileName = this.file!.name;
|
||||
this.newFileName = this.file.name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -162,10 +166,14 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
* @param e Click event.
|
||||
*/
|
||||
async changeName(newName: string, e: Event): Promise<void> {
|
||||
if (!this.file) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
if (newName == this.file!.name) {
|
||||
if (newName == this.file.name) {
|
||||
// Name hasn't changed, stop.
|
||||
this.editMode = false;
|
||||
CoreForms.triggerFormCancelledEvent(this.formElement, CoreSites.getCurrentSiteId());
|
||||
|
@ -174,7 +182,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
}
|
||||
|
||||
const modal = await CoreDomUtils.showModalLoading();
|
||||
const fileAndDir = CoreFile.getFileAndDirectoryFromPath(this.relativePath!);
|
||||
const fileAndDir = CoreFile.getFileAndDirectoryFromPath(this.relativePath);
|
||||
const newPath = CoreText.concatenatePaths(fileAndDir.directory, newName);
|
||||
|
||||
try {
|
||||
|
@ -186,7 +194,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
} catch {
|
||||
try {
|
||||
// File doesn't exist, move it.
|
||||
const fileEntry = await CoreFile.moveFile(this.relativePath!, newPath);
|
||||
const fileEntry = await CoreFile.moveFile(this.relativePath, newPath);
|
||||
|
||||
CoreForms.triggerFormSubmittedEvent(this.formElement, false, CoreSites.getCurrentSiteId());
|
||||
|
||||
|
@ -219,7 +227,7 @@ export class CoreLocalFileComponent implements OnInit {
|
|||
|
||||
modal = await CoreDomUtils.showModalLoading('core.deleting', true);
|
||||
|
||||
await CoreFile.removeFile(this.relativePath!);
|
||||
await CoreFile.removeFile(this.relativePath);
|
||||
|
||||
this.onDelete.emit();
|
||||
} catch (error) {
|
||||
|
|
|
@ -208,7 +208,11 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
this.expandedHeader = this.page?.querySelector('ion-item[collapsible]') ?? undefined;
|
||||
|
||||
if (!this.expandedHeader) {
|
||||
this.enabled = false;
|
||||
this.setEnabled(this.enabled);
|
||||
|
||||
throw new Error('[collapsible-header] Couldn\'t initialize expanded header');
|
||||
|
||||
}
|
||||
this.expandedHeader.classList.add('collapsible-header-expanded');
|
||||
|
||||
|
@ -384,11 +388,11 @@ export class CoreCollapsibleHeaderDirective implements OnInit, OnChanges, OnDest
|
|||
* @param enable True to enable, false otherwise
|
||||
*/
|
||||
async setEnabled(enable: boolean): Promise<void> {
|
||||
if (!this.page || !this.content) {
|
||||
if (!this.page) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (enable) {
|
||||
if (enable && this.content) {
|
||||
const contentScroll = await this.content.getScrollElement();
|
||||
|
||||
// Do nothing, since scroll has already started on the page.
|
||||
|
|
|
@ -15,11 +15,14 @@
|
|||
import { Directive, ElementRef, Input, OnDestroy, OnInit } from '@angular/core';
|
||||
import { CoreCancellablePromise } from '@classes/cancellable-promise';
|
||||
import { CoreLoadingComponent } from '@components/loading/loading';
|
||||
import { CoreSettingsHelper } from '@features/settings/services/settings-helper';
|
||||
import { CoreUtils } from '@services/utils/utils';
|
||||
import { Translate } from '@singletons';
|
||||
import { CoreColors } from '@singletons/colors';
|
||||
import { CoreComponentsRegistry } from '@singletons/components-registry';
|
||||
import { CoreDom } from '@singletons/dom';
|
||||
import { CoreEventObserver } from '@singletons/events';
|
||||
import { Subscription } from 'rxjs';
|
||||
import { CoreFormatTextDirective } from './format-text';
|
||||
|
||||
const defaultMaxHeight = 80;
|
||||
|
@ -50,6 +53,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
protected maxHeight = defaultMaxHeight;
|
||||
protected expandedHeight = 0;
|
||||
protected resizeListener?: CoreEventObserver;
|
||||
protected darkModeListener?: Subscription;
|
||||
protected domPromise?: CoreCancellablePromise<void>;
|
||||
protected uniqueId: string;
|
||||
|
||||
|
@ -92,6 +96,10 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
this.resizeListener = CoreDom.onWindowResize(() => {
|
||||
this.calculateHeight();
|
||||
}, 50);
|
||||
|
||||
this.darkModeListener = CoreSettingsHelper.onDarkModeChange().subscribe(() => {
|
||||
this.setGradientColor();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -135,7 +143,34 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
this.element.classList.remove('collapsible-loading-height');
|
||||
|
||||
// If cannot calculate height, shorten always.
|
||||
this.setExpandButtonEnabled(!this.expandedHeight || this.expandedHeight >= this.maxHeight);
|
||||
const enable = !this.expandedHeight || this.expandedHeight >= this.maxHeight;
|
||||
this.setExpandButtonEnabled(enable);
|
||||
this.setGradientColor();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the gradient color based on the background.
|
||||
*/
|
||||
protected setGradientColor(): void {
|
||||
if (!this.toggleExpandEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
let coloredElement: HTMLElement | null = this.element;
|
||||
let backgroundColor = [0, 0, 0, 0];
|
||||
let background = '';
|
||||
while (coloredElement && backgroundColor[3] === 0) {
|
||||
background = getComputedStyle(coloredElement).backgroundColor;
|
||||
backgroundColor = CoreColors.getColorRGBA(background);
|
||||
coloredElement = coloredElement.parentElement;
|
||||
}
|
||||
|
||||
if (backgroundColor[3] !== 0) {
|
||||
delete(backgroundColor[3]);
|
||||
const bgList = backgroundColor.join(',');
|
||||
this.element.style.setProperty('--background-gradient-rgb', `${bgList}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -241,6 +276,7 @@ export class CoreCollapsibleItemDirective implements OnInit, OnDestroy {
|
|||
*/
|
||||
ngOnDestroy(): void {
|
||||
this.resizeListener?.off();
|
||||
this.darkModeListener?.unsubscribe();
|
||||
this.domPromise?.cancel();
|
||||
}
|
||||
|
||||
|
|
|
@ -44,7 +44,7 @@
|
|||
</core-dynamic-component>
|
||||
|
||||
|
||||
<core-block-side-blocks-button slot="fixed" *ngIf="loaded && course && displayBlocks && hasBlocks" contextlevel="course"
|
||||
<core-block-side-blocks-button slot="fixed" *ngIf="loaded && course && displayBlocks && hasBlocks" contextLevel="course"
|
||||
[instanceId]="course.id">
|
||||
</core-block-side-blocks-button>
|
||||
|
||||
|
|
|
@ -14,43 +14,39 @@
|
|||
</ion-label>
|
||||
</ion-item>
|
||||
|
||||
<div class="core-module-info-box">
|
||||
<!-- Module completion. -->
|
||||
<ion-item class="ion-text-wrap"
|
||||
*ngIf="showCompletion && module.completiondata && (module.completiondata.isautomatic || (showManualCompletion && module.uservisible))">
|
||||
<ion-label>
|
||||
<div class="core-module-info-completion core-module-info-box-section" *ngIf="showCompletion &&
|
||||
module.completiondata && (module.completiondata.isautomatic || (showManualCompletion && module.uservisible))">
|
||||
<core-course-module-completion [completion]="module.completiondata" [moduleName]="module.name" [moduleId]="module.id"
|
||||
[showCompletionConditions]="true" [showManualCompletion]="showManualCompletion && module.uservisible"
|
||||
(completionChanged)="completionChanged.emit($event)">
|
||||
</core-course-module-completion>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
|
||||
<div class="core-module-dates-availabilityinfo"
|
||||
*ngIf="(module.dates && module.dates.length) || (showAvailabilityInfo && module.availabilityinfo)">
|
||||
<!-- Activity dates. -->
|
||||
<div *ngIf="module.dates && module.dates.length" class="core-module-dates">
|
||||
<div *ngIf="module.dates && module.dates.length" class="core-module-dates core-module-info-box-section">
|
||||
<p *ngFor="let date of module.dates">
|
||||
<ion-icon name="fas-calendar" aria-hidden="true"></ion-icon><strong>{{ date.label }}</strong> {{ date.timestamp
|
||||
*
|
||||
1000 | coreFormatDate:'strftimedatetime' }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Availability info space. -->
|
||||
<div class="core-module-availabilityinfo" *ngIf="showAvailabilityInfo">
|
||||
<div class="core-module-availabilityinfo core-module-info-box-section" *ngIf="showAvailabilityInfo">
|
||||
<ion-icon name="fas-lock" [attr.aria-label]="'core.restricted' | translate"></ion-icon>
|
||||
<core-format-text [text]="module.availabilityinfo" contextLevel="module" [contextInstanceId]="module.id" [courseId]="module.course">
|
||||
</core-format-text>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ion-item class="ion-text-wrap" *ngIf="description">
|
||||
<ion-label>
|
||||
<div class="core-module-info-description core-module-info-box-section" *ngIf="description">
|
||||
<core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
|
||||
[contextInstanceId]="module.id" [courseId]="courseId" [collapsible-item]="expandDescription ? null : ''">
|
||||
</core-format-text>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</div>
|
||||
<ng-content select="[description]"></ng-content>
|
||||
</div>
|
||||
|
||||
<ng-content></ng-content>
|
||||
|
||||
|
|
|
@ -23,11 +23,34 @@
|
|||
|
||||
}
|
||||
|
||||
.core-module-dates-availabilityinfo {
|
||||
.core-module-info-box {
|
||||
background: var(--light);
|
||||
border-radius: var(--small-radius);
|
||||
padding: 8px;
|
||||
margin: 8px;
|
||||
padding: 8px;
|
||||
|
||||
::ng-deep ion-item {
|
||||
--ion-item-background: var(--light);
|
||||
--background: var(--light);
|
||||
}
|
||||
|
||||
::ng-deep ion-card.card-file {
|
||||
--ion-card-horizontal-margin: 0px;
|
||||
}
|
||||
|
||||
.core-module-info-box-section + .core-module-info-box-section {
|
||||
border-top: 1px solid var(--stroke);
|
||||
margin-top: 8px;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.core-module-dates ion-icon {
|
||||
margin-left: 4px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
.core-module-dates,
|
||||
.core-module-availabilityinfo {
|
||||
font-size: 90%;
|
||||
ion-icon {
|
||||
position: static;
|
||||
|
@ -40,10 +63,6 @@
|
|||
margin-bottom: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
.core-module-dates + .core-module-availabilityinfo {
|
||||
border-top: 1px solid var(--stroke);
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
core-course-module-completion ::ng-deep ion-button {
|
||||
|
|
|
@ -21,6 +21,10 @@
|
|||
margin-top: var(--button-vertical-margin);
|
||||
margin-bottom: var(--button-vertical-margin);
|
||||
}
|
||||
|
||||
&.empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
:host-context(core-course-format.core-course-format-singleactivity) {
|
||||
|
|