From 30fdefd1db6deaf404c84ac387057f8c92253654 Mon Sep 17 00:00:00 2001 From: Dani Palou Date: Thu, 30 Sep 2021 10:59:54 +0200 Subject: [PATCH] MOBILE-3873 bbb: Support BBB activity --- scripts/langindex.json | 13 ++ .../mod/assign/classes/submissions-source.ts | 1 + .../mod/assign/components/index/index.ts | 1 + .../components/index/index.html | 94 ++++++++++++- .../components/index/index.scss | 7 + .../bigbluebuttonbn/components/index/index.ts | 123 +++++++++++++++++- src/addons/mod/bigbluebuttonbn/lang.json | 14 +- .../services/bigbluebuttonbn.ts | 4 +- .../services/handlers/module.ts | 10 +- .../mod/workshop/components/index/index.ts | 1 + src/core/services/groups.ts | 8 ++ 11 files changed, 263 insertions(+), 13 deletions(-) create mode 100644 src/addons/mod/bigbluebuttonbn/components/index/index.scss diff --git a/scripts/langindex.json b/scripts/langindex.json index cc6776547..d9f55134b 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -433,6 +433,19 @@ "addon.mod_assign_submission_file.pluginname": "assignsubmission_file", "addon.mod_assign_submission_onlinetext.pluginname": "assignsubmission_onlinetext", "addon.mod_assign_submission_onlinetext.wordlimitexceeded": "assignsubmission_onlinetext", + "addon.mod_bigbluebuttonbn.mod_form_field_closingtime": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.mod_form_field_openingtime": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.userlimitreached": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_conference_action_join": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_error_unable_join_student": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_groups_selection_warning": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_conference_in_progress": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_conference_room_ready": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_moderator": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_moderators": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_session_started_at": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_viewer": "bigbluebuttonbn", + "addon.mod_bigbluebuttonbn.view_message_viewers": "bigbluebuttonbn", "addon.mod_book.errorchapter": "book", "addon.mod_book.modulenameplural": "book", "addon.mod_book.navnexttitle": "book", diff --git a/src/addons/mod/assign/classes/submissions-source.ts b/src/addons/mod/assign/classes/submissions-source.ts index fce121386..b0905d5fe 100644 --- a/src/addons/mod/assign/classes/submissions-source.ts +++ b/src/addons/mod/assign/classes/submissions-source.ts @@ -55,6 +55,7 @@ export class AddonModAssignSubmissionsSource extends CoreItemsManagerSource - -

TODO: BBB native content

+ + + + + {{ 'addon.mod_bigbluebuttonbn.view_groups_selection_warning' | translate }} + + + + + + {{'core.groupsseparate' | translate }} + {{'core.groupsvisible' | translate }} + + + + {{groupOpt.name}} + + + + + + + + +

{{ 'addon.mod_bigbluebuttonbn.mod_form_field_openingtime' | translate }}

+
+

{{ meetingInfo.openingtime * 1000 | coreFormatDate }}

+
+ + +

{{ 'addon.mod_bigbluebuttonbn.mod_form_field_closingtime' | translate }}

+
+

{{ meetingInfo.closingtime * 1000 | coreFormatDate }}

+
+ + + +

{{ 'addon.mod_bigbluebuttonbn.view_message_conference_room_ready' | translate }}

+
+
+ + + + +

{{ 'addon.mod_bigbluebuttonbn.view_message_conference_in_progress' | translate }}

+
+
+ + + +

{{ 'addon.mod_bigbluebuttonbn.view_message_session_started_at' | translate }}

+
+

{{ meetingInfo.startedat * 1000 | coreFormatDate: "strftimetime" }}

+
+ + + +

+ {{ 'addon.mod_bigbluebuttonbn.view_message_moderators' | translate }} +

+

+ {{ 'addon.mod_bigbluebuttonbn.view_message_moderator' | translate }} +

+
+

{{ meetingInfo.moderatorcount }}

+
+ + + +

+ {{ 'addon.mod_bigbluebuttonbn.view_message_viewers' | translate }} +

+

+ {{ 'addon.mod_bigbluebuttonbn.view_message_viewer' | translate }} +

+
+

{{ meetingInfo.participantcount }}

