forked from EVOgeek/Vmeda.Online
		
	MOBILE-3686 courses: Merge available courses and search courses pages
This commit is contained in:
		
							parent
							
								
									55b6d9f76a
								
							
						
					
					
						commit
						5ac62106bf
					
				| @ -33,16 +33,10 @@ const routes: Routes = [ | |||||||
|                 .then(m => m.CoreCoursesCategoriesPageModule), |                 .then(m => m.CoreCoursesCategoriesPageModule), | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         path: 'all', |         path: 'list', | ||||||
|         loadChildren: () => |         loadChildren: () => | ||||||
|             import('./pages/available-courses/available-courses.module') |             import('./pages/list/list.module') | ||||||
|                 .then(m => m.CoreCoursesAvailableCoursesPageModule), |                 .then(m => m.CoreCoursesListPageModule), | ||||||
|     }, |  | ||||||
|     { |  | ||||||
|         path: 'search', |  | ||||||
|         loadChildren: () => |  | ||||||
|             import('./pages/search/search.module') |  | ||||||
|                 .then(m => m.CoreCoursesSearchPageModule), |  | ||||||
|     }, |     }, | ||||||
|     { |     { | ||||||
|         path: 'my', |         path: 'my', | ||||||
|  | |||||||
| @ -1,19 +0,0 @@ | |||||||
| <ion-header> |  | ||||||
|     <ion-toolbar> |  | ||||||
|         <ion-buttons slot="start"> |  | ||||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> |  | ||||||
|         </ion-buttons> |  | ||||||
|         <h1>{{ 'core.courses.availablecourses' | translate }}</h1> |  | ||||||
|     </ion-toolbar> |  | ||||||
| </ion-header> |  | ||||||
| <ion-content> |  | ||||||
|     <ion-refresher slot="fixed" [disabled]="!coursesLoaded" (ionRefresh)="refreshCourses($event.target)"> |  | ||||||
|         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> |  | ||||||
|     </ion-refresher> |  | ||||||
|     <core-loading [hideUntil]="coursesLoaded"> |  | ||||||
|         <ng-container *ngIf="courses.length > 0"> |  | ||||||
|             <core-courses-course-list-item *ngFor="let course of courses" [course]="course"></core-courses-course-list-item> |  | ||||||
|         </ng-container> |  | ||||||
|         <core-empty-box *ngIf="!courses.length" icon="fas-graduation-cap" [message]="'core.courses.nocourses' | translate"></core-empty-box> |  | ||||||
|     </core-loading> |  | ||||||
| </ion-content> |  | ||||||
| @ -1,41 +0,0 @@ | |||||||
| // (C) Copyright 2015 Moodle Pty Ltd.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| import { NgModule } from '@angular/core'; |  | ||||||
| import { RouterModule, Routes } from '@angular/router'; |  | ||||||
| 
 |  | ||||||
| import { CoreSharedModule } from '@/core/shared.module'; |  | ||||||
| import { CoreCoursesComponentsModule } from '../../components/components.module'; |  | ||||||
| 
 |  | ||||||
| import { CoreCoursesAvailableCoursesPage } from './available-courses'; |  | ||||||
| 
 |  | ||||||
| const routes: Routes = [ |  | ||||||
|     { |  | ||||||
|         path: '', |  | ||||||
|         component: CoreCoursesAvailableCoursesPage, |  | ||||||
|     }, |  | ||||||
| ]; |  | ||||||
| 
 |  | ||||||
| @NgModule({ |  | ||||||
|     imports: [ |  | ||||||
|         RouterModule.forChild(routes), |  | ||||||
|         CoreSharedModule, |  | ||||||
|         CoreCoursesComponentsModule, |  | ||||||
|     ], |  | ||||||
|     declarations: [ |  | ||||||
|         CoreCoursesAvailableCoursesPage, |  | ||||||
|     ], |  | ||||||
|     exports: [RouterModule], |  | ||||||
| }) |  | ||||||
| export class CoreCoursesAvailableCoursesPageModule { } |  | ||||||
| @ -1,78 +0,0 @@ | |||||||
| // (C) Copyright 2015 Moodle Pty Ltd.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| import { Component, OnInit } from '@angular/core'; |  | ||||||
| import { IonRefresher } from '@ionic/angular'; |  | ||||||
| 
 |  | ||||||
| import { CoreSites } from '@services/sites'; |  | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; |  | ||||||
| import { CoreCourses, CoreCourseSearchedData } from '../../services/courses'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Page that displays available courses in current site. |  | ||||||
|  */ |  | ||||||
| @Component({ |  | ||||||
|     selector: 'page-core-courses-available-courses', |  | ||||||
|     templateUrl: 'available-courses.html', |  | ||||||
| }) |  | ||||||
| export class CoreCoursesAvailableCoursesPage implements OnInit { |  | ||||||
| 
 |  | ||||||
|     courses: CoreCourseSearchedData[] = []; |  | ||||||
|     coursesLoaded = false; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * View loaded. |  | ||||||
|      */ |  | ||||||
|     ngOnInit(): void { |  | ||||||
|         this.loadCourses().finally(() => { |  | ||||||
|             this.coursesLoaded = true; |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Load the courses. |  | ||||||
|      * |  | ||||||
|      * @return Promise resolved when done. |  | ||||||
|      */ |  | ||||||
|     protected async loadCourses(): Promise<void> { |  | ||||||
|         const frontpageCourseId = CoreSites.getCurrentSiteHomeId(); |  | ||||||
| 
 |  | ||||||
|         try { |  | ||||||
|             const courses = await CoreCourses.getCoursesByField(); |  | ||||||
| 
 |  | ||||||
|             this.courses = courses.filter((course) => course.id != frontpageCourseId); |  | ||||||
|         } catch (error) { |  | ||||||
|             CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Refresh the courses. |  | ||||||
|      * |  | ||||||
|      * @param refresher Refresher. |  | ||||||
|      */ |  | ||||||
|     refreshCourses(refresher: IonRefresher): void { |  | ||||||
|         const promises: Promise<void>[] = []; |  | ||||||
| 
 |  | ||||||
|         promises.push(CoreCourses.invalidateUserCourses()); |  | ||||||
|         promises.push(CoreCourses.invalidateCoursesByField()); |  | ||||||
| 
 |  | ||||||
|         Promise.all(promises).finally(() => { |  | ||||||
|             this.loadCourses().finally(() => { |  | ||||||
|                 refresher?.complete(); |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -167,7 +167,7 @@ export class CoreCoursesDashboardPage implements OnInit, OnDestroy { | |||||||
|      * Go to search courses. |      * Go to search courses. | ||||||
|      */ |      */ | ||||||
|     async openSearch(): Promise<void> { |     async openSearch(): Promise<void> { | ||||||
|         CoreNavigator.navigateToSitePath('/courses/search'); |         CoreNavigator.navigateToSitePath('/courses/list', { params : { mode: 'search' } }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
							
								
								
									
										36
									
								
								src/core/features/courses/pages/list/list.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								src/core/features/courses/pages/list/list.html
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | |||||||
|  | <ion-header> | ||||||
|  |     <ion-toolbar> | ||||||
|  |         <ion-buttons slot="start"> | ||||||
|  |             <ion-back-button [text]="'core.back' | translate"></ion-back-button> | ||||||
|  |         </ion-buttons> | ||||||
|  |         <h1>{{ 'core.courses.availablecourses' | translate }}</h1> | ||||||
|  |     </ion-toolbar> | ||||||
|  | </ion-header> | ||||||
|  | <ion-content> | ||||||
|  |     <ion-refresher slot="fixed" [disabled]="!coursesLoaded" (ionRefresh)="refreshCourses($event.target)"> | ||||||
|  |         <ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content> | ||||||
|  |     </ion-refresher> | ||||||
|  |      | ||||||
|  |     <core-search-box *ngIf="searchEnabled" (onSubmit)="search($event)" (onClear)="clearSearch()" | ||||||
|  |         [placeholder]="'core.courses.search' | translate" [searchLabel]="'core.courses.search' | translate" [autoFocus]="searchMode" | ||||||
|  |         searchArea="CoreCoursesSearch"></core-search-box> | ||||||
|  | 
 | ||||||
|  |     <core-loading [hideUntil]="coursesLoaded"> | ||||||
|  |         <ng-container *ngIf="searchMode && searchTotal > 0"> | ||||||
|  |             <ion-item-divider> | ||||||
|  |                 <ion-label><h2>{{ 'core.courses.totalcoursesearchresults' | translate:{$a: searchTotal} }}</h2></ion-label> | ||||||
|  |             </ion-item-divider> | ||||||
|  |         </ng-container> | ||||||
|  |          | ||||||
|  |         <core-courses-course-list-item *ngFor="let course of courses" [course]="course"></core-courses-course-list-item> | ||||||
|  | 
 | ||||||
|  |         <core-infinite-loading [enabled]="searchMode && searchCanLoadMore" (action)="loadMoreResults($event)" [error]="searchLoadMoreError"> | ||||||
|  |         </core-infinite-loading> | ||||||
|  |         <core-empty-box *ngIf="searchMode && !courses.length" icon="fas-search" [message]="'core.courses.nosearchresults' | translate"> | ||||||
|  |         </core-empty-box> | ||||||
|  | 
 | ||||||
|  |         <core-empty-box *ngIf="!searchMode && !courses.length" icon="fas-graduation-cap" [message]="'core.courses.nocourses' | translate"> | ||||||
|  |         </core-empty-box> | ||||||
|  |          | ||||||
|  |     </core-loading> | ||||||
|  | </ion-content> | ||||||
| @ -19,12 +19,12 @@ import { CoreSharedModule } from '@/core/shared.module'; | |||||||
| import { CoreCoursesComponentsModule } from '../../components/components.module'; | import { CoreCoursesComponentsModule } from '../../components/components.module'; | ||||||
| import { CoreSearchComponentsModule } from '@features/search/components/components.module'; | import { CoreSearchComponentsModule } from '@features/search/components/components.module'; | ||||||
| 
 | 
 | ||||||
| import { CoreCoursesSearchPage } from './search'; | import { CoreCoursesListPage } from './list'; | ||||||
| 
 | 
 | ||||||
| const routes: Routes = [ | const routes: Routes = [ | ||||||
|     { |     { | ||||||
|         path: '', |         path: '', | ||||||
|         component: CoreCoursesSearchPage, |         component: CoreCoursesListPage, | ||||||
|     }, |     }, | ||||||
| ]; | ]; | ||||||
| 
 | 
 | ||||||
| @ -36,8 +36,8 @@ const routes: Routes = [ | |||||||
|         CoreSearchComponentsModule, |         CoreSearchComponentsModule, | ||||||
|     ], |     ], | ||||||
|     declarations: [ |     declarations: [ | ||||||
|         CoreCoursesSearchPage, |         CoreCoursesListPage, | ||||||
|     ], |     ], | ||||||
|     exports: [RouterModule], |     exports: [RouterModule], | ||||||
| }) | }) | ||||||
| export class CoreCoursesSearchPageModule { } | export class CoreCoursesListPageModule { } | ||||||
							
								
								
									
										211
									
								
								src/core/features/courses/pages/list/list.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										211
									
								
								src/core/features/courses/pages/list/list.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,211 @@ | |||||||
|  | // (C) Copyright 2015 Moodle Pty Ltd.
 | ||||||
|  | //
 | ||||||
|  | // Licensed under the Apache License, Version 2.0 (the "License");
 | ||||||
|  | // you may not use this file except in compliance with the License.
 | ||||||
|  | // You may obtain a copy of the License at
 | ||||||
|  | //
 | ||||||
|  | //     http://www.apache.org/licenses/LICENSE-2.0
 | ||||||
|  | //
 | ||||||
|  | // Unless required by applicable law or agreed to in writing, software
 | ||||||
|  | // distributed under the License is distributed on an "AS IS" BASIS,
 | ||||||
|  | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | ||||||
|  | // See the License for the specific language governing permissions and
 | ||||||
|  | // limitations under the License.
 | ||||||
|  | 
 | ||||||
|  | import { Component, OnDestroy, OnInit } from '@angular/core'; | ||||||
|  | import { IonRefresher } from '@ionic/angular'; | ||||||
|  | import { CoreNavigator } from '@services/navigator'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
|  | import { CoreEventObserver, CoreEvents } from '@singletons/events'; | ||||||
|  | import { CoreCourseBasicSearchedData, CoreCourses } from '../../services/courses'; | ||||||
|  | 
 | ||||||
|  | type CoreCoursesListMode = 'search' | 'all'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Page that shows a list of courses. | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'page-core-courses-list', | ||||||
|  |     templateUrl: 'list.html', | ||||||
|  | }) | ||||||
|  | export class CoreCoursesListPage implements OnInit, OnDestroy { | ||||||
|  | 
 | ||||||
|  |     searchEnabled = false; | ||||||
|  |     searchMode = false; | ||||||
|  |     searchCanLoadMore = false; | ||||||
|  |     searchLoadMoreError = false; | ||||||
|  |     searchTotal = 0; | ||||||
|  | 
 | ||||||
|  |     mode: CoreCoursesListMode = 'all'; | ||||||
|  | 
 | ||||||
|  |     courses: CoreCourseBasicSearchedData[] = []; | ||||||
|  |     coursesLoaded = false; | ||||||
|  | 
 | ||||||
|  |     protected currentSiteId: string; | ||||||
|  |     protected frontpageCourseId: number; | ||||||
|  |     protected searchPage = 0; | ||||||
|  |     protected searchText = ''; | ||||||
|  |     protected siteUpdatedObserver: CoreEventObserver; | ||||||
|  | 
 | ||||||
|  |     constructor() { | ||||||
|  |         this.currentSiteId = CoreSites.getRequiredCurrentSite().getId(); | ||||||
|  |         this.frontpageCourseId = CoreSites.getRequiredCurrentSite().getSiteHomeId(); | ||||||
|  | 
 | ||||||
|  |         // Refresh the enabled flags if site is updated.
 | ||||||
|  |         this.siteUpdatedObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => { | ||||||
|  |             this.searchEnabled = !CoreCourses.isSearchCoursesDisabledInSite(); | ||||||
|  | 
 | ||||||
|  |             if (!this.searchEnabled) { | ||||||
|  |                 this.searchMode = false; | ||||||
|  | 
 | ||||||
|  |                 this.fetchCourses(); | ||||||
|  |             } | ||||||
|  |         }, this.currentSiteId); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     ngOnInit(): void { | ||||||
|  |         this.mode = CoreNavigator.getRouteParam<CoreCoursesListMode>('mode') || this.mode; | ||||||
|  | 
 | ||||||
|  |         if (this.mode == 'search') { | ||||||
|  |             this.searchMode = true; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.searchEnabled = !CoreCourses.isSearchCoursesDisabledInSite(); | ||||||
|  |         if (!this.searchEnabled) { | ||||||
|  |             this.searchMode = false; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.fetchCourses(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Load the course list. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected async fetchCourses(): Promise<void> { | ||||||
|  |         try { | ||||||
|  |             if (this.searchMode && this.searchText) { | ||||||
|  |                 await this.search(this.searchText); | ||||||
|  |             } else { | ||||||
|  |                 await this.loadAvailableCourses(); | ||||||
|  |             } | ||||||
|  |         } finally { | ||||||
|  |             this.coursesLoaded = true; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Load the courses. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected async loadAvailableCourses(): Promise<void> { | ||||||
|  |         try { | ||||||
|  |             const courses = await CoreCourses.getCoursesByField(); | ||||||
|  | 
 | ||||||
|  |             this.courses = courses.filter((course) => course.id != this.frontpageCourseId); | ||||||
|  |         } catch (error) { | ||||||
|  |             CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorloadcourses', true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Refresh the courses. | ||||||
|  |      * | ||||||
|  |      * @param refresher Refresher. | ||||||
|  |      */ | ||||||
|  |     refreshCourses(refresher: IonRefresher): void { | ||||||
|  |         const promises: Promise<void>[] = []; | ||||||
|  | 
 | ||||||
|  |         promises.push(CoreCourses.invalidateUserCourses()); | ||||||
|  |         promises.push(CoreCourses.invalidateCoursesByField()); | ||||||
|  | 
 | ||||||
|  |         Promise.all(promises).finally(() => { | ||||||
|  |             this.fetchCourses().finally(() => { | ||||||
|  |                 refresher?.complete(); | ||||||
|  |             }); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Search a new text. | ||||||
|  |      * | ||||||
|  |      * @param text The text to search. | ||||||
|  |      */ | ||||||
|  |     async search(text: string): Promise<void> { | ||||||
|  |         this.searchMode = true; | ||||||
|  |         this.searchText = text; | ||||||
|  |         this.courses = []; | ||||||
|  |         this.searchPage = 0; | ||||||
|  |         this.searchTotal = 0; | ||||||
|  | 
 | ||||||
|  |         const modal = await CoreDomUtils.showModalLoading('core.searching', true); | ||||||
|  |         this.searchCourses().finally(() => { | ||||||
|  |             modal.dismiss(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Clear search box. | ||||||
|  |      */ | ||||||
|  |     clearSearch(): void { | ||||||
|  |         this.searchText = ''; | ||||||
|  |         this.courses = []; | ||||||
|  |         this.searchPage = 0; | ||||||
|  |         this.searchTotal = 0; | ||||||
|  |         this.searchMode = false; | ||||||
|  | 
 | ||||||
|  |         this.coursesLoaded = false; | ||||||
|  |         this.fetchCourses(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Load more results. | ||||||
|  |      * | ||||||
|  |      * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. | ||||||
|  |      */ | ||||||
|  |     loadMoreResults(infiniteComplete?: () => void ): void { | ||||||
|  |         this.searchCourses().finally(() => { | ||||||
|  |             infiniteComplete && infiniteComplete(); | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Search courses or load the next page of current search. | ||||||
|  |      * | ||||||
|  |      * @return Promise resolved when done. | ||||||
|  |      */ | ||||||
|  |     protected async searchCourses(): Promise<void> { | ||||||
|  |         this.searchLoadMoreError = false; | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             const response = await CoreCourses.search(this.searchText, this.searchPage); | ||||||
|  | 
 | ||||||
|  |             if (this.searchPage === 0) { | ||||||
|  |                 this.courses = response.courses; | ||||||
|  |             } else { | ||||||
|  |                 this.courses = this.courses.concat(response.courses); | ||||||
|  |             } | ||||||
|  |             this.searchTotal = response.total; | ||||||
|  | 
 | ||||||
|  |             this.searchPage++; | ||||||
|  |             this.searchCanLoadMore = this.courses.length < this.searchTotal; | ||||||
|  |         } catch (error) { | ||||||
|  |             this.searchLoadMoreError = true; // Set to prevent infinite calls with infinite-loading.
 | ||||||
|  |             CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorsearching', true); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     ngOnDestroy(): void { | ||||||
|  |         this.siteUpdatedObserver?.off(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -204,7 +204,7 @@ export class CoreCoursesMyCoursesPage implements OnInit, OnDestroy { | |||||||
|      * Go to search courses. |      * Go to search courses. | ||||||
|      */ |      */ | ||||||
|     openSearch(): void { |     openSearch(): void { | ||||||
|         CoreNavigator.navigateToSitePath('courses/search'); |         CoreNavigator.navigateToSitePath('courses/list', { params : { mode: 'search' } }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -1,23 +0,0 @@ | |||||||
| <ion-header> |  | ||||||
|     <ion-toolbar> |  | ||||||
|         <ion-buttons slot="start"> |  | ||||||
|             <ion-back-button [text]="'core.back' | translate"></ion-back-button> |  | ||||||
|         </ion-buttons> |  | ||||||
|         <h1>{{ 'core.courses.searchcourses' | translate }}</h1> |  | ||||||
|     </ion-toolbar> |  | ||||||
| </ion-header> |  | ||||||
| <ion-content> |  | ||||||
|     <core-search-box (onSubmit)="search($event)" (onClear)="clearSearch()" |  | ||||||
|     [placeholder]="'core.courses.search' | translate" [searchLabel]="'core.courses.search' | translate" autoFocus="true" |  | ||||||
|     searchArea="CoreCoursesSearch"></core-search-box> |  | ||||||
| 
 |  | ||||||
|     <ng-container *ngIf="total > 0"> |  | ||||||
|         <ion-item-divider> |  | ||||||
|             <ion-label><h2>{{ 'core.courses.totalcoursesearchresults' | translate:{$a: total} }}</h2></ion-label> |  | ||||||
|         </ion-item-divider> |  | ||||||
|         <core-courses-course-list-item *ngFor="let course of courses" [course]="course"></core-courses-course-list-item> |  | ||||||
|         <core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreResults($event)" [error]="loadMoreError"> |  | ||||||
|         </core-infinite-loading> |  | ||||||
|     </ng-container> |  | ||||||
|     <core-empty-box *ngIf="total == 0" icon="search" [message]="'core.courses.nosearchresults' | translate"></core-empty-box> |  | ||||||
| </ion-content> |  | ||||||
| @ -1,100 +0,0 @@ | |||||||
| // (C) Copyright 2015 Moodle Pty Ltd.
 |  | ||||||
| //
 |  | ||||||
| // Licensed under the Apache License, Version 2.0 (the "License");
 |  | ||||||
| // you may not use this file except in compliance with the License.
 |  | ||||||
| // You may obtain a copy of the License at
 |  | ||||||
| //
 |  | ||||||
| //     http://www.apache.org/licenses/LICENSE-2.0
 |  | ||||||
| //
 |  | ||||||
| // Unless required by applicable law or agreed to in writing, software
 |  | ||||||
| // distributed under the License is distributed on an "AS IS" BASIS,
 |  | ||||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 |  | ||||||
| // See the License for the specific language governing permissions and
 |  | ||||||
| // limitations under the License.
 |  | ||||||
| 
 |  | ||||||
| import { Component } from '@angular/core'; |  | ||||||
| import { CoreDomUtils } from '@services/utils/dom'; |  | ||||||
| import { CoreCourseBasicSearchedData, CoreCourses } from '../../services/courses'; |  | ||||||
| 
 |  | ||||||
| /** |  | ||||||
|  * Page that allows searching for courses. |  | ||||||
|  */ |  | ||||||
| @Component({ |  | ||||||
|     selector: 'page-core-courses-search', |  | ||||||
|     templateUrl: 'search.html', |  | ||||||
| }) |  | ||||||
| export class CoreCoursesSearchPage { |  | ||||||
| 
 |  | ||||||
|     total = 0; |  | ||||||
|     courses: CoreCourseBasicSearchedData[] = []; |  | ||||||
|     canLoadMore = false; |  | ||||||
|     loadMoreError = false; |  | ||||||
| 
 |  | ||||||
|     protected page = 0; |  | ||||||
|     protected currentSearch = ''; |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Search a new text. |  | ||||||
|      * |  | ||||||
|      * @param text The text to search. |  | ||||||
|      */ |  | ||||||
|     async search(text: string): Promise<void> { |  | ||||||
|         this.currentSearch = text; |  | ||||||
|         this.courses = []; |  | ||||||
|         this.page = 0; |  | ||||||
|         this.total = 0; |  | ||||||
| 
 |  | ||||||
|         const modal = await CoreDomUtils.showModalLoading('core.searching', true); |  | ||||||
|         this.searchCourses().finally(() => { |  | ||||||
|             modal.dismiss(); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Clear search box. |  | ||||||
|      */ |  | ||||||
|     clearSearch(): void { |  | ||||||
|         this.currentSearch = ''; |  | ||||||
|         this.courses = []; |  | ||||||
|         this.page = 0; |  | ||||||
|         this.total = 0; |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Load more results. |  | ||||||
|      * |  | ||||||
|      * @param infiniteComplete Infinite scroll complete function. Only used from core-infinite-loading. |  | ||||||
|      */ |  | ||||||
|     loadMoreResults(infiniteComplete?: () => void ): void { |  | ||||||
|         this.searchCourses().finally(() => { |  | ||||||
|             infiniteComplete && infiniteComplete(); |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Search courses or load the next page of current search. |  | ||||||
|      * |  | ||||||
|      * @return Promise resolved when done. |  | ||||||
|      */ |  | ||||||
|     protected async searchCourses(): Promise<void> { |  | ||||||
|         this.loadMoreError = false; |  | ||||||
| 
 |  | ||||||
|         try { |  | ||||||
|             const response = await CoreCourses.search(this.currentSearch, this.page); |  | ||||||
| 
 |  | ||||||
|             if (this.page === 0) { |  | ||||||
|                 this.courses = response.courses; |  | ||||||
|             } else { |  | ||||||
|                 this.courses = this.courses.concat(response.courses); |  | ||||||
|             } |  | ||||||
|             this.total = response.total; |  | ||||||
| 
 |  | ||||||
|             this.page++; |  | ||||||
|             this.canLoadMore = this.courses.length < this.total; |  | ||||||
|         } catch (error) { |  | ||||||
|             this.loadMoreError = true; // Set to prevent infinite calls with infinite-loading.
 |  | ||||||
|             CoreDomUtils.showErrorModalDefault(error, 'core.courses.errorsearching', true); |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } |  | ||||||
| @ -42,14 +42,17 @@ export class CoreCoursesIndexLinkHandlerService extends CoreContentLinksHandlerB | |||||||
|         return [{ |         return [{ | ||||||
|             action: (siteId): void => { |             action: (siteId): void => { | ||||||
|                 let pageName = CoreCoursesMyCoursesHomeHandlerService.PAGE_NAME; |                 let pageName = CoreCoursesMyCoursesHomeHandlerService.PAGE_NAME; | ||||||
|  |                 const pageParams: Params = {}; | ||||||
| 
 | 
 | ||||||
|                 if (params.categoryid) { |                 if (params.categoryid) { | ||||||
|                     pageName += '/categories/' + params.categoryid; |                     pageName += '/categories/' + params.categoryid; | ||||||
|                 } else { |                 } else { | ||||||
|                     pageName += '/all'; |                     pageName += '/list'; | ||||||
|  |                     pageParams.mode = 'all'; | ||||||
|                 } |                 } | ||||||
| 
 | 
 | ||||||
|                 CoreNavigator.navigateToSitePath(pageName, { siteId }); | 
 | ||||||
|  |                 CoreNavigator.navigateToSitePath(pageName, { params: pageParams, siteId }); | ||||||
|             }, |             }, | ||||||
|         }]; |         }]; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -218,14 +218,14 @@ export class CoreSiteHomeIndexPage implements OnInit, OnDestroy { | |||||||
|      * Go to search courses. |      * Go to search courses. | ||||||
|      */ |      */ | ||||||
|     openSearch(): void { |     openSearch(): void { | ||||||
|         CoreNavigator.navigateToSitePath('courses/search'); |         CoreNavigator.navigateToSitePath('courses/list', { params : { mode: 'search' } }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Go to available courses. |      * Go to available courses. | ||||||
|      */ |      */ | ||||||
|     openAvailableCourses(): void { |     openAvailableCourses(): void { | ||||||
|         CoreNavigator.navigateToSitePath('courses/all'); |         CoreNavigator.navigateToSitePath('courses/list', { params : { mode: 'all' } }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user