MOBILE-3594 sitehome: Fix header buttons on sitehome

main
Pau Ferrer Ocaña 2020-11-20 17:05:30 +01:00
parent 2ce1950210
commit 55da132b9b
9 changed files with 230 additions and 65 deletions

View File

@ -18,7 +18,7 @@
<ion-icon *ngIf="tab.icon" [name]="tab.icon"></ion-icon>
<ion-label>{{ tab.title | translate}}</ion-label>
<ion-badge *ngIf="tab.badge">{{ tab.badge }}</ion-badge>
</ion-tab-button>
</ion-tab-button>
</ion-slide>
</ng-container>
</ion-slides>

View File

@ -33,6 +33,9 @@ import { CoreConstants } from '@/core/constants';
import { CoreUtils } from '@services/utils/utils';
import { NavigationOptions } from '@ionic/angular/providers/nav-controller';
import { Params } from '@angular/router';
import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons';
import { CoreDomUtils } from '@/core/services/utils/dom';
import { StackEvent } from '@ionic/angular/directives/navigation/stack-utils';
/**
* This component displays some top scrollable tabs that will autohide on vertical scroll.
@ -105,6 +108,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe
protected isInTransition = false; // Weather Slides is in transition.
protected slidesSwiper: any;
protected slidesSwiperLoaded = false;
protected stackEventsSubscription?: Subscription;
constructor(
protected element: ElementRef,
@ -151,6 +155,21 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe
return;
}
this.stackEventsSubscription = this.ionTabs!.outlet.stackEvents.subscribe(async (stackEvent: StackEvent) => {
if (this.isCurrentView) {
const content = stackEvent.enteringView.element.querySelector('ion-content');
this.showHideNavBarButtons(stackEvent.enteringView.element.tagName);
if (content) {
const scroll = await content.getScrollElement();
content.scrollEvents = true;
content.addEventListener('ionScroll', (e: CustomEvent): void => {
this.showHideTabs(e, scroll);
});
}
}
});
this.tabBarElement = this.element.nativeElement.querySelector('ion-tab-bar');
this.tabsElement = this.element.nativeElement.querySelector('ion-tabs');
@ -576,19 +595,29 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe
this.selectedIndex = index;
this.ionChange.emit(selectedTab);
const content = this.ionTabs!.outlet.nativeEl.querySelector('ion-content');
if (content) {
const scroll = await content.getScrollElement();
content.scrollEvents = true;
content.addEventListener('ionScroll', (e: CustomEvent): void => {
this.showHideTabs(e, scroll);
});
}
}
}
/**
* Get all child core-navbar-buttons and show or hide depending on the page state.
* We need to use querySelectorAll because ContentChildren doesn't work with ng-template.
* https://github.com/angular/angular/issues/14842
*
* @param activatedPageName Activated page name.
*/
protected showHideNavBarButtons(activatedPageName: string): void {
const elements = this.ionTabs!.outlet.nativeEl.querySelectorAll('core-navbar-buttons');
const domUtils = CoreDomUtils.instance;
elements.forEach((element) => {
const instance: CoreNavBarButtonsComponent = domUtils.getInstanceByElement(element);
if (instance) {
const pagetagName = element.closest('.ion-page')?.tagName;
instance.forceHide(activatedPageName != pagetagName);
}
});
}
/**
* Adapt tabs to a window resize.
*/
@ -607,6 +636,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe
if (this.resizeFunction) {
window.removeEventListener('resize', this.resizeFunction);
}
this.stackEventsSubscription?.unsubscribe();
}
}

View File

@ -1,3 +1,16 @@
<core-navbar-buttons slot="end">
<ion-button *ngIf="searchEnabled" (click)="openSearch()" [attr.aria-label]="'core.courses.searchcourses' | translate">
<ion-icon name="fas-search" slot="icon-only"></ion-icon>
</ion-button>
<core-context-menu>
<core-context-menu-item *ngIf="(downloadCourseEnabled || downloadCoursesEnabled)" [priority]="1000"
[content]="'core.settings.showdownloadoptions' | translate" (action)="toggleDownload()"
[iconAction]="downloadEnabledIcon"></core-context-menu-item>
<core-context-menu-item *ngIf="(downloadCourseEnabled || downloadCoursesEnabled)" [priority]="500"
[content]="'addon.storagemanager.managestorage' | translate"
(action)="manageCoursesStorage()" iconAction="fas-archive"></core-context-menu-item>
</core-context-menu>
</core-navbar-buttons>
<ion-content>
<!-- @todo -->
<core-empty-box icon="fa-home" [message]="'core.courses.nocourses' | translate">

