MOBILE-3335 glossary: Improve UX on browser modes
parent
f27bd969d1
commit
52e6e41fcd
|
@ -1,7 +1,10 @@
|
||||||
<!-- Buttons to add to the header. -->
|
<!-- Buttons to add to the header. -->
|
||||||
<core-navbar-buttons end>
|
<core-navbar-buttons end>
|
||||||
<button *ngIf="glossary" ion-button icon-only (click)="openModePicker($event)" [attr.aria-label]="'addon.mod_glossary.browsemode' | translate">
|
<button *ngIf="glossary && glossary.browsemodes && glossary.browsemodes.length > 1" ion-button icon-only (click)="openModePicker($event)" [attr.aria-label]="'addon.mod_glossary.browsemode' | translate">
|
||||||
<ion-icon name="funnel"></ion-icon>
|
<core-icon name="fa-sort"></core-icon>
|
||||||
|
</button>
|
||||||
|
<button *ngIf="glossary" ion-button icon-only (click)="toggleSearch()" [attr.aria-label]="'addon.mod_glossary.bysearch' | translate">
|
||||||
|
<ion-icon name="search"></ion-icon>
|
||||||
</button>
|
</button>
|
||||||
<core-context-menu>
|
<core-context-menu>
|
||||||
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl" [iconAction]="'open'"></core-context-menu-item>
|
<core-context-menu-item *ngIf="externalUrl" [priority]="900" [content]="'core.openinbrowser' | translate" [href]="externalUrl" [iconAction]="'open'"></core-context-menu-item>
|
||||||
|
@ -29,11 +32,11 @@
|
||||||
<ion-icon name="warning"></ion-icon> {{ 'core.hasdatatosync' | translate:{$a: moduleName} }}
|
<ion-icon name="warning"></ion-icon> {{ 'core.hasdatatosync' | translate:{$a: moduleName} }}
|
||||||
</ion-card>
|
</ion-card>
|
||||||
|
|
||||||
<core-search-box *ngIf="viewMode == 'search'" (onSubmit)="search($event)" [placeholder]="'addon.mod_glossary.searchquery' | translate" [autoFocus]="true" [lengthCheck]="2" [showClear]="false" searchArea="AddonModGlossary-{{module.id}}"></core-search-box>
|
<core-search-box *ngIf="isSearch" (onSubmit)="search($event)" [placeholder]="'addon.mod_glossary.searchquery' | translate" [autoFocus]="true" [lengthCheck]="2" [showClear]="false" searchArea="AddonModGlossary-{{module.id}}"></core-search-box>
|
||||||
|
|
||||||
<core-loading [hideUntil]="loaded" class="core-loading-center">
|
<core-loading [hideUntil]="loaded" class="core-loading-center">
|
||||||
|
|
||||||
<ion-list *ngIf="viewMode != 'search' && offlineEntries.length > 0">
|
<ion-list *ngIf="!isSearch && offlineEntries.length > 0">
|
||||||
<ion-item-divider>
|
<ion-item-divider>
|
||||||
{{ 'addon.mod_glossary.entriestobesynced' | translate }}
|
{{ 'addon.mod_glossary.entriestobesynced' | translate }}
|
||||||
</ion-item-divider>
|
</ion-item-divider>
|
||||||
|
|
|
@ -25,7 +25,7 @@ import { AddonModGlossarySyncProvider } from '../../providers/sync';
|
||||||
import { AddonModGlossaryModePickerPopoverComponent } from '../mode-picker/mode-picker';
|
import { AddonModGlossaryModePickerPopoverComponent } from '../mode-picker/mode-picker';
|
||||||
import { AddonModGlossaryPrefetchHandler } from '../../providers/prefetch-handler';
|
import { AddonModGlossaryPrefetchHandler } from '../../providers/prefetch-handler';
|
||||||
|
|
||||||
type FetchMode = 'author_all' | 'cat_all' | 'newest_first' | 'recently_updated' | 'search' | 'letter_all';
|
type FetchMode = 'author_all' | 'cat_all' | 'newest_first' | 'recently_updated' | 'letter_all';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Component that displays a glossary entry page.
|
* Component that displays a glossary entry page.
|
||||||
|
@ -41,8 +41,6 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
component = AddonModGlossaryProvider.COMPONENT;
|
component = AddonModGlossaryProvider.COMPONENT;
|
||||||
moduleName = 'glossary';
|
moduleName = 'glossary';
|
||||||
|
|
||||||
fetchMode: FetchMode;
|
|
||||||
viewMode: string;
|
|
||||||
isSearch = false;
|
isSearch = false;
|
||||||
entries = [];
|
entries = [];
|
||||||
offlineEntries = [];
|
offlineEntries = [];
|
||||||
|
@ -60,6 +58,10 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
protected showDivider: (entry: any, previous?: any) => boolean;
|
protected showDivider: (entry: any, previous?: any) => boolean;
|
||||||
protected getDivider: (entry: any) => string;
|
protected getDivider: (entry: any) => string;
|
||||||
protected addEntryObserver: any;
|
protected addEntryObserver: any;
|
||||||
|
protected fetchMode: FetchMode;
|
||||||
|
protected viewMode: string;
|
||||||
|
protected fetchedEntriesCanLoadMore = false;
|
||||||
|
protected fetchedEntries = [];
|
||||||
|
|
||||||
hasOfflineRatings: boolean;
|
hasOfflineRatings: boolean;
|
||||||
protected ratingOfflineObserver: any;
|
protected ratingOfflineObserver: any;
|
||||||
|
@ -252,6 +254,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
*/
|
*/
|
||||||
protected switchMode(mode: FetchMode): void {
|
protected switchMode(mode: FetchMode): void {
|
||||||
this.fetchMode = mode;
|
this.fetchMode = mode;
|
||||||
|
this.isSearch = false;
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'author_all':
|
case 'author_all':
|
||||||
|
@ -294,15 +297,6 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
this.getDivider = null;
|
this.getDivider = null;
|
||||||
this.showDivider = (): boolean => false;
|
this.showDivider = (): boolean => false;
|
||||||
break;
|
break;
|
||||||
case 'search':
|
|
||||||
// Search for entries.
|
|
||||||
this.viewMode = 'search';
|
|
||||||
this.fetchFunction = this.glossaryProvider.getEntriesBySearch;
|
|
||||||
this.fetchInvalidate = this.glossaryProvider.invalidateEntriesBySearch;
|
|
||||||
this.fetchArguments = null; // Dynamically set later.
|
|
||||||
this.getDivider = null;
|
|
||||||
this.showDivider = (): boolean => false;
|
|
||||||
break;
|
|
||||||
case 'letter_all':
|
case 'letter_all':
|
||||||
default:
|
default:
|
||||||
// Consider it is 'letter_all'.
|
// Consider it is 'letter_all'.
|
||||||
|
@ -341,26 +335,15 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
*/
|
*/
|
||||||
openModePicker(event: MouseEvent): void {
|
openModePicker(event: MouseEvent): void {
|
||||||
const popover = this.popoverCtrl.create(AddonModGlossaryModePickerPopoverComponent, {
|
const popover = this.popoverCtrl.create(AddonModGlossaryModePickerPopoverComponent, {
|
||||||
glossary: this.glossary,
|
browsemodes: this.glossary.browsemodes,
|
||||||
selectedMode: this.fetchMode
|
selectedMode: this.isSearch ? '' : this.fetchMode
|
||||||
});
|
});
|
||||||
|
|
||||||
popover.onDidDismiss((newMode: FetchMode) => {
|
popover.onDidDismiss((mode: FetchMode) => {
|
||||||
if (newMode === this.fetchMode) {
|
if (mode !== this.fetchMode) {
|
||||||
return;
|
this.changeFetchMode(mode);
|
||||||
}
|
} else if (this.isSearch) {
|
||||||
|
this.toggleSearch();
|
||||||
this.loadingMessage = this.translate.instant('core.loading');
|
|
||||||
this.domUtils.scrollToTop(this.content);
|
|
||||||
this.switchMode(newMode);
|
|
||||||
|
|
||||||
if (this.fetchMode === 'search') {
|
|
||||||
// If it's not an instant search, then we reset the values.
|
|
||||||
this.entries = [];
|
|
||||||
this.canLoadMore = false;
|
|
||||||
} else {
|
|
||||||
this.loaded = false;
|
|
||||||
this.loadContent();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -369,6 +352,44 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Toggles between search and fetch mode.
|
||||||
|
*/
|
||||||
|
toggleSearch(): void {
|
||||||
|
if (this.isSearch) {
|
||||||
|
this.isSearch = false;
|
||||||
|
this.entries = this.fetchedEntries;
|
||||||
|
this.canLoadMore = this.fetchedEntriesCanLoadMore;
|
||||||
|
this.switchMode(this.fetchMode);
|
||||||
|
} else {
|
||||||
|
// Search for entries.
|
||||||
|
this.fetchFunction = this.glossaryProvider.getEntriesBySearch;
|
||||||
|
this.fetchInvalidate = this.glossaryProvider.invalidateEntriesBySearch;
|
||||||
|
this.fetchArguments = null; // Dynamically set later.
|
||||||
|
this.getDivider = null;
|
||||||
|
this.showDivider = (): boolean => false;
|
||||||
|
this.isSearch = true;
|
||||||
|
|
||||||
|
this.fetchedEntries = this.entries;
|
||||||
|
this.fetchedEntriesCanLoadMore = this.canLoadMore;
|
||||||
|
this.canLoadMore = false;
|
||||||
|
this.entries = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change fetch mode
|
||||||
|
* @param {FetchMode} mode [description]
|
||||||
|
*/
|
||||||
|
changeFetchMode(mode: FetchMode): void {
|
||||||
|
this.isSearch = false;
|
||||||
|
this.loadingMessage = this.translate.instant('core.loading');
|
||||||
|
this.domUtils.scrollToTop(this.content);
|
||||||
|
this.switchMode(mode);
|
||||||
|
this.loaded = false;
|
||||||
|
this.loadContent();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens an entry.
|
* Opens an entry.
|
||||||
*
|
*
|
||||||
|
|
|
@ -27,14 +27,10 @@ export class AddonModGlossaryModePickerPopoverComponent {
|
||||||
selectedMode: string;
|
selectedMode: string;
|
||||||
|
|
||||||
constructor(navParams: NavParams, private viewCtrl: ViewController) {
|
constructor(navParams: NavParams, private viewCtrl: ViewController) {
|
||||||
this.selectedMode = navParams.get('selectedMode');
|
this.selectedMode = navParams.get('selectedMode') || '';
|
||||||
const glossary = navParams.get('glossary');
|
const browsemodes = navParams.get('browsemodes');
|
||||||
|
|
||||||
// Preparing browse modes.
|
browsemodes.forEach((mode) => {
|
||||||
this.modes = [
|
|
||||||
{key: 'search', langkey: 'addon.mod_glossary.bysearch'}
|
|
||||||
];
|
|
||||||
glossary.browsemodes.forEach((mode) => {
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'letter' :
|
case 'letter' :
|
||||||
this.modes.push({key: 'letter_all', langkey: 'addon.mod_glossary.byalphabet'});
|
this.modes.push({key: 'letter_all', langkey: 'addon.mod_glossary.byalphabet'});
|
||||||
|
|
Loading…
Reference in New Issue