Skip to content

Commit

Permalink
Only display activity if owner + owner warning dialog
Browse files Browse the repository at this point in the history
  • Loading branch information
Liototo committed May 10, 2024
1 parent e792424 commit 350de83
Show file tree
Hide file tree
Showing 7 changed files with 82 additions and 96 deletions.
40 changes: 3 additions & 37 deletions packages/collaboration-extension/src/collaboration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import { IAwareness } from '@jupyter/ydoc';

import {
ActivityDisplay,
addDisplay,
Chatbox,
CollaboratorsPanel,
IGlobalAwareness,
Expand Down Expand Up @@ -161,7 +160,7 @@ export const rtcPanelPlugin: JupyterFrontEndPlugin<void> = {
userPanel.addClass('jp-RTCPanel');
app.shell.add(userPanel, 'left', { rank: 300 });

const roles = new Roles(user, awareness, awarenessProvider);
const roles = new Roles(user, awareness, awarenessProvider, translator);

const currentUserPanel = new UserInfoPanel(user, roles);
currentUserPanel.title.label = trans.__('User info');
Expand All @@ -181,11 +180,10 @@ export const rtcPanelPlugin: JupyterFrontEndPlugin<void> = {
collaboratorsPanel.title.label = trans.__('Online Collaborators');
userPanel.addWidget(collaboratorsPanel);

const activityDisplay = new ActivityDisplay(tracker);
const activityDisplay = new ActivityDisplay(tracker, user, roles);
activityDisplay.title.label = trans.__('User activity');
userPanel.addWidget(activityDisplay);


const chatPanel = new SidePanel({
alignment: 'justify'
});
Expand All @@ -204,6 +202,7 @@ export const rtcPanelPlugin: JupyterFrontEndPlugin<void> = {

pollTab.title.label = trans.__('Polls');
chatPanel.addWidget(pollTab);

}
};

Expand Down Expand Up @@ -255,37 +254,4 @@ export const cellTracker: JupyterFrontEndPlugin<void> = {

}

}

export const activeUsersDisplay: JupyterFrontEndPlugin<void> = {

id: '@jupyter/collaboration-extension:activeUsersDisplay',
description:
'Display how many users are working on each cell',
autoStart: true,
requires: [INotebookTracker],
activate: (
app: JupyterFrontEnd,
tracker: INotebookTracker
): void => {

tracker.widgetAdded.connect((sender, notebookPanel) => {
const notebook = notebookPanel.content;

notebook.model?.cells.changed.connect(() => {

notebook.widgets.forEach(cell => {
addDisplay(cell);

cell.model.metadataChanged.connect(() => {
addDisplay(cell);
})
});

});

notebook.widgets.forEach(cell => addDisplay(cell));

});
}
}
6 changes: 2 additions & 4 deletions packages/collaboration-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import {
rtcGlobalAwarenessPlugin,
rtcPanelPlugin,
userEditorCursors,
cellTracker,
activeUsersDisplay
cellTracker
} from './collaboration';
import { sharedLink } from './sharedlink';

Expand All @@ -40,8 +39,7 @@ const plugins: JupyterFrontEndPlugin<any>[] = [
rtcPanelPlugin,
sharedLink,
userEditorCursors,
cellTracker,
activeUsersDisplay
cellTracker
];

export default plugins;
42 changes: 0 additions & 42 deletions packages/collaboration/src/activeusersdisplay.ts

This file was deleted.

49 changes: 41 additions & 8 deletions packages/collaboration/src/activitydisplay.tsx
Original file line number Diff line number Diff line change
@@ -1,22 +1,31 @@
import * as React from 'react';
import { ReactWidget } from '@jupyterlab/apputils';
import { INotebookTracker, Notebook, NotebookPanel } from '@jupyterlab/notebook';
import { User } from '@jupyterlab/services';

import * as React from 'react';
import Plot from 'react-plotly.js';

import { Roles, Role } from './roles';


export class ActivityDisplay extends ReactWidget {

private _tracker: INotebookTracker
private _currentUser: User.IManager;
private _roles: Roles;

constructor(tracker: INotebookTracker) {
constructor(tracker: INotebookTracker, currentUser: User.IManager, roles: Roles) {

super();

this._tracker = tracker;
this._currentUser = currentUser;
this._roles = roles;

}

render() {
return <ActivityDisplayComponent tracker={this._tracker}/>
return <ActivityDisplayComponent tracker={this._tracker} currentUser={this._currentUser} userRoles={this._roles}/>
}

}
Expand All @@ -25,10 +34,15 @@ export class ActivityDisplay extends ReactWidget {
interface ActivityDisplayComponentProps {

tracker: INotebookTracker;
currentUser: User.IManager;
userRoles: Roles

}

const ActivityDisplayComponent: React.FC<ActivityDisplayComponentProps> = ({tracker}) => {
const ActivityDisplayComponent: React.FC<ActivityDisplayComponentProps> = ({tracker, currentUser, userRoles}) => {

const user = currentUser;
const roles = userRoles;

const [state, setState] = React.useState<number[]>([]);

Expand Down Expand Up @@ -75,16 +89,35 @@ const ActivityDisplayComponent: React.FC<ActivityDisplayComponentProps> = ({trac
x: state,
type: 'bar',
orientation: 'h',
marker: {color: 'green'}
marker: {color: 'green'},
hovertemplate: '%{x} user(s) on cell %{y}'
}] as Plotly.Data[];

const layout = {
width: 300,
height: 500,
xaxis: {title: 'Active users'},
yaxis: {title: 'Cell', autorange: 'reversed' as const}
xaxis: {
title: 'Active users'
},
yaxis: {
title: 'Cell',
autorange: 'reversed' as const
},
margin: {
l: 60,
r: 30,
t: 30,
b: 60
},
hoverlabel: {
namelength: 0
}
};

return <Plot className='jp-graph' data={data} layout={layout}/>
return <div>
{roles.get(user.identity!.username) === Role.Owner && (
<Plot className='jp-graph' data={data} layout={layout}/>
)}
</div>

}
4 changes: 2 additions & 2 deletions packages/collaboration/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ export * from './messageEncoding';
export * from './polls';
export * from './roles';
export * from './cellTracker';
export * from './activeusersdisplay';
export * from './activitydisplay';
export * from './activitydisplay';
export * from './ownerdialog';
17 changes: 17 additions & 0 deletions packages/collaboration/src/ownerdialog.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Dialog, showDialog } from '@jupyterlab/apputils';
import { ITranslator, nullTranslator } from '@jupyterlab/translation';

export async function showOwnerDialog(translator: ITranslator | null): Promise<Dialog.IResult<string>> {

const trans = (translator ?? nullTranslator).load('collaboration');

return showDialog({
title: trans.__('Owner'),
body: trans.__('You have been set as the session owner and have been granted extra privileges. Be aware that ' +
'refreshing or closing the page may make you lose those privileges.'),
buttons: [
Dialog.okButton({label: trans.__('OK')})
]
});

}
20 changes: 17 additions & 3 deletions packages/collaboration/src/roles.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { IChatMessage, WebSocketAwarenessProvider } from '@jupyter/docprovider';
import { User } from '@jupyterlab/services';
import { ITranslator } from '@jupyterlab/translation';

import { Awareness } from 'y-protocols/awareness';

import { IChatMessage, WebSocketAwarenessProvider } from '@jupyter/docprovider';
import { ICollaboratorAwareness } from './tokens';

import { showOwnerDialog } from './ownerdialog';
import { ICollaboratorAwareness } from './tokens';
import * as msgEnc from './messageEncoding';

import * as time from 'lib0/time';


Expand All @@ -26,12 +30,14 @@ export class Roles {
private _aProvider: WebSocketAwarenessProvider;
private _connectedAt: number;
private _currentUser: User.IManager;
private _translator: ITranslator | null;

constructor(currentUser: User.IManager, awareness: Awareness, aProvider: WebSocketAwarenessProvider) {
constructor(currentUser: User.IManager, awareness: Awareness, aProvider: WebSocketAwarenessProvider, translator: ITranslator | null) {
this._awareness = awareness;
this._aProvider = aProvider;
this._connectedAt = time.getUnixTime();
this._currentUser = currentUser;
this._translator = translator;

this._awareness.on('change', this._onAwarenessChanged);

Expand All @@ -47,6 +53,14 @@ export class Roles {
// Once connection is set, request other users' timestamps to check if one came before
setTimeout(() => {this._aProvider.sendMessage('times')}, 500);

setTimeout(async () => {
if (this._map.get(currentUser.identity!.username) === Role.Owner) {

await showOwnerDialog(this._translator);

}
}, 1000);

}

// Handle collaborator change
Expand Down

0 comments on commit 350de83

Please sign in to comment.