View File

@ -12,25 +12,93 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { CoreCourses, CoreCoursesProvider } from '../../services/courses';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSites } from '@services/sites';
/**
* Page that displays the Home.
* Page that displays the dashboard page.
*/
@Component({
selector: 'page-core-courses-dashboard',
templateUrl: 'dashboard.html',
styleUrls: ['dashboard.scss'],
})
export class CoreCoursesDashboardPage implements OnInit {
export class CoreCoursesDashboardPage implements OnInit, OnDestroy {
searchEnabled = false;
downloadEnabled = false;
downloadCourseEnabled = false;
downloadCoursesEnabled = false;
downloadEnabledIcon = 'far-square';
protected updateSiteObserver?: CoreEventObserver;
siteName = 'Hello world';
constructor(
protected navCtrl: NavController,
) { }
/**
* Initialize the component.
*/
ngOnInit(): void {
// @todo
this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite();
this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite();
this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite();
// Refresh the enabled flags if site is updated.
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite();
this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite();
this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite();
this.switchDownload(this.downloadEnabled && this.downloadCourseEnabled && this.downloadCoursesEnabled);
}, CoreSites.instance.getCurrentSiteId());
}
/**
* Toggle download enabled.
*/
toggleDownload(): void {
this.switchDownload(!this.downloadEnabled);
}
/**
* Convenience function to switch download enabled.
*
* @param enable If enable or disable.
*/
protected switchDownload(enable: boolean): void {
this.downloadEnabled = (this.downloadCourseEnabled || this.downloadCoursesEnabled) && enable;
this.downloadEnabledIcon = this.downloadEnabled ? 'far-check-square' : 'far-square';
CoreEvents.trigger(CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED, { enabled: this.downloadEnabled });
}
/**
* Open page to manage courses storage.
*/
manageCoursesStorage(): void {
// @todo this.navCtrl.navigateForward(['/courses/storage']);
}
/**
* Go to search courses.
*/
openSearch(): void {
this.navCtrl.navigateForward(['/courses/search']);
}
/**
* Component being destroyed.
*/
ngOnDestroy(): void {
this.updateSiteObserver?.off();
}
}

View File

@ -10,16 +10,16 @@
<ion-button *ngIf="searchEnabled" (click)="openSearch()" [attr.aria-label]="'core.courses.searchcourses' | translate">
<ion-icon name="fas-search" slot="icon-only"></ion-icon>
</ion-button>
<ng-container *ngIf="downloadAllCoursesEnabled && courses && courses.length >= 2">
<ion-button *ngIf="!downloadAllCoursesLoading" (click)="prefetchCourses()"
[attr.aria-label]="'core.courses.downloadcourses' | translate">
<ion-icon [name]="downloadAllCoursesIcon" slot="icon-only"></ion-icon>
</ion-button>
<ion-spinner *ngIf="downloadAllCoursesBadge == '' && downloadAllCoursesLoading"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-badge *ngIf="downloadAllCoursesBadge != '' && downloadAllCoursesLoading"
[attr.aria-label]="'core.downloading' | translate">{{downloadAllCoursesBadge}}</ion-badge>
</ng-container>
<ion-button [hidden]="!downloadAllCoursesEnabled || !courses || courses.length < 2 || downloadAllCoursesLoading"
(click)="prefetchCourses()" [attr.aria-label]="'core.courses.downloadcourses' | translate">
<ion-icon [name]="downloadAllCoursesIcon" slot="icon-only"></ion-icon>
</ion-button>
<ion-spinner [hidden]="!downloadAllCoursesEnabled || !courses || courses.length < 2 ||
downloadAllCoursesBadge != '' || !downloadAllCoursesLoading"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-badge [hidden]="!downloadAllCoursesEnabled || !courses || courses.length < 2 || !downloadAllCoursesLoading ||
downloadAllCoursesBadge == '' || !downloadAllCoursesLoading"
[attr.aria-label]="'core.downloading' | translate">{{downloadAllCoursesBadge}}</ion-badge>
</core-navbar-buttons>
</ion-buttons>
</ion-toolbar>

View File

@ -9,14 +9,6 @@
<img src="assets/img/login_logo.png" class="core-header-logo" [alt]="siteName">
</ion-title>
<ion-buttons slot="end">
<ion-button *ngIf="searchEnabled" (click)="openSearch()" [attr.aria-label]="'core.courses.searchcourses' | translate">
<ion-icon name="fas-search" slot="icon-only"></ion-icon>
</ion-button>
<core-context-menu>
<core-context-menu-item *ngIf="(downloadCourseEnabled || downloadCoursesEnabled)" [priority]="500"
[content]="'addon.storagemanager.managestorage' | translate"
(action)="manageCoursesStorage()" iconAction="fas-archive"></core-context-menu-item>
</core-context-menu>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@ -12,14 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit } from '@angular/core';
import { NavController } from '@ionic/angular';
import { Component, OnInit, ViewChild } from '@angular/core';
import { Subscription } from 'rxjs';
import { CoreSites } from '@services/sites';
import { CoreHomeDelegate, CoreHomeHandlerToDisplay } from '../../services/home.delegate';
import { CoreCourses } from '@features/courses/services/courses';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreTabsComponent } from '@components/tabs/tabs';
/**
* Page that displays the Home.
@ -31,20 +30,19 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
})
export class CoreHomePage implements OnInit {
@ViewChild(CoreTabsComponent) tabsComponent?: CoreTabsComponent;
siteName!: string;
tabs: CoreHomeHandlerToDisplay[] = [];
loaded = false;
selectedTab?: number;
searchEnabled = false;
downloadCourseEnabled = false;
downloadCoursesEnabled = false;
protected subscription?: Subscription;
protected updateSiteObserver?: CoreEventObserver;
constructor(
protected homeDelegate: CoreHomeDelegate,
protected navCtrl: NavController,
) {
this.loadSiteName();
}
@ -53,20 +51,12 @@ export class CoreHomePage implements OnInit {
* Initialize the component.
*/
ngOnInit(): void {
this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite();
this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite();
this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite();
this.subscription = this.homeDelegate.getHandlersObservable().subscribe((handlers) => {
handlers && this.initHandlers(handlers);
});
// Refresh the enabled flags if site is updated.
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite();
this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite();
this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite();
this.loadSiteName();
}, CoreSites.instance.getCurrentSiteId());
}
@ -114,17 +104,17 @@ export class CoreHomePage implements OnInit {
}
/**
* Open page to manage courses storage.
* User entered the page.
*/
manageCoursesStorage(): void {
// @todo this.navCtrl.navigateForward(['/courses/storage']);
ionViewDidEnter(): void {
this.tabsComponent?.ionViewDidEnter();
}
/**
* Go to search courses.
* User left the page.
*/
openSearch(): void {
this.navCtrl.navigateForward(['/courses/search']);
ionViewDidLeave(): void {
this.tabsComponent?.ionViewDidLeave();
}
}

View File

@ -1,3 +1,16 @@
<core-navbar-buttons slot="end">
<ion-button *ngIf="searchEnabled" (click)="openSearch()" [attr.aria-label]="'core.courses.searchcourses' | translate">
<ion-icon name="fas-search" slot="icon-only"></ion-icon>
</ion-button>
<core-context-menu>
<core-context-menu-item *ngIf="(downloadCourseEnabled || downloadCoursesEnabled)" [priority]="1000"
[content]="'core.settings.showdownloadoptions' | translate" (action)="toggleDownload()"
[iconAction]="downloadEnabledIcon"></core-context-menu-item>
<core-context-menu-item *ngIf="(downloadCourseEnabled || downloadCoursesEnabled)" [priority]="500"
[content]="'addon.storagemanager.managestorage' | translate"
(action)="manageCoursesStorage()" iconAction="fas-archive"></core-context-menu-item>
</core-context-menu>
</core-navbar-buttons>
<ion-content>
<ion-refresher slot="fixed" [disabled]="!dataLoaded"
(ionRefresh)="doRefresh($event)">

View File

@ -12,16 +12,18 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, OnInit } from '@angular/core';
import { Component, OnDestroy, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { IonRefresher } from '@ionic/angular';
import { IonRefresher, NavController } from '@ionic/angular';
import { CoreSite, CoreSiteConfig } from '@classes/site';
import { CoreCourse, CoreCourseSection } from '@features/course/services/course';
import { CoreDomUtils } from '@services/utils/dom';
import { CoreSites } from '@services/sites';
import { CoreSiteHome } from '@features/sitehome/services/sitehome';
// import { CoreCourseHelperProvider } from '@features/course/services/helper';
import { CoreCourses, CoreCoursesProvider } from '@features//courses/services/courses';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreCourseHelper } from '@features/course/services/course.helper';
/**
* Page that displays site home index.
@ -30,9 +32,8 @@ import { CoreSiteHome } from '@features/sitehome/services/sitehome';
selector: 'page-core-sitehome-index',
templateUrl: 'index.html',
})
export class CoreSiteHomeIndexPage implements OnInit {
export class CoreSiteHomeIndexPage implements OnInit, OnDestroy {
// @todo @Input() downloadEnabled: boolean;
// @todo @ViewChild(CoreBlockCourseBlocksComponent) courseBlocksComponent: CoreBlockCourseBlocksComponent;
dataLoaded = false;
@ -44,13 +45,19 @@ export class CoreSiteHomeIndexPage implements OnInit {
items: string[] = [];
siteHomeId?: number;
currentSite?: CoreSite;
searchEnabled = false;
downloadEnabled = false;
downloadCourseEnabled = false;
downloadCoursesEnabled = false;
downloadEnabledIcon = 'far-square';
protected updateSiteObserver?: CoreEventObserver;
constructor(
protected route: ActivatedRoute,
protected navCtrl: NavController,
// @todo private prefetchDelegate: CoreCourseModulePrefetchDelegate,
) {
}
) {}
/**
* Page being initialized.
@ -58,13 +65,26 @@ export class CoreSiteHomeIndexPage implements OnInit {
ngOnInit(): void {
const navParams = this.route.snapshot.queryParams;
this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite();
this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite();
this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite();
// Refresh the enabled flags if site is updated.
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, () => {
this.searchEnabled = !CoreCourses.instance.isSearchCoursesDisabledInSite();
this.downloadCourseEnabled = !CoreCourses.instance.isDownloadCourseDisabledInSite();
this.downloadCoursesEnabled = !CoreCourses.instance.isDownloadCoursesDisabledInSite();
this.switchDownload(this.downloadEnabled && this.downloadCourseEnabled && this.downloadCoursesEnabled);
}, CoreSites.instance.getCurrentSiteId());
this.currentSite = CoreSites.instance.getCurrentSite()!;
this.siteHomeId = this.currentSite.getSiteHomeId();
const module = navParams['module'];
if (module) {
// @todo const modParams = navParams.get('modParams');
// courseHelper.openModule(module, this.siteHomeId, undefined, modParams);
// CoreCourseHelper.instance.openModule(module, this.siteHomeId, undefined, modParams);
}
this.loadContent().finally(() => {
@ -92,8 +112,8 @@ export class CoreSiteHomeIndexPage implements OnInit {
this.section = config.numsections ? sections.find((section) => section.section == 1) : undefined;
if (this.section) {
this.section.hasContent = false;
/* @todo this.section.hasContent = this.courseHelper.sectionHasContent(this.section);
this.hasContent = this.courseHelper.addHandlerDataForModules(
this.section.hasContent = CoreCourseHelper.instance.sectionHasContent(this.section);
/* @todo this.hasContent = CoreCourseHelper.instance.addHandlerDataForModules(
[this.section],
this.siteHomeId,
undefined,
@ -152,4 +172,43 @@ export class CoreSiteHomeIndexPage implements OnInit {
});
}
/**
* Toggle download enabled.
*/
toggleDownload(): void {
this.switchDownload(!this.downloadEnabled);
}
/**
* Convenience function to switch download enabled.
*
* @param enable If enable or disable.
*/
protected switchDownload(enable: boolean): void {
this.downloadEnabled = (this.downloadCourseEnabled || this.downloadCoursesEnabled) && enable;
this.downloadEnabledIcon = this.downloadEnabled ? 'far-check-square' : 'far-square';
CoreEvents.trigger(CoreCoursesProvider.EVENT_DASHBOARD_DOWNLOAD_ENABLED_CHANGED, { enabled: this.downloadEnabled });
}
/**
* Open page to manage courses storage.
*/
manageCoursesStorage(): void {
// @todo this.navCtrl.navigateForward(['/courses/storage']);
}
/**
* Go to search courses.
*/
openSearch(): void {
this.navCtrl.navigateForward(['/courses/search']);
}
/**
* Component being destroyed.
*/
ngOnDestroy(): void {
this.updateSiteObserver?.off();
}
}