MOBILE-3806 myoverview: Renew filter interface
parent
8a04123132
commit
c24bb2e5cc
|
@ -40,11 +40,13 @@
|
|||
"addon.block_learningplans.pluginname": "block_lp",
|
||||
"addon.block_myoverview.all": "block_myoverview",
|
||||
"addon.block_myoverview.allincludinghidden": "block_myoverview",
|
||||
"addon.block_myoverview.favourites": "block_myoverview",
|
||||
"addon.block_myoverview.aria:hiddencourses": "block_myoverview",
|
||||
"addon.block_myoverview.card": "block_myoverview",
|
||||
"addon.block_myoverview.favouritesonly": "local_moodlemobileapp",
|
||||
"addon.block_myoverview.future": "block_myoverview",
|
||||
"addon.block_myoverview.hiddencourses": "block_myoverview",
|
||||
"addon.block_myoverview.inprogress": "block_myoverview",
|
||||
"addon.block_myoverview.lastaccessed": "block_myoverview",
|
||||
"addon.block_myoverview.list": "block_myoverview",
|
||||
"addon.block_myoverview.nocourses": "block_myoverview",
|
||||
"addon.block_myoverview.past": "block_myoverview",
|
||||
"addon.block_myoverview.pluginname": "block_myoverview",
|
||||
|
@ -1400,6 +1402,7 @@
|
|||
"core.allparticipants": "moodle",
|
||||
"core.answer": "moodle",
|
||||
"core.answered": "quiz",
|
||||
"core.applyfilters": "user",
|
||||
"core.areyousure": "moodle",
|
||||
"core.back": "moodle",
|
||||
"core.block.blocks": "moodle",
|
||||
|
|
|
@ -17,10 +17,12 @@ import { NgModule } from '@angular/core';
|
|||
import { CoreSharedModule } from '@/core/shared.module';
|
||||
import { CoreCoursesComponentsModule } from '@features/courses/components/components.module';
|
||||
import { AddonBlockMyOverviewComponent } from './myoverview/myoverview';
|
||||
import { AddonBlockMyOverviewFilterOptionsComponent } from './filteroptions/filteroptions';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
AddonBlockMyOverviewComponent,
|
||||
AddonBlockMyOverviewFilterOptionsComponent,
|
||||
],
|
||||
imports: [
|
||||
CoreSharedModule,
|
||||
|
|
|
@ -0,0 +1,56 @@
|
|||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<h1>{{ 'core.courses.filtermycourses' | translate }}</h1>
|
||||
<ion-buttons slot="end">
|
||||
<ion-button fill="clear" (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
|
||||
<ion-icon name="fas-times" slot="icon-only" aria-hidden=true></ion-icon>
|
||||
</ion-button>
|
||||
</ion-buttons>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content>
|
||||
<ion-list>
|
||||
<ion-radio-group [(ngModel)]="options.timeFilterSelected">
|
||||
<ion-item class="ion-text-wrap" *ngIf="options.show.all">
|
||||
<ion-label>{{'addon.block_myoverview.allincludinghidden' | translate}}</ion-label>
|
||||
<ion-radio slot="end" value="all"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="options.show.inprogress">
|
||||
<ion-label>{{'addon.block_myoverview.inprogress' | translate}}</ion-label>
|
||||
<ion-radio slot="end" value="inprogress"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="options.show.future">
|
||||
<ion-label>{{'addon.block_myoverview.future' | translate}}</ion-label>
|
||||
<ion-radio slot="end" value="future"></ion-radio>
|
||||
</ion-item>
|
||||
<ion-item class="ion-text-wrap" *ngIf="options.show.past">
|
||||
<ion-label>{{'addon.block_myoverview.past' | translate}}</ion-label>
|
||||
<ion-radio slot="end" value="past"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
|
||||
<core-spacer *ngIf="options.show.custom"></core-spacer>
|
||||
<ion-radio-group [(ngModel)]="options.customSelected" *ngIf="options.show.custom" allowEmptySelection="true">
|
||||
<ion-item class="ion-text-wrap" *ngFor="let customOption of options.customFilters">
|
||||
<ion-label>{{customOption.name}}</ion-label>
|
||||
<ion-radio slot="end" [value]="customOption.value"></ion-radio>
|
||||
</ion-item>
|
||||
</ion-radio-group>
|
||||
|
||||
<core-spacer></core-spacer>
|
||||
<ion-item *ngIf="options.show.favourite">
|
||||
<ion-label>{{ 'addon.block_myoverview.favouritesonly' | translate }}</ion-label>
|
||||
<ion-toggle [(ngModel)]="options.favouriteSelected"></ion-toggle>
|
||||
</ion-item>
|
||||
|
||||
<ion-item *ngIf="options.show.hidden">
|
||||
<ion-label>{{ 'addon.block_myoverview.aria:hiddencourses' | translate }}</ion-label>
|
||||
<ion-toggle [(ngModel)]="options.hiddenSelected"></ion-toggle>
|
||||
</ion-item>
|
||||
</ion-list>
|
||||
</ion-content>
|
||||
<ion-footer class="ion-padding">
|
||||
<ion-button (click)="apply()" expand="block" [attr.aria-label]="'core.applyfilters' | translate" class="ion-text-wrap">
|
||||
{{ 'core.applyfilters' | translate }}
|
||||
</ion-button>
|
||||
</ion-footer>
|
|
@ -0,0 +1,44 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// 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, Input } from '@angular/core';
|
||||
import { ModalController } from '@singletons';
|
||||
import { AddonBlockMyOverviewFilterOptions } from '../myoverview/myoverview';
|
||||
|
||||
/**
|
||||
* Component to render a my overview filter options.
|
||||
*/
|
||||
@Component({
|
||||
selector: 'addon-block-myoverview-filter-options',
|
||||
templateUrl: 'filteroptions.html',
|
||||
})
|
||||
export class AddonBlockMyOverviewFilterOptionsComponent {
|
||||
|
||||
@Input() options!: AddonBlockMyOverviewFilterOptions;
|
||||
|
||||
/**
|
||||
* Appl filters.
|
||||
*/
|
||||
apply(): void {
|
||||
ModalController.dismiss(this.options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Close modal.
|
||||
*/
|
||||
closeModal(): void {
|
||||
ModalController.dismiss();
|
||||
}
|
||||
|
||||
}
|
|
@ -4,105 +4,81 @@
|
|||
</ion-label>
|
||||
<div slot="end" class="flex-row">
|
||||
<!-- Download all courses. -->
|
||||
<div *ngIf="downloadCoursesEnabled && downloadEnabled && filteredCourses.length > 1 && !showFilter" class="core-button-spinner">
|
||||
<ion-button *ngIf="!prefetchCoursesData[timeSelectorFilter].loading" fill="clear" color="dark" (click)="prefetchCourses()"
|
||||
<div *ngIf="downloadCoursesEnabled && downloadEnabled && filteredCourses.length > 1" class="core-button-spinner">
|
||||
<ion-button *ngIf="!prefetchCoursesData.loading" fill="clear" color="dark" (click)="prefetchCourses()"
|
||||
[attr.aria-label]="'core.courses.downloadcourses' | translate">
|
||||
<ion-icon [name]="prefetchCoursesData[timeSelectorFilter].icon" slot="icon-only" aria-hidden="true">
|
||||
<ion-icon [name]="prefetchCoursesData.icon" slot="icon-only" aria-hidden="true">
|
||||
</ion-icon>
|
||||
</ion-button>
|
||||
<ion-badge class="core-course-download-courses-progress" *ngIf="prefetchCoursesData[timeSelectorFilter].badge"
|
||||
role="progressbar" [attr.aria-valuemax]="prefetchCoursesData[timeSelectorFilter].total"
|
||||
[attr.aria-valuenow]="prefetchCoursesData[timeSelectorFilter].count"
|
||||
[attr.aria-valuetext]="prefetchCoursesData[timeSelectorFilter].badgeA11yText">
|
||||
{{prefetchCoursesData[timeSelectorFilter].badge}}
|
||||
<ion-badge class="core-course-download-courses-progress" *ngIf="prefetchCoursesData.badge" role="progressbar"
|
||||
[attr.aria-valuemax]="prefetchCoursesData.total" [attr.aria-valuenow]="prefetchCoursesData.count"
|
||||
[attr.aria-valuetext]="prefetchCoursesData.badgeA11yText">
|
||||
{{prefetchCoursesData.badge}}
|
||||
</ion-badge>
|
||||
<ion-spinner *ngIf="prefetchCoursesData[timeSelectorFilter].loading" [attr.aria-label]="'core.loading' | translate">
|
||||
<ion-spinner *ngIf="prefetchCoursesData.loading" [attr.aria-label]="'core.loading' | translate">
|
||||
</ion-spinner>
|
||||
</div>
|
||||
<core-context-menu>
|
||||
<core-context-menu-item *ngIf="loaded && showFilterSwitchButton()" [priority]="1000"
|
||||
[content]="'core.courses.filtermycourses' | translate" (action)="switchFilter()" iconAction="fas-filter"
|
||||
(onClosed)="switchFilterClosed()"></core-context-menu-item>
|
||||
<core-context-menu-item *ngIf="loaded && showSortFilter" [priority]="900"
|
||||
content="{{('core.sortby' | translate) + ' ' + ('addon.block_myoverview.title' | translate)}}"
|
||||
(action)="switchSort('fullname')" [iconAction]="sort == 'fullname' ? 'far-dot-circle' : 'far-circle'">
|
||||
</core-context-menu-item>
|
||||
<core-context-menu-item *ngIf="loaded && showSortFilter && showSortByShortName" [priority]="800"
|
||||
content="{{('core.sortby' | translate) + ' ' + ('addon.block_myoverview.shortname' | translate)}}"
|
||||
(action)="switchSort('shortname')" [iconAction]="sort == 'shortname' ? 'far-dot-circle' : 'far-circle'">
|
||||
</core-context-menu-item>
|
||||
<core-context-menu-item *ngIf="loaded && showSortFilter" [priority]="700"
|
||||
content="{{('core.sortby' | translate) + ' ' + ('addon.block_myoverview.lastaccessed' | translate)}}"
|
||||
(action)="switchSort('lastaccess')" [iconAction]="sort == 'lastaccess' ? 'far-dot-circle' : 'far-circle'">
|
||||
</core-context-menu-item>
|
||||
</core-context-menu>
|
||||
</div>
|
||||
</ion-item-divider>
|
||||
<core-loading [hideUntil]="loaded" [fullscreen]="false">
|
||||
<div class="safe-area-padding-horizontal" [hidden]="showFilter || !showTimeSelectorFilter">
|
||||
<!-- "Time" selector. -->
|
||||
<core-combobox [label]="'core.show' | translate" [selection]="timeSelectorFilter" (onChange)="timeSelectorChanged($event)">
|
||||
<ion-select-option class="ion-text-wrap" value="allincludinghidden" *ngIf="showFilters.allincludinghidden != 'hidden'">
|
||||
{{ 'addon.block_myoverview.allincludinghidden' | translate }}
|
||||
|
||||
<ion-row class="ion-no-padding ion-justify-content-between" *ngIf="hasCourses">
|
||||
<ion-col size="auto" class="ion-no-padding" *ngIf="filters.enabled">
|
||||
<core-combobox interface="modal" [label]="'core.courses.filtermycourses' | translate" (onChange)="filterOptionsChanged($event)"
|
||||
icon="fas-filter" [badge]="filters.count" [modalOptions]="filterModalOptions">
|
||||
</core-combobox>
|
||||
</ion-col>
|
||||
<ion-col class="ion-no-padding">
|
||||
<!-- Filter courses. -->
|
||||
<ion-searchbar class="ion-hide-md-down" [(ngModel)]="textFilter" (ionInput)="filterTextChanged($event.target)"
|
||||
(ionCancel)="filterTextChanged($event.target)" [placeholder]="'core.filter' | translate">
|
||||
</ion-searchbar>
|
||||
</ion-col>
|
||||
<ion-col size="auto" class="ion-no-padding" *ngIf="sort.enabled">
|
||||
<core-combobox [label]="'core.sortby' | translate" [selection]="sort.selected" (onChange)="sortCourses($event)"
|
||||
icon="fas-sort-amount-down-alt">
|
||||
<ion-select-option class="ion-text-wrap" value="fullname">
|
||||
{{'addon.block_myoverview.title' | translate}}
|
||||
</ion-select-option>
|
||||
<ion-select-option class="ion-text-wrap" value="all" *ngIf="showFilters.all != 'hidden'">
|
||||
{{ 'addon.block_myoverview.all' | translate }}
|
||||
<ion-select-option class="ion-text-wrap" value="shortname" *ngIf="sort.shortnameEnabled">
|
||||
{{'addon.block_myoverview.shortname' | translate}}
|
||||
</ion-select-option>
|
||||
<ion-select-option class="ion-text-wrap" value="inprogress" *ngIf="showFilters.inprogress != 'hidden'"
|
||||
[disabled]="showFilters.inprogress == 'disabled'">
|
||||
{{ 'addon.block_myoverview.inprogress' | translate }}
|
||||
</ion-select-option>
|
||||
<ion-select-option class="ion-text-wrap" value="future" *ngIf="showFilters.future != 'hidden'"
|
||||
[disabled]="showFilters.future == 'disabled'">
|
||||
{{ 'addon.block_myoverview.future' | translate }}
|
||||
</ion-select-option>
|
||||
<ion-select-option class="ion-text-wrap" value="past" *ngIf="showFilters.past != 'hidden'"
|
||||
[disabled]="showFilters.past == 'disabled'">
|
||||
{{ 'addon.block_myoverview.past' | translate }}
|
||||
</ion-select-option>
|
||||
<ng-container *ngIf="showFilters.custom != 'hidden'">
|
||||
<ng-container *ngFor="let customOption of customFilter; let index = index">
|
||||
<ion-select-option class="ion-text-wrap" value="custom-{{index}}">{{ customOption.name }}</ion-select-option>
|
||||
</ng-container>
|
||||
</ng-container>
|
||||
<ion-select-option class="ion-text-wrap" value="favourite" *ngIf="showFilters.favourite != 'hidden'"
|
||||
[disabled]="showFilters.favourite == 'disabled'">
|
||||
{{ 'addon.block_myoverview.favourites' | translate }}
|
||||
</ion-select-option>
|
||||
<ion-select-option class="ion-text-wrap" value="hidden" *ngIf="showFilters.hidden != 'hidden'"
|
||||
[disabled]="showFilters.hidden == 'disabled'">
|
||||
{{ 'addon.block_myoverview.hiddencourses' | translate }}
|
||||
<ion-select-option class="ion-text-wrap" value="lastaccess">
|
||||
{{'addon.block_myoverview.lastaccessed' | translate}}
|
||||
</ion-select-option>
|
||||
</core-combobox>
|
||||
</div>
|
||||
|
||||
<div class="safe-area-padding-horizontal" [hidden]="showFilter || layouts.length <= 1">
|
||||
</ion-col>
|
||||
<ion-col size="auto" class="ion-no-padding" *ngIf="layouts.options.length > 1">
|
||||
<!-- "Layouts" selector. -->
|
||||
<core-combobox [label]="'core.show' | translate" [selection]="selectedLayout" (onChange)="layoutChanged($event)">
|
||||
<ng-container *ngFor="let layout of layouts">
|
||||
<core-combobox [label]="'core.show' | translate" [selection]="layouts.selected" (onChange)="saveLayout($event)" icon="fas-th">
|
||||
<ng-container *ngFor="let layout of layouts.options">
|
||||
<ion-select-option class="ion-text-wrap" [value]="layout">{{ 'addon.block_myoverview.'+layout | translate }}
|
||||
</ion-select-option>
|
||||
</ng-container>
|
||||
</core-combobox>
|
||||
</div>
|
||||
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
<ion-row class="ion-no-padding ion-hide-md-up" *ngIf="hasCourses">
|
||||
<ion-col class="ion-no-padding">
|
||||
<!-- Filter courses. -->
|
||||
<ion-searchbar #searchbar *ngIf="showFilter" [(ngModel)]="courses.filter" (ionInput)="filterChanged($event)"
|
||||
(ionCancel)="filterChanged($event)" [placeholder]="'core.courses.filtermycourses' | translate">
|
||||
<ion-searchbar [(ngModel)]="textFilter" (ionInput)="filterTextChanged($event.target)"
|
||||
(ionCancel)="filterTextChanged($event.target)" [placeholder]="'core.filter' | translate">
|
||||
</ion-searchbar>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
||||
<core-empty-box *ngIf="filteredCourses.length == 0" image="assets/img/icons/courses.svg"
|
||||
[message]="'addon.block_myoverview.nocourses' | translate" inline="true">
|
||||
</core-empty-box>
|
||||
|
||||
<!-- List of courses. -->
|
||||
<div class="safe-area-padding">
|
||||
<ion-grid class="ion-no-padding" [class.core-no-grid]="selectedLayout != 'card'">
|
||||
<div class="safe-area-padding" *ngIf="hasCourses">
|
||||
<ion-grid class="ion-no-padding" [class.core-no-grid]="layouts.selected != 'card'">
|
||||
<ion-row class="ion-no-padding">
|
||||
<ion-col *ngFor="let course of filteredCourses" class="ion-no-padding" size="12" size-sm="6" size-md="6" size-lg="4"
|
||||
size-xl="3">
|
||||
<core-courses-course-list-item [course]="course" class="core-courseoverview"
|
||||
[showDownload]="downloadCourseEnabled && downloadEnabled" [layout]="selectedLayout">
|
||||
[showDownload]="downloadCourseEnabled && downloadEnabled" [layout]="layouts.selected">
|
||||
</core-courses-course-list-item>
|
||||
</ion-col>
|
||||
</ion-row>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,10 +1,10 @@
|
|||
{
|
||||
"all": "All (except removed from view)",
|
||||
"allincludinghidden": "All",
|
||||
"aria:hiddencourses": "Show courses removed from view",
|
||||
"card": "Card",
|
||||
"favourites": "Starred",
|
||||
"favouritesonly": "Show starred courses only",
|
||||
"future": "Future",
|
||||
"hiddencourses": "Removed from view",
|
||||
"inprogress": "In progress",
|
||||
"lastaccessed": "Last accessed",
|
||||
"list": "List",
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</ion-avatar>
|
||||
<ion-label>
|
||||
<ion-row>
|
||||
<ion-col>
|
||||
<ion-col class="ion-align-self-center">
|
||||
<p *ngIf="course.categoryname || (course.displayname && course.shortname && course.fullname != course.displayname)"
|
||||
class="core-course-additional-info">
|
||||
<span *ngIf="course.categoryname" class="core-course-category">
|
||||
|
@ -32,7 +32,7 @@
|
|||
</core-format-text>
|
||||
</p>
|
||||
</ion-col>
|
||||
<ion-col size="auto">
|
||||
<ion-col size="auto" class="ion-align-self-center">
|
||||
<ng-container *ngIf="!isEnrolled">
|
||||
<ion-icon *ngFor="let icon of enrolmentIcons" color="dark" size="small" [name]="icon.icon"
|
||||
[title]="icon.label | translate" [attr.aria-label]="icon.label | translate">
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
"all": "All",
|
||||
"allgroups": "All groups",
|
||||
"allparticipants": "All participants",
|
||||
"applyfilters": "Apply filters",
|
||||
"answer": "Answer",
|
||||
"answered": "Answered",
|
||||
"areyousure": "Are you sure?",
|
||||
|
|
Loading…
Reference in New Issue