-
-
Notifications
You must be signed in to change notification settings - Fork 3.1k
/
collaboratorspanel.tsx
149 lines (119 loc) · 3.62 KB
/
collaboratorspanel.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
import * as React from 'react';
import { Awareness } from 'y-protocols/awareness';
import { Panel } from '@lumino/widgets';
import { ReactWidget } from '@jupyterlab/apputils';
import { User } from '@jupyterlab/services';
import { PathExt } from '@jupyterlab/coreutils';
import { ICollaboratorAwareness } from './utils';
/**
* The CSS class added to collaborators list container.
*/
const COLLABORATORS_LIST_CLASS = 'jp-CollaboratorsList';
/**
* The CSS class added to each collaborator element.
*/
const COLLABORATOR_CLASS = 'jp-Collaborator';
/**
* The CSS class added to each collaborator element.
*/
const CLICKABLE_COLLABORATOR_CLASS = 'jp-ClickableCollaborator';
/**
* The CSS class added to each collaborator icon.
*/
const COLLABORATOR_ICON_CLASS = 'jp-CollaboratorIcon';
export class CollaboratorsPanel extends Panel {
private _currentUser: User.IManager;
private _awareness: Awareness;
private _body: CollaboratorsBody;
constructor(
currentUser: User.IManager,
awareness: Awareness,
fileopener: (path: string) => void
) {
super({});
this._awareness = awareness;
this._currentUser = currentUser;
this._body = new CollaboratorsBody(fileopener);
this.addWidget(this._body);
this.update();
this._awareness.on('change', this._onAwarenessChanged);
}
/**
* Handle collaborator change.
*/
private _onAwarenessChanged = () => {
const state = this._awareness.getStates();
const collaborators: ICollaboratorAwareness[] = [];
state.forEach((value: ICollaboratorAwareness, key: any) => {
if (
this._currentUser.isReady &&
value.user.name !== this._currentUser.identity!.name
) {
collaborators.push(value);
}
});
this._body.collaborators = collaborators;
};
}
/**
* The collaborators list.
*/
export class CollaboratorsBody extends ReactWidget {
private _collaborators: ICollaboratorAwareness[] = [];
private _fileopener: (path: string) => void;
constructor(fileopener: (path: string) => void) {
super();
this._fileopener = fileopener;
this.addClass(COLLABORATORS_LIST_CLASS);
}
get collaborators(): ICollaboratorAwareness[] {
return this._collaborators;
}
set collaborators(value: ICollaboratorAwareness[]) {
this._collaborators = value;
this.update();
}
render(): React.ReactElement<any>[] {
return this._collaborators.map((value, i) => {
let canOpenCurrent = false;
let current = '';
let separator = '';
let currentFileLocation = '';
if (value.current) {
canOpenCurrent = true;
currentFileLocation = value.current.split(':')[1];
current = PathExt.basename(currentFileLocation);
current =
current.length > 25 ? current.slice(0, 12).concat(`…`) : current;
separator = '•';
}
const onClick = () => {
if (canOpenCurrent) {
this._fileopener(currentFileLocation);
}
};
const displayName = `${value.user.display_name} ${separator} ${current}`;
return (
<div
className={
canOpenCurrent
? `${CLICKABLE_COLLABORATOR_CLASS} ${COLLABORATOR_CLASS}`
: COLLABORATOR_CLASS
}
key={i}
onClick={onClick}
>
<div
className={COLLABORATOR_ICON_CLASS}
style={{ backgroundColor: value.user.color }}
>
<span>{value.user.initials}</span>
</div>
<span>{displayName}</span>
</div>
);
});
}
}