MOBILE-2080 forum: Update badge

main
Pau Ferrer Ocaña 2018-08-16 12:20:23 +02:00
parent 19c9a7e70e
commit fe494fe700
10 changed files with 94 additions and 17 deletions

View File

@ -84,7 +84,7 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom
this.newDiscObserver = this.eventsProvider.on(AddonModForumProvider.NEW_DISCUSSION_EVENT, this.eventReceived.bind(this)); this.newDiscObserver = this.eventsProvider.on(AddonModForumProvider.NEW_DISCUSSION_EVENT, this.eventReceived.bind(this));
this.replyObserver = this.eventsProvider.on(AddonModForumProvider.REPLY_DISCUSSION_EVENT, this.eventReceived.bind(this)); this.replyObserver = this.eventsProvider.on(AddonModForumProvider.REPLY_DISCUSSION_EVENT, this.eventReceived.bind(this));
// Select the curren opened discussion. // Select the current opened discussion.
this.viewDiscObserver = this.eventsProvider.on(AddonModForumProvider.VIEW_DISCUSSION_EVENT, (data) => { this.viewDiscObserver = this.eventsProvider.on(AddonModForumProvider.VIEW_DISCUSSION_EVENT, (data) => {
if (this.forum && this.forum.id == data.forumId) { if (this.forum && this.forum.id == data.forumId) {
this.selectedDiscussion = this.splitviewCtrl.isOn() ? data.discussion : 0; this.selectedDiscussion = this.splitviewCtrl.isOn() ? data.discussion : 0;

View File

@ -145,7 +145,7 @@ export class AddonModForumDiscussionPage implements OnDestroy {
// Trigger view event, to highlight the current opened discussion in the split view. // Trigger view event, to highlight the current opened discussion in the split view.
this.eventsProvider.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, { this.eventsProvider.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, {
forumId: this.forumId, forumId: this.forumId,
discussion: this.discussionId, discussion: this.discussionId
}, this.sitesProvider.getCurrentSiteId()); }, this.sitesProvider.getCurrentSiteId());
} }
@ -297,6 +297,12 @@ export class AddonModForumDiscussionPage implements OnDestroy {
// // Add log in Moodle and mark unread posts as readed. // // Add log in Moodle and mark unread posts as readed.
this.forumProvider.logDiscussionView(this.discussionId).catch(() => { this.forumProvider.logDiscussionView(this.discussionId).catch(() => {
// Ignore errors. // Ignore errors.
}).finally(() => {
// Trigger mark read posts.
this.eventsProvider.trigger(AddonModForumProvider.MARK_READ_EVENT, {
courseId: this.courseId,
moduleId: this.cmId
}, this.sitesProvider.getCurrentSiteId());
}); });
} }
}); });

View File

