MOBILE-2486 glossary: Ratings
parent
8fe3e09e9b
commit
af6694c915
|
@ -294,7 +294,7 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider {
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
results.forEach((result) => {
|
results.forEach((result) => {
|
||||||
if (result.updated) {
|
if (result.updated.length) {
|
||||||
updated = true;
|
updated = true;
|
||||||
|
|
||||||
// Invalidate discussions of updated ratings.
|
// Invalidate discussions of updated ratings.
|
||||||
|
|
|
@ -25,7 +25,7 @@
|
||||||
<core-course-module-description [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
|
<core-course-module-description [description]="description" [component]="component" [componentId]="componentId"></core-course-module-description>
|
||||||
|
|
||||||
<!-- Glossary entries found to be synchronized -->
|
<!-- Glossary entries found to be synchronized -->
|
||||||
<ion-card class="core-warning-card" icon-start *ngIf="hasOffline">
|
<ion-card class="core-warning-card" icon-start *ngIf="hasOffline || hasOfflineRatings">
|
||||||
<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>
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@ import { Component, Injector, ViewChild } from '@angular/core';
|
||||||
import { Content, PopoverController } from 'ionic-angular';
|
import { Content, PopoverController } from 'ionic-angular';
|
||||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||||
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
import { CoreCourseModuleMainActivityComponent } from '@core/course/classes/main-activity-component';
|
||||||
|
import { CoreRatingProvider } from '@core/rating/providers/rating';
|
||||||
|
import { CoreRatingOfflineProvider } from '@core/rating/providers/offline';
|
||||||
|
import { CoreRatingSyncProvider } from '@core/rating/providers/sync';
|
||||||
import { AddonModGlossaryProvider } from '../../providers/glossary';
|
import { AddonModGlossaryProvider } from '../../providers/glossary';
|
||||||
import { AddonModGlossaryOfflineProvider } from '../../providers/offline';
|
import { AddonModGlossaryOfflineProvider } from '../../providers/offline';
|
||||||
import { AddonModGlossarySyncProvider } from '../../providers/sync';
|
import { AddonModGlossarySyncProvider } from '../../providers/sync';
|
||||||
|
@ -57,11 +60,16 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
protected getDivider: (entry: any) => string;
|
protected getDivider: (entry: any) => string;
|
||||||
protected addEntryObserver: any;
|
protected addEntryObserver: any;
|
||||||
|
|
||||||
|
hasOfflineRatings: boolean;
|
||||||
|
protected ratingOfflineObserver: any;
|
||||||
|
protected ratingSyncObserver: any;
|
||||||
|
|
||||||
constructor(injector: Injector,
|
constructor(injector: Injector,
|
||||||
private popoverCtrl: PopoverController,
|
private popoverCtrl: PopoverController,
|
||||||
private glossaryProvider: AddonModGlossaryProvider,
|
private glossaryProvider: AddonModGlossaryProvider,
|
||||||
private glossaryOffline: AddonModGlossaryOfflineProvider,
|
private glossaryOffline: AddonModGlossaryOfflineProvider,
|
||||||
private glossarySync: AddonModGlossarySyncProvider) {
|
private glossarySync: AddonModGlossarySyncProvider,
|
||||||
|
private ratingOffline: CoreRatingOfflineProvider) {
|
||||||
super(injector);
|
super(injector);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,6 +82,20 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
// When an entry is added, we reload the data.
|
// When an entry is added, we reload the data.
|
||||||
this.addEntryObserver = this.eventsProvider.on(AddonModGlossaryProvider.ADD_ENTRY_EVENT, this.eventReceived.bind(this));
|
this.addEntryObserver = this.eventsProvider.on(AddonModGlossaryProvider.ADD_ENTRY_EVENT, this.eventReceived.bind(this));
|
||||||
|
|
||||||
|
// Listen for offline ratings saved and synced.
|
||||||
|
this.ratingOfflineObserver = this.eventsProvider.on(CoreRatingProvider.RATING_SAVED_EVENT, (data) => {
|
||||||
|
if (this.glossary && data.component == 'mod_glossary' && data.ratingArea == 'entry' && data.contextLevel == 'module'
|
||||||
|
&& data.instanceId == this.glossary.coursemodule) {
|
||||||
|
this.hasOfflineRatings = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.ratingSyncObserver = this.eventsProvider.on(CoreRatingSyncProvider.SYNCED_EVENT, (data) => {
|
||||||
|
if (this.glossary && data.component == 'mod_glossary' && data.ratingArea == 'entry' && data.contextLevel == 'module'
|
||||||
|
&& data.instanceId == this.glossary.coursemodule) {
|
||||||
|
this.hasOfflineRatings = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.loadContent(false, true).then(() => {
|
this.loadContent(false, true).then(() => {
|
||||||
if (!this.glossary) {
|
if (!this.glossary) {
|
||||||
return;
|
return;
|
||||||
|
@ -118,15 +140,23 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
return this.syncActivity(showErrors);
|
return this.syncActivity(showErrors);
|
||||||
}
|
}
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
return this.fetchEntries().then(() => {
|
promises.push(this.fetchEntries().then(() => {
|
||||||
// Check if there are responses stored in offline.
|
// Check if there are responses stored in offline.
|
||||||
return this.glossaryOffline.getGlossaryNewEntries(this.glossary.id).then((offlineEntries) => {
|
return this.glossaryOffline.getGlossaryNewEntries(this.glossary.id).then((offlineEntries) => {
|
||||||
offlineEntries.sort((a, b) => a.concept.localeCompare(b.fullname));
|
offlineEntries.sort((a, b) => a.concept.localeCompare(b.fullname));
|
||||||
this.hasOffline = !!offlineEntries.length;
|
this.hasOffline = !!offlineEntries.length;
|
||||||
this.offlineEntries = offlineEntries || [];
|
this.offlineEntries = offlineEntries || [];
|
||||||
});
|
});
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
promises.push(this.ratingOffline.hasRatings('mod_glossary', 'entry', 'module', this.glossary.coursemodule)
|
||||||
|
.then((hasRatings) => {
|
||||||
|
this.hasOfflineRatings = hasRatings;
|
||||||
|
}));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
// All data obtained, now fill the context menu.
|
// All data obtained, now fill the context menu.
|
||||||
this.fillContextMenu(refresh);
|
this.fillContextMenu(refresh);
|
||||||
|
@ -189,7 +219,17 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
* @return {Promise<any>} Promise resolved when done.
|
* @return {Promise<any>} Promise resolved when done.
|
||||||
*/
|
*/
|
||||||
protected sync(): Promise<boolean> {
|
protected sync(): Promise<boolean> {
|
||||||
return this.glossarySync.syncGlossaryEntries(this.glossary.id);
|
const promises = [
|
||||||
|
this.glossarySync.syncGlossaryEntries(this.glossary.id),
|
||||||
|
this.glossarySync.syncRatings(this.glossary.coursemodule)
|
||||||
|
];
|
||||||
|
|
||||||
|
return Promise.all(promises).then((results) => {
|
||||||
|
return results.reduce((a, b) => ({
|
||||||
|
updated: a.updated || b.updated,
|
||||||
|
warnings: (a.warnings || []).concat(b.warnings || []),
|
||||||
|
}), {updated: false});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -345,7 +385,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
openEntry(entryId: number): void {
|
openEntry(entryId: number): void {
|
||||||
const params = {
|
const params = {
|
||||||
courseId: this.courseId,
|
courseId: this.courseId,
|
||||||
entryId: entryId,
|
entryId: entryId
|
||||||
};
|
};
|
||||||
this.splitviewCtrl.push('AddonModGlossaryEntryPage', params);
|
this.splitviewCtrl.push('AddonModGlossaryEntryPage', params);
|
||||||
this.selectedEntry = entryId;
|
this.selectedEntry = entryId;
|
||||||
|
@ -400,5 +440,7 @@ export class AddonModGlossaryIndexComponent extends CoreCourseModuleMainActivity
|
||||||
super.ngOnDestroy();
|
super.ngOnDestroy();
|
||||||
|
|
||||||
this.addEntryObserver && this.addEntryObserver.off();
|
this.addEntryObserver && this.addEntryObserver.off();
|
||||||
|
this.ratingOfflineObserver && this.ratingOfflineObserver.off();
|
||||||
|
this.ratingSyncObserver && this.ratingSyncObserver.off();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
<ion-item text-wrap *ngIf="entry.approved != 1">
|
<ion-item text-wrap *ngIf="entry.approved != 1">
|
||||||
<p><em>{{ 'addon.mod_glossary.entrypendingapproval' | translate }}</em></p>
|
<p><em>{{ 'addon.mod_glossary.entrypendingapproval' | translate }}</em></p>
|
||||||
</ion-item>
|
</ion-item>
|
||||||
|
<core-rating-rate *ngIf="glossary && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="glossary.coursemodule" [itemId]="entry.id" [itemSetId]="0" [courseId]="glossary.courseid" [aggregateMethod]="glossary.assessed" [scaleId]="glossary.scale" [userId]="entry.userid" (onUpdate)="ratingUpdated()"></core-rating-rate>
|
||||||
|
<core-rating-aggregate *ngIf="glossary && ratingInfo" [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="glossary.coursemodule" [itemId]="entry.id" [courseId]="glossary.courseid" [aggregateMethod]="glossary.assessed" [scaleId]="glossary.scale"></core-rating-aggregate>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
<ion-card *ngIf="!entry">
|
<ion-card *ngIf="!entry">
|
||||||
|
|
|
@ -18,6 +18,7 @@ import { TranslateModule } from '@ngx-translate/core';
|
||||||
import { CoreComponentsModule } from '@components/components.module';
|
import { CoreComponentsModule } from '@components/components.module';
|
||||||
import { CoreDirectivesModule } from '@directives/directives.module';
|
import { CoreDirectivesModule } from '@directives/directives.module';
|
||||||
import { CorePipesModule } from '@pipes/pipes.module';
|
import { CorePipesModule } from '@pipes/pipes.module';
|
||||||
|
import { CoreRatingComponentsModule } from '@core/rating/components/components.module';
|
||||||
import { AddonModGlossaryEntryPage } from './entry';
|
import { AddonModGlossaryEntryPage } from './entry';
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -29,7 +30,8 @@ import { AddonModGlossaryEntryPage } from './entry';
|
||||||
CoreDirectivesModule,
|
CoreDirectivesModule,
|
||||||
CorePipesModule,
|
CorePipesModule,
|
||||||
IonicPageModule.forChild(AddonModGlossaryEntryPage),
|
IonicPageModule.forChild(AddonModGlossaryEntryPage),
|
||||||
TranslateModule.forChild()
|
TranslateModule.forChild(),
|
||||||
|
CoreRatingComponentsModule
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
export class AddonModForumDiscussionPageModule {}
|
export class AddonModForumDiscussionPageModule {}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import { Component } from '@angular/core';
|
import { Component } from '@angular/core';
|
||||||
import { IonicPage, NavParams } from 'ionic-angular';
|
import { IonicPage, NavParams } from 'ionic-angular';
|
||||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||||
|
import { CoreRatingInfo } from '@core/rating/providers/rating';
|
||||||
import { AddonModGlossaryProvider } from '../../providers/glossary';
|
import { AddonModGlossaryProvider } from '../../providers/glossary';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,9 +30,11 @@ export class AddonModGlossaryEntryPage {
|
||||||
component = AddonModGlossaryProvider.COMPONENT;
|
component = AddonModGlossaryProvider.COMPONENT;
|
||||||
componentId: number;
|
componentId: number;
|
||||||
entry: any;
|
entry: any;
|
||||||
|
glossary: any;
|
||||||
loaded = false;
|
loaded = false;
|
||||||
showAuthor = false;
|
showAuthor = false;
|
||||||
showDate = false;
|
showDate = false;
|
||||||
|
ratingInfo: CoreRatingInfo;
|
||||||
|
|
||||||
protected courseId: number;
|
protected courseId: number;
|
||||||
protected entryId: number;
|
protected entryId: number;
|
||||||
|
@ -80,11 +83,13 @@ export class AddonModGlossaryEntryPage {
|
||||||
*/
|
*/
|
||||||
protected fetchEntry(refresh?: boolean): Promise<any> {
|
protected fetchEntry(refresh?: boolean): Promise<any> {
|
||||||
return this.glossaryProvider.getEntry(this.entryId).then((result) => {
|
return this.glossaryProvider.getEntry(this.entryId).then((result) => {
|
||||||
this.entry = result;
|
this.entry = result.entry;
|
||||||
|
this.ratingInfo = result.ratinginfo;
|
||||||
|
|
||||||
if (!refresh) {
|
if (!refresh) {
|
||||||
// Load the glossary.
|
// Load the glossary.
|
||||||
return this.glossaryProvider.getGlossaryById(this.courseId, this.entry.glossaryid).then((glossary) => {
|
return this.glossaryProvider.getGlossaryById(this.courseId, this.entry.glossaryid).then((glossary) => {
|
||||||
|
this.glossary = glossary;
|
||||||
this.componentId = glossary.coursemodule;
|
this.componentId = glossary.coursemodule;
|
||||||
|
|
||||||
switch (glossary.displayformat) {
|
switch (glossary.displayformat) {
|
||||||
|
@ -109,4 +114,11 @@ export class AddonModGlossaryEntryPage {
|
||||||
return Promise.reject(null);
|
return Promise.reject(null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function called when rating is updated online.
|
||||||
|
*/
|
||||||
|
ratingUpdated(): void {
|
||||||
|
this.glossaryProvider.invalidateEntry(this.entryId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,8 +61,8 @@ export class AddonModGlossaryEntryLinkHandler extends CoreContentLinksHandlerBas
|
||||||
this.domUtils.showErrorModalDefault(error, 'addon.mod_glossary.errorloadingentry', true);
|
this.domUtils.showErrorModalDefault(error, 'addon.mod_glossary.errorloadingentry', true);
|
||||||
|
|
||||||
return Promise.reject(null);
|
return Promise.reject(null);
|
||||||
}).then((entry) => {
|
}).then((response) => {
|
||||||
return this.courseHelper.getModuleCourseIdByInstance(entry.glossaryid, 'glossary', siteId);
|
return this.courseHelper.getModuleCourseIdByInstance(response.entry.glossaryid, 'glossary', siteId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@ import { CoreSitesProvider } from '@providers/sites';
|
||||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
import { CoreCourseLogHelperProvider } from '@core/course/providers/log-helper';
|
||||||
|
import { CoreRatingInfo } from '@core/rating/providers/rating';
|
||||||
import { AddonModGlossaryOfflineProvider } from './offline';
|
import { AddonModGlossaryOfflineProvider } from './offline';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -489,7 +490,7 @@ export class AddonModGlossaryProvider {
|
||||||
* @param {string} [siteId] Site ID. If not defined, current site.
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
* @return {Promise<any>} Promise resolved with the entry.
|
* @return {Promise<any>} Promise resolved with the entry.
|
||||||
*/
|
*/
|
||||||
getEntry(entryId: number, siteId?: string): Promise<any> {
|
getEntry(entryId: number, siteId?: string): Promise<{entry: any, ratinginfo: CoreRatingInfo}> {
|
||||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||||
const params = {
|
const params = {
|
||||||
id: entryId
|
id: entryId
|
||||||
|
@ -500,7 +501,7 @@ export class AddonModGlossaryProvider {
|
||||||
|
|
||||||
return site.read('mod_glossary_get_entry_by_id', params, preSets).then((response) => {
|
return site.read('mod_glossary_get_entry_by_id', params, preSets).then((response) => {
|
||||||
if (response && response.entry) {
|
if (response && response.entry) {
|
||||||
return response.entry;
|
return response;
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(null);
|
return Promise.reject(null);
|
||||||
}
|
}
|
||||||
|
@ -615,31 +616,35 @@ export class AddonModGlossaryProvider {
|
||||||
*
|
*
|
||||||
* @param {any} glossary The glossary object.
|
* @param {any} glossary The glossary object.
|
||||||
* @param {boolean} [onlyEntriesList] If true, entries won't be invalidated.
|
* @param {boolean} [onlyEntriesList] If true, entries won't be invalidated.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
* @return {Promise<any>} Promise resolved when data is invalidated.
|
* @return {Promise<any>} Promise resolved when data is invalidated.
|
||||||
*/
|
*/
|
||||||
invalidateGlossaryEntries(glossary: any, onlyEntriesList?: boolean): Promise<any> {
|
invalidateGlossaryEntries(glossary: any, onlyEntriesList?: boolean, siteId?: string): Promise<any> {
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
const promises = [];
|
const promises = [];
|
||||||
|
|
||||||
if (!onlyEntriesList) {
|
if (!onlyEntriesList) {
|
||||||
promises.push(this.fetchAllEntries(this.getEntriesByLetter, [glossary.id, 'ALL'], true).then((entries) => {
|
promises.push(this.fetchAllEntries(this.getEntriesByLetter, [glossary.id, 'ALL'], true, siteId).then((entries) => {
|
||||||
return this.invalidateEntries(entries);
|
return this.invalidateEntries(entries, siteId);
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
glossary.browsemodes.forEach((mode) => {
|
glossary.browsemodes.forEach((mode) => {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case 'letter':
|
case 'letter':
|
||||||
promises.push(this.invalidateEntriesByLetter(glossary.id, 'ALL'));
|
promises.push(this.invalidateEntriesByLetter(glossary.id, 'ALL', siteId));
|
||||||
break;
|
break;
|
||||||
case 'cat':
|
case 'cat':
|
||||||
promises.push(this.invalidateEntriesByCategory(glossary.id, AddonModGlossaryProvider.SHOW_ALL_CATERGORIES));
|
promises.push(this.invalidateEntriesByCategory(glossary.id, AddonModGlossaryProvider.SHOW_ALL_CATERGORIES,
|
||||||
|
siteId));
|
||||||
break;
|
break;
|
||||||
case 'date':
|
case 'date':
|
||||||
promises.push(this.invalidateEntriesByDate(glossary.id, 'CREATION', 'DESC'));
|
promises.push(this.invalidateEntriesByDate(glossary.id, 'CREATION', 'DESC', siteId));
|
||||||
promises.push(this.invalidateEntriesByDate(glossary.id, 'UPDATE', 'DESC'));
|
promises.push(this.invalidateEntriesByDate(glossary.id, 'UPDATE', 'DESC', siteId));
|
||||||
break;
|
break;
|
||||||
case 'author':
|
case 'author':
|
||||||
promises.push(this.invalidateEntriesByAuthor(glossary.id, 'ALL', 'LASTNAME', 'ASC'));
|
promises.push(this.invalidateEntriesByAuthor(glossary.id, 'ALL', 'LASTNAME', 'ASC', siteId));
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ import { CoreCourseProvider } from '@core/course/providers/course';
|
||||||
import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler';
|
import { CoreCourseActivityPrefetchHandlerBase } from '@core/course/classes/activity-prefetch-handler';
|
||||||
import { CoreUserProvider } from '@core/user/providers/user';
|
import { CoreUserProvider } from '@core/user/providers/user';
|
||||||
import { AddonModGlossaryProvider } from './glossary';
|
import { AddonModGlossaryProvider } from './glossary';
|
||||||
|
import { CoreRatingProvider } from '@core/rating/providers/rating';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handler to prefetch forums.
|
* Handler to prefetch forums.
|
||||||
|
@ -42,6 +43,7 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
sitesProvider: CoreSitesProvider,
|
sitesProvider: CoreSitesProvider,
|
||||||
domUtils: CoreDomUtilsProvider,
|
domUtils: CoreDomUtilsProvider,
|
||||||
private userProvider: CoreUserProvider,
|
private userProvider: CoreUserProvider,
|
||||||
|
private ratingProvider: CoreRatingProvider,
|
||||||
private glossaryProvider: AddonModGlossaryProvider) {
|
private glossaryProvider: AddonModGlossaryProvider) {
|
||||||
|
|
||||||
super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils);
|
super(translate, appProvider, utils, courseProvider, filepoolProvider, sitesProvider, domUtils);
|
||||||
|
@ -164,7 +166,11 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
// Fetch user avatars.
|
// Fetch user avatars.
|
||||||
entries.forEach((entry) => {
|
entries.forEach((entry) => {
|
||||||
// Fetch individual entries.
|
// Fetch individual entries.
|
||||||
promises.push(this.glossaryProvider.getEntry(entry.id, siteId));
|
promises.push(this.glossaryProvider.getEntry(entry.id, siteId).then((entry) => {
|
||||||
|
// Fetch individual ratings.
|
||||||
|
return this.ratingProvider.prefetchRatings('module', module.id, glossary.scale, courseId, entry.ratinginfo,
|
||||||
|
siteId);
|
||||||
|
}));
|
||||||
|
|
||||||
userIds.push(entry.userid);
|
userIds.push(entry.userid);
|
||||||
});
|
});
|
||||||
|
@ -177,6 +183,8 @@ export class AddonModGlossaryPrefetchHandler extends CoreCourseActivityPrefetchH
|
||||||
|
|
||||||
return Promise.all(promises);
|
return Promise.all(promises);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,7 @@ import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||||
import { AddonModGlossaryProvider } from './glossary';
|
import { AddonModGlossaryProvider } from './glossary';
|
||||||
import { AddonModGlossaryHelperProvider } from './helper';
|
import { AddonModGlossaryHelperProvider } from './helper';
|
||||||
import { AddonModGlossaryOfflineProvider } from './offline';
|
import { AddonModGlossaryOfflineProvider } from './offline';
|
||||||
|
import { CoreRatingSyncProvider } from '@core/rating/providers/sync';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Service to sync glossaries.
|
* Service to sync glossaries.
|
||||||
|
@ -54,7 +55,8 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider {
|
||||||
private glossaryProvider: AddonModGlossaryProvider,
|
private glossaryProvider: AddonModGlossaryProvider,
|
||||||
private glossaryHelper: AddonModGlossaryHelperProvider,
|
private glossaryHelper: AddonModGlossaryHelperProvider,
|
||||||
private glossaryOffline: AddonModGlossaryOfflineProvider,
|
private glossaryOffline: AddonModGlossaryOfflineProvider,
|
||||||
private logHelper: CoreCourseLogHelperProvider) {
|
private logHelper: CoreCourseLogHelperProvider,
|
||||||
|
private ratingSync: CoreRatingSyncProvider) {
|
||||||
|
|
||||||
super('AddonModGlossarySyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
|
super('AddonModGlossarySyncProvider', loggerProvider, sitesProvider, appProvider, syncProvider, textUtils, translate,
|
||||||
timeUtils);
|
timeUtils);
|
||||||
|
@ -79,8 +81,12 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider {
|
||||||
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
protected syncAllGlossariesFunc(siteId?: string): Promise<any> {
|
protected syncAllGlossariesFunc(siteId?: string): Promise<any> {
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
// Sync all new entries
|
// Sync all new entries
|
||||||
return this.glossaryOffline.getAllNewEntries(siteId).then((entries) => {
|
promises.push(this.glossaryOffline.getAllNewEntries(siteId).then((entries) => {
|
||||||
const promises = {};
|
const promises = {};
|
||||||
|
|
||||||
// Do not sync same glossary twice.
|
// Do not sync same glossary twice.
|
||||||
|
@ -106,7 +112,11 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider {
|
||||||
|
|
||||||
// Promises will be an object so, convert to an array first;
|
// Promises will be an object so, convert to an array first;
|
||||||
return Promise.all(this.utils.objectToArray(promises));
|
return Promise.all(this.utils.objectToArray(promises));
|
||||||
});
|
}));
|
||||||
|
|
||||||
|
promises.push(this.syncRatings(undefined, siteId));
|
||||||
|
|
||||||
|
return Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -241,6 +251,50 @@ export class AddonModGlossarySyncProvider extends CoreSyncBaseProvider {
|
||||||
return this.addOngoingSync(syncId, syncPromise, siteId);
|
return this.addOngoingSync(syncId, syncPromise, siteId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Synchronize offline ratings.
|
||||||
|
*
|
||||||
|
* @param {number} [cmId] Course module to be synced. If not defined, sync all glossaries.
|
||||||
|
* @param {string} [siteId] Site ID. If not defined, current site.
|
||||||
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected otherwise.
|
||||||
|
*/
|
||||||
|
syncRatings(cmId?: number, siteId?: string): Promise<any> {
|
||||||
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
return this.ratingSync.syncRatings('mod_glossary', 'entry', 'module', cmId, 0, siteId).then((results) => {
|
||||||
|
let updated = false;
|
||||||
|
const warnings = [];
|
||||||
|
const promises = [];
|
||||||
|
|
||||||
|
results.forEach((result) => {
|
||||||
|
if (result.updated.length) {
|
||||||
|
updated = true;
|
||||||
|
|
||||||
|
// Invalidate entry of updated ratings.
|
||||||
|
result.updated.forEach((itemId) => {
|
||||||
|
promises.push(this.glossaryProvider.invalidateEntry(itemId, siteId));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (result.warnings.length) {
|
||||||
|
promises.push(this.glossaryProvider.getGlossary(result.itemSet.courseId, result.itemSet.instanceId, siteId)
|
||||||
|
.then((glossary) => {
|
||||||
|
result.warnings.forEach((warning) => {
|
||||||
|
warnings.push(this.translate.instant('core.warningofflinedatadeleted', {
|
||||||
|
component: this.componentTranslate,
|
||||||
|
name: glossary.name,
|
||||||
|
error: warning
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return this.utils.allPromises(promises).then(() => {
|
||||||
|
return { updated, warnings };
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete a new entry.
|
* Delete a new entry.
|
||||||
*
|
*
|
||||||
|
|
|
@ -63,7 +63,7 @@ export class CoreRatingSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected if sync fails.
|
||||||
*/
|
*/
|
||||||
syncRatings(component: string, ratingArea: string, contextLevel?: string, instanceId?: number, itemSetId?: number,
|
syncRatings(component: string, ratingArea: string, contextLevel?: string, instanceId?: number, itemSetId?: number,
|
||||||
siteId?: string): Promise<{itemSet: CoreRatingItemSet, updated: boolean, warnings: string[]}[]> {
|
siteId?: string): Promise<{itemSet: CoreRatingItemSet, updated: number[], warnings: string[]}[]> {
|
||||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
return this.ratingOffline.getItemSets(component, ratingArea, contextLevel, instanceId, itemSetId, siteId)
|
return this.ratingOffline.getItemSets(component, ratingArea, contextLevel, instanceId, itemSetId, siteId)
|
||||||
|
@ -102,7 +102,7 @@ export class CoreRatingSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @return {Promise<any>} Promise resolved when ratings are synced or if it doesn't need to be synced.
|
* @return {Promise<any>} Promise resolved when ratings are synced or if it doesn't need to be synced.
|
||||||
*/
|
*/
|
||||||
protected syncItemSetIfNeeded(component: string, ratingArea: string, contextLevel: string, instanceId: number,
|
protected syncItemSetIfNeeded(component: string, ratingArea: string, contextLevel: string, instanceId: number,
|
||||||
itemSetId: number, siteId?: string): Promise<{updated: boolean, warnings: string[]}> {
|
itemSetId: number, siteId?: string): Promise<{updated: number[], warnings: string[]}> {
|
||||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
const syncId = this.getItemSetSyncId(component, ratingArea, contextLevel, instanceId, itemSetId);
|
const syncId = this.getItemSetSyncId(component, ratingArea, contextLevel, instanceId, itemSetId);
|
||||||
|
@ -126,7 +126,7 @@ export class CoreRatingSyncProvider extends CoreSyncBaseProvider {
|
||||||
* @return {Promise<any>} Promise resolved if sync is successful, rejected otherwise.
|
* @return {Promise<any>} Promise resolved if sync is successful, rejected otherwise.
|
||||||
*/
|
*/
|
||||||
protected syncItemSet(component: string, ratingArea: string, contextLevel: string, instanceId: number, itemSetId: number,
|
protected syncItemSet(component: string, ratingArea: string, contextLevel: string, instanceId: number, itemSetId: number,
|
||||||
siteId?: string): Promise<{updated: boolean, warnings: string[]}> {
|
siteId?: string): Promise<{updated: number[], warnings: string[]}> {
|
||||||
|
|
||||||
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
siteId = siteId || this.sitesProvider.getCurrentSiteId();
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ export class CoreRatingSyncProvider extends CoreSyncBaseProvider {
|
||||||
this.logger.debug(`Try to sync ratings of component '${component}' rating area '${ratingArea}'` +
|
this.logger.debug(`Try to sync ratings of component '${component}' rating area '${ratingArea}'` +
|
||||||
` context level '${contextLevel}' instance ${instanceId} item set ${itemSetId}`);
|
` context level '${contextLevel}' instance ${instanceId} item set ${itemSetId}`);
|
||||||
|
|
||||||
let updated = false;
|
const updated = [];
|
||||||
const warnings = [];
|
const warnings = [];
|
||||||
|
|
||||||
return this.ratingOffline.getRatings(component, ratingArea, contextLevel, instanceId, itemSetId, siteId).then((ratings) => {
|
return this.ratingOffline.getRatings(component, ratingArea, contextLevel, instanceId, itemSetId, siteId).then((ratings) => {
|
||||||
|
@ -162,7 +162,7 @@ export class CoreRatingSyncProvider extends CoreSyncBaseProvider {
|
||||||
return Promise.reject(error);
|
return Promise.reject(error);
|
||||||
}
|
}
|
||||||
}).then(() => {
|
}).then(() => {
|
||||||
updated = true;
|
updated.push(rating.itemid);
|
||||||
|
|
||||||
return this.ratingOffline.deleteRating(component, ratingArea, rating.contextlevel, rating.instanceid,
|
return this.ratingOffline.deleteRating(component, ratingArea, rating.contextlevel, rating.instanceid,
|
||||||
rating.itemid, siteId).finally(() => {
|
rating.itemid, siteId).finally(() => {
|
||||||
|
|
Loading…
Reference in New Issue