MOBILE-3931 module: Add a new module summary page
parent
279071634b
commit
d224876f42
|
@ -24,6 +24,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
|
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
|
[iconAction]="prefetchStatusIcon" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -33,6 +33,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
(action)="showSortOrderSelector()">
|
(action)="showSortOrderSelector()">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -36,6 +36,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -30,6 +30,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
|
(action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -15,6 +15,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -23,6 +23,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
|
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)"
|
||||||
[iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
[iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -24,6 +24,10 @@
|
||||||
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
iconDescription="fas-archive" (action)="removeFiles($event)" iconAction="fas-trash" [closeOnClick]="false">
|
||||||
</core-context-menu-item>
|
</core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
|
|
||||||
|
<ion-button fill="clear" (click)="openModuleSummary()" aria-haspopup="true" [attr.aria-label]="'core.course.modulesummary' | translate">
|
||||||
|
<ion-icon name="fas-info-circle" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
<!-- Content. -->
|
<!-- Content. -->
|
||||||
|
|
|
@ -1,8 +1,5 @@
|
||||||
<ion-header>
|
<ion-header class="no-title">
|
||||||
<ion-toolbar>
|
<ion-toolbar>
|
||||||
<ion-title>
|
|
||||||
<h2>{{ 'core.block.blocks' | translate }}</h2>
|
|
||||||
</ion-title>
|
|
||||||
<ion-buttons slot="end">
|
<ion-buttons slot="end">
|
||||||
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
<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-icon name="fas-times" slot="icon-only" aria-hidden=true></ion-icon>
|
||||||
|
@ -10,7 +7,7 @@
|
||||||
</ion-buttons>
|
</ion-buttons>
|
||||||
</ion-toolbar>
|
</ion-toolbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content [fullscreen]="true">
|
||||||
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="doRefresh($event.target)">
|
<ion-refresher slot="fixed" [disabled]="!loaded" (ionRefresh)="doRefresh($event.target)">
|
||||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
|
@ -42,7 +42,6 @@ export class CoreCourseModuleMainActivityComponent extends CoreCourseModuleMainR
|
||||||
|
|
||||||
// Data for context menu.
|
// Data for context menu.
|
||||||
syncIcon?: string; // Sync icon.
|
syncIcon?: string; // Sync icon.
|
||||||
hasOffline?: boolean; // If it has offline data to be synced.
|
|
||||||
isOnline?: boolean; // If the app is online or not.
|
isOnline?: boolean; // If the app is online or not.
|
||||||
|
|
||||||
protected syncObserver?: CoreEventObserver; // It will observe the sync auto event.
|
protected syncObserver?: CoreEventObserver; // It will observe the sync auto event.
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { CoreUtils } from '@services/utils/utils';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
|
import { CoreCourseModuleSummaryComponent, CoreCourseModuleSummaryResult } from '../components/module-summary/module-summary';
|
||||||
import { CoreCourseContentsPage } from '../pages/contents/contents';
|
import { CoreCourseContentsPage } from '../pages/contents/contents';
|
||||||
import { CoreCourse } from '../services/course';
|
import { CoreCourse } from '../services/course';
|
||||||
import { CoreCourseHelper, CoreCourseModuleData } from '../services/course-helper';
|
import { CoreCourseHelper, CoreCourseModuleData } from '../services/course-helper';
|
||||||
|
@ -58,6 +59,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
loaded = false; // If the component has been loaded.
|
loaded = false; // If the component has been loaded.
|
||||||
component?: string; // Component name.
|
component?: string; // Component name.
|
||||||
componentId?: number; // Component ID.
|
componentId?: number; // Component ID.
|
||||||
|
hasOffline = false; // Resources don't have any data to sync.
|
||||||
blog?: boolean; // If blog is available.
|
blog?: boolean; // If blog is available.
|
||||||
|
|
||||||
// Data for context menu.
|
// Data for context menu.
|
||||||
|
@ -253,16 +255,11 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expand the description.
|
* Expand the description.
|
||||||
|
*
|
||||||
|
* @deprecated Use openModuleSummary instead.
|
||||||
*/
|
*/
|
||||||
expandDescription(): void {
|
expandDescription(): void {
|
||||||
CoreTextUtils.viewText(Translate.instant('core.description'), this.description!, {
|
this.openModuleSummary();
|
||||||
component: this.component,
|
|
||||||
componentId: this.module.id,
|
|
||||||
filter: true,
|
|
||||||
contextLevel: 'module',
|
|
||||||
instanceId: this.module.id,
|
|
||||||
courseId: this.courseId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -449,6 +446,48 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
this.module = module;
|
this.module = module;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a module summary page.
|
||||||
|
*/
|
||||||
|
async openModuleSummary(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await CoreDomUtils.openSideModal<CoreCourseModuleSummaryResult>({
|
||||||
|
component: CoreCourseModuleSummaryComponent,
|
||||||
|
componentProps: {
|
||||||
|
moduleId: this.module.id,
|
||||||
|
module: this.module,
|
||||||
|
description: this.description,
|
||||||
|
component: this.component,
|
||||||
|
courseId: this.courseId,
|
||||||
|
hasOffline: this.hasOffline,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (data) {
|
||||||
|
if (data.action == 'refresh') {
|
||||||
|
const modal = await CoreDomUtils.showModalLoading();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.doRefresh();
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
}
|
||||||
|
} else if(data.action == 'sync') {
|
||||||
|
const modal = await CoreDomUtils.showModalLoading();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await this.doRefresh( undefined, undefined, true);
|
||||||
|
} finally {
|
||||||
|
modal.dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component being destroyed.
|
* Component being destroyed.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@ import { CoreCourseModuleCompletionLegacyComponent } from './module-completion-l
|
||||||
import { CoreCourseModuleInfoComponent } from './module-info/module-info';
|
import { CoreCourseModuleInfoComponent } from './module-info/module-info';
|
||||||
import { CoreCourseModuleManualCompletionComponent } from './module-manual-completion/module-manual-completion';
|
import { CoreCourseModuleManualCompletionComponent } from './module-manual-completion/module-manual-completion';
|
||||||
import { CoreCourseModuleNavigationComponent } from './module-navigation/module-navigation';
|
import { CoreCourseModuleNavigationComponent } from './module-navigation/module-navigation';
|
||||||
|
import { CoreCourseModuleSummaryComponent } from './module-summary/module-summary';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [
|
declarations: [
|
||||||
|
@ -41,6 +42,7 @@ import { CoreCourseModuleNavigationComponent } from './module-navigation/module-
|
||||||
CoreCourseTagAreaComponent,
|
CoreCourseTagAreaComponent,
|
||||||
CoreCourseUnsupportedModuleComponent,
|
CoreCourseUnsupportedModuleComponent,
|
||||||
CoreCourseModuleNavigationComponent,
|
CoreCourseModuleNavigationComponent,
|
||||||
|
CoreCourseModuleSummaryComponent,
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CoreBlockComponentsModule,
|
CoreBlockComponentsModule,
|
||||||
|
@ -58,6 +60,7 @@ import { CoreCourseModuleNavigationComponent } from './module-navigation/module-
|
||||||
CoreCourseTagAreaComponent,
|
CoreCourseTagAreaComponent,
|
||||||
CoreCourseUnsupportedModuleComponent,
|
CoreCourseUnsupportedModuleComponent,
|
||||||
CoreCourseModuleNavigationComponent,
|
CoreCourseModuleNavigationComponent,
|
||||||
|
CoreCourseModuleSummaryComponent,
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class CoreCourseComponentsModule {}
|
export class CoreCourseComponentsModule {}
|
||||||
|
|
|
@ -0,0 +1,82 @@
|
||||||
|
<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 slot="icon-only" name="fas-times" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-buttons>
|
||||||
|
</ion-toolbar>
|
||||||
|
</ion-header>
|
||||||
|
<ion-content [fullscreen]="true">
|
||||||
|
<!-- Content. -->
|
||||||
|
<core-loading [hideUntil]="loaded">
|
||||||
|
<!-- Activity info. -->
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="module">
|
||||||
|
<ion-label>
|
||||||
|
<h1>
|
||||||
|
<core-format-text [text]="module.name" contextLevel="module" [component]="component" [componentId]="componentId"
|
||||||
|
[contextInstanceId]="module.id" [courseId]="courseId">
|
||||||
|
</core-format-text>
|
||||||
|
</h1>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button fill="clear" [href]="externalUrl" core-link [showBrowserWarning]="false" color="dark"
|
||||||
|
[attr.aria-label]="'core.openinbrowser' | translate" slot="end">
|
||||||
|
<ion-icon name="fas-external-link-alt" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
</ion-item>
|
||||||
|
<ion-item class="ion-text-wrap" *ngIf="module && description">
|
||||||
|
<ion-label>
|
||||||
|
<core-format-text [text]="description" [component]="component" [componentId]="componentId" contextLevel="module"
|
||||||
|
[contextInstanceId]="module.id" [courseId]="courseId" [maxHeight]="120">
|
||||||
|
</core-format-text>
|
||||||
|
</ion-label>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item button class="ion-margin" *ngIf="prefetchText" class="ion-text-wrap">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading ion-text-wrap">{{ prefetchText }}</p>
|
||||||
|
<p *ngIf="downloadTimeReadable">{{ downloadTimeReadable }}</p>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button *ngIf="prefetchStatusIcon && prefetchStatusIcon != 'spinner'" (click)="prefetch()" color="primary" fill="outline"
|
||||||
|
[attr.aria-label]="'core.download' | translate" slot="end">
|
||||||
|
<ion-icon [name]="prefetchStatusIcon" slot="icon-only" aria-hidden="true">
|
||||||
|
</ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
<ion-spinner *ngIf="prefetchStatusIcon == 'spinner'" slot="end" aria-hidden="true"></ion-spinner>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-item button class="ion-margin" *ngIf="sizeReadable" class="ion-text-wrap">
|
||||||
|
<ion-label>
|
||||||
|
<p class="item-heading ion-text-wrap">{{ 'addon.storagemanager.totalspaceusage' | translate }}</p>
|
||||||
|
<ion-badge color="light">{{ sizeReadable | coreBytesToSize }}</ion-badge>
|
||||||
|
</ion-label>
|
||||||
|
<ion-button *ngIf="!removeFilesLoading && size > 0" (click)="removeFiles()" color="danger" fill="outline"
|
||||||
|
[attr.aria-label]="'core.clearstoreddata' | translate:{$a: sizeReadable}" slot="end">
|
||||||
|
<ion-icon name="fas-trash" slot="icon-only" aria-hidden="true"></ion-icon>
|
||||||
|
</ion-button>
|
||||||
|
<ion-spinner *ngIf="removeFilesLoading" slot="end" aria-hidden="true"></ion-spinner>
|
||||||
|
</ion-item>
|
||||||
|
|
||||||
|
<ion-button *ngIf="blog" class="ion-margin" (click)="gotoBlog()" expand="block" fill="outline">
|
||||||
|
<ion-icon name="far-newspaper" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
{{ 'addon.blog.blog' | translate }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
</core-loading>
|
||||||
|
</ion-content>
|
||||||
|
<ion-footer *ngIf="loaded && isOnline">
|
||||||
|
<ion-button class="ion-margin" *ngIf="!hasOffline" (click)="refresh()" expand="block">
|
||||||
|
<ion-icon name="fas-redo-alt" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
{{ 'core.refresh' | translate }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
|
||||||
|
<ion-button class="ion-margin" *ngIf="hasOffline" (click)="sync()" expand="block">
|
||||||
|
<ion-icon name="fas-sync-alt" slot="start" aria-hidden="true"></ion-icon>
|
||||||
|
<ion-label>
|
||||||
|
{{ 'core.settings.synchronizenow' | translate }}
|
||||||
|
</ion-label>
|
||||||
|
</ion-button>
|
||||||
|
</ion-footer>
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
:host ::ng-deep .collapsible-title ion-label {
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
|
@ -0,0 +1,311 @@
|
||||||
|
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
import { CoreConstants } from '@/core/constants';
|
||||||
|
import { AddonBlog } from '@addons/blog/services/blog';
|
||||||
|
import { AddonBlogMainMenuHandlerService } from '@addons/blog/services/handlers/mainmenu';
|
||||||
|
import { Component, Input, OnDestroy, OnInit } from '@angular/core';
|
||||||
|
import { Params } from '@angular/router';
|
||||||
|
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
|
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
||||||
|
import { CoreApp } from '@services/app';
|
||||||
|
import { CoreFilepool } from '@services/filepool';
|
||||||
|
import { CoreNavigator } from '@services/navigator';
|
||||||
|
import { CoreSites } from '@services/sites';
|
||||||
|
import { CoreDomUtils } from '@services/utils/dom';
|
||||||
|
import { CoreTextUtils } from '@services/utils/text';
|
||||||
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
|
import { ModalController, Network, Translate, NgZone } from '@singletons';
|
||||||
|
import { CoreEventObserver, CoreEvents } from '@singletons/events';
|
||||||
|
import { Subscription } from 'rxjs';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component to display a module summary modal.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
selector: 'core-course-module-summary',
|
||||||
|
templateUrl: 'module-summary.html',
|
||||||
|
styleUrls: ['module-summary.scss'],
|
||||||
|
})
|
||||||
|
export class CoreCourseModuleSummaryComponent implements OnInit, OnDestroy {
|
||||||
|
|
||||||
|
@Input() module?: CoreCourseModuleData; // The module of the component.
|
||||||
|
@Input() courseId = 0; // Course ID the component belongs to.
|
||||||
|
@Input() moduleId = 0; // Module ID the component belongs to.
|
||||||
|
@Input() component = ''; // Component name.
|
||||||
|
@Input() description = ''; // Module description.
|
||||||
|
@Input() hasOffline = false; // If it has offline data to be synced.
|
||||||
|
|
||||||
|
loaded = false; // If the component has been loaded.
|
||||||
|
componentId?: number; // Component ID.
|
||||||
|
|
||||||
|
// Data for context menu.
|
||||||
|
externalUrl?: string; // External URL to open in browser.
|
||||||
|
|
||||||
|
removeFilesLoading = false;
|
||||||
|
prefetchStatusIcon?: string;
|
||||||
|
prefetchStatus?: string;
|
||||||
|
prefetchText?: string;
|
||||||
|
sizeReadable?: string;
|
||||||
|
downloadTimeReadable?: string; // Last download time in a readable format.
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
blog = false; // If blog is available.
|
||||||
|
|
||||||
|
isOnline = false; // If the app is online or not.
|
||||||
|
|
||||||
|
protected onlineSubscription: Subscription; // It will observe the status of the network connection.
|
||||||
|
|
||||||
|
protected packageStatusObserver?: CoreEventObserver; // Observer of package status.
|
||||||
|
protected fileStatusObserver?: CoreEventObserver; // Observer of file status.
|
||||||
|
protected siteId: string;
|
||||||
|
protected isDestroyed = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.siteId = CoreSites.getCurrentSiteId();
|
||||||
|
this.isOnline = CoreApp.isOnline();
|
||||||
|
|
||||||
|
// Refresh online status when changes.
|
||||||
|
this.onlineSubscription = Network.onChange().subscribe(() => {
|
||||||
|
// Execute the callback in the Angular zone, so change detection doesn't stop working.
|
||||||
|
NgZone.run(() => {
|
||||||
|
this.isOnline = CoreApp.isOnline();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
async ngOnInit(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
this.closeModal();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.fetchContent();
|
||||||
|
|
||||||
|
if (this.component) {
|
||||||
|
this.packageStatusObserver = CoreEvents.on(
|
||||||
|
CoreEvents.PACKAGE_STATUS_CHANGED,
|
||||||
|
(data) => {
|
||||||
|
if (data.componentId == module.id && data.component == this.component) {
|
||||||
|
this.getPackageStatus();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
this.siteId,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Debounce the update size function to prevent too many calls when downloading or deleting a whole activity.
|
||||||
|
const debouncedUpdateSize = CoreUtils.debounce(async () => {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const moduleSize = await CoreCourseModulePrefetchDelegate.getModuleStoredSize(this.module, this.courseId);
|
||||||
|
|
||||||
|
this.sizeReadable = moduleSize > 0 ? CoreTextUtils.bytesToSize(moduleSize, 2) : '';
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
this.fileStatusObserver = CoreEvents.on(
|
||||||
|
CoreEvents.COMPONENT_FILE_ACTION,
|
||||||
|
(data) => {
|
||||||
|
if (data.component != this.component || data.componentId != module.id) {
|
||||||
|
// The event doesn't belong to this component, ignore.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!CoreFilepool.isFileEventDownloadedOrDeleted(data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the module size.
|
||||||
|
debouncedUpdateSize();
|
||||||
|
},
|
||||||
|
this.siteId,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fetch content to populate the page.
|
||||||
|
*/
|
||||||
|
protected async fetchContent(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.componentId = this.module.id;
|
||||||
|
this.externalUrl = this.module.url;
|
||||||
|
this.courseId = this.courseId || this.module.course;
|
||||||
|
|
||||||
|
this.blog = await AddonBlog.isPluginEnabled();
|
||||||
|
|
||||||
|
await this.getPackageStatus();
|
||||||
|
|
||||||
|
this.loaded = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updage package status.
|
||||||
|
*
|
||||||
|
* @param refresh If prefetch info has to be refreshed.
|
||||||
|
*/
|
||||||
|
async getPackageStatus(refresh = false): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const moduleInfo =
|
||||||
|
await CoreCourseHelper.getModulePrefetchInfo(this.module, this.courseId, refresh, this.component);
|
||||||
|
|
||||||
|
this.prefetchStatusIcon = moduleInfo.statusIcon;
|
||||||
|
this.prefetchStatus = moduleInfo.status;
|
||||||
|
this.downloadTimeReadable = '';
|
||||||
|
|
||||||
|
if (moduleInfo.status != CoreConstants.NOT_DOWNLOADABLE) {
|
||||||
|
// Module is downloadable, get the text to display to prefetch.
|
||||||
|
if (moduleInfo.downloadTime && moduleInfo.downloadTime > 0) {
|
||||||
|
this.prefetchText = Translate.instant('core.lastdownloaded');
|
||||||
|
this.downloadTimeReadable = CoreTextUtils.ucFirst(moduleInfo.downloadTimeReadable);
|
||||||
|
} else {
|
||||||
|
// Module not downloaded, show a default text.
|
||||||
|
this.prefetchText = Translate.instant('core.download');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.sizeReadable = moduleInfo.sizeReadable;
|
||||||
|
this.size = moduleInfo.size;
|
||||||
|
if (moduleInfo.status == CoreConstants.DOWNLOADING) {
|
||||||
|
// Set this to empty to prevent "remove file" option showing up while downloading.
|
||||||
|
this.sizeReadable = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Go to blog posts.
|
||||||
|
*/
|
||||||
|
async gotoBlog(): Promise<void> {
|
||||||
|
const params: Params = { cmId: this.moduleId };
|
||||||
|
|
||||||
|
await CoreNavigator.navigateToSitePath(AddonBlogMainMenuHandlerService.PAGE_NAME, { params });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prefetch the module.
|
||||||
|
*/
|
||||||
|
async prefetch(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialIcon = this.prefetchStatusIcon;
|
||||||
|
this.prefetchStatusIcon = CoreConstants.ICON_DOWNLOADING; // Show spinner since this operation might take a while.
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We need to call getDownloadSize, the package might have been updated.
|
||||||
|
const size = await CoreCourseModulePrefetchDelegate.getModuleDownloadSize(this.module, this.courseId, true);
|
||||||
|
|
||||||
|
await CoreDomUtils.confirmDownloadSize(size);
|
||||||
|
|
||||||
|
await CoreCourseModulePrefetchDelegate.prefetchModule(this.module, this.courseId, true);
|
||||||
|
|
||||||
|
await this.getPackageStatus(true);
|
||||||
|
} catch (error) {
|
||||||
|
this.prefetchStatusIcon = initialIcon;
|
||||||
|
|
||||||
|
if (!this.isDestroyed) {
|
||||||
|
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm and remove downloaded files.
|
||||||
|
*/
|
||||||
|
async removeFiles(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.prefetchStatus == CoreConstants.DOWNLOADING) {
|
||||||
|
CoreDomUtils.showAlertTranslated(undefined, 'core.course.cannotdeletewhiledownloading');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await CoreDomUtils.showDeleteConfirm('addon.storagemanager.confirmdeletedatafrom', { name: this.module.name });
|
||||||
|
|
||||||
|
this.removeFilesLoading = true;
|
||||||
|
|
||||||
|
await CoreCourseHelper.removeModuleStoredData(this.module, this.courseId);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
if (!this.isDestroyed &&error) {
|
||||||
|
CoreDomUtils.showErrorModal(error);
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
this.removeFilesLoading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.getPackageStatus();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Refresh the data.
|
||||||
|
*/
|
||||||
|
async refresh(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModalController.dismiss({ action: 'refresh' });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sync the data.
|
||||||
|
*/
|
||||||
|
async sync(): Promise<void> {
|
||||||
|
if (!this.module) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ModalController.dismiss({ action: 'sync' });
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Close the modal.
|
||||||
|
*/
|
||||||
|
closeModal(): void {
|
||||||
|
ModalController.dismiss();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @inheritdoc
|
||||||
|
*/
|
||||||
|
ngOnDestroy(): void {
|
||||||
|
this.isDestroyed = true;
|
||||||
|
this.packageStatusObserver?.off();
|
||||||
|
this.fileStatusObserver?.off();
|
||||||
|
this.onlineSubscription.unsubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
export type CoreCourseModuleSummaryResult = {
|
||||||
|
action: 'sync'|'refresh';
|
||||||
|
};
|
|
@ -297,6 +297,14 @@ button,
|
||||||
|
|
||||||
ion-button {
|
ion-button {
|
||||||
margin: 4px 8px;
|
margin: 4px 8px;
|
||||||
|
|
||||||
|
ion-spinner[slot=start] {
|
||||||
|
@include margin-horizontal(-0.3em, 0.3em);
|
||||||
|
}
|
||||||
|
|
||||||
|
ion-spinner[slot=end] {
|
||||||
|
@include margin-horizontal(-0.3em, 0.3em);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ion-button.button-outline {
|
ion-button.button-outline {
|
||||||
|
@ -1465,6 +1473,16 @@ ion-grid.core-no-grid > ion-row {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ion-header.no-title {
|
||||||
|
--core-header-toolbar-border-width: 0;
|
||||||
|
--core-header-toolbar-background: transparent;
|
||||||
|
|
||||||
|
ion-toolbar .button.button-clear,
|
||||||
|
ion-toolbar .button.button-solid {
|
||||||
|
--background: var(--ion-background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ion-header[collapsible] {
|
ion-header[collapsible] {
|
||||||
@include core-transition(all, 500ms);
|
@include core-transition(all, 500ms);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue