Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(extensible-area): add actions bar selector and toggle + extend separator #141

Merged
merged 3 commits into from
Jan 21, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
import { useEffect } from 'react';

import {
ActionsBarButton, ActionsBarInterface, ActionsBarPosition, ActionsBarSeparator,
BbbPluginSdk, GraphqlResponseWrapper,
ActionsBarButton, ActionsBarInterface, ActionsBarPosition, ActionsBarSelector,
ActionsBarSeparator, ActionsBarToggleGroup, BbbPluginSdk, GraphqlResponseWrapper,
PluginApi, UsersBasicInfoResponseFromGraphqlWrapper,
pluginLogger,
} from 'bigbluebutton-html-plugin-sdk';
Expand All @@ -14,23 +14,62 @@
}: SampleActionsBarPluginProps): React.ReactNode {
BbbPluginSdk.initialize(uuid);
const pluginApi: PluginApi = BbbPluginSdk.getPluginApi(uuid);
const options = [
{ value: 1, label: 'one' },
{ value: 2, label: 'two' },
{ value: 3, label: 'three' },
{ value: 4, label: 'four' },
{ value: 5, label: 'five' },
{ value: 6, label: 'six' },
];

useEffect(() => {
const buttonToUserListItem:
ActionsBarInterface = new ActionsBarButton({
icon: 'user',
tooltip: 'This will log on the console.',
onClick: () => {
pluginLogger.info('The action bar button from plugin was clicked');
pluginLogger.info('The actions bar button from plugin was clicked');
},
position: ActionsBarPosition.RIGHT,
});
const dropdownToUserListItem:
const separatorToUserListItem:
ActionsBarInterface = new ActionsBarSeparator({
position: ActionsBarPosition.RIGHT,
});
const selectorItem: ActionsBarInterface = new ActionsBarSelector({
title: 'Selector',
options,
defaultOption: options[4],
onChange: (value, event) => {
console.log({ value, event });

Check warning on line 45 in samples/sample-actions-bar-plugin/src/sample-actions-bar-plugin/component.tsx

View workflow job for this annotation

GitHub Actions / ts-code-validation

Unexpected console statement
pluginLogger.info('The actions bar selector has changed', { value, event });
},
position: ActionsBarPosition.RIGHT,
width: 150, // To define a specific width, uncomment this line
});
const separatorIconItem: ActionsBarInterface = new ActionsBarSeparator({
position: ActionsBarPosition.RIGHT,
icon: 'whiteboard',
});
const toggleGroupItem: ActionsBarInterface = new ActionsBarToggleGroup({
title: 'Toggle',
options: options.slice(0, 2), // Toggle groups can have more than 2 options
defaultOption: options[2],
onChange: (value, event) => {
pluginLogger.info('The actions bar toggle group has changed', { value, event: event.nativeEvent });
},
position: ActionsBarPosition.RIGHT,
// exclusive: false, // To allow for checking more than one option, uncomment this line
});

pluginApi.setActionsBarItems([dropdownToUserListItem, buttonToUserListItem]);
pluginApi.setActionsBarItems([
separatorToUserListItem,
buttonToUserListItem,
selectorItem,
separatorIconItem,
toggleGroupItem,
]);
}, []);

const users: GraphqlResponseWrapper<UsersBasicInfoResponseFromGraphqlWrapper> = pluginApi
Expand Down
146 changes: 123 additions & 23 deletions src/extensible-areas/actions-bar-item/component.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,45 @@
import { ChangeEvent, MouseEvent } from 'react';
import { ActionsBarPosition, ActionsBarItemType } from './enums';
import {
ActionsBarInterface, ActionsBarButtonProps, ActionsBarSeparatorProps,
ActionsBarInterface,
ActionsBarItemProps,
ActionsBarButtonProps,
ActionsBarSeparatorProps,
ActionsBarSelectorProps,
SelectOption,
ToggleGroupOption,
ActionsBarToggleGroupProps,
} from './types';

// ActionsBar Extensible Area

export class ActionsBarButton implements ActionsBarInterface {
class ActionsBarItem implements ActionsBarInterface {
id: string = '';

type: ActionsBarItemType;

position: ActionsBarPosition;

constructor({
id, type, position = ActionsBarPosition.RIGHT,
}: ActionsBarItemProps) {
if (id) {
this.id = id;
}
this.type = type;
this.position = position;
}

setItemId(id: string):void {
this.id = `ActionsBar${this.type}_${id}`;
}
}

export class ActionsBarButton extends ActionsBarItem {
icon: string;

tooltip: string;

position: ActionsBarPosition;

onClick: () => void;

/**
Expand All @@ -32,44 +56,120 @@ export class ActionsBarButton implements ActionsBarInterface {
constructor({
id, icon = '', tooltip = '', onClick = () => {}, position = ActionsBarPosition.RIGHT,
}: ActionsBarButtonProps) {
if (id) {
this.id = id;
}
super({ id, type: ActionsBarItemType.BUTTON, position });
this.icon = icon;
this.tooltip = tooltip;
this.onClick = onClick;
this.position = position;
this.type = ActionsBarItemType.BUTTON;
}
}

setItemId: (id: string) => void = (id: string) => {
this.id = `ActionsBarButton_${id}`;
};
export class ActionsBarSeparator extends ActionsBarItem {
icon: string;

/**
* Returns object to be used in the setter for action bar. In this case,
* a separator.
*
* @param position - position that this button will be displayed, see {@link ActionsBarPosition}
* @param icon - Icon to be displayed as the separator. If not provided, the default separator
* (a vertical bar) will be displayed.
*
* @returns Object that will be interpreted by the core of Bigbluebutton (HTML5)
*/
constructor({
position = ActionsBarPosition.RIGHT,
icon = '',
}: ActionsBarSeparatorProps) {
super({ type: ActionsBarItemType.SEPARATOR, position });
this.icon = icon;
}
}

export class ActionsBarSeparator implements ActionsBarInterface {
position: ActionsBarPosition;
export class ActionsBarSelector extends ActionsBarItem {
title: string;

id: string = '';
options: SelectOption[];

type: ActionsBarItemType;
defaultOption: SelectOption;

onChange: (value: string | number, event: ChangeEvent<HTMLInputElement>) => void;

width: number = 145;

/**
* Returns object to be used in the setter for action bar. In this case,
* a separator.
* a selector.
*
* @param title - title to be used in the selector for the actions bar
* @param options - an array of options to be available in the selector
* @param defaultOption - the option to be initially selected, if not present, the first option is
* selected
* @param onChange - function to be called when selected value changes
* @param position - position that this button will be displayed, see {@link ActionsBarPosition}
* @param width - desired width for the selector in px, default is 140
*
* @returns Object that will be interpreted by the core of Bigbluebutton (HTML5)
*/

constructor({
id,
title = '',
options = [],
defaultOption = options[0],
onChange = () => {},
position = ActionsBarPosition.RIGHT,
}: ActionsBarSeparatorProps) {
this.position = position;
this.type = ActionsBarItemType.SEPARATOR;
width = 140,
}: ActionsBarSelectorProps) {
super({ id, type: ActionsBarItemType.SELECTOR, position });
this.title = title;
this.options = options;
this.defaultOption = defaultOption;
this.onChange = onChange;
this.width = width;
}
}

export class ActionsBarToggleGroup extends ActionsBarItem {
title: string;

setItemId: (id: string) => void = (id: string) => {
this.id = `ActionsBarSeparator_${id}`;
};
exclusive: boolean;

options: ToggleGroupOption[];

defaultOption: ToggleGroupOption;

onChange: (values: string | number | string[] | number[], event: MouseEvent<HTMLElement>) => void;

/**
* Returns object to be used in the setter for action bar. In this case,
* a toggle group.
*
* @param title - title to be used in the selector for the actions bar
* @param exclusive - whether the toggle group should be exclusive or not - allow checking
* multiple options
* @param options - an array of options to be available in the toggle group
* @param defaultOption - the option to be initially checked, if not present, the first option is
* checked
* @param onChange - function to be called when checked value changes
* @param position - position that this button will be displayed, see {@link ActionsBarPosition}
*
* @returns Object that will be interpreted by the core of Bigbluebutton (HTML5)
*/

constructor({
id,
title = '',
exclusive = true,
options = [],
defaultOption = options[0],
onChange = () => {},
position = ActionsBarPosition.RIGHT,
}: ActionsBarToggleGroupProps) {
super({ id, type: ActionsBarItemType.TOGGLE_GROUP, position });
this.title = title;
this.exclusive = exclusive;
this.options = options;
this.defaultOption = defaultOption;
this.onChange = onChange;
}
}
2 changes: 2 additions & 0 deletions src/extensible-areas/actions-bar-item/enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
export enum ActionsBarItemType {
BUTTON = 'ACTIONS_BAR_BUTTON',
SEPARATOR = 'ACTIONS_BAR_SEPARATOR',
SELECTOR = 'ACTIONS_BAR_SELECTOR',
TOGGLE_GROUP = 'ACTIONS_BAR_TOGGLE_GROUP',
}

/**
Expand Down
3 changes: 3 additions & 0 deletions src/extensible-areas/actions-bar-item/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
export {
ActionsBarButton,
ActionsBarSeparator,
ActionsBarSelector,
ActionsBarToggleGroup,
} from './component';
export {
ActionsBarInterface,
} from './types';
export {
ActionsBarItemType,
ActionsBarPosition,
} from './enums';
38 changes: 37 additions & 1 deletion src/extensible-areas/actions-bar-item/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChangeEvent, MouseEvent } from 'react';
import { PluginProvidedUiItemDescriptor } from '../base';
import { ActionsBarPosition } from './enums';
import { ActionsBarItemType, ActionsBarPosition } from './enums';

/**
* Interface for the generic Actions bar item. (`position` is mandatory)
Expand All @@ -8,6 +9,12 @@ export interface ActionsBarInterface extends PluginProvidedUiItemDescriptor{
position: ActionsBarPosition;
}

export interface ActionsBarItemProps {
id?: string;
position: ActionsBarPosition;
type: ActionsBarItemType;
}

export interface ActionsBarButtonProps {
id?: string;
icon: string;
Expand All @@ -18,4 +25,33 @@ export interface ActionsBarButtonProps {

export interface ActionsBarSeparatorProps {
position: ActionsBarPosition;
icon?: string;
}

export interface SelectOption {
value: string | number;
label: string;
}

export interface ToggleGroupOption extends SelectOption {
}

export interface ActionsBarSelectorProps {
id?: string;
title: string;
options: SelectOption[];
defaultOption?: SelectOption;
onChange: (value: string | number, event: ChangeEvent<HTMLInputElement>) => void;
position: ActionsBarPosition;
width?: number;
}

export interface ActionsBarToggleGroupProps {
id?: string;
title: string;
options: ToggleGroupOption[];
defaultOption?: ToggleGroupOption;
exclusive?: boolean;
onChange: (values: string | number | string[] | number[], event: MouseEvent<HTMLElement>) => void;
position: ActionsBarPosition;
}
Loading