@ -117,7 +117,7 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
// Trigger view event, to highlight the current opened discussion in the split view. // Trigger view event, to highlight the current opened discussion in the split view.
this.eventsProvider.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, { this.eventsProvider.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, {
forumId: this.forumId, forumId: this.forumId,
discussion: -this.timeCreated, discussion: -this.timeCreated
}, this.sitesProvider.getCurrentSiteId()); }, this.sitesProvider.getCurrentSiteId());
} }
@ -378,7 +378,7 @@ export class AddonModForumNewDiscussionPage implements OnDestroy {
// Trigger view event, to highlight the current opened discussion in the split view. // Trigger view event, to highlight the current opened discussion in the split view.
this.eventsProvider.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, { this.eventsProvider.trigger(AddonModForumProvider.VIEW_DISCUSSION_EVENT, {
forumId: this.forumId, forumId: this.forumId,
discussion: 0, discussion: 0
}, this.sitesProvider.getCurrentSiteId()); }, this.sitesProvider.getCurrentSiteId());
} else { } else {
this.originalData = null; // Avoid asking for confirmation. this.originalData = null; // Avoid asking for confirmation.

View File

@ -32,6 +32,7 @@ export class AddonModForumProvider {
static NEW_DISCUSSION_EVENT = 'addon_mod_forum_new_discussion'; static NEW_DISCUSSION_EVENT = 'addon_mod_forum_new_discussion';
static REPLY_DISCUSSION_EVENT = 'addon_mod_forum_reply_discussion'; static REPLY_DISCUSSION_EVENT = 'addon_mod_forum_reply_discussion';
static VIEW_DISCUSSION_EVENT = 'addon_mod_forum_view_discussion'; static VIEW_DISCUSSION_EVENT = 'addon_mod_forum_view_discussion';
static MARK_READ_EVENT = 'addon_mod_forum_mark_read';
protected ROOT_CACHE_KEY = 'mmaModForum:'; protected ROOT_CACHE_KEY = 'mmaModForum:';

View File

@ -15,10 +15,12 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { NavController, NavOptions } from 'ionic-angular'; import { NavController, NavOptions } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core'; import { TranslateService } from '@ngx-translate/core';
import { AddonModForumIndexComponent } from '../components/index/index'; import { CoreEventsProvider } from '@providers/events';
import { CoreSitesProvider } from '@providers/sites';
import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@core/course/providers/module-delegate';
import { CoreCourseProvider } from '@core/course/providers/course'; import { CoreCourseProvider } from '@core/course/providers/course';
import { AddonModForumProvider } from './forum'; import { AddonModForumProvider } from './forum';
import { AddonModForumIndexComponent } from '../components/index/index';
/** /**
* Handler to support forum modules. * Handler to support forum modules.
@ -29,7 +31,8 @@ export class AddonModForumModuleHandler implements CoreCourseModuleHandler {
modName = 'forum'; modName = 'forum';
constructor(private courseProvider: CoreCourseProvider, private forumProvider: AddonModForumProvider, constructor(private courseProvider: CoreCourseProvider, private forumProvider: AddonModForumProvider,
private translate: TranslateService) { } private translate: TranslateService, private eventsProvider: CoreEventsProvider,
private sitesProvider: CoreSitesProvider) {}
/** /**
* Check if the handler is enabled on a site level. * Check if the handler is enabled on a site level.
@ -59,13 +62,17 @@ export class AddonModForumModuleHandler implements CoreCourseModuleHandler {
} }
}; };
// Handle unread posts. this.updateExtraBadge(data, courseId, module.id);
this.forumProvider.getForum(courseId, module.id).then((forumData) => {
data.extraBadge = forumData.unreadpostscount ? this.translate.instant('addon.mod_forum.unreadpostsnumber', const event = this.eventsProvider.on(AddonModForumProvider.MARK_READ_EVENT, (eventData) => {
{$a : forumData.unreadpostscount }) : ''; if (eventData.courseId == courseId && eventData.moduleId == module.id) {
}).catch(() => { this.updateExtraBadge(data, eventData.courseId, eventData.moduleId, eventData.siteId);
// Ignore errors. }
}); }, this.sitesProvider.getCurrentSiteId());
data.onDestroy = (): void => {
event && event.off();
};
return data; return data;
} }
@ -91,4 +98,35 @@ export class AddonModForumModuleHandler implements CoreCourseModuleHandler {
displayRefresherInSingleActivity(): boolean { displayRefresherInSingleActivity(): boolean {
return false; return false;
} }
/**
* Triggers an update for the extra badge text.
*
* @param {CoreCourseModuleHandlerData} data Course Module Handler data.
* @param {number} courseId Course ID.
* @param {number} moduleId Course module ID.
* @param {string} [siteId] Site ID. If not defined, current site.
*/
updateExtraBadge(data: CoreCourseModuleHandlerData, courseId: number, moduleId: number, siteId?: string): void {
siteId = siteId || this.sitesProvider.getCurrentSiteId();
if (!siteId) {
return;
}
data.extraBadge = this.translate.instant('core.loading');
data.extraBadgeColor = 'light';
this.forumProvider.invalidateForumData(courseId).finally(() => {
// Handle unread posts.
this.forumProvider.getForum(courseId, moduleId, siteId).then((forumData) => {
data.extraBadgeColor = '';
data.extraBadge = forumData.unreadpostscount ? this.translate.instant('addon.mod_forum.unreadpostsnumber',
{$a : forumData.unreadpostscount }) : '';
}).catch(() => {
data.extraBadgeColor = '';
data.extraBadge = '';
// Ignore errors.
});
});
}
} }

