forked from EVOgeek/Vmeda.Online
		
	
						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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user