Merge pull request #2107 from crazyserver/MOBILE-3105

Mobile 3105
main
Juan Leyva 2019-10-01 12:14:32 +02:00 committed by GitHub
commit 4c433ddff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 246 additions and 163 deletions

View File

@ -5,9 +5,8 @@
<ion-icon name="person"></ion-icon>
</button>
<!-- Go to "home". -->
<button ion-button icon-only *ngIf="showHomeButton" (click)="goToWikiHome()" [attr.aria-label]="'addon.mod_wiki.gowikihome' | translate">
<ion-icon name="home"></ion-icon>
<button *ngIf="loaded && currentPageObj" ion-button icon-only (click)="openMap($event)"[attr.aria-label]="'addon.mod_wiki.map' | translate" aria-haspopup="true">
<ion-icon name="map"></ion-icon>
</button>
<core-context-menu>
@ -25,58 +24,33 @@
<!-- Content. -->
<core-loading [hideUntil]="loaded" class="core-loading-center">
<div padding *ngIf="(isMainPage && description) || pageIsOffline || hasOffline || pageWarning">
<core-course-module-description *ngIf="isMainPage" [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
<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">
<core-course-module-description *ngIf="isMainPage" [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
<!-- Wiki has something offline. -->
<div class="core-warning-card" icon-start *ngIf="pageIsOffline || hasOffline">
<ion-icon name="warning"></ion-icon>
<span *ngIf="pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: pageStr} }}</span>
<span *ngIf="!pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</span>
</div>
<!-- Wiki has something offline. -->
<div class="core-warning-card" icon-start *ngIf="pageIsOffline || hasOffline">
<ion-icon name="warning"></ion-icon>
<span *ngIf="pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: pageStr} }}</span>
<span *ngIf="!pageIsOffline">{{ 'core.hasdatatosync' | translate:{$a: moduleName} }}</span>
</div>
<!-- Page warning. -->
<div class="core-warning-card" icon-start *ngIf="pageWarning">
<ion-icon name="warning"></ion-icon>
{{ pageWarning }}
</div>
<article [ngClass]="{'addon-mod_wiki-noedit': !canEdit}">
<core-format-text *ngIf="pageContent" [component]="component" [componentId]="componentId" [text]="pageContent"></core-format-text>
<core-empty-box *ngIf="!pageContent" icon="document" [message]="'addon.mod_wiki.nocontent' | translate" [inline]="true"></core-empty-box>
</article>
<div margin-top *ngIf="tagsEnabled && currentPageObj && currentPageObj.tags && currentPageObj.tags.length > 0">
<b>{{ 'core.tag.tags' | translate }}:</b>
<core-tag-list [tags]="currentPageObj.tags"></core-tag-list>
</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>
<!-- Page warning. -->
<div class="core-warning-card" icon-start *ngIf="pageWarning">
<ion-icon name="warning"></ion-icon>
{{ pageWarning }}
</div>
</div>
<div padding class="addon-mod_wiki-page-content">
<article [ngClass]="{'addon-mod_wiki-noedit': !canEdit}">
<core-format-text *ngIf="pageContent" [component]="component" [componentId]="componentId" [text]="pageContent"></core-format-text>
<core-empty-box *ngIf="!pageContent" icon="document" [message]="'addon.mod_wiki.nocontent' | translate" [inline]="true"></core-empty-box>
</article>
<div margin-top *ngIf="tagsEnabled && currentPageObj && currentPageObj.tags && currentPageObj.tags.length > 0">
<b>{{ 'core.tag.tags' | translate }}:</b>
<core-tag-list [tags]="currentPageObj.tags"></core-tag-list>
</div>
</div>
</core-loading>
<ion-fab core-fab bottom end *ngIf="canEdit">

View File

@ -12,6 +12,7 @@ ion-app.app-root addon-mod-wiki-index {
.addon-mod_wiki-page-content {
background-color: $white;
border-top: 1px solid $gray;
@include darkmode() {
background-color: $black;
}

View File

@ -12,8 +12,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Optional, Injector, Input, ViewChild } from '@angular/core';
import { Content, NavController, PopoverController, ViewController } from 'ionic-angular';
import { Component, Optional, Injector, Input } from '@angular/core';
import { Content, NavController, PopoverController, ViewController, ModalController } from 'ionic-angular';
import { CoreGroupsProvider } from '@providers/groups';
import { CoreUtilsProvider } from '@providers/utils/utils';
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 { AddonModWikiOfflineProvider } from '../../providers/wiki-offline';
import { AddonModWikiSyncProvider } from '../../providers/wiki-sync';
import { CoreTabsComponent } from '@components/tabs/tabs';
import { AddonModWikiSubwikiPickerComponent } from '../../components/subwiki-picker/subwiki-picker';
import { CoreTagProvider } from '@core/tag/providers/tag';
@ -33,7 +32,6 @@ import { CoreTagProvider } from '@core/tag/providers/tag';
templateUrl: 'addon-mod-wiki-index.html',
})
export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComponent {
@ViewChild(CoreTabsComponent) tabs: CoreTabsComponent;
@Input() action: string;
@Input() pageId: number;
@ -55,9 +53,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
loadedSubwikis: any[] = []; // The loaded subwikis.
pageIsOffline: boolean; // Whether the loaded page is an offline page.
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.
subwikiSelected: 0,
userSelected: 0,
@ -66,25 +61,23 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
count: 0
};
tagsEnabled: boolean;
currentPageObj: any; // Object of the current loaded page.
protected syncEventName = AddonModWikiSyncProvider.AUTO_SYNCED;
protected currentSubwiki: any; // Current selected subwiki.
protected currentPage: number; // Current loaded page ID.
protected currentPageObj: any; // Object of the current loaded page.
protected subwikiPages: any[]; // List of subwiki pages.
protected newPageObserver: any; // Observer to check for new pages.
protected ignoreManualSyncEvent: boolean; // Whether manual sync event should be ignored.
protected manualSyncObserver: any; // An observer to watch for manual sync events.
protected currentUserId: number; // Current user ID.
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,
protected wikiOffline: AddonModWikiOfflineProvider, protected wikiSync: AddonModWikiSyncProvider,
protected navCtrl: NavController, protected utils: CoreUtilsProvider, protected groupsProvider: CoreGroupsProvider,
protected userProvider: CoreUserProvider, private popoverCtrl: PopoverController,
private tagProvider: CoreTagProvider) {
private tagProvider: CoreTagProvider, protected modalCtrl: ModalController) {
super(injector, content);
this.pageStr = this.translate.instant('addon.mod_wiki.wikipage');
@ -100,7 +93,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
this.currentUserId = this.sitesProvider.getCurrentSiteUserId();
this.isMainPage = !this.pageId && !this.pageTitle;
this.currentPage = this.pageId;
this.selectedTab = this.action == 'map' ? 1 : 0;
this.loadContent(false, true).then(() => {
if (!this.wiki) {
@ -118,6 +110,10 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
// Ignore errors.
});
}
}).finally(() => {
if (this.action == 'map') {
this.openMap();
}
});
// Listen for manual sync events.
@ -149,70 +145,25 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
protected checkPageCreatedOrDiscarded(data: any): void {
if (!this.currentPage && data) {
// This is an offline page. Check if the page was created.
let pageId;
for (let i = 0, len = data.created.length; i < len; i++) {
const page = data.created[i];
if (page.title == this.pageTitle) {
pageId = page.pageId;
break;
}
}
if (pageId) {
const page = data.created.find((page) => page.title == this.pageTitle);
if (page) {
// Page was created, set the ID so it's retrieved from server.
this.currentPage = pageId;
this.currentPage = page.pageId;
this.pageIsOffline = false;
} else {
// Page not found in created list, check if it was discarded.
for (let i = 0, len = data.discarded.length; i < len; i++) {
const page = data.discarded[i];
if (page.title == this.pageTitle) {
// Page discarded, show warning.
this.pageWarning = page.warning;
this.pageContent = '';
this.pageIsOffline = false;
this.hasOffline = false;
}
const page = data.discarded.find((page) => page.title == this.pageTitle);
if (page) {
// Page discarded, show warning.
this.pageWarning = page.warning;
this.pageContent = '';
this.pageIsOffline = false;
this.hasOffline = false;
}
}
}
}
/**
* 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.
*
@ -248,11 +199,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
return Promise.reject(null);
}
if (this.isCurrentView || this.initHomeButton) {
this.initHomeButton = false;
this.showHomeButton = !!this.getWikiHomeView();
}
// Get module instance if it's empty.
let promise;
if (!this.module.id) {
@ -370,12 +316,9 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
// If no page specified, search first page.
if (!this.currentPage && !this.pageTitle) {
for (const i in subwikiPages) {
const page = subwikiPages[i];
if (page.firstpage) {
this.currentPage = page.id;
break;
}
const firstPage = subwikiPages.find((page) => page.firstpage );
if (firstPage) {
this.currentPage = firstPage.id;
}
}
@ -396,7 +339,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
}
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).
if (!this.currentPage && !this.pageTitle && this.subwikiPages.length > 0) {
@ -491,17 +433,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.
*/
@ -581,7 +512,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
*
* @param page Page to view.
*/
goToPage(page: any): void {
protected goToPage(page: any): void {
if (!page.id) {
// It's an offline page. Check if we are already in the same offline page.
if (this.currentPage || !this.pageTitle || page.title != this.pageTitle) {
@ -590,8 +521,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
courseId: this.courseId,
pageTitle: page.title,
wikiId: this.wiki.id,
subwikiId: page.subwikiid,
action: 'page'
subwikiId: page.subwikiid
});
return;
@ -605,16 +535,45 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
pageTitle: page.title,
pageId: page.id,
wikiId: page.wikiid,
subwikiId: page.subwikiid,
action: 'page'
subwikiId: page.subwikiid
});
});
return;
}
}
// No changes done.
this.tabs.selectTab(0);
/**
* Show the map.
*
* @param 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 page, 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
});
}
/**
@ -637,8 +596,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
wikiId: this.wiki.id,
subwikiId: subwikiId,
userId: userId,
groupId: groupId,
action: this.tabs.selected == 0 ? 'page' : 'map'
groupId: groupId
});
}
}
@ -730,8 +688,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
ionViewDidEnter(): void {
super.ionViewDidEnter();
this.tabs && this.tabs.ionViewDidEnter();
if (this.hasEdited) {
this.hasEdited = false;
this.showLoadingAndRefresh(true, false);
@ -744,8 +700,6 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
ionViewDidLeave(): void {
super.ionViewDidLeave();
this.tabs && this.tabs.ionViewDidLeave();
if (this.navCtrl.getActive().component.name == 'AddonModWikiEditPage') {
this.hasEdited = true;
}
@ -1013,9 +967,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
if (multiLevelList) {
// As we loop over each subwiki, add it to the current group
for (const i in subwikiList) {
const subwiki = subwikiList[i];
subwikiList.forEach((subwiki) => {
// Should we create a new grouping?
if (subwiki.groupid !== groupValue) {
grouping = {label: subwiki.groupLabel, subwikis: []};
@ -1026,16 +978,14 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
// Add the subwiki to the currently active grouping.
grouping.subwikis.push(subwiki);
}
});
} else if (showMyGroupsLabel) {
const noGrouping = {label: '', subwikis: []},
myGroupsGrouping = {label: this.translate.instant('core.mygroups'), subwikis: []},
otherGroupsGrouping = {label: this.translate.instant('core.othergroups'), subwikis: []};
// As we loop over each subwiki, add it to the current group
for (const i in subwikiList) {
const subwiki = subwikiList[i];
subwikiList.forEach((subwiki) => {
// Add the subwiki to the currently active grouping.
if (typeof subwiki.canedit == 'undefined') {
noGrouping.subwikis.push(subwiki);
@ -1044,7 +994,7 @@ export class AddonModWikiIndexComponent extends CoreCourseModuleMainActivityComp
} else {
otherGroupsGrouping.subwikis.push(subwiki);
}
}
});
// Add each grouping to the subwikis
if (noGrouping.subwikis.length > 0) {

View File

@ -0,0 +1,32 @@
<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>
<ion-icon name="time"></ion-icon>
<span text-wrap>{{ 'core.notsent' | translate }}</span>
</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 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 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();
}
}