From 0fdd0761755e6471a3370ecf78906d97e363cb7a Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Fri, 25 Jul 2025 11:37:02 -0300 Subject: [PATCH 01/22] [lad-new-functions-plugin] added upsert and delete for lad entries --- src/core/api/BbbPluginSdk.ts | 14 +++++- src/core/api/types.ts | 12 ++++- src/learning-analytics-dashboard/enums.ts | 2 + src/learning-analytics-dashboard/hooks.ts | 54 ++++++++++++++++++++--- src/learning-analytics-dashboard/types.ts | 49 ++++++++++++++++++-- 5 files changed, 120 insertions(+), 11 deletions(-) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 90d06ded..fadf2218 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -46,7 +46,7 @@ import { useUiData } from '../../ui-data/hooks/hooks'; import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-core/types'; import { useMeeting } from '../../data-consumption/domain/meeting/from-core/hooks'; import { serverCommands } from '../../server-commands/commands'; -import { sendGenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/hooks'; +import { deleteGenericData, sendGenericDataForLearningAnalyticsDashboard, upsertGenericData } from '../../learning-analytics-dashboard/hooks'; import { GenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { getRemoteData } from '../../remote-data/utils'; import { persistEventFunctionWrapper } from '../../event-persistence/hooks'; @@ -131,6 +131,18 @@ export abstract class BbbPluginSdk { pluginApi.sendGenericDataForLearningAnalyticsDashboard = ( data: GenericDataForLearningAnalyticsDashboard, ) => sendGenericDataForLearningAnalyticsDashboard(data, pluginName); + pluginApi.learningAnalyticsDashboard = { + upsertGenericData: (data, targetUserId) => upsertGenericData( + data, + pluginName, + targetUserId, + ), + deleteGenericData: (data, targetUserId) => deleteGenericData( + data, + pluginName, + targetUserId, + ), + }; pluginApi.getRemoteData = ( dataSourceName: string, ) => getRemoteData(dataSourceName, pluginName); diff --git a/src/core/api/types.ts b/src/core/api/types.ts index 48a66821..9709e47d 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -27,7 +27,7 @@ import { GenericContentInterface } from '../../extensible-areas/generic-content- import { UseUiDataFunction } from '../../ui-data/hooks/types'; import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-core/types'; import { ServerCommands } from '../../server-commands/types'; -import { SendGenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; +import { LearningAnalyticsDashboardWrapperObject, SendGenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { UseUserCameraDomElementsFunction } from '../../dom-element-manipulation/user-camera/types'; import { ScreenshareHelperInterface, UserCameraHelperInterface } from '../../extensible-areas'; import { GetDataSource } from '../../remote-data/types'; @@ -287,12 +287,22 @@ export interface PluginApi { */ useLocaleMessages?: UseLocaleMessagesFunction /** + * @deprecated Use {@link learningAnalyticsDashboard.upsertGenericData} object instead. + * * Send data to the Learning analytics dashboard * * @param data - object in which one can render in the learning analytics dashboard * */ sendGenericDataForLearningAnalyticsDashboard?: SendGenericDataForLearningAnalyticsDashboard; + /** + * Wrapper object of functions related to the learning analytics dashboard. + * It contains the following functions: + * - deleteGenericData: Deletes a certain entry in the learning dashboard generic-data; + * - upsertGenericData: Updates or insert a generic data entry in the learning dashboard; + * + */ + learningAnalyticsDashboard?: LearningAnalyticsDashboardWrapperObject; /** * Fetches external data from pre-defined data-source in manifest. * diff --git a/src/learning-analytics-dashboard/enums.ts b/src/learning-analytics-dashboard/enums.ts index fe5b568d..fd7d71ff 100644 --- a/src/learning-analytics-dashboard/enums.ts +++ b/src/learning-analytics-dashboard/enums.ts @@ -1,3 +1,5 @@ export enum LearningAnalyticsDashboardEvents { GENERIC_DATA_SENT = 'GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + UPSERT_GENERIC_DATA_SENT = 'UPSERT_GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + DELETE_GENERIC_DATA_SENT = 'DELETE_GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', } diff --git a/src/learning-analytics-dashboard/hooks.ts b/src/learning-analytics-dashboard/hooks.ts index 1a1a3766..b8a42477 100644 --- a/src/learning-analytics-dashboard/hooks.ts +++ b/src/learning-analytics-dashboard/hooks.ts @@ -1,6 +1,8 @@ import { LearningAnalyticsDashboardEventDetails, GenericDataForLearningAnalyticsDashboard, + UpsertGenericDataArguments, + DeleteGenericDataArguments, } from './types'; import { LearningAnalyticsDashboardEvents } from './enums'; @@ -10,11 +12,51 @@ export const sendGenericDataForLearningAnalyticsDashboard = ( ) => { window.dispatchEvent( new CustomEvent< - LearningAnalyticsDashboardEventDetails>(LearningAnalyticsDashboardEvents.GENERIC_DATA_SENT, { - detail: { - pluginName, - data, - }, - }), + LearningAnalyticsDashboardEventDetails>(LearningAnalyticsDashboardEvents.GENERIC_DATA_SENT, { + detail: { + pluginName, + data, + }, + }), + ); +}; + +export const upsertGenericData = ( + data: UpsertGenericDataArguments, + pluginName: string, + targetUserId?: string, +) => { + window.dispatchEvent( + new CustomEvent< + LearningAnalyticsDashboardEventDetails>( + LearningAnalyticsDashboardEvents.UPSERT_GENERIC_DATA_SENT, + { + detail: { + pluginName, + data, + targetUserId, + }, + }, + ), + ); +}; + +export const deleteGenericData = ( + data: DeleteGenericDataArguments, + pluginName: string, + targetUserId?: string, +) => { + window.dispatchEvent( + new CustomEvent< + LearningAnalyticsDashboardEventDetails>( + LearningAnalyticsDashboardEvents.DELETE_GENERIC_DATA_SENT, + { + detail: { + pluginName, + data, + targetUserId, + }, + }, + ), ); }; diff --git a/src/learning-analytics-dashboard/types.ts b/src/learning-analytics-dashboard/types.ts index a93c426d..c579bdfb 100644 --- a/src/learning-analytics-dashboard/types.ts +++ b/src/learning-analytics-dashboard/types.ts @@ -1,13 +1,56 @@ +// Deprecated Send data function export interface GenericDataForLearningAnalyticsDashboard { cardTitle: string; columnTitle: string; value: string; } +export type SendGenericDataForLearningAnalyticsDashboard = ( + data: GenericDataForLearningAnalyticsDashboard) => void; + +// Upsert function +export interface UpsertGenericDataArguments { + cardTitle: string; + columnTitle: string; + value: string; +} + +export type UpsertGenericDataFunction = ( + data: UpsertGenericDataArguments, + targetUserId?: string, +) => void; + +// Delete function +export interface DeleteGenericDataArguments { + cardTitle: string; + columnTitle: string; +} + +export type DeleteGenericDataFunction = ( + data: DeleteGenericDataArguments, + targetUserId?: string, +) => void; + +// General typing. + export interface LearningAnalyticsDashboardEventDetails { pluginName: string; - data: GenericDataForLearningAnalyticsDashboard; + data: GenericDataForLearningAnalyticsDashboard + | UpsertGenericDataArguments | DeleteGenericDataArguments; + targetUserId?: string; } -export type SendGenericDataForLearningAnalyticsDashboard = ( - data: GenericDataForLearningAnalyticsDashboard) => void; +export interface LearningAnalyticsDashboardWrapperObject { + /** + * Updates or insert a generic data entry in the learning dashboard; + * + * @param data Data to insert or update + */ + upsertGenericData: UpsertGenericDataFunction; + /** + * Updates or insert a generic data entry in the learning dashboard; + * + * @param data Data to be deleted + */ + deleteGenericData: DeleteGenericDataFunction; +} From 7685701896bac9689857d866f663814b7e7a0111 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Fri, 25 Jul 2025 15:34:02 -0300 Subject: [PATCH 02/22] [lad-new-functions-plugin] rename from genericData -> data --- src/core/api/BbbPluginSdk.ts | 6 +++--- src/learning-analytics-dashboard/enums.ts | 4 ++-- src/learning-analytics-dashboard/hooks.ts | 16 ++++++++-------- src/learning-analytics-dashboard/types.ts | 18 +++++++++--------- 4 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index fadf2218..7fb369b7 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -46,7 +46,7 @@ import { useUiData } from '../../ui-data/hooks/hooks'; import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-core/types'; import { useMeeting } from '../../data-consumption/domain/meeting/from-core/hooks'; import { serverCommands } from '../../server-commands/commands'; -import { deleteGenericData, sendGenericDataForLearningAnalyticsDashboard, upsertGenericData } from '../../learning-analytics-dashboard/hooks'; +import { deleteData, sendGenericDataForLearningAnalyticsDashboard, upsertData } from '../../learning-analytics-dashboard/hooks'; import { GenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { getRemoteData } from '../../remote-data/utils'; import { persistEventFunctionWrapper } from '../../event-persistence/hooks'; @@ -132,12 +132,12 @@ export abstract class BbbPluginSdk { data: GenericDataForLearningAnalyticsDashboard, ) => sendGenericDataForLearningAnalyticsDashboard(data, pluginName); pluginApi.learningAnalyticsDashboard = { - upsertGenericData: (data, targetUserId) => upsertGenericData( + upsertData: (data, targetUserId) => upsertData( data, pluginName, targetUserId, ), - deleteGenericData: (data, targetUserId) => deleteGenericData( + deleteData: (data, targetUserId) => deleteData( data, pluginName, targetUserId, diff --git a/src/learning-analytics-dashboard/enums.ts b/src/learning-analytics-dashboard/enums.ts index fd7d71ff..39790099 100644 --- a/src/learning-analytics-dashboard/enums.ts +++ b/src/learning-analytics-dashboard/enums.ts @@ -1,5 +1,5 @@ export enum LearningAnalyticsDashboardEvents { GENERIC_DATA_SENT = 'GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', - UPSERT_GENERIC_DATA_SENT = 'UPSERT_GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', - DELETE_GENERIC_DATA_SENT = 'DELETE_GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + UPSERT_DATA_COMMAND_SENT = 'UPSERT_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + DELETE_DATA_COMMAND_SENT = 'DELETE_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', } diff --git a/src/learning-analytics-dashboard/hooks.ts b/src/learning-analytics-dashboard/hooks.ts index b8a42477..cf88a7fe 100644 --- a/src/learning-analytics-dashboard/hooks.ts +++ b/src/learning-analytics-dashboard/hooks.ts @@ -1,8 +1,8 @@ import { LearningAnalyticsDashboardEventDetails, GenericDataForLearningAnalyticsDashboard, - UpsertGenericDataArguments, - DeleteGenericDataArguments, + UpsertDataArguments, + DeleteDataArguments, } from './types'; import { LearningAnalyticsDashboardEvents } from './enums'; @@ -21,15 +21,15 @@ export const sendGenericDataForLearningAnalyticsDashboard = ( ); }; -export const upsertGenericData = ( - data: UpsertGenericDataArguments, +export const upsertData = ( + data: UpsertDataArguments, pluginName: string, targetUserId?: string, ) => { window.dispatchEvent( new CustomEvent< LearningAnalyticsDashboardEventDetails>( - LearningAnalyticsDashboardEvents.UPSERT_GENERIC_DATA_SENT, + LearningAnalyticsDashboardEvents.UPSERT_DATA_COMMAND_SENT, { detail: { pluginName, @@ -41,15 +41,15 @@ export const upsertGenericData = ( ); }; -export const deleteGenericData = ( - data: DeleteGenericDataArguments, +export const deleteData = ( + data: DeleteDataArguments, pluginName: string, targetUserId?: string, ) => { window.dispatchEvent( new CustomEvent< LearningAnalyticsDashboardEventDetails>( - LearningAnalyticsDashboardEvents.DELETE_GENERIC_DATA_SENT, + LearningAnalyticsDashboardEvents.DELETE_DATA_COMMAND_SENT, { detail: { pluginName, diff --git a/src/learning-analytics-dashboard/types.ts b/src/learning-analytics-dashboard/types.ts index c579bdfb..3f71c838 100644 --- a/src/learning-analytics-dashboard/types.ts +++ b/src/learning-analytics-dashboard/types.ts @@ -9,25 +9,25 @@ export type SendGenericDataForLearningAnalyticsDashboard = ( data: GenericDataForLearningAnalyticsDashboard) => void; // Upsert function -export interface UpsertGenericDataArguments { +export interface UpsertDataArguments { cardTitle: string; columnTitle: string; value: string; } -export type UpsertGenericDataFunction = ( - data: UpsertGenericDataArguments, +export type UpsertDataFunction = ( + data: UpsertDataArguments, targetUserId?: string, ) => void; // Delete function -export interface DeleteGenericDataArguments { +export interface DeleteDataArguments { cardTitle: string; columnTitle: string; } -export type DeleteGenericDataFunction = ( - data: DeleteGenericDataArguments, +export type DeleteDataFunction = ( + data: DeleteDataArguments, targetUserId?: string, ) => void; @@ -36,7 +36,7 @@ export type DeleteGenericDataFunction = ( export interface LearningAnalyticsDashboardEventDetails { pluginName: string; data: GenericDataForLearningAnalyticsDashboard - | UpsertGenericDataArguments | DeleteGenericDataArguments; + | UpsertDataArguments | DeleteDataArguments; targetUserId?: string; } @@ -46,11 +46,11 @@ export interface LearningAnalyticsDashboardWrapperObject { * * @param data Data to insert or update */ - upsertGenericData: UpsertGenericDataFunction; + upsertData: UpsertDataFunction; /** * Updates or insert a generic data entry in the learning dashboard; * * @param data Data to be deleted */ - deleteGenericData: DeleteGenericDataFunction; + deleteData: DeleteDataFunction; } From 5d1ebfea49ee70a3f16c6bcb504374cdca646659 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Fri, 25 Jul 2025 16:50:44 -0300 Subject: [PATCH 03/22] [lad-new-functions-plugin] added documentation --- README.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 22b8af2c..00568f76 100644 --- a/README.md +++ b/README.md @@ -458,18 +458,34 @@ So the idea is that we have a `uiCommands` object and at a point, there will be ### Learning Analytics Dashboard integration -- `sendGenericDataForLearningAnalyticsDashboard`: This function will send data for the bbb to render inside the plugin's table +This integration allow you to insert/update entry in LAD (Learning Analytics Dashboard) via `upsert` function and also delete entries via `delete` function. -The object structure of this function's argument must be: +It's an object available in the `pluginApi` that wraps those 2 functions: + +- `pluginApi.learningAnalyticsDashboard.upsert` +- `pluginApi.learningAnalyticsDashboard.delete` + +For the `upsert` function, the argument's data object structure must be: ```ts -interface GenericDataForLearningAnalyticsDashboard { - cardTitle: string; // Yet to be implemented (future updates) +interface UpsertDataArguments { + cardTitle: string; columnTitle: string; value: string; } ``` +For the `delete` function, the argument's data object structure must be: + +```ts +interface DeleteDataArguments { + cardTitle: string; + columnTitle: string; +} +``` + +And if the user is a moderator, there is the possibility to publish data on behalf of other users by using the second **optional** parameter named `targetUserId` + So that the data will appear in the following form: | User | Count | `` | @@ -477,6 +493,32 @@ So that the data will appear in the following form: | user-name | 1 | `` | +See example of use ahead: + +```ts +const targetUserId = 'abcd-efg'; +pluginApi.learningAnalyticsDashboard.upsertData( + { + cardTitle: 'Example Title', + columnTitle: 'link sent by user', + value: '[link](https://my-website.com/abc.png)' + }, + targetUserId, +); + +pluginApi.learningAnalyticsDashboard.deleteData( + { + cardTitle: 'Example Title', + columnTitle: 'link sent by user', + }, + targetUserId, +); +``` + +Note 1: the `value` field (in the upsert function's argument) supports markdown, so feel free to use it as you wish. + +Note 2: pluginApi.sendGenericDataForLearningAnalyticsDashboard is now being deprecated, but has the same data structure as upsert (without the possibility to send entry on behalf of another user) + ### External data resources This is the new integration with external servers to fetch data in a secure manner. From 536c70166ba9598ff48d42934e449195743a4b14 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Thu, 7 Aug 2025 10:05:07 -0300 Subject: [PATCH 04/22] [lad-new-functions-plugin] rename data -> userData for LAD --- README.md | 16 +++++----- src/core/api/BbbPluginSdk.ts | 6 ++-- src/learning-analytics-dashboard/enums.ts | 4 +-- src/learning-analytics-dashboard/hooks.ts | 33 +++++++++++++++----- src/learning-analytics-dashboard/types.ts | 38 ++++++++++++++++------- 5 files changed, 64 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index 00568f76..f90ac235 100644 --- a/README.md +++ b/README.md @@ -458,27 +458,27 @@ So the idea is that we have a `uiCommands` object and at a point, there will be ### Learning Analytics Dashboard integration -This integration allow you to insert/update entry in LAD (Learning Analytics Dashboard) via `upsert` function and also delete entries via `delete` function. +This integration allow you to insert/update entry in LAD (Learning Analytics Dashboard) via `upsertUserData` function and also delete entries via `deleteUserData` function. It's an object available in the `pluginApi` that wraps those 2 functions: -- `pluginApi.learningAnalyticsDashboard.upsert` -- `pluginApi.learningAnalyticsDashboard.delete` +- `pluginApi.learningAnalyticsDashboard.upsertUserData` +- `pluginApi.learningAnalyticsDashboard.deleteUserData` For the `upsert` function, the argument's data object structure must be: ```ts -interface UpsertDataArguments { +interface LearningAnalyticsDashboardUserData { cardTitle: string; columnTitle: string; value: string; } ``` -For the `delete` function, the argument's data object structure must be: +For the `deleteUserData` function, the argument's data object structure must be: ```ts -interface DeleteDataArguments { +interface LearningAnalyticsDashboardDeleteUserData { cardTitle: string; columnTitle: string; } @@ -497,7 +497,7 @@ See example of use ahead: ```ts const targetUserId = 'abcd-efg'; -pluginApi.learningAnalyticsDashboard.upsertData( +pluginApi.learningAnalyticsDashboard.upsertUserData( { cardTitle: 'Example Title', columnTitle: 'link sent by user', @@ -506,7 +506,7 @@ pluginApi.learningAnalyticsDashboard.upsertData( targetUserId, ); -pluginApi.learningAnalyticsDashboard.deleteData( +pluginApi.learningAnalyticsDashboard.deleteUserData( { cardTitle: 'Example Title', columnTitle: 'link sent by user', diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 7fb369b7..8584e047 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -46,7 +46,7 @@ import { useUiData } from '../../ui-data/hooks/hooks'; import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-core/types'; import { useMeeting } from '../../data-consumption/domain/meeting/from-core/hooks'; import { serverCommands } from '../../server-commands/commands'; -import { deleteData, sendGenericDataForLearningAnalyticsDashboard, upsertData } from '../../learning-analytics-dashboard/hooks'; +import { deleteUserData, sendGenericDataForLearningAnalyticsDashboard, upsertUserData } from '../../learning-analytics-dashboard/hooks'; import { GenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { getRemoteData } from '../../remote-data/utils'; import { persistEventFunctionWrapper } from '../../event-persistence/hooks'; @@ -132,12 +132,12 @@ export abstract class BbbPluginSdk { data: GenericDataForLearningAnalyticsDashboard, ) => sendGenericDataForLearningAnalyticsDashboard(data, pluginName); pluginApi.learningAnalyticsDashboard = { - upsertData: (data, targetUserId) => upsertData( + upsertUserData: (data, targetUserId) => upsertUserData( data, pluginName, targetUserId, ), - deleteData: (data, targetUserId) => deleteData( + deleteUserData: (data, targetUserId) => deleteUserData( data, pluginName, targetUserId, diff --git a/src/learning-analytics-dashboard/enums.ts b/src/learning-analytics-dashboard/enums.ts index 39790099..cc3f098f 100644 --- a/src/learning-analytics-dashboard/enums.ts +++ b/src/learning-analytics-dashboard/enums.ts @@ -1,5 +1,5 @@ export enum LearningAnalyticsDashboardEvents { GENERIC_DATA_SENT = 'GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', - UPSERT_DATA_COMMAND_SENT = 'UPSERT_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', - DELETE_DATA_COMMAND_SENT = 'DELETE_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + UPSERT_USER_DATA_COMMAND_SENT = 'UPSERT_USER_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + DELETE_USER_DATA_COMMAND_SENT = 'DELETE_USER_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', } diff --git a/src/learning-analytics-dashboard/hooks.ts b/src/learning-analytics-dashboard/hooks.ts index cf88a7fe..1485b661 100644 --- a/src/learning-analytics-dashboard/hooks.ts +++ b/src/learning-analytics-dashboard/hooks.ts @@ -1,8 +1,9 @@ import { LearningAnalyticsDashboardEventDetails, GenericDataForLearningAnalyticsDashboard, - UpsertDataArguments, - DeleteDataArguments, + LearningAnalyticsDashboardUserData, + LearningAnalyticsDashboardDeleteUserData, + ClearLearningAnalyticsDashboardEventDetails, } from './types'; import { LearningAnalyticsDashboardEvents } from './enums'; @@ -21,15 +22,15 @@ export const sendGenericDataForLearningAnalyticsDashboard = ( ); }; -export const upsertData = ( - data: UpsertDataArguments, +export const upsertUserData = ( + data: LearningAnalyticsDashboardUserData, pluginName: string, targetUserId?: string, ) => { window.dispatchEvent( new CustomEvent< LearningAnalyticsDashboardEventDetails>( - LearningAnalyticsDashboardEvents.UPSERT_DATA_COMMAND_SENT, + LearningAnalyticsDashboardEvents.UPSERT_USER_DATA_COMMAND_SENT, { detail: { pluginName, @@ -41,15 +42,15 @@ export const upsertData = ( ); }; -export const deleteData = ( - data: DeleteDataArguments, +export const deleteUserData = ( + data: LearningAnalyticsDashboardDeleteUserData, pluginName: string, targetUserId?: string, ) => { window.dispatchEvent( new CustomEvent< LearningAnalyticsDashboardEventDetails>( - LearningAnalyticsDashboardEvents.DELETE_DATA_COMMAND_SENT, + LearningAnalyticsDashboardEvents.DELETE_USER_DATA_COMMAND_SENT, { detail: { pluginName, @@ -60,3 +61,19 @@ export const deleteData = ( ), ); }; + +export const clearAllUsersData = ( + pluginName: string, +) => { + window.dispatchEvent( + new CustomEvent< + ClearLearningAnalyticsDashboardEventDetails>( + LearningAnalyticsDashboardEvents.DELETE_USER_DATA_COMMAND_SENT, + { + detail: { + pluginName, + }, + }, + ), + ); +}; diff --git a/src/learning-analytics-dashboard/types.ts b/src/learning-analytics-dashboard/types.ts index 3f71c838..cb666d8b 100644 --- a/src/learning-analytics-dashboard/types.ts +++ b/src/learning-analytics-dashboard/types.ts @@ -9,48 +9,62 @@ export type SendGenericDataForLearningAnalyticsDashboard = ( data: GenericDataForLearningAnalyticsDashboard) => void; // Upsert function -export interface UpsertDataArguments { +export interface LearningAnalyticsDashboardUserData { cardTitle: string; columnTitle: string; value: string; } -export type UpsertDataFunction = ( - data: UpsertDataArguments, +export type UpsertUserDataFunction = ( + data: LearningAnalyticsDashboardUserData, targetUserId?: string, ) => void; // Delete function -export interface DeleteDataArguments { +export interface LearningAnalyticsDashboardDeleteUserData { cardTitle: string; columnTitle: string; } -export type DeleteDataFunction = ( - data: DeleteDataArguments, +export type DeleteUserDataFunction = ( + data: LearningAnalyticsDashboardDeleteUserData, targetUserId?: string, ) => void; -// General typing. +export type ClearUsersDataFunction = () => void; +// General typing. export interface LearningAnalyticsDashboardEventDetails { pluginName: string; data: GenericDataForLearningAnalyticsDashboard - | UpsertDataArguments | DeleteDataArguments; + | LearningAnalyticsDashboardUserData | LearningAnalyticsDashboardDeleteUserData; targetUserId?: string; } +export interface ClearLearningAnalyticsDashboardEventDetails { + pluginName: string; +} + export interface LearningAnalyticsDashboardWrapperObject { /** - * Updates or insert a generic data entry in the learning dashboard; + * Updates or insert a generic data entry in the learning dashboard for a target user + * (if target user is not passed, current user will be considered); * * @param data Data to insert or update + * @targetUserId string representing the internal userId of the target user (Optional) */ - upsertData: UpsertDataFunction; + upsertUserData: UpsertUserDataFunction; /** - * Updates or insert a generic data entry in the learning dashboard; + * Deletes generic data entry for target user (if target user is not passed, + * current user will be considered). * * @param data Data to be deleted + * @targetUserId string representing the internal userId of the target user (Optional) + */ + deleteUserData: DeleteUserDataFunction; + /** + * Clears all Users Data for a specific plugin. (No arguments required) + * */ - deleteData: DeleteDataFunction; + clearAllUsersData: ClearUsersDataFunction; } From d37c682f4bd9068092b24826a04138c8f68d31d7 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Thu, 7 Aug 2025 16:14:07 -0300 Subject: [PATCH 05/22] [lad-new-functions-plugin] Created new function to clear LAD data --- src/core/api/BbbPluginSdk.ts | 11 ++++++++++- src/learning-analytics-dashboard/enums.ts | 1 + src/learning-analytics-dashboard/hooks.ts | 4 +++- src/learning-analytics-dashboard/types.ts | 4 ++-- 4 files changed, 16 insertions(+), 4 deletions(-) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 8584e047..c7d3f948 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -46,7 +46,12 @@ import { useUiData } from '../../ui-data/hooks/hooks'; import { UseMeetingFunction } from '../../data-consumption/domain/meeting/from-core/types'; import { useMeeting } from '../../data-consumption/domain/meeting/from-core/hooks'; import { serverCommands } from '../../server-commands/commands'; -import { deleteUserData, sendGenericDataForLearningAnalyticsDashboard, upsertUserData } from '../../learning-analytics-dashboard/hooks'; +import { + clearAllUsersData, + deleteUserData, + sendGenericDataForLearningAnalyticsDashboard, + upsertUserData, +} from '../../learning-analytics-dashboard/hooks'; import { GenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { getRemoteData } from '../../remote-data/utils'; import { persistEventFunctionWrapper } from '../../event-persistence/hooks'; @@ -142,6 +147,10 @@ export abstract class BbbPluginSdk { pluginName, targetUserId, ), + clearAllUsersData: (cardTitle?: string) => clearAllUsersData( + pluginName, + cardTitle, + ), }; pluginApi.getRemoteData = ( dataSourceName: string, diff --git a/src/learning-analytics-dashboard/enums.ts b/src/learning-analytics-dashboard/enums.ts index cc3f098f..e229c343 100644 --- a/src/learning-analytics-dashboard/enums.ts +++ b/src/learning-analytics-dashboard/enums.ts @@ -2,4 +2,5 @@ export enum LearningAnalyticsDashboardEvents { GENERIC_DATA_SENT = 'GENERIC_DATA_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', UPSERT_USER_DATA_COMMAND_SENT = 'UPSERT_USER_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', DELETE_USER_DATA_COMMAND_SENT = 'DELETE_USER_DATA_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', + CLEAR_ALL_USERS_DATA_COMMAND_SENT = 'CLEAR_ALL_USERS_DATA_COMMAND_SENT_COMMAND_FOR_LEARNING_ANALYTICS_DASHBOARD_SENT', } diff --git a/src/learning-analytics-dashboard/hooks.ts b/src/learning-analytics-dashboard/hooks.ts index 1485b661..c7bf6b2b 100644 --- a/src/learning-analytics-dashboard/hooks.ts +++ b/src/learning-analytics-dashboard/hooks.ts @@ -64,14 +64,16 @@ export const deleteUserData = ( export const clearAllUsersData = ( pluginName: string, + cardTitle?: string, ) => { window.dispatchEvent( new CustomEvent< ClearLearningAnalyticsDashboardEventDetails>( - LearningAnalyticsDashboardEvents.DELETE_USER_DATA_COMMAND_SENT, + LearningAnalyticsDashboardEvents.CLEAR_ALL_USERS_DATA_COMMAND_SENT, { detail: { pluginName, + cardTitle, }, }, ), diff --git a/src/learning-analytics-dashboard/types.ts b/src/learning-analytics-dashboard/types.ts index cb666d8b..139e93cc 100644 --- a/src/learning-analytics-dashboard/types.ts +++ b/src/learning-analytics-dashboard/types.ts @@ -31,7 +31,7 @@ export type DeleteUserDataFunction = ( targetUserId?: string, ) => void; -export type ClearUsersDataFunction = () => void; +export type ClearUsersDataFunction = (cardTitle?: string) => void; // General typing. export interface LearningAnalyticsDashboardEventDetails { @@ -43,6 +43,7 @@ export interface LearningAnalyticsDashboardEventDetails { export interface ClearLearningAnalyticsDashboardEventDetails { pluginName: string; + cardTitle?: string; } export interface LearningAnalyticsDashboardWrapperObject { @@ -64,7 +65,6 @@ export interface LearningAnalyticsDashboardWrapperObject { deleteUserData: DeleteUserDataFunction; /** * Clears all Users Data for a specific plugin. (No arguments required) - * */ clearAllUsersData: ClearUsersDataFunction; } From 87c9a26bf420cf289978676b5315c4c5b8c55dac Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Thu, 7 Aug 2025 17:16:49 -0300 Subject: [PATCH 06/22] [lad-new-functions-plugin] updated documentation --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f90ac235..6ecb9419 100644 --- a/README.md +++ b/README.md @@ -464,6 +464,7 @@ It's an object available in the `pluginApi` that wraps those 2 functions: - `pluginApi.learningAnalyticsDashboard.upsertUserData` - `pluginApi.learningAnalyticsDashboard.deleteUserData` +- `pluginApi.learningAnalyticsDashboard.clearAllUsersData` For the `upsert` function, the argument's data object structure must be: @@ -484,7 +485,9 @@ interface LearningAnalyticsDashboardDeleteUserData { } ``` -And if the user is a moderator, there is the possibility to publish data on behalf of other users by using the second **optional** parameter named `targetUserId` +For the `clearAllUsersData` function, the argument is the cardTitle (optionally), and when it's not sent, all the entries for a specific plugin will be deleted. (And if the card ends up empty, it will be removed) + +If the user is a moderator, there is the possibility to publish data on behalf of other users by using the second **optional** parameter named `targetUserId` So that the data will appear in the following form: @@ -513,6 +516,10 @@ pluginApi.learningAnalyticsDashboard.deleteUserData( }, targetUserId, ); + +pluginApi.learningAnalyticsDashboard.clearAllUsersData(columnTitle); + +pluginApi.learningAnalyticsDashboard.clearAllUsersData(); // Or without the Column Title ``` Note 1: the `value` field (in the upsert function's argument) supports markdown, so feel free to use it as you wish. From 884cb80930aa95eb2012499c6fdc8a6f2837016e Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 20 Aug 2025 11:54:27 -0300 Subject: [PATCH 07/22] [lad-new-functions-plugin] rename hooks file to commands file. --- src/core/api/BbbPluginSdk.ts | 2 +- src/learning-analytics-dashboard/{hooks.ts => commands.ts} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/learning-analytics-dashboard/{hooks.ts => commands.ts} (100%) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index c7d3f948..3fe568fa 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -51,7 +51,7 @@ import { deleteUserData, sendGenericDataForLearningAnalyticsDashboard, upsertUserData, -} from '../../learning-analytics-dashboard/hooks'; +} from '../../learning-analytics-dashboard/commands'; import { GenericDataForLearningAnalyticsDashboard } from '../../learning-analytics-dashboard/types'; import { getRemoteData } from '../../remote-data/utils'; import { persistEventFunctionWrapper } from '../../event-persistence/hooks'; diff --git a/src/learning-analytics-dashboard/hooks.ts b/src/learning-analytics-dashboard/commands.ts similarity index 100% rename from src/learning-analytics-dashboard/hooks.ts rename to src/learning-analytics-dashboard/commands.ts From 5c0bef6ca3a00430f7d53459dd6eacbd9b0a63f4 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Mon, 3 Nov 2025 13:47:06 -0300 Subject: [PATCH 08/22] [new-logger-structure] added new logger structure set by the client to have more possibilities of configurations --- README.md | 2 +- package-lock.json | 222 +++++++++++++----- .../sample-data-channel-plugin/manifest.json | 18 +- .../component.tsx | 2 +- .../sample-data-channel-plugin/src/index.tsx | 4 + src/core/api/BbbPluginSdk.ts | 5 + src/core/api/types.ts | 26 ++ 7 files changed, 216 insertions(+), 63 deletions(-) diff --git a/README.md b/README.md index 3b3baddb..94e25e3c 100644 --- a/README.md +++ b/README.md @@ -350,7 +350,7 @@ The data-channel name must be in the `manifest.json` along with all the permissi { "name": "channel-name", "pushPermission": ["moderator","presenter"], - "replaceOrDeletePermission": ["moderator", "sender"] + "replaceOrDeletePermission": ["moderator", "creator"] } ] } diff --git a/package-lock.json b/package-lock.json index 57ea56af..41a8d95f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -376,13 +376,12 @@ } }, "node_modules/@playwright/test": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.51.1.tgz", - "integrity": "sha512-nM+kEaTSAoVlXmMPH10017vn3FSiFqr/bh4fKg9vmAdMfd9SDqRZNvPSiAHADc/itWak+qPvMPZQOPwCBW7k7Q==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.56.1.tgz", + "integrity": "sha512-vSMYtL/zOcFpvJCW71Q/OEGQb7KYBPAdKh35WNSkaZA75JlAO8ED8UN6GUNTm3drWomcbcqRPFqQbLae8yBTdg==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright": "1.51.1" + "playwright": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -976,10 +975,13 @@ "license": "MIT" }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -997,14 +999,13 @@ } }, "node_modules/axios": { - "version": "1.8.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz", - "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", + "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", "dev": true, - "license": "MIT", "dependencies": { "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", + "form-data": "^4.0.4", "proxy-from-env": "^1.1.0" } }, @@ -1066,13 +1067,18 @@ } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", "dev": true, "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1092,6 +1098,22 @@ "node": ">= 0.4" } }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", @@ -1289,6 +1311,23 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", @@ -2137,12 +2176,18 @@ } }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/form-data": { @@ -2446,12 +2491,12 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2864,16 +2909,12 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -2894,6 +2935,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -3633,13 +3680,12 @@ } }, "node_modules/playwright": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.51.1.tgz", - "integrity": "sha512-kkx+MB2KQRkyxjYPc3a0wLZZoDczmppyGJIvQ43l+aZihkaVvmu/21kiyaHeHjiFxjxNNFnUncKmcGIyOojsaw==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.56.1.tgz", + "integrity": "sha512-aFi5B0WovBHTEvpM3DzXTUaeN6eN0qWnTkKx4NQaH4Wvcmc153PdaY2UBdSYKaGYw+UyWXSVyxDUg5DoPEttjw==", "dev": true, - "license": "Apache-2.0", "dependencies": { - "playwright-core": "1.51.1" + "playwright-core": "1.56.1" }, "bin": { "playwright": "cli.js" @@ -3652,11 +3698,10 @@ } }, "node_modules/playwright-core": { - "version": "1.51.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.51.1.tgz", - "integrity": "sha512-/crRMj8+j/Nq5s8QcvegseuyeZPxpQCZb6HNk3Sos3BlZyAknRjoyJPFWkpNn8v0+P3WiwqFF8P+zQo4eqiNuw==", + "version": "1.56.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.56.1.tgz", + "integrity": "sha512-hutraynyn31F+Bifme+Ps9Vq59hKuUCz7H1kDOcBs+2oGguKkWTU50bBWrtz34OUWmIwpBTWDxaRPXrIXkgvmQ==", "dev": true, - "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" }, @@ -3673,6 +3718,15 @@ "semver-compare": "^1.0.0" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -3976,18 +4030,41 @@ "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/sha.js": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", - "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "version": "2.4.12", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz", + "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==", "dev": true, - "license": "(MIT AND BSD-3-Clause)", "dependencies": { - "inherits": "^2.0.1", - "safe-buffer": "^5.0.1" + "inherits": "^2.0.4", + "safe-buffer": "^5.2.1", + "to-buffer": "^1.2.0" }, "bin": { "sha.js": "bin.js" + }, + "engines": { + "node": ">= 0.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/shebang-command": { @@ -4247,6 +4324,20 @@ "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", "dev": true }, + "node_modules/to-buffer": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz", + "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==", + "dev": true, + "dependencies": { + "isarray": "^2.0.5", + "safe-buffer": "^5.2.1", + "typed-array-buffer": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4311,6 +4402,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/typed-array-length": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", @@ -4409,17 +4514,18 @@ } }, "node_modules/which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" diff --git a/samples/sample-data-channel-plugin/manifest.json b/samples/sample-data-channel-plugin/manifest.json index e4431be4..839c2930 100644 --- a/samples/sample-data-channel-plugin/manifest.json +++ b/samples/sample-data-channel-plugin/manifest.json @@ -1,13 +1,25 @@ { "requiredSdkVersion": "~0.0.59", "name": "SampleDataChannelPlugin", + "version": "0.0.8-beta1", "javascriptEntrypointUrl": "SampleDataChannelPlugin.js", "localesBaseUrl": "https://cdn.dominio.com/pluginabc/", - "dataChannels":[ + "loggerSettings": { + "console": { + "level": "error" + } + }, + "dataChannels": [ { "name": "public-channel", - "pushPermission": ["moderator","presenter"], - "replaceOrDeletePermission": ["moderator", "sender"] + "pushPermission": [ + "moderator", + "presenter" + ], + "replaceOrDeletePermission": [ + "moderator", + "creator" + ] } ] } diff --git a/samples/sample-data-channel-plugin/src/components/sample-data-channel-plugin-item/component.tsx b/samples/sample-data-channel-plugin/src/components/sample-data-channel-plugin-item/component.tsx index 371a528c..d68bd062 100644 --- a/samples/sample-data-channel-plugin/src/components/sample-data-channel-plugin-item/component.tsx +++ b/samples/sample-data-channel-plugin/src/components/sample-data-channel-plugin-item/component.tsx @@ -4,9 +4,9 @@ import { useEffect } from 'react'; import { BbbPluginSdk, PluginApi, ActionButtonDropdownOption, RESET_DATA_CHANNEL, DataChannelTypes, - pluginLogger, } from 'bigbluebutton-html-plugin-sdk'; import { SampleDataChannelPluginProps } from './types'; +import { pluginLogger } from '../..'; interface DataExampleType { first_example_field: number; diff --git a/samples/sample-data-channel-plugin/src/index.tsx b/samples/sample-data-channel-plugin/src/index.tsx index 643762d8..f254e277 100644 --- a/samples/sample-data-channel-plugin/src/index.tsx +++ b/samples/sample-data-channel-plugin/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleDataChannelPlugin from './components/sample-data-channel-plugin-item/component'; @@ -7,6 +8,9 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; const root = ReactDOM.createRoot(document.getElementById(uuid)); + +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + root.render( { }, }, getSessionToken: () => getSessionToken(), + logger: pluginLogger, pluginName, localesBaseUrl, }; } + if (!window.bbb_plugins[uuid].logger) { + window.bbb_plugins[uuid].logger = pluginLogger; + } return window.bbb_plugins[uuid]; } diff --git a/src/core/api/types.ts b/src/core/api/types.ts index 48a66821..6af176c7 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -1,3 +1,4 @@ +import { Logger } from 'browser-bunyan'; import { UiCommands } from '../../ui-commands/types'; import { UseChatMessageDomElementsFunction } from '../../dom-element-manipulation/chat/message/types'; import { ActionButtonDropdownInterface } from '../../extensible-areas/action-button-dropdown-item/types'; @@ -308,6 +309,30 @@ export interface PluginApi { * */ persistEvent?: PersistEventFunction; + /** + * Function used to log in the console. + */ + logger: Logger; +} + +export interface Console { + enabled: boolean + level: string +} + +export interface External { + enabled: boolean + level: string + url: string + method: string + throttleInterval: number + flushOnClose: boolean + logTag: string +} + +export interface ClientLog { + console: Console + external: External } export interface MeetingClientSettings { @@ -315,6 +340,7 @@ export interface MeetingClientSettings { app: { bbbWebBase: string; } + clientLog: ClientLog; } } From 453398590bd2a2ec638db877452c7a6490d71031 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Mon, 3 Nov 2025 15:44:27 -0300 Subject: [PATCH 09/22] [new-logger-structure] changed logger used in the samples --- .../component.tsx | 3 +- .../src/index.tsx | 3 + .../sample-actions-bar-plugin/src/index.tsx | 3 + .../sample-actions-bar-plugin/component.tsx | 3 +- .../src/index.tsx | 3 + .../component.tsx | 3 +- .../component.tsx | 2 +- .../src/index.tsx | 3 + .../component.tsx | 2 +- .../src/index.tsx | 3 + samples/sample-nav-bar-plugin/src/index.tsx | 3 + .../sample-nav-bar-plugin-item/component.tsx | 2 +- .../src/index.tsx | 3 + .../component.tsx | 2 +- .../user-aggregator-query/component.tsx | 2 +- .../component.tsx | 2 +- .../src/index.tsx | 3 + .../src/index.tsx | 3 + .../src/index.tsx | 3 + .../component.tsx | 4 +- samples/sample-ui-events-plugin/src/index.tsx | 3 + .../component.tsx | 2 +- samples/sample-use-meeting/src/index.tsx | 3 + .../src/sample-use-meeting/component.tsx | 4 +- .../src/index.tsx | 3 + .../component.tsx | 4 +- .../src/index.tsx | 3 + .../component.tsx | 4 +- .../src/index.tsx | 3 + .../component.tsx | 78 +++++++++---------- .../locale-messages/useLocaleMessages.ts | 2 +- 31 files changed, 106 insertions(+), 58 deletions(-) diff --git a/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx b/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx index 1f01a1ec..7d11f64f 100644 --- a/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx +++ b/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx @@ -5,10 +5,11 @@ import { PluginApi, ActionButtonDropdownSeparator, ActionButtonDropdownOption, - pluginLogger, ChangeEnforcedLayoutTypeEnum, } from 'bigbluebutton-html-plugin-sdk'; +import { pluginLogger } from '../../index'; + import { SampleActionButtonDropdownPluginProps } from './types'; export interface DataExampleType { diff --git a/samples/sample-action-button-dropdown-plugin/src/index.tsx b/samples/sample-action-button-dropdown-plugin/src/index.tsx index b5620cac..c78cb9e2 100644 --- a/samples/sample-action-button-dropdown-plugin/src/index.tsx +++ b/samples/sample-action-button-dropdown-plugin/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleActionButtonDropdownPlugin from './components/sample-action-button-dropdown-plugin/component'; @@ -6,6 +7,8 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); diff --git a/samples/sample-ui-events-plugin/src/index.tsx b/samples/sample-ui-events-plugin/src/index.tsx index c9aa5b06..25f5e69b 100644 --- a/samples/sample-ui-events-plugin/src/index.tsx +++ b/samples/sample-ui-events-plugin/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUiEventsPlugin from './sample-ui-events-plugin-item/component'; @@ -6,6 +7,8 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); const userListOpened = pluginApi diff --git a/samples/sample-use-meeting/src/index.tsx b/samples/sample-use-meeting/src/index.tsx index 89c8531d..602abca0 100644 --- a/samples/sample-use-meeting/src/index.tsx +++ b/samples/sample-use-meeting/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUseMeetingPlugin from './sample-use-meeting/component'; @@ -6,6 +7,8 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); const meetingInfoGraphqlResponse = pluginApi.useMeeting(); diff --git a/samples/sample-user-camera-dropdown-plugin/src/index.tsx b/samples/sample-user-camera-dropdown-plugin/src/index.tsx index db8382cb..f6182b85 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/index.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUserCameraDropdownPlugin from './sample-user-camera-dropdown-plugin-item/component'; @@ -6,6 +7,8 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); diff --git a/samples/sample-user-camera-helper-plugin/src/index.tsx b/samples/sample-user-camera-helper-plugin/src/index.tsx index f30f5044..3d5c3026 100644 --- a/samples/sample-user-camera-helper-plugin/src/index.tsx +++ b/samples/sample-user-camera-helper-plugin/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUserCameraHelperPlugin from './sample-user-camera-helper-plugin/component'; @@ -6,6 +7,8 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { + React.ReactElement { BbbPluginSdk.initialize(uuid); const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid); diff --git a/samples/sample-user-list-dropdown-plugin/src/index.tsx b/samples/sample-user-list-dropdown-plugin/src/index.tsx index 7c312f31..47801395 100644 --- a/samples/sample-user-list-dropdown-plugin/src/index.tsx +++ b/samples/sample-user-list-dropdown-plugin/src/index.tsx @@ -1,3 +1,4 @@ +import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUserListDropdownPlugin from './sample-user-list-dropdown-plugin-item/component'; @@ -6,6 +7,8 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; +export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); + const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { if (loadedUserList !== undefined && loadedUserList.length > 0) { const listOfInformationToSend: - Array = loadedUserList.map( - (user) => { - const buttonToUserListItem: - UserListDropdownInterface = new UserListDropdownFixedContentInformation({ - label: 'Warning test', - iconRight: 'warning', - userId: user.userId, - textColor: 'red', - allowed: true, - }); - return buttonToUserListItem as UserListDropdownInterface; - }, - ); + Array = loadedUserList.map( + (user) => { + const buttonToUserListItem: + UserListDropdownInterface = new UserListDropdownFixedContentInformation({ + label: 'Warning test', + iconRight: 'warning', + userId: user.userId, + textColor: 'red', + allowed: true, + }); + return buttonToUserListItem as UserListDropdownInterface; + }, + ); const listOfOptionsToSend: - Array = loadedUserList.map( - (user) => { - const buttonToUserListItem: - UserListDropdownInterface = new UserListDropdownOption({ - label: 'Click to log something in the console', - icon: 'user', - userId: user.userId, - tooltip: 'This will log something in the console', - allowed: true, - onClick: () => { - pluginLogger.info('Log from sample user-list-dropdown-plugin'); - }, - }); - return buttonToUserListItem as UserListDropdownInterface; - }, - ); + Array = loadedUserList.map( + (user) => { + const buttonToUserListItem: + UserListDropdownInterface = new UserListDropdownOption({ + label: 'Click to log something in the console', + icon: 'user', + userId: user.userId, + tooltip: 'This will log something in the console', + allowed: true, + onClick: () => { + pluginLogger.info('Log from sample user-list-dropdown-plugin'); + }, + }); + return buttonToUserListItem as UserListDropdownInterface; + }, + ); const listOfDropdownsToSend: - Array = loadedUserList.map( - (user) => { - const dropdownToUserListItem: - UserListDropdownInterface = new UserListDropdownSeparator({ - userId: user.userId, - }); - return dropdownToUserListItem as UserListDropdownInterface; - }, - ); + Array = loadedUserList.map( + (user) => { + const dropdownToUserListItem: + UserListDropdownInterface = new UserListDropdownSeparator({ + userId: user.userId, + }); + return dropdownToUserListItem as UserListDropdownInterface; + }, + ); pluginApi.setUserListDropdownItems( [...listOfInformationToSend, ...listOfDropdownsToSend, ...listOfOptionsToSend], ); diff --git a/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts b/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts index 15dfb56a..51f88181 100644 --- a/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts +++ b/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts @@ -1,11 +1,11 @@ import { useEffect, useState } from 'react'; -import { pluginLogger } from '../../../../utils'; import { IntlMessages, UseLocaleMessagesProps } from './types'; import { fetchLocaleAndStore, mergeLocaleMessages, useGetNormalizedLocale } from './utils'; function useLocaleMessagesAuxiliary( { pluginApi, fetchConfigs }: UseLocaleMessagesProps, ): IntlMessages { + const { logger: pluginLogger } = pluginApi; const [loading, setLoading] = useState(true); const [messages, setMessages] = useState>({}); const [fallbackMessages, setFallbackMessages] = useState>(); From 72b438d5bb38a1bbd00f9f973f7d5435238c21f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Mon, 10 Nov 2025 11:44:22 -0300 Subject: [PATCH 10/22] feat: Add nameSortable in the UsersBasicInfo data hook --- src/data-consumption/domain/users/users-basic-info/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data-consumption/domain/users/users-basic-info/types.ts b/src/data-consumption/domain/users/users-basic-info/types.ts index 66b427e7..0c3ab971 100644 --- a/src/data-consumption/domain/users/users-basic-info/types.ts +++ b/src/data-consumption/domain/users/users-basic-info/types.ts @@ -4,6 +4,7 @@ export interface UsersBasicInfoData { userId: string; extId: string; name: string; + nameSortable: string; /** * @deprecated use {@link isModerator} instead */ From 1db3e625b0c44718fc41f9685461e166b0fbc579 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 12 Nov 2025 13:23:55 -0300 Subject: [PATCH 11/22] [new-logger-structure] created exported singleton logger that proxies all methods to that defined by the pluginApi logger --- .../component.tsx | 3 +- .../src/index.tsx | 3 - src/core/api/BbbPluginSdk.ts | 4 -- src/utils/logger/logger.ts | 58 ++++++++++++++++++- 4 files changed, 56 insertions(+), 12 deletions(-) diff --git a/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx b/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx index 7d11f64f..1f01a1ec 100644 --- a/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx +++ b/samples/sample-action-button-dropdown-plugin/src/components/sample-action-button-dropdown-plugin/component.tsx @@ -5,11 +5,10 @@ import { PluginApi, ActionButtonDropdownSeparator, ActionButtonDropdownOption, + pluginLogger, ChangeEnforcedLayoutTypeEnum, } from 'bigbluebutton-html-plugin-sdk'; -import { pluginLogger } from '../../index'; - import { SampleActionButtonDropdownPluginProps } from './types'; export interface DataExampleType { diff --git a/samples/sample-action-button-dropdown-plugin/src/index.tsx b/samples/sample-action-button-dropdown-plugin/src/index.tsx index c78cb9e2..b5620cac 100644 --- a/samples/sample-action-button-dropdown-plugin/src/index.tsx +++ b/samples/sample-action-button-dropdown-plugin/src/index.tsx @@ -1,4 +1,3 @@ -import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleActionButtonDropdownPlugin from './components/sample-action-button-dropdown-plugin/component'; @@ -7,8 +6,6 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; -export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); - const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( ; + +function logWith(level: T, ...args: LoggerArgument[]): void { + const logger = getLogger(); + const method = logger[level] as (...params: LoggerArgument[]) => void; + + try { + method.call(logger, ...args); + } catch (err) { + console.error(`[pluginLogger.${String(level)}] fallback`, err, ...args); + } +} + +const pluginLogger = { + error: (...args: LoggerArgument[]) => logWith('error', ...args), + warn: (...args: LoggerArgument[]) => logWith('warn', ...args), + info: (...args: LoggerArgument[]) => logWith('info', ...args), + debug: (...args: LoggerArgument[]) => logWith('debug', ...args), + trace: (...args: LoggerArgument[]) => logWith('trace', ...args), + addStream(stream: StreamOptions) { + const logger = getLogger(); + logger.addStream.call(logger, stream); + }, +} as Logger; + export default pluginLogger; From aafeaadd94ae40e59b18720b7144c6c3e3018c3a Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 12 Nov 2025 13:39:21 -0300 Subject: [PATCH 12/22] [new-logger-structure] restore previous way of importing logger --- samples/sample-actions-bar-plugin/src/index.tsx | 3 --- .../src/sample-actions-bar-plugin/component.tsx | 2 +- samples/sample-audio-settings-dropdown-plugin/src/index.tsx | 3 --- .../src/sample-audio-settings-dropdown-plugin/component.tsx | 3 +-- .../sample-camera-settings-dropdown-plugin-item/component.tsx | 2 +- samples/sample-camera-settings-dropdown-plugin/src/index.tsx | 3 --- .../component.tsx | 2 +- samples/sample-custom-subscription-hook/src/index.tsx | 3 --- .../components/sample-data-channel-plugin-item/component.tsx | 2 +- samples/sample-data-channel-plugin/src/index.tsx | 4 ---- samples/sample-nav-bar-plugin/src/index.tsx | 3 --- .../src/sample-nav-bar-plugin-item/component.tsx | 2 +- samples/sample-options-dropdown-plugin/src/index.tsx | 3 --- .../src/sample-options-dropdown-plugin-item/component.tsx | 2 +- .../user-aggregator-query/component.tsx | 2 +- .../sample-presentation-dropdown-plugin/component.tsx | 2 +- samples/sample-presentation-dropdown-plugin/src/index.tsx | 3 --- samples/sample-presentation-toolbar-plugin/src/index.tsx | 3 --- samples/sample-screenshare-helper-plugin/src/index.tsx | 3 --- .../src/sample-screenshare-helper-plugin/component.tsx | 2 +- samples/sample-ui-events-plugin/src/index.tsx | 3 --- samples/sample-use-meeting/src/index.tsx | 3 --- .../sample-use-meeting/src/sample-use-meeting/component.tsx | 2 +- samples/sample-user-camera-dropdown-plugin/src/index.tsx | 3 --- .../src/sample-user-camera-dropdown-plugin-item/component.tsx | 2 +- samples/sample-user-camera-helper-plugin/src/index.tsx | 3 --- .../src/sample-user-camera-helper-plugin/component.tsx | 2 +- samples/sample-user-list-dropdown-plugin/src/index.tsx | 3 --- .../src/sample-user-list-dropdown-plugin-item/component.tsx | 2 +- 29 files changed, 14 insertions(+), 61 deletions(-) diff --git a/samples/sample-actions-bar-plugin/src/index.tsx b/samples/sample-actions-bar-plugin/src/index.tsx index c44d2d5b..04402997 100644 --- a/samples/sample-actions-bar-plugin/src/index.tsx +++ b/samples/sample-actions-bar-plugin/src/index.tsx @@ -1,4 +1,3 @@ -import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleActionsBarPlugin from './sample-actions-bar-plugin/component'; @@ -7,8 +6,6 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; -export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); - const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { diff --git a/samples/sample-ui-events-plugin/src/index.tsx b/samples/sample-ui-events-plugin/src/index.tsx index 25f5e69b..c9aa5b06 100644 --- a/samples/sample-ui-events-plugin/src/index.tsx +++ b/samples/sample-ui-events-plugin/src/index.tsx @@ -1,4 +1,3 @@ -import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUiEventsPlugin from './sample-ui-events-plugin-item/component'; @@ -7,8 +6,6 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; -export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); - const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { diff --git a/samples/sample-user-camera-dropdown-plugin/src/index.tsx b/samples/sample-user-camera-dropdown-plugin/src/index.tsx index f6182b85..db8382cb 100644 --- a/samples/sample-user-camera-dropdown-plugin/src/index.tsx +++ b/samples/sample-user-camera-dropdown-plugin/src/index.tsx @@ -1,4 +1,3 @@ -import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUserCameraDropdownPlugin from './sample-user-camera-dropdown-plugin-item/component'; @@ -7,8 +6,6 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; -export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); - const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { diff --git a/samples/sample-user-camera-helper-plugin/src/index.tsx b/samples/sample-user-camera-helper-plugin/src/index.tsx index 3d5c3026..f30f5044 100644 --- a/samples/sample-user-camera-helper-plugin/src/index.tsx +++ b/samples/sample-user-camera-helper-plugin/src/index.tsx @@ -1,4 +1,3 @@ -import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUserCameraHelperPlugin from './sample-user-camera-helper-plugin/component'; @@ -7,8 +6,6 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; -export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); - const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( { diff --git a/samples/sample-user-list-dropdown-plugin/src/index.tsx b/samples/sample-user-list-dropdown-plugin/src/index.tsx index 47801395..7c312f31 100644 --- a/samples/sample-user-list-dropdown-plugin/src/index.tsx +++ b/samples/sample-user-list-dropdown-plugin/src/index.tsx @@ -1,4 +1,3 @@ -import { BbbPluginSdk } from 'bigbluebutton-html-plugin-sdk'; import * as React from 'react'; import * as ReactDOM from 'react-dom/client'; import SampleUserListDropdownPlugin from './sample-user-list-dropdown-plugin-item/component'; @@ -7,8 +6,6 @@ const uuid = document.currentScript?.getAttribute('uuid') || 'root'; const pluginName = document.currentScript?.getAttribute('pluginName') || 'plugin'; -export const { logger: pluginLogger } = BbbPluginSdk.getPluginApi(uuid); - const root = ReactDOM.createRoot(document.getElementById(uuid)); root.render( Date: Wed, 12 Nov 2025 14:39:37 -0300 Subject: [PATCH 13/22] [new-logger-structure] resolve multiple runs of setLogger when new renders --- src/core/api/BbbPluginSdk.ts | 2 -- src/core/api/types.ts | 2 +- .../plugin-information/locale-messages/useLocaleMessages.ts | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 22c02332..52bf5f38 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -56,7 +56,6 @@ import { useCustomQuery } from '../../data-consumption/domain/shared/custom-quer import { UseCustomQueryFunction } from '../../data-consumption/domain/shared/custom-query/types'; import { useCustomMutation } from '../../data-creation/hook'; import { UseCustomMutationFunction } from '../../data-creation/types'; -import pluginLogger from '../../utils/logger/logger'; declare const window: PluginBrowserWindow; @@ -203,7 +202,6 @@ export abstract class BbbPluginSdk { '': () => { }, }, getSessionToken: () => getSessionToken(), - logger: pluginLogger, pluginName, localesBaseUrl, }; diff --git a/src/core/api/types.ts b/src/core/api/types.ts index 6af176c7..b34a4b11 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -312,7 +312,7 @@ export interface PluginApi { /** * Function used to log in the console. */ - logger: Logger; + logger?: Logger; } export interface Console { diff --git a/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts b/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts index 51f88181..15dfb56a 100644 --- a/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts +++ b/src/core/auxiliary/plugin-information/locale-messages/useLocaleMessages.ts @@ -1,11 +1,11 @@ import { useEffect, useState } from 'react'; +import { pluginLogger } from '../../../../utils'; import { IntlMessages, UseLocaleMessagesProps } from './types'; import { fetchLocaleAndStore, mergeLocaleMessages, useGetNormalizedLocale } from './utils'; function useLocaleMessagesAuxiliary( { pluginApi, fetchConfigs }: UseLocaleMessagesProps, ): IntlMessages { - const { logger: pluginLogger } = pluginApi; const [loading, setLoading] = useState(true); const [messages, setMessages] = useState>({}); const [fallbackMessages, setFallbackMessages] = useState>(); From 77d17a772cb8c9a2b53d7ed459286c78ebfa9a72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Victor?= Date: Wed, 12 Nov 2025 16:04:24 -0300 Subject: [PATCH 14/22] feat(plugin): Add bot in the UsersBasicInfo data hook --- src/data-consumption/domain/users/users-basic-info/types.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/data-consumption/domain/users/users-basic-info/types.ts b/src/data-consumption/domain/users/users-basic-info/types.ts index 0c3ab971..5ae21780 100644 --- a/src/data-consumption/domain/users/users-basic-info/types.ts +++ b/src/data-consumption/domain/users/users-basic-info/types.ts @@ -5,6 +5,7 @@ export interface UsersBasicInfoData { extId: string; name: string; nameSortable: string; + bot: boolean; /** * @deprecated use {@link isModerator} instead */ From df90ab3083eea76717bee5664474aa7ec13ecc37 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Thu, 13 Nov 2025 10:22:51 -0300 Subject: [PATCH 15/22] [technical-docs] added examples and a more technical documentation --- README.md | 1007 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 991 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 3b3baddb..2eab1855 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ by the BigBlueButton HTML5 client to extend its functionalities. An overview of the plugin architecture and capabilities can be found [here](https://github.com/bigbluebutton/plugins/blob/main/README.md#capabilities-and-technical-details). +For comprehensive documentation including architecture details, please refer to the [official BigBlueButton plugins documentation](https://docs.bigbluebutton.org/plugins/). + ## Examples A variety of example implementations to manipulate different parts of the BBB client can be found in the [`samples`](samples) folder. @@ -115,21 +117,23 @@ In this case, the your manifest URL will be `https:///plugins/sampleA ### Manifest Json -Here is as complete `manifest.json` example with all possible configurations: +Here is a complete `manifest.json` example with all possible configurations: ```json { "requiredSdkVersion": "~0.0.59", "name": "MyPlugin", + "version": "1.0.0", "javascriptEntrypointUrl": "MyPlugin.js", - "localesBaseUrl": "https://cdn.domain.com/my-plugin/", // Optional - "dataChannels":[ + "javascriptEntrypointIntegrity": "sha384-Bwsz2rxm...", + "localesBaseUrl": "https://cdn.domain.com/my-plugin/", + "dataChannels": [ { "name": "public-channel", "pushPermission": ["moderator","presenter"], // "moderator","presenter", "all" "replaceOrDeletePermission": ["moderator", "creator"] // "moderator", "presenter","all", "creator" } - ], // One can enable more data-channels to better organize client communication + ], "eventPersistence": { "isEnabled": true, // By default it is not enabled }, @@ -141,6 +145,9 @@ Here is as complete `manifest.json` example with all possible configurations: "permissions": ["moderator", "viewer"] } ], + "serverCommandsPermission": { + "chat.sendCustomPublicChatMessage": ["presenter", "moderator"] + }, "settingsSchema": [ { "name": "myJson", @@ -155,6 +162,39 @@ Here is as complete `manifest.json` example with all possible configurations: } ``` +**Manifest field descriptions:** + +| Field | Required | Description | +|-------|----------|-------------| +| `requiredSdkVersion` | Yes | Specifies the SDK version compatibility (e.g., `~0.0.59`) | +| `name` | Yes | Plugin name as referenced in configuration | +| `version` | No | Plugin version for cache-busting (appends `?version=X` to JS URL) | +| `javascriptEntrypointUrl` | Yes | URL to the main JavaScript bundle | +| `javascriptEntrypointIntegrity` | No | Subresource Integrity (SRI) hash for security | +| `localesBaseUrl` | No | Base URL for internationalization locale files | +| `dataChannels` | No | Array of data channels for inter-client communication | +| `eventPersistence` | No | Configuration for persisting events to meeting recording | +| `remoteDataSources` | No | External API endpoints for fetching data | +| `serverCommandsPermission` | No | Role-based permissions for server commands | +| `settingsSchema` | No | Configuration schema for plugin settings | + +**Possible values for permissions:** +- `pushPermission`: `"moderator"`, `"presenter"`, `"all"`, `"viewer"` +- `replaceOrDeletePermission`: `"moderator"`, `"presenter"`, `"all"`, `"viewer"`, `"creator"` +- `serverCommandsPermission`: `"moderator"`, `"presenter"`, `"all"`, `"viewer"` +- `remoteDataSources.permissions`: `"moderator"`, `"viewer"`, `"presenter"` + +**Possible values for fetchMode:** +- `"onMeetingCreate"`: Fetch once when meeting is created and cache the result +- `"onDemand"`: Fetch every time the plugin requests the data + +**Possible values for settingsSchema.type:** +- `"int"`: Integer number +- `"float"`: Floating-point number +- `"string"`: Text string +- `"boolean"`: True/false value +- `"json"`: JSON object + To better understand remote-data-sources, please, refer to [this section](#external-data-resources) **settingsSchema:** @@ -227,12 +267,229 @@ That being said, here are the extensible areas we have so far: Mind that no plugin will interfere into another's extensible area. So feel free to set whatever you need into a certain plugin with no worries. -### Auxiliary functions: +**Example usage for different extensible areas:** + +```typescript +BbbPluginSdk.initialize(pluginUuid); +const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + +useEffect(() => { + // 1. Action Bar Items (bottom toolbar) + pluginApi.setActionsBarItems([ + new ActionsBarButton({ + icon: { iconName: 'user' }, + tooltip: 'My custom action', + onClick: () => pluginLogger.info('Action bar button clicked'), + position: ActionsBarPosition.RIGHT, + }), + new ActionsBarSeparator({ + position: ActionsBarPosition.RIGHT, + }), + ]); + + // 2. Action Button Dropdown Items (three dots menu in action bar) + pluginApi.setActionButtonDropdownItems([ + new ActionButtonDropdownSeparator(), + new ActionButtonDropdownOption({ + label: 'Custom dropdown option', + icon: 'copy', + tooltip: 'This is a custom option', + onClick: () => pluginLogger.info('Dropdown option clicked'), + }), + ]); + + // 3. Options Dropdown Items (three dots menu in top-right) + pluginApi.setOptionsDropdownItems([ + new OptionsDropdownSeparator(), + new OptionsDropdownOption({ + label: 'Plugin Settings', + icon: 'settings', + onClick: () => pluginLogger.info('Options clicked'), + }), + ]); + + // 4. Nav Bar Items (top navigation bar) + pluginApi.setNavBarItems([ + new NavBarButton({ + icon: 'user', + label: 'Custom Nav Button', + tooltip: 'Navigate to custom area', + position: NavBarItemPosition.RIGHT, + onClick: () => pluginLogger.info('Nav button clicked'), + hasSeparator: true, + }), + new NavBarInfo({ + label: 'Plugin Active', + position: NavBarItemPosition.CENTER, + hasSeparator: false, + }), + ]); + + // 5. Presentation Toolbar Items (presentation controls) + pluginApi.setPresentationToolbarItems([ + new PresentationToolbarButton({ + label: 'Custom Tool', + tooltip: 'Use custom presentation tool', + onClick: () => pluginLogger.info('Presentation tool clicked'), + }), + new PresentationToolbarSeparator(), + ]); + + // 6. User List Dropdown Items (per-user menu) + pluginApi.setUserListDropdownItems([ + new UserListDropdownSeparator(), + new UserListDropdownOption({ + label: 'View Profile', + icon: 'user', + onClick: (userId) => { + pluginLogger.info('View profile for user:', userId); + }, + }), + ]); + + // 7. Audio Settings Dropdown Items + pluginApi.setAudioSettingsDropdownItems([ + new AudioSettingsDropdownOption({ + label: 'Audio Plugin Settings', + icon: 'settings', + onClick: () => pluginLogger.info('Audio settings clicked'), + }), + ]); + + // 8. Camera Settings Dropdown Items + pluginApi.setCameraSettingsDropdownItems([ + new CameraSettingsDropdownOption({ + label: 'Camera Plugin Settings', + icon: 'video', + onClick: () => pluginLogger.info('Camera settings clicked'), + }), + ]); + + // 9. Floating Window + pluginApi.setFloatingWindows([ + new FloatingWindow({ + top: 100, + left: 100, + width: 400, + height: 300, + movable: true, + resizable: true, + backgroundColor: '#ffffff', + boxShadow: '0 4px 12px rgba(0,0,0,0.15)', + contentFunction: (element: HTMLElement) => { + const root = ReactDOM.createRoot(element); + root.render( +
+

Custom Floating Window

+

This is custom plugin content!

+
+ ); + return root; + }, + }), + ]); + + // 10. Generic Content Sidekick Area + pluginApi.setGenericContentItems([ + new GenericContentSidekickArea({ + id: 'my-plugin-content', + name: 'Plugin Content', + section: 'Custom Section', + buttonIcon: 'copy', + open: false, + contentFunction: (element: HTMLElement) => { + const root = ReactDOM.createRoot(element); + root.render( +
+

Sidekick Content

+

Custom sidekick panel content here!

+
+ ); + return root; + }, + }), + ]); + + // 11. User List Item Additional Information + pluginApi.setUserListItemAdditionalInformation([ + new UserListItemAdditionalInformation({ + userId: 'specific-user-id', // or use a function to determine dynamically + label: 'VIP', + icon: 'star', + }), + ]); + + // 12. Presentation Dropdown Items + pluginApi.setPresentationDropdownItems([ + new PresentationDropdownOption({ + label: 'Export Presentation', + icon: 'download', + onClick: () => pluginLogger.info('Export presentation clicked'), + }), + ]); + + // 13. User Camera Dropdown Items + pluginApi.setUserCameraDropdownItems([ + new UserCameraDropdownOption({ + label: 'Camera Effects', + icon: 'video', + displayFunction: ({ userId }) => { + // Show only for specific users or conditions + return true; + }, + onClick: ({ userId, streamId }) => { + pluginLogger.info('Camera option clicked:', userId, streamId); + }, + }), + ]); + +}, []); + +``` + +**Key Points:** +- Each extensible area has its own setter function (e.g., `setActionsBarItems`, `setOptionsDropdownItems`) +- Items are set as arrays, allowing multiple items per area +- Use separators to visually group related items +- Items from different plugins won't conflict - each plugin manages its own items +- Most items support icons, labels, tooltips, and onClick handlers +- Some items support positioning (LEFT, CENTER, RIGHT) or display conditions + +### Auxiliary functions - `getSessionToken`: returns the user session token located on the user's URL. - `getJoinUrl`: returns the join url associated with the parameters passed as an argument. Since it fetches the BigBlueButton API, this getter method is asynchronous. - `useLocaleMessages`: returns the messages to be used in internationalization functions (recommend to use `react-intl`, as example, refer to official plugins) +**Example usage:** + +```typescript +BbbPluginSdk.initialize(pluginUuid); +const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + +// Get session token +const sessionToken = pluginApi.getSessionToken(); +console.log('Session token:', sessionToken); + +// Get join URL (async) +useEffect(() => { + pluginApi.getJoinUrl({ + fullName: 'John Doe', + role: 'MODERATOR', + // other join parameters... + }).then((joinUrl) => { + console.log('Join URL:', joinUrl); + }); +}, []); + +// Use locale messages for internationalization +const localeMessages = pluginApi.useLocaleMessages(); +console.log('Current locale:', localeMessages); + +return null; + +``` + ### Realtime data consumption - `useCurrentPresentation` hook: provides information regarding the current presentation; @@ -257,6 +514,87 @@ export interface GraphqlResponseWrapper { So we have the `data`, which is different for each hook, that's why it's a generic, the error, that will be set if, and only if, there is an error, otherwise it is undefined, and loading, which tells the developer if the query is still loading (being fetched) or not. +**Example usage:** + +```typescript + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + // Get current user information + const { data: currentUser, loading: userLoading, error: userError } = + pluginApi.useCurrentUser(); + + // Get meeting information + const { data: meeting, loading: meetingLoading } = pluginApi.useMeeting(); + + // Get current presentation + const { data: presentation } = pluginApi.useCurrentPresentation(); + + // Get all users basic info + const { data: usersBasicInfo } = pluginApi.useUsersBasicInfo(); + + // Get loaded chat messages + const { data: chatMessages } = pluginApi.useLoadedChatMessages(); + + // Get talking indicators + const { data: talkingIndicators } = pluginApi.useTalkingIndicator(); + + // Get plugin settings + const { data: pluginSettings } = pluginApi.usePluginSettings(); + + useEffect(() => { + if (currentUser && !userLoading) { + pluginLogger.info('Current user:', currentUser); + pluginLogger.info('User is presenter:', currentUser.presenter); + pluginLogger.info('User is moderator:', currentUser.isModerator); + } + if (userError) { + pluginLogger.error('Error fetching user:', userError); + } + }, [currentUser, userLoading, userError]); + + useEffect(() => { + if (meeting) { + pluginLogger.info('Meeting ID:', meeting.meetingId); + pluginLogger.info('Meeting name:', meeting.name); + } + }, [meeting]); + + useEffect(() => { + if (presentation) { + pluginLogger.info('Current page:', presentation.currentPage?.num); + pluginLogger.info('Total pages:', presentation.totalPages); + } + }, [presentation]); + + useEffect(() => { + if (chatMessages) { + pluginLogger.info('Total messages:', chatMessages.length); + chatMessages.forEach((msg) => { + pluginLogger.info(`Message from ${msg.senderName}: ${msg.message}`); + }); + } + }, [chatMessages]); + + // Custom subscription example + const { data: customData } = pluginApi.useCustomSubscription(` + subscription MyCustomSubscription { + user { + userId + name + role + } + } + `); + + useEffect(() => { + if (customData) { + pluginLogger.info('Custom subscription data:', customData); + } + }, [customData]); + +``` + ### Realtime Data Creation **`useCustomMutation` Hook** @@ -421,7 +759,7 @@ One other thing is that the type of the return is precisely the same type requir - volume: - set: this function will set the external video volume to a certain number between 0 and 1 (that is 0% and); - layout: - - changeEnforcedLayout: (deprecated) Changes the enforced layout + - changeEnforcedLayout: (deprecated) Changes the enforced layout - setEnforcedLayout: Sets the enforced layout - navBar: - setDisplayNavBar: Sets the displayNavBar to true (show it) or false (hide it). @@ -444,23 +782,71 @@ One other thing is that the type of the return is precisely the same type requir - close: this function will close the sidekick options panel automatically (and also the sidebar content if open, to avoid inconsistencies in ui); - user-status: - setAwayStatus: this function will set the away status of the user to a certain status; -See usage ahead: -```ts - pluginApi.uiCommands.chat.form.open(); - pluginApi.uiCommands.chat.form.fill({ - text: 'Just an example message filled by the plugin', - }); +**Example usage:** + +```typescript + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + useEffect(() => { + // Open and fill chat form + pluginApi.uiCommands.chat.form.open(); + pluginApi.uiCommands.chat.form.fill({ + text: 'Just an example message filled by the plugin', + }); + + // Set speaker volume to 50% + pluginApi.uiCommands.conference.setSpeakerLevel(0.5); + + // Set external video volume to 75% + pluginApi.uiCommands.externalVideo.volume.set(0.75); + + // Change layout + pluginApi.uiCommands.layout.setEnforcedLayout('FOCUS'); + + // Show/hide nav bar + pluginApi.uiCommands.navBar.setDisplayNavBar(false); + + // Send a notification + pluginApi.uiCommands.notification.send({ + type: 'info', + message: 'This is a notification from the plugin', + icon: 'user', + }); + + // Open presentation area + pluginApi.uiCommands.presentationArea.open(); + + // Sidekick area commands + pluginApi.uiCommands.sidekickArea.options.setMenuBadge('my-content-id', '5'); + pluginApi.uiCommands.sidekickArea.options.renameGenericContentMenu( + 'my-content-id', + 'New Menu Name' + ); + pluginApi.uiCommands.sidekickArea.options.renameGenericContentSection( + 'my-content-id', + 'New Section Name' + ); + + // Camera commands + pluginApi.uiCommands.camera.setSelfViewDisableAllDevices(true); + pluginApi.uiCommands.camera.setSelfViewDisable('camera-stream-id', false); + + // Set away status + pluginApi.uiCommands.userStatus.setAwayStatus(true); + }, []); + ``` So the idea is that we have a `uiCommands` object and at a point, there will be the command to do the intended action, such as open the chat form and/or fill it, as demonstrated above ### Server Commands - + `serverCommands` object: It contains all the possible commands available to the developer to interact with the BBB core server, see the ones implemented down below: - + - chat: - - sendPublicMessage: This function sends a message to the public chat on behalf of the currently logged-in user. + - sendPublicChatMessage: This function sends a message to the public chat on behalf of the currently logged-in user. - sendCustomPublicMessage: This function sends a text message to the public chat, optionally including custom metadata. > **Note**: The custom messages sent by plugins are not automatically rendered by the client. To display these messages, a plugin must handle the rendering using `useLoadedChatMessages` and `useChatMessageDomElements`. @@ -469,11 +855,192 @@ So the idea is that we have a `uiCommands` object and at a point, there will be - save: this function saves the given text, locale and caption type - addLocale: this function sends a locale to be added to the available options +**Example usage:** + +```typescript + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + useEffect(() => { + // Add a button that sends a chat message + pluginApi.setActionButtonDropdownItems([ + new ActionButtonDropdownOption({ + label: 'Send chat message', + icon: 'chat', + onClick: () => { + // Send a public chat message + pluginApi.serverCommands.chat.sendPublicChatMessage({ + textMessageInMarkdownFormat: 'Hello from plugin!', + pluginCustomMetadata: pluginUuid, + }); + }, + }), + new ActionButtonDropdownOption({ + label: 'Send custom message', + icon: 'copy', + onClick: () => { + // Send a custom public chat message with metadata + pluginApi.serverCommands.chat.sendCustomPublicMessage({ + textMessageInMarkdownFormat: '**Custom message** with metadata', + pluginCustomMetadata: { + type: 'notification', + pluginId: pluginUuid, + timestamp: Date.now(), + }, + }); + }, + }), + new ActionButtonDropdownOption({ + label: 'Save caption', + icon: 'closed_caption', + onClick: () => { + // Save a caption + pluginApi.serverCommands.caption.save({ + text: 'This is a caption text', + locale: 'en-US', + captionType: 'TYPED', + }); + }, + }), + new ActionButtonDropdownOption({ + label: 'Add caption locale', + icon: 'closed_caption', + onClick: () => { + // Add a new locale option for captions + pluginApi.serverCommands.caption.addLocale({ + locale: 'pt-BR', + localeName: 'Portuguese (Brazil)', + }); + }, + }), + ]); + }, []); + +``` + +**Note on permissions:** Some server commands have permission controls based on roles defined in the manifest. See the [Manifest Json](#manifest-json) section for configuration details. + ### Dom Element Manipulation - `useChatMessageDomElements` hook: This hook will return the dom element of a chat message reactively, so one can modify whatever is inside, such as text, css, js, etc.; - `useUserCameraDomElements` hook: This hook will return the dom element of each of the user's webcam corresponding to the streamIds passed reactively, so one can modify whatever is inside, such as text, css, js, etc., and also can get the video element within it; +**Example usage:** + +```typescript + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + const [chatIdsToHighlight, setChatIdsToHighlight] = useState([]); + const [streamIdsToStyle, setStreamIdsToStyle] = useState([]); + + // Example 1: Manipulate chat messages (highlight mentions) + const { data: chatMessages } = pluginApi.useLoadedChatMessages(); + + useEffect(() => { + if (chatMessages) { + // Filter messages that mention someone with @ pattern + const MENTION_REGEX = /@([A-Z][a-z]+ ){0,2}[A-Z][a-z]+/; + const messageIds = chatMessages + .filter((msg) => MENTION_REGEX.test(msg.message)) + .map((msg) => msg.messageId); + setChatIdsToHighlight(messageIds); + } + }, [chatMessages]); + + // Get DOM elements for the chat messages we want to manipulate + const chatMessagesDomElements = pluginApi.useChatMessageDomElements(chatIdsToHighlight); + + useEffect(() => { + if (chatMessagesDomElements && chatMessagesDomElements.length > 0) { + chatMessagesDomElements.forEach((chatMessageDomElement) => { + const MENTION_REGEX = /@([A-Z][a-z]+ ){0,2}[A-Z][a-z]+/; + const mention = chatMessageDomElement.innerHTML.match(MENTION_REGEX); + + if (mention) { + // Highlight the mention with custom styling + chatMessageDomElement.innerHTML = chatMessageDomElement.innerHTML.replace( + mention[0], + `${mention[0]}` + ); + } + + // Style the parent element + const { parentElement } = chatMessageDomElement; + if (parentElement) { + parentElement.style.paddingTop = '0.5rem'; + parentElement.style.paddingBottom = '0.5rem'; + parentElement.style.borderLeft = '3px solid #4185cf'; + parentElement.style.backgroundColor = '#f8f9fa'; + } + + pluginLogger.info('Styled chat message:', chatMessageDomElement); + }); + } + }, [chatMessagesDomElements]); + + // Example 2: Manipulate user camera streams + const { data: videoStreams } = pluginApi.useCustomSubscription(` + subscription VideoStreams { + user_camera { + streamId + user { + userId + name + } + } + } + `); + + useEffect(() => { + if (videoStreams?.user_camera) { + // Get all stream IDs + const streamIds = videoStreams.user_camera.map((stream) => stream.streamId); + setStreamIdsToStyle(streamIds); + } + }, [videoStreams]); + + // Get DOM elements for user cameras + const userCameraDomElements = pluginApi.useUserCameraDomElements(streamIdsToStyle); + + useEffect(() => { + if (userCameraDomElements && userCameraDomElements.length > 0) { + userCameraDomElements.forEach((cameraElement) => { + // Add a custom border to the camera + cameraElement.element.style.border = '3px solid #0c5cb3'; + cameraElement.element.style.borderRadius = '8px'; + cameraElement.element.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)'; + + // Access the video element directly + if (cameraElement.videoElement) { + cameraElement.videoElement.style.objectFit = 'cover'; + pluginLogger.info('Styled video element for stream:', cameraElement.streamId); + } + + // Add a custom overlay + const overlay = document.createElement('div'); + overlay.style.position = 'absolute'; + overlay.style.top = '5px'; + overlay.style.right = '5px'; + overlay.style.backgroundColor = 'rgba(0, 0, 0, 0.7)'; + overlay.style.color = 'white'; + overlay.style.padding = '4px 8px'; + overlay.style.borderRadius = '4px'; + overlay.style.fontSize = '12px'; + overlay.textContent = '🎥 Live'; + cameraElement.element.style.position = 'relative'; + cameraElement.element.appendChild(overlay); + }); + } + }, [userCameraDomElements]); +``` + +**Important notes:** +- Use DOM manipulation carefully and only when necessary +- Always check if elements exist before manipulating them +- Prefer using the provided hooks over direct DOM queries +- Be aware that excessive DOM manipulation can impact performance +- When styling chat messages, avoid changing the actual text content as it may cause issues with recordings for more information on that, see [guidelines section](https://docs.bigbluebutton.org/plugins/#dom-element-manipulation-guidelines) + ### Learning Analytics Dashboard integration - `sendGenericDataForLearningAnalyticsDashboard`: This function will send data for the bbb to render inside the plugin's table @@ -494,6 +1061,80 @@ So that the data will appear in the following form: | --- | :-- | --: | | user-name | 1 | `` | +**Example usage:** + +```typescript + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + const [interactionCount, setInteractionCount] = useState(0); + + // Example: Track user interactions and send to Learning Analytics Dashboard + useEffect(() => { + const handleUserInteraction = () => { + const newCount = interactionCount + 1; + setInteractionCount(newCount); + + // Send data to Learning Analytics Dashboard + pluginApi.sendGenericDataForLearningAnalyticsDashboard({ + cardTitle: 'User Interactions', // For future use + columnTitle: 'Total Clicks', + value: newCount.toString(), + }); + + pluginLogger.info('Sent interaction data to dashboard:', newCount); + }; + + // Example: Track button clicks + pluginApi.setActionButtonDropdownItems([ + new ActionButtonDropdownOption({ + label: 'Track Interaction', + icon: 'user', + onClick: handleUserInteraction, + }), + ]); + }, [interactionCount]); + + // Example: Send engagement metrics periodically + useEffect(() => { + const interval = setInterval(() => { + const engagementScore = Math.floor(Math.random() * 100); + + pluginApi.sendGenericDataForLearningAnalyticsDashboard({ + cardTitle: 'Engagement Metrics', + columnTitle: 'Engagement Score', + value: `${engagementScore}%`, + }); + + pluginLogger.info('Sent engagement score:', engagementScore); + }, 60000); // Every minute + + return () => clearInterval(interval); + }, []); + + // Example: Track specific plugin events + const { data: chatMessages } = pluginApi.useLoadedChatMessages(); + + useEffect(() => { + if (chatMessages) { + const messageCount = chatMessages.length; + + pluginApi.sendGenericDataForLearningAnalyticsDashboard({ + cardTitle: 'Chat Activity', + columnTitle: 'Messages Sent', + value: messageCount.toString(), + }); + } + }, [chatMessages]); + +``` + +**Use cases for Learning Analytics:** +- Track user participation and engagement +- Monitor plugin-specific metrics (e.g., poll responses, quiz answers) +- Measure feature usage and adoption +- Collect custom learning indicators +- Generate post-meeting reports with plugin data + ### External data resources @@ -549,12 +1190,167 @@ pluginApi.getRemoteData('allUsers').then((response: Response) => { }); ``` -### Meta_ parameters +### Fetch ui data on demand + +- `getUiData` async function: This will return certain data from the UI depending on the parameter the developer uses. Unlike the `useUiData` this function does not return real-time information as it changes. See the currently supported: + - PresentationWhiteboardUiDataNames.CURRENT_PAGE_SNAPSHOT; + +**Example usage:** + +```typescript + BbbPluginSdk.initialize(pluginUuid); + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + useEffect(() => { + pluginApi.setActionButtonDropdownItems([ + new ActionButtonDropdownOption({ + label: 'Capture whiteboard snapshot', + icon: 'copy', + onClick: async () => { + // Fetch the current whiteboard page as a PNG snapshot + const snapshotData = await pluginApi.getUiData( + PresentationWhiteboardUiDataNames.CURRENT_PAGE_SNAPSHOT + ); + + if (snapshotData?.pngBase64) { + console.log('Whiteboard snapshot (base64 PNG):', snapshotData.pngBase64); + + // Example: Download the snapshot + const link = document.createElement('a'); + link.href = `data:image/png;base64,${snapshotData.pngBase64}`; + link.download = `whiteboard-snapshot-${Date.now()}.png`; + link.click(); + } + }, + }), + ]); + }, []); + +``` + +### Customize manifest.json + +The following sections explain how you can dynamically customize your manifest.json for different runs. + +#### Meta_ parameters This is not part of the API, but it's a way of passing information to the manifest. Any value can be passed like this, one just needs to put something like `${meta_nameOfParameter}` in a specific config of the manifest, and in the `/create` call, set this meta-parameter to whatever is preferred, like `meta_nameOfParameter="Sample message"` This feature is mainly used for security purposes, see [external data section](#external-data-resources). But can be used for customization reasons as well. +**Example:** + +```json +{ + "requiredSdkVersion": "~0.0.59", + "name": "MyPlugin", + "javascriptEntrypointUrl": "MyPlugin.js", + "remoteDataSources": [ + { + "name": "userData", + "url": "${meta_userDataEndpoint}", + "fetchMode": "onMeetingCreate", + "permissions": ["moderator", "viewer"] + } + ] +} +``` + +Then in the `/create` call: + +``` +meta_userDataEndpoint=https://my-api.com/users +pluginManifests=[{"url": "https://my-cdn.com/my-plugin/manifest.json"}] +``` + +#### Plugin_ parameters + +`plugin_` parameters work similarly to `meta_` parameters, allowing data to be passed dynamically to the manifest. While they can serve the same purposes — like security or customization — they are specifically scoped to individual plugins. + +**Format:** + +``` +plugin__ +``` + +- `` — The name of the plugin as defined in `manifest.json`. +- `` — The parameter's name. It may include letters (uppercase or lowercase), numbers and hyphens (`-`). + +This naming convention ensures that each plugin has its own namespace for parameters. Other plugins cannot access values outside their own namespace. For example: + +``` +plugin_MyPlugin_api-endpoint=https://api.example.com +plugin_MyPlugin_theme-color=blue +``` + +This isolates the parameter to `MyPlugin` and avoids conflicts with other plugins. + +**Example manifest.json:** + +```json +{ + "requiredSdkVersion": "~0.0.59", + "name": "MyPlugin", + "javascriptEntrypointUrl": "MyPlugin.js", + "dataChannels": [ + { + "name": "${plugin_MyPlugin_channel-name:defaultChannel}", + "pushPermission": ["moderator", "presenter"], + "replaceOrDeletePermission": ["moderator", "creator"] + } + ], + "remoteDataSources": [ + { + "name": "pluginData", + "url": "${plugin_MyPlugin_api-endpoint}", + "fetchMode": "onDemand", + "permissions": ["moderator"] + } + ] +} +``` + +Then in the `/create` call: + +``` +plugin_MyPlugin_channel-name=customChannelName +plugin_MyPlugin_api-endpoint=https://my-api.com/plugin-data +pluginManifests=[{"url": "https://my-cdn.com/my-plugin/manifest.json"}] +``` + +#### Default value (fallback) for missing placeholder's parameters + +If a plugin expects a placeholder (via `meta_` or `plugin_`) but doesn't receive a value, the plugin will fail to load. To prevent this, both types of placeholders support default values. This allows the system administrator to define fallback values, ensuring the plugin loads correctly. + +**Example with a default value:** + +```json +{ + "requiredSdkVersion": "~0.0.59", + "name": "MyPlugin", + "javascriptEntrypointUrl": "MyPlugin.js", + "dataChannels": [ + { + "name": "${plugin_MyPlugin_data-channel-name:storeState}", + "pushPermission": ["moderator", "presenter"], + "replaceOrDeletePermission": ["moderator", "creator"] + } + ], + "remoteDataSources": [ + { + "name": "apiData", + "url": "${meta_apiEndpoint:https://default-api.com/data}", + "fetchMode": "onMeetingCreate", + "permissions": ["moderator"] + } + ] +} +``` + +In this example: +- If `plugin_MyPlugin_data-channel-name` is not provided, it will fall back to `"storeState"` +- If `meta_apiEndpoint` is not provided, it will fall back to `"https://default-api.com/data"` + ### Event persistence This feature will allow the developer to save an information (an event) in the `event.xml` file of the meeting, if it's being recorded. @@ -608,6 +1404,185 @@ Where `` is the id of the the meeting you just recorded. Then, among ``` +## Common Patterns and Best Practices + +This section covers common patterns and best practices for plugin development. + +### Plugin Initialization Pattern + +Always initialize your plugin in this order: + +```typescript +import { BbbPluginSdk, PluginApi } from 'bigbluebutton-html-plugin-sdk'; +import { useEffect } from 'react'; + +function MyPlugin({ pluginUuid }: MyPluginProps) { + // 1. Initialize the SDK (must be first) + BbbPluginSdk.initialize(pluginUuid); + + // 2. Get the plugin API instance + const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + // 3. Use hooks to fetch data + const { data: currentUser } = pluginApi.useCurrentUser(); + + // 4. Set up UI extensions in useEffect + useEffect(() => { + // Register UI items here + pluginApi.setActionButtonDropdownItems([...]); + }, []); // Empty dependency array for one-time setup + + // 5. Return null (plugins typically don't render directly) + return null; +} +``` + +### Error Handling Pattern + +```typescript +function MyPlugin({ pluginUuid }: MyPluginProps) { + BbbPluginSdk.initialize(pluginUuid); + const pluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + const { data, loading, error } = pluginApi.useCurrentUser(); + + useEffect(() => { + if (error) { + pluginLogger.error('Error fetching user data:', error); + // Show user-friendly notification + pluginApi.uiCommands.notification.send({ + type: 'error', + message: 'Failed to load plugin. Please refresh the page.', + icon: 'warning', + }); + return; + } + + if (loading) { + pluginLogger.info('Loading user data...'); + return; + } + + if (data) { + // Proceed with plugin logic + pluginLogger.info('User data loaded successfully'); + } + }, [data, loading, error]); + + return null; +} +``` + +### State Management Pattern + +```typescript +function MyPlugin({ pluginUuid }: MyPluginProps) { + BbbPluginSdk.initialize(pluginUuid); + const pluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + const [count, setCount] = useState(0); + const [isActive, setIsActive] = useState(false); + + useEffect(() => { + pluginApi.setActionButtonDropdownItems([ + new ActionButtonDropdownOption({ + label: `Counter: ${count}`, + icon: 'copy', + onClick: () => { + setCount(prevCount => prevCount + 1); + setIsActive(true); + }, + }), + ]); + }, [count]); // Re-render when count changes + + return null; +} +``` + +### Data Channel Communication Pattern + +```typescript +interface MessageType { + userId: string; + message: string; + timestamp: number; +} + +function MyPlugin({ pluginUuid }: MyPluginProps) { + BbbPluginSdk.initialize(pluginUuid); + const pluginApi = BbbPluginSdk.getPluginApi(pluginUuid); + + const { + data: messages, + pushEntry, + deleteEntry, + } = pluginApi.useDataChannel( + 'my-channel', + DataChannelTypes.ALL_ITEMS, + 'default' + ); + + const sendMessage = (text: string) => { + if (pushEntry) { + pushEntry({ + userId: 'current-user-id', + message: text, + timestamp: Date.now(), + }); + } + }; + + const clearMessages = () => { + if (deleteEntry) { + deleteEntry(RESET_DATA_CHANNEL); + } + }; + + useEffect(() => { + pluginApi.setActionButtonDropdownItems([ + new ActionButtonDropdownOption({ + label: 'Send Message', + icon: 'chat', + onClick: () => sendMessage('Hello!'), + }), + new ActionButtonDropdownOption({ + label: 'Clear Messages', + icon: 'delete', + onClick: clearMessages, + }), + ]); + }, []); + + useEffect(() => { + if (messages?.data) { + pluginLogger.info('Messages:', messages.data); + } + }, [messages]); + + return null; +} +``` + +### Best Practices + +1. **Always initialize the SDK first** before using any plugin API +2. **Use TypeScript** for type safety and better development experience +3. **Handle loading and error states** gracefully +4. **Clean up resources** (intervals, event listeners) in useEffect cleanup +5. **Use pluginLogger** instead of console.log for better debugging +6. **Test your plugin** with different user roles (moderator, presenter, viewer) +7. **Use the samples** as reference - they demonstrate best practices +8. **Document your plugin** - include a README with usage instructions + +### Performance Tips + +- **Minimize re-renders**: Use proper dependency arrays in useEffect +- **Avoid excessive DOM manipulation**: Use the provided hooks when possible +- **Debounce frequent operations**: Use debouncing for frequent UI updates +- **Clean up subscriptions**: Always return cleanup functions from useEffect +- **Use memoization**: Use React.useMemo and React.useCallback for expensive operations + + ### Frequently Asked Questions (FAQ) **How do I remove a certain extensible area that I don't want anymore?** From d9c9c9829cf1d209ac3f102450376e7c768a2cd4 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Thu, 20 Nov 2025 17:19:40 -0300 Subject: [PATCH 16/22] [zindex-floating-window] added z-index property into floating window constructor --- src/extensible-areas/floating-window/component.ts | 5 +++++ src/extensible-areas/floating-window/types.ts | 1 + 2 files changed, 6 insertions(+) diff --git a/src/extensible-areas/floating-window/component.ts b/src/extensible-areas/floating-window/component.ts index 6b86e76b..4810c782 100644 --- a/src/extensible-areas/floating-window/component.ts +++ b/src/extensible-areas/floating-window/component.ts @@ -19,6 +19,8 @@ export class FloatingWindow implements FloatingWindowInterface { boxShadow: string; + zIndex?: number; + contentFunction: (element: HTMLElement) => ReactDOM.Root; /** @@ -32,6 +34,7 @@ export class FloatingWindow implements FloatingWindowInterface { * @param movable - tells whether the floating window is movable or static. * @param backgroundColor - background color of the floating window. * @param boxShadow - box shadow to apply to the floating window + * @param zIndex - z-index of the floating window (Optional). * @param contentFunction - function that gives the html element to render the content of * the floating window. It must return the root element where the floating window was rendered. * @@ -44,6 +47,7 @@ export class FloatingWindow implements FloatingWindowInterface { movable, backgroundColor, boxShadow, + zIndex, contentFunction, }: FloatingWindowProps) { if (id) { @@ -54,6 +58,7 @@ export class FloatingWindow implements FloatingWindowInterface { this.movable = movable; this.backgroundColor = backgroundColor; this.boxShadow = boxShadow; + this.zIndex = zIndex; this.contentFunction = contentFunction; this.type = FloatingWindowType.CONTAINER; diff --git a/src/extensible-areas/floating-window/types.ts b/src/extensible-areas/floating-window/types.ts index ecb56732..746514e1 100644 --- a/src/extensible-areas/floating-window/types.ts +++ b/src/extensible-areas/floating-window/types.ts @@ -11,6 +11,7 @@ export interface FloatingWindowProps { movable: boolean; backgroundColor: string; boxShadow: string; + zIndex?: number; contentFunction: (element: HTMLElement) => ReactDOM.Root; } From b87085eef662d41af62946f6014757dcfc56f72e Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Tue, 9 Dec 2025 16:54:41 -0300 Subject: [PATCH 17/22] [use-meeting-data] added more fields to useMeeting and projection function --- src/core/api/BbbPluginSdk.ts | 3 + src/core/api/types.ts | 14 ++ src/data-consumption/domain/meeting/index.ts | 1 + .../domain/meeting/meeting-data/hooks.ts | 16 ++ .../domain/meeting/meeting-data/types.ts | 154 ++++++++++++++++++ src/data-consumption/enums.ts | 1 + src/data-consumption/factory/hooks.ts | 82 ++++++++++ src/data-consumption/factory/types.ts | 7 + src/data-consumption/factory/utils.ts | 11 ++ src/data-consumption/index.ts | 2 + 10 files changed, 291 insertions(+) create mode 100644 src/data-consumption/domain/meeting/meeting-data/hooks.ts create mode 100644 src/data-consumption/domain/meeting/meeting-data/types.ts create mode 100644 src/data-consumption/factory/hooks.ts create mode 100644 src/data-consumption/factory/types.ts create mode 100644 src/data-consumption/factory/utils.ts diff --git a/src/core/api/BbbPluginSdk.ts b/src/core/api/BbbPluginSdk.ts index 90d06ded..a7de443d 100644 --- a/src/core/api/BbbPluginSdk.ts +++ b/src/core/api/BbbPluginSdk.ts @@ -56,6 +56,8 @@ import { useCustomQuery } from '../../data-consumption/domain/shared/custom-quer import { UseCustomQueryFunction } from '../../data-consumption/domain/shared/custom-query/types'; import { useCustomMutation } from '../../data-creation/hook'; import { UseCustomMutationFunction } from '../../data-creation/types'; +import { UseMeetingDataFunction } from '../../data-consumption/domain/meeting/meeting-data/types'; +import { useMeetingData } from '../../data-consumption/domain/meeting/meeting-data/hooks'; declare const window: PluginBrowserWindow; @@ -98,6 +100,7 @@ export abstract class BbbPluginSdk { pluginApi.useLoadedUserList = (() => useLoadedUserList()) as UseLoadedUserListFunction; pluginApi.useCurrentUser = (() => useCurrentUser()) as UseCurrentUserFunction; pluginApi.useMeeting = (() => useMeeting()) as UseMeetingFunction; + pluginApi.useMeetingData = useMeetingData as UseMeetingDataFunction; pluginApi.useUsersBasicInfo = (() => useUsersBasicInfo()) as UseUsersBasicInfoFunction; pluginApi.useTalkingIndicator = (() => useTalkingIndicator()) as UseTalkingIndicatorFunction; pluginApi.getJoinUrl = (params) => getJoinUrl(params); diff --git a/src/core/api/types.ts b/src/core/api/types.ts index 48a66821..65172232 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -37,6 +37,7 @@ import { UseShouldUnmountPluginFunction } from '../auxiliary/plugin-unmount/type import { GetUiDataFunction } from '../../ui-data/getters/types'; import { UseCustomQueryFunction } from '../../data-consumption/domain/shared/custom-query/types'; import { UseCustomMutationFunction } from '../../data-creation/types'; +import { UseMeetingDataFunction } from '../../data-consumption/domain/meeting/meeting-data/types'; // Setter Functions for the API export type SetPresentationToolbarItems = (presentationToolbarItem: @@ -147,8 +148,21 @@ export interface PluginApi { * * @returns `GraphqlResponseWrapper` with the CurrentMeeting type. * + * @deprecated use {@link useMeetingData} + * */ useMeeting?: UseMeetingFunction; + /** + * Returns an object containing the data on the current meeting, i.e. the meeting on which the + * plugin is running. + * + * @param projectionFunction - function to select only specific fields from the + * Meeting type (Optional - if not provided, returns all fields). + * + * @returns `GraphqlResponseWrapper` with the CurrentMeeting type. + * + */ + useMeetingData?: UseMeetingDataFunction; /** * Returns an object containing the brief data on every user in te meeting. * diff --git a/src/data-consumption/domain/meeting/index.ts b/src/data-consumption/domain/meeting/index.ts index 0b68de78..c9321833 100644 --- a/src/data-consumption/domain/meeting/index.ts +++ b/src/data-consumption/domain/meeting/index.ts @@ -1 +1,2 @@ export { Meeting } from './from-core/types'; +export { MeetingData } from './meeting-data/types'; diff --git a/src/data-consumption/domain/meeting/meeting-data/hooks.ts b/src/data-consumption/domain/meeting/meeting-data/hooks.ts new file mode 100644 index 00000000..fa2ee282 --- /dev/null +++ b/src/data-consumption/domain/meeting/meeting-data/hooks.ts @@ -0,0 +1,16 @@ +import { DeepPartial } from '../../../../data-consumption/factory/types'; +import { useProjectedValue } from '../../../../data-consumption/factory/hooks'; +import { DataConsumptionHooks } from '../../../enums'; +import { createDataConsumptionHook } from '../../../factory/hookCreator'; +import { MeetingData } from './types'; + +export const useMeetingData = ( + projectionFunction?: (q: MeetingData) => DeepPartial, +) => useProjectedValue( + createDataConsumptionHook< + MeetingData + >( + DataConsumptionHooks.MEETING_DATA, + ), + projectionFunction, +); diff --git a/src/data-consumption/domain/meeting/meeting-data/types.ts b/src/data-consumption/domain/meeting/meeting-data/types.ts new file mode 100644 index 00000000..151896e0 --- /dev/null +++ b/src/data-consumption/domain/meeting/meeting-data/types.ts @@ -0,0 +1,154 @@ +import { DeepPartial } from '../../../../data-consumption/factory/types'; +import { GraphqlResponseWrapper } from '../../../../core'; + +export interface LockSettings { + disableCam: boolean; + disableMic: boolean; + disableNotes: boolean; + disablePrivateChat: boolean; + disablePublicChat: boolean; + hasActiveLockSetting: boolean; + hideUserList: boolean; + hideViewersCursor: boolean; + hideViewersAnnotation: false, + meetingId: boolean; + webcamsOnlyForModerator: boolean; +} + +export interface groups { + groupId: string; + name: string; +} + +export interface WelcomeSettings { + welcomeMsg: string; + welcomeMsgForModerators: string; + meetingId: string; +} + +export interface MeetingRecording { + isRecording: boolean; + startedAt: Date; + previousRecordedTimeInSeconds: number; + startedBy: string; + stoppedAt: number; + stoppedBy: string; +} +export interface MeetingRecordingPolicies { + allowStartStopRecording: boolean; + autoStartRecording: boolean; + record: boolean; + keepEvents: boolean; + startedAt: number; + startedBy: string; + stoppedAt: number; + stoppedBy: string; +} + +export interface UsersPolicies { + allowModsToEjectCameras: boolean; + allowModsToUnmuteUsers: boolean; + authenticatedGuest: boolean; + allowPromoteGuestToModerator: boolean; + guestPolicy: string; + maxUserConcurrentAccesses: number; + maxUsers: number; + meetingId: string; + meetingLayout: string; + userCameraCap: number; + webcamsOnlyForModerator: boolean; + guestLobbyMessage: string | null; +} + +export interface VoiceSettings { + dialNumber: string; + meetingId: string; + muteOnStart: boolean; + telVoice: string; + voiceConf: string; +} + +export interface BreakoutPolicies { + breakoutRooms: Array; + captureNotes: string; + captureNotesFilename: string; + captureSlides: string; + captureSlidesFilename: string; + freeJoin: boolean; + parentId: string; + privateChatEnabled: boolean; + record: boolean; + sequence: number; +} + +export interface BreakoutRoomsCommonProperties { + durationInSeconds: number; + freeJoin: boolean; + sendInvitationToModerators: boolean; + startedAt: Date; +} + +export interface ExternalVideo { + externalVideoId: string; + playerCurrentTime: number; + playerPlaybackRate: number; + playerPlaying: boolean; + externalVideoUrl: string; + startedSharingAt: number; + stoppedSharingAt: number; + updatedAt: string; +} + +export interface Layout { + currentLayoutType: string; +} + +export interface ComponentsFlags { + hasCaption: boolean; + hasBreakoutRoom: boolean; + hasExternalVideo: boolean; + hasPoll: boolean; + hasScreenshare: boolean; + hasTimer: boolean; + showRemainingTime: boolean; + hasCameraAsContent: boolean; + hasScreenshareAsContent: boolean; + hasCurrentPresentation: boolean; + hasSharedNotes: boolean; + isSharedNotesPinned: boolean; +} + +export interface MeetingData { + createdTime: number; + disabledFeatures: Array; + durationInSeconds: number; + extId: string; + isBreakout: boolean; + learningDashboardAccessToken: string; + maxPinnedCameras: number; + meetingCameraCap: number; + cameraBridge: string; + screenShareBridge: string; + audioBridge: string; + meetingId: string; + name: string; + notifyRecordingIsOn: boolean; + presentationUploadExternalDescription: string; + presentationUploadExternalUrl: string; + usersPolicies: UsersPolicies; + lockSettings: LockSettings; + voiceSettings: VoiceSettings; + breakoutPolicies: BreakoutPolicies; + breakoutRoomsCommonProperties: BreakoutRoomsCommonProperties; + externalVideo: ExternalVideo; + layout: Layout; + componentsFlags: ComponentsFlags; + endWhenNoModerator: boolean; + endWhenNoModeratorDelayInMinutes: number; + loginUrl: string | null; + groups: Array; +} + +export type UseMeetingDataFunction = ( + projectionFunction?: (q: MeetingData) => DeepPartial, +) => GraphqlResponseWrapper; diff --git a/src/data-consumption/enums.ts b/src/data-consumption/enums.ts index b8ed57f2..238ce3c1 100644 --- a/src/data-consumption/enums.ts +++ b/src/data-consumption/enums.ts @@ -5,6 +5,7 @@ export enum DataConsumptionHooks { USERS_BASIC_INFO = 'Hooks::UseUsersBasicInfo', LOADED_CHAT_MESSAGES = 'Hooks::UseLoadedChatMessages', MEETING = 'Hooks::UseMeeting', + MEETING_DATA = 'Hooks::UseMeetingData', TALKING_INDICATOR = 'Hooks::UseTalkingIndicator', CUSTOM_SUBSCRIPTION = 'Hooks::CustomSubscription', CUSTOM_QUERY = 'Hooks::CustomQuery', diff --git a/src/data-consumption/factory/hooks.ts b/src/data-consumption/factory/hooks.ts new file mode 100644 index 00000000..d88bd48c --- /dev/null +++ b/src/data-consumption/factory/hooks.ts @@ -0,0 +1,82 @@ +import { + useRef, + useMemo, + useEffect, + useState, +} from 'react'; +import { sortedStringify } from '../utils'; +import { GraphqlResponseWrapper } from '../../core'; +import { hasErrorChanged } from './utils'; +import { DeepPartial } from './types'; + +// Function overload for array type +export function useProjectedValue( + queryResult: GraphqlResponseWrapper, + project?: (q: TQueryResult) => DeepPartial, +): GraphqlResponseWrapper | GraphqlResponseWrapper[]>; +// Function overload for single value type +export function useProjectedValue( + queryResult: GraphqlResponseWrapper, + project?: (q: TQueryResult) => DeepPartial, +): GraphqlResponseWrapper | GraphqlResponseWrapper>; +// Implementation +export function useProjectedValue( + queryResult: GraphqlResponseWrapper, + project?: (q: TQueryResult) => DeepPartial, +): GraphqlResponseWrapper + | GraphqlResponseWrapper[] | DeepPartial> { + if (!project) return queryResult; + + const isArray = Array.isArray(queryResult.data); + + // Store the previous projected data to compare against + const previousProjectedDataRef = useRef< + DeepPartial[] | DeepPartial | undefined + >(undefined); + + // Compute the new projected value from the data field + const currentProjectedData = useMemo(() => { + if (!queryResult.data) return undefined; + if (isArray) { + return (queryResult.data as TQueryResult[]).map((item) => project(item)); + } + return project(queryResult.data as TQueryResult); + }, [queryResult.data, project, isArray]); + + // Initialize state with the wrapper structure + const [projectionResult, setProjectionResult] = useState< + GraphqlResponseWrapper[] | DeepPartial> + >({ + loading: queryResult.loading, + data: currentProjectedData, + error: queryResult.error, + }); + + useEffect(() => { + // Perform deep equality check using sortedStringify + const currentSerialized = sortedStringify(currentProjectedData); + const previousSerialized = sortedStringify(previousProjectedDataRef.current); + + // Check if loading or error states changed + const loadingChanged = queryResult.loading !== projectionResult.loading; + const errorChanged = hasErrorChanged(projectionResult.error, queryResult.error); + + // Only update if the projected data, loading, or error state has changed + if (currentSerialized !== previousSerialized || loadingChanged || errorChanged) { + previousProjectedDataRef.current = currentProjectedData; + setProjectionResult({ + loading: queryResult.loading, + data: currentProjectedData, + error: queryResult.error, + }); + } + }, [ + currentProjectedData, + queryResult.loading, + queryResult.error, + projectionResult.loading, + projectionResult.error, + ]); + + return projectionResult; +} diff --git a/src/data-consumption/factory/types.ts b/src/data-consumption/factory/types.ts new file mode 100644 index 00000000..1a58cf55 --- /dev/null +++ b/src/data-consumption/factory/types.ts @@ -0,0 +1,7 @@ +export type DeepPartial = { + [K in keyof T]?: T[K] extends (infer U)[] + ? DeepPartial[] + : T[K] extends object + ? DeepPartial + : T[K]; +}; diff --git a/src/data-consumption/factory/utils.ts b/src/data-consumption/factory/utils.ts new file mode 100644 index 00000000..0eacd4d0 --- /dev/null +++ b/src/data-consumption/factory/utils.ts @@ -0,0 +1,11 @@ +import { ApolloError } from '@apollo/client'; +import { sortedStringify } from '../utils'; + +export const hasErrorChanged = ( + previousResultError?: ApolloError, + currentResultError?: ApolloError, +) => { + const currentSerialized = sortedStringify(currentResultError); + const previousSerialized = sortedStringify(previousResultError); + return currentSerialized !== previousSerialized; +}; diff --git a/src/data-consumption/index.ts b/src/data-consumption/index.ts index 0a28ea66..410f4af5 100644 --- a/src/data-consumption/index.ts +++ b/src/data-consumption/index.ts @@ -4,3 +4,5 @@ export * from './domain/meeting'; export * from './domain/users'; export * from './domain/user-voice'; export * from './domain/shared'; + +export * from './factory/types'; From 98651f67ca82f955e817d1dfa8f1d9557dcc22f5 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 10 Dec 2025 17:45:45 -0300 Subject: [PATCH 18/22] [add-data-test] added data-tests to all extensible areas available to plugin-developers --- .../actions-bar-item/types.ts | 2 +- src/extensible-areas/base.ts | 1 + .../floating-window/component.ts | 4 +++ src/extensible-areas/floating-window/types.ts | 1 + .../generic-content-item/component.ts | 12 ++++++-- .../generic-content-item/types.ts | 2 ++ .../nav-bar-item/component.ts | 12 ++++++-- src/extensible-areas/nav-bar-item/types.ts | 2 ++ .../options-dropdown-item/component.ts | 13 ++++++-- .../options-dropdown-item/types.ts | 1 + .../presentation-dropdown-item/component.ts | 15 ++++++++-- .../presentation-dropdown-item/types.ts | 1 + .../screenshare-helper-item/component.ts | 6 +++- .../screenshare-helper-item/types.ts | 1 + .../user-camera-dropdown-item/component.ts | 13 ++++++-- .../user-camera-dropdown-item/types.ts | 2 ++ .../user-camera-helper-item/component.ts | 6 +++- .../user-camera-helper-item/types.ts | 1 + .../user-list-dropdown-item/component.ts | 30 +++++++++++++++---- .../user-list-dropdown-item/types.ts | 5 ++++ .../component.ts | 12 ++++++-- .../types.ts | 2 ++ 22 files changed, 123 insertions(+), 21 deletions(-) diff --git a/src/extensible-areas/actions-bar-item/types.ts b/src/extensible-areas/actions-bar-item/types.ts index 07b63888..6c8746f9 100644 --- a/src/extensible-areas/actions-bar-item/types.ts +++ b/src/extensible-areas/actions-bar-item/types.ts @@ -5,7 +5,7 @@ import { ActionsBarItemType, ActionsBarPosition } from './enums'; /** * Interface for the generic Actions bar item. (`position` is mandatory) */ -export interface ActionsBarInterface extends PluginProvidedUiItemDescriptor{ +export interface ActionsBarInterface extends PluginProvidedUiItemDescriptor { position: ActionsBarPosition; } diff --git a/src/extensible-areas/base.ts b/src/extensible-areas/base.ts index 91d637dc..e09df377 100644 --- a/src/extensible-areas/base.ts +++ b/src/extensible-areas/base.ts @@ -27,4 +27,5 @@ export interface PluginProvidedUiItemDescriptor { id: string; type: PluginProvidedUiItemType; setItemId: (id: string) => void; + dataTest?: string; } diff --git a/src/extensible-areas/floating-window/component.ts b/src/extensible-areas/floating-window/component.ts index 6b86e76b..1215f3c0 100644 --- a/src/extensible-areas/floating-window/component.ts +++ b/src/extensible-areas/floating-window/component.ts @@ -19,6 +19,8 @@ export class FloatingWindow implements FloatingWindowInterface { boxShadow: string; + dataTest?: string; + contentFunction: (element: HTMLElement) => ReactDOM.Root; /** @@ -45,6 +47,7 @@ export class FloatingWindow implements FloatingWindowInterface { backgroundColor, boxShadow, contentFunction, + dataTest, }: FloatingWindowProps) { if (id) { this.id = id; @@ -52,6 +55,7 @@ export class FloatingWindow implements FloatingWindowInterface { this.top = top; this.left = left; this.movable = movable; + this.dataTest = dataTest; this.backgroundColor = backgroundColor; this.boxShadow = boxShadow; diff --git a/src/extensible-areas/floating-window/types.ts b/src/extensible-areas/floating-window/types.ts index ecb56732..453dbe20 100644 --- a/src/extensible-areas/floating-window/types.ts +++ b/src/extensible-areas/floating-window/types.ts @@ -11,6 +11,7 @@ export interface FloatingWindowProps { movable: boolean; backgroundColor: string; boxShadow: string; + dataTest?: string; contentFunction: (element: HTMLElement) => ReactDOM.Root; } diff --git a/src/extensible-areas/generic-content-item/component.ts b/src/extensible-areas/generic-content-item/component.ts index 12170d36..9e0413dd 100644 --- a/src/extensible-areas/generic-content-item/component.ts +++ b/src/extensible-areas/generic-content-item/component.ts @@ -11,22 +11,26 @@ export class GenericContentMainArea implements GenericContentInterface { contentFunction: (element: HTMLElement) => ReactDOM.Root; + dataTest: string; + /** * Returns an object that when used in the setter as a generic content will be rendered * over the meeting main presentation. * * @param contentFunction - function that gives the html element to render the content of * the generic component + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, contentFunction, + id, contentFunction, dataTest = '', }: GenericContentMainAreaProps) { if (id) { this.id = id; } this.contentFunction = contentFunction; + this.dataTest = dataTest; this.type = GenericContentType.MAIN_AREA; } @@ -48,6 +52,8 @@ export class GenericContentSidekickArea implements GenericContentInterface { open: boolean = false; + dataTest: string; + contentFunction: (element: HTMLElement) => ReactDOM.Root; /** @@ -63,11 +69,12 @@ export class GenericContentSidekickArea implements GenericContentInterface { * displayed * @param buttonIcon - the icon of the associated sidebar navigation button * @param open - boolean value to decide wether to start open + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, contentFunction, name, section, buttonIcon, open, + id, contentFunction, name, section, buttonIcon, open, dataTest = '', }: GenericContentSidekickAreaProps) { if (id) { this.id = id; @@ -76,6 +83,7 @@ export class GenericContentSidekickArea implements GenericContentInterface { this.name = name; this.section = section; this.buttonIcon = buttonIcon; + this.dataTest = dataTest; this.type = GenericContentType.SIDEKICK_AREA; this.open = open; } diff --git a/src/extensible-areas/generic-content-item/types.ts b/src/extensible-areas/generic-content-item/types.ts index 46c05065..55d026a5 100644 --- a/src/extensible-areas/generic-content-item/types.ts +++ b/src/extensible-areas/generic-content-item/types.ts @@ -7,6 +7,7 @@ export interface GenericContentInterface extends PluginProvidedUiItemDescriptor export interface GenericContentMainAreaProps { id?: string; contentFunction: (element: HTMLElement) => ReactDOM.Root; + dataTest?: string; } export interface GenericContentSidekickAreaProps { @@ -16,4 +17,5 @@ export interface GenericContentSidekickAreaProps { section: string; buttonIcon: string; open: boolean; + dataTest?: string; } diff --git a/src/extensible-areas/nav-bar-item/component.ts b/src/extensible-areas/nav-bar-item/component.ts index e769f320..29c03dfc 100644 --- a/src/extensible-areas/nav-bar-item/component.ts +++ b/src/extensible-areas/nav-bar-item/component.ts @@ -19,6 +19,8 @@ export class NavBarButton implements NavBarInterface { disabled: boolean; + dataTest: string; + position: NavBarItemPosition; hasSeparator: boolean; @@ -38,11 +40,12 @@ export class NavBarButton implements NavBarInterface { * @param hasSeparator - boolean indicating whether the navigation bar button has separator * (vertical bar) * @param disabled - if true, the navigation bar button will not be clickable + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, label = '', icon = '', tooltip = '', disabled = true, onClick = () => {}, + id, label = '', icon = '', tooltip = '', disabled = true, dataTest = '', onClick = () => {}, position = NavBarItemPosition.RIGHT, hasSeparator = true, }: NavBarButtonProps) { if (id) { @@ -52,6 +55,7 @@ export class NavBarButton implements NavBarInterface { this.icon = icon; this.tooltip = tooltip; this.disabled = disabled; + this.dataTest = dataTest; this.onClick = onClick; this.type = NavBarItemType.BUTTON; this.hasSeparator = hasSeparator; @@ -70,6 +74,8 @@ export class NavBarInfo implements NavBarInterface { label: string; + dataTest: string; + hasSeparator: boolean; position: NavBarItemPosition; @@ -83,17 +89,19 @@ export class NavBarInfo implements NavBarInterface { * See {@link NavBarItemPosition} * @param hasSeparator - boolean indicating whether the navigation bar information has separator * (vertical bar) + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ id, label = '', position = NavBarItemPosition.RIGHT, - hasSeparator = true, + hasSeparator = true, dataTest = '', }: NavBarInfoProps) { if (id) { this.id = id; } this.label = label; + this.dataTest = dataTest; this.type = NavBarItemType.INFO; this.position = position; this.hasSeparator = hasSeparator; diff --git a/src/extensible-areas/nav-bar-item/types.ts b/src/extensible-areas/nav-bar-item/types.ts index 4952503b..737042f2 100644 --- a/src/extensible-areas/nav-bar-item/types.ts +++ b/src/extensible-areas/nav-bar-item/types.ts @@ -15,6 +15,7 @@ export interface NavBarButtonProps { hasSeparator: boolean; position: NavBarItemPosition; onClick: () => void; + dataTest?: string; } export interface NavBarInfoProps { @@ -22,4 +23,5 @@ export interface NavBarInfoProps { label: string; hasSeparator: boolean; position: NavBarItemPosition; + dataTest?: string; } diff --git a/src/extensible-areas/options-dropdown-item/component.ts b/src/extensible-areas/options-dropdown-item/component.ts index 20b0422c..08fe90c6 100644 --- a/src/extensible-areas/options-dropdown-item/component.ts +++ b/src/extensible-areas/options-dropdown-item/component.ts @@ -14,6 +14,8 @@ export class OptionsDropdownOption implements OptionsDropdownInterface { icon: string; + dataTest: string; + onClick: () => void; /** @@ -22,18 +24,20 @@ export class OptionsDropdownOption implements OptionsDropdownInterface { * * @param label - label to be displayed in the options dropdown option. * @param icon - icon to be displayed in the options dropdown. It goes in the left side of it. + * @param dataTest - string attribute to be used for testing * @param onClick - function to be called when clicking the option. * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, label = '', icon = '', onClick = () => {}, + id, label = '', icon = '', dataTest = '', onClick = () => {}, }: OptionsDropdownOptionProps) { if (id) { this.id = id; } this.label = label; this.icon = icon; + this.dataTest = dataTest; this.onClick = onClick; this.type = OptionsDropdownItemType.OPTION; } @@ -48,13 +52,18 @@ export class OptionsDropdownSeparator implements OptionsDropdownInterface { type: OptionsDropdownItemType; + dataTest: string; + /** * Returns object to be used in the setter for the Navigation Bar. In this case, * a separator. * + * @param dataTest - string attribute to be used for testing + * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ - constructor() { + constructor({ dataTest = '' } = {}) { + this.dataTest = dataTest; this.type = OptionsDropdownItemType.SEPARATOR; } diff --git a/src/extensible-areas/options-dropdown-item/types.ts b/src/extensible-areas/options-dropdown-item/types.ts index d4d8ffd5..c08bd3df 100644 --- a/src/extensible-areas/options-dropdown-item/types.ts +++ b/src/extensible-areas/options-dropdown-item/types.ts @@ -15,4 +15,5 @@ export interface OptionsDropdownOptionProps { label: string; icon: string; onClick: () => void; + dataTest?: string; } diff --git a/src/extensible-areas/presentation-dropdown-item/component.ts b/src/extensible-areas/presentation-dropdown-item/component.ts index 210c98e4..9ed50230 100644 --- a/src/extensible-areas/presentation-dropdown-item/component.ts +++ b/src/extensible-areas/presentation-dropdown-item/component.ts @@ -14,6 +14,8 @@ export class PresentationDropdownOption implements PresentationDropdownInterface icon: string; + dataTest: string; + onClick: () => void; /** @@ -23,18 +25,20 @@ export class PresentationDropdownOption implements PresentationDropdownInterface * @param label - label to be displayed in the presentation dropdown option. * @param icon - icon to be displayed in the presentation dropdown. * It goes in the left side of it. + * @param dataTest - string attribute to be used for testing * @param onClick - function to be called when clicking the option. * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, label = '', icon = '', onClick = () => {}, + id, label = '', icon = '', dataTest = '', onClick = () => {}, }: PresentationDropdownOptionProps) { if (id) { this.id = id; } this.label = label; this.icon = icon; + this.dataTest = dataTest; this.onClick = onClick; this.type = PresentationDropdownItemType.OPTION; } @@ -49,13 +53,18 @@ export class PresentationDropdownSeparator implements PresentationDropdownInterf type: PresentationDropdownItemType; + dataTest: string; + /** * Returns object to be used in the setter for the Presentation Dropdown. In this case, * a separator (horizontal thin black line). - + * + * @param dataTest - string attribute to be used for testing + * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ - constructor() { + constructor({ dataTest = '' } = {}) { + this.dataTest = dataTest; this.type = PresentationDropdownItemType.SEPARATOR; } diff --git a/src/extensible-areas/presentation-dropdown-item/types.ts b/src/extensible-areas/presentation-dropdown-item/types.ts index 1553528b..a5363a3c 100644 --- a/src/extensible-areas/presentation-dropdown-item/types.ts +++ b/src/extensible-areas/presentation-dropdown-item/types.ts @@ -15,4 +15,5 @@ export interface PresentationDropdownOptionProps { label: string; icon: string; onClick: () => void; + dataTest?: string; } diff --git a/src/extensible-areas/screenshare-helper-item/component.ts b/src/extensible-areas/screenshare-helper-item/component.ts index 01255aca..93bc9f3f 100644 --- a/src/extensible-areas/screenshare-helper-item/component.ts +++ b/src/extensible-areas/screenshare-helper-item/component.ts @@ -20,6 +20,8 @@ export class ScreenshareHelperButton implements ScreenshareHelperButtonInterface disabled: boolean; + dataTest: string; + position: ScreenshareHelperItemPosition; onClick: (args: ScreenshareHelperButtonOnclickCallback) => void; @@ -37,11 +39,12 @@ export class ScreenshareHelperButton implements ScreenshareHelperButtonInterface * @param hasSeparator - boolean indicating whether the screenshare helper button has separator * (vertical bar) * @param disabled - if true, the screenshare helper button will not be clickable + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, label = '', icon = '', tooltip = '', disabled = true, onClick = () => {}, + id, label = '', icon = '', tooltip = '', disabled = true, dataTest = '', onClick = () => {}, position = ScreenshareHelperItemPosition.TOP_RIGHT, }: ScreenshareHelperButtonProps) { if (id) { @@ -51,6 +54,7 @@ export class ScreenshareHelperButton implements ScreenshareHelperButtonInterface this.icon = icon; this.tooltip = tooltip; this.disabled = disabled; + this.dataTest = dataTest; this.onClick = onClick; this.type = ScreenshareHelperItemType.BUTTON; this.position = position; diff --git a/src/extensible-areas/screenshare-helper-item/types.ts b/src/extensible-areas/screenshare-helper-item/types.ts index 8f907e5c..6448c37f 100644 --- a/src/extensible-areas/screenshare-helper-item/types.ts +++ b/src/extensible-areas/screenshare-helper-item/types.ts @@ -32,4 +32,5 @@ export interface ScreenshareHelperButtonProps { hasSeparator: boolean; position: ScreenshareHelperItemPosition; onClick: (args: ScreenshareHelperButtonOnclickCallback) => void; + dataTest?: string; } diff --git a/src/extensible-areas/user-camera-dropdown-item/component.ts b/src/extensible-areas/user-camera-dropdown-item/component.ts index 62aab540..500ead9e 100644 --- a/src/extensible-areas/user-camera-dropdown-item/component.ts +++ b/src/extensible-areas/user-camera-dropdown-item/component.ts @@ -17,6 +17,8 @@ export class UserCameraDropdownOption implements UserCameraDropdownInterface { icon: string; + dataTest: string; + onClick: (args: OnclickFunctionCallbackArguments) => void; displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; @@ -27,12 +29,13 @@ export class UserCameraDropdownOption implements UserCameraDropdownInterface { * * @param label - label to be displayed in the option. * @param icon - icon to be displayed in the option. Left side of it. + * @param dataTest - string attribute to be used for testing * @param onClick - function to be called when clicking the button * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5) */ constructor({ - id, label = '', icon = '', onClick = () => {}, + id, label = '', icon = '', dataTest = '', onClick = () => {}, displayFunction = () => true, }: UserCameraDropdownOptionProps) { if (id) { @@ -41,6 +44,7 @@ export class UserCameraDropdownOption implements UserCameraDropdownInterface { this.displayFunction = displayFunction; this.label = label; this.icon = icon; + this.dataTest = dataTest; this.onClick = onClick; this.type = UserCameraDropdownItemType.OPTION; } @@ -55,18 +59,23 @@ export class UserCameraDropdownSeparator implements UserCameraDropdownInterface type: UserCameraDropdownItemType; + dataTest: string; + displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; /** * Returns object to be used in the setter for User Camera Dropdown. In this case * a separator. * + * @param dataTest - string attribute to be used for testing + * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5) */ constructor({ - displayFunction, + displayFunction, dataTest = '', }: UserCameraDropdownSeparatorProps = { displayFunction: () => true }) { this.displayFunction = displayFunction; + this.dataTest = dataTest; this.type = UserCameraDropdownItemType.SEPARATOR; } diff --git a/src/extensible-areas/user-camera-dropdown-item/types.ts b/src/extensible-areas/user-camera-dropdown-item/types.ts index 6b9e3452..61184b3e 100644 --- a/src/extensible-areas/user-camera-dropdown-item/types.ts +++ b/src/extensible-areas/user-camera-dropdown-item/types.ts @@ -22,6 +22,7 @@ export interface UserCameraDropdownInterface extends PluginProvidedUiItemDescrip export interface UserCameraDropdownSeparatorProps { displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; + dataTest?: string; } export interface UserCameraDropdownOptionProps { @@ -30,4 +31,5 @@ export interface UserCameraDropdownOptionProps { icon: string; onClick: (args: OnclickFunctionCallbackArguments) => void; displayFunction?: (args: UserCameraDropdownCallbackFunctionsArguments) => boolean; + dataTest?: string; } diff --git a/src/extensible-areas/user-camera-helper-item/component.ts b/src/extensible-areas/user-camera-helper-item/component.ts index a28d91ee..a5c9cbcf 100644 --- a/src/extensible-areas/user-camera-helper-item/component.ts +++ b/src/extensible-areas/user-camera-helper-item/component.ts @@ -23,6 +23,8 @@ export class UserCameraHelperButton implements UserCameraHelperButtonInterface { disabled: boolean; + dataTest: string; + position: UserCameraHelperItemPosition; onClick: (args: UserCameraHelperButtonOnclickCallback) => void; @@ -40,11 +42,12 @@ export class UserCameraHelperButton implements UserCameraHelperButtonInterface { * @param position - position to place the userCamera helper button. * See {@link UserCameraHelperItemPosition} * @param disabled - if true, the userCamera helper button will not be clickable + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, label = '', icon = '', tooltip = '', disabled = true, onClick = () => {}, + id, label = '', icon = '', tooltip = '', disabled = true, dataTest = '', onClick = () => {}, position = UserCameraHelperItemPosition.TOP_RIGHT, displayFunction, }: UserCameraHelperButtonProps) { if (id) { @@ -54,6 +57,7 @@ export class UserCameraHelperButton implements UserCameraHelperButtonInterface { this.icon = icon; this.tooltip = tooltip; this.disabled = disabled; + this.dataTest = dataTest; this.onClick = onClick; this.displayFunction = displayFunction; this.type = UserCameraHelperItemType.BUTTON; diff --git a/src/extensible-areas/user-camera-helper-item/types.ts b/src/extensible-areas/user-camera-helper-item/types.ts index 5a5eb5fc..6474d741 100644 --- a/src/extensible-areas/user-camera-helper-item/types.ts +++ b/src/extensible-areas/user-camera-helper-item/types.ts @@ -41,4 +41,5 @@ export interface UserCameraHelperButtonProps { displayFunction?: (args: UserCameraHelperCallbackFunctionArguments) => boolean; position: UserCameraHelperItemPosition; onClick: (args: UserCameraHelperButtonOnclickCallback) => void; + dataTest?: string; } diff --git a/src/extensible-areas/user-list-dropdown-item/component.ts b/src/extensible-areas/user-list-dropdown-item/component.ts index a217db16..3dd4255f 100644 --- a/src/extensible-areas/user-list-dropdown-item/component.ts +++ b/src/extensible-areas/user-list-dropdown-item/component.ts @@ -25,6 +25,8 @@ export class UserListDropdownOption implements UserListDropdownInterface { allowed: boolean; + dataTest: string; + onClick: () => void; /** @@ -38,11 +40,12 @@ export class UserListDropdownOption implements UserListDropdownInterface { * @param allowed - if false, the use list dropdown will not appear in the dropdown. * @param userId - the userId in which this dropdown option will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - label = '', icon = '', tooltip = '', allowed = true, onClick = () => {}, + label = '', icon = '', tooltip = '', allowed = true, dataTest = '', onClick = () => {}, userId = '', }: UserListDropdownOptionProps) { this.userId = userId; @@ -50,6 +53,7 @@ export class UserListDropdownOption implements UserListDropdownInterface { this.icon = icon; this.tooltip = tooltip; this.allowed = allowed; + this.dataTest = dataTest; this.onClick = onClick; this.type = UserListDropdownItemType.OPTION; } @@ -68,18 +72,22 @@ export class UserListDropdownSeparator implements UserListDropdownInterface { type: UserListDropdownItemType; + dataTest: string; + /** * Returns object to be used in the setter for the User List Dropdown. In this case, * a separator. * * @param userId - the userId in which this dropdown separator will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ - constructor({ userId = '', position = UserListDropdownSeparatorPosition.AFTER }: UserListDropdownSeparatorProps) { + constructor({ userId = '', position = UserListDropdownSeparatorPosition.AFTER, dataTest = '' }: UserListDropdownSeparatorProps) { this.userId = userId; this.position = position; + this.dataTest = dataTest; this.type = UserListDropdownItemType.SEPARATOR; } @@ -105,6 +113,8 @@ export class UserListDropdownFixedContentInformation implements UserListDropdown allowed: boolean; + dataTest: string; + /** * Returns object to be used in the setter for the User List Dropdown. In this case, * a button. @@ -118,12 +128,13 @@ export class UserListDropdownFixedContentInformation implements UserListDropdown * @param textColor - Color that the text will have. * @param userId - the userId in which this dropdown information will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ id, label = '', icon = '', iconRight = '', allowed = true, - userId = '', textColor = '', + userId = '', textColor = '', dataTest = '', }: UserListDropdownFixedContentInformationProps) { if (id) { this.id = id; @@ -134,6 +145,7 @@ export class UserListDropdownFixedContentInformation implements UserListDropdown this.iconRight = iconRight; this.textColor = textColor; this.allowed = allowed; + this.dataTest = dataTest; this.type = UserListDropdownItemType.FIXED_CONTENT_INFORMATION; } @@ -152,6 +164,8 @@ implements UserListDropdownInterface { type: UserListDropdownItemType; + dataTest: string; + contentFunction: (element: HTMLElement) => void; /** @@ -167,18 +181,20 @@ implements UserListDropdownInterface { * @param textColor - Color that the text will have. * @param userId - the userId in which this dropdown information will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ id, contentFunction, allowed = true, - userId = '', + userId = '', dataTest = '', }: UserListDropdownGenericContentInformationProps) { if (id) { this.id = id; } this.userId = userId; this.allowed = allowed; + this.dataTest = dataTest; this.contentFunction = contentFunction; this.type = UserListDropdownItemType.GENERIC_CONTENT_INFORMATION; } @@ -199,6 +215,8 @@ export class UserListDropdownTitleAction implements UserListDropdownInterface { tooltip: string; + dataTest: string; + onClick: (args: UserListDropdownTitleActionOnClickArguments) => void; /** @@ -211,11 +229,12 @@ export class UserListDropdownTitleAction implements UserListDropdownInterface { * It goes on the left side of it. * @param userId - the userId in which this dropdown title action will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, icon = '', userId = '', onClick, tooltip, + id, icon = '', userId = '', onClick, tooltip, dataTest = '', }: UserListDropdownTitleActionProps) { if (id) { this.id = id; @@ -223,6 +242,7 @@ export class UserListDropdownTitleAction implements UserListDropdownInterface { this.userId = userId; this.icon = icon; this.tooltip = tooltip; + this.dataTest = dataTest; this.onClick = onClick; this.type = UserListDropdownItemType.TITLE_ACTION; } diff --git a/src/extensible-areas/user-list-dropdown-item/types.ts b/src/extensible-areas/user-list-dropdown-item/types.ts index 55ebaf72..e8ded734 100644 --- a/src/extensible-areas/user-list-dropdown-item/types.ts +++ b/src/extensible-areas/user-list-dropdown-item/types.ts @@ -19,11 +19,13 @@ export interface UserListDropdownOptionProps { allowed: boolean; userId: string; onClick: () => void; + dataTest?: string; } export interface UserListDropdownSeparatorProps { userId: string; position?: UserListDropdownSeparatorPosition; + dataTest?: string; } export interface UserListDropdownGenericContentInformationProps { @@ -31,6 +33,7 @@ export interface UserListDropdownGenericContentInformationProps { contentFunction: (element: HTMLElement) => void; allowed: boolean; userId: string; + dataTest?: string; } export interface UserListDropdownFixedContentInformationProps { @@ -41,6 +44,7 @@ export interface UserListDropdownFixedContentInformationProps { allowed: boolean; userId: string; textColor: string; + dataTest?: string; } export interface UserListDropdownTitleActionOnClickArguments { @@ -53,4 +57,5 @@ export interface UserListDropdownTitleActionProps { icon: string; userId: string; onClick: (args: UserListDropdownTitleActionOnClickArguments) => void; + dataTest?: string; } diff --git a/src/extensible-areas/user-list-item-additional-information/component.ts b/src/extensible-areas/user-list-item-additional-information/component.ts index 22ad7f1d..c831aad3 100644 --- a/src/extensible-areas/user-list-item-additional-information/component.ts +++ b/src/extensible-areas/user-list-item-additional-information/component.ts @@ -15,6 +15,8 @@ export class UserListItemIcon implements UserListItemAdditionalInformationInterf icon: string; + dataTest: string; + /** * Returns object to be used in the setter for the User List Item Additional information Item. * In this case, a icon. @@ -23,17 +25,19 @@ export class UserListItemIcon implements UserListItemAdditionalInformationInterf * It goes on the left side of it. * @param userId - the userId in which this information will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, icon = '', userId = '', + id, icon = '', userId = '', dataTest = '', }: UserListItemIconProps) { if (id) { this.id = id; } this.icon = icon; this.userId = userId; + this.dataTest = dataTest; this.type = UserListItemAdditionalInformationType.ICON; } @@ -53,6 +57,8 @@ export class UserListItemLabel implements UserListItemAdditionalInformationInter label: string; + dataTest: string; + /** * Returns object to be used in the setter for the User List Item Additional information Item. * In this case, a label (Information). @@ -62,11 +68,12 @@ export class UserListItemLabel implements UserListItemAdditionalInformationInter * It goes on the left side of it. * @param userId - the userId in which this information will appear when the user * list item is clicked. + * @param dataTest - string attribute to be used for testing * * @returns Object that will be interpreted by the core of Bigbluebutton (HTML5). */ constructor({ - id, icon = '', userId = '', label = '', + id, icon = '', userId = '', label = '', dataTest = '', }: UserListItemLabelProps) { if (id) { this.id = id; @@ -74,6 +81,7 @@ export class UserListItemLabel implements UserListItemAdditionalInformationInter this.icon = icon; this.label = label; this.userId = userId; + this.dataTest = dataTest; this.type = UserListItemAdditionalInformationType.LABEL; } diff --git a/src/extensible-areas/user-list-item-additional-information/types.ts b/src/extensible-areas/user-list-item-additional-information/types.ts index f4ce96c9..73b4ca8b 100644 --- a/src/extensible-areas/user-list-item-additional-information/types.ts +++ b/src/extensible-areas/user-list-item-additional-information/types.ts @@ -15,6 +15,7 @@ export interface UserListItemIconProps { id?: string; userId: string; icon: string; + dataTest?: string; } export interface UserListItemLabelProps { @@ -22,4 +23,5 @@ export interface UserListItemLabelProps { userId: string; icon: string; label: string; + dataTest?: string; } From 723fd499a344552ecf4d377b9a3a2e361947b990 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 10 Dec 2025 17:46:50 -0300 Subject: [PATCH 19/22] [add-data-test] added data-test to sample of generic-content-sidekick-plugin --- .../sample-generic-content-sidekick-plugin-item/component.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/samples/sample-generic-content-sidekick-plugin/src/components/sample-generic-content-sidekick-plugin-item/component.tsx b/samples/sample-generic-content-sidekick-plugin/src/components/sample-generic-content-sidekick-plugin-item/component.tsx index 98713163..d004a069 100644 --- a/samples/sample-generic-content-sidekick-plugin/src/components/sample-generic-content-sidekick-plugin-item/component.tsx +++ b/samples/sample-generic-content-sidekick-plugin/src/components/sample-generic-content-sidekick-plugin-item/component.tsx @@ -27,6 +27,7 @@ function SampleGenericContentSidekickPlugin( id: GENERIC_CONTENT_BADGE_ID, name: 'Generic Content 1', section: 'Section 1', + dataTest: 'section-1-generic-content-sidekick-abc', buttonIcon: 'video', open: false, contentFunction: (element: HTMLElement) => { From f9550105f9635782c4336c5985df025411d492f5 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Wed, 17 Dec 2025 09:14:41 -0300 Subject: [PATCH 20/22] [lad-new-functions-plugin] fixed documentation --- README.md | 2 +- src/core/api/types.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6ecb9419..2692e51c 100644 --- a/README.md +++ b/README.md @@ -460,7 +460,7 @@ So the idea is that we have a `uiCommands` object and at a point, there will be This integration allow you to insert/update entry in LAD (Learning Analytics Dashboard) via `upsertUserData` function and also delete entries via `deleteUserData` function. -It's an object available in the `pluginApi` that wraps those 2 functions: +It's an object available in the `pluginApi` that wraps those 3 functions: - `pluginApi.learningAnalyticsDashboard.upsertUserData` - `pluginApi.learningAnalyticsDashboard.deleteUserData` diff --git a/src/core/api/types.ts b/src/core/api/types.ts index 9709e47d..24c19b3f 100644 --- a/src/core/api/types.ts +++ b/src/core/api/types.ts @@ -287,7 +287,7 @@ export interface PluginApi { */ useLocaleMessages?: UseLocaleMessagesFunction /** - * @deprecated Use {@link learningAnalyticsDashboard.upsertGenericData} object instead. + * @deprecated Use {@link learningAnalyticsDashboard.upsertUserData} object instead. * * Send data to the Learning analytics dashboard * From 928cce0ac07fdebf4bf133aa184d8cd883bf8bc0 Mon Sep 17 00:00:00 2001 From: Guilherme Leme Date: Thu, 8 Jan 2026 16:29:01 -0300 Subject: [PATCH 21/22] [zindex-floating-window] fixed some lint-errors --- .eslintignore | 2 ++ src/extensible-areas/floating-window/component.ts | 2 +- src/utils/logger/logger.ts | 1 + 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/.eslintignore b/.eslintignore index f06235c4..a8c16873 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,2 +1,4 @@ node_modules dist +samples/*/dist +samples/*/dist-tsc diff --git a/src/extensible-areas/floating-window/component.ts b/src/extensible-areas/floating-window/component.ts index 5ae58ef3..4c7e07d2 100644 --- a/src/extensible-areas/floating-window/component.ts +++ b/src/extensible-areas/floating-window/component.ts @@ -20,7 +20,7 @@ export class FloatingWindow implements FloatingWindowInterface { boxShadow: string; zIndex?: number; - + dataTest?: string; contentFunction: (element: HTMLElement) => ReactDOM.Root; diff --git a/src/utils/logger/logger.ts b/src/utils/logger/logger.ts index 4cd498b4..6cd28f95 100644 --- a/src/utils/logger/logger.ts +++ b/src/utils/logger/logger.ts @@ -50,6 +50,7 @@ function logWith(level: T, ...args: LoggerArgument[]): v try { method.call(logger, ...args); } catch (err) { + // eslint-disable-next-line no-console console.error(`[pluginLogger.${String(level)}] fallback`, err, ...args); } } From 77e4f61334c14c45515746ae4e3bc1123d8e9a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ram=C3=B3n=20Souza?= Date: Mon, 12 Jan 2026 16:54:59 -0300 Subject: [PATCH 22/22] Bump version to 0.0.96 --- package-lock.json | 4 ++-- package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- .../sample-actions-bar-plugin/package-lock.json | 8 ++++---- samples/sample-actions-bar-plugin/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- .../package-lock.json | 14 +++++++------- .../sample-custom-subscription-hook/package.json | 2 +- .../sample-data-channel-plugin/package-lock.json | 14 +++++++------- samples/sample-data-channel-plugin/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../sample-dom-element-manipulation/package.json | 2 +- .../package-lock.json | 14 +++++++------- samples/sample-floating-window-plugin/package.json | 2 +- .../package-lock.json | 8 ++++---- .../package.json | 2 +- samples/sample-nav-bar-plugin/package-lock.json | 14 +++++++------- samples/sample-nav-bar-plugin/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../sample-options-dropdown-plugin/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- .../package-lock.json | 14 +++++++------- .../sample-screenshare-helper-plugin/package.json | 2 +- .../package-lock.json | 8 ++++---- samples/sample-server-commands-plugin/package.json | 2 +- .../sample-ui-commands-plugin/package-lock.json | 14 +++++++------- samples/sample-ui-commands-plugin/package.json | 2 +- samples/sample-ui-events-plugin/package-lock.json | 14 +++++++------- samples/sample-ui-events-plugin/package.json | 2 +- samples/sample-use-meeting/package-lock.json | 14 +++++++------- samples/sample-use-meeting/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- .../package-lock.json | 14 +++++++------- .../sample-user-camera-helper-plugin/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../sample-user-list-dropdown-plugin/package.json | 2 +- .../package-lock.json | 14 +++++++------- .../package.json | 2 +- 46 files changed, 170 insertions(+), 170 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9e6b537f..1ba2e5af 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "bigbluebutton-html-plugin-sdk", - "version": "0.0.95", + "version": "0.0.96", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "bigbluebutton-html-plugin-sdk", - "version": "0.0.95", + "version": "0.0.96", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", diff --git a/package.json b/package.json index 6033ad79..d11f3e88 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bigbluebutton-html-plugin-sdk", - "version": "0.0.95", + "version": "0.0.96", "homepage": "https://github.com/bigbluebutton/bigbluebutton-html-plugin-sdk", "main": "dist/cjs/index.js", "module": "dist/esm/index.js", diff --git a/samples/sample-action-button-dropdown-plugin/package-lock.json b/samples/sample-action-button-dropdown-plugin/package-lock.json index 342c9974..32e10ef2 100644 --- a/samples/sample-action-button-dropdown-plugin/package-lock.json +++ b/samples/sample-action-button-dropdown-plugin/package-lock.json @@ -14,7 +14,7 @@ "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3457,9 +3457,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -12224,9 +12224,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-action-button-dropdown-plugin/package.json b/samples/sample-action-button-dropdown-plugin/package.json index 9c1b4c05..29503c98 100644 --- a/samples/sample-action-button-dropdown-plugin/package.json +++ b/samples/sample-action-button-dropdown-plugin/package.json @@ -10,7 +10,7 @@ "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-actions-bar-plugin/package-lock.json b/samples/sample-actions-bar-plugin/package-lock.json index e15c3d8f..1d2f7210 100644 --- a/samples/sample-actions-bar-plugin/package-lock.json +++ b/samples/sample-actions-bar-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3624,9 +3624,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", diff --git a/samples/sample-actions-bar-plugin/package.json b/samples/sample-actions-bar-plugin/package.json index ce2ea86c..937a52a8 100644 --- a/samples/sample-actions-bar-plugin/package.json +++ b/samples/sample-actions-bar-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-audio-settings-dropdown-plugin/package-lock.json b/samples/sample-audio-settings-dropdown-plugin/package-lock.json index e6baf650..35548da3 100644 --- a/samples/sample-audio-settings-dropdown-plugin/package-lock.json +++ b/samples/sample-audio-settings-dropdown-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "browser-bunyan": "^1.8.0", "path": "^0.12.7", "react": "^18.2.0", @@ -3398,9 +3398,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11629,9 +11629,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-audio-settings-dropdown-plugin/package.json b/samples/sample-audio-settings-dropdown-plugin/package.json index 55109160..f994c1bd 100644 --- a/samples/sample-audio-settings-dropdown-plugin/package.json +++ b/samples/sample-audio-settings-dropdown-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "browser-bunyan": "^1.8.0", "path": "^0.12.7", "react": "^18.2.0", diff --git a/samples/sample-camera-settings-dropdown-plugin/package-lock.json b/samples/sample-camera-settings-dropdown-plugin/package-lock.json index de3d510a..2cc5eafa 100644 --- a/samples/sample-camera-settings-dropdown-plugin/package-lock.json +++ b/samples/sample-camera-settings-dropdown-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3397,9 +3397,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11628,9 +11628,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-camera-settings-dropdown-plugin/package.json b/samples/sample-camera-settings-dropdown-plugin/package.json index d24d8229..7145a8b2 100644 --- a/samples/sample-camera-settings-dropdown-plugin/package.json +++ b/samples/sample-camera-settings-dropdown-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-custom-subscription-hook/package-lock.json b/samples/sample-custom-subscription-hook/package-lock.json index 876a50a9..a71cf61d 100644 --- a/samples/sample-custom-subscription-hook/package-lock.json +++ b/samples/sample-custom-subscription-hook/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3397,9 +3397,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11628,9 +11628,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-custom-subscription-hook/package.json b/samples/sample-custom-subscription-hook/package.json index a9ac49f8..ecd666c6 100644 --- a/samples/sample-custom-subscription-hook/package.json +++ b/samples/sample-custom-subscription-hook/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-data-channel-plugin/package-lock.json b/samples/sample-data-channel-plugin/package-lock.json index cd8bb5ef..2380e361 100644 --- a/samples/sample-data-channel-plugin/package-lock.json +++ b/samples/sample-data-channel-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "browser-bunyan": "^1.8.0", "path": "^0.12.7", "react": "^18.2.0", @@ -3405,9 +3405,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11647,9 +11647,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-data-channel-plugin/package.json b/samples/sample-data-channel-plugin/package.json index f9bb53ae..8800fd47 100644 --- a/samples/sample-data-channel-plugin/package.json +++ b/samples/sample-data-channel-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "browser-bunyan": "^1.8.0", "react": "^18.2.0", diff --git a/samples/sample-dom-element-manipulation/package-lock.json b/samples/sample-dom-element-manipulation/package-lock.json index e6366532..ed9a4b34 100644 --- a/samples/sample-dom-element-manipulation/package-lock.json +++ b/samples/sample-dom-element-manipulation/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11646,9 +11646,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-dom-element-manipulation/package.json b/samples/sample-dom-element-manipulation/package.json index 412ca95c..d464d5ff 100644 --- a/samples/sample-dom-element-manipulation/package.json +++ b/samples/sample-dom-element-manipulation/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-floating-window-plugin/package-lock.json b/samples/sample-floating-window-plugin/package-lock.json index cacf2637..ce0e16dc 100644 --- a/samples/sample-floating-window-plugin/package-lock.json +++ b/samples/sample-floating-window-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3453,9 +3453,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11775,9 +11775,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-floating-window-plugin/package.json b/samples/sample-floating-window-plugin/package.json index cc13db20..dee142fd 100644 --- a/samples/sample-floating-window-plugin/package.json +++ b/samples/sample-floating-window-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-generic-content-sidekick-plugin/package-lock.json b/samples/sample-generic-content-sidekick-plugin/package-lock.json index c409b050..a39b182a 100644 --- a/samples/sample-generic-content-sidekick-plugin/package-lock.json +++ b/samples/sample-generic-content-sidekick-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "react": "^18.2.0", "react-dom": "^18.2.0" }, @@ -3608,9 +3608,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", diff --git a/samples/sample-generic-content-sidekick-plugin/package.json b/samples/sample-generic-content-sidekick-plugin/package.json index 8d95535d..a29aa351 100644 --- a/samples/sample-generic-content-sidekick-plugin/package.json +++ b/samples/sample-generic-content-sidekick-plugin/package.json @@ -10,7 +10,7 @@ "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", "react-dom": "^18.2.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "react": "^18.2.0" }, "scripts": { diff --git a/samples/sample-nav-bar-plugin/package-lock.json b/samples/sample-nav-bar-plugin/package-lock.json index f01906cd..e3d7889e 100644 --- a/samples/sample-nav-bar-plugin/package-lock.json +++ b/samples/sample-nav-bar-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "browser-bunyan": "^1.8.0", "path": "^0.12.7", "react": "^18.2.0", @@ -3416,9 +3416,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11676,9 +11676,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-nav-bar-plugin/package.json b/samples/sample-nav-bar-plugin/package.json index 05cb0f92..72cf465d 100644 --- a/samples/sample-nav-bar-plugin/package.json +++ b/samples/sample-nav-bar-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "browser-bunyan": "^1.8.0", "react": "^18.2.0", diff --git a/samples/sample-options-dropdown-plugin/package-lock.json b/samples/sample-options-dropdown-plugin/package-lock.json index 3fe9ca74..3f3b8b7f 100644 --- a/samples/sample-options-dropdown-plugin/package-lock.json +++ b/samples/sample-options-dropdown-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "browser-bunyan": "^1.8.0", "path": "^0.12.7", "react": "^18.2.0", @@ -3405,9 +3405,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11647,9 +11647,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-options-dropdown-plugin/package.json b/samples/sample-options-dropdown-plugin/package.json index 595700f9..e0c7b9ef 100644 --- a/samples/sample-options-dropdown-plugin/package.json +++ b/samples/sample-options-dropdown-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "browser-bunyan": "^1.8.0", "react": "^18.2.0", diff --git a/samples/sample-presentation-dropdown-plugin/package-lock.json b/samples/sample-presentation-dropdown-plugin/package-lock.json index 43ee908e..c645406e 100644 --- a/samples/sample-presentation-dropdown-plugin/package-lock.json +++ b/samples/sample-presentation-dropdown-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11646,9 +11646,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-presentation-dropdown-plugin/package.json b/samples/sample-presentation-dropdown-plugin/package.json index bcbaa7bd..bd1f925d 100644 --- a/samples/sample-presentation-dropdown-plugin/package.json +++ b/samples/sample-presentation-dropdown-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-presentation-toolbar-plugin/package-lock.json b/samples/sample-presentation-toolbar-plugin/package-lock.json index d9bc764d..ec73c682 100644 --- a/samples/sample-presentation-toolbar-plugin/package-lock.json +++ b/samples/sample-presentation-toolbar-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11646,9 +11646,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-presentation-toolbar-plugin/package.json b/samples/sample-presentation-toolbar-plugin/package.json index acc2a133..8cbeeeac 100644 --- a/samples/sample-presentation-toolbar-plugin/package.json +++ b/samples/sample-presentation-toolbar-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-screenshare-helper-plugin/package-lock.json b/samples/sample-screenshare-helper-plugin/package-lock.json index ea13d645..68d22b59 100644 --- a/samples/sample-screenshare-helper-plugin/package-lock.json +++ b/samples/sample-screenshare-helper-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11644,9 +11644,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-screenshare-helper-plugin/package.json b/samples/sample-screenshare-helper-plugin/package.json index d4a767eb..fc964e09 100644 --- a/samples/sample-screenshare-helper-plugin/package.json +++ b/samples/sample-screenshare-helper-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react-dom": "^18.2.0", "react": "^18.2.0", diff --git a/samples/sample-server-commands-plugin/package-lock.json b/samples/sample-server-commands-plugin/package-lock.json index f85168b0..f7742bbf 100644 --- a/samples/sample-server-commands-plugin/package-lock.json +++ b/samples/sample-server-commands-plugin/package-lock.json @@ -14,7 +14,7 @@ "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3457,9 +3457,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", diff --git a/samples/sample-server-commands-plugin/package.json b/samples/sample-server-commands-plugin/package.json index fc922fd5..baf86e82 100644 --- a/samples/sample-server-commands-plugin/package.json +++ b/samples/sample-server-commands-plugin/package.json @@ -10,7 +10,7 @@ "@types/react": "^18.2.13", "@types/react-dom": "^18.2.6", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-ui-commands-plugin/package-lock.json b/samples/sample-ui-commands-plugin/package-lock.json index f9baed8e..010eb9ef 100644 --- a/samples/sample-ui-commands-plugin/package-lock.json +++ b/samples/sample-ui-commands-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3414,9 +3414,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11675,9 +11675,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-ui-commands-plugin/package.json b/samples/sample-ui-commands-plugin/package.json index 60da4209..0537a2cc 100644 --- a/samples/sample-ui-commands-plugin/package.json +++ b/samples/sample-ui-commands-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-ui-events-plugin/package-lock.json b/samples/sample-ui-events-plugin/package-lock.json index 8cdde281..7edb80dc 100644 --- a/samples/sample-ui-events-plugin/package-lock.json +++ b/samples/sample-ui-events-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3414,9 +3414,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11675,9 +11675,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-ui-events-plugin/package.json b/samples/sample-ui-events-plugin/package.json index 110c07a1..b767e27f 100644 --- a/samples/sample-ui-events-plugin/package.json +++ b/samples/sample-ui-events-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-use-meeting/package-lock.json b/samples/sample-use-meeting/package-lock.json index bcd90566..9f73ddfd 100644 --- a/samples/sample-use-meeting/package-lock.json +++ b/samples/sample-use-meeting/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3414,9 +3414,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11675,9 +11675,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-use-meeting/package.json b/samples/sample-use-meeting/package.json index bf586236..e1edd352 100644 --- a/samples/sample-use-meeting/package.json +++ b/samples/sample-use-meeting/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-user-camera-dropdown-plugin/package-lock.json b/samples/sample-user-camera-dropdown-plugin/package-lock.json index e8a3c9d8..a3c34e23 100644 --- a/samples/sample-user-camera-dropdown-plugin/package-lock.json +++ b/samples/sample-user-camera-dropdown-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11646,9 +11646,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-user-camera-dropdown-plugin/package.json b/samples/sample-user-camera-dropdown-plugin/package.json index 743b05e5..00e48606 100644 --- a/samples/sample-user-camera-dropdown-plugin/package.json +++ b/samples/sample-user-camera-dropdown-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-user-camera-helper-plugin/package-lock.json b/samples/sample-user-camera-helper-plugin/package-lock.json index 0bf1a66e..02985d22 100644 --- a/samples/sample-user-camera-helper-plugin/package-lock.json +++ b/samples/sample-user-camera-helper-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11646,9 +11646,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-user-camera-helper-plugin/package.json b/samples/sample-user-camera-helper-plugin/package.json index 4c6da0b6..a5ca1fbe 100644 --- a/samples/sample-user-camera-helper-plugin/package.json +++ b/samples/sample-user-camera-helper-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "react-dom": "^18.2.0", "path": "^0.12.7", "react": "^18.2.0", diff --git a/samples/sample-user-list-dropdown-plugin/package-lock.json b/samples/sample-user-list-dropdown-plugin/package-lock.json index ac95c499..ee20a5aa 100644 --- a/samples/sample-user-list-dropdown-plugin/package-lock.json +++ b/samples/sample-user-list-dropdown-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3463,9 +3463,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -12241,9 +12241,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-user-list-dropdown-plugin/package.json b/samples/sample-user-list-dropdown-plugin/package.json index d1b3ac18..15ed17f5 100644 --- a/samples/sample-user-list-dropdown-plugin/package.json +++ b/samples/sample-user-list-dropdown-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", diff --git a/samples/sample-user-list-item-additional-information-plugin/package-lock.json b/samples/sample-user-list-item-additional-information-plugin/package-lock.json index 788a4670..0cfa7f93 100644 --- a/samples/sample-user-list-item-additional-information-plugin/package-lock.json +++ b/samples/sample-user-list-item-additional-information-plugin/package-lock.json @@ -13,7 +13,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0", @@ -3404,9 +3404,9 @@ "dev": true }, "node_modules/bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "license": "LGPL-3.0", "dependencies": { "@apollo/client": "^3.8.7", @@ -11646,9 +11646,9 @@ "dev": true }, "bigbluebutton-html-plugin-sdk": { - "version": "0.0.95", - "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.95.tgz", - "integrity": "sha512-b4Uq2Vqpe+YWuC1Ofq5USCR3/IjOFLOGO8sbDAipr4RijOBdjQe4y5RwKoi3vIItlqTSTKxR5+rc7VBjvoNOAQ==", + "version": "0.0.96", + "resolved": "https://registry.npmjs.org/bigbluebutton-html-plugin-sdk/-/bigbluebutton-html-plugin-sdk-0.0.96.tgz", + "integrity": "sha512-TnCjTa9+LolRbElDNR28wWPMN2RnWbNdbwIMerZfufsTgNqUUF/KjBeIKwoiy2nO+RmCbmOGqDsjnpAIO1uwWA==", "requires": { "@apollo/client": "^3.8.7", "@browser-bunyan/console-formatted-stream": "^1.8.0", diff --git a/samples/sample-user-list-item-additional-information-plugin/package.json b/samples/sample-user-list-item-additional-information-plugin/package.json index aff6d888..483cc864 100644 --- a/samples/sample-user-list-item-additional-information-plugin/package.json +++ b/samples/sample-user-list-item-additional-information-plugin/package.json @@ -9,7 +9,7 @@ "@types/node": "^20.3.1", "@types/react": "^18.2.13", "babel-plugin-syntax-dynamic-import": "^6.18.0", - "bigbluebutton-html-plugin-sdk": "0.0.95", + "bigbluebutton-html-plugin-sdk": "0.0.96", "path": "^0.12.7", "react": "^18.2.0", "react-dom": "^18.2.0",