MOBILE-2324 participants: Add list page
parent
41c8d0c94f
commit
861f3b2339
|
@ -18,8 +18,8 @@
|
|||
<core-loading [hideUntil]="dataLoaded">
|
||||
<!-- @todo: Use core-tabs or a new component. core-tabs might initialize all tabs at start, so we might require a new component. -->
|
||||
<div class="core-tabs-bar">
|
||||
<a aria-selected="true">{{ 'core.course.contents' | translate }}</a>
|
||||
<a *ngFor="let handler of courseHandlers">{{ handler.data.title || translate }}</a>
|
||||
<a aria-selected="true" [title]="'core.course.contents' | translate">{{ 'core.course.contents' | translate }}</a>
|
||||
<a *ngFor="let handler of courseHandlers" (click)="handler.data.action(course)" [title]="handler.data.title | translate">{{ handler.data.title | translate }}</a>
|
||||
</div>
|
||||
<core-course-format [course]="course" [sections]="sections" [initialSectionId]="sectionId" [initialSectionNumber]="sectionNumber" [downloadEnabled]="downloadEnabled" (completionChanged)="onCompletionChange()"></core-course-format>
|
||||
</core-loading>
|
||||
|
|
|
@ -50,12 +50,12 @@
|
|||
<ion-icon name="briefcase" item-start></ion-icon>
|
||||
<h2>{{ 'core.course.contents' | translate }}</h2>
|
||||
</a>
|
||||
<div class="core-course-handlers" *ngIf="handlersShouldBeShown && course._handlers && course._handlers.length">
|
||||
<a ion-item text-wrap *ngFor="let handler of course._handlers" class="core-courses-handler {{handler.class}}">
|
||||
<ion-icon [name]="icon" item-start></ion-icon>
|
||||
<h2><core-format-text [text]="title | translate"></core-format-text></h2>
|
||||
<ng-container *ngIf="handlersShouldBeShown && course._handlers && course._handlers.length">
|
||||
<a ion-item text-wrap *ngFor="let handler of course._handlers" class="core-courses-handler {{handler.data.class}}" (click)="handler.data.action(course)" [title]="handler.data.title | translate">
|
||||
<ion-icon [name]="handler.data.icon" item-start></ion-icon>
|
||||
<h2>{{ handler.data.title | translate }}</h2>
|
||||
</a>
|
||||
</div>
|
||||
</ng-container>
|
||||
<ion-item class="core-loading-course-handlers" text-center *ngIf="handlersShouldBeShown && !handlersLoaded">
|
||||
<ion-spinner></ion-spinner>
|
||||
</ion-item>
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
"lastname": "Surname",
|
||||
"manager": "Manager",
|
||||
"newpicture": "New picture",
|
||||
"noparticipants": "No participants found for this course.",
|
||||
"participants": "Participants",
|
||||
"phone1": "Phone",
|
||||
"phone2": "Mobile phone",
|
||||
"roles": "Roles",
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
<ion-header>
|
||||
<ion-navbar>
|
||||
<ion-title>{{ 'core.user.participants' | translate }}</ion-title>
|
||||
</ion-navbar>
|
||||
</ion-header>
|
||||
<core-split-view>
|
||||
<ion-content>
|
||||
<ion-refresher [enabled]="participantsLoaded" (ionRefresh)="refreshParticipants($event)">
|
||||
<ion-refresher-content pullingText="{{ 'core.pulltorefresh' | translate }}"></ion-refresher-content>
|
||||
</ion-refresher>
|
||||
<core-loading [hideUntil]="participantsLoaded">
|
||||
<core-empty-box *ngIf="participants && participants.length == 0" icon="person" [message]="'core.user.noparticipants' | translate">
|
||||
</core-empty-box>
|
||||
|
||||
<ion-list *ngIf="participants && participants.length > 0">
|
||||
<a ion-item text-wrap *ngFor="let participant of participants" [title]="participant.fullname" (click)="gotoParticipant(participant.id)" [class.core-split-item-selected]="participant.id == participantId">
|
||||
<ion-avatar item-start>
|
||||
<img src="{{participant.profileimageurl}}" [alt]="'core.pictureof' | translate:{$a: participant.fullname}" core-external-content>
|
||||
</ion-avatar>
|
||||
<h2><core-format-text [text]="participant.fullname"></core-format-text></h2>
|
||||
<p *ngIf="participant.lastaccess"><strong>{{ 'core.lastaccess' | translate }}: </strong>{{ participant.lastaccess * 1000 | coreFormatDate:"dfmediumdate"}}</p>
|
||||
</a>
|
||||
</ion-list>
|
||||
|
||||
<ion-infinite-scroll [enabled]="canLoadMore" (ionInfinite)="$event.waitFor(fetchData())">
|
||||
<ion-infinite-scroll-content></ion-infinite-scroll-content>
|
||||
</ion-infinite-scroll>
|
||||
</core-loading>
|
||||
</ion-content>
|
||||
</core-split-view>
|
|
@ -0,0 +1,35 @@
|
|||
// (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 { CorePipesModule } from '../../../../pipes/pipes.module';
|
||||
import { CoreUserParticipantsPage } from './participants';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
CoreUserParticipantsPage,
|
||||
],
|
||||
imports: [
|
||||
CoreComponentsModule,
|
||||
CoreDirectivesModule,
|
||||
CorePipesModule,
|
||||
IonicPageModule.forChild(CoreUserParticipantsPage),
|
||||
TranslateModule.forChild()
|
||||
],
|
||||
})
|
||||
export class CoreUserParticipantsPageModule {}
|
|
@ -0,0 +1,104 @@
|
|||
// (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 } 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';
|
||||
|
||||
/**
|
||||
* Page that displays the list of course participants.
|
||||
*/
|
||||
@IonicPage({segment: 'core-user-participants'})
|
||||
@Component({
|
||||
selector: 'page-core-user-participants',
|
||||
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) {
|
||||
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<any>} Resolved when done.
|
||||
*/
|
||||
fetchData(refresh: boolean = false): Promise<any> {
|
||||
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});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { NavController } from 'ionic-angular';
|
||||
import { CoreCourseOptionsHandler, CoreCourseOptionsHandlerData } from '../../course/providers/options-delegate';
|
||||
import { CoreCourseProvider } from '../../course/providers/course';
|
||||
import { CoreUserProvider } from './user';
|
||||
import { CoreLoginHelperProvider } from '../../login/providers/helper';
|
||||
|
||||
/**
|
||||
* Course nav handler.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreUserParticipantsCourseOptionHandler implements CoreCourseOptionsHandler {
|
||||
name = 'AddonParticipants';
|
||||
priority = 600;
|
||||
|
||||
constructor(private userProvider: CoreUserProvider, private loginHelper: CoreLoginHelperProvider) {}
|
||||
|
||||
/**
|
||||
* Should invalidate the data to determine if the handler is enabled for a certain course.
|
||||
*
|
||||
* @param {number} courseId The course ID.
|
||||
* @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions.
|
||||
* @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
invalidateEnabledForCourse(courseId: number, navOptions?: any, admOptions?: any): Promise<any> {
|
||||
if (navOptions && typeof navOptions.participants != 'undefined') {
|
||||
// No need to invalidate anything.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return this.userProvider.invalidateParticipantsList(courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled on a site level.
|
||||
*
|
||||
* @return {boolean} Whether or not the handler is enabled on a site level.
|
||||
*/
|
||||
isEnabled(): boolean | Promise<boolean> {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the handler is enabled for a certain course.
|
||||
* For perfomance reasons, do NOT call WebServices in here, call them in shouldDisplayForCourse.
|
||||
*
|
||||
* @param {number} courseId The course ID.
|
||||
* @param {any} accessData Access type and data. Default, guest, ...
|
||||
* @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions.
|
||||
* @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
|
||||
*/
|
||||
isEnabledForCourse(courseId: number, accessData: any, navOptions?: any, admOptions?: any): boolean | Promise<boolean> {
|
||||
if (accessData && accessData.type == CoreCourseProvider.ACCESS_GUEST) {
|
||||
return false; // Not enabled for guests.
|
||||
}
|
||||
|
||||
if (navOptions && typeof navOptions.participants != 'undefined') {
|
||||
return navOptions.participants;
|
||||
}
|
||||
|
||||
// Assume it's enabled for now, further checks will be done in shouldDisplayForCourse.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the handler should be displayed for a course. If not implemented, assume it's true.
|
||||
*
|
||||
* @param {number} courseId The course ID.
|
||||
* @param {any} accessData Access type and data. Default, guest, ...
|
||||
* @param {any} [navOptions] Course navigation options for current user. See CoreCoursesProvider.getUserNavigationOptions.
|
||||
* @param {any} [admOptions] Course admin options for current user. See CoreCoursesProvider.getUserAdministrationOptions.
|
||||
* @return {boolean|Promise<boolean>} True or promise resolved with true if enabled.
|
||||
*/
|
||||
shouldDisplayForCourse(courseId: number, accessData: any, navOptions?: any, admOptions?: any): boolean | Promise<boolean> {
|
||||
if (navOptions && typeof navOptions.participants != 'undefined') {
|
||||
return navOptions.participants;
|
||||
}
|
||||
|
||||
return this.userProvider.isPluginEnabledForCourse(courseId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data needed to render the handler.
|
||||
*
|
||||
* @return {CoreMainMenuHandlerData} Data needed to render the handler.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
// (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 { Injectable } from '@angular/core';
|
||||
import { CoreContentLinksHandlerBase } from '../../../core/contentlinks/classes/base-handler';
|
||||
import { CoreContentLinksAction } from '../../../core/contentlinks/providers/delegate';
|
||||
import { CoreLoginHelperProvider } from '../../../core/login/providers/helper';
|
||||
import { CoreUserProvider } from './user';
|
||||
|
||||
/**
|
||||
* Handler to treat links to user participants page.
|
||||
*/
|
||||
@Injectable()
|
||||
export class CoreUserParticipantsLinkHandler extends CoreContentLinksHandlerBase {
|
||||
name = 'AddonParticipants';
|
||||
featureName = '$mmCoursesDelegate_mmaParticipants';
|
||||
pattern = /\/user\/index\.php/;
|
||||
|
||||
constructor(private userProvider: CoreUserProvider, private loginHelper: CoreLoginHelperProvider) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of actions for a link (url).
|
||||
*
|
||||
* @param {string[]} siteIds List of sites the URL belongs to.
|
||||
* @param {string} url The URL to treat.
|
||||
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||
* @return {CoreContentLinksAction[]|Promise<CoreContentLinksAction[]>} List of (or promise resolved with list of) actions.
|
||||
*/
|
||||
getActions(siteIds: string[], url: string, params: any, courseId?: number):
|
||||
CoreContentLinksAction[] | Promise<CoreContentLinksAction[]> {
|
||||
courseId = parseInt(params.id, 10) || courseId;
|
||||
|
||||
return [{
|
||||
action: (siteId, navCtrl?): void => {
|
||||
// Always use redirect to make it the new history root (to avoid "loops" in history).
|
||||
this.loginHelper.redirect('AddonParticipantsListPage', {courseId: courseId}, siteId);
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the handler is enabled for a certain site (site + user) and a URL.
|
||||
* If not defined, defaults to true.
|
||||
*
|
||||
* @param {string} siteId The site ID.
|
||||
* @param {string} url The URL to treat.
|
||||
* @param {any} params The params of the URL. E.g. 'mysite.com?id=1' -> {id: 1}
|
||||
* @param {number} [courseId] Course ID related to the URL. Optional but recommended.
|
||||
* @return {boolean|Promise<boolean>} Whether the handler is enabled for the URL and site.
|
||||
*/
|
||||
isEnabled(siteId: string, url: string, params: any, courseId?: number): boolean | Promise<boolean> {
|
||||
courseId = parseInt(params.id, 10) || courseId;
|
||||
|
||||
if (!courseId || url.indexOf('/grade/report/') != -1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return this.userProvider.isPluginEnabledForCourse(courseId, siteId);
|
||||
}
|
||||
}
|
|
@ -23,6 +23,7 @@ import { CoreUtilsProvider } from '../../../providers/utils/utils';
|
|||
*/
|
||||
@Injectable()
|
||||
export class CoreUserProvider {
|
||||
static PARTICIPANTS_LIST_LIMIT = 50; // Max of participants to retrieve in each WS call.
|
||||
static PROFILE_REFRESHED = 'CoreUserProfileRefreshed';
|
||||
static PROFILE_PICTURE_UPDATED = 'CoreUserProfilePictureUpdated';
|
||||
protected ROOT_CACHE_KEY = 'mmUser:';
|
||||
|
@ -106,6 +107,59 @@ export class CoreUserProvider {
|
|||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get participants for a certain course.
|
||||
*
|
||||
* @param {number} courseId ID of the course.
|
||||
* @param {number} limitFrom Position of the first participant to get.
|
||||
* @param {number} limitNumber Number of participants to get.
|
||||
* @param {string} [siteId] Site Id. If not defined, use current site.
|
||||
* @return {Promise<any>} Promise to be resolved when the participants are retrieved.
|
||||
*/
|
||||
getParticipants(courseId: number, limitFrom: number = 0, limitNumber: number = CoreUserProvider.PARTICIPANTS_LIST_LIMIT,
|
||||
siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
this.logger.debug(`Get participants for course '${courseId}' starting at '${limitFrom}'`);
|
||||
|
||||
const data = {
|
||||
courseid: courseId,
|
||||
options: [
|
||||
{
|
||||
name: 'limitfrom',
|
||||
value: limitFrom
|
||||
},
|
||||
{
|
||||
name: 'limitnumber',
|
||||
value: limitNumber
|
||||
},
|
||||
{
|
||||
name: 'sortby',
|
||||
value: 'siteorder'
|
||||
}
|
||||
]
|
||||
}, preSets = {
|
||||
cacheKey: this.getParticipantsListCacheKey(courseId)
|
||||
};
|
||||
|
||||
return site.read('core_enrol_get_enrolled_users', data, preSets).then((users) => {
|
||||
const canLoadMore = users.length >= limitNumber;
|
||||
this.storeUsers(users, siteId);
|
||||
|
||||
return { participants: users, canLoadMore: canLoadMore };
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Get cache key for participant list WS calls.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @return {string} Cache key.
|
||||
*/
|
||||
protected getParticipantsListCacheKey(courseId: number): string {
|
||||
return this.ROOT_CACHE_KEY + 'list:' + courseId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get user profile. The type of profile retrieved depends on the params.
|
||||
*
|
||||
|
@ -218,6 +272,59 @@ export class CoreUserProvider {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates participant list for a certain course.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} [siteId] Site Id. If not defined, use current site.
|
||||
* @return {Promise<any>} Promise resolved when the list is invalidated.
|
||||
*/
|
||||
invalidateParticipantsList(courseId: number, siteId?: string): Promise<any> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return site.invalidateWsCacheForKey(this.getParticipantsListCacheKey(courseId));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if course participants is disabled in a certain site.
|
||||
*
|
||||
* @param {string} [siteId] Site Id. If not defined, use current site.
|
||||
* @return {Promise<boolean>} Promise resolved with true if disabled, rejected or resolved with false otherwise.
|
||||
*/
|
||||
isParticipantsDisabled(siteId?: string): Promise<boolean> {
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
return this.isParticipantsDisabledInSite(site);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if course participants is disabled in a certain site.
|
||||
*
|
||||
* @param {CoreSite} [site] Site. If not defined, use current site.
|
||||
* @return {boolean} Whether it's disabled.
|
||||
*/
|
||||
isParticipantsDisabledInSite(site?: any): boolean {
|
||||
site = site || this.sitesProvider.getCurrentSite();
|
||||
|
||||
return site.isFeatureDisabled('$mmCoursesDelegate_mmaParticipants');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the participants addon is enabled for a certain course.
|
||||
*
|
||||
* @param {number} courseId Course ID.
|
||||
* @param {string} [siteId] Site Id. If not defined, use current site.
|
||||
* @return {Promise<any>} Promise resolved with true if plugin is enabled, rejected or resolved with false otherwise.
|
||||
*/
|
||||
isPluginEnabledForCourse(courseId: number, siteId?: string): Promise<any> {
|
||||
if (!courseId) {
|
||||
return Promise.reject(null);
|
||||
}
|
||||
|
||||
// Retrieving one participant will fail if browsing users is disabled by capabilities.
|
||||
return this.utils.promiseWorks(this.getParticipants(courseId, 0, 1, siteId));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if update profile picture is disabled in a certain site.
|
||||
*
|
||||
|
@ -248,6 +355,17 @@ export class CoreUserProvider {
|
|||
return this.sitesProvider.getCurrentSite().write('core_user_view_user_profile', params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Participants list view in Moodle.
|
||||
* @param {number} courseId Course ID.
|
||||
* @return {Promise<any>} Promise resolved when done.
|
||||
*/
|
||||
logParticipantsView(courseId?: number): Promise<any> {
|
||||
return this.sitesProvider.getCurrentSite().write('core_user_view_user_list', {
|
||||
courseid: courseId
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store user basic information in local DB to be retrieved if the WS call fails.
|
||||
*
|
||||
|
@ -268,4 +386,23 @@ export class CoreUserProvider {
|
|||
return site.getDb().insertOrUpdateRecord(this.USERS_TABLE, userRecord, { id: userId });
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Store users basic information in local DB.
|
||||
*
|
||||
* @param {any[]} users Users to store. Fields stored: id, fullname, profileimageurl.
|
||||
* @param {string} [siteId] ID of the site. If not defined, use current site.
|
||||
* @return {Promise<any>} Promise resolve when the user is stored.
|
||||
*/
|
||||
storeUsers(users: any[], siteId?: string): Promise<any> {
|
||||
const promises = [];
|
||||
|
||||
users.forEach((user) => {
|
||||
if (typeof user.id != 'undefined') {
|
||||
promises.push(this.storeUser(user.id, user.fullname, user.profileimageurl, siteId));
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,9 @@ import { CoreEventsProvider } from '../../providers/events';
|
|||
import { CoreSitesProvider } from '../../providers/sites';
|
||||
import { CoreContentLinksDelegate } from '../contentlinks/providers/delegate';
|
||||
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';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
|
@ -34,15 +37,22 @@ import { CoreUserProfileLinkHandler } from './providers/user-link-handler';
|
|||
CoreUserProfileMailHandler,
|
||||
CoreUserProvider,
|
||||
CoreUserHelperProvider,
|
||||
CoreUserProfileLinkHandler
|
||||
CoreUserProfileLinkHandler,
|
||||
CoreUserParticipantsCourseOptionHandler,
|
||||
CoreUserParticipantsLinkHandler
|
||||
]
|
||||
})
|
||||
export class CoreUserModule {
|
||||
constructor(userDelegate: CoreUserDelegate, userProfileMailHandler: CoreUserProfileMailHandler,
|
||||
eventsProvider: CoreEventsProvider, sitesProvider: CoreSitesProvider, userProvider: CoreUserProvider,
|
||||
contentLinksDelegate: CoreContentLinksDelegate, userLinkHandler: CoreUserProfileLinkHandler) {
|
||||
contentLinksDelegate: CoreContentLinksDelegate, userLinkHandler: CoreUserProfileLinkHandler,
|
||||
courseOptionHandler: CoreUserParticipantsCourseOptionHandler, linkHandler: CoreUserParticipantsLinkHandler,
|
||||
courseOptionsDelegate: CoreCourseOptionsDelegate) {
|
||||
|
||||
userDelegate.registerHandler(userProfileMailHandler);
|
||||
courseOptionsDelegate.registerHandler(courseOptionHandler);
|
||||
contentLinksDelegate.registerHandler(userLinkHandler);
|
||||
contentLinksDelegate.registerHandler(linkHandler);
|
||||
|
||||
eventsProvider.on(CoreEventsProvider.USER_DELETED, (data) => {
|
||||
// Search for userid in params.
|
||||
|
|
|
@ -96,6 +96,7 @@
|
|||
"info": "Info",
|
||||
"ios": "iOS",
|
||||
"labelsep": ": ",
|
||||
"lastaccess": "Last access",
|
||||
"lastdownloaded": "Last downloaded",
|
||||
"lastmodified": "Last modified",
|
||||
"lastsync": "Last synchronization",
|
||||
|
|
Loading…
Reference in New Issue