View File

@ -132,6 +132,24 @@ export class AddonModForumPrefetchHandler extends CoreCourseActivityPrefetchHand
return this.forumProvider.invalidateContent(moduleId, courseId); return this.forumProvider.invalidateContent(moduleId, courseId);
} }
/**
* Invalidate WS calls needed to determine module status (usually, to check if module is downloadable).
* It doesn't need to invalidate check updates. It should NOT invalidate files nor all the prefetched data.
*
* @param {any} module Module.
* @param {number} courseId Course ID the module belongs to.
* @return {Promise<any>} Promise resolved when invalidated.
*/
invalidateModule(module: any, courseId: number): Promise<any> {
// Invalidate forum data to recalculate unread message count badge.
const promises = [];
promises.push(this.forumProvider.invalidateForumData(courseId));
promises.push(this.courseProvider.invalidateModule(module.id));
return Promise.all(promises);
}
/** /**
* Prefetch a module. * Prefetch a module.
* *

View File

@ -1,6 +1,6 @@
<ion-row *ngIf="actions && actions.length > 0"> <ion-row *ngIf="actions && actions.length > 0" justify-content-around>
<ion-col *ngFor="let action of actions"> <ion-col *ngFor="let action of actions">
<button ion-button icon-left clear small (click)="action.action()"> <button ion-button icon-left clear small block (click)="action.action()">
<ion-icon name="{{action.icon}}"></ion-icon> <ion-icon name="{{action.icon}}"></ion-icon>
{{ action.message | translate }} {{ action.message | translate }}
</button> </button>

View File

@ -31,7 +31,9 @@
</div> </div>
</div> </div>
<div *ngIf="module.visible === 0 || module.availabilityinfo || module.handlerData.extraBadge"> <div *ngIf="module.visible === 0 || module.availabilityinfo || module.handlerData.extraBadge">
<ion-badge item-end *ngIf="module.handlerData.extraBadge"><core-format-text [text]="module.handlerData.extraBadge"></core-format-text></ion-badge> <ion-badge item-end *ngIf="module.handlerData.extraBadge" [color]="module.handlerData.extraBadgeColor">
<core-format-text [text]="module.handlerData.extraBadge"></core-format-text>
</ion-badge>
<ion-badge item-end *ngIf="module.visible === 0">{{ 'core.course.hiddenfromstudents' | translate }}</ion-badge> <ion-badge item-end *ngIf="module.visible === 0">{{ 'core.course.hiddenfromstudents' | translate }}</ion-badge>
<ion-badge item-end *ngIf="module.availabilityinfo"><core-format-text [text]="module.availabilityinfo"></core-format-text></ion-badge> <ion-badge item-end *ngIf="module.availabilityinfo"><core-format-text [text]="module.availabilityinfo"></core-format-text></ion-badge>
</div> </div>

View File

@ -173,6 +173,7 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy {
*/ */
ngOnDestroy(): void { ngOnDestroy(): void {
this.statusObserver && this.statusObserver.off(); this.statusObserver && this.statusObserver.off();
this.module && this.module.handlerData && this.module.handlerData.onDestroy && this.module.handlerData.onDestroy();
this.isDestroyed = true; this.isDestroyed = true;
} }
} }

View File

@ -91,6 +91,12 @@ export interface CoreCourseModuleHandlerData {
*/ */
extraBadge?: string; extraBadge?: string;
/**
* The color of the extra badge. Default: primary.
* @type {string}
*/
extraBadgeColor?: string;
/** /**
* Whether to display a button to download/refresh the module if it's downloadable. * Whether to display a button to download/refresh the module if it's downloadable.
* If it's set to true, the app will show a download/refresh button when needed and will handle the download of the * If it's set to true, the app will show a download/refresh button when needed and will handle the download of the
@ -128,6 +134,11 @@ export interface CoreCourseModuleHandlerData {
* @param {string} status Module status. * @param {string} status Module status.
*/ */
updateStatus?(status: string): void; updateStatus?(status: string): void;
/**
* On Destroy function in case it's needed.
*/
onDestroy?(): void;
} }
/** /**