forked from EVOgeek/Vmeda.Online
		
	MOBILE-3663 forum: Add ratings to forum
This commit is contained in:
		
							parent
							
								
									44a03b61e7
								
							
						
					
					
						commit
						44e3c42d76
					
				| @ -18,6 +18,7 @@ import { CoreCourseComponentsModule } from '@features/course/components/componen | ||||
| import { CoreEditorComponentsModule } from '@features/editor/components/components.module'; | ||||
| import { CoreSharedModule } from '@/core/shared.module'; | ||||
| import { CoreTagComponentsModule } from '@features/tag/components/components.module'; | ||||
| import { CoreRatingComponentsModule } from '@features/rating/components/components.module'; | ||||
| 
 | ||||
| import { AddonModForumDiscussionOptionsMenuComponent } from './discussion-options-menu/discussion-options-menu'; | ||||
| import { AddonModForumEditPostComponent } from './edit-post/edit-post'; | ||||
| @ -40,6 +41,7 @@ import { AddonModForumSortOrderSelectorComponent } from './sort-order-selector/s | ||||
|         CoreCourseComponentsModule, | ||||
|         CoreTagComponentsModule, | ||||
|         CoreEditorComponentsModule, | ||||
|         CoreRatingComponentsModule, | ||||
|     ], | ||||
|     exports: [ | ||||
|         AddonModForumIndexComponent, | ||||
|  | ||||
| @ -50,6 +50,10 @@ import { CoreScreen } from '@services/screen'; | ||||
| import { CoreArray } from '@singletons/array'; | ||||
| import { AddonModForumPrefetchHandler } from '../../services/handlers/prefetch'; | ||||
| import { AddonModForumModuleHandlerService } from '../../services/handlers/module'; | ||||
| import { CoreRatingProvider } from '@features/rating/services/rating'; | ||||
| import { CoreRatingSyncProvider } from '@features/rating/services/rating-sync'; | ||||
| import { CoreRatingOffline } from '@features/rating/services/rating-offline'; | ||||
| import { ContextLevel } from '@/core/constants'; | ||||
| 
 | ||||
| /** | ||||
|  * Component that displays a forum entry page. | ||||
| @ -88,9 +92,9 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|     protected viewDiscObserver?: CoreEventObserver; | ||||
|     protected changeDiscObserver?: CoreEventObserver; | ||||
| 
 | ||||
|     hasOfflineRatings?: boolean; | ||||
|     protected ratingOfflineObserver: any; | ||||
|     protected ratingSyncObserver: any; | ||||
|     hasOfflineRatings = false; | ||||
|     protected ratingOfflineObserver?: CoreEventObserver; | ||||
|     protected ratingSyncObserver?: CoreEventObserver; | ||||
| 
 | ||||
|     constructor( | ||||
|         route: ActivatedRoute, | ||||
| @ -166,7 +170,21 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         // @todo Listen for offline ratings saved and synced.
 | ||||
|         // Listen for offline ratings saved and synced.
 | ||||
|         this.ratingOfflineObserver = CoreEvents.on(CoreRatingProvider.RATING_SAVED_EVENT, (data) => { | ||||
|             if (this.forum && data.component == 'mod_forum' && data.ratingArea == 'post' && | ||||
|                     data.contextLevel == ContextLevel.MODULE && data.instanceId == this.forum.cmid) { | ||||
|                 this.hasOfflineRatings = true; | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         this.ratingSyncObserver = CoreEvents.on(CoreRatingSyncProvider.SYNCED_EVENT, async (data) => { | ||||
|             if (this.forum && data.component == 'mod_forum' && data.ratingArea == 'post' && | ||||
|                     data.contextLevel == ContextLevel.MODULE && data.instanceId == this.forum.cmid) { | ||||
|                 this.hasOfflineRatings = | ||||
|                     await CoreRatingOffline.hasRatings('mod_forum', 'post', ContextLevel.MODULE, this.forum.cmid); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     async ngAfterViewInit(): Promise<void> { | ||||
| @ -224,7 +242,11 @@ export class AddonModForumIndexComponent extends CoreCourseModuleMainActivityCom | ||||
|             await Promise.all([ | ||||
|                 this.fetchOfflineDiscussions(), | ||||
|                 this.fetchDiscussions(refresh), | ||||
|                 // @todo fetch hasOfflineRatings.
 | ||||
|                 CoreRatingOffline.hasRatings('mod_forum', 'post', ContextLevel.MODULE, this.forum!.cmid).then((hasRatings) => { | ||||
|                     this.hasOfflineRatings = hasRatings; | ||||
| 
 | ||||
|                     return; | ||||
|                 }), | ||||
|             ]); | ||||
|         } catch (error) { | ||||
|             if (refresh) { | ||||
|  | ||||
| @ -75,8 +75,7 @@ | ||||
|                 <core-tag-list [tags]="post.tags"></core-tag-list> | ||||
|             </ion-label> | ||||
|         </ion-item> | ||||
|         <!-- @todo --> | ||||
|         <!-- <core-rating-rate *ngIf="forum && ratingInfo" | ||||
|         <core-rating-rate *ngIf="forum && ratingInfo" | ||||
|             [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" | ||||
|             [itemSetId]="discussionId" [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale" | ||||
|             [userId]="post.author.id" (onUpdate)="ratingUpdated()"> | ||||
| @ -84,7 +83,7 @@ | ||||
|         <core-rating-aggregate *ngIf="forum && ratingInfo" | ||||
|             [ratingInfo]="ratingInfo" contextLevel="module" [instanceId]="componentId" [itemId]="post.id" | ||||
|             [courseId]="courseId" [aggregateMethod]="forum.assessed" [scaleId]="forum.scale"> | ||||
|         </core-rating-aggregate> --> | ||||
|         </core-rating-aggregate> | ||||
| 
 | ||||
|         <ion-item *ngIf="post.id > 0 && post.capabilities.reply && !post.isprivatereply" | ||||
|             class="ion-no-padding ion-text-end addon-forum-reply-button"> | ||||
|  | ||||
| @ -52,6 +52,7 @@ import { AddonModForumOffline, AddonModForumReplyOptions } from '../../services/ | ||||
| import { CoreUtils } from '@services/utils/utils'; | ||||
| import { AddonModForumPostOptionsMenuComponent } from '../post-options-menu/post-options-menu'; | ||||
| import { AddonModForumEditPostComponent } from '../edit-post/edit-post'; | ||||
| import { CoreRatingInfo } from '@features/rating/services/rating'; | ||||
| 
 | ||||
| /** | ||||
|  * Components that shows a discussion post, its attachments and the action buttons allowed (reply, etc.). | ||||
| @ -75,7 +76,7 @@ export class AddonModForumPostComponent implements OnInit, OnDestroy, OnChanges | ||||
|     @Input() forum!: AddonModForumData; // The forum the post belongs to. Required for attachments and offline posts.
 | ||||
|     @Input() accessInfo!: AddonModForumAccessInformation; // Forum access information.
 | ||||
|     @Input() parentSubject?: string; // Subject of parent post.
 | ||||
|     @Input() ratingInfo?: any; // TODO CoreRatingInfo; // Rating info item.
 | ||||
|     @Input() ratingInfo?: CoreRatingInfo; // Rating info item.
 | ||||
|     @Input() leavingPage?: boolean; // Whether the page that contains this post is being left and will be destroyed.
 | ||||
|     @Input() highlight = false; | ||||
|     @Output() onPostChange: EventEmitter<void> = new EventEmitter<void>(); // Event emitted when a reply is posted or modified.
 | ||||
|  | ||||
| @ -12,9 +12,13 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { ContextLevel } from '@/core/constants'; | ||||
| import { Component, OnDestroy, ViewChild, OnInit, AfterViewInit, ElementRef, Optional } from '@angular/core'; | ||||
| import { CoreSplitViewComponent } from '@components/split-view/split-view'; | ||||
| import { CoreFileUploader } from '@features/fileuploader/services/fileuploader'; | ||||
| import { CoreRatingInfo, CoreRatingProvider } from '@features/rating/services/rating'; | ||||
| import { CoreRatingOffline } from '@features/rating/services/rating-offline'; | ||||
| import { CoreRatingSyncProvider } from '@features/rating/services/rating-sync'; | ||||
| import { CoreUser } from '@features/user/services/user'; | ||||
| import { CanLeave } from '@guards/can-leave'; | ||||
| import { IonContent } from '@ionic/angular'; | ||||
| @ -34,7 +38,6 @@ import { | ||||
|     AddonModForumDiscussion, | ||||
|     AddonModForumPost, | ||||
|     AddonModForumProvider, | ||||
|     AddonModForumRatingInfo, | ||||
| } from '../../services/forum'; | ||||
| import { AddonModForumHelper } from '../../services/helper'; | ||||
| import { AddonModForumOffline } from '../../services/offline'; | ||||
| @ -101,8 +104,8 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes | ||||
|     protected syncObserver?: CoreEventObserver; | ||||
|     protected syncManualObserver?: CoreEventObserver; | ||||
| 
 | ||||
|     ratingInfo?: AddonModForumRatingInfo; | ||||
|     hasOfflineRatings!: boolean; | ||||
|     ratingInfo?: CoreRatingInfo; | ||||
|     hasOfflineRatings = false; | ||||
|     protected ratingOfflineObserver?: CoreEventObserver; | ||||
|     protected ratingSyncObserver?: CoreEventObserver; | ||||
|     protected changeDiscObserver?: CoreEventObserver; | ||||
| @ -203,7 +206,20 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes | ||||
|             AddonModForum.invalidateDiscussionsList(this.forumId); | ||||
|         } | ||||
| 
 | ||||
|         // @todo Listen for offline ratings saved and synced.
 | ||||
|         // Listen for offline ratings saved and synced.
 | ||||
|         this.ratingOfflineObserver = CoreEvents.on(CoreRatingProvider.RATING_SAVED_EVENT, (data) => { | ||||
|             if (data.component == 'mod_forum' && data.ratingArea == 'post' && data.contextLevel == ContextLevel.MODULE && | ||||
|                     data.instanceId == this.cmId && data.itemSetId == this.discussionId) { | ||||
|                 this.hasOfflineRatings = true; | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         this.ratingSyncObserver = CoreEvents.on(CoreRatingSyncProvider.SYNCED_EVENT, async (data) => { | ||||
|             if (data.component == 'mod_forum' && data.ratingArea == 'post' && data.contextLevel == ContextLevel.MODULE && | ||||
|                     data.instanceId == this.cmId && data.itemSetId == this.discussionId) { | ||||
|                 this.hasOfflineRatings = false; | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         this.changeDiscObserver = CoreEvents.on(AddonModForumProvider.CHANGE_DISCUSSION_EVENT, data => { | ||||
|             if ((this.forumId && this.forumId === data.forumId) || data.cmId === this.cmId) { | ||||
| @ -345,7 +361,8 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes | ||||
| 
 | ||||
|             const response = await AddonModForum.getDiscussionPosts(this.discussionId, { cmId: this.cmId }); | ||||
|             const replies = await AddonModForumOffline.getDiscussionReplies(this.discussionId); | ||||
|             const ratingInfo = response.ratinginfo; | ||||
|             this.ratingInfo = response.ratinginfo; | ||||
| 
 | ||||
|             onlinePosts = response.posts; | ||||
|             this.courseId = response.courseid || this.courseId; | ||||
|             this.forumId = response.forumid || this.forumId; | ||||
| @ -462,7 +479,6 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes | ||||
|             } | ||||
| 
 | ||||
|             this.posts = posts; | ||||
|             this.ratingInfo = ratingInfo; | ||||
|             this.postSubjects = this.getAllPosts().reduce( | ||||
|                 (postSubjects, post) => { | ||||
|                     postSubjects[post.id] = post.subject; | ||||
| @ -487,7 +503,8 @@ export class AddonModForumDiscussionPage implements OnInit, AfterViewInit, OnDes | ||||
|                 this.canPin = false; | ||||
|             } | ||||
| 
 | ||||
|             // @todo fetch hasOfflineRatings.
 | ||||
|             this.hasOfflineRatings = | ||||
|                 await CoreRatingOffline.hasRatings('mod_forum', 'post', ContextLevel.MODULE, this.cmId, this.discussionId); | ||||
|         } catch (error) { | ||||
|             CoreDomUtils.showErrorModal(error); | ||||
|         } finally { | ||||
|  | ||||
| @ -17,6 +17,7 @@ import { CoreSite, CoreSiteWSPreSets } from '@classes/site'; | ||||
| import { CoreCourseCommonModWSOptions } from '@features/course/services/course'; | ||||
| import { CoreCourseLogHelper } from '@features/course/services/log-helper'; | ||||
| import { CoreFileEntry } from '@features/fileuploader/services/fileuploader'; | ||||
| import { CoreRatingInfo } from '@features/rating/services/rating'; | ||||
| import { CoreUser } from '@features/user/services/user'; | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreFilepool } from '@services/filepool'; | ||||
| @ -553,7 +554,7 @@ export class AddonModForumProvider { | ||||
|         posts: AddonModForumPost[]; | ||||
|         courseid?: number; | ||||
|         forumid?: number; | ||||
|         ratinginfo?: AddonModForumRatingInfo; | ||||
|         ratinginfo?: CoreRatingInfo; | ||||
|     }> { | ||||
|         // Convenience function to translate legacy data to new format.
 | ||||
|         const translateLegacyPostsFormat = (posts: AddonModForumLegacyPost[]): AddonModForumPost[] => posts.map((post) => { | ||||
| @ -1526,40 +1527,6 @@ export type AddonModForumLegacyPost = { | ||||
|     }[]; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Forum rating info. | ||||
|  */ | ||||
| export type AddonModForumRatingInfo = { | ||||
|     contextid: number; // Context id.
 | ||||
|     component: string; // Context name.
 | ||||
|     ratingarea: string; // Rating area name.
 | ||||
|     canviewall?: boolean; // Whether the user can view all the individual ratings.
 | ||||
|     canviewany?: boolean; // Whether the user can view aggregate of ratings of others.
 | ||||
|     scales?: { // Different scales used information.
 | ||||
|         id: number; // Scale id.
 | ||||
|         courseid?: number; // Course id.
 | ||||
|         name?: string; // Scale name (when a real scale is used).
 | ||||
|         max: number; // Max value for the scale.
 | ||||
|         isnumeric: boolean; // Whether is a numeric scale.
 | ||||
|         items?: { // Scale items. Only returned for not numerical scales.
 | ||||
|             value: number; // Scale value/option id.
 | ||||
|             name: string; // Scale name.
 | ||||
|         }[]; | ||||
|     }[]; | ||||
|     ratings?: { // The ratings.
 | ||||
|         itemid: number; // Item id.
 | ||||
|         scaleid?: number; // Scale id.
 | ||||
|         userid?: number; // User who rated id.
 | ||||
|         aggregate?: number; // Aggregated ratings grade.
 | ||||
|         aggregatestr?: string; // Aggregated ratings as string.
 | ||||
|         aggregatelabel?: string; // The aggregation label.
 | ||||
|         count?: number; // Ratings count (used when aggregating).
 | ||||
|         rating?: number; // The rating the user gave.
 | ||||
|         canrate?: boolean; // Whether the user can rate the item.
 | ||||
|         canviewaggregate?: boolean; // Whether the user can view the aggregated grade.
 | ||||
|     }[]; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Options to pass to get discussions. | ||||
|  */ | ||||
| @ -1994,7 +1961,7 @@ export type AddonModForumGetDiscussionPostsWSResponse = { | ||||
|     posts: AddonModForumWSPost[]; | ||||
|     forumid: number; // The forum id.
 | ||||
|     courseid: number; // The forum course id.
 | ||||
|     ratinginfo?: AddonModForumRatingInfo; // Rating information.
 | ||||
|     ratinginfo?: CoreRatingInfo; // Rating information.
 | ||||
|     warnings?: CoreWSExternalWarning[]; | ||||
| }; | ||||
| 
 | ||||
| @ -2012,7 +1979,7 @@ export type AddonModForumGetForumDiscussionPostsWSParams = { | ||||
|  */ | ||||
| export type AddonModForumGetForumDiscussionPostsWSResponse = { | ||||
|     posts: AddonModForumLegacyPost[]; | ||||
|     ratinginfo?: AddonModForumRatingInfo; // Rating information.
 | ||||
|     ratinginfo?: CoreRatingInfo; // Rating information.
 | ||||
|     warnings?: CoreWSExternalWarning[]; | ||||
| }; | ||||
| 
 | ||||
|  | ||||
| @ -12,11 +12,13 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { ContextLevel } from '@/core/constants'; | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { CoreSyncBaseProvider } from '@classes/base-sync'; | ||||
| import { CoreCourse } from '@features/course/services/course'; | ||||
| import { CoreCourseLogHelper } from '@features/course/services/log-helper'; | ||||
| import { CoreFileUploader } from '@features/fileuploader/services/fileuploader'; | ||||
| import { CoreRatingSync } from '@features/rating/services/rating-sync'; | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreGroups } from '@services/groups'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| @ -327,14 +329,44 @@ export class AddonModForumSyncProvider extends CoreSyncBaseProvider<AddonModForu | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return Promise resolved if sync is successful, rejected otherwise. | ||||
|      */ | ||||
|     // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | ||||
|     async syncRatings(cmId?: number, discussionId?: number, force?: boolean, siteId?: string): Promise<{ | ||||
|         updated: boolean; | ||||
|         warnings: string[]; | ||||
|     }> { | ||||
|         // @todo
 | ||||
|     async syncRatings(cmId?: number, discussionId?: number, force?: boolean, siteId?: string): Promise<AddonModForumSyncResult> { | ||||
|         siteId = siteId || CoreSites.getCurrentSiteId(); | ||||
| 
 | ||||
|         return { updated: true, warnings: [] }; | ||||
|         const results = | ||||
|             await CoreRatingSync.syncRatings('mod_forum', 'post', ContextLevel.MODULE, cmId, discussionId, force, siteId); | ||||
| 
 | ||||
|         let updated = false; | ||||
|         const warnings: string[] = []; | ||||
|         const promises: Promise<void>[] = []; | ||||
| 
 | ||||
|         results.forEach((result) => { | ||||
|             if (result.updated.length) { | ||||
|                 updated = true; | ||||
| 
 | ||||
|                 // Invalidate discussions of updated ratings.
 | ||||
|                 promises.push(AddonModForum.invalidateDiscussionPosts(result.itemSet!.itemSetId, undefined, siteId)); | ||||
|             } | ||||
| 
 | ||||
|             if (result.warnings.length) { | ||||
|                 // Fetch forum to construct the warning message.
 | ||||
|                 promises.push(AddonModForum.getForum(result.itemSet!.courseId!, result.itemSet!.instanceId, { siteId }) | ||||
|                     .then((forum) => { | ||||
|                         result.warnings.forEach((warning) => { | ||||
|                             warnings.push(Translate.instant('core.warningofflinedatadeleted', { | ||||
|                                 component: this.componentTranslate, | ||||
|                                 name: forum.name, | ||||
|                                 error: warning, | ||||
|                             })); | ||||
|                         }); | ||||
| 
 | ||||
|                         return; | ||||
|                     })); | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         await CoreUtils.allPromises(promises); | ||||
| 
 | ||||
|         return { updated, warnings }; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user