MOBILE-3105 wiki: Move Map to a lateral modal

main
Pau Ferrer Ocaña 2019-08-29 17:09:16 +02:00
parent 6964c01c77
commit 10328b7582
5 changed files with 220 additions and 122 deletions

View File

@ -5,9 +5,8 @@
<ion-icon name="person"></ion-icon> <ion-icon name="person"></ion-icon>
</button> </button>
<!-- Go to "home". --> <button *ngIf="loaded && currentPageObj" ion-button icon-only (click)="openMap($event)"[attr.aria-label]="'addon.mod_wiki.map' | translate" aria-haspopup="true">
<button ion-button icon-only *ngIf="showHomeButton" (click)="goToWikiHome()" [attr.aria-label]="'addon.mod_wiki.gowikihome' | translate"> <ion-icon name="map"></ion-icon>
<ion-icon name="home"></ion-icon>
</button> </button>
<core-context-menu> <core-context-menu>
@ -25,11 +24,6 @@
<!-- Content. --> <!-- Content. -->
<core-loading [hideUntil]="loaded" class="core-loading-center"> <core-loading [hideUntil]="loaded" class="core-loading-center">
<core-tabs [hideUntil]="loaded" [selectedIndex]="selectedTab">
<!-- Page contents. -->
<core-tab [title]="'addon.mod_wiki.viewpage' | translate" icon="document">
<ng-template>
<div padding class="addon-mod_wiki-page-content"> <div padding class="addon-mod_wiki-page-content">
<core-course-module-description *ngIf="isMainPage" [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description> <core-course-module-description *ngIf="isMainPage" [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
@ -56,27 +50,6 @@
<core-tag-list [tags]="currentPageObj.tags"></core-tag-list> <core-tag-list [tags]="currentPageObj.tags"></core-tag-list>
</div> </div>
</div> </div>
</ng-template>
</core-tab>
<!-- Map. -->
<core-tab [title]="'addon.mod_wiki.map' | translate" icon="map">
<ng-template>
<ion-list>
<ng-container *ngFor="let letter of map">
<ion-item-divider *ngIf="letter.label">
{{ letter.label }}
</ion-item-divider>
<a ion-item text-wrap *ngFor="let page of letter.pages" (click)="goToPage(page)">
{{ page.title }}
<ion-note *ngIf="!page.id" item-end color="danger">{{ 'core.offline' | translate }}</ion-note>
</a>
</ng-container>
</ion-list>
</ng-template>
</core-tab>
</core-tabs>
</core-loading> </core-loading>
<ion-fab core-fab bottom end *ngIf="canEdit"> <ion-fab core-fab bottom end *ngIf="canEdit">

View File

@ -12,8 +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, Optional, Injector, Input, ViewChild } from '@angular/core'; import { Component, Optional, Injector, Input } from '@angular/core';
import { Content, NavController, PopoverController, ViewController } from 'ionic-angular'; import { Content, NavController, PopoverController, ViewController, ModalController } from 'ionic-angular';
import { CoreGroupsProvider } from '@providers/groups'; import { CoreGroupsProvider } from '@providers/groups';
import { CoreUtilsProvider } from '@providers/utils/utils'; import { CoreUtilsProvider } from '@providers/utils/utils';
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component'; import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
@ -21,7 +21,6 @@ import { CoreUserProvider } from '@core/user/providers/user';
import { AddonModWikiProvider, AddonModWikiSubwikiListData } from '../../providers/wiki'; import { AddonModWikiProvider, AddonModWikiSubwikiListData } from '../../providers/wiki';
import { AddonModWikiOfflineProvider } from '../../providers/wiki-offline'; import { AddonModWikiOfflineProvider } from '../../providers/wiki-offline';
import { AddonModWikiSyncProvider } from '../../providers/wiki-sync'; import { AddonModWikiSyncProvider } from '../../providers/wiki-sync';
import { CoreTabsComponent } from '@components/tabs/tabs';
import { AddonModWikiSubwikiPickerComponent } from '../../components/subwiki-picker/subwiki-picker'; import { AddonModWikiSubwikiPickerComponent } from '../../components/subwiki-picker/subwiki-picker';
import { CoreTagProvider } from '@core/tag/providers/tag'; import { CoreTagProvider } from '@core/tag/providers/tag';
@ -33,7 +32,6 @@ import { CoreTagProvider } from '@core/tag/providers/tag';
templateUrl: 'addon-mod-wiki-index.html', templateUrl: 'addon-mod-wiki-index.html',
}) })
export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComponent { export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComponent {
@ViewChild(CoreTabsComponent) tabs: CoreTabsComponent;
@Input() action: string; @Input() action: string;
@Input() pageId: number; @Input() pageId: number;
@ -55,9 +53,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
loadedSubwikis: any[] = []; // The loaded subwikis. loadedSubwikis: any[] = []; // The loaded subwikis.
pageIsOffline: boolean; // Whether the loaded page is an offline page. pageIsOffline: boolean; // Whether the loaded page is an offline page.
pageContent: string; // Page content to display. pageContent: string; // Page content to display.
showHomeButton: boolean; // Whether to display the home button.
selectedTab = 0; // Tab to select at start.
map: any[] = []; // Map of pages, categorized by letter.
subwikiData: AddonModWikiSubwikiListData = { // Data for the subwiki selector. subwikiData: AddonModWikiSubwikiListData = { // Data for the subwiki selector.
subwikiSelected: 0, subwikiSelected: 0,
userSelected: 0, userSelected: 0,
@ -66,25 +61,23 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
count: 0 count: 0
}; };
tagsEnabled: boolean; tagsEnabled: boolean;
currentPageObj: any; // Object of the current loaded page.
protected syncEventName = AddonModWikiSyncProvider.AUTO_SYNCED; protected syncEventName = AddonModWikiSyncProvider.AUTO_SYNCED;
protected currentSubwiki: any; // Current selected subwiki. protected currentSubwiki: any; // Current selected subwiki.
protected currentPage: number; // Current loaded page ID. protected currentPage: number; // Current loaded page ID.
protected currentPageObj: any; // Object of the current loaded page.
protected subwikiPages: any[]; // List of subwiki pages. protected subwikiPages: any[]; // List of subwiki pages.
protected newPageObserver: any; // Observer to check for new pages. protected newPageObserver: any; // Observer to check for new pages.
protected ignoreManualSyncEvent: boolean; // Whether manual sync event should be ignored. protected ignoreManualSyncEvent: boolean; // Whether manual sync event should be ignored.
protected manualSyncObserver: any; // An observer to watch for manual sync events. protected manualSyncObserver: any; // An observer to watch for manual sync events.
protected currentUserId: number; // Current user ID. protected currentUserId: number; // Current user ID.
protected hasEdited = false; // Whether the user has opened the edit page. protected hasEdited = false; // Whether the user has opened the edit page.
protected mapInitialized = false; // Whether the map was initialized.
protected initHomeButton = true; // Whether the init home button must be initialized.
constructor(injector: Injector, protected wikiProvider: AddonModWikiProvider, @Optional() protected content: Content, constructor(injector: Injector, protected wikiProvider: AddonModWikiProvider, @Optional() protected content: Content,
protected wikiOffline: AddonModWikiOfflineProvider, protected wikiSync: AddonModWikiSyncProvider, protected wikiOffline: AddonModWikiOfflineProvider, protected wikiSync: AddonModWikiSyncProvider,
protected navCtrl: NavController, protected utils: CoreUtilsProvider, protected groupsProvider: CoreGroupsProvider, protected navCtrl: NavController, protected utils: CoreUtilsProvider, protected groupsProvider: CoreGroupsProvider,
protected userProvider: CoreUserProvider, private popoverCtrl: PopoverController, protected userProvider: CoreUserProvider, private popoverCtrl: PopoverController,
private tagProvider: CoreTagProvider) { private tagProvider: CoreTagProvider, protected modalCtrl: ModalController) {
super(injector, content); super(injector, content);
this.pageStr = this.translate.instant('addon.mod_wiki.wikipage'); this.pageStr = this.translate.instant('addon.mod_wiki.wikipage');
@ -100,7 +93,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
this.currentUserId = this.sitesProvider.getCurrentSiteUserId(); this.currentUserId = this.sitesProvider.getCurrentSiteUserId();
this.isMainPage = !this.pageId && !this.pageTitle; this.isMainPage = !this.pageId && !this.pageTitle;
this.currentPage = this.pageId; this.currentPage = this.pageId;
this.selectedTab = this.action == 'map' ? 1 : 0;
this.loadContent(false, true).then(() => { this.loadContent(false, true).then(() => {
if (!this.wiki) { if (!this.wiki) {
@ -118,6 +110,10 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
// Ignore errors. // Ignore errors.
}); });
} }
}).finally(() => {
if (this.action == 'map') {
this.openMap();
}
}); });
// Listen for manual sync events. // Listen for manual sync events.
@ -179,40 +175,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
} }
/**
* Construct the map of pages.
*
* @param subwikiPages List of pages.
*/
constructMap(subwikiPages: any[]): void {
let letter,
initialLetter;
this.map = [];
this.mapInitialized = true;
subwikiPages.sort((a, b) => {
const compareA = a.title.toLowerCase().trim(),
compareB = b.title.toLowerCase().trim();
return compareA.localeCompare(compareB);
});
subwikiPages.forEach((page) => {
const letterCandidate = page.title.charAt(0).toLocaleUpperCase();
// Should we create a new grouping?
if (letterCandidate !== initialLetter) {
initialLetter = letterCandidate;
letter = {label: letterCandidate, pages: []};
this.map.push(letter);
}
// Add the subwiki to the currently active grouping.
letter.pages.push(page);
});
}
/** /**
* Get the wiki data. * Get the wiki data.
* *
@ -248,11 +210,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
return Promise.reject(null); return Promise.reject(null);
} }
if (this.isCurrentView || this.initHomeButton) {
this.initHomeButton = false;
this.showHomeButton = !!this.getWikiHomeView();
}
// Get module instance if it's empty. // Get module instance if it's empty.
let promise; let promise;
if (!this.module.id) { if (!this.module.id) {
@ -397,7 +354,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
this.subwikiPages = this.wikiProvider.sortPagesByTitle(subwikiPages.concat(offlinePages)); this.subwikiPages = this.wikiProvider.sortPagesByTitle(subwikiPages.concat(offlinePages));
this.constructMap(this.subwikiPages);
// Reject if no currentPage selected from the subwikis given (if no subwikis available, do not reject). // Reject if no currentPage selected from the subwikis given (if no subwikis available, do not reject).
if (!this.currentPage && !this.pageTitle && this.subwikiPages.length > 0) { if (!this.currentPage && !this.pageTitle && this.subwikiPages.length > 0) {
@ -492,17 +448,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} }
} }
/**
* Go back to the initial page of the wiki.
*/
goToWikiHome(): void {
const homeView = this.getWikiHomeView();
if (homeView) {
this.navCtrl.popTo(homeView);
}
}
/** /**
* Open the view to create the first page of the wiki. * Open the view to create the first page of the wiki.
*/ */
@ -613,9 +558,39 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
return; return;
} }
}
// No changes done. /**
this.tabs.selectTab(0); * Show the map.
*
* @param {MouseEvent} event Event.
*/
openMap(event: MouseEvent): void {
const modal = this.modalCtrl.create('AddonModWikiMapPage', {
pages: this.subwikiPages,
selected: this.currentPageObj && this.currentPageObj.id,
homeView: this.getWikiHomeView()
}, { cssClass: 'core-modal-lateral',
showBackdrop: true,
enableBackdropDismiss: true,
enterAnimation: 'core-modal-lateral-transition',
leaveAnimation: 'core-modal-lateral-transition' });
// If the modal sends back a SCO, load it.
modal.onDidDismiss((page) => {
if (page) {
if (page.type == 'home') {
// Go back to the initial page of the wiki.
this.navCtrl.popTo(page.goto);
} else {
this.goToPage(page.goto);
}
}
});
modal.present({
ev: event
});
} }
/** /**
@ -638,8 +613,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
wikiId: this.wiki.id, wikiId: this.wiki.id,
subwikiId: subwikiId, subwikiId: subwikiId,
userId: userId, userId: userId,
groupId: groupId, groupId: groupId
action: this.tabs.selected == 0 ? 'page' : 'map'
}); });
} }
} }
@ -731,8 +705,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
ionViewDidEnter(): void { ionViewDidEnter(): void {
super.ionViewDidEnter(); super.ionViewDidEnter();
this.tabs && this.tabs.ionViewDidEnter();
if (this.hasEdited) { if (this.hasEdited) {
this.hasEdited = false; this.hasEdited = false;
this.showLoadingAndRefresh(true, false); this.showLoadingAndRefresh(true, false);
@ -745,8 +717,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
ionViewDidLeave(): void { ionViewDidLeave(): void {
super.ionViewDidLeave(); super.ionViewDidLeave();
this.tabs && this.tabs.ionViewDidLeave();
if (this.navCtrl.getActive().component.name == 'AddonModWikiEditPage') { if (this.navCtrl.getActive().component.name == 'AddonModWikiEditPage') {
this.hasEdited = true; this.hasEdited = true;
} }

View File

@ -0,0 +1,29 @@
<ion-header>
<ion-navbar core-back-button>
<ion-title>{{ 'addon.mod_wiki.map' | translate }}</ion-title>
<ion-buttons end>
<button ion-button icon-only (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
<ion-icon name="close"></ion-icon>
</button>
</ion-buttons>
</ion-navbar>
</ion-header>
<ion-content>
<nav>
<ion-list>
<!-- Go to "home". -->
<a ion-item text-wrap *ngIf="homeView" (click)="goToWikiHome()">
<ion-icon name="home" item-start></ion-icon> {{ 'addon.mod_wiki.gowikihome' | translate }}
</a>
<ng-container *ngFor="let letter of map">
<ion-item-divider *ngIf="letter.label">
{{ letter.label }}
</ion-item-divider>
<a ion-item text-wrap *ngFor="let page of letter.pages" (click)="goToPage(page)" [class.core-nav-item-selected]="selected == page.id">
<ion-icon name="home" item-start *ngIf="page.firstpage"></ion-icon> {{ page.title }}
<ion-note *ngIf="!page.id" item-end color="danger">{{ 'core.offline' | translate }}</ion-note>
</a>
</ng-container>
</ion-list>
</nav>
</ion-content>

View File

@ -0,0 +1,33 @@
// (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 { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
import { AddonModWikiMapPage } from './map';
@NgModule({
declarations: [
AddonModWikiMapPage,
],
imports: [
CoreComponentsModule,
CoreDirectivesModule,
IonicPageModule.forChild(AddonModWikiMapPage),
TranslateModule.forChild()
],
})
export class AddonModWikiMapPageModule {}

View File

@ -0,0 +1,93 @@
// (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 } from '@angular/core';
import { IonicPage, NavParams, ViewController } from 'ionic-angular';
/**
* Modal to display the map of a Wiki.
*/
@IonicPage({ segment: 'addon-mod-wiki-map' })
@Component({
selector: 'page-addon-mod-wiki-map',
templateUrl: 'map.html',
})
export class AddonModWikiMapPage {
map: any[] = []; // Map of pages, categorized by letter.
selected: number;
homeView: ViewController;
constructor(navParams: NavParams, protected viewCtrl: ViewController) {
this.constructMap(navParams.get('pages') || []);
this.selected = navParams.get('selected');
this.homeView = navParams.get('homeView');
}
/**
* Function called when a page is clicked.
*
* @param {any} page Clicked page.
*/
goToPage(page: any): void {
this.viewCtrl.dismiss({type: 'page', goto: page});
}
/**
* Go back to the initial page of the wiki.
*/
goToWikiHome(): void {
this.viewCtrl.dismiss({type: 'home', goto: this.homeView});
}
/**
* Construct the map of pages.
*
* @param {any[]} pages List of pages.
*/
protected constructMap(pages: any[]): void {
let letter,
initialLetter;
this.map = [];
pages.sort((a, b) => {
const compareA = a.title.toLowerCase().trim(),
compareB = b.title.toLowerCase().trim();
return compareA.localeCompare(compareB);
});
pages.forEach((page) => {
const letterCandidate = page.title.charAt(0).toLocaleUpperCase();
// Should we create a new grouping?
if (letterCandidate !== initialLetter) {
initialLetter = letterCandidate;
letter = {label: letterCandidate, pages: []};
this.map.push(letter);
}
// Add the subwiki to the currently active grouping.
letter.pages.push(page);
});
}
/**
* Close modal.
*/
closeModal(): void {
this.viewCtrl.dismiss();
}
}