diff --git a/packages/collaboration-extension/src/collaboration.ts b/packages/collaboration-extension/src/collaboration.ts index dd7f726..5c4e117 100644 --- a/packages/collaboration-extension/src/collaboration.ts +++ b/packages/collaboration-extension/src/collaboration.ts @@ -180,9 +180,7 @@ export const rtcPanelPlugin: JupyterFrontEndPlugin = { collaboratorsPanel.title.label = trans.__('Online Collaborators'); userPanel.addWidget(collaboratorsPanel); - const activityDisplay = new ActivityDisplay(tracker, user, roles); - activityDisplay.title.label = trans.__('User activity'); - userPanel.addWidget(activityDisplay); + const chatPanel = new SidePanel({ alignment: 'justify' @@ -193,12 +191,18 @@ export const rtcPanelPlugin: JupyterFrontEndPlugin = { chatPanel.addClass('jp-RTCPanel'); app.shell.add(chatPanel, 'left', { rank: 301 }); - const chatbox = new Chatbox(user, awarenessProvider, roles); + const chatbox = new Chatbox(user, awarenessProvider); + chatbox.id = 'jp-chatbox'; chatbox.title.label = trans.__('Chat with collaborators'); chatPanel.addWidget(chatbox); + const activityDisplay = new ActivityDisplay(tracker, user, roles, app, chatPanel); + activityDisplay.title.label = trans.__('User activity'); + userPanel.addWidget(activityDisplay); + setTimeout(() => { const pollTab = new PollList(user, awarenessProvider, roles); + pollTab.id = 'jp-polls'; pollTab.title.label = trans.__('Polls'); chatPanel.addWidget(pollTab); }, 1000); diff --git a/packages/collaboration/src/activitydisplay.tsx b/packages/collaboration/src/activitydisplay.tsx index 42a970d..d58d652 100644 --- a/packages/collaboration/src/activitydisplay.tsx +++ b/packages/collaboration/src/activitydisplay.tsx @@ -1,18 +1,22 @@ import { ReactWidget } from '@jupyterlab/apputils'; import { INotebookTracker } from '@jupyterlab/notebook'; import { User } from '@jupyterlab/services'; +import { JupyterFrontEnd } from '@jupyterlab/application'; import * as React from 'react'; import { ActivityBarGraph } from './activitybargraph'; import { ActivityDotPlot } from './activitydotplot'; import { Role, Roles } from './roles'; +import { SidePanel } from '@jupyterlab/ui-components'; export interface ActivityDisplayComponentProps { tracker: INotebookTracker; currentUser: User.IManager; - userRoles: Roles + userRoles: Roles; + app: JupyterFrontEnd; + chatPanel: SidePanel; } @@ -27,31 +31,41 @@ export class ActivityDisplay extends ReactWidget { private _tracker: INotebookTracker private _currentUser: User.IManager; private _roles: Roles; + private _app: JupyterFrontEnd; + private _chatPanel: SidePanel; - constructor(tracker: INotebookTracker, currentUser: User.IManager, roles: Roles) { + constructor(tracker: INotebookTracker, currentUser: User.IManager, roles: Roles, app: JupyterFrontEnd, chatPanel: SidePanel) { super(); this._tracker = tracker; this._currentUser = currentUser; this._roles = roles; + this._app = app; + this._chatPanel = chatPanel; } render() { - return + return } } -const ActivityDisplayComponent: React.FC = ({tracker, currentUser, userRoles}) => { +const ActivityDisplayComponent: React.FC = ({tracker, currentUser, userRoles, app, chatPanel}) => { const [showBarGraph, setShowBarGraph] = React.useState(true); const switchGraph = () => {setShowBarGraph(prev => !prev)}; const barGraph = ActivityBarGraph({tracker}); - const dotPlot = ActivityDotPlot({tracker}); + const dotPlot = ActivityDotPlot({tracker, app, chatPanel}); return
{userRoles.get(currentUser.identity!.username) === Role.Owner && ( diff --git a/packages/collaboration/src/activitydotplot.tsx b/packages/collaboration/src/activitydotplot.tsx index b21da2a..e07320a 100644 --- a/packages/collaboration/src/activitydotplot.tsx +++ b/packages/collaboration/src/activitydotplot.tsx @@ -1,12 +1,22 @@ import { Notebook, NotebookPanel } from '@jupyterlab/notebook'; +import { JupyterFrontEnd } from '@jupyterlab/application'; import * as React from 'react'; import Plot from 'react-plotly.js'; import { GraphProps } from './activitydisplay'; import { SimpleUser } from './cellTracker'; +import { SidePanel } from '@jupyterlab/ui-components'; +import { Chatbox } from './chatbox'; -export const ActivityDotPlot: React.FC = ({tracker}) => { +interface DotPlotProps extends GraphProps { + + app: JupyterFrontEnd; + chatPanel: SidePanel + +} + +export const ActivityDotPlot: React.FC = ({tracker, app, chatPanel}) => { const [state, setState] = React.useState([]); @@ -102,6 +112,25 @@ export const ActivityDotPlot: React.FC = ({tracker}) => { } }; - return + const handleDotClick = (data: any) => { + + app.shell.activateById('jp-chat-panel'); + + const chatbox = chatPanel.widgets.find(widget => widget.id === 'jp-chatbox') as Chatbox | null; + + if (chatbox) { + + chatbox.show(); + chatbox.focusOnWritingField(); + + } + + const polls = chatPanel.widgets.find(widget => widget.id === 'jp-polls'); + + if (polls) polls.hide(); + + } + + return } \ No newline at end of file diff --git a/packages/collaboration/src/chatbox.tsx b/packages/collaboration/src/chatbox.tsx index bf33fb2..246c0a5 100644 --- a/packages/collaboration/src/chatbox.tsx +++ b/packages/collaboration/src/chatbox.tsx @@ -6,26 +6,35 @@ import { User } from '@jupyterlab/services'; import { WebSocketAwarenessProvider, IChatMessage } from '@jupyter/docprovider'; import * as msgEnc from './messageEncoding'; -import { Roles } from './roles'; export class Chatbox extends ReactWidget { private _currentUser: User.IManager; private _awarenessProvider: WebSocketAwarenessProvider; - private _roles: Roles; - constructor(currentUser: User.IManager, awarenessProvider: WebSocketAwarenessProvider, roles: Roles) { + constructor(currentUser: User.IManager, awarenessProvider: WebSocketAwarenessProvider) { super(); this._currentUser = currentUser; this._awarenessProvider = awarenessProvider; - this._roles = roles; this.addClass('jp-Chat-Panel') } + focusOnWritingField() { + + const writingField = this.node?.querySelector('.jp-Chat-WritableField') as HTMLTextAreaElement | null; + + if (writingField) { + + writingField.focus(); + + } + + } + render(): JSX.Element { - return ; + return ; } } @@ -34,7 +43,6 @@ interface ChatBoxComponentProps { currentUser: User.IManager; awarenessProvider: WebSocketAwarenessProvider; - userRoles: Roles } @@ -48,11 +56,10 @@ interface ChatBoxComponentState { } -const ChatBoxComponent: React.FC = ({currentUser, awarenessProvider, userRoles}) => { +const ChatBoxComponent: React.FC = ({currentUser, awarenessProvider}) => { const user = currentUser; const aProvider = awarenessProvider; -// const roles = userRoles; // Getter and setter for the chat state const [state, setState] = React.useState({message: '', messages: []});