MOBILE-3335 glossary: Improve UX on browser modes

main
Pau Ferrer Ocaña 2020-02-06 15:02:19 +01:00
parent f27bd969d1
commit 52e6e41fcd
3 changed files with 61 additions and 41 deletions

View File

@ -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>

View File

@ -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.
* *

View File

@ -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'});