commit
07f661e5ab
|
@ -29,7 +29,7 @@
|
||||||
<ion-item class="ion-text-wrap" *ngIf="activityInstructions">
|
<ion-item class="ion-text-wrap" *ngIf="activityInstructions">
|
||||||
<ion-label>
|
<ion-label>
|
||||||
<core-format-text [text]="activityInstructions" [component]="component" [componentId]="moduleId" contextLevel="module"
|
<core-format-text [text]="activityInstructions" [component]="component" [componentId]="moduleId" contextLevel="module"
|
||||||
[contextInstanceId]="moduleId" [courseId]="courseId" [maxHeight]="120">
|
[contextInstanceId]="moduleId" [courseId]="courseId">
|
||||||
</core-format-text>
|
</core-format-text>
|
||||||
</ion-label>
|
</ion-label>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
|
|
@ -19,10 +19,6 @@ import { CoreSiteError, CoreSiteErrorOptions } from '@classes/errors/siteerror';
|
||||||
*/
|
*/
|
||||||
export class CoreAjaxError extends CoreSiteError {
|
export class CoreAjaxError extends CoreSiteError {
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. AJAX endpoint should always be available in supported Moodle versions.
|
|
||||||
*/
|
|
||||||
available = 1;
|
|
||||||
status?: number;
|
status?: number;
|
||||||
|
|
||||||
constructor(messageOrOptions: string | CoreSiteErrorOptions, available?: number, status?: number) {
|
constructor(messageOrOptions: string | CoreSiteErrorOptions, available?: number, status?: number) {
|
||||||
|
|
|
@ -1634,38 +1634,6 @@ export class CoreSite {
|
||||||
return CoreUrlUtils.addParamsToUrl(CorePath.concatenatePaths(this.siteUrl, path), params, anchor);
|
return CoreUrlUtils.addParamsToUrl(CorePath.concatenatePaths(this.siteUrl, path), params, anchor);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the local_mobile plugin is installed in the Moodle site.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved when the check is done.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
async checkLocalMobilePlugin(): Promise<LocalMobileResponse> {
|
|
||||||
// Not used anymore.
|
|
||||||
return { code: 0, coreSupported: true };
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if local_mobile has been installed in Moodle.
|
|
||||||
*
|
|
||||||
* @returns Whether the App is able to use local_mobile plugin for this site.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
checkIfAppUsesLocalMobile(): boolean {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if local_mobile has been installed in Moodle but the app is not using it.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved it local_mobile was added, rejected otherwise.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async checkIfLocalMobileInstalledAndNotUsed(): Promise<void> {
|
|
||||||
throw new CoreError('Deprecated.');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a URL belongs to this site.
|
* Check if a URL belongs to this site.
|
||||||
*
|
*
|
||||||
|
@ -2666,33 +2634,6 @@ export type CoreSiteWSPreSets = {
|
||||||
updateInBackground?: boolean;
|
updateInBackground?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Response of checking local_mobile status.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
export type LocalMobileResponse = {
|
|
||||||
/**
|
|
||||||
* Code to identify the authentication method to use.
|
|
||||||
*/
|
|
||||||
code: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Name of the service to use.
|
|
||||||
*/
|
|
||||||
service?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Code of the warning message.
|
|
||||||
*/
|
|
||||||
warning?: string;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether core SSO is supported.
|
|
||||||
*/
|
|
||||||
coreSupported?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Info of a request waiting in the queue.
|
* Info of a request waiting in the queue.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, Output, OnInit, OnDestroy, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
|
import { Component, Input, Output, OnInit, OnDestroy, EventEmitter, OnChanges, SimpleChange } from '@angular/core';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
|
||||||
import { CoreContextMenuComponent } from '../context-menu/context-menu';
|
import { CoreContextMenuComponent } from '../context-menu/context-menu';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,11 +57,6 @@ export class CoreContextMenuItemComponent implements OnInit, OnDestroy, OnChange
|
||||||
@Output() onClosed?: EventEmitter<() => void>; // Will emit an event when the popover is closed because the item was clicked.
|
@Output() onClosed?: EventEmitter<() => void>; // Will emit an event when the popover is closed because the item was clicked.
|
||||||
@Output() toggleChange = new EventEmitter<boolean>();// Will emit an event when toggle changes to enable 2-way data binding.
|
@Output() toggleChange = new EventEmitter<boolean>();// Will emit an event when toggle changes to enable 2-way data binding.
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
@Input() iconDescription?: string;
|
|
||||||
|
|
||||||
protected hasAction = false;
|
protected hasAction = false;
|
||||||
protected destroyed = false;
|
protected destroyed = false;
|
||||||
|
|
||||||
|
@ -92,12 +86,6 @@ export class CoreContextMenuItemComponent implements OnInit, OnDestroy, OnChange
|
||||||
if (!this.destroyed) {
|
if (!this.destroyed) {
|
||||||
this.ctxtMenu.addItem(this);
|
this.ctxtMenu.addItem(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
if (this.iconDescription !== undefined) {
|
|
||||||
CoreLogger.getInstance('CoreContextMenuItemComponent')
|
|
||||||
.warn('iconDescription Input is deprecated and should not be used');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -35,10 +35,6 @@ export class CoreDownloadRefreshComponent {
|
||||||
@Input() statusTranslatable?: string; // Download status translatable string.
|
@Input() statusTranslatable?: string; // Download status translatable string.
|
||||||
@Input() enabled = false; // Whether the download is enabled.
|
@Input() enabled = false; // Whether the download is enabled.
|
||||||
@Input() loading = true; // Force loading status when is not downloading.
|
@Input() loading = true; // Force loading status when is not downloading.
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
@Input() size = ''; // Size of the buttons.
|
|
||||||
@Input() canTrustDownload = false; // If false, refresh will be shown if downloaded.
|
@Input() canTrustDownload = false; // If false, refresh will be shown if downloaded.
|
||||||
@Output() action: EventEmitter<boolean>; // Will emit an event when the item clicked.
|
@Output() action: EventEmitter<boolean>; // Will emit an event when the item clicked.
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,6 @@ export class CoreEmptyBoxComponent {
|
||||||
@Input() image?: string; // Image source. If an icon is provided, image won't be used.
|
@Input() image?: string; // Image source. If an icon is provided, image won't be used.
|
||||||
@Input() flipIconRtl = false; // Whether to flip the icon in RTL. Defaults to false.
|
@Input() flipIconRtl = false; // Whether to flip the icon in RTL. Defaults to false.
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
@Input() inline = false;
|
|
||||||
|
|
||||||
@HostBinding('class.dimmed')
|
@HostBinding('class.dimmed')
|
||||||
get isDimmed(): boolean {
|
get isDimmed(): boolean {
|
||||||
return this.dimmed;
|
return this.dimmed;
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
import { Component, Input, OnInit, OnChanges, SimpleChange, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
|
import { Component, Input, OnInit, OnChanges, SimpleChange, ElementRef, AfterViewInit, OnDestroy } from '@angular/core';
|
||||||
|
|
||||||
import { CoreEventLoadingChangedData, CoreEvents } from '@singletons/events';
|
|
||||||
import { CoreUtils } from '@services/utils/utils';
|
import { CoreUtils } from '@services/utils/utils';
|
||||||
import { CoreAnimations } from '@components/animations';
|
import { CoreAnimations } from '@components/animations';
|
||||||
import { Translate } from '@singletons';
|
import { Translate } from '@singletons';
|
||||||
|
@ -153,13 +152,6 @@ export class CoreLoadingComponent implements OnInit, OnChanges, AfterViewInit, A
|
||||||
this.lastScrollPosition = this.getScrollPosition();
|
this.lastScrollPosition = this.getScrollPosition();
|
||||||
this.mutationObserver.disconnect();
|
this.mutationObserver.disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Event has been deprecated since app 4.0.
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
CoreEvents.trigger(CoreEvents.CORE_LOADING_CHANGED, <CoreEventLoadingChangedData> {
|
|
||||||
loaded,
|
|
||||||
uniqueId: this.uniqueId,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -78,10 +78,6 @@ export class CoreConstants {
|
||||||
// WS constants.
|
// WS constants.
|
||||||
static readonly WS_TIMEOUT = 30000; // Timeout when not in WiFi.
|
static readonly WS_TIMEOUT = 30000; // Timeout when not in WiFi.
|
||||||
static readonly WS_TIMEOUT_WIFI = 30000; // Timeout when in WiFi.
|
static readonly WS_TIMEOUT_WIFI = 30000; // Timeout when in WiFi.
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
static readonly WS_PREFIX = 'local_mobile_';
|
|
||||||
|
|
||||||
// Login constants.
|
// Login constants.
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -90,21 +90,6 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
|
||||||
@Input() hideIfEmpty = false; // If true, the tag will contain nothing if text is empty.
|
@Input() hideIfEmpty = false; // If true, the tag will contain nothing if text is empty.
|
||||||
@Input() disabled?: boolean; // If disabled, autoplay elements will be disabled.
|
@Input() disabled?: boolean; // If disabled, autoplay elements will be disabled.
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
@Input() fullOnClick?: boolean | string;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
@Input() fullTitle?: string;
|
|
||||||
/**
|
|
||||||
* Max height in pixels to render the content box. It should be 50 at least to make sense.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0 Use collapsible-item directive instead.
|
|
||||||
*/
|
|
||||||
@Input() maxHeight?: number;
|
|
||||||
|
|
||||||
@Output() afterRender: EventEmitter<void>; // Called when the data is rendered.
|
@Output() afterRender: EventEmitter<void>; // Called when the data is rendered.
|
||||||
@Output() onClick: EventEmitter<void> = new EventEmitter(); // Called when clicked.
|
@Output() onClick: EventEmitter<void> = new EventEmitter(); // Called when clicked.
|
||||||
|
|
||||||
|
@ -380,15 +365,6 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
|
||||||
|
|
||||||
await CoreUtils.nextTick();
|
await CoreUtils.nextTick();
|
||||||
|
|
||||||
// Use collapsible-item directive instead.
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
if (this.maxHeight && !this.collapsible) {
|
|
||||||
this.collapsible = new CoreCollapsibleItemDirective(new ElementRef(this.element));
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
this.collapsible.height = this.maxHeight;
|
|
||||||
this.collapsible.ngOnInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add magnifying glasses to images.
|
// Add magnifying glasses to images.
|
||||||
this.addMagnifyingGlasses();
|
this.addMagnifyingGlasses();
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { CoreContentLinksHandlerBase } from './base-handler';
|
import { CoreContentLinksHandlerBase } from './base-handler';
|
||||||
import { Params } from '@angular/router';
|
|
||||||
import { CoreContentLinksAction } from '../services/contentlinks-delegate';
|
import { CoreContentLinksAction } from '../services/contentlinks-delegate';
|
||||||
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
import { CoreCourseHelper } from '@features/course/services/course-helper';
|
||||||
import { CoreNavigationOptions } from '@services/navigator';
|
import { CoreNavigationOptions } from '@services/navigator';
|
||||||
|
@ -52,20 +51,6 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
|
||||||
this.featureName = 'CoreCourseModuleDelegate_' + addon;
|
this.featureName = 'CoreCourseModuleDelegate_' + addon;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the mod params necessary to open an activity.
|
|
||||||
*
|
|
||||||
* @param url The URL to treat.
|
|
||||||
* @param params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
|
||||||
* @param courseId Course ID related to the URL. Optional but recommended.
|
|
||||||
* @returns List of params to pass to navigateToModule / navigateToModuleByInstance.
|
|
||||||
* @deprecated since 4.0. Not used anymore.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
getPageParams(url: string, params: Record<string, string>, courseId?: number): Params {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the navigation options to open the module.
|
* Get the navigation options to open the module.
|
||||||
*
|
*
|
||||||
|
@ -97,19 +82,6 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
|
||||||
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
): CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||||
|
|
||||||
courseId = Number(courseId || params.courseid || params.cid);
|
courseId = Number(courseId || params.courseid || params.cid);
|
||||||
const getModNavOptions = (siteId: string): CoreNavigationOptions => {
|
|
||||||
let modNavOptions = this.getModNavOptions(url, params, siteId, courseId);
|
|
||||||
if (!modNavOptions) {
|
|
||||||
// Use the old function, currently deprecated.
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
const pageParams = this.getPageParams(url, params, courseId);
|
|
||||||
if (pageParams && Object.keys(pageParams).length > 0) {
|
|
||||||
modNavOptions = { params: pageParams };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return modNavOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
if (this.instanceIdParam && params[this.instanceIdParam] !== undefined) {
|
if (this.instanceIdParam && params[this.instanceIdParam] !== undefined) {
|
||||||
const instanceId = parseInt(params[this.instanceIdParam], 10);
|
const instanceId = parseInt(params[this.instanceIdParam], 10);
|
||||||
|
@ -122,7 +94,7 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
|
||||||
{
|
{
|
||||||
courseId,
|
courseId,
|
||||||
useModNameToGetModule: this.useModNameToGetModule,
|
useModNameToGetModule: this.useModNameToGetModule,
|
||||||
modNavOptions: getModNavOptions(siteId),
|
modNavOptions: this.getModNavOptions(url, params, siteId, courseId),
|
||||||
siteId,
|
siteId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -137,7 +109,7 @@ export class CoreContentLinksModuleIndexHandler extends CoreContentLinksHandlerB
|
||||||
{
|
{
|
||||||
courseId,
|
courseId,
|
||||||
modName: this.useModNameToGetModule ? this.modName : undefined,
|
modName: this.useModNameToGetModule ? this.modName : undefined,
|
||||||
modNavOptions: getModNavOptions(siteId),
|
modNavOptions: this.getModNavOptions(url, params, siteId, courseId),
|
||||||
siteId,
|
siteId,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input } from '@angular/core';
|
import { Component, HostBinding, Input } from '@angular/core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component to display the description of a module.
|
* Component to display the description of a module.
|
||||||
|
@ -47,4 +47,8 @@ export class CoreCourseModuleDescriptionComponent {
|
||||||
@Input() contextInstanceId?: number; // The instance ID related to the context.
|
@Input() contextInstanceId?: number; // The instance ID related to the context.
|
||||||
@Input() courseId?: number; // Course ID the text belongs to. It can be used to improve performance with filters.
|
@Input() courseId?: number; // Course ID the text belongs to. It can be used to improve performance with filters.
|
||||||
|
|
||||||
|
@HostBinding('class.deprecated') get isDeprecated(): boolean {
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -148,14 +148,6 @@ export class CoreCourseIndexPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
this.modNavOptions = CoreNavigator.getRouteParam<CoreNavigationOptions>('modNavOptions');
|
this.modNavOptions = CoreNavigator.getRouteParam<CoreNavigationOptions>('modNavOptions');
|
||||||
this.openModule = CoreNavigator.getRouteBooleanParam('openModule') ?? true; // If false, just scroll to module.
|
this.openModule = CoreNavigator.getRouteBooleanParam('openModule') ?? true; // If false, just scroll to module.
|
||||||
if (!this.modNavOptions) {
|
|
||||||
// Fallback to old way of passing params. @deprecated since 4.0.
|
|
||||||
const modParams = CoreNavigator.getRouteParam<Params>('modParams');
|
|
||||||
if (modParams) {
|
|
||||||
this.modNavOptions = { params: modParams };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.currentPagePath = CoreNavigator.getCurrentPath();
|
this.currentPagePath = CoreNavigator.getCurrentPath();
|
||||||
this.contentsTab.page = CorePath.concatenatePaths(this.currentPagePath, this.contentsTab.page);
|
this.contentsTab.page = CorePath.concatenatePaths(this.currentPagePath, this.contentsTab.page);
|
||||||
this.contentsTab.pageParams = {
|
this.contentsTab.pageParams = {
|
||||||
|
|
|
@ -42,7 +42,6 @@ import {
|
||||||
CoreEnrolledCourseData,
|
CoreEnrolledCourseData,
|
||||||
} from '@features/courses/services/courses';
|
} from '@features/courses/services/courses';
|
||||||
import { CoreArray } from '@singletons/array';
|
import { CoreArray } from '@singletons/array';
|
||||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
|
||||||
import { CoreCourseOffline } from './course-offline';
|
import { CoreCourseOffline } from './course-offline';
|
||||||
import {
|
import {
|
||||||
CoreCourseOptionsDelegate,
|
CoreCourseOptionsDelegate,
|
||||||
|
@ -258,22 +257,6 @@ export class CoreCourseHelperProvider {
|
||||||
return section.uservisible !== false;
|
return section.uservisible !== false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Calculate completion data of a module.
|
|
||||||
*
|
|
||||||
* @param module Module.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
calculateModuleCompletionData(module: CoreCourseModuleData): void {
|
|
||||||
if (!module.completiondata || !module.completion) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.completiondata.courseId = module.course;
|
|
||||||
module.completiondata.tracking = module.completion;
|
|
||||||
module.completiondata.cmid = module.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the status of a section.
|
* Calculate the status of a section.
|
||||||
*
|
*
|
||||||
|
@ -312,8 +295,6 @@ export class CoreCourseHelperProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
sectionWithStatus.downloadStatus = result.status;
|
sectionWithStatus.downloadStatus = result.status;
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
sectionWithStatus.canCheckUpdates = true;
|
|
||||||
|
|
||||||
// Set this section data.
|
// Set this section data.
|
||||||
if (result.status !== CoreConstants.DOWNLOADING) {
|
if (result.status !== CoreConstants.DOWNLOADING) {
|
||||||
|
@ -375,8 +356,6 @@ export class CoreCourseHelperProvider {
|
||||||
if (allSectionsSection) {
|
if (allSectionsSection) {
|
||||||
// Set "All sections" data.
|
// Set "All sections" data.
|
||||||
allSectionsSection.downloadStatus = allSectionsStatus;
|
allSectionsSection.downloadStatus = allSectionsStatus;
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
allSectionsSection.canCheckUpdates = true;
|
|
||||||
allSectionsSection.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
|
allSectionsSection.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -514,32 +493,6 @@ export class CoreCourseHelperProvider {
|
||||||
return CoreUtils.allPromises(promises);
|
return CoreUtils.allPromises(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Show confirmation dialog and then remove a module files.
|
|
||||||
*
|
|
||||||
* @param module Module to remove the files.
|
|
||||||
* @param courseId Course ID the module belongs to.
|
|
||||||
* @returns Promise resolved when done.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async confirmAndRemoveFiles(module: CoreCourseModuleData, courseId: number): Promise<void> {
|
|
||||||
let modal: CoreIonLoadingElement | undefined;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await CoreDomUtils.showDeleteConfirm('addon.storagemanager.confirmdeletedatafrom', { name: module.name });
|
|
||||||
|
|
||||||
modal = await CoreDomUtils.showModalLoading();
|
|
||||||
|
|
||||||
await this.removeModuleStoredData(module, courseId);
|
|
||||||
} catch (error) {
|
|
||||||
if (error) {
|
|
||||||
CoreDomUtils.showErrorModal(error);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
modal?.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the size to download a section and show a confirm modal if needed.
|
* Calculate the size to download a section and show a confirm modal if needed.
|
||||||
*
|
*
|
||||||
|
@ -1358,31 +1311,6 @@ export class CoreCourseHelperProvider {
|
||||||
return CoreConstants.ICON_DOWNLOADING;
|
return CoreConstants.ICON_DOWNLOADING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the course ID from a module instance ID, showing an error message if it can't be retrieved.
|
|
||||||
*
|
|
||||||
* @param instanceId Instance ID.
|
|
||||||
* @param moduleName Name of the module. E.g. 'glossary'.
|
|
||||||
* @param siteId Site ID. If not defined, current site.
|
|
||||||
* @returns Promise resolved with the module's course ID.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async getModuleCourseIdByInstance(instanceId: number, moduleName: string, siteId?: string): Promise<number> {
|
|
||||||
try {
|
|
||||||
const cm = await CoreCourse.getModuleBasicInfoByInstance(
|
|
||||||
instanceId,
|
|
||||||
moduleName,
|
|
||||||
{ siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE },
|
|
||||||
);
|
|
||||||
|
|
||||||
return cm.course;
|
|
||||||
} catch (error) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errorgetmodule', true);
|
|
||||||
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get prefetch info for a module.
|
* Get prefetch info for a module.
|
||||||
*
|
*
|
||||||
|
@ -1805,8 +1733,6 @@ export class CoreCourseHelperProvider {
|
||||||
|
|
||||||
// Set "All sections" data.
|
// Set "All sections" data.
|
||||||
section.downloadStatus = allSectionsStatus;
|
section.downloadStatus = allSectionsStatus;
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
section.canCheckUpdates = true;
|
|
||||||
section.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
|
section.isDownloading = allSectionsStatus === CoreConstants.DOWNLOADING;
|
||||||
} finally {
|
} finally {
|
||||||
section.isDownloading = false;
|
section.isDownloading = false;
|
||||||
|
@ -2120,10 +2046,6 @@ export type CoreCourseSection = CoreCourseWSSection & {
|
||||||
*/
|
*/
|
||||||
export type CoreCourseSectionWithStatus = CoreCourseSection & {
|
export type CoreCourseSectionWithStatus = CoreCourseSection & {
|
||||||
downloadStatus?: string; // Section status.
|
downloadStatus?: string; // Section status.
|
||||||
/**
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
canCheckUpdates?: boolean; // Whether can check updates.
|
|
||||||
isDownloading?: boolean; // Whether section is being downloaded.
|
isDownloading?: boolean; // Whether section is being downloaded.
|
||||||
total?: number; // Total of modules being downloaded.
|
total?: number; // Total of modules being downloaded.
|
||||||
count?: number; // Number of downloaded modules.
|
count?: number; // Number of downloaded modules.
|
||||||
|
@ -2141,13 +2063,6 @@ export type CoreCourseModuleData = Omit<CoreCourseGetContentsWSModule, 'completi
|
||||||
section: number;
|
section: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Module with calculated data.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0. Use CoreCourseModuleData instead.
|
|
||||||
*/
|
|
||||||
export type CoreCourseModule = CoreCourseModuleData;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module completion with calculated data.
|
* Module completion with calculated data.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -110,36 +110,6 @@ export class CoreCourseProvider {
|
||||||
static readonly ACCESS_DEFAULT = 'courses_access_default';
|
static readonly ACCESS_DEFAULT = 'courses_access_default';
|
||||||
static readonly ALL_COURSES_CLEARED = -1;
|
static readonly ALL_COURSES_CLEARED = -1;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_NONE instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_TRACKING_NONE = 0;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_MANUAL instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_TRACKING_MANUAL = 1;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionTracking.COMPLETION_TRACKING_AUTOMATIC instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_TRACKING_AUTOMATIC = 2;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_INCOMPLETE instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_INCOMPLETE = 0;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_COMPLETE = 1;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_PASS instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_COMPLETE_PASS = 2;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use CoreCourseModuleCompletionStatus.COMPLETION_COMPLETE_FAIL instead.
|
|
||||||
*/
|
|
||||||
static readonly COMPLETION_COMPLETE_FAIL = 3;
|
|
||||||
|
|
||||||
static readonly COMPONENT = 'CoreCourse';
|
static readonly COMPONENT = 'CoreCourse';
|
||||||
|
|
||||||
readonly CORE_MODULES = [
|
readonly CORE_MODULES = [
|
||||||
|
@ -863,24 +833,6 @@ export class CoreCourseProvider {
|
||||||
return path + moduleName + '.svg';
|
return path + moduleName + '.svg';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the section ID a module belongs to.
|
|
||||||
*
|
|
||||||
* @param moduleId The module ID.
|
|
||||||
* @param siteId Site ID. If not defined, current site.
|
|
||||||
* @returns Promise resolved with the section ID.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async getModuleSectionId(moduleId: number, siteId?: string): Promise<number> {
|
|
||||||
// Try to get the section using getModuleBasicInfo.
|
|
||||||
const module = await CoreCourse.getModuleBasicInfo(
|
|
||||||
moduleId,
|
|
||||||
{ siteId, readingStrategy: CoreSitesReadingStrategy.PREFER_CACHE },
|
|
||||||
);
|
|
||||||
|
|
||||||
return module.section;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return a specific section.
|
* Return a specific section.
|
||||||
*
|
*
|
||||||
|
@ -1829,15 +1781,6 @@ type CoreCourseGetCourseModuleWSResponse = {
|
||||||
warnings?: CoreWSExternalWarning[];
|
warnings?: CoreWSExternalWarning[];
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Course module data returned by the WS with course added.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0. Use CoreCourseModuleData instead.
|
|
||||||
*/
|
|
||||||
export type CoreCourseWSModule = CoreCourseGetContentsWSModule & {
|
|
||||||
course: number; // The course id.
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module completion data.
|
* Module completion data.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -57,24 +57,6 @@ export interface CoreCourseFormatHandler extends CoreDelegateHandler {
|
||||||
*/
|
*/
|
||||||
displayBlocks?(course: CoreCourseAnyCourseData): boolean;
|
displayBlocks?(course: CoreCourseAnyCourseData): boolean;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the option to enable section/module download should be displayed.
|
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @returns Whether the option to enable section/module download should be displayed.
|
|
||||||
* @deprecated since 4.0 Not used anymore because prefetch has been moved to storage manager.
|
|
||||||
*/
|
|
||||||
displayEnableDownload?(course: CoreCourseAnyCourseData): boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the default course index should be displayed. Defaults to true.
|
|
||||||
*
|
|
||||||
* @param course The course to check.
|
|
||||||
* @returns Whether the default course index should be displayed.
|
|
||||||
* @deprecated since 4.0. Please use displayCourseIndex instead.
|
|
||||||
*/
|
|
||||||
displaySectionSelector?(course: CoreCourseAnyCourseData): boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether the default section selector should be displayed. Defaults to true.
|
* Whether the default section selector should be displayed. Defaults to true.
|
||||||
*
|
*
|
||||||
|
|
|
@ -77,16 +77,6 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate<CoreCo
|
||||||
}, CoreSites.getCurrentSiteId());
|
}, CoreSites.getCurrentSiteId());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if current site can check updates using core_course_check_updates.
|
|
||||||
*
|
|
||||||
* @returns True if can check updates, false otherwise.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
canCheckUpdates(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a certain module can use core_course_check_updates.
|
* Check if a certain module can use core_course_check_updates.
|
||||||
*
|
*
|
||||||
|
@ -705,8 +695,7 @@ export class CoreCourseModulePrefetchDelegateService extends CoreDelegate<CoreCo
|
||||||
await Promise.all(modules.map(async (module) => {
|
await Promise.all(modules.map(async (module) => {
|
||||||
const handler = this.getPrefetchHandlerFor(module.modname);
|
const handler = this.getPrefetchHandlerFor(module.modname);
|
||||||
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
if (!handler) {
|
||||||
if (!handler || (onlyToDisplay && handler.skipListStatus)) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1364,14 +1353,6 @@ export interface CoreCourseModulePrefetchHandler extends CoreDelegateHandler {
|
||||||
*/
|
*/
|
||||||
updatesNames?: RegExp;
|
updatesNames?: RegExp;
|
||||||
|
|
||||||
/**
|
|
||||||
* If true, this module will be treated as not downloadable when determining the status of a list of modules. The module will
|
|
||||||
* still be downloaded when downloading the section/course, it only affects whether the button should be displayed.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
skipListStatus?: boolean;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the download size of a module.
|
* Get the download size of a module.
|
||||||
*
|
*
|
||||||
|
|
|
@ -1,60 +1,3 @@
|
||||||
<ion-card [attr.course-color]="course.color ? null : course.colorNumber">
|
<core-courses-course-list-item [course]="course" class="core-course-progress" [showDownload]="showDownload"
|
||||||
<div (click)="openCourse()" class="core-course-thumb" [class.core-course-color-img]="course.courseimage"
|
[layout]="showAll ? 'card' : 'summarycard'">
|
||||||
[style.background-color]="course.color">
|
</core-courses-course-list-item>
|
||||||
<img *ngIf="course.courseimage" [src]="course.courseimage" core-external-content alt="" />
|
|
||||||
</div>
|
|
||||||
<ion-item button (click)="openCourse()" [attr.aria-label]="course.displayname || course.fullname" class="core-course-header"
|
|
||||||
[class.core-course-only-title]="!showAll || progress < 0 && completionUserTracked === false" detail="false">
|
|
||||||
<ion-label class="ion-text-wrap core-course-title"
|
|
||||||
[class.core-course-with-buttons]="courseOptionMenuEnabled || (downloadCourseEnabled && showDownload)"
|
|
||||||
[class.core-course-with-spinner]="(downloadCourseEnabled && prefetchCourseData.icon == 'spinner') || showSpinner">
|
|
||||||
<p *ngIf="course.categoryname || (course.displayname && course.shortname && course.fullname != course.displayname)"
|
|
||||||
class="core-course-additional-info">
|
|
||||||
<span class="sr-only">{{ 'core.courses.aria:coursecategory' | translate }}</span>
|
|
||||||
<span *ngIf="course.categoryname" class="core-course-category">
|
|
||||||
<core-format-text [text]="course.categoryname"></core-format-text>
|
|
||||||
</span>
|
|
||||||
<span *ngIf="course.categoryname && course.displayname && course.shortname && course.fullname != course.displayname"
|
|
||||||
class="core-course-category"> | </span>
|
|
||||||
<span *ngIf="course.displayname && course.shortname && course.fullname != course.displayname" class="core-course-shortname">
|
|
||||||
<core-format-text [text]="course.shortname" contextLevel="course" [contextInstanceId]="course.id">
|
|
||||||
</core-format-text>
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
<p class="item-heading">
|
|
||||||
<ion-icon name="fas-star" *ngIf="isFavourite" [attr.aria-label]="'core.courses.favourite' | translate">
|
|
||||||
</ion-icon>
|
|
||||||
<span class="sr-only" *ngIf="isFavourite">{{ 'core.courses.aria:favourite' | translate }}</span>
|
|
||||||
<span class="sr-only">{{ 'core.courses.aria:coursename' | translate }}</span>
|
|
||||||
<core-format-text [text]="course.fullname" contextLevel="course" [contextInstanceId]="course.id"></core-format-text>
|
|
||||||
</p>
|
|
||||||
</ion-label>
|
|
||||||
|
|
||||||
<div class="core-button-spinner" *ngIf="downloadCourseEnabled && !courseOptionMenuEnabled && showDownload" slot="end">
|
|
||||||
<core-download-refresh [status]="prefetchCourseData.status" [enabled]="downloadCourseEnabled"
|
|
||||||
[statusTranslatable]="prefetchCourseData.statusTranslatable" [canTrustDownload]="false"
|
|
||||||
[loading]="prefetchCourseData.loading" (action)="prefetchCourse()"></core-download-refresh>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="core-button-spinner" *ngIf="courseOptionMenuEnabled" slot="end">
|
|
||||||
<!-- Download course spinner. -->
|
|
||||||
<ion-spinner *ngIf="(downloadCourseEnabled && prefetchCourseData.icon == 'spinner') || showSpinner"
|
|
||||||
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
|
|
||||||
|
|
||||||
<!-- Downloaded icon. -->
|
|
||||||
<ion-icon *ngIf="downloadCourseEnabled && prefetchCourseData.downloadSucceeded && !showSpinner" class="core-icon-downloaded"
|
|
||||||
name="fam-cloud-done" color="success" role="status" [attr.aria-label]="'core.downloaded' | translate"></ion-icon>
|
|
||||||
|
|
||||||
<!-- Options menu. -->
|
|
||||||
<ion-button fill="clear" (click)="showCourseOptionsMenu($event)" *ngIf="!showSpinner"
|
|
||||||
[attr.aria-label]="('core.displayoptions' | translate)">
|
|
||||||
<ion-icon name="ellipsis-vertical" slot="icon-only" aria-hidden="true"></ion-icon>
|
|
||||||
</ion-button>
|
|
||||||
</div>
|
|
||||||
</ion-item>
|
|
||||||
<ion-item *ngIf="showAll && progress >= 0 && completionUserTracked !== false" class="core-course-progress">
|
|
||||||
<ion-label>
|
|
||||||
<core-progress-bar [progress]="progress" a11yText="core.courses.aria:courseprogress"></core-progress-bar>
|
|
||||||
</ion-label>
|
|
||||||
</ion-item>
|
|
||||||
</ion-card>
|
|
||||||
|
|
|
@ -1,159 +0,0 @@
|
||||||
@import "~theme/globals";
|
|
||||||
|
|
||||||
:host {
|
|
||||||
ion-card {
|
|
||||||
--vertical-margin: 12px;
|
|
||||||
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-self: stretch;
|
|
||||||
height: calc(100% - var(--vertical-margin) - var(--vertical-margin));
|
|
||||||
margin-top: var(--vertical-margin);
|
|
||||||
margin-bottom: var(--vertical-margin);
|
|
||||||
|
|
||||||
@for $i from 0 to length($core-course-image-background) {
|
|
||||||
&[course-color="#{$i}"] .core-course-thumb {
|
|
||||||
background: var(--core-course-color-#{$i});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-thumb {
|
|
||||||
padding-top: 40%;
|
|
||||||
width: 100%;
|
|
||||||
overflow: hidden;
|
|
||||||
cursor: pointer;
|
|
||||||
pointer-events: auto;
|
|
||||||
position: relative;
|
|
||||||
background-position: center;
|
|
||||||
background-size: cover;
|
|
||||||
-webkit-transition: all 50ms ease-in-out;
|
|
||||||
transition: all 50ms ease-in-out;
|
|
||||||
|
|
||||||
&.core-course-color-img {
|
|
||||||
background: var(--ion-item-background);
|
|
||||||
}
|
|
||||||
|
|
||||||
img {
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 0;
|
|
||||||
left: 0;
|
|
||||||
margin: auto;
|
|
||||||
|
|
||||||
// Fill geopaterns
|
|
||||||
&[src$=".svg"] {
|
|
||||||
min-width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@if ($core-course-hide-thumb-on-cards) {
|
|
||||||
.core-course-thumb {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@if ($core-course-thumb-on-cards-background) {
|
|
||||||
.core-course-thumb {
|
|
||||||
background: $core-course-thumb-on-cards-background !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-additional-info {
|
|
||||||
margin-bottom: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-header {
|
|
||||||
flex-grow: 1;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
|
|
||||||
&.core-course-only-title {
|
|
||||||
&::part(native) {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-title {
|
|
||||||
margin: 12px 0;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
.item-heading ion-icon {
|
|
||||||
margin-right: 4px;
|
|
||||||
color: var(--core-star-color);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-button-spinner {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
.core-button-spinner ion-spinner {
|
|
||||||
vertical-align: top; // the better option for most scenarios
|
|
||||||
vertical-align: -webkit-baseline-middle; // the best for those that support it
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-button-spinner .core-icon-downloaded {
|
|
||||||
font-size: 28.8px;
|
|
||||||
margin-top: 8px;
|
|
||||||
vertical-align: top;
|
|
||||||
}
|
|
||||||
|
|
||||||
.item-button[icon-only] {
|
|
||||||
min-width: 50px;
|
|
||||||
width: 50px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@if ($core-course-hide-progress-on-cards) {
|
|
||||||
.core-course-progress {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
z-index: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Common styles.
|
|
||||||
:host-context(.core-horizontal-scroll) {
|
|
||||||
@include horizontal_scroll_item(80%, 250px, 300px);
|
|
||||||
|
|
||||||
ion-card {
|
|
||||||
.core-course-thumb {
|
|
||||||
padding-top: 30%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.core-course-header {
|
|
||||||
.core-course-title {
|
|
||||||
margin: 7px 0;
|
|
||||||
|
|
||||||
.item-heading ion-icon {
|
|
||||||
margin-right: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.core-course-with-buttons {
|
|
||||||
max-width: calc(100% - 40px);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.core-button-spinner {
|
|
||||||
min-height: 40px;
|
|
||||||
min-width: 40px;
|
|
||||||
|
|
||||||
ion-spinner {
|
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.item-button[icon-only] {
|
|
||||||
min-width: 40px;
|
|
||||||
width: 40px;
|
|
||||||
padding: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,21 +12,8 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, Input, OnInit, OnDestroy, OnChanges } from '@angular/core';
|
import { Component, HostBinding, Input } from '@angular/core';
|
||||||
import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events';
|
import { CoreCourseListItem } from '@features/courses/services/courses';
|
||||||
import { CoreSites } from '@services/sites';
|
|
||||||
import { CoreDomUtils } from '@services/utils/dom';
|
|
||||||
import { CoreCourses, CoreCoursesProvider } from '@features/courses/services/courses';
|
|
||||||
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
|
|
||||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
|
|
||||||
import { Translate } from '@singletons';
|
|
||||||
import { CoreConstants } from '@/core/constants';
|
|
||||||
import {
|
|
||||||
CoreCourseAnyCourseDataWithExtraInfoAndOptions,
|
|
||||||
CoreEnrolledCourseDataWithExtraInfoAndOptions,
|
|
||||||
} from '../../services/courses-helper';
|
|
||||||
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
|
|
||||||
import { CoreUser } from '@features/user/services/user';
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This component is meant to display a course for a list of courses with progress.
|
* This component is meant to display a course for a list of courses with progress.
|
||||||
|
@ -41,296 +28,15 @@ import { CoreUser } from '@features/user/services/user';
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'core-courses-course-progress',
|
selector: 'core-courses-course-progress',
|
||||||
templateUrl: 'core-courses-course-progress.html',
|
templateUrl: 'core-courses-course-progress.html',
|
||||||
styleUrls: ['course-progress.scss'],
|
|
||||||
})
|
})
|
||||||
export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy, OnChanges {
|
export class CoreCoursesCourseProgressComponent {
|
||||||
|
|
||||||
// The course to render.
|
@Input() course!: CoreCourseListItem; // The course to render.
|
||||||
@Input() course!: CoreCourseAnyCourseDataWithExtraInfoAndOptions;
|
|
||||||
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
@Input() showAll = false; // If true, will show all actions, options, star and progress.
|
||||||
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
@Input() showDownload = true; // If true, will show download button. Only works if the options menu is not shown.
|
||||||
|
|
||||||
prefetchCourseData: CorePrefetchStatusInfo = {
|
@HostBinding('class.deprecated') get isDeprecated(): boolean {
|
||||||
icon: '',
|
return true;
|
||||||
statusTranslatable: 'core.loading',
|
|
||||||
status: '',
|
|
||||||
loading: true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
showSpinner = false;
|
|
||||||
downloadCourseEnabled = false;
|
|
||||||
courseOptionMenuEnabled = false;
|
|
||||||
isFavourite = false;
|
|
||||||
progress = -1;
|
|
||||||
completionUserTracked: boolean | undefined = false;
|
|
||||||
|
|
||||||
protected courseStatus = CoreConstants.NOT_DOWNLOADED;
|
|
||||||
protected isDestroyed = false;
|
|
||||||
protected courseStatusObserver?: CoreEventObserver;
|
|
||||||
protected siteUpdatedObserver?: CoreEventObserver;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
ngOnInit(): void {
|
|
||||||
|
|
||||||
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
|
|
||||||
|
|
||||||
if (this.downloadCourseEnabled) {
|
|
||||||
this.initPrefetchCourse();
|
|
||||||
}
|
|
||||||
|
|
||||||
// This field is only available from 3.6 onwards.
|
|
||||||
this.courseOptionMenuEnabled = this.showAll && 'isfavourite' in this.course &&
|
|
||||||
this.course.isfavourite !== undefined;
|
|
||||||
|
|
||||||
// Refresh the enabled flag if site is updated.
|
|
||||||
this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
|
|
||||||
const wasEnabled = this.downloadCourseEnabled;
|
|
||||||
|
|
||||||
this.downloadCourseEnabled = !CoreCourses.isDownloadCourseDisabledInSite();
|
|
||||||
|
|
||||||
if (!wasEnabled && this.downloadCourseEnabled) {
|
|
||||||
// Download course is enabled now, initialize it.
|
|
||||||
this.initPrefetchCourse();
|
|
||||||
}
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @inheritdoc
|
|
||||||
*/
|
|
||||||
ngOnChanges(): void {
|
|
||||||
this.isFavourite = 'isfavourite' in this.course && !!this.course.isfavourite;
|
|
||||||
this.progress = 'progress' in this.course ? this.course.progress || -1 : -1;
|
|
||||||
this.completionUserTracked = 'completionusertracked' in this.course && this.course.completionusertracked;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize prefetch course.
|
|
||||||
*/
|
|
||||||
async initPrefetchCourse(): Promise<void> {
|
|
||||||
if (this.courseStatusObserver !== undefined) {
|
|
||||||
// Already initialized.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Listen for status change in course.
|
|
||||||
this.courseStatusObserver = CoreEvents.on(CoreEvents.COURSE_STATUS_CHANGED, (data: CoreEventCourseStatusChanged) => {
|
|
||||||
if (data.courseId == this.course.id || data.courseId == CoreCourseProvider.ALL_COURSES_CLEARED) {
|
|
||||||
this.updateCourseStatus(data.status);
|
|
||||||
}
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
|
|
||||||
// Determine course prefetch icon.
|
|
||||||
const status = await CoreCourse.getCourseStatus(this.course.id);
|
|
||||||
|
|
||||||
this.updateCourseStatus(status);
|
|
||||||
|
|
||||||
if (this.prefetchCourseData.loading) {
|
|
||||||
// Course is being downloaded. Get the download promise.
|
|
||||||
const promise = CoreCourseHelper.getCourseDownloadPromise(this.course.id);
|
|
||||||
if (promise) {
|
|
||||||
// There is a download promise. If it fails, show an error.
|
|
||||||
promise.catch((error) => {
|
|
||||||
if (!this.isDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// No download, this probably means that the app was closed while downloading. Set previous status.
|
|
||||||
CoreCourse.setCoursePreviousStatus(this.course.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Open a course.
|
|
||||||
*/
|
|
||||||
openCourse(): void {
|
|
||||||
CoreCourseHelper.openCourse(this.course);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Prefetch the course.
|
|
||||||
*
|
|
||||||
* @param e Click event.
|
|
||||||
*/
|
|
||||||
async prefetchCourse(e?: Event): Promise<void> {
|
|
||||||
e?.preventDefault();
|
|
||||||
e?.stopPropagation();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await CoreCourseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course);
|
|
||||||
} catch (error) {
|
|
||||||
if (!this.isDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Delete the course.
|
|
||||||
*/
|
|
||||||
async deleteCourse(): Promise<void> {
|
|
||||||
try {
|
|
||||||
await CoreDomUtils.showDeleteConfirm(
|
|
||||||
'addon.storagemanager.confirmdeletedatafrom',
|
|
||||||
{ name: this.course.displayname || this.course.fullname },
|
|
||||||
);
|
|
||||||
} catch (error) {
|
|
||||||
if (!CoreDomUtils.isCanceledError(error)) {
|
|
||||||
throw error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const modal = await CoreDomUtils.showModalLoading();
|
|
||||||
|
|
||||||
try {
|
|
||||||
await CoreCourseHelper.deleteCourseFiles(this.course.id);
|
|
||||||
} catch (error) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, Translate.instant('core.errordeletefile'));
|
|
||||||
} finally {
|
|
||||||
modal.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Update the course status icon and title.
|
|
||||||
*
|
|
||||||
* @param status Status to show.
|
|
||||||
*/
|
|
||||||
protected updateCourseStatus(status: string): void {
|
|
||||||
const statusData = CoreCourseHelper.getCoursePrefetchStatusInfo(status);
|
|
||||||
|
|
||||||
this.courseStatus = status;
|
|
||||||
this.prefetchCourseData.status = statusData.status;
|
|
||||||
this.prefetchCourseData.icon = statusData.icon;
|
|
||||||
this.prefetchCourseData.statusTranslatable = statusData.statusTranslatable;
|
|
||||||
this.prefetchCourseData.loading = statusData.loading;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Show the context menu.
|
|
||||||
*
|
|
||||||
* @param e Click Event.
|
|
||||||
*/
|
|
||||||
async showCourseOptionsMenu(e: Event): Promise<void> {
|
|
||||||
e.preventDefault();
|
|
||||||
e.stopPropagation();
|
|
||||||
|
|
||||||
const popoverData = await CoreDomUtils.openPopover<string>({
|
|
||||||
component: CoreCoursesCourseOptionsMenuComponent,
|
|
||||||
componentProps: {
|
|
||||||
course: this.course,
|
|
||||||
prefetch: this.prefetchCourseData,
|
|
||||||
},
|
|
||||||
event: e,
|
|
||||||
});
|
|
||||||
|
|
||||||
switch (popoverData) {
|
|
||||||
case 'download':
|
|
||||||
if (!this.prefetchCourseData.loading) {
|
|
||||||
this.prefetchCourse(e);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'delete':
|
|
||||||
if (this.courseStatus == CoreConstants.DOWNLOADED || this.courseStatus == CoreConstants.OUTDATED) {
|
|
||||||
this.deleteCourse();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'hide':
|
|
||||||
this.setCourseHidden(true);
|
|
||||||
break;
|
|
||||||
case 'show':
|
|
||||||
this.setCourseHidden(false);
|
|
||||||
break;
|
|
||||||
case 'favourite':
|
|
||||||
this.setCourseFavourite(true);
|
|
||||||
break;
|
|
||||||
case 'unfavourite':
|
|
||||||
this.setCourseFavourite(false);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hide/Unhide the course from the course list.
|
|
||||||
*
|
|
||||||
* @param hide True to hide and false to show.
|
|
||||||
*/
|
|
||||||
protected async setCourseHidden(hide: boolean): Promise<void> {
|
|
||||||
this.showSpinner = true;
|
|
||||||
|
|
||||||
// We should use null to unset the preference.
|
|
||||||
try {
|
|
||||||
await CoreUser.updateUserPreference(
|
|
||||||
'block_myoverview_hidden_course_' + this.course.id,
|
|
||||||
hide ? '1' : undefined,
|
|
||||||
);
|
|
||||||
|
|
||||||
(<CoreEnrolledCourseDataWithExtraInfoAndOptions> this.course).hidden = hide;
|
|
||||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
|
|
||||||
courseId: this.course.id,
|
|
||||||
course: this.course,
|
|
||||||
action: CoreCoursesProvider.ACTION_STATE_CHANGED,
|
|
||||||
state: CoreCoursesProvider.STATE_HIDDEN,
|
|
||||||
value: hide,
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
if (!this.isDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'Error changing course visibility.');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.showSpinner = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Favourite/Unfavourite the course from the course list.
|
|
||||||
*
|
|
||||||
* @param favourite True to favourite and false to unfavourite.
|
|
||||||
*/
|
|
||||||
protected async setCourseFavourite(favourite: boolean): Promise<void> {
|
|
||||||
this.showSpinner = true;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await CoreCourses.setFavouriteCourse(this.course.id, favourite);
|
|
||||||
|
|
||||||
(<CoreEnrolledCourseDataWithExtraInfoAndOptions> this.course).isfavourite = favourite;
|
|
||||||
this.isFavourite = favourite;
|
|
||||||
CoreEvents.trigger(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
|
|
||||||
courseId: this.course.id,
|
|
||||||
course: this.course,
|
|
||||||
action: CoreCoursesProvider.ACTION_STATE_CHANGED,
|
|
||||||
state: CoreCoursesProvider.STATE_FAVOURITE,
|
|
||||||
value: favourite,
|
|
||||||
}, CoreSites.getCurrentSiteId());
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
if (!this.isDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'Error changing course favourite attribute.');
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
this.showSpinner = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component destroyed.
|
|
||||||
*/
|
|
||||||
ngOnDestroy(): void {
|
|
||||||
this.isDestroyed = true;
|
|
||||||
|
|
||||||
this.siteUpdatedObserver?.off();
|
|
||||||
this.courseStatusObserver?.off();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,16 +70,6 @@ export class CoreCoursesProvider {
|
||||||
protected userCoursesIds?: Set<number>;
|
protected userCoursesIds?: Set<number>;
|
||||||
protected downloadOptionsEnabled = false;
|
protected downloadOptionsEnabled = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether current site supports getting course options.
|
|
||||||
*
|
|
||||||
* @returns Whether current site supports getting course options.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
canGetAdminAndNavOptions(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get categories. They can be filtered by id.
|
* Get categories. They can be filtered by id.
|
||||||
*
|
*
|
||||||
|
@ -602,26 +592,6 @@ export class CoreCoursesProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if get courses by field WS is available in a certain site.
|
|
||||||
*
|
|
||||||
* @returns Whether get courses by field is available.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
isGetCoursesByFieldAvailable(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if get courses by field WS is available in a certain site, by site ID.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved with boolean: whether get courses by field is available.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async isGetCoursesByFieldAvailableInSite(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the navigation and administration options for the given courses.
|
* Get the navigation and administration options for the given courses.
|
||||||
*
|
*
|
||||||
|
@ -1462,7 +1432,7 @@ export type CoreCourseGetCoursesData = CoreEnrolledCourseBasicData & {
|
||||||
/**
|
/**
|
||||||
* Number of weeks/topics.
|
* Number of weeks/topics.
|
||||||
*
|
*
|
||||||
* @deprecated use courseformatoptions. This attribute is deprecated in moodle since 2.4 but still present.
|
* @deprecatedonmoodle since 2.4. Use courseformatoptions. This attribute is deprecated in moodle since 2.4 but still present.
|
||||||
*/
|
*/
|
||||||
numsections?: number;
|
numsections?: number;
|
||||||
maxbytes?: number; // Largest size of file that can be uploaded into the course.
|
maxbytes?: number; // Largest size of file that can be uploaded into the course.
|
||||||
|
@ -1470,7 +1440,7 @@ export type CoreCourseGetCoursesData = CoreEnrolledCourseBasicData & {
|
||||||
/**
|
/**
|
||||||
* How the hidden sections in the course are displayed to students.
|
* How the hidden sections in the course are displayed to students.
|
||||||
*
|
*
|
||||||
* @deprecated use courseformatoptions. This attribute is deprecated in moodle since 2.4 but still present.
|
* @deprecatedonmoodle since 2.4. Use courseformatoptions. This attribute is deprecated in moodle since 2.4 but still present.
|
||||||
*/
|
*/
|
||||||
hiddensections?: number;
|
hiddensections?: number;
|
||||||
groupmode?: number; // No group, separate, visible.
|
groupmode?: number; // No group, separate, visible.
|
||||||
|
|
|
@ -60,26 +60,6 @@ export class CoreFilterProvider {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not WS get available in context is available.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved with true if ws is available, false otherwise.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async canGetAvailableInContext(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not WS get available in context is available in a certain site.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved with true if ws is available, false otherwise.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
canGetAvailableInContextInSite(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns whether or not we can get the available filters: the WS is available and the feature isn't disabled.
|
* Returns whether or not we can get the available filters: the WS is available and the feature isn't disabled.
|
||||||
*
|
*
|
||||||
|
|
|
@ -60,49 +60,6 @@ export class CoreGradesHelperProvider {
|
||||||
this.logger = CoreLogger.getInstance('CoreGradesHelperProvider');
|
this.logger = CoreLogger.getInstance('CoreGradesHelperProvider');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a row from the grades table te be rendered in a page.
|
|
||||||
*
|
|
||||||
* @param tableRow JSON object representing row of grades table data.
|
|
||||||
* @returns Formatted row object.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
protected async formatGradeRow(tableRow: CoreGradesTableRow): Promise<CoreGradesFormattedRow> {
|
|
||||||
const row: CoreGradesFormattedRow = {
|
|
||||||
rowclass: '',
|
|
||||||
};
|
|
||||||
for (const name in tableRow) {
|
|
||||||
const column: CoreGradesTableColumn = tableRow[name];
|
|
||||||
|
|
||||||
if (column.content === undefined || column.content === null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
let content = String(column.content);
|
|
||||||
|
|
||||||
if (name == 'itemname') {
|
|
||||||
await this.setRowIconAndType(row, content);
|
|
||||||
|
|
||||||
row.link = this.getModuleLink(content);
|
|
||||||
row.rowclass += column.class.indexOf('hidden') >= 0 ? ' hidden' : '';
|
|
||||||
row.rowclass += column.class.indexOf('dimmed_text') >= 0 ? ' dimmed_text' : '';
|
|
||||||
|
|
||||||
content = content.replace(/<\/span>/gi, '\n');
|
|
||||||
content = CoreTextUtils.cleanTags(content);
|
|
||||||
} else {
|
|
||||||
content = CoreTextUtils.replaceNewLines(content, '<br>');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (content == ' ') {
|
|
||||||
content = '';
|
|
||||||
}
|
|
||||||
|
|
||||||
row[name] = content.trim();
|
|
||||||
}
|
|
||||||
|
|
||||||
return row;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a row from the grades table to be rendered in one table.
|
* Formats a row from the grades table to be rendered in one table.
|
||||||
*
|
*
|
||||||
|
@ -353,34 +310,6 @@ export class CoreGradesHelperProvider {
|
||||||
return someCoursesAreMissing;
|
return someCoursesAreMissing;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get an specific grade item.
|
|
||||||
*
|
|
||||||
* @param courseId ID of the course to get the grades from.
|
|
||||||
* @param gradeId Grade ID.
|
|
||||||
* @param userId ID of the user to get the grades from. If not defined use site's current user.
|
|
||||||
* @param siteId Site ID. If not defined, current site.
|
|
||||||
* @param ignoreCache True if it should ignore cached data (it will always fail in offline or server down).
|
|
||||||
* @returns Promise to be resolved when the grades are retrieved.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async getGradeItem(
|
|
||||||
courseId: number,
|
|
||||||
gradeId: number,
|
|
||||||
userId?: number,
|
|
||||||
siteId?: string,
|
|
||||||
ignoreCache: boolean = false,
|
|
||||||
): Promise<CoreGradesFormattedRow | null> {
|
|
||||||
const grades = await CoreGrades.getCourseGradesTable(courseId, userId, siteId, ignoreCache);
|
|
||||||
|
|
||||||
if (!grades) {
|
|
||||||
throw new CoreError('Couldn\'t get grade item');
|
|
||||||
}
|
|
||||||
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
return this.getGradesTableRow(grades, gradeId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the label of the selected grade.
|
* Returns the label of the selected grade.
|
||||||
*
|
*
|
||||||
|
@ -460,65 +389,6 @@ export class CoreGradesHelperProvider {
|
||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a row from the grades table.
|
|
||||||
*
|
|
||||||
* @param table JSON object representing a table with data.
|
|
||||||
* @param gradeId Grade Object identifier.
|
|
||||||
* @returns Formatted HTML table.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async getGradesTableRow(table: CoreGradesTable, gradeId: number): Promise<CoreGradesFormattedRow | null> {
|
|
||||||
if (table.tabledata) {
|
|
||||||
const selectedRow = table.tabledata.find(
|
|
||||||
(row) =>
|
|
||||||
row.itemname &&
|
|
||||||
row.itemname.id &&
|
|
||||||
row.itemname.id.substring(0, 3) == 'row' &&
|
|
||||||
parseInt(row.itemname.id.split('_')[1], 10) == gradeId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (selectedRow) {
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
return await this.formatGradeRow(selectedRow);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the rows related to a module from the grades table.
|
|
||||||
*
|
|
||||||
* @param table JSON object representing a table with data.
|
|
||||||
* @param moduleId Grade Object identifier.
|
|
||||||
* @returns Formatted HTML table.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async getModuleGradesTableRows(table: CoreGradesTable, moduleId: number): Promise<CoreGradesFormattedRow[]> {
|
|
||||||
if (!table.tabledata) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find href containing "/mod/xxx/xxx.php".
|
|
||||||
const regex = /href="([^"]*\/mod\/[^"|^/]*\/[^"|^.]*\.php[^"]*)/;
|
|
||||||
|
|
||||||
return Promise.all(table.tabledata.filter((row) => {
|
|
||||||
if (row.itemname && row.itemname.content) {
|
|
||||||
const matches = row.itemname.content.match(regex);
|
|
||||||
|
|
||||||
if (matches && matches.length) {
|
|
||||||
const hrefParams = CoreUrlUtils.extractUrlParams(matches[1]);
|
|
||||||
|
|
||||||
return hrefParams && parseInt(hrefParams.id) === moduleId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
}).map((row) => this.formatGradeRow(row)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get module grades to display.
|
* Get module grades to display.
|
||||||
*
|
*
|
||||||
|
|
|
@ -342,16 +342,6 @@ export class CoreGradesProvider {
|
||||||
return !(course && course.showgrades !== undefined && !course.showgrades);
|
return !(course && course.showgrades !== undefined && !course.showgrades);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether or not WS Grade Items is available.
|
|
||||||
*
|
|
||||||
* @returns True if ws is available, false otherwise.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async isGradeItemsAvailable(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Log Course grades view in Moodle.
|
* Log Course grades view in Moodle.
|
||||||
*
|
*
|
||||||
|
|
|
@ -44,16 +44,6 @@ export class CoreRatingProvider {
|
||||||
static readonly AGGREGATE_CHANGED_EVENT = 'core_rating_aggregate_changed';
|
static readonly AGGREGATE_CHANGED_EVENT = 'core_rating_aggregate_changed';
|
||||||
static readonly RATING_SAVED_EVENT = 'core_rating_rating_saved';
|
static readonly RATING_SAVED_EVENT = 'core_rating_rating_saved';
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns whether the web serivce to add ratings is available.
|
|
||||||
*
|
|
||||||
* @returns If WS is available.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
isAddRatingWSAvailable(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a rating to an item.
|
* Add a rating to an item.
|
||||||
*
|
*
|
||||||
|
|
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
import { Component, OnDestroy, OnInit } from '@angular/core';
|
import { Component, OnDestroy, OnInit } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
import { IonRefresher } from '@ionic/angular';
|
||||||
import { ActivatedRoute, Params } from '@angular/router';
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
|
||||||
import { CoreSite, CoreSiteConfig } from '@classes/site';
|
import { CoreSite, CoreSiteConfig } from '@classes/site';
|
||||||
import { CoreCourse, CoreCourseWSSection } from '@features/course/services/course';
|
import { CoreCourse, CoreCourseWSSection } from '@features/course/services/course';
|
||||||
|
@ -89,14 +89,7 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
|
||||||
|
|
||||||
const module = CoreNavigator.getRouteParam<CoreCourseModuleData>('module');
|
const module = CoreNavigator.getRouteParam<CoreCourseModuleData>('module');
|
||||||
if (module) {
|
if (module) {
|
||||||
let modNavOptions = CoreNavigator.getRouteParam<CoreNavigationOptions>('modNavOptions');
|
const modNavOptions = CoreNavigator.getRouteParam<CoreNavigationOptions>('modNavOptions');
|
||||||
if (!modNavOptions) {
|
|
||||||
// Fallback to old way of passing params. @deprecated since 4.0.
|
|
||||||
const modParams = CoreNavigator.getRouteParam<Params>('modParams');
|
|
||||||
if (modParams) {
|
|
||||||
modNavOptions = { params: modParams };
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CoreCourseHelper.openModule(module, this.siteHomeId, { modNavOptions });
|
CoreCourseHelper.openModule(module, this.siteHomeId, { modNavOptions });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,7 @@ export class CoreSitePluginsCourseFormatHandler extends CoreSitePluginsBaseHandl
|
||||||
*/
|
*/
|
||||||
displayCourseIndex(): boolean {
|
displayCourseIndex(): boolean {
|
||||||
// Use displaysectionselector while is not completely deprecated.
|
// Use displaysectionselector while is not completely deprecated.
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
return this.handlerSchema.displaycourseindex ?? true;
|
||||||
return this.handlerSchema.displaycourseindex ?? this.handlerSchema.displaysectionselector ?? true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -12,11 +12,11 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { Component, OnChanges, Input, ViewChild, Output, EventEmitter, HostBinding } from '@angular/core';
|
import { Component, OnChanges, Input, ViewChild, HostBinding } from '@angular/core';
|
||||||
import { IonRefresher } from '@ionic/angular';
|
import { IonRefresher } from '@ionic/angular';
|
||||||
|
|
||||||
import { CoreCourseFormatComponent } from '@features/course/components/course-format/course-format';
|
import { CoreCourseFormatComponent } from '@features/course/components/course-format/course-format';
|
||||||
import { CoreCourseModuleCompletionData, CoreCourseSection } from '@features/course/services/course-helper';
|
import { CoreCourseSection } from '@features/course/services/course-helper';
|
||||||
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
import { CoreCourseFormatDelegate } from '@features/course/services/format-delegate';
|
||||||
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
import { CoreCourseAnyCourseData } from '@features/courses/services/courses';
|
||||||
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
|
import { CoreSitePlugins, CoreSitePluginsContent } from '@features/siteplugins/services/siteplugins';
|
||||||
|
@ -37,12 +37,6 @@ export class CoreSitePluginsCourseFormatComponent implements OnChanges {
|
||||||
@Input() initialSectionId?: number; // The section to load first (by ID).
|
@Input() initialSectionId?: number; // The section to load first (by ID).
|
||||||
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
@Input() initialSectionNumber?: number; // The section to load first (by number).
|
||||||
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
@Input() moduleId?: number; // The module ID to scroll to. Must be inside the initial selected section.
|
||||||
/**
|
|
||||||
* Notify when any module completion changes.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0. Use CoreEvents instead.
|
|
||||||
*/
|
|
||||||
@Output() completionChanged = new EventEmitter<CoreCourseModuleCompletionData>();
|
|
||||||
|
|
||||||
// Special input, allows access to the parent instance properties and methods.
|
// Special input, allows access to the parent instance properties and methods.
|
||||||
// Please notice that all the other inputs/outputs are also accessible through this instance, so they could be removed.
|
// Please notice that all the other inputs/outputs are also accessible through this instance, so they could be removed.
|
||||||
|
@ -87,8 +81,6 @@ export class CoreSitePluginsCourseFormatComponent implements OnChanges {
|
||||||
initialSectionId: this.initialSectionId,
|
initialSectionId: this.initialSectionId,
|
||||||
initialSectionNumber: this.initialSectionNumber,
|
initialSectionNumber: this.initialSectionNumber,
|
||||||
moduleId: this.moduleId,
|
moduleId: this.moduleId,
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
completionChanged: this.completionChanged,
|
|
||||||
coreCourseFormatComponent: this.coreCourseFormatComponent,
|
coreCourseFormatComponent: this.coreCourseFormatComponent,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,9 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
import { CoreConstants } from '@/core/constants';
|
|
||||||
import { Component, OnInit, OnDestroy, Input, ViewChild, HostBinding } from '@angular/core';
|
import { Component, OnInit, OnDestroy, Input, ViewChild, HostBinding } from '@angular/core';
|
||||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
|
|
||||||
|
|
||||||
import { CoreSiteWSPreSets } from '@classes/site';
|
import { CoreSiteWSPreSets } from '@classes/site';
|
||||||
import {
|
import {
|
||||||
|
@ -22,12 +20,11 @@ import {
|
||||||
CoreCourseModuleSummaryComponent,
|
CoreCourseModuleSummaryComponent,
|
||||||
} from '@features/course/components/module-summary/module-summary';
|
} from '@features/course/components/module-summary/module-summary';
|
||||||
import { CoreCourse } from '@features/course/services/course';
|
import { CoreCourse } from '@features/course/services/course';
|
||||||
import { CoreCourseHelper, CoreCourseModuleData } from '@features/course/services/course-helper';
|
import { CoreCourseModuleData } from '@features/course/services/course-helper';
|
||||||
import {
|
import {
|
||||||
CoreCourseModuleDelegate,
|
CoreCourseModuleDelegate,
|
||||||
CoreCourseModuleMainComponent,
|
CoreCourseModuleMainComponent,
|
||||||
} from '@features/course/services/module-delegate';
|
} from '@features/course/services/module-delegate';
|
||||||
import { CoreCourseModulePrefetchDelegate } from '@features/course/services/module-prefetch-delegate';
|
|
||||||
import {
|
import {
|
||||||
CoreSitePlugins,
|
CoreSitePlugins,
|
||||||
CoreSitePluginsContent,
|
CoreSitePluginsContent,
|
||||||
|
@ -61,31 +58,6 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
||||||
preSets?: CoreSiteWSPreSets;
|
preSets?: CoreSiteWSPreSets;
|
||||||
description?: string;
|
description?: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0, use module.url instead.
|
|
||||||
*/
|
|
||||||
externalUrl?: string;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. It won't be populated anymore.
|
|
||||||
*/
|
|
||||||
refreshIcon = CoreConstants.ICON_REFRESH;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. It won't be populated anymore.
|
|
||||||
*/
|
|
||||||
prefetchStatus?: string;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. It won't be populated anymore.
|
|
||||||
*/
|
|
||||||
prefetchStatusIcon?: string;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. It won't be populated anymore.
|
|
||||||
*/
|
|
||||||
prefetchText?: string;
|
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. It won't be populated anymore.
|
|
||||||
*/
|
|
||||||
size?: string;
|
|
||||||
|
|
||||||
collapsibleFooterAppearOnBottom = true;
|
collapsibleFooterAppearOnBottom = true;
|
||||||
|
|
||||||
displayOpenInBrowser = true;
|
displayOpenInBrowser = true;
|
||||||
|
@ -142,8 +114,6 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
||||||
|
|
||||||
// Get the data for the context menu.
|
// Get the data for the context menu.
|
||||||
this.description = this.module.description;
|
this.description = this.module.description;
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
this.externalUrl = this.module.url;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -178,15 +148,6 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Expand the description.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
expandDescription(): void {
|
|
||||||
this.openModuleSummary();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens a module summary page.
|
* Opens a module summary page.
|
||||||
*/
|
*/
|
||||||
|
@ -221,50 +182,7 @@ export class CoreSitePluginsModuleIndexComponent implements OnInit, OnDestroy, C
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prefetch the module.
|
* @inheritdoc
|
||||||
*
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async prefetch(): Promise<void> {
|
|
||||||
try {
|
|
||||||
// We need to call getDownloadSize, the package might have been updated.
|
|
||||||
const size = await CoreCourseModulePrefetchDelegate.getModuleDownloadSize(this.module, this.courseId, true);
|
|
||||||
|
|
||||||
await CoreDomUtils.confirmDownloadSize(size);
|
|
||||||
|
|
||||||
await CoreCourseModulePrefetchDelegate.prefetchModule(this.module, this.courseId, true);
|
|
||||||
} catch (error) {
|
|
||||||
if (!this.isDestroyed) {
|
|
||||||
CoreDomUtils.showErrorModalDefault(error, 'core.errordownloading', true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Confirm and remove downloaded files.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async removeFiles(): Promise<void> {
|
|
||||||
let modal: CoreIonLoadingElement | undefined;
|
|
||||||
|
|
||||||
try {
|
|
||||||
await CoreDomUtils.showDeleteConfirm('addon.storagemanager.confirmdeletedatafrom', { name: this.module.name });
|
|
||||||
|
|
||||||
modal = await CoreDomUtils.showModalLoading();
|
|
||||||
|
|
||||||
await CoreCourseHelper.removeModuleStoredData(this.module, this.courseId);
|
|
||||||
} catch (error) {
|
|
||||||
if (error) {
|
|
||||||
CoreDomUtils.showErrorModal(error);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
modal?.dismiss();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component destroyed.
|
|
||||||
*/
|
*/
|
||||||
ngOnDestroy(): void {
|
ngOnDestroy(): void {
|
||||||
this.isDestroyed = true;
|
this.isDestroyed = true;
|
||||||
|
|
|
@ -391,16 +391,6 @@ export class CoreSitePluginsProvider {
|
||||||
await site.invalidateWsCacheForKey(this.getContentCacheKey(component, callback, args || {}));
|
await site.invalidateWsCacheForKey(this.getContentCacheKey(component, callback, args || {}));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if the get content WS is available.
|
|
||||||
*
|
|
||||||
* @returns If get content WS is available.
|
|
||||||
* @deprecated since 4.0
|
|
||||||
*/
|
|
||||||
isGetContentAvailable(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a handler is enabled for a certain course.
|
* Check if a handler is enabled for a certain course.
|
||||||
*
|
*
|
||||||
|
@ -904,10 +894,6 @@ export type CoreSitePluginsCourseModuleHandlerData = CoreSitePluginsHandlerCommo
|
||||||
export type CoreSitePluginsCourseFormatHandlerData = CoreSitePluginsHandlerCommonData & {
|
export type CoreSitePluginsCourseFormatHandlerData = CoreSitePluginsHandlerCommonData & {
|
||||||
canviewallsections?: boolean;
|
canviewallsections?: boolean;
|
||||||
displayenabledownload?: boolean;
|
displayenabledownload?: boolean;
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Use displaycourseindex instead.
|
|
||||||
*/
|
|
||||||
displaysectionselector?: boolean;
|
|
||||||
displaycourseindex?: boolean;
|
displaycourseindex?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -109,26 +109,6 @@ export class CoreUserProvider {
|
||||||
return !!site?.wsAvailable('core_enrol_search_users');
|
return !!site?.wsAvailable('core_enrol_search_users');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if WS to update profile picture is available in site.
|
|
||||||
*
|
|
||||||
* @returns Promise resolved with boolean: whether it's available.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
async canUpdatePicture(): Promise<boolean> {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if WS to search participants is available in site.
|
|
||||||
*
|
|
||||||
* @returns Whether it's available.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
canUpdatePictureInSite(): boolean {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the given user profile picture.
|
* Change the given user profile picture.
|
||||||
*
|
*
|
||||||
|
|
|
@ -411,63 +411,6 @@ export class CoreSitesProvider {
|
||||||
return new CoreLoginError(options);
|
return new CoreLoginError(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a site exists.
|
|
||||||
*
|
|
||||||
* @param siteUrl URL of the site to check.
|
|
||||||
* @returns A promise to be resolved if the site exists.
|
|
||||||
* @deprecated since 4.0. Now the app calls uses tool_mobile_get_public_config to check if site exists.
|
|
||||||
*/
|
|
||||||
async siteExists(siteUrl: string): Promise<void> {
|
|
||||||
let data: CoreSitesLoginTokenResponse;
|
|
||||||
|
|
||||||
// Use a valid path first.
|
|
||||||
siteUrl = CoreUrlUtils.removeUrlParams(siteUrl);
|
|
||||||
|
|
||||||
try {
|
|
||||||
const lang = await CoreLang.getCurrentLanguage(CoreLangFormat.LMS);
|
|
||||||
|
|
||||||
data = await Http.post(`${siteUrl}/login/token.php?lang=${lang}`, { appsitecheck: 1 })
|
|
||||||
.pipe(timeout(CoreWS.getRequestTimeout()))
|
|
||||||
.toPromise();
|
|
||||||
} catch (error) {
|
|
||||||
throw this.createCannotConnectLoginError(null, {
|
|
||||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
|
||||||
errorcode: 'sitecheckfailed',
|
|
||||||
errorDetails: CoreDomUtils.getErrorMessage(error) ?? undefined,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data === null) {
|
|
||||||
// Cannot connect.
|
|
||||||
throw this.createCannotConnectLoginError(null, {
|
|
||||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
|
||||||
errorcode: 'appsitecheckfailed',
|
|
||||||
errorDetails: 'A request to /login/token.php with appsitecheck=1 returned an empty response',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.errorcode && (data.errorcode == 'enablewsdescription' || data.errorcode == 'requirecorrectaccess')) {
|
|
||||||
throw this.createCannotConnectLoginError(siteUrl, {
|
|
||||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
|
||||||
critical: data.errorcode == 'enablewsdescription',
|
|
||||||
errorcode: data.errorcode,
|
|
||||||
errorDetails: data.error,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.error && data.error == 'Web services must be enabled in Advanced features.') {
|
|
||||||
throw this.createCannotConnectLoginError(siteUrl, {
|
|
||||||
supportConfig: await CoreUserGuestSupportConfig.forSite(siteUrl),
|
|
||||||
critical: true,
|
|
||||||
errorcode: 'enablewsdescription',
|
|
||||||
errorDetails: data.error,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other errors are not being checked because invalid login will be always raised and we cannot differ them.
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a user token from the server.
|
* Gets a user token from the server.
|
||||||
*
|
*
|
||||||
|
@ -702,16 +645,6 @@ export class CoreSitesProvider {
|
||||||
return <string> Md5.hashAsciiStr(siteUrl + username);
|
return <string> Md5.hashAsciiStr(siteUrl + username);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Function for determine which service we should use (default or extended plugin).
|
|
||||||
*
|
|
||||||
* @returns The service shortname.
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
determineService(): string {
|
|
||||||
return CoreConstants.CONFIG.wsservice;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Visit a site link.
|
* Visit a site link.
|
||||||
*
|
*
|
||||||
|
@ -2184,13 +2117,6 @@ export type CoreSiteCheckResponse = {
|
||||||
*/
|
*/
|
||||||
service: string;
|
service: string;
|
||||||
|
|
||||||
/**
|
|
||||||
* Code of the warning message to show to the user.
|
|
||||||
*
|
|
||||||
* @deprecated since 4.0.
|
|
||||||
*/
|
|
||||||
warning?: string;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Site public config (if available).
|
* Site public config (if available).
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -49,8 +49,6 @@ import { CoreSites } from '@services/sites';
|
||||||
import { NavigationStart } from '@angular/router';
|
import { NavigationStart } from '@angular/router';
|
||||||
import { filter } from 'rxjs/operators';
|
import { filter } from 'rxjs/operators';
|
||||||
import { Subscription } from 'rxjs';
|
import { Subscription } from 'rxjs';
|
||||||
import { CoreDirectivesRegistry } from '@singletons/directives-registry';
|
|
||||||
import { CoreDom } from '@singletons/dom';
|
|
||||||
import { CoreNetwork } from '@services/network';
|
import { CoreNetwork } from '@services/network';
|
||||||
import { CoreSiteError } from '@classes/errors/siteerror';
|
import { CoreSiteError } from '@classes/errors/siteerror';
|
||||||
import { CoreUserSupport } from '@features/user/services/support';
|
import { CoreUserSupport } from '@features/user/services/support';
|
||||||
|
@ -99,20 +97,6 @@ export class CoreDomUtilsProvider {
|
||||||
this.debugDisplay = debugDisplay != 0;
|
this.debugDisplay = debugDisplay != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Equivalent to element.closest(). If the browser doesn't support element.closest, it will
|
|
||||||
* traverse the parents to achieve the same functionality.
|
|
||||||
* Returns the closest ancestor of the current element (or the current element itself) which matches the selector.
|
|
||||||
*
|
|
||||||
* @param element DOM Element.
|
|
||||||
* @param selector Selector to search.
|
|
||||||
* @returns Closest ancestor.
|
|
||||||
* @deprecated since 4.0. Not needed anymore since it's supported on both Android and iOS. Use closest instead.
|
|
||||||
*/
|
|
||||||
closest(element: Element | undefined | null, selector: string): Element | null {
|
|
||||||
return element?.closest(selector) ?? null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If the download size is higher than a certain threshold shows a confirm dialog.
|
* If the download size is higher than a certain threshold shows a confirm dialog.
|
||||||
*
|
*
|
||||||
|
@ -396,91 +380,6 @@ export class CoreDomUtilsProvider {
|
||||||
return this.convertToElement(html).children[0].getAttribute(attribute);
|
return this.convertToElement(html).children[0].getAttribute(attribute);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns height of an element.
|
|
||||||
*
|
|
||||||
* @param element DOM element to measure.
|
|
||||||
* @param usePadding Whether to use padding to calculate the measure.
|
|
||||||
* @param useMargin Whether to use margin to calculate the measure.
|
|
||||||
* @param useBorder Whether to use borders to calculate the measure.
|
|
||||||
* @param innerMeasure If inner measure is needed: padding, margin or borders will be substracted.
|
|
||||||
* @returns Height in pixels.
|
|
||||||
* @deprecated since 4.0 Use getBoundingClientRect.height instead.
|
|
||||||
*/
|
|
||||||
getElementHeight(
|
|
||||||
element: HTMLElement,
|
|
||||||
usePadding?: boolean,
|
|
||||||
useMargin?: boolean,
|
|
||||||
useBorder?: boolean,
|
|
||||||
innerMeasure?: boolean,
|
|
||||||
): number {
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
return this.getElementMeasure(element, false, usePadding, useMargin, useBorder, innerMeasure);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns height or width of an element.
|
|
||||||
*
|
|
||||||
* @param element DOM element to measure.
|
|
||||||
* @param getWidth Whether to get width or height.
|
|
||||||
* @param usePadding Whether to use padding to calculate the measure.
|
|
||||||
* @param useMargin Whether to use margin to calculate the measure.
|
|
||||||
* @param useBorder Whether to use borders to calculate the measure.
|
|
||||||
* @param innerMeasure If inner measure is needed: padding, margin or borders will be substracted.
|
|
||||||
* @returns Measure in pixels.
|
|
||||||
* @deprecated since 4.0. Use getBoundingClientRect.height or width instead.
|
|
||||||
*/
|
|
||||||
getElementMeasure(
|
|
||||||
element: HTMLElement,
|
|
||||||
getWidth?: boolean,
|
|
||||||
usePadding?: boolean,
|
|
||||||
useMargin?: boolean,
|
|
||||||
useBorder?: boolean,
|
|
||||||
innerMeasure?: boolean,
|
|
||||||
): number {
|
|
||||||
const offsetMeasure = getWidth ? 'offsetWidth' : 'offsetHeight';
|
|
||||||
const measureName = getWidth ? 'width' : 'height';
|
|
||||||
const clientMeasure = getWidth ? 'clientWidth' : 'clientHeight';
|
|
||||||
const priorSide = getWidth ? 'Left' : 'Top';
|
|
||||||
const afterSide = getWidth ? 'Right' : 'Bottom';
|
|
||||||
let measure = element[offsetMeasure] || element[measureName] || element[clientMeasure] || 0;
|
|
||||||
|
|
||||||
// Measure not correctly taken.
|
|
||||||
if (measure <= 0) {
|
|
||||||
const style = getComputedStyle(element);
|
|
||||||
if (style?.display == '') {
|
|
||||||
element.style.display = 'inline-block';
|
|
||||||
measure = element[offsetMeasure] || element[measureName] || element[clientMeasure] || 0;
|
|
||||||
element.style.display = '';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usePadding || useMargin || useBorder) {
|
|
||||||
const computedStyle = getComputedStyle(element);
|
|
||||||
let surround = 0;
|
|
||||||
|
|
||||||
if (usePadding) {
|
|
||||||
surround += this.getComputedStyleMeasure(computedStyle, 'padding' + priorSide) +
|
|
||||||
this.getComputedStyleMeasure(computedStyle, 'padding' + afterSide);
|
|
||||||
}
|
|
||||||
if (useMargin) {
|
|
||||||
surround += this.getComputedStyleMeasure(computedStyle, 'margin' + priorSide) +
|
|
||||||
this.getComputedStyleMeasure(computedStyle, 'margin' + afterSide);
|
|
||||||
}
|
|
||||||
if (useBorder) {
|
|
||||||
surround += this.getComputedStyleMeasure(computedStyle, 'border' + priorSide + 'Width') +
|
|
||||||
this.getComputedStyleMeasure(computedStyle, 'border' + afterSide + 'Width');
|
|
||||||
}
|
|
||||||
if (innerMeasure) {
|
|
||||||
measure = measure > surround ? measure - surround : 0;
|
|
||||||
} else {
|
|
||||||
measure += surround;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return measure;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the computed style measure or 0 if not found or NaN.
|
* Returns the computed style measure or 0 if not found or NaN.
|
||||||
*
|
*
|
||||||
|
@ -492,62 +391,6 @@ export class CoreDomUtilsProvider {
|
||||||
return parseInt(style[measure], 10) || 0;
|
return parseInt(style[measure], 10) || 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns width of an element.
|
|
||||||
*
|
|
||||||
* @param element DOM element to measure.
|
|
||||||
* @param usePadding Whether to use padding to calculate the measure.
|
|
||||||
* @param useMargin Whether to use margin to calculate the measure.
|
|
||||||
* @param useBorder Whether to use borders to calculate the measure.
|
|
||||||
* @param innerMeasure If inner measure is needed: padding, margin or borders will be substracted.
|
|
||||||
* @returns Width in pixels.
|
|
||||||
* @deprecated since 4.0. Use getBoundingClientRect.width instead.
|
|
||||||
*/
|
|
||||||
getElementWidth(
|
|
||||||
element: HTMLElement,
|
|
||||||
usePadding?: boolean,
|
|
||||||
useMargin?: boolean,
|
|
||||||
useBorder?: boolean,
|
|
||||||
innerMeasure?: boolean,
|
|
||||||
): number {
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
return this.getElementMeasure(element, true, usePadding, useMargin, useBorder, innerMeasure);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the position of a element relative to another element.
|
|
||||||
*
|
|
||||||
* @param element Element to search in.
|
|
||||||
* @param selector Selector to find the element to gets the position.
|
|
||||||
* @param positionParentClass Parent Class where to stop calculating the position. Default inner-scroll.
|
|
||||||
* @returns positionLeft, positionTop of the element relative to.
|
|
||||||
* @deprecated since 4.0. Use CoreDom.getRelativeElementPosition instead.
|
|
||||||
*/
|
|
||||||
getElementXY(element: HTMLElement, selector?: string, positionParentClass = 'inner-scroll'): [number, number] | null {
|
|
||||||
if (selector) {
|
|
||||||
const foundElement = element.querySelector<HTMLElement>(selector);
|
|
||||||
if (!foundElement) {
|
|
||||||
// Element not found.
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
element = foundElement;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parent = element.closest<HTMLElement>(`.${positionParentClass}`);
|
|
||||||
if (!parent) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const position = CoreDom.getRelativeElementPosition(element, parent);
|
|
||||||
|
|
||||||
// Calculate the top and left positions.
|
|
||||||
return [
|
|
||||||
Math.ceil(position.x),
|
|
||||||
Math.ceil(position.y),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Given a message, it deduce if it's a network error.
|
* Given a message, it deduce if it's a network error.
|
||||||
*
|
*
|
||||||
|
@ -639,19 +482,6 @@ export class CoreDomUtilsProvider {
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve component/directive instance.
|
|
||||||
* Please use this function only if you cannot retrieve the instance using parent/child methods: ViewChild (or similar)
|
|
||||||
* or Angular's injection.
|
|
||||||
*
|
|
||||||
* @param element The root element of the component/directive.
|
|
||||||
* @returns The instance, undefined if not found.
|
|
||||||
* @deprecated since 4.0. Use CoreDirectivesRegistry instead.
|
|
||||||
*/
|
|
||||||
getInstanceByElement<T = unknown>(element: Element): T | undefined {
|
|
||||||
return CoreDirectivesRegistry.resolve<T>(element) ?? undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether an error is an error caused because the user canceled a showConfirm.
|
* Check whether an error is an error caused because the user canceled a showConfirm.
|
||||||
*
|
*
|
||||||
|
@ -672,36 +502,6 @@ export class CoreDomUtilsProvider {
|
||||||
return error instanceof CoreSilentError;
|
return error instanceof CoreSilentError;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Wait an element to exists using the findFunction.
|
|
||||||
*
|
|
||||||
* @param findFunction The function used to find the element.
|
|
||||||
* @param retries Number of retries before giving up.
|
|
||||||
* @param retryAfter Milliseconds to wait before retrying if the element wasn't found.
|
|
||||||
* @returns Resolved if found, rejected if too many tries.
|
|
||||||
* @deprecated since 4.0. Use CoreDom.waitToBeInsideElement instead.
|
|
||||||
*/
|
|
||||||
async waitElementToExist(
|
|
||||||
findFunction: () => HTMLElement | null,
|
|
||||||
retries: number = 100,
|
|
||||||
retryAfter: number = 100,
|
|
||||||
): Promise<HTMLElement> {
|
|
||||||
const element = findFunction();
|
|
||||||
|
|
||||||
if (!element && retries === 0) {
|
|
||||||
throw Error('Element not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!element) {
|
|
||||||
await CoreUtils.wait(retryAfter);
|
|
||||||
|
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
return this.waitElementToExist(findFunction, retries - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return element;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handle bootstrap tooltips in a certain element.
|
* Handle bootstrap tooltips in a certain element.
|
||||||
*
|
*
|
||||||
|
@ -853,28 +653,6 @@ export class CoreDomUtilsProvider {
|
||||||
return element.innerHTML;
|
return element.innerHTML;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a component/directive instance using the DOM Element.
|
|
||||||
*
|
|
||||||
* @param element The root element of the component/directive.
|
|
||||||
* @deprecated since 4.0. It's no longer necessary to remove instances.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
removeInstanceByElement(element: Element): void {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove a component/directive instance using the ID.
|
|
||||||
*
|
|
||||||
* @param id The ID to remove.
|
|
||||||
* @deprecated since 4.0. It's no longer necessary to remove instances.
|
|
||||||
*/
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
||||||
removeInstanceById(id: string): void {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Search for certain classes in an element contents and replace them with the specified new values.
|
* Search for certain classes in an element contents and replace them with the specified new values.
|
||||||
*
|
*
|
||||||
|
@ -998,67 +776,6 @@ export class CoreDomUtilsProvider {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Scroll to a certain element.
|
|
||||||
*
|
|
||||||
* @param content Not used anymore.
|
|
||||||
* @param element The element to scroll to.
|
|
||||||
* @param scrollParentClass Not used anymore.
|
|
||||||
* @param duration Duration of the scroll animation in milliseconds.
|
|
||||||
* @returns True if the element is found, false otherwise.
|
|
||||||
* @deprecated since 4.0. Use CoreDom.scrollToElement instead.
|
|
||||||
*/
|
|
||||||
scrollToElement(content: IonContent, element: HTMLElement, scrollParentClass?: string, duration?: number): boolean {
|
|
||||||
CoreDom.scrollToElement(element, undefined, { duration });
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Scroll to a certain element using a selector to find it.
|
|
||||||
*
|
|
||||||
* @param container The element that contains the element that must be scrolled.
|
|
||||||
* @param content Not used anymore.
|
|
||||||
* @param selector Selector to find the element to scroll to.
|
|
||||||
* @param scrollParentClass Not used anymore.
|
|
||||||
* @param duration Duration of the scroll animation in milliseconds.
|
|
||||||
* @returns True if the element is found, false otherwise.
|
|
||||||
* @deprecated since 4.0. Use CoreDom.scrollToElement instead.
|
|
||||||
*/
|
|
||||||
scrollToElementBySelector(
|
|
||||||
container: HTMLElement | null,
|
|
||||||
content: unknown | null,
|
|
||||||
selector: string,
|
|
||||||
scrollParentClass?: string,
|
|
||||||
duration?: number,
|
|
||||||
): boolean {
|
|
||||||
if (!container || !content) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreDom.scrollToElement(container, selector, { duration });
|
|
||||||
|
|
||||||
return true;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Search for an input with error (core-input-error directive) and scrolls to it if found.
|
|
||||||
*
|
|
||||||
* @param container The element that contains the element that must be scrolled.
|
|
||||||
* @returns True if the element is found, false otherwise.
|
|
||||||
* @deprecated since 4.0. Use CoreDom.scrollToInputError instead.
|
|
||||||
*/
|
|
||||||
scrollToInputError(container: HTMLElement | null): boolean {
|
|
||||||
if (!container) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
CoreDom.scrollToInputError(container);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether debug messages should be displayed.
|
* Set whether debug messages should be displayed.
|
||||||
*
|
*
|
||||||
|
@ -1669,17 +1386,6 @@ export class CoreDomUtilsProvider {
|
||||||
return loader;
|
return loader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Stores a component/directive instance.
|
|
||||||
*
|
|
||||||
* @param element The root element of the component/directive.
|
|
||||||
* @param instance The instance to store.
|
|
||||||
* @deprecated since 4.0. Use CoreDirectivesRegistry instead.
|
|
||||||
*/
|
|
||||||
storeInstanceByElement(element: Element, instance: unknown): void {
|
|
||||||
CoreDirectivesRegistry.register(element, instance);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if an element supports input via keyboard.
|
* Check if an element supports input via keyboard.
|
||||||
*
|
*
|
||||||
|
|
|
@ -298,18 +298,6 @@ export class CoreTextUtilsProvider {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Concatenate two paths, adding a slash between them if needed.
|
|
||||||
*
|
|
||||||
* @param leftPath Left path.
|
|
||||||
* @param rightPath Right path.
|
|
||||||
* @returns Concatenated path.
|
|
||||||
* @deprecated since 4.0. Use CorePath instead.
|
|
||||||
*/
|
|
||||||
concatenatePaths(leftPath: string, rightPath: string): string {
|
|
||||||
return CorePath.concatenatePaths(leftPath, rightPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert some HTML as text into an HTMLElement. This HTML is put inside a div or a body.
|
* Convert some HTML as text into an HTMLElement. This HTML is put inside a div or a body.
|
||||||
* This function is the same as in DomUtils, but we cannot use that one because of circular dependencies.
|
* This function is the same as in DomUtils, but we cannot use that one because of circular dependencies.
|
||||||
|
|
|
@ -16,7 +16,6 @@ import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
import moment, { LongDateFormatKey } from 'moment-timezone';
|
import moment, { LongDateFormatKey } from 'moment-timezone';
|
||||||
import { makeSingleton, Translate } from '@singletons';
|
import { makeSingleton, Translate } from '@singletons';
|
||||||
import { CoreTime } from '@singletons/time';
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* "Utils" service with helper functions for date and time.
|
* "Utils" service with helper functions for date and time.
|
||||||
|
@ -155,52 +154,6 @@ export class CoreTimeUtilsProvider {
|
||||||
return fixed;
|
return fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns years, months, days, hours, minutes and seconds in a human readable format.
|
|
||||||
*
|
|
||||||
* @param seconds A number of seconds
|
|
||||||
* @param precision Number of elements to have in precision.
|
|
||||||
* @returns Seconds in a human readable format.
|
|
||||||
* @deprecated since 4.0. Use CoreTime.formatTime instead.
|
|
||||||
*/
|
|
||||||
formatTime(seconds: number, precision = 2): string {
|
|
||||||
return CoreTime.formatTime(seconds, precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Converts a number of seconds into a short human readable format: minutes and seconds, in fromat: 3' 27''.
|
|
||||||
*
|
|
||||||
* @param duration Seconds
|
|
||||||
* @returns Short human readable text.
|
|
||||||
* @deprecated since 4.0. Use CoreTime.formatTimeShort instead.
|
|
||||||
*/
|
|
||||||
formatTimeShort(duration: number): string {
|
|
||||||
return CoreTime.formatTimeShort(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns hours, minutes and seconds in a human readable format.
|
|
||||||
*
|
|
||||||
* @param duration Duration in seconds
|
|
||||||
* @param precision Number of elements to have in precision. 0 or undefined to full precission.
|
|
||||||
* @returns Duration in a human readable format.
|
|
||||||
* @deprecated since 4.0. Use CoreTime.formatTime instead.
|
|
||||||
*/
|
|
||||||
formatDuration(duration: number, precision?: number): string {
|
|
||||||
return CoreTime.formatTime(duration, precision);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns duration in a short human readable format: minutes and seconds, in fromat: 3' 27''.
|
|
||||||
*
|
|
||||||
* @param duration Duration in seconds
|
|
||||||
* @returns Duration in a short human readable format.
|
|
||||||
* @deprecated since 4.0. Use CoreTime.formatTimeShort instead.
|
|
||||||
*/
|
|
||||||
formatDurationShort(duration: number): string {
|
|
||||||
return CoreTime.formatTimeShort(duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the current timestamp in a "readable" format: YYYYMMDDHHmmSS.
|
* Return the current timestamp in a "readable" format: YYYYMMDDHHmmSS.
|
||||||
*
|
*
|
||||||
|
|
|
@ -39,8 +39,6 @@ export interface CoreEventsData {
|
||||||
[CoreEvents.SITE_ADDED]: CoreEventSiteAddedData;
|
[CoreEvents.SITE_ADDED]: CoreEventSiteAddedData;
|
||||||
[CoreEvents.SITE_DELETED]: CoreSite;
|
[CoreEvents.SITE_DELETED]: CoreSite;
|
||||||
[CoreEvents.SESSION_EXPIRED]: CoreEventSessionExpiredData;
|
[CoreEvents.SESSION_EXPIRED]: CoreEventSessionExpiredData;
|
||||||
// eslint-disable-next-line deprecation/deprecation
|
|
||||||
[CoreEvents.CORE_LOADING_CHANGED]: CoreEventLoadingChangedData;
|
|
||||||
[CoreEvents.COURSE_STATUS_CHANGED]: CoreEventCourseStatusChanged;
|
[CoreEvents.COURSE_STATUS_CHANGED]: CoreEventCourseStatusChanged;
|
||||||
[CoreEvents.PACKAGE_STATUS_CHANGED]: CoreEventPackageStatusChanged;
|
[CoreEvents.PACKAGE_STATUS_CHANGED]: CoreEventPackageStatusChanged;
|
||||||
[CoreEvents.USER_DELETED]: CoreEventUserDeletedData;
|
[CoreEvents.USER_DELETED]: CoreEventUserDeletedData;
|
||||||
|
@ -104,10 +102,6 @@ export class CoreEvents {
|
||||||
static readonly APP_LAUNCHED_URL = 'app_launched_url'; // App opened with a certain URL (custom URL scheme).
|
static readonly APP_LAUNCHED_URL = 'app_launched_url'; // App opened with a certain URL (custom URL scheme).
|
||||||
static readonly FILE_SHARED = 'file_shared';
|
static readonly FILE_SHARED = 'file_shared';
|
||||||
static readonly KEYBOARD_CHANGE = 'keyboard_change';
|
static readonly KEYBOARD_CHANGE = 'keyboard_change';
|
||||||
/**
|
|
||||||
* @deprecated since 4.0. Use CoreDirectivesRegistry promises instead.
|
|
||||||
*/
|
|
||||||
static readonly CORE_LOADING_CHANGED = 'core_loading_changed';
|
|
||||||
static readonly ORIENTATION_CHANGE = 'orientation_change';
|
static readonly ORIENTATION_CHANGE = 'orientation_change';
|
||||||
static readonly SEND_ON_ENTER_CHANGED = 'send_on_enter_changed';
|
static readonly SEND_ON_ENTER_CHANGED = 'send_on_enter_changed';
|
||||||
static readonly SELECT_COURSE_TAB = 'select_course_tab';
|
static readonly SELECT_COURSE_TAB = 'select_course_tab';
|
||||||
|
|
Loading…
Reference in New Issue