From 9843da3fb0adca039d16c909a8a4e3af79b85518 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Tue, 30 Jan 2018 13:16:28 +0100 Subject: [PATCH] MOBILE-2324 course: Use core-tabs in section and render addon components --- src/components/split-view/split-view.html | 1 - src/components/tabs/tabs.scss | 10 ++ src/components/tabs/tabs.ts | 4 +- src/core/course/pages/section/section.html | 32 ++++-- src/core/course/pages/section/section.ts | 2 + src/core/course/providers/options-delegate.ts | 13 +-- src/core/user/components/components.module.ts | 12 +- .../components/participants/participants.html | 25 +++++ .../components/participants/participants.ts | 103 ++++++++++++++++++ .../user/pages/participants/participants.html | 26 +---- .../pages/participants/participants.module.ts | 8 +- .../user/pages/participants/participants.ts | 78 +------------ .../user/providers/course-option-handler.ts | 10 +- src/core/user/user.module.ts | 2 + 14 files changed, 187 insertions(+), 139 deletions(-) create mode 100644 src/core/user/components/participants/participants.html create mode 100644 src/core/user/components/participants/participants.ts diff --git a/src/components/split-view/split-view.html b/src/components/split-view/split-view.html index dbea8c69b..6f8042dd3 100644 --- a/src/components/split-view/split-view.html +++ b/src/components/split-view/split-view.html @@ -1,6 +1,5 @@ - diff --git a/src/components/tabs/tabs.scss b/src/components/tabs/tabs.scss index dd40b2d86..c68461533 100644 --- a/src/components/tabs/tabs.scss +++ b/src/components/tabs/tabs.scss @@ -36,10 +36,20 @@ core-tabs { core-tab { display: none; height: 100%; + position: relative; &.selected { display: block; } + + ion-header { + display: none; + } + + .fixed-content, .scroll-content { + margin-top: 0 !important; + margin-bottom: 0 !important; + } } } diff --git a/src/components/tabs/tabs.ts b/src/components/tabs/tabs.ts index f5e056984..04f744e0d 100644 --- a/src/components/tabs/tabs.ts +++ b/src/components/tabs/tabs.ts @@ -43,7 +43,7 @@ import { Content } from 'ionic-angular'; }) export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges { @Input() selectedIndex = 0; // Index of the tab to select. - @Input() hideUntil: boolean; // Determine when should the contents be shown. + @Input() hideUntil = true; // Determine when should the contents be shown. @Output() ionChange: EventEmitter = new EventEmitter(); // Emitted when the tab changes. @ViewChild('originalTabs') originalTabsRef: ElementRef; @ViewChild('topTabs') topTabs: ElementRef; @@ -148,7 +148,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges { let selectedIndex = this.selectedIndex || 0, selectedTab = this.tabs[selectedIndex]; - if (!selectedTab.enabled || !selectedTab.show) { + if (!selectedTab || !selectedTab.enabled || !selectedTab.show) { // The tab is not enabled or not shown. Get the first tab that is enabled. selectedTab = this.tabs.find((tab, index) => { if (tab.enabled && tab.show) { diff --git a/src/core/course/pages/section/section.html b/src/core/course/pages/section/section.html index 2cf256aee..b57f35177 100644 --- a/src/core/course/pages/section/section.html +++ b/src/core/course/pages/section/section.html @@ -11,16 +11,26 @@ - - - + + + + + + + + - - - - - + + + + + + + + + + + + + diff --git a/src/core/course/pages/section/section.ts b/src/core/course/pages/section/section.ts index a0b293a74..06dd8666a 100644 --- a/src/core/course/pages/section/section.ts +++ b/src/core/course/pages/section/section.ts @@ -43,6 +43,7 @@ export class CoreCourseSectionPage implements OnDestroy { sectionId: number; sectionNumber: number; courseHandlers: CoreCourseOptionsHandlerToDisplay[]; + handlerData: any = {}; // Data to send to the handlers components. dataLoaded: boolean; downloadEnabled: boolean; downloadEnabledIcon = 'square-outline'; // Disabled by default. @@ -63,6 +64,7 @@ export class CoreCourseSectionPage implements OnDestroy { this.course = navParams.get('course'); this.sectionId = navParams.get('sectionId'); this.sectionNumber = navParams.get('sectionNumber'); + this.handlerData.courseId = this.course.id; // Get the title to display. We dont't have sections yet. this.title = courseFormatDelegate.getCourseTitle(this.course); diff --git a/src/core/course/providers/options-delegate.ts b/src/core/course/providers/options-delegate.ts index ec74e848f..758003c14 100644 --- a/src/core/course/providers/options-delegate.ts +++ b/src/core/course/providers/options-delegate.ts @@ -91,12 +91,6 @@ export interface CoreCourseOptionsHandlerData { */ title: string; - /** - * Name of the icon to display for the handler. - * @type {string} - */ - icon: string; - /** * Class to add to the displayed handler. * @type {string} @@ -104,11 +98,10 @@ export interface CoreCourseOptionsHandlerData { class?: string; /** - * Action to perform when the handler is clicked. - * - * @param {any} course The course. + * The component to render the handler. It must be the component class, not the name or an instance. + * When the component is created, it will receive the courseId as input. */ - action(course: any): void; + component: any; } /** diff --git a/src/core/user/components/components.module.ts b/src/core/user/components/components.module.ts index 3fd47b41e..215319610 100644 --- a/src/core/user/components/components.module.ts +++ b/src/core/user/components/components.module.ts @@ -16,23 +16,33 @@ import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { IonicModule } from 'ionic-angular'; import { TranslateModule } from '@ngx-translate/core'; +import { CoreUserParticipantsComponent } from './participants/participants'; import { CoreUserProfileFieldComponent } from './user-profile-field/user-profile-field'; import { CoreComponentsModule } from '../../../components/components.module'; +import { CoreDirectivesModule } from '../../../directives/directives.module'; +import { CorePipesModule } from '../../../pipes/pipes.module'; @NgModule({ declarations: [ + CoreUserParticipantsComponent, CoreUserProfileFieldComponent ], imports: [ CommonModule, IonicModule, TranslateModule.forChild(), - CoreComponentsModule + CoreComponentsModule, + CoreDirectivesModule, + CorePipesModule ], providers: [ ], exports: [ + CoreUserParticipantsComponent, CoreUserProfileFieldComponent + ], + entryComponents: [ + CoreUserParticipantsComponent ] }) export class CoreUserComponentsModule {} diff --git a/src/core/user/components/participants/participants.html b/src/core/user/components/participants/participants.html new file mode 100644 index 000000000..9364acc74 --- /dev/null +++ b/src/core/user/components/participants/participants.html @@ -0,0 +1,25 @@ + + + + + + + + + + + + + + +

+

{{ 'core.lastaccess' | translate }}: {{ participant.lastaccess * 1000 | coreFormatDate:"dfmediumdate"}}

+
+
+ + + + +
+
+
\ No newline at end of file diff --git a/src/core/user/components/participants/participants.ts b/src/core/user/components/participants/participants.ts new file mode 100644 index 000000000..5c9a2f75a --- /dev/null +++ b/src/core/user/components/participants/participants.ts @@ -0,0 +1,103 @@ +// (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, ViewChild, Input, OnInit } from '@angular/core'; +import { Content, NavParams } from 'ionic-angular'; +import { CoreUserProvider } from '../../providers/user'; +import { CoreDomUtilsProvider } from '../../../../providers/utils/dom'; +import { CoreSplitViewComponent } from '../../../../components/split-view/split-view'; + +/** + * Component that displays the list of course participants. + */ +@Component({ + selector: 'core-user-participants', + templateUrl: 'participants.html', +}) +export class CoreUserParticipantsComponent implements OnInit { + @ViewChild(Content) content: Content; + @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent; + + @Input() courseId: number; + + participantId: number; + participants = []; + canLoadMore = false; + participantsLoaded = false; + + constructor(private userProvider: CoreUserProvider, private domUtils: CoreDomUtilsProvider) { } + + /** + * View loaded. + */ + ngOnInit(): void { + // Get first participants. + this.fetchData(true).then(() => { + if (!this.participantId && this.splitviewCtrl.isOn() && this.participants.length > 0) { + // Take first and load it. + this.gotoParticipant(this.participants[0].id); + } + // Add log in Moodle. + this.userProvider.logView(this.courseId).catch(() => { + // Ignore errors. + }); + }).finally(() => { + this.participantsLoaded = true; + }); + } + + /** + * Fetch all the data required for the view. + * + * @param {boolean} [refresh] Empty events array first. + * @return {Promise} Resolved when done. + */ + fetchData(refresh: boolean = false): Promise { + const firstToGet = refresh ? 0 : this.participants.length; + + return this.userProvider.getParticipants(this.courseId, firstToGet).then((data) => { + if (refresh) { + this.participants = data.participants; + } else { + this.participants = this.participants.concat(data.participants); + } + this.canLoadMore = data.canLoadMore; + }).catch((error) => { + this.domUtils.showErrorModalDefault(error, 'Error loading participants'); + this.canLoadMore = false; // Set to false to prevent infinite calls with infinite-loading. + }); + } + + /** + * Refresh data. + * + * @param {any} refresher Refresher. + */ + refreshParticipants(refresher: any): void { + this.userProvider.invalidateParticipantsList(this.courseId).finally(() => { + this.fetchData(true).finally(() => { + refresher.complete(); + }); + }); + } + + /** + * Navigate to a particular user profile. + * @param {number} userId User Id where to navigate. + */ + gotoParticipant(userId: number): void { + this.participantId = userId; + this.splitviewCtrl.push('CoreUserProfilePage', {userId: userId, courseId: this.courseId}); + } +} diff --git a/src/core/user/pages/participants/participants.html b/src/core/user/pages/participants/participants.html index 67cc2b8b6..ec0f41e69 100644 --- a/src/core/user/pages/participants/participants.html +++ b/src/core/user/pages/participants/participants.html @@ -3,28 +3,4 @@ {{ 'core.user.participants' | translate }} - - - - - - - - - - - - - - -

-

{{ 'core.lastaccess' | translate }}: {{ participant.lastaccess * 1000 | coreFormatDate:"dfmediumdate"}}

-
-
- - - - -
-
-
\ No newline at end of file + \ No newline at end of file diff --git a/src/core/user/pages/participants/participants.module.ts b/src/core/user/pages/participants/participants.module.ts index ceaea818a..29089cd65 100644 --- a/src/core/user/pages/participants/participants.module.ts +++ b/src/core/user/pages/participants/participants.module.ts @@ -15,9 +15,7 @@ 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 { CorePipesModule } from '../../../../pipes/pipes.module'; +import { CoreUserComponentsModule } from '../../components/components.module'; import { CoreUserParticipantsPage } from './participants'; @NgModule({ @@ -25,9 +23,7 @@ import { CoreUserParticipantsPage } from './participants'; CoreUserParticipantsPage, ], imports: [ - CoreComponentsModule, - CoreDirectivesModule, - CorePipesModule, + CoreUserComponentsModule, IonicPageModule.forChild(CoreUserParticipantsPage), TranslateModule.forChild() ], diff --git a/src/core/user/pages/participants/participants.ts b/src/core/user/pages/participants/participants.ts index c82d69703..ae2a470c8 100644 --- a/src/core/user/pages/participants/participants.ts +++ b/src/core/user/pages/participants/participants.ts @@ -12,11 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -import { Component, ViewChild } from '@angular/core'; -import { IonicPage, Content, NavParams } from 'ionic-angular'; -import { CoreUserProvider } from '../../providers/user'; -import { CoreDomUtilsProvider } from '../../../../providers/utils/dom'; -import { CoreSplitViewComponent } from '../../../../components/split-view/split-view'; +import { Component } from '@angular/core'; +import { IonicPage, NavParams } from 'ionic-angular'; /** * Page that displays the list of course participants. @@ -27,78 +24,9 @@ import { CoreSplitViewComponent } from '../../../../components/split-view/split- templateUrl: 'participants.html', }) export class CoreUserParticipantsPage { - @ViewChild(Content) content: Content; - @ViewChild(CoreSplitViewComponent) splitviewCtrl: CoreSplitViewComponent; - courseId: number; - participantId: number; - participants = []; - canLoadMore = false; - participantsLoaded = false; - constructor(private userProvider: CoreUserProvider, private domUtils: CoreDomUtilsProvider, - navParams: NavParams) { + constructor(navParams: NavParams) { this.courseId = navParams.get('courseId'); } - - /** - * View loaded. - */ - ionViewDidLoad(): void { - // Get first participants. - this.fetchData(true).then(() => { - if (!this.participantId && this.splitviewCtrl.isOn() && this.participants.length > 0) { - // Take first and load it. - this.gotoParticipant(this.participants[0].id); - } - // Add log in Moodle. - this.userProvider.logView(this.courseId); - }).finally(() => { - this.participantsLoaded = true; - }); - } - - /** - * Fetch all the data required for the view. - * - * @param {boolean} [refresh] Empty events array first. - * @return {Promise} Resolved when done. - */ - fetchData(refresh: boolean = false): Promise { - const firstToGet = refresh ? 0 : this.participants.length; - - return this.userProvider.getParticipants(this.courseId, firstToGet).then((data) => { - if (refresh) { - this.participants = data.participants; - } else { - this.participants = this.participants.concat(data.participants); - } - this.canLoadMore = data.canLoadMore; - }).catch((error) => { - this.domUtils.showErrorModalDefault(error, 'Error loading participants'); - this.canLoadMore = false; // Set to false to prevent infinite calls with infinite-loading. - }); - } - - /** - * Refresh data. - * - * @param {any} refresher Refresher. - */ - refreshParticipants(refresher: any): void { - this.userProvider.invalidateParticipantsList(this.courseId).finally(() => { - this.fetchData(true).finally(() => { - refresher.complete(); - }); - }); - } - - /** - * Navigate to a particular user profile. - * @param {number} userId User Id where to navigate. - */ - gotoParticipant(userId: number): void { - this.participantId = userId; - this.splitviewCtrl.push('CoreUserProfilePage', {userId: userId, courseId: this.courseId}); - } } diff --git a/src/core/user/providers/course-option-handler.ts b/src/core/user/providers/course-option-handler.ts index 44c03a75c..35336cb65 100644 --- a/src/core/user/providers/course-option-handler.ts +++ b/src/core/user/providers/course-option-handler.ts @@ -18,6 +18,7 @@ import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '../../co import { CoreCourseProvider } from '../../course/providers/course'; import { CoreUserProvider } from './user'; import { CoreLoginHelperProvider } from '../../login/providers/helper'; +import { CoreUserParticipantsComponent } from '../components/participants/participants'; /** * Course nav handler. @@ -102,16 +103,9 @@ export class CoreUserParticipantsCourseOptionHandler implements CoreCourseOption */ getDisplayData(): CoreCourseOptionsHandlerData { return { - icon: 'person', title: 'core.user.participants', class: 'core-user-participants-handler', - action: (course: any): void => { - const pageParams = { - courseId: course.id - }; - // Always use redirect to make it the new history root (to avoid "loops" in history). - this.loginHelper.redirect('CoreUserParticipantsPage', pageParams); - } + component: CoreUserParticipantsComponent }; } } diff --git a/src/core/user/user.module.ts b/src/core/user/user.module.ts index 6a4fc9730..92588ca57 100644 --- a/src/core/user/user.module.ts +++ b/src/core/user/user.module.ts @@ -25,11 +25,13 @@ import { CoreUserProfileLinkHandler } from './providers/user-link-handler'; import { CoreUserParticipantsCourseOptionHandler } from './providers/course-option-handler'; import { CoreUserParticipantsLinkHandler } from './providers/participants-link-handler'; import { CoreCourseOptionsDelegate } from '../course/providers/options-delegate'; +import { CoreUserComponentsModule } from './components/components.module'; @NgModule({ declarations: [ ], imports: [ + CoreUserComponentsModule ], providers: [ CoreUserDelegate,