+
+
+ + + {{ 'addon.mod_bigbluebuttonbn.view_conference_action_join' | translate }} + + + + + + {{ meetingInfo.statusmessage }} + + +
diff --git a/src/addons/mod/bigbluebuttonbn/components/index/index.scss b/src/addons/mod/bigbluebuttonbn/components/index/index.scss new file mode 100644 index 000000000..66566a376 --- /dev/null +++ b/src/addons/mod/bigbluebuttonbn/components/index/index.scss @@ -0,0 +1,7 @@ +@import "~theme/globals"; + +:host { + ion-item > p[slot="end"] { + font-size: 14px; + } +} diff --git a/src/addons/mod/bigbluebuttonbn/components/index/index.ts b/src/addons/mod/bigbluebuttonbn/components/index/index.ts index a2427c8f4..3f62eea6e 100644 --- a/src/addons/mod/bigbluebuttonbn/components/index/index.ts +++ b/src/addons/mod/bigbluebuttonbn/components/index/index.ts @@ -15,8 +15,13 @@ import { Component, OnInit, Optional } from '@angular/core'; import { CoreCourseModuleMainActivityComponent } from '@features/course/classes/main-activity-component'; import { CoreCourseContentsPage } from '@features/course/pages/contents/contents'; +import { CoreCourse } from '@features/course/services/course'; import { IonContent } from '@ionic/angular'; -import { AddonModBBBData, AddonModBBBService } from '../../services/bigbluebuttonbn'; +import { CoreGroupInfo, CoreGroups } from '@services/groups'; +import { CoreDomUtils } from '@services/utils/dom'; +import { CoreUtils } from '@services/utils/utils'; +import { Translate } from '@singletons'; +import { AddonModBBB, AddonModBBBData, AddonModBBBMeetingInfoWSResponse, AddonModBBBService } from '../../services/bigbluebuttonbn'; /** * Component that displays a Big Blue Button activity. @@ -24,12 +29,16 @@ import { AddonModBBBData, AddonModBBBService } from '../../services/bigbluebutto @Component({ selector: 'addon-mod-bbb-index', templateUrl: 'index.html', + styleUrls: ['index.scss'], }) export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityComponent implements OnInit { component = AddonModBBBService.COMPONENT; moduleName = 'bigbluebuttonbn'; bbb?: AddonModBBBData; + groupInfo?: CoreGroupInfo; + groupId = 0; + meetingInfo?: AddonModBBBMeetingInfoWSResponse; constructor( protected content?: IonContent, @@ -46,7 +55,17 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo await this.loadContent(); - // @todo + if (!this.bbb) { + return; + } + + try { + await AddonModBBB.logView(this.bbb.id, this.bbb.name); + + CoreCourse.checkModuleCompletion(this.courseId, this.module.completiondata); + } catch { + // Ignore errors. + } } /** @@ -54,10 +73,108 @@ export class AddonModBBBIndexComponent extends CoreCourseModuleMainActivityCompo */ protected async fetchContent(refresh: boolean = false): Promise { try { - // @todo + this.bbb = await AddonModBBB.getBBB(this.courseId, this.module.id); + + this.description = this.bbb.intro; + this.dataRetrieved.emit(this.bbb); + + this.groupInfo = await CoreGroups.getActivityGroupInfo(this.module.id, false); + + this.groupId = CoreGroups.validateGroupId(this.groupId, this.groupInfo); + + await this.fetchMeetingInfo(); } finally { this.fillContextMenu(refresh); } } + /** + * Get meeting info. + * + * @return Promise resolved when done. + */ + async fetchMeetingInfo(): Promise { + if (!this.bbb) { + return; + } + + this.meetingInfo = await AddonModBBB.getMeetingInfo(this.bbb.id, this.groupId); + + if (this.meetingInfo.statusrunning && this.meetingInfo.userlimit > 0) { + const count = (this.meetingInfo.participantcount || 0) + (this.meetingInfo.moderatorcount || 0); + if (count === this.meetingInfo.userlimit) { + this.meetingInfo.statusmessage = Translate.instant('addon.mod_bigbluebuttonbn.userlimitreached'); + } + } + } + + /** + * Update meeting info. + * + * @return Promise resolved when done. + */ + async updateMeetingInfo(): Promise { + if (!this.bbb) { + return; + } + + await AddonModBBB.invalidateAllGroupsMeetingInfo(this.bbb.id); + + await this.fetchMeetingInfo(); + } + + /** + * @inheritdoc + */ + protected async invalidateContent(): Promise { + const promises: Promise[] = []; + + promises.push(AddonModBBB.invalidateBBBs(this.courseId)); + promises.push(CoreGroups.invalidateActivityGroupInfo(this.module.id)); + + if (this.bbb) { + promises.push(AddonModBBB.invalidateAllGroupsMeetingInfo(this.bbb.id)); + } + + await Promise.all(promises); + } + + /** + * Group changed, reload some data. + * + * @return Promise resolved when done. + */ + async groupChanged(): Promise { + this.loaded = false; + + try { + await this.fetchMeetingInfo(); + } catch (error) { + CoreDomUtils.showErrorModal(error); + } finally { + this.loaded = true; + } + } + + /** + * Join the room. + * + * @return Promise resolved when done. + */ + async joinRoom(): Promise { + const modal = await CoreDomUtils.showModalLoading(); + + try { + const joinUrl = await AddonModBBB.getJoinUrl(this.module.id, this.groupId); + + CoreUtils.openInBrowser(joinUrl); + + this.updateMeetingInfo(); + } catch (error) { + CoreDomUtils.showErrorModal(error); + } finally { + modal.dismiss(); + } + } + } diff --git a/src/addons/mod/bigbluebuttonbn/lang.json b/src/addons/mod/bigbluebuttonbn/lang.json index a87fdb56f..ccc84da16 100644 --- a/src/addons/mod/bigbluebuttonbn/lang.json +++ b/src/addons/mod/bigbluebuttonbn/lang.json @@ -1,3 +1,15 @@ { - "view_error_unable_join_student": "BeeUnable to connect to the BigBlueButton server. Please contact your Teacher or the Administrator.p" + "mod_form_field_closingtime": "Join closed", + "mod_form_field_openingtime": "Join open", + "userlimitreached": "The number of users allowed in a meeting has been reached.", + "view_conference_action_join": "Join session", + "view_error_unable_join_student": "Unable to connect to the BigBlueButton server. Please contact your Teacher or the Administrator.", + "view_groups_selection_warning": "There is a conference room for each group and you have access to more than one. Be sure to select the correct one.", + "view_message_conference_in_progress": "This conference is in progress.", + "view_message_conference_room_ready": "This conference room is ready. You can join the session now.", + "view_message_moderator": "moderator", + "view_message_moderators": "moderators", + "view_message_session_started_at": "This session started at", + "view_message_viewer": "viewer", + "view_message_viewers": "viewers" } diff --git a/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts b/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts index f1ed9f3cf..74c672d55 100644 --- a/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts +++ b/src/addons/mod/bigbluebuttonbn/services/bigbluebuttonbn.ts @@ -304,8 +304,8 @@ export type AddonModBBBMeetingInfoWSResponse = { userlimit: number; // User limit. bigbluebuttonbnid: string; // Bigbluebuttonbn instance id. meetingid: string; // Meeting id. - openingtime?: string; // Opening time. - closingtime?: string; // Closing time. + openingtime?: number; // Opening time. + closingtime?: number; // Closing time. statusrunning?: boolean; // Status running. statusclosed?: boolean; // Status closed. statusopen?: boolean; // Status open. diff --git a/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts b/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts index 4863be94e..85956b4ed 100644 --- a/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts +++ b/src/addons/mod/bigbluebuttonbn/services/handlers/module.ts @@ -15,7 +15,7 @@ import { CoreConstants } from '@/core/constants'; import { Injectable, Type } from '@angular/core'; import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler'; -import { CoreCourseAnyModuleData } from '@features/course/services/course'; +import { CoreCourseModule } from '@features/course/services/course-helper'; import { CoreCourseModuleHandler, CoreCourseModuleHandlerData } from '@features/course/services/module-delegate'; import { CoreSitePluginsModuleHandler } from '@features/siteplugins/classes/handlers/module-handler'; import { CoreSitePlugins } from '@features/siteplugins/services/siteplugins'; @@ -71,17 +71,17 @@ export class AddonModBBBModuleHandlerService extends CoreModuleHandlerBase imple /** * @inheritdoc */ - getData( - module: CoreCourseAnyModuleData, + async getData( + module: CoreCourseModule, courseId: number, sectionId?: number, forCoursePage?: boolean, - ): CoreCourseModuleHandlerData { + ): Promise { if (this.sitePluginHandler) { return this.sitePluginHandler.getData(module, courseId, sectionId, forCoursePage); } - const data = super.getData(module, courseId, sectionId, forCoursePage); + const data = await super.getData(module, courseId, sectionId, forCoursePage); data.showDownloadButton = false; diff --git a/src/addons/mod/workshop/components/index/index.ts b/src/addons/mod/workshop/components/index/index.ts index ef11aedf7..91c8bba44 100644 --- a/src/addons/mod/workshop/components/index/index.ts +++ b/src/addons/mod/workshop/components/index/index.ts @@ -82,6 +82,7 @@ export class AddonModWorkshopIndexComponent extends CoreCourseModuleMainActivity separateGroups: false, visibleGroups: false, defaultGroupId: 0, + canAccessAllGroups: false, }; canSubmit = false; diff --git a/src/core/services/groups.ts b/src/core/services/groups.ts index 7aad3f30c..b0d63b803 100644 --- a/src/core/services/groups.ts +++ b/src/core/services/groups.ts @@ -151,6 +151,7 @@ export class CoreGroupsProvider { const groupInfo: CoreGroupInfo = { groups: [], defaultGroupId: 0, + canAccessAllGroups: false, }; const groupMode = await this.getActivityGroupMode(cmId, siteId, ignoreCache); @@ -161,6 +162,8 @@ export class CoreGroupsProvider { let result: CoreGroupGetActivityAllowedGroupsWSResponse; if (groupInfo.separateGroups || groupInfo.visibleGroups) { result = await this.getActivityAllowedGroups(cmId, userId, siteId, ignoreCache); + + groupInfo.canAccessAllGroups = !!result.canaccessallgroups; } else { result = { groups: [], @@ -471,6 +474,11 @@ export type CoreGroupInfo = { * The group ID to use by default. If all participants is visible, 0 will be used. First group ID otherwise. */ defaultGroupId: number; + + /** + * Whether the user has the capability to access all groups in the context. + */ + canAccessAllGroups: boolean; }; /**