Skip to content

Commit a95e20c

Browse files
committed
Refactor activity graphs
1 parent 2445ffe commit a95e20c

File tree

3 files changed

+102
-95
lines changed

3 files changed

+102
-95
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import { INotebookTracker, Notebook, NotebookPanel } from '@jupyterlab/notebook';
2+
import { User } from '@jupyterlab/services';
3+
4+
import * as React from 'react';
5+
import Plot from 'react-plotly.js';
6+
7+
import { Roles, Role } from './roles';
8+
9+
10+
interface ActivityDisplayComponentProps {
11+
12+
tracker: INotebookTracker;
13+
currentUser: User.IManager;
14+
userRoles: Roles
15+
16+
}
17+
18+
export const ActivityBarGraph: React.FC<ActivityDisplayComponentProps> = ({tracker, currentUser, userRoles}) => {
19+
20+
const user = currentUser;
21+
const roles = userRoles;
22+
23+
const [state, setState] = React.useState<number[]>([]);
24+
25+
React.useEffect(() => {
26+
27+
const updateCounts = (notebook: Notebook) => {
28+
29+
const counts = notebook.widgets.map(cell => {
30+
let activeUsers = cell.model.getMetadata('active_users');
31+
if (!activeUsers || !Array.isArray(activeUsers)) return 0;
32+
return activeUsers.length;
33+
});
34+
35+
setState(counts);
36+
37+
}
38+
39+
const startTracking = (_: any, panel: NotebookPanel) => {
40+
41+
const notebook = panel.content;
42+
43+
notebook.model?.cells.changed.connect(() => {
44+
45+
updateCounts(notebook);
46+
47+
notebook.widgets.forEach(cell => {
48+
cell.model.metadataChanged.connect(() => {
49+
updateCounts(notebook);
50+
})
51+
})
52+
53+
})
54+
55+
}
56+
57+
tracker.widgetAdded.connect(startTracking);
58+
59+
return () => {
60+
tracker.widgetAdded.disconnect(startTracking);
61+
}
62+
63+
}, [tracker]);
64+
65+
const data = [{
66+
y: state.map((_, index) => index + 1),
67+
x: state,
68+
type: 'bar',
69+
orientation: 'h',
70+
marker: {color: 'green'},
71+
hovertemplate: '%{x} user(s) on cell %{y}<extra></extra>'
72+
}] as Plotly.Data[];
73+
74+
const layout = {
75+
width: 300,
76+
height: 500,
77+
xaxis: {
78+
title: 'Active users'
79+
},
80+
yaxis: {
81+
title: 'Cell',
82+
autorange: 'reversed' as const
83+
},
84+
margin: {
85+
l: 60,
86+
r: 30,
87+
t: 30,
88+
b: 60
89+
}
90+
};
91+
92+
return <div>
93+
{roles.get(user.identity!.username) === Role.Owner && (
94+
<Plot className='jp-graph' data={data} layout={layout}/>
95+
)}
96+
</div>
97+
98+
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { ReactWidget } from '@jupyterlab/apputils';
2-
import { INotebookTracker, Notebook, NotebookPanel } from '@jupyterlab/notebook';
2+
import { INotebookTracker } from '@jupyterlab/notebook';
33
import { User } from '@jupyterlab/services';
44

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

8-
import { Roles, Role } from './roles';
7+
import { ActivityBarGraph } from './activitybargraph';
8+
import { Roles } from './roles';
99

1010

1111
export class ActivityDisplay extends ReactWidget {
@@ -25,98 +25,7 @@ export class ActivityDisplay extends ReactWidget {
2525
}
2626

2727
render() {
28-
return <ActivityDisplayComponent tracker={this._tracker} currentUser={this._currentUser} userRoles={this._roles}/>
28+
return <ActivityBarGraph tracker={this._tracker} currentUser={this._currentUser} userRoles={this._roles}/>
2929
}
3030

3131
}
32-
33-
34-
interface ActivityDisplayComponentProps {
35-
36-
tracker: INotebookTracker;
37-
currentUser: User.IManager;
38-
userRoles: Roles
39-
40-
}
41-
42-
const ActivityDisplayComponent: React.FC<ActivityDisplayComponentProps> = ({tracker, currentUser, userRoles}) => {
43-
44-
const user = currentUser;
45-
const roles = userRoles;
46-
47-
const [state, setState] = React.useState<number[]>([]);
48-
49-
React.useEffect(() => {
50-
51-
const updateCounts = (notebook: Notebook) => {
52-
53-
const counts = notebook.widgets.map(cell => {
54-
let activeUsers = cell.model.getMetadata('active_users');
55-
if (!activeUsers || !Array.isArray(activeUsers)) return 0;
56-
return activeUsers.length;
57-
});
58-
59-
setState(counts);
60-
61-
}
62-
63-
const startTracking = (_: any, panel: NotebookPanel) => {
64-
65-
const notebook = panel.content;
66-
67-
notebook.model?.cells.changed.connect(() => {
68-
69-
updateCounts(notebook);
70-
71-
notebook.widgets.forEach(cell => {
72-
cell.model.metadataChanged.connect(() => {
73-
updateCounts(notebook);
74-
})
75-
})
76-
77-
})
78-
79-
}
80-
81-
tracker.widgetAdded.connect(startTracking);
82-
83-
return () => {
84-
tracker.widgetAdded.disconnect(startTracking);
85-
}
86-
87-
}, [tracker]);
88-
89-
const data = [{
90-
y: state.map((_, index) => index + 1),
91-
x: state,
92-
type: 'bar',
93-
orientation: 'h',
94-
marker: {color: 'green'},
95-
hovertemplate: '%{x} user(s) on cell %{y}<extra></extra>'
96-
}] as Plotly.Data[];
97-
98-
const layout = {
99-
width: 300,
100-
height: 500,
101-
xaxis: {
102-
title: 'Active users'
103-
},
104-
yaxis: {
105-
title: 'Cell',
106-
autorange: 'reversed' as const
107-
},
108-
margin: {
109-
l: 60,
110-
r: 30,
111-
t: 30,
112-
b: 60
113-
}
114-
};
115-
116-
return <div>
117-
{roles.get(user.identity!.username) === Role.Owner && (
118-
<Plot className='jp-graph' data={data} layout={layout}/>
119-
)}
120-
</div>
121-
122-
}

packages/collaboration/src/activitydotplot.tsx

Whitespace-only changes.

0 commit comments

Comments
 (0)