commit
2d9e24652b
|
@ -1390,6 +1390,7 @@
|
||||||
"core.course.allsections": "local_moodlemobileapp",
|
"core.course.allsections": "local_moodlemobileapp",
|
||||||
"core.course.askadmintosupport": "local_moodlemobileapp",
|
"core.course.askadmintosupport": "local_moodlemobileapp",
|
||||||
"core.course.availablespace": "local_moodlemobileapp",
|
"core.course.availablespace": "local_moodlemobileapp",
|
||||||
|
"core.course.cannotdeletewhiledownloading": "local_moodlemobileapp",
|
||||||
"core.course.confirmdeletemodulefiles": "local_moodlemobileapp",
|
"core.course.confirmdeletemodulefiles": "local_moodlemobileapp",
|
||||||
"core.course.confirmdownload": "local_moodlemobileapp",
|
"core.course.confirmdownload": "local_moodlemobileapp",
|
||||||
"core.course.confirmdownloadunknownsize": "local_moodlemobileapp",
|
"core.course.confirmdownloadunknownsize": "local_moodlemobileapp",
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
||||||
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
<core-context-menu-item [priority]="500" *ngIf="canAdd" [content]="'addon.mod_data.addentries' | translate" [iconAction]="'add'" (action)="gotoAddEntries($event)"></core-context-menu-item>
|
<core-context-menu-item [priority]="500" *ngIf="canAdd" [content]="'addon.mod_data.addentries' | translate" [iconAction]="'add'" (action)="gotoAddEntries($event)"></core-context-menu-item>
|
||||||
<core-context-menu-item [priority]="400" *ngIf="firstEntry" [content]="'addon.mod_data.single' | translate" [iconAction]="'document'" (action)="gotoEntry(firstEntry)"></core-context-menu-item>
|
<core-context-menu-item [priority]="400" *ngIf="firstEntry" [content]="'addon.mod_data.single' | translate" [iconAction]="'document'" (action)="gotoEntry(firstEntry)"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="300" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="300" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="200" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="200" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl" [iconAction]="'open'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl" [iconAction]="'open'"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate" (action)="expandDescription()" [iconAction]="'arrow-forward'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="description" [priority]="800" [content]="'core.moduleintro' | translate" (action)="expandDescription()" [iconAction]="'arrow-forward'"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="!path" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="!subfolder" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
@ -17,11 +17,11 @@
|
||||||
|
|
||||||
<ion-list *ngIf="contents && contents.length > 0">
|
<ion-list *ngIf="contents && contents.length > 0">
|
||||||
<ng-container *ngFor="let file of contents">
|
<ng-container *ngFor="let file of contents">
|
||||||
<a *ngIf="file.type === 'folder'" ion-item class="item-media" navPush="AddonModFolderIndexPage" [navParams]="{path: file.filepath, courseId: courseId, module: file}">
|
<a *ngIf="file.type === 'folder'" ion-item class="item-media" navPush="AddonModFolderIndexPage" [navParams]="{subfolder: file, courseId: courseId, module: module, folderInstance: folderInstance}">
|
||||||
<ion-icon name="folder" item-start></ion-icon>
|
<ion-icon name="folder" item-start></ion-icon>
|
||||||
<h2>{{file.name}}</h2>
|
<h2>{{file.name}}</h2>
|
||||||
</a>
|
</a>
|
||||||
<core-file *ngIf="file.type !== 'folder'" [file]="file" [component]="component" [componentId]="file.contextid"></core-file>
|
<core-file *ngIf="file.type !== 'folder'" [file]="file" [component]="component" [componentId]="componentId"></core-file>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ion-list>
|
</ion-list>
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,8 @@ import { AddonModFolderHelperProvider } from '../../providers/helper';
|
||||||
templateUrl: 'addon-mod-folder-index.html',
|
templateUrl: 'addon-mod-folder-index.html',
|
||||||
})
|
})
|
||||||
export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceComponent {
|
export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceComponent {
|
||||||
@Input() path: string; // For subfolders. Use the path instead of a boolean so Angular detects them as different states.
|
@Input() folderInstance?: any; // The mod_folder instance.
|
||||||
|
@Input() subfolder?: any; // Subfolder to show.
|
||||||
|
|
||||||
component = AddonModFolderProvider.COMPONENT;
|
component = AddonModFolderProvider.COMPONENT;
|
||||||
canGetFolder: boolean;
|
canGetFolder: boolean;
|
||||||
|
@ -48,9 +49,9 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
||||||
|
|
||||||
this.canGetFolder = this.folderProvider.isGetFolderWSAvailable();
|
this.canGetFolder = this.folderProvider.isGetFolderWSAvailable();
|
||||||
|
|
||||||
if (this.path) {
|
if (this.subfolder) {
|
||||||
// Subfolder. Use module param.
|
// Subfolder. Use module param.
|
||||||
this.showModuleData(this.module, this.module.contents);
|
this.showModuleData(this.subfolder.contents);
|
||||||
this.loaded = true;
|
this.loaded = true;
|
||||||
this.refreshIcon = 'refresh';
|
this.refreshIcon = 'refresh';
|
||||||
} else {
|
} else {
|
||||||
|
@ -77,15 +78,14 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convenience function to set scope data using module.
|
* Convenience function to set data to display.
|
||||||
* @param module Module to show.
|
*
|
||||||
|
* @param folderContents Contents to show.
|
||||||
*/
|
*/
|
||||||
protected showModuleData(module: any, folderContents: any): void {
|
protected showModuleData(folderContents: any): void {
|
||||||
this.description = module.intro || module.description;
|
this.description = this.folderInstance ? this.folderInstance.intro : this.module.description;
|
||||||
|
|
||||||
this.dataRetrieved.emit(module);
|
if (this.subfolder) {
|
||||||
|
|
||||||
if (this.path) {
|
|
||||||
// Subfolder.
|
// Subfolder.
|
||||||
this.contents = folderContents;
|
this.contents = folderContents;
|
||||||
} else {
|
} else {
|
||||||
|
@ -107,25 +107,29 @@ export class AddonModFolderIndexComponent extends CoreCourseModuleMainResourceCo
|
||||||
promise = this.folderProvider.getFolder(this.courseId, this.module.id).then((folder) => {
|
promise = this.folderProvider.getFolder(this.courseId, this.module.id).then((folder) => {
|
||||||
return this.courseProvider.loadModuleContents(this.module, this.courseId, undefined, false, refresh).then(() => {
|
return this.courseProvider.loadModuleContents(this.module, this.courseId, undefined, false, refresh).then(() => {
|
||||||
folderContents = this.module.contents;
|
folderContents = this.module.contents;
|
||||||
|
this.folderInstance = folder;
|
||||||
|
|
||||||
return folder;
|
return folder;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
promise = this.courseProvider.getModule(this.module.id, this.courseId).then((folder) => {
|
promise = this.courseProvider.getModule(this.module.id, this.courseId).then((module) => {
|
||||||
if (!folder.contents.length && this.module.contents.length && !this.appProvider.isOnline()) {
|
if (!module.contents.length && this.module.contents.length && !this.appProvider.isOnline()) {
|
||||||
// The contents might be empty due to a cached data. Use the old ones.
|
// The contents might be empty due to a cached data. Use the old ones.
|
||||||
folder.contents = this.module.contents;
|
module.contents = this.module.contents;
|
||||||
}
|
}
|
||||||
this.module = folder;
|
this.module = module;
|
||||||
folderContents = folder.contents;
|
folderContents = module.contents;
|
||||||
|
|
||||||
return folder;
|
return module;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return promise.then((folder) => {
|
return promise.then(() => {
|
||||||
this.showModuleData(folder, folderContents);
|
|
||||||
|
this.dataRetrieved.emit(this.folderInstance || this.module);
|
||||||
|
|
||||||
|
this.showModuleData(folderContents);
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.fillContextMenu(refresh);
|
this.fillContextMenu(refresh);
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,9 +8,9 @@
|
||||||
</ion-navbar>
|
</ion-navbar>
|
||||||
</ion-header>
|
</ion-header>
|
||||||
<ion-content>
|
<ion-content>
|
||||||
<ion-refresher [enabled]="!path && folderComponent.loaded" (ionRefresh)="folderComponent.doRefresh($event)">
|
<ion-refresher [enabled]="!subfolder && folderComponent.loaded" (ionRefresh)="folderComponent.doRefresh($event)">
|
||||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||||
</ion-refresher>
|
</ion-refresher>
|
||||||
|
|
||||||
<addon-mod-folder-index [module]="module" [courseId]="courseId" [path]="path" (dataRetrieved)="updateData($event)"></addon-mod-folder-index>
|
<addon-mod-folder-index [module]="module" [courseId]="courseId" [folderInstance]="folderInstance" [subfolder]="subfolder" (dataRetrieved)="updateData($event)"></addon-mod-folder-index>
|
||||||
</ion-content>
|
</ion-content>
|
||||||
|
|
|
@ -30,13 +30,15 @@ export class AddonModFolderIndexPage {
|
||||||
title: string;
|
title: string;
|
||||||
module: any;
|
module: any;
|
||||||
courseId: number;
|
courseId: number;
|
||||||
path: string;
|
folderInstance: any;
|
||||||
|
subfolder: any;
|
||||||
|
|
||||||
constructor(navParams: NavParams) {
|
constructor(navParams: NavParams) {
|
||||||
this.module = navParams.get('module') || {};
|
this.module = navParams.get('module') || {};
|
||||||
this.courseId = navParams.get('courseId');
|
this.courseId = navParams.get('courseId');
|
||||||
this.path = navParams.get('path');
|
this.folderInstance = navParams.get('folderInstance');
|
||||||
this.title = this.module.name;
|
this.subfolder = navParams.get('subfolder');
|
||||||
|
this.title = this.subfolder ? this.subfolder.name : this.module.name;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !(hasOffline || hasOfflineRatings) && isOnline" [priority]="700" [content]="'addon.mod_forum.refreshdiscussions' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !(hasOffline || hasOfflineRatings) && isOnline" [priority]="700" [content]="'addon.mod_forum.refreshdiscussions' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="sortingAvailable" [priority]="300" [content]="'core.sort' | translate" (action)="showSortOrderSelector($event)" iconAction="fa-sort"></core-context-menu-item>
|
<core-context-menu-item *ngIf="sortingAvailable" [priority]="300" [content]="'core.sort' | translate" (action)="showSortOrderSelector($event)" iconAction="fa-sort"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="650" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && (hasOffline || hasOfflineRatings) && isOnline" [priority]="650" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="canAdd" [priority]="600" [content]="'addon.mod_glossary.addentry' | translate" (action)="openNewEntry()" iconAction="add"></core-context-menu-item>
|
<core-context-menu-item *ngIf="canAdd" [priority]="600" [content]="'addon.mod_glossary.addentry' | translate" (action)="openNewEntry()" iconAction="add"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
||||||
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
||||||
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
<core-context-menu-item *ngIf="blog" [priority]="750" content="{{'addon.blog.blog' | translate}}" [iconAction]="'fa-newspaper-o'" (action)="gotoBlog($event)"></core-context-menu-item>
|
||||||
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="600" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
<core-context-menu-item *ngIf="canEdit && (isOnline || pageIsOffline)" [priority]="590" [content]="'core.edit' | translate" iconAction="create" (action)="goToEditPage()"></core-context-menu-item>
|
<core-context-menu-item *ngIf="canEdit && (isOnline || pageIsOffline)" [priority]="590" [content]="'core.edit' | translate" iconAction="create" (action)="goToEditPage()"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="canEdit" [priority]="580" [content]="'addon.mod_wiki.createpage' | translate" iconAction="add" (action)="goToNewPage()"></core-context-menu-item>
|
<core-context-menu-item *ngIf="canEdit" [priority]="580" [content]="'addon.mod_wiki.createpage' | translate" iconAction="add" (action)="goToNewPage()"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && !hasOffline && isOnline" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="loaded && hasOffline && isOnline" [priority]="600" [content]="'core.settings.synchronizenow' | translate" (action)="doRefresh(null, $event, true)" [iconAction]="syncIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item *ngIf="prefetchStatusIcon" [priority]="500" [content]="prefetchText" (action)="prefetch($event)" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="size" [priority]="400" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -1390,6 +1390,7 @@
|
||||||
"core.course.allsections": "All sections",
|
"core.course.allsections": "All sections",
|
||||||
"core.course.askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.",
|
"core.course.askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.",
|
||||||
"core.course.availablespace": " You currently have about {{available}} free space.",
|
"core.course.availablespace": " You currently have about {{available}} free space.",
|
||||||
|
"core.course.cannotdeletewhiledownloading": "Files cannot be deleted while the activity is being downloaded. Please wait for the download to finish.",
|
||||||
"core.course.confirmdeletemodulefiles": "Are you sure you want to delete these files?",
|
"core.course.confirmdeletemodulefiles": "Are you sure you want to delete these files?",
|
||||||
"core.course.confirmdownload": "You are about to download {{size}}.{{availableSpace}} Are you sure you want to continue?",
|
"core.course.confirmdownload": "You are about to download {{size}}.{{availableSpace}} Are you sure you want to continue?",
|
||||||
"core.course.confirmdownloadunknownsize": "It was not possible to calculate the size of the download.{{availableSpace}} Are you sure you want to continue?",
|
"core.course.confirmdownloadunknownsize": "It was not possible to calculate the size of the download.{{availableSpace}} Are you sure you want to continue?",
|
||||||
|
|
|
@ -49,6 +49,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
|
|
||||||
protected isDestroyed; // Whether the component is destroyed, used when calling fillContextMenu.
|
protected isDestroyed; // Whether the component is destroyed, used when calling fillContextMenu.
|
||||||
protected contextMenuStatusObserver; // Observer of package status changed, used when calling fillContextMenu.
|
protected contextMenuStatusObserver; // Observer of package status changed, used when calling fillContextMenu.
|
||||||
|
protected contextFileStatusObserver; // Observer of file status changed, used when calling fillContextMenu.
|
||||||
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
|
protected fetchContentDefaultError = 'core.course.errorgetmodule'; // Default error to show when loading contents.
|
||||||
protected isCurrentView: boolean; // Whether the component is in the current view.
|
protected isCurrentView: boolean; // Whether the component is in the current view.
|
||||||
|
|
||||||
|
@ -260,9 +261,17 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Confirm and remove downloaded files.
|
* Confirm and remove downloaded files.
|
||||||
|
*
|
||||||
|
* @param done Function to call when done.
|
||||||
*/
|
*/
|
||||||
removeFiles(): void {
|
removeFiles(done?: () => void): void {
|
||||||
this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId);
|
if (this.prefetchStatus == CoreConstants.DOWNLOADING) {
|
||||||
|
this.domUtils.showAlertTranslated(null, 'core.course.cannotdeletewhiledownloading');
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.courseHelper.confirmAndRemoveFiles(this.module, this.courseId, done);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -285,6 +294,7 @@ export class CoreCourseModuleMainResourceComponent implements OnInit, OnDestroy,
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.isDestroyed = true;
|
this.isDestroyed = true;
|
||||||
this.contextMenuStatusObserver && this.contextMenuStatusObserver.off();
|
this.contextMenuStatusObserver && this.contextMenuStatusObserver.off();
|
||||||
|
this.contextFileStatusObserver && this.contextFileStatusObserver.off();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
"allsections": "All sections",
|
"allsections": "All sections",
|
||||||
"askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.",
|
"askadmintosupport": "Contact the site administrator and tell them you want to use this activity with the Moodle Mobile app.",
|
||||||
"availablespace": " You currently have about {{available}} free space.",
|
"availablespace": " You currently have about {{available}} free space.",
|
||||||
|
"cannotdeletewhiledownloading": "Files cannot be deleted while the activity is being downloaded. Please wait for the download to finish.",
|
||||||
"confirmdeletemodulefiles": "Are you sure you want to delete these files?",
|
"confirmdeletemodulefiles": "Are you sure you want to delete these files?",
|
||||||
"confirmdownload": "You are about to download {{size}}.{{availableSpace}} Are you sure you want to continue?",
|
"confirmdownload": "You are about to download {{size}}.{{availableSpace}} Are you sure you want to continue?",
|
||||||
"confirmdownloadunknownsize": "It was not possible to calculate the size of the download.{{availableSpace}} Are you sure you want to continue?",
|
"confirmdownloadunknownsize": "It was not possible to calculate the size of the download.{{availableSpace}} Are you sure you want to continue?",
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Injectable, Injector } from '@angular/core';
|
import { Injectable, Injector } from '@angular/core';
|
||||||
import { NavController } from 'ionic-angular';
|
import { NavController, Loading } from 'ionic-angular';
|
||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { CoreAppProvider } from '@providers/app';
|
import { CoreAppProvider } from '@providers/app';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreFileProvider } from '@providers/file';
|
import { CoreFileProvider } from '@providers/file';
|
||||||
import { CoreFilepoolProvider } from '@providers/filepool';
|
import { CoreFilepoolProvider, CoreFilepoolComponentFileEventData } from '@providers/filepool';
|
||||||
import { CoreFileHelperProvider } from '@providers/file-helper';
|
import { CoreFileHelperProvider } from '@providers/file-helper';
|
||||||
import { CoreSitesProvider } from '@providers/sites';
|
import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
@ -408,16 +408,29 @@ export class CoreCourseHelperProvider {
|
||||||
*
|
*
|
||||||
* @param module Module to remove the files.
|
* @param module Module to remove the files.
|
||||||
* @param courseId Course ID the module belongs to.
|
* @param courseId Course ID the module belongs to.
|
||||||
|
* @param done Function to call when done. It will close the context menu.
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
confirmAndRemoveFiles(module: any, courseId: number): Promise<any> {
|
async confirmAndRemoveFiles(module: any, courseId: number, done?: () => void): Promise<void> {
|
||||||
return this.domUtils.showDeleteConfirm('core.course.confirmdeletemodulefiles').then(() => {
|
let modal: Loading;
|
||||||
return this.prefetchDelegate.removeModuleFiles(module, courseId);
|
|
||||||
}).catch((error) => {
|
try {
|
||||||
|
|
||||||
|
await this.domUtils.showDeleteConfirm('core.course.confirmdeletemodulefiles');
|
||||||
|
|
||||||
|
modal = this.domUtils.showModalLoading();
|
||||||
|
|
||||||
|
await this.prefetchDelegate.removeModuleFiles(module, courseId);
|
||||||
|
|
||||||
|
done && done();
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
this.domUtils.showErrorModal(error);
|
this.domUtils.showErrorModal(error);
|
||||||
}
|
}
|
||||||
});
|
} finally {
|
||||||
|
modal && modal.dismiss();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -800,6 +813,8 @@ export class CoreCourseHelperProvider {
|
||||||
* @return Promise resolved when done.
|
* @return Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
fillContextMenu(instance: any, module: any, courseId: number, invalidateCache?: boolean, component?: string): Promise<any> {
|
fillContextMenu(instance: any, module: any, courseId: number, invalidateCache?: boolean, component?: string): Promise<any> {
|
||||||
|
const siteId = this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
return this.getModulePrefetchInfo(module, courseId, invalidateCache, component).then((moduleInfo) => {
|
return this.getModulePrefetchInfo(module, courseId, invalidateCache, component).then((moduleInfo) => {
|
||||||
instance.size = moduleInfo.size > 0 ? moduleInfo.sizeReadable : 0;
|
instance.size = moduleInfo.size > 0 ? moduleInfo.sizeReadable : 0;
|
||||||
instance.prefetchStatusIcon = moduleInfo.statusIcon;
|
instance.prefetchStatusIcon = moduleInfo.statusIcon;
|
||||||
|
@ -825,7 +840,32 @@ export class CoreCourseHelperProvider {
|
||||||
if (data.componentId == module.id && data.component == component) {
|
if (data.componentId == module.id && data.component == component) {
|
||||||
this.fillContextMenu(instance, module, courseId, false, component);
|
this.fillContextMenu(instance, module, courseId, false, component);
|
||||||
}
|
}
|
||||||
}, this.sitesProvider.getCurrentSiteId());
|
}, siteId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof instance.contextFileStatusObserver == 'undefined' && component) {
|
||||||
|
// Debounce the update size function to prevent too many calls when downloading or deleting a whole activity.
|
||||||
|
const debouncedUpdateSize = this.utils.debounce(() => {
|
||||||
|
this.prefetchDelegate.getModuleDownloadedSize(module, courseId).then((moduleSize) => {
|
||||||
|
instance.size = moduleSize > 0 ? this.textUtils.bytesToSize(moduleSize, 2) : 0;
|
||||||
|
});
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
instance.contextFileStatusObserver = this.eventsProvider.on(CoreEventsProvider.COMPONENT_FILE_ACTION,
|
||||||
|
(data: CoreFilepoolComponentFileEventData) => {
|
||||||
|
|
||||||
|
if (data.component != component || data.componentId != module.id) {
|
||||||
|
// The event doesn't belong to this component, ignore.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.filepoolProvider.isFileEventDownloadedOrDeleted(data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the module size.
|
||||||
|
debouncedUpdateSize();
|
||||||
|
}, siteId);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { CoreEventsProvider } from '@providers/events';
|
import { CoreEventsProvider } from '@providers/events';
|
||||||
import { CoreFileProvider } from '@providers/file';
|
import { CoreFileProvider } from '@providers/file';
|
||||||
import { CoreFilepoolProvider } from '@providers/filepool';
|
import { CoreFilepoolProvider, CoreFilepoolComponentFileEventData } from '@providers/filepool';
|
||||||
import { CoreLoggerProvider } from '@providers/logger';
|
import { CoreLoggerProvider } from '@providers/logger';
|
||||||
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
import { CoreSitesProvider, CoreSiteSchema } from '@providers/sites';
|
||||||
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
import { CoreTimeUtilsProvider } from '@providers/utils/time';
|
||||||
|
@ -276,6 +276,15 @@ export class CoreCourseModulePrefetchDelegate extends CoreDelegate {
|
||||||
eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => {
|
eventsProvider.on(CoreEventsProvider.PACKAGE_STATUS_CHANGED, (data) => {
|
||||||
this.updateStatusCache(data.status, data.component, data.componentId);
|
this.updateStatusCache(data.status, data.component, data.componentId);
|
||||||
}, this.sitesProvider.getCurrentSiteId());
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
|
|
||||||
|
// If a file inside a module is downloaded/deleted, clear the corresponding cache.
|
||||||
|
eventsProvider.on(CoreEventsProvider.COMPONENT_FILE_ACTION, (data: CoreFilepoolComponentFileEventData) => {
|
||||||
|
if (!this.filepoolProvider.isFileEventDownloadedOrDeleted(data)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.statusCache.invalidate(this.filepoolProvider.getPackageId(data.component, data.componentId));
|
||||||
|
}, this.sitesProvider.getCurrentSiteId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
<core-context-menu-item [hidden]="!displayDescription || !description || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displayDescription === false)" [priority]="800" [content]="'core.moduleintro' | translate" (action)="expandDescription()" [iconAction]="'arrow-forward'"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!displayDescription || !description || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displayDescription === false)" [priority]="800" [content]="'core.moduleintro' | translate" (action)="expandDescription()" [iconAction]="'arrow-forward'"></core-context-menu-item>
|
||||||
<core-context-menu-item [hidden]="!displayRefresh || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displayRefresh === false)" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!displayRefresh || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displayRefresh === false)" [priority]="700" [content]="'core.refresh' | translate" (action)="doRefresh(null, $event)" [iconAction]="refreshIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item [hidden]="!displayPrefetch || !prefetchStatusIcon || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displayPrefetch === false)" [priority]="600" [content]="prefetchText" (action)="prefetch()" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!displayPrefetch || !prefetchStatusIcon || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displayPrefetch === false)" [priority]="600" [content]="prefetchText" (action)="prefetch()" [iconAction]="prefetchStatusIcon" [closeOnClick]="false"></core-context-menu-item>
|
||||||
<core-context-menu-item [hidden]="!displaySize || !size || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displaySize === false)" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles()" [iconAction]="'trash'"></core-context-menu-item>
|
<core-context-menu-item [hidden]="!displaySize || !size || (content && content.compileComponent && content.compileComponent.componentInstance && content.compileComponent.componentInstance.displaySize === false)" [priority]="500" [content]="'core.removefiles' | translate:{$a: size}" [iconDescription]="'cube'" (action)="removeFiles($event)" [iconAction]="'trash'" [closeOnClick]="false"></core-context-menu-item>
|
||||||
</core-context-menu>
|
</core-context-menu>
|
||||||
</core-navbar-buttons>
|
</core-navbar-buttons>
|
||||||
|
|
||||||
|
|
|
@ -47,6 +47,7 @@ export class CoreEventsProvider {
|
||||||
static PACKAGE_STATUS_CHANGED = 'package_status_changed';
|
static PACKAGE_STATUS_CHANGED = 'package_status_changed';
|
||||||
static COURSE_STATUS_CHANGED = 'course_status_changed';
|
static COURSE_STATUS_CHANGED = 'course_status_changed';
|
||||||
static SECTION_STATUS_CHANGED = 'section_status_changed';
|
static SECTION_STATUS_CHANGED = 'section_status_changed';
|
||||||
|
static COMPONENT_FILE_ACTION = 'component_file_action';
|
||||||
static SITE_PLUGINS_LOADED = 'site_plugins_loaded';
|
static SITE_PLUGINS_LOADED = 'site_plugins_loaded';
|
||||||
static SITE_PLUGINS_COURSE_RESTRICT_UPDATED = 'site_plugins_course_restrict_updated';
|
static SITE_PLUGINS_COURSE_RESTRICT_UPDATED = 'site_plugins_course_restrict_updated';
|
||||||
static LOGIN_SITE_CHECKED = 'login_site_checked';
|
static LOGIN_SITE_CHECKED = 'login_site_checked';
|
||||||
|
|
|
@ -144,7 +144,7 @@ export interface CoreFilepoolQueueEntry {
|
||||||
/**
|
/**
|
||||||
* File links (to link the file to components and componentIds).
|
* File links (to link the file to components and componentIds).
|
||||||
*/
|
*/
|
||||||
links?: any[];
|
links?: CoreFilepoolComponentLink[];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,6 +197,66 @@ export interface CoreFilepoolPackageEntry {
|
||||||
extra?: string;
|
extra?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A component link.
|
||||||
|
*/
|
||||||
|
export interface CoreFilepoolComponentLink {
|
||||||
|
/**
|
||||||
|
* Link's component.
|
||||||
|
*/
|
||||||
|
component: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Link's componentId.
|
||||||
|
*/
|
||||||
|
componentId?: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File actions.
|
||||||
|
*/
|
||||||
|
export const enum CoreFilepoolFileActions {
|
||||||
|
DOWNLOAD = 'download',
|
||||||
|
DOWNLOADING = 'downloading',
|
||||||
|
DELETED = 'deleted',
|
||||||
|
OUTDATED = 'outdated',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data sent to file events.
|
||||||
|
*/
|
||||||
|
export interface CoreFilepoolFileEventData {
|
||||||
|
/**
|
||||||
|
* The file ID.
|
||||||
|
*/
|
||||||
|
fileId: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The file ID.
|
||||||
|
*/
|
||||||
|
action: CoreFilepoolFileActions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the action was a success. Only for DOWNLOAD action.
|
||||||
|
*/
|
||||||
|
success?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Data sent to component file events.
|
||||||
|
*/
|
||||||
|
export interface CoreFilepoolComponentFileEventData extends CoreFilepoolFileEventData {
|
||||||
|
/**
|
||||||
|
* The component.
|
||||||
|
*/
|
||||||
|
component: string;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The component ID.
|
||||||
|
*/
|
||||||
|
componentId: string | number;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Factory for handling downloading files and retrieve downloaded files.
|
* Factory for handling downloading files and retrieve downloaded files.
|
||||||
*
|
*
|
||||||
|
@ -495,7 +555,7 @@ export class CoreFilepoolProvider {
|
||||||
* @param links Array of objects containing the component and optionally componentId.
|
* @param links Array of objects containing the component and optionally componentId.
|
||||||
* @return Promise resolved on success.
|
* @return Promise resolved on success.
|
||||||
*/
|
*/
|
||||||
protected addFileLinks(siteId: string, fileId: string, links: any[]): Promise<any> {
|
protected addFileLinks(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): Promise<any> {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
links.forEach((link) => {
|
links.forEach((link) => {
|
||||||
promises.push(this.addFileLink(siteId, fileId, link.component, link.componentId));
|
promises.push(this.addFileLink(siteId, fileId, link.component, link.componentId));
|
||||||
|
@ -575,7 +635,9 @@ export class CoreFilepoolProvider {
|
||||||
* @return Promise resolved when the file is downloaded.
|
* @return Promise resolved when the file is downloaded.
|
||||||
*/
|
*/
|
||||||
protected async addToQueue(siteId: string, fileId: string, url: string, priority: number, revision: number,
|
protected async addToQueue(siteId: string, fileId: string, url: string, priority: number, revision: number,
|
||||||
timemodified: number, filePath: string, onProgress?: (event: any) => any, options: any = {}, link?: any): Promise<any> {
|
timemodified: number, filePath: string, onProgress?: (event: any) => any, options: any = {},
|
||||||
|
link?: CoreFilepoolComponentLink): Promise<any> {
|
||||||
|
|
||||||
await this.dbReady;
|
await this.dbReady;
|
||||||
|
|
||||||
this.logger.debug(`Adding ${fileId} to the queue`);
|
this.logger.debug(`Adding ${fileId} to the queue`);
|
||||||
|
@ -596,7 +658,7 @@ export class CoreFilepoolProvider {
|
||||||
|
|
||||||
// Check if the queue is running.
|
// Check if the queue is running.
|
||||||
this.checkQueueProcessing();
|
this.checkQueueProcessing();
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, link ? [link] : []);
|
||||||
|
|
||||||
return this.getQueuePromise(siteId, fileId, true, onProgress);
|
return this.getQueuePromise(siteId, fileId, true, onProgress);
|
||||||
}
|
}
|
||||||
|
@ -623,7 +685,6 @@ export class CoreFilepoolProvider {
|
||||||
await this.dbReady;
|
await this.dbReady;
|
||||||
|
|
||||||
let fileId,
|
let fileId,
|
||||||
link,
|
|
||||||
queueDeferred;
|
queueDeferred;
|
||||||
|
|
||||||
if (!this.fileProvider.isAvailable()) {
|
if (!this.fileProvider.isAvailable()) {
|
||||||
|
@ -651,12 +712,7 @@ export class CoreFilepoolProvider {
|
||||||
const primaryKey = { siteId: siteId, fileId: fileId };
|
const primaryKey = { siteId: siteId, fileId: fileId };
|
||||||
|
|
||||||
// Set up the component.
|
// Set up the component.
|
||||||
if (typeof component != 'undefined') {
|
const link = this.createComponentLink(component, componentId);
|
||||||
link = {
|
|
||||||
component: component,
|
|
||||||
componentId: this.fixComponentId(componentId)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Retrieve the queue deferred now if it exists.
|
// Retrieve the queue deferred now if it exists.
|
||||||
// This is to prevent errors if file is removed from queue while we're checking if the file is in queue.
|
// This is to prevent errors if file is removed from queue while we're checking if the file is in queue.
|
||||||
|
@ -866,7 +922,7 @@ export class CoreFilepoolProvider {
|
||||||
return this.sitesProvider.getSiteDb(siteId).then((db) => {
|
return this.sitesProvider.getSiteDb(siteId).then((db) => {
|
||||||
const conditions = {
|
const conditions = {
|
||||||
component: component,
|
component: component,
|
||||||
componentId: componentId || ''
|
componentId: this.fixComponentId(componentId)
|
||||||
};
|
};
|
||||||
|
|
||||||
return db.countRecords(this.LINKS_TABLE, conditions).then((count) => {
|
return db.countRecords(this.LINKS_TABLE, conditions).then((count) => {
|
||||||
|
@ -877,6 +933,34 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare a component link.
|
||||||
|
*
|
||||||
|
* @param component The component to link the file to.
|
||||||
|
* @param componentId An ID to use in conjunction with the component.
|
||||||
|
* @return Link, null if nothing to link.
|
||||||
|
*/
|
||||||
|
protected createComponentLink(component: string, componentId?: string | number): CoreFilepoolComponentLink {
|
||||||
|
if (typeof component != 'undefined' && component != null) {
|
||||||
|
return { component: component, componentId: this.fixComponentId(componentId) };
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare list of links from component and componentId.
|
||||||
|
*
|
||||||
|
* @param component The component to link the file to.
|
||||||
|
* @param componentId An ID to use in conjunction with the component.
|
||||||
|
* @return Links.
|
||||||
|
*/
|
||||||
|
protected createComponentLinks(component: string, componentId?: string | number): CoreFilepoolComponentLink[] {
|
||||||
|
const link = this.createComponentLink(component, componentId);
|
||||||
|
|
||||||
|
return link ? [link] : [];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given the current status of a list of packages and the status of one of the packages,
|
* Given the current status of a list of packages and the status of one of the packages,
|
||||||
* determine the new status for the list of packages. The status of a list of packages is:
|
* determine the new status for the list of packages. The status of a list of packages is:
|
||||||
|
@ -1179,8 +1263,9 @@ export class CoreFilepoolProvider {
|
||||||
downloadUrl(siteId: string, fileUrl: string, ignoreStale?: boolean, component?: string, componentId?: string | number,
|
downloadUrl(siteId: string, fileUrl: string, ignoreStale?: boolean, component?: string, componentId?: string | number,
|
||||||
timemodified: number = 0, onProgress?: (event: any) => any, filePath?: string, options: any = {}, revision?: number)
|
timemodified: number = 0, onProgress?: (event: any) => any, filePath?: string, options: any = {}, revision?: number)
|
||||||
: Promise<any> {
|
: Promise<any> {
|
||||||
let fileId,
|
let fileId;
|
||||||
promise;
|
let promise;
|
||||||
|
let alreadyDownloaded = true;
|
||||||
|
|
||||||
if (this.fileProvider.isAvailable()) {
|
if (this.fileProvider.isAvailable()) {
|
||||||
return this.fixPluginfileURL(siteId, fileUrl).then((file) => {
|
return this.fixPluginfileURL(siteId, fileUrl).then((file) => {
|
||||||
|
@ -1193,18 +1278,22 @@ export class CoreFilepoolProvider {
|
||||||
options.revision = revision || this.getRevisionFromUrl(fileUrl);
|
options.revision = revision || this.getRevisionFromUrl(fileUrl);
|
||||||
fileId = this.getFileIdByUrl(fileUrl);
|
fileId = this.getFileIdByUrl(fileUrl);
|
||||||
|
|
||||||
|
const links = this.createComponentLinks(component, componentId);
|
||||||
|
|
||||||
return this.hasFileInPool(siteId, fileId).then((fileObject) => {
|
return this.hasFileInPool(siteId, fileId).then((fileObject) => {
|
||||||
|
|
||||||
if (typeof fileObject === 'undefined') {
|
if (typeof fileObject === 'undefined') {
|
||||||
// We do not have the file, download and add to pool.
|
// We do not have the file, download and add to pool.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, links);
|
||||||
|
alreadyDownloaded = false;
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
||||||
|
|
||||||
} else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) &&
|
} else if (this.isFileOutdated(fileObject, options.revision, options.timemodified) &&
|
||||||
this.appProvider.isOnline() && !ignoreStale) {
|
this.appProvider.isOnline() && !ignoreStale) {
|
||||||
// The file is outdated, force the download and update it.
|
// The file is outdated, force the download and update it.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, links);
|
||||||
|
alreadyDownloaded = false;
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
||||||
}
|
}
|
||||||
|
@ -1220,14 +1309,16 @@ export class CoreFilepoolProvider {
|
||||||
return response;
|
return response;
|
||||||
}, () => {
|
}, () => {
|
||||||
// The file was not found in the pool, weird.
|
// The file was not found in the pool, weird.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, links);
|
||||||
|
alreadyDownloaded = false;
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress, fileObject);
|
||||||
});
|
});
|
||||||
|
|
||||||
}, () => {
|
}, () => {
|
||||||
// The file is not in the pool just yet.
|
// The file is not in the pool just yet.
|
||||||
this.notifyFileDownloading(siteId, fileId);
|
this.notifyFileDownloading(siteId, fileId, links);
|
||||||
|
alreadyDownloaded = false;
|
||||||
|
|
||||||
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
return this.downloadForPoolByUrl(siteId, fileUrl, options, filePath, onProgress);
|
||||||
}).then((response) => {
|
}).then((response) => {
|
||||||
|
@ -1236,11 +1327,14 @@ export class CoreFilepoolProvider {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.notifyFileDownloaded(siteId, fileId);
|
|
||||||
|
if (!alreadyDownloaded) {
|
||||||
|
this.notifyFileDownloaded(siteId, fileId, links);
|
||||||
|
}
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}, (err) => {
|
}, (err) => {
|
||||||
this.notifyFileDownloadError(siteId, fileId);
|
this.notifyFileDownloadError(siteId, fileId, links);
|
||||||
|
|
||||||
return Promise.reject(err);
|
return Promise.reject(err);
|
||||||
});
|
});
|
||||||
|
@ -1404,10 +1498,16 @@ export class CoreFilepoolProvider {
|
||||||
protected getComponentFiles(db: SQLiteDB, component: string, componentId?: string | number): Promise<any[]> {
|
protected getComponentFiles(db: SQLiteDB, component: string, componentId?: string | number): Promise<any[]> {
|
||||||
const conditions = {
|
const conditions = {
|
||||||
component: component,
|
component: component,
|
||||||
componentId: componentId || ''
|
componentId: this.fixComponentId(componentId)
|
||||||
};
|
};
|
||||||
|
|
||||||
return db.getRecords(this.LINKS_TABLE, conditions);
|
return db.getRecords(this.LINKS_TABLE, conditions).then((items) => {
|
||||||
|
items.forEach((item) => {
|
||||||
|
item.componentId = this.fixComponentId(item.componentId);
|
||||||
|
});
|
||||||
|
|
||||||
|
return items;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1516,6 +1616,12 @@ export class CoreFilepoolProvider {
|
||||||
protected getFileLinks(siteId: string, fileId: string): Promise<any[]> {
|
protected getFileLinks(siteId: string, fileId: string): Promise<any[]> {
|
||||||
return this.sitesProvider.getSiteDb(siteId).then((db) => {
|
return this.sitesProvider.getSiteDb(siteId).then((db) => {
|
||||||
return db.getRecords(this.LINKS_TABLE, { fileId: fileId });
|
return db.getRecords(this.LINKS_TABLE, { fileId: fileId });
|
||||||
|
}).then((items) => {
|
||||||
|
items.forEach((item) => {
|
||||||
|
item.componentId = this.fixComponentId(item.componentId);
|
||||||
|
});
|
||||||
|
|
||||||
|
return items;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2385,6 +2491,17 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether a file action indicates a file was downloaded or deleted.
|
||||||
|
*
|
||||||
|
* @param data Event data.
|
||||||
|
* @return Whether downloaded or deleted.
|
||||||
|
*/
|
||||||
|
isFileEventDownloadedOrDeleted(data: CoreFilepoolFileEventData): boolean {
|
||||||
|
return (data.action == CoreFilepoolFileActions.DOWNLOAD && data.success == true) ||
|
||||||
|
data.action == CoreFilepoolFileActions.DELETED;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether a file is downloadable.
|
* Check whether a file is downloadable.
|
||||||
*
|
*
|
||||||
|
@ -2439,14 +2556,41 @@ export class CoreFilepoolProvider {
|
||||||
return !!entry.isexternalfile || (entry.revision < 1 && !entry.timemodified);
|
return !!entry.isexternalfile || (entry.revision < 1 && !entry.timemodified);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notify an action performed on a file to a list of components.
|
||||||
|
*
|
||||||
|
* @param siteId The site ID.
|
||||||
|
* @param eventData The file event data.
|
||||||
|
* @param links The links to the components.
|
||||||
|
*/
|
||||||
|
protected notifyFileActionToComponents(siteId: string, eventData: CoreFilepoolFileEventData,
|
||||||
|
links: CoreFilepoolComponentLink[]): void {
|
||||||
|
|
||||||
|
links.forEach((link) => {
|
||||||
|
const data: CoreFilepoolComponentFileEventData = Object.assign({
|
||||||
|
component: link.component,
|
||||||
|
componentId: link.componentId,
|
||||||
|
}, eventData);
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(CoreEventsProvider.COMPONENT_FILE_ACTION, data, siteId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Notify a file has been deleted.
|
* Notify a file has been deleted.
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDeleted(siteId: string, fileId: string): void {
|
protected notifyFileDeleted(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'deleted' });
|
const data: CoreFilepoolFileEventData = {
|
||||||
|
fileId: fileId,
|
||||||
|
action: CoreFilepoolFileActions.DELETED,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data);
|
||||||
|
this.notifyFileActionToComponents(siteId, data, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2454,9 +2598,17 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDownloaded(siteId: string, fileId: string): void {
|
protected notifyFileDownloaded(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'download', success: true });
|
const data: CoreFilepoolFileEventData = {
|
||||||
|
fileId: fileId,
|
||||||
|
action: CoreFilepoolFileActions.DOWNLOAD,
|
||||||
|
success: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data);
|
||||||
|
this.notifyFileActionToComponents(siteId, data, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2464,9 +2616,17 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDownloadError(siteId: string, fileId: string): void {
|
protected notifyFileDownloadError(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'download', success: false });
|
const data: CoreFilepoolFileEventData = {
|
||||||
|
fileId: fileId,
|
||||||
|
action: CoreFilepoolFileActions.DOWNLOAD,
|
||||||
|
success: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data);
|
||||||
|
this.notifyFileActionToComponents(siteId, data, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2474,9 +2634,17 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileDownloading(siteId: string, fileId: string): void {
|
protected notifyFileDownloading(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'downloading' });
|
const data: CoreFilepoolFileEventData = {
|
||||||
|
fileId: fileId,
|
||||||
|
action: CoreFilepoolFileActions.DOWNLOADING,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data);
|
||||||
|
this.notifyFileActionToComponents(siteId, data, links);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2484,9 +2652,16 @@ export class CoreFilepoolProvider {
|
||||||
*
|
*
|
||||||
* @param siteId The site ID.
|
* @param siteId The site ID.
|
||||||
* @param fileId The file ID.
|
* @param fileId The file ID.
|
||||||
|
* @param links The links to components.
|
||||||
*/
|
*/
|
||||||
protected notifyFileOutdated(siteId: string, fileId: string): void {
|
protected notifyFileOutdated(siteId: string, fileId: string, links: CoreFilepoolComponentLink[]): void {
|
||||||
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), { action: 'outdated' });
|
const data: CoreFilepoolFileEventData = {
|
||||||
|
fileId: fileId,
|
||||||
|
action: CoreFilepoolFileActions.OUTDATED,
|
||||||
|
};
|
||||||
|
|
||||||
|
this.eventsProvider.trigger(this.getFileEventName(siteId, fileId), data);
|
||||||
|
this.notifyFileActionToComponents(siteId, data, links);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -2612,7 +2787,6 @@ export class CoreFilepoolProvider {
|
||||||
}).finally(() => {
|
}).finally(() => {
|
||||||
this.treatQueueDeferred(siteId, fileId, true);
|
this.treatQueueDeferred(siteId, fileId, true);
|
||||||
});
|
});
|
||||||
this.notifyFileDownloaded(siteId, fileId);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -2627,7 +2801,7 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.treatQueueDeferred(siteId, fileId, true);
|
this.treatQueueDeferred(siteId, fileId, true);
|
||||||
this.notifyFileDownloaded(siteId, fileId);
|
this.notifyFileDownloaded(siteId, fileId, links);
|
||||||
|
|
||||||
// Wait for the item to be removed from queue before resolving the promise.
|
// Wait for the item to be removed from queue before resolving the promise.
|
||||||
// If the item could not be removed from queue we still resolve the promise.
|
// If the item could not be removed from queue we still resolve the promise.
|
||||||
|
@ -2677,12 +2851,12 @@ export class CoreFilepoolProvider {
|
||||||
// Consider this as a silent error, never reject the promise here.
|
// Consider this as a silent error, never reject the promise here.
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
||||||
this.notifyFileDownloadError(siteId, fileId);
|
this.notifyFileDownloadError(siteId, fileId, links);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// We considered the file as legit but did not get it, failure.
|
// We considered the file as legit but did not get it, failure.
|
||||||
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
this.treatQueueDeferred(siteId, fileId, false, errorMessage);
|
||||||
this.notifyFileDownloadError(siteId, fileId);
|
this.notifyFileDownloadError(siteId, fileId, links);
|
||||||
|
|
||||||
return Promise.reject(errorObject);
|
return Promise.reject(errorObject);
|
||||||
}
|
}
|
||||||
|
@ -2730,13 +2904,19 @@ export class CoreFilepoolProvider {
|
||||||
// If file not found, use the path without extension.
|
// If file not found, use the path without extension.
|
||||||
return path;
|
return path;
|
||||||
}).then((path) => {
|
}).then((path) => {
|
||||||
|
const conditions = {
|
||||||
|
fileId: fileId
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get links to components to notify them after remove.
|
||||||
|
return this.getFileLinks(siteId, fileId).then((links) => {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
// Remove entry from filepool store.
|
// Remove entry from filepool store.
|
||||||
promises.push(db.deleteRecords(this.FILES_TABLE, { fileId: fileId }));
|
promises.push(db.deleteRecords(this.FILES_TABLE, conditions));
|
||||||
|
|
||||||
// Remove links.
|
// Remove links.
|
||||||
promises.push(db.deleteRecords(this.LINKS_TABLE, { fileId: fileId }));
|
promises.push(db.deleteRecords(this.LINKS_TABLE, conditions));
|
||||||
|
|
||||||
// Remove the file.
|
// Remove the file.
|
||||||
if (this.fileProvider.isAvailable()) {
|
if (this.fileProvider.isAvailable()) {
|
||||||
|
@ -2750,7 +2930,7 @@ export class CoreFilepoolProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
return Promise.all(promises).then(() => {
|
return Promise.all(promises).then(() => {
|
||||||
this.notifyFileDeleted(siteId, fileId);
|
this.notifyFileDeleted(siteId, fileId, links);
|
||||||
|
|
||||||
return this.pluginFileDelegate.fileDeleted(fileUrl, path, siteId).catch((error) => {
|
return this.pluginFileDelegate.fileDeleted(fileUrl, path, siteId).catch((error) => {
|
||||||
// Ignore errors.
|
// Ignore errors.
|
||||||
|
@ -2758,6 +2938,7 @@ export class CoreFilepoolProvider {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1392,4 +1392,27 @@ export class CoreUtilsProvider {
|
||||||
|
|
||||||
return filtered;
|
return filtered;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Debounce a function so consecutive calls are ignored until a certain time has passed since the last call.
|
||||||
|
*
|
||||||
|
* @param context The context to apply to the function.
|
||||||
|
* @param fn Function to debounce.
|
||||||
|
* @param delay Time that must pass until the function is called.
|
||||||
|
* @return Debounced function.
|
||||||
|
*/
|
||||||
|
debounce(fn: (...args: any[]) => any, delay: number): (...args: any[]) => void {
|
||||||
|
|
||||||
|
let timeoutID: number;
|
||||||
|
|
||||||
|
const debounced = (...args: any[]): void => {
|
||||||
|
clearTimeout(timeoutID);
|
||||||
|
|
||||||
|
timeoutID = window.setTimeout(() => {
|
||||||
|
fn.apply(null, args);
|
||||||
|
}, delay);
|
||||||
|
};
|
||||||
|
|
||||||
|
return debounced;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue