MOBILE-2302 mainmenu: Implement delegate and Main Menu page

main
Dani Palou 2017-12-07 10:39:11 +01:00
parent 9cbf682370
commit 704e3796a0
44 changed files with 687 additions and 38 deletions

View File

@ -379,49 +379,54 @@ export class CoreLoginHelperProvider {
* @return {Promise<any>} Promise resolved when done.
*/
goToSiteInitialPage(navCtrl: NavController, setRoot?: boolean) : Promise<any> {
return this.isMyOverviewEnabled().then((myOverview) => {
let myCourses = !myOverview && this.isMyCoursesEnabled(),
site = this.sitesProvider.getCurrentSite(),
promise;
if (setRoot) {
return navCtrl.setRoot('CoreMainMenuPage', {}, {animate: false});
} else {
return navCtrl.push('CoreMainMenuPage');
}
// return this.isMyOverviewEnabled().then((myOverview) => {
// let myCourses = !myOverview && this.isMyCoursesEnabled(),
// site = this.sitesProvider.getCurrentSite(),
// promise;
if (!site) {
return Promise.reject(null);
}
// if (!site) {
// return Promise.reject(null);
// }
// Check if frontpage is needed to be shown. (If configured or if any of the other avalaible).
if ((site.getInfo() && site.getInfo().userhomepage === 0) || (!myCourses && !myOverview)) {
promise = this.isFrontpageEnabled();
} else {
promise = Promise.resolve(false);
}
// // Check if frontpage is needed to be shown. (If configured or if any of the other avalaible).
// if ((site.getInfo() && site.getInfo().userhomepage === 0) || (!myCourses && !myOverview)) {
// promise = this.isFrontpageEnabled();
// } else {
// promise = Promise.resolve(false);
// }
return promise.then((frontpage) => {
// Check avalaibility in priority order.
let pageName,
params;
// return promise.then((frontpage) => {
// // Check avalaibility in priority order.
// let pageName,
// params;
// @todo Use real pages names when they are implemented.
if (frontpage) {
pageName = 'Frontpage';
} else if (myOverview) {
pageName = 'MyOverview';
} else if (myCourses) {
pageName = 'MyCourses';
} else {
// Anything else available, go to the user profile.
pageName = 'User';
params = {
userId: site.getUserId()
};
}
// // @todo Use real pages names when they are implemented.
// if (frontpage) {
// pageName = 'Frontpage';
// } else if (myOverview) {
// pageName = 'MyOverview';
// } else if (myCourses) {
// pageName = 'MyCourses';
// } else {
// // Anything else available, go to the user profile.
// pageName = 'User';
// params = {
// userId: site.getUserId()
// };
// }
if (setRoot) {
return navCtrl.setRoot(pageName, params, {animate: false});
} else {
return navCtrl.push(pageName, params);
}
});
});
// if (setRoot) {
// return navCtrl.setRoot(pageName, params, {animate: false});
// } else {
// return navCtrl.push(pageName, params);
// }
// });
// });
}
/**

View File

@ -0,0 +1,8 @@
{
"appsettings": "إعدادات التطبيق",
"changesite": "الخروج",
"help": "مساعدة",
"logout": "خروج",
"mycourses": "مقرراتي الدراسية",
"website": "الموقع"
}

View File

@ -0,0 +1,8 @@
{
"appsettings": "Настройки на приложението",
"changesite": "Изход",
"help": "Помощ",
"logout": "Изход",
"mycourses": "Моите курсове",
"website": "Уебсайт"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Paràmetres de l'aplicació",
"changesite": "Canvia de lloc",
"help": "Ajuda",
"logout": "Surt",
"mycourses": "Els meus cursos",
"togglemenu": "Canvia menú",
"website": "Lloc web"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Nastavení aplikace",
"changesite": "Změnit stránky",
"help": "Pomoc",
"logout": "Odhlásit se",
"mycourses": "Moje kurzy",
"togglemenu": "Přepnout nabídku",
"website": "Webová stránka"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "App-indstillinger",
"changesite": "Skift side",
"help": "Hjælp",
"logout": "Log ud",
"mycourses": "Mine kurser",
"togglemenu": "Skift menu",
"website": "Websted"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Einstellungen",
"changesite": "Website wechseln",
"help": "Hilfe",
"logout": "Abmelden",
"mycourses": "Meine Kurse",
"togglemenu": "Menü umschalten",
"website": "Website im Browser"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Einstellungen",
"changesite": "Website wechseln",
"help": "Hilfe",
"logout": "Abmelden",
"mycourses": "Meine Kurse",
"togglemenu": "Menü umschalten",
"website": "Website im Browser"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Ρυθμίσεις εφαρμογής",
"changesite": "Αλλαγή ιστότοπου",
"help": "Βοήθεια",
"logout": "Έξοδος",
"mycourses": "Τα μαθήματά μου",
"togglemenu": "Αλλαγή μενού",
"website": "Ιστότοπος"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "App settings",
"changesite": "Change site",
"help": "Help",
"logout": "Log out",
"mycourses": "My courses",
"togglemenu": "Toggle menu",
"website": "Website"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Configuraciones del App",
"changesite": "Cambiar sitio",
"help": "Ayuda",
"logout": "Salir",
"mycourses": "Mis cursos",
"togglemenu": "Alternar menú",
"website": "Página web"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Configuración de la aplicación",
"changesite": "Cambiar de sitio",
"help": "Ayuda",
"logout": "Salir",
"mycourses": "Mis cursos",
"togglemenu": "Cambiar menú",
"website": "Página web"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "App-aren ezarpenak",
"changesite": "Aldatu gunea",
"help": "Laguntza",
"logout": "Saioa amaitu",
"mycourses": "Nire ikastaroak",
"togglemenu": "Aldatu menua",
"website": "Webgunea"
}

View File

@ -0,0 +1,8 @@
{
"appsettings": "تنظیمات برنامه",
"changesite": "خروج",
"help": "راهنمایی",
"logout": "خروج از سایت",
"mycourses": "درس‌های من",
"website": "پایگاه اینترنتی"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Mobiilisovelluksen asetukset",
"changesite": "Vaihda sivustoa",
"help": "Ohje",
"logout": "Kirjaudu ulos",
"mycourses": "Omat kurssini",
"togglemenu": "Valikko päälle/pois",
"website": "Www-sivusto"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Réglages de l'app",
"changesite": "Changer de plateforme",
"help": "Aide",
"logout": "Déconnexion",
"mycourses": "Mes cours",
"togglemenu": "Menu",
"website": "Site web"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "הגדרות יישומון",
"changesite": "התנתק",
"help": "עזרה",
"logout": "התנתקות",
"mycourses": "הקורסים שלי",
"togglemenu": "החלפת מצב תפריט",
"website": "אתר אינטרנט"
}

View File

@ -0,0 +1,8 @@
{
"appsettings": "Postavke aplikacije",
"changesite": "Promijeni poslužitelj",
"help": "Pomoć",
"logout": "Odjava",
"mycourses": "Moji e-kolegiji",
"website": "Web"
}

View File

@ -0,0 +1,7 @@
{
"changesite": "Kilépés",
"help": "Súgó",
"logout": "Kilépés",
"mycourses": "Kurzusaim",
"website": "Weboldal"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Impostazioni app",
"changesite": "Cambia sito",
"help": "Aiuto",
"logout": "Esci",
"mycourses": "I miei corsi",
"togglemenu": "Attiva/disattiva menu",
"website": "Sito web"
}

View File

@ -0,0 +1,8 @@
{
"appsettings": "アプリ設定",
"changesite": "ログアウト",
"help": "ヘルプ",
"logout": "ログアウト",
"mycourses": "マイコース",
"website": "ウェブサイト"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Programėlės nustatymai",
"changesite": "Pakeisti svetainę",
"help": "Žinynas",
"logout": "Atsijungti",
"mycourses": "Mano kursai",
"togglemenu": "Perjungti",
"website": "Interneto svetainė"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "अॅप सेटिंग्ज",
"changesite": "साइट बदला",
"help": "मदत",
"logout": "लॉग-आउट",
"mycourses": "माझे कोर्सेस",
"togglemenu": "मेनू बदला",
"website": "वेबसाइट"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "App instellingen",
"changesite": "Naar andere site",
"help": "Help",
"logout": "Uitloggen",
"mycourses": "Mijn cursussen",
"togglemenu": "Menu schakelen",
"website": "Website"
}

View File

@ -0,0 +1,5 @@
{
"help": "Hjelp",
"logout": "Logg ut",
"mycourses": "Mine kurs"
}

View File

@ -0,0 +1,7 @@
{
"changesite": "Wyloguj",
"help": "Pomoc",
"logout": "Wyloguj",
"mycourses": "Moje kursy",
"website": "Witryna"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Configurações do aplicativo",
"changesite": "Mudar site",
"help": "Ajuda",
"logout": "Sair",
"mycourses": "Meus cursos",
"togglemenu": "Alternar menu",
"website": "Site"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Configurações da aplicação",
"changesite": "Mudar de site",
"help": "Ajuda",
"logout": "Sair",
"mycourses": "As minhas disciplinas",
"togglemenu": "Alternar menu",
"website": "Site"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Setările aplicației",
"changesite": "Schimbați siteul",
"help": "Ajutor",
"logout": "Ieşire",
"mycourses": "Cursurile mele",
"togglemenu": "Meniul pentru comutare",
"website": "Website"
}

View File

@ -0,0 +1,8 @@
{
"appsettings": "Настройки приложения",
"changesite": "Выход",
"help": "Справка",
"logout": "Выход",
"mycourses": "Мои курсы",
"website": "Сайт"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Подешавања апликације",
"changesite": "Промени сајт",
"help": "Помоћ",
"logout": "Одјава",
"mycourses": "Моји курсеви",
"togglemenu": "Укључи/искључи мени",
"website": "Веб сајт"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Podešavanja aplikacije",
"changesite": "Promeni sajt",
"help": "Pomoć",
"logout": "Odjava",
"mycourses": "Moji kursevi",
"togglemenu": "Uključi/isključi meni",
"website": "Veb sajt"
}

View File

@ -0,0 +1,8 @@
{
"appsettings": "App inställningar",
"changesite": "Byt webbsida",
"help": "Hjälp",
"logout": "Logga ut",
"mycourses": "Mina kurser",
"website": "Webbsida"
}

View File

@ -0,0 +1,7 @@
{
"changesite": ıkış",
"help": "Yardım",
"logout": ıkış yap",
"mycourses": "Derslerim",
"website": "Websitesi"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "Налаштування додатку",
"changesite": "Змінити сайт",
"help": "Допомога",
"logout": "Вихід",
"mycourses": "Мої курси",
"togglemenu": "Перемикання меню",
"website": "Веб-сайт"
}

View File

@ -0,0 +1,7 @@
{
"changesite": "注销",
"help": "帮助",
"logout": "注销",
"mycourses": "我的课程",
"website": "网站"
}

View File

@ -0,0 +1,9 @@
{
"appsettings": "應用程式設定",
"changesite": "更換網站",
"help": "協助",
"logout": "更換網站",
"mycourses": "我的課程",
"togglemenu": "切換功能選單",
"website": "網站"
}

View File

@ -0,0 +1,27 @@
// (C) Copyright 2015 Martin Dougiamas
//
// 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 { CoreMainMenuDelegate } from './providers/delegate';
@NgModule({
declarations: [
],
imports: [
],
providers: [
CoreMainMenuDelegate,
]
})
export class CoreMainMenuModule {}

View File

@ -0,0 +1,3 @@
<ion-tabs *ngIf="loaded">
<ion-tab *ngFor="let tab of tabs" [root]="tab.page" [tabTitle]="tab.title | translate" [tabIcon]="tab.icon" class="{{tab.class}}"></ion-tab>
</ion-tabs>

View File

@ -0,0 +1,31 @@
// (C) Copyright 2015 Martin Dougiamas
//
// 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 { IonicPageModule } from 'ionic-angular';
import { TranslateModule } from '@ngx-translate/core';
import { CoreMainMenuPage } from './menu';
import { CoreMainMenuModule } from '../../mainmenu.module';
@NgModule({
declarations: [
CoreMainMenuPage,
],
imports: [
CoreMainMenuModule,
IonicPageModule.forChild(CoreMainMenuPage),
TranslateModule.forChild()
],
})
export class CoreMainMenuPageModule {}

View File

@ -0,0 +1,3 @@
page-core-mainmenu {
}

View File

@ -0,0 +1,72 @@
// (C) Copyright 2015 Martin Dougiamas
//
// 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 } from '@angular/core';
import { IonicPage, NavController } from 'ionic-angular';
import { CoreEventsProvider } from '../../../../providers/events';
import { CoreSitesProvider } from '../../../../providers/sites';
import { CoreMainMenuDelegate, CoreMainMenuHandlerData } from '../../providers/delegate';
/**
* Page that displays the main menu of the app.
*/
@IonicPage()
@Component({
selector: 'page-core-mainmenu',
templateUrl: 'menu.html',
})
export class CoreMainMenuPage implements OnDestroy {
tabs: CoreMainMenuHandlerData[];
loaded: boolean;
protected subscription;
protected moreTabData = {
page: 'CoreMainMenuMorePage',
title: 'core.more',
icon: 'more'
};
protected logoutObserver;
constructor(private menuDelegate: CoreMainMenuDelegate, private sitesProvider: CoreSitesProvider,
private navCtrl: NavController, eventsProvider: CoreEventsProvider) {
// Go to sites page when user is logged out.
this.logoutObserver = eventsProvider.on(CoreEventsProvider.LOGOUT, () => {
this.navCtrl.setRoot('CoreLoginSitesPage');
});
}
/**
* View loaded.
*/
ionViewDidLoad() {
if (!this.sitesProvider.isLoggedIn()) {
this.navCtrl.setRoot('CoreLoginSitesPage');
return;
}
this.subscription = this.menuDelegate.getHandlers().subscribe((handlers) => {
this.tabs = handlers.slice(0, 4); // Get first 4.
this.tabs.push(this.moreTabData); // Add "More" tab.
this.loaded = this.menuDelegate.areHandlersLoaded();
});
}
/**
* Page destroyed.
*/
ngOnDestroy() {
this.subscription && this.subscription.unsubscribe();
this.logoutObserver && this.logoutObserver.off();
}
}

View File

@ -0,0 +1,202 @@
// (C) Copyright 2015 Martin Dougiamas
//
// 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 { Injectable } from '@angular/core';
import { CoreEventsProvider } from '../../../providers/events';
import { CoreLoggerProvider } from '../../../providers/logger';
import { CoreSitesProvider } from '../../../providers/sites';
import { Subject, BehaviorSubject } from 'rxjs';
export interface CoreMainMenuHandler {
name: string; // Name of the handler.
priority: number; // The highest priority is displayed first.
isEnabled(): boolean|Promise<boolean>; // Whether or not the handler is enabled on a site level.
getDisplayData(): CoreMainMenuHandlerData; // Returns the data needed to render the handler.
};
export interface CoreMainMenuHandlerData {
page: string; // Name of the page.
title: string; // Title to display in the tab.
icon: string; // Name of the icon to display in the tab.
class?: string; // Class to add to the displayed handler.
};
/**
* Service to interact with plugins to be shown in the main menu. Provides functions to register a plugin
* and notify an update in the data.
*/
@Injectable()
export class CoreMainMenuDelegate {
protected logger;
protected handlers: {[s: string]: CoreMainMenuHandler} = {};
protected enabledHandlers: {[s: string]: CoreMainMenuHandler} = {};
protected loaded = false;
protected lastUpdateHandlersStart: number;
protected siteHandlers: Subject<CoreMainMenuHandlerData[]> = new BehaviorSubject<CoreMainMenuHandlerData[]>([]);
constructor(logger: CoreLoggerProvider, private sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider) {
this.logger = logger.getInstance('CoreMainMenuDelegate');
eventsProvider.on(CoreEventsProvider.LOGIN, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.SITE_UPDATED, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.REMOTE_ADDONS_LOADED, this.updateHandlers.bind(this));
eventsProvider.on(CoreEventsProvider.LOGOUT, this.clearSiteHandlers.bind(this));
}
/**
* Check if handlers are loaded.
*
* @return {boolean} True if handlers are loaded, false otherwise.
*/
areHandlersLoaded() : boolean {
return this.loaded;
}
/**
* Clear current site handlers. Reserved for core use.
*/
protected clearSiteHandlers() {
this.loaded = false;
this.siteHandlers.next([]);
}
/**
* Get the handlers for the current site.
*
* @return {Subject<CoreMainMenuHandlerData[]>} An observable that will receive the handlers.
*/
getHandlers() : Subject<CoreMainMenuHandlerData[]> {
return this.siteHandlers;
}
/**
* Check if a time belongs to the last update handlers call.
* This is to handle the cases where updateHandlers don't finish in the same order as they're called.
*
* @param {number} time Time to check.
* @return {boolean} Whether it's the last call.
*/
isLastUpdateCall(time: number) : boolean {
if (!this.lastUpdateHandlersStart) {
return true;
}
return time == this.lastUpdateHandlersStart;
}
/**
* Register a handler.
*
* @param {CoreInitHandler} handler The handler to register.
* @return {boolean} True if registered successfully, false otherwise.
*/
registerHandler(handler: CoreMainMenuHandler) : boolean {
if (typeof this.handlers[handler.name] !== 'undefined') {
this.logger.log(`Addon 'handler.name' already registered`);
return false;
}
this.logger.log(`Registered addon 'handler.name'`);
this.handlers[handler.name] = handler;
return true;
}
/**
* Update the handler for the current site.
*
* @param {CoreInitHandler} handler The handler to check.
* @param {number} time Time this update process started.
* @return {Promise<void>} Resolved when done.
*/
protected updateHandler(handler: CoreMainMenuHandler, time: number) : Promise<void> {
let promise,
siteId = this.sitesProvider.getCurrentSiteId(),
currentSite = this.sitesProvider.getCurrentSite();
if (!this.sitesProvider.isLoggedIn()) {
promise = Promise.reject(null);
} else if (currentSite.isFeatureDisabled('$mmSideMenuDelegate_' + handler.name)) {
promise = Promise.resolve(false);
} else {
promise = Promise.resolve(handler.isEnabled());
}
// Checks if the handler is enabled.
return promise.catch(() => {
return false;
}).then((enabled: boolean) => {
// Verify that this call is the last one that was started.
// Check that site hasn't changed since the check started.
if (this.isLastUpdateCall(time) && this.sitesProvider.getCurrentSiteId() === siteId) {
if (enabled) {
this.enabledHandlers[handler.name] = handler;
} else {
delete this.enabledHandlers[handler.name];
}
}
});
}
/**
* Update the handlers for the current site.
*
* @return {Promise<void>} Resolved when done.
*/
protected updateHandlers() : Promise<void> {
let promises = [],
now = Date.now();
this.logger.debug('Updating handlers for current site.');
this.lastUpdateHandlersStart = now;
// Loop over all the handlers.
for (let name in this.handlers) {
promises.push(this.updateHandler(this.handlers[name], now));
}
return Promise.all(promises).then(() => {
return true;
}, () => {
// Never reject.
return true;
}).then(() => {
// Verify that this call is the last one that was started.
if (this.isLastUpdateCall(now)) {
let handlersData: any[] = [];
for (let name in this.enabledHandlers) {
let handler = this.enabledHandlers[name],
data = handler.getDisplayData();
handlersData.push({
data: data,
priority: handler.priority
});
}
// Sort them by priority.
handlersData.sort((a, b) => {
return b.priority - a.priority;
});
// Return only the display data.
let displayData = handlersData.map((item) => {
return item.data;
});
this.loaded = true;
this.siteHandlers.next(displayData);
}
});
}
}

View File

@ -133,6 +133,7 @@
"mod_url": "URL",
"mod_wiki": "Wiki",
"mod_workshop": "Workshop",
"more": "More",
"mygroups": "My groups",
"name": "Name",
"nograde": "No grade",