MOBILE-2895 course: Show modules downloaded status
parent
c6e01bfa66
commit
99809afbad
|
@ -1329,6 +1329,7 @@
|
|||
"core.dismiss": "local_moodlemobileapp",
|
||||
"core.done": "survey",
|
||||
"core.download": "moodle",
|
||||
"core.downloaded": "local_moodlemobileapp",
|
||||
"core.downloading": "local_moodlemobileapp",
|
||||
"core.edit": "moodle",
|
||||
"core.emptysplit": "local_moodlemobileapp",
|
||||
|
|
|
@ -1329,6 +1329,7 @@
|
|||
"core.dismiss": "Dismiss",
|
||||
"core.done": "Done",
|
||||
"core.download": "Download",
|
||||
"core.downloaded": "Downloaded",
|
||||
"core.downloading": "Downloading",
|
||||
"core.edit": "Edit",
|
||||
"core.emptysplit": "This page will appear blank if the left panel is empty or is loading.",
|
||||
|
|
|
@ -34,6 +34,7 @@ import { CoreContextMenuPopoverComponent } from './context-menu/context-menu-pop
|
|||
import { CoreCoursePickerMenuPopoverComponent } from './course-picker-menu/course-picker-menu-popover';
|
||||
import { CoreChartComponent } from './chart/chart';
|
||||
import { CoreChronoComponent } from './chrono/chrono';
|
||||
import { CoreDownloadRefreshComponent } from './download-refresh/download-refresh';
|
||||
import { CoreLocalFileComponent } from './local-file/local-file';
|
||||
import { CoreSitePickerComponent } from './site-picker/site-picker';
|
||||
import { CoreTabsComponent } from './tabs/tabs';
|
||||
|
@ -72,6 +73,7 @@ import { CoreStyleComponent } from './style/style';
|
|||
CoreCoursePickerMenuPopoverComponent,
|
||||
CoreChartComponent,
|
||||
CoreChronoComponent,
|
||||
CoreDownloadRefreshComponent,
|
||||
CoreLocalFileComponent,
|
||||
CoreSitePickerComponent,
|
||||
CoreTabsComponent,
|
||||
|
@ -118,6 +120,7 @@ import { CoreStyleComponent } from './style/style';
|
|||
CoreContextMenuItemComponent,
|
||||
CoreChartComponent,
|
||||
CoreChronoComponent,
|
||||
CoreDownloadRefreshComponent,
|
||||
CoreLocalFileComponent,
|
||||
CoreSitePickerComponent,
|
||||
CoreTabsComponent,
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
<ng-container *ngIf="enabled && !(loading || status === statusDownloading)">
|
||||
<!-- Download button. -->
|
||||
<button *ngIf="status == statusNotDownloaded" ion-button icon-only clear (click)="download($event, false)" color="dark" class="core-animate-show-hide" [attr.aria-label]="'core.download' | translate">
|
||||
<ion-icon name="cloud-download"></ion-icon>
|
||||
</button>
|
||||
|
||||
<!-- Refresh button. -->
|
||||
<button *ngIf="status == statusOutdated || (status == statusDownloaded && !canTrustDownload)" ion-button icon-only clear (click)="download($event, true)" color="dark" class="core-animate-show-hide" [attr.aria-label]="'core.refresh' | translate">
|
||||
<ion-icon name="refresh"></ion-icon>
|
||||
</button>
|
||||
|
||||
<!-- Downloaded status icon. -->
|
||||
<ion-icon *ngIf="status == statusDownloaded && canTrustDownload" class="core-icon-downloaded" color="success" name="cloud-done" [attr.aria-label]="'core.downloaded' | translate" role="status"></ion-icon>
|
||||
</ng-container>
|
||||
|
||||
<!-- Spinner. -->
|
||||
<ion-spinner *ngIf="loading || status === statusDownloading" class="core-animate-show-hide"></ion-spinner>
|
|
@ -0,0 +1,16 @@
|
|||
ion-app.app-root core-download-refresh {
|
||||
button, ion-icon {
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.core-icon-downloaded {
|
||||
font-size: 1.8em;
|
||||
}
|
||||
|
||||
.spinner {
|
||||
/*@include position(null, 13px, null, null);
|
||||
position: absolute;*/
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
// (C) Copyright 2015 Martin Dougiamas
|
||||
//
|
||||
// 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 { Component, Input, Output, EventEmitter } from '@angular/core';
|
||||
import { CoreConstants } from '@core/constants';
|
||||
|
||||
/**
|
||||
* Component to show a download button with refresh option, the spinner and the status of it.
|
||||
*
|
||||
* Usage:
|
||||
* <core-download-refresh [status]="status" enabled="true" canCheckUpdates="true" action="download()"></core-download-refresh>
|
||||
*/
|
||||
@Component({
|
||||
selector: 'core-download-refresh',
|
||||
templateUrl: 'core-download-refresh.html'
|
||||
})
|
||||
export class CoreDownloadRefreshComponent {
|
||||
@Input() status: string; // Download status.
|
||||
@Input() enabled = false; // Whether the download is enabled.
|
||||
@Input() loading = true; // Force loading status when is not downloading.
|
||||
@Input() canTrustDownload = false; // If false, refresh will be shown if downloaded.
|
||||
@Output() action: EventEmitter<boolean>; // Will emit an event when the item clicked.
|
||||
|
||||
statusDownloaded = CoreConstants.DOWNLOADED;
|
||||
statusNotDownloaded = CoreConstants.NOT_DOWNLOADED;
|
||||
statusOutdated = CoreConstants.OUTDATED;
|
||||
statusDownloading = CoreConstants.DOWNLOADING;
|
||||
|
||||
constructor() {
|
||||
this.action = new EventEmitter();
|
||||
}
|
||||
|
||||
/**
|
||||
* Download clicked.
|
||||
*
|
||||
* @param {Event} e Click event.
|
||||
* @param {boolean} refresh Whether it's refreshing.
|
||||
*/
|
||||
download(e: Event, refresh: boolean): void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
this.action.emit(refresh);
|
||||
}
|
||||
}
|
|
@ -90,17 +90,9 @@
|
|||
<!-- Template to render a section download button/progress. -->
|
||||
<ng-template #sectionDownloadTemplate let-section="section">
|
||||
<div *ngIf="section && downloadEnabled" class="core-button-spinner" float-end>
|
||||
<!-- Download button. -->
|
||||
<button *ngIf="section.showDownload && !section.isDownloading && !section.isCalculating" (click)="prefetch($event, section)" ion-button icon-only clear color="dark" [attr.aria-label]="'core.download' | translate">
|
||||
<ion-icon name="cloud-download"></ion-icon>
|
||||
</button>
|
||||
<!-- Refresh button. -->
|
||||
<button *ngIf="section.showRefresh && !section.isDownloading && !section.isCalculating" (click)="prefetch($event, section)" ion-button icon-only clear color="dark" [attr.aria-label]="'core.refresh' | translate">
|
||||
<ion-icon name="refresh"></ion-icon>
|
||||
</button>
|
||||
<!-- Download progress. -->
|
||||
<ion-badge class="core-course-download-section-progress" *ngIf="section.isDownloading && section.total > 0 && section.count < section.total">{{section.count}} / {{section.total}}</ion-badge>
|
||||
<!-- Spinner (downloading or calculating status). -->
|
||||
<ion-spinner *ngIf="section.isDownloading || section.isCalculating"></ion-spinner>
|
||||
|
||||
<core-download-refresh [status]="section.downloadStatus" [enabled]="downloadEnabled" [loading]="section.isDownloading || section.isCalculating" [canTrustDownload]="section.canCheckUpdates" (action)="prefetch(section, $event)"></core-download-refresh>
|
||||
</div>
|
||||
</ng-template>
|
||||
|
|
|
@ -119,7 +119,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
this.courseHelper.calculateSectionStatus(section, this.course.id, false).then(() => {
|
||||
if (section.isDownloading && !prefetchDelegate.isBeingDownloaded(downloadId)) {
|
||||
// All the modules are now downloading, set a download all promise.
|
||||
this.prefetch(section, false);
|
||||
this.prefetch(section);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -339,13 +339,10 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy {
|
|||
/**
|
||||
* Confirm and prefetch a section. If the section is "all sections", prefetch all the sections.
|
||||
*
|
||||
* @param {Event} e Click event.
|
||||
* @param {any} section Section to download.
|
||||
* @param {boolean} refresh Refresh clicked (not used).
|
||||
*/
|
||||
prefetch(e: Event, section: any): void {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
prefetch(section: any, refresh: boolean = false): void {
|
||||
section.isCalculating = true;
|
||||
this.courseHelper.confirmDownloadSizeSection(this.course.id, section, this.sections).then(() => {
|
||||
this.prefetchSection(section, true);
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
ion-app.app-root core-course-module-completion a {
|
||||
display: block;
|
||||
|
||||
img {
|
||||
padding: 5px;
|
||||
width: 30px;
|
||||
|
|
|
@ -10,23 +10,12 @@
|
|||
<core-course-module-completion *ngIf="module.completiondata" [completion]="module.completiondata" [moduleName]="module.name" (completionChanged)="completionChanged.emit($event)"></core-course-module-completion>
|
||||
|
||||
<div class="core-module-buttons-more">
|
||||
<!-- Download button. -->
|
||||
<button *ngIf="downloadEnabled && showDownload" [hidden]="spinner || module.handlerData.spinner" ion-button icon-only clear (click)="download($event, false)" color="dark" class="core-animate-show-hide" [attr.aria-label]="'core.download' | translate">
|
||||
<ion-icon name="cloud-download"></ion-icon>
|
||||
</button>
|
||||
|
||||
<!-- Refresh button. -->
|
||||
<button *ngIf="downloadEnabled && showRefresh" [hidden]="spinner || module.handlerData.spinner" ion-button icon-only clear (click)="download($event, true)" color="dark" class="core-animate-show-hide" [attr.aria-label]="'core.refresh' | translate">
|
||||
<ion-icon name="refresh"></ion-icon>
|
||||
</button>
|
||||
<core-download-refresh [status]="downloadStatus" [enabled]="downloadEnabled" [loading]="spinner || module.handlerData.spinner" [canTrustDownload]="canCheckUpdates" (action)="download($event)"></core-download-refresh>
|
||||
|
||||
<!-- Buttons defined by the module handler. -->
|
||||
<button ion-button icon-only clear *ngFor="let button of module.handlerData.buttons" [hidden]="button.hidden || spinner || module.handlerData.spinner" (click)="buttonClicked($event, button)" color="dark" class="core-animate-show-hide" [attr.aria-label]="button.label | translate">
|
||||
<core-icon [name]="button.icon" [ios]="button.iosIcon || ''" [md]="button.mdIcon || ''"></core-icon>
|
||||
</button>
|
||||
|
||||
<!-- Spinner. -->
|
||||
<ion-spinner *ngIf="spinner || module.handlerData.spinner" class="core-animate-show-hide"></ion-spinner>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -36,6 +36,8 @@ ion-app.app-root core-course-module {
|
|||
flex-flow: row;
|
||||
align-items: center;
|
||||
z-index: 1;
|
||||
justify-content: space-around;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
.core-module-buttons core-course-module-completion,
|
||||
|
@ -44,9 +46,8 @@ ion-app.app-root core-course-module {
|
|||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.core-module-buttons-more .spinner {
|
||||
@include position(null, 13px, null, null);
|
||||
position: absolute;
|
||||
.core-module-buttons core-course-module-completion {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,6 @@ import { CoreCourseHelperProvider } from '../../providers/helper';
|
|||
import { CoreCourseProvider } from '../../providers/course';
|
||||
import { CoreCourseModuleHandlerButton } from '../../providers/module-delegate';
|
||||
import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler } from '../../providers/module-prefetch-delegate';
|
||||
import { CoreConstants } from '../../../constants';
|
||||
|
||||
/**
|
||||
* Component to display a module entry in a list of modules.
|
||||
|
@ -52,9 +51,9 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
}
|
||||
@Output() completionChanged?: EventEmitter<any>; // Will emit an event when the module completion changes.
|
||||
|
||||
showDownload: boolean; // Whether to display the download button.
|
||||
showRefresh: boolean; // Whether to display the refresh button.
|
||||
spinner: boolean; // Whether to display a spinner.
|
||||
downloadStatus: string;
|
||||
canCheckUpdates: boolean;
|
||||
spinner: boolean; // Whether to display a loading spinner.
|
||||
downloadEnabled: boolean; // Whether the download of sections and modules is enabled.
|
||||
|
||||
protected prefetchHandler: CoreCourseModulePrefetchHandler;
|
||||
|
@ -81,6 +80,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
if (this.module.handlerData.showDownloadButton) {
|
||||
// Listen for changes on this module status, even if download isn't enabled.
|
||||
this.prefetchHandler = this.prefetchDelegate.getPrefetchHandlerFor(this.module);
|
||||
this.canCheckUpdates = this.prefetchDelegate.canCheckUpdates();
|
||||
|
||||
this.statusObserver = this.eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => {
|
||||
if (data.componentId === this.module.id && this.prefetchHandler &&
|
||||
|
@ -135,13 +135,9 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
/**
|
||||
* Download the module.
|
||||
*
|
||||
* @param {Event} event Click event.
|
||||
* @param {boolean} refresh Whether it's refreshing.
|
||||
*/
|
||||
download(event: Event, refresh: boolean): void {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
download(refresh: boolean): void {
|
||||
if (!this.prefetchHandler) {
|
||||
return;
|
||||
}
|
||||
|
@ -168,10 +164,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
|
|||
*/
|
||||
protected showStatus(status: string): void {
|
||||
if (status) {
|
||||
this.spinner = status === CoreConstants.DOWNLOADING;
|
||||
this.showDownload = status === CoreConstants.NOT_DOWNLOADED;
|
||||
this.showRefresh = status === CoreConstants.OUTDATED ||
|
||||
(!this.prefetchDelegate.canCheckUpdates() && status === CoreConstants.DOWNLOADED);
|
||||
this.spinner = false;
|
||||
this.downloadStatus = status;
|
||||
|
||||
if (this.module.handlerData.updateStatus) {
|
||||
this.module.handlerData.updateStatus(status);
|
||||
|
|
|
@ -197,11 +197,9 @@ export class CoreCourseHelperProvider {
|
|||
result.status = CoreConstants.DOWNLOADING;
|
||||
}
|
||||
|
||||
section.downloadStatus = result.status;
|
||||
section.canCheckUpdates = this.prefetchDelegate.canCheckUpdates();
|
||||
// Set this section data.
|
||||
section.showDownload = result.status === CoreConstants.NOT_DOWNLOADED;
|
||||
section.showRefresh = result.status === CoreConstants.OUTDATED ||
|
||||
(!this.prefetchDelegate.canCheckUpdates() && result.status === CoreConstants.DOWNLOADED);
|
||||
|
||||
if (result.status !== CoreConstants.DOWNLOADING || !this.prefetchDelegate.isBeingDownloaded(section.id)) {
|
||||
section.isDownloading = false;
|
||||
section.total = 0;
|
||||
|
@ -250,9 +248,8 @@ export class CoreCourseHelperProvider {
|
|||
return Promise.all(promises).then(() => {
|
||||
if (allSectionsSection) {
|
||||
// Set "All sections" data.
|
||||
allSectionsSection.showDownload = allSectionsStatus === CoreConstants.NOT_DOWNLOADED;
|
||||
allSectionsSection.showRefresh = allSectionsStatus === CoreConstants.OUTDATED ||
|
||||
(!this.prefetchDelegate.canCheckUpdates() && allSectionsStatus === CoreConstants.DOWNLOADED);
|
||||
allSectionsSection.downloadStatus = allSectionsStatus;
|
||||
allSectionsSection.canCheckUpdates = this.prefetchDelegate.canCheckUpdates();
|
||||
allSectionsSection.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
|
||||
}
|
||||
}).finally(() => {
|
||||
|
@ -981,7 +978,7 @@ export class CoreCourseHelperProvider {
|
|||
*/
|
||||
getCourseStatusIconAndTitleFromStatus(status: string): {icon: string, title: string} {
|
||||
if (status == CoreConstants.DOWNLOADED) {
|
||||
// Always show refresh icon, we cannot knew if there's anything new in course options.
|
||||
// Always show refresh icon, we cannot know if there's anything new in course options.
|
||||
return {
|
||||
icon: 'refresh',
|
||||
title: 'core.course.refreshcourse'
|
||||
|
@ -1330,9 +1327,8 @@ export class CoreCourseHelperProvider {
|
|||
|
||||
return this.utils.allPromises(promises).then(() => {
|
||||
// Set "All sections" data.
|
||||
section.showDownload = allSectionsStatus === CoreConstants.NOT_DOWNLOADED;
|
||||
section.showRefresh = allSectionsStatus === CoreConstants.OUTDATED ||
|
||||
(!this.prefetchDelegate.canCheckUpdates() && allSectionsStatus === CoreConstants.DOWNLOADED);
|
||||
section.downloadStatus = allSectionsStatus;
|
||||
section.canCheckUpdates = this.prefetchDelegate.canCheckUpdates();
|
||||
section.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
|
||||
}).finally(() => {
|
||||
section.isDownloading = false;
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
"dismiss": "Dismiss",
|
||||
"done": "Done",
|
||||
"download": "Download",
|
||||
"downloaded": "Downloaded",
|
||||
"downloading": "Downloading",
|
||||
"edit": "Edit",
|
||||
"emptysplit": "This page will appear blank if the left panel is empty or is loading.",
|
||||
|
|
Loading…
Reference in New Issue