jupyterlab-chat 0.16.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/factory.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { IAttachmentOpenerRegistry, IChatCommandRegistry, IInputToolbarRegistry, IMessageFooterRegistry } from '@jupyter/chat';
1
+ import { IAttachmentOpenerRegistry, IChatCommandRegistry, IInputToolbarRegistry, IMessageFooterRegistry, IInputToolbarRegistryFactory } from '@jupyter/chat';
2
2
  import { IThemeManager } from '@jupyterlab/apputils';
3
3
  import { IDocumentManager } from '@jupyterlab/docmanager';
4
4
  import { ABCWidgetFactory, DocumentRegistry } from '@jupyterlab/docregistry';
@@ -8,7 +8,7 @@ import { ISignal } from '@lumino/signaling';
8
8
  import { LabChatModel } from './model';
9
9
  import { LabChatPanel } from './widget';
10
10
  import { YChat } from './ychat';
11
- import { IInputToolbarRegistryFactory, ILabChatConfig, IWidgetConfig } from './token';
11
+ import { ILabChatConfig, IWidgetConfig } from './token';
12
12
  /**
13
13
  * The object provided by the chatDocument extension.
14
14
  * It is used to set the current config (from settings) to newly created chat widget,
package/lib/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  export * from './factory';
2
2
  export * from './model';
3
3
  export * from './token';
4
+ export * from './utils';
4
5
  export * from './widget';
5
6
  export * from './ychat';
package/lib/index.js CHANGED
@@ -5,5 +5,6 @@
5
5
  export * from './factory';
6
6
  export * from './model';
7
7
  export * from './token';
8
+ export * from './utils';
8
9
  export * from './widget';
9
10
  export * from './ychat';
package/lib/model.d.ts CHANGED
@@ -54,12 +54,10 @@ export declare class LabChatModel extends AbstractChatModel implements DocumentR
54
54
  get sharedModel(): YChat;
55
55
  get contentChanged(): ISignal<this, void>;
56
56
  get stateChanged(): ISignal<this, IChangedArgs<any, any, string>>;
57
- get ready(): Promise<void>;
58
57
  get dirty(): boolean;
59
58
  set dirty(value: boolean);
60
59
  get readOnly(): boolean;
61
60
  set readOnly(value: boolean);
62
- get disposed(): ISignal<LabChatModel, void>;
63
61
  set id(value: string | undefined);
64
62
  dispose(): void;
65
63
  toString(): string;
@@ -96,11 +94,9 @@ export declare class LabChatModel extends AbstractChatModel implements DocumentR
96
94
  private _onchange;
97
95
  readonly defaultKernelName: string;
98
96
  readonly defaultKernelLanguage: string;
99
- private _ready;
100
97
  private _sharedModel;
101
98
  private _dirty;
102
99
  private _readOnly;
103
- private _disposed;
104
100
  private _contentChanged;
105
101
  private _stateChanged;
106
102
  private _timeoutWriting;
package/lib/model.js CHANGED
@@ -3,7 +3,7 @@
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
5
  import { AbstractChatModel, AbstractChatContext } from '@jupyter/chat';
6
- import { PromiseDelegate, UUID } from '@lumino/coreutils';
6
+ import { UUID } from '@lumino/coreutils';
7
7
  import { Signal } from '@lumino/signaling';
8
8
  import { YChat } from './ychat';
9
9
  const WRITING_DELAY = 1000;
@@ -172,10 +172,8 @@ export class LabChatModel extends AbstractChatModel {
172
172
  };
173
173
  this.defaultKernelName = '';
174
174
  this.defaultKernelLanguage = '';
175
- this._ready = new PromiseDelegate();
176
175
  this._dirty = false;
177
176
  this._readOnly = false;
178
- this._disposed = new Signal(this);
179
177
  this._contentChanged = new Signal(this);
180
178
  this._stateChanged = new Signal(this);
181
179
  this._timeoutWriting = null;
@@ -209,9 +207,6 @@ export class LabChatModel extends AbstractChatModel {
209
207
  get stateChanged() {
210
208
  return this._stateChanged;
211
209
  }
212
- get ready() {
213
- return this._ready.promise;
214
- }
215
210
  get dirty() {
216
211
  return this._dirty;
217
212
  }
@@ -224,13 +219,10 @@ export class LabChatModel extends AbstractChatModel {
224
219
  set readOnly(value) {
225
220
  this._readOnly = value;
226
221
  }
227
- get disposed() {
228
- return this._disposed;
229
- }
230
222
  set id(value) {
231
223
  super.id = value;
232
224
  if (value) {
233
- this._ready.resolve();
225
+ this.setReady();
234
226
  }
235
227
  }
236
228
  dispose() {
@@ -239,7 +231,6 @@ export class LabChatModel extends AbstractChatModel {
239
231
  }
240
232
  super.dispose();
241
233
  this._sharedModel.dispose();
242
- this._disposed.emit();
243
234
  Signal.clearData(this);
244
235
  }
245
236
  toString() {
@@ -260,7 +251,7 @@ export class LabChatModel extends AbstractChatModel {
260
251
  async messagesInserted(index, messages) {
261
252
  // Ensure the chat has an ID before inserting the messages, to properly catch the
262
253
  // unread messages (the last read message is saved using the chat ID).
263
- return this._ready.promise.then(() => {
254
+ return this.ready.then(() => {
264
255
  super.messagesInserted(index, messages);
265
256
  });
266
257
  }
package/lib/token.d.ts CHANGED
@@ -1,9 +1,10 @@
1
- import { IConfig, IActiveCellManager, ISelectionWatcher, ChatWidget, IInputToolbarRegistry } from '@jupyter/chat';
1
+ import { IConfig, IActiveCellManager, ISelectionWatcher, ChatWidget } from '@jupyter/chat';
2
2
  import { WidgetTracker } from '@jupyterlab/apputils';
3
3
  import { DocumentRegistry } from '@jupyterlab/docregistry';
4
4
  import { Token } from '@lumino/coreutils';
5
5
  import { ISignal } from '@lumino/signaling';
6
- import { ChatPanel, LabChatPanel } from './widget';
6
+ import { LabChatPanel } from './widget';
7
+ import { MultiChatPanel as ChatPanel } from '@jupyter/chat';
7
8
  /**
8
9
  * The file type for a chat document.
9
10
  */
@@ -64,6 +65,10 @@ export declare const CommandIDs: {
64
65
  * Open a chat file.
65
66
  */
66
67
  openChat: string;
68
+ /**
69
+ * Create and open.
70
+ */
71
+ createAndOpen: string;
67
72
  /**
68
73
  * Move a main widget to the side panel.
69
74
  */
@@ -76,6 +81,10 @@ export declare const CommandIDs: {
76
81
  * Focus the input of the current chat.
77
82
  */
78
83
  focusInput: string;
84
+ /**
85
+ * Rename the current chat.
86
+ */
87
+ renameChat: string;
79
88
  };
80
89
  /**
81
90
  * The chat panel token.
@@ -89,19 +98,6 @@ export declare const IActiveCellManagerToken: Token<IActiveCellManager>;
89
98
  * The selection watcher plugin.
90
99
  */
91
100
  export declare const ISelectionWatcherToken: Token<ISelectionWatcher>;
92
- /**
93
- * The input toolbar registry factory.
94
- */
95
- export interface IInputToolbarRegistryFactory {
96
- /**
97
- * Create an input toolbar registry.
98
- */
99
- create: () => IInputToolbarRegistry;
100
- }
101
- /**
102
- * The token of the factory to create an input toolbar registry.
103
- */
104
- export declare const IInputToolbarRegistryFactory: Token<IInputToolbarRegistryFactory>;
105
101
  /**
106
102
  * The token to add a welcome message to the chat.
107
103
  * This token is not provided by default, but can be provided by third party extensions
package/lib/token.js CHANGED
@@ -32,6 +32,10 @@ export const CommandIDs = {
32
32
  * Open a chat file.
33
33
  */
34
34
  openChat: 'jupyterlab-chat:open',
35
+ /**
36
+ * Create and open.
37
+ */
38
+ createAndOpen: 'jupyterlab-chat:createAndOpen',
35
39
  /**
36
40
  * Move a main widget to the side panel.
37
41
  */
@@ -43,7 +47,11 @@ export const CommandIDs = {
43
47
  /**
44
48
  * Focus the input of the current chat.
45
49
  */
46
- focusInput: 'jupyterlab-chat:focusInput'
50
+ focusInput: 'jupyterlab-chat:focusInput',
51
+ /**
52
+ * Rename the current chat.
53
+ */
54
+ renameChat: 'jupyterlab-chat:renameChat'
47
55
  };
48
56
  /**
49
57
  * The chat panel token.
@@ -57,10 +65,6 @@ export const IActiveCellManagerToken = new Token('jupyterlab-chat:IActiveCellMan
57
65
  * The selection watcher plugin.
58
66
  */
59
67
  export const ISelectionWatcherToken = new Token('jupyterlab-chat:ISelectionWatcher');
60
- /**
61
- * The token of the factory to create an input toolbar registry.
62
- */
63
- export const IInputToolbarRegistryFactory = new Token('jupyterlab-chat:IInputToolbarRegistryFactory');
64
68
  /**
65
69
  * The token to add a welcome message to the chat.
66
70
  * This token is not provided by default, but can be provided by third party extensions
package/lib/utils.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ *
3
+ * @param defaultDirectory - the default directory.
4
+ * @param path - the path of the chat file.
5
+ * @returns - the display name of the chat.
6
+ */
7
+ export declare function getDisplayName(path: string, defaultDirectory?: string): string;
package/lib/utils.js ADDED
@@ -0,0 +1,23 @@
1
+ /*
2
+ * Copyright (c) Jupyter Development Team.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ import { PathExt } from '@jupyterlab/coreutils';
6
+ import { chatFileType } from './token';
7
+ /**
8
+ *
9
+ * @param defaultDirectory - the default directory.
10
+ * @param path - the path of the chat file.
11
+ * @returns - the display name of the chat.
12
+ */
13
+ export function getDisplayName(path, defaultDirectory) {
14
+ const inDefault = defaultDirectory
15
+ ? !PathExt.relative(defaultDirectory, path).startsWith('..')
16
+ : true;
17
+ const pattern = new RegExp(`${chatFileType.extensions[0]}$`, 'g');
18
+ return (inDefault
19
+ ? defaultDirectory
20
+ ? PathExt.relative(defaultDirectory, path)
21
+ : path
22
+ : '/' + path).replace(pattern, '');
23
+ }
package/lib/widget.d.ts CHANGED
@@ -1,14 +1,6 @@
1
- import { ChatWidget, IAttachmentOpenerRegistry, IChatCommandRegistry, IChatModel, IMessageFooterRegistry } from '@jupyter/chat';
2
- import { Contents } from '@jupyterlab/services';
3
- import { IThemeManager } from '@jupyterlab/apputils';
1
+ import { ChatWidget } from '@jupyter/chat';
4
2
  import { DocumentWidget } from '@jupyterlab/docregistry';
5
- import { IRenderMimeRegistry } from '@jupyterlab/rendermime';
6
- import { SidePanel } from '@jupyterlab/ui-components';
7
- import { CommandRegistry } from '@lumino/commands';
8
- import { Message } from '@lumino/messaging';
9
- import { Panel } from '@lumino/widgets';
10
3
  import { LabChatModel } from './model';
11
- import { IInputToolbarRegistryFactory } from './token';
12
4
  /**
13
5
  * DocumentWidget: widget that represents the view or editor for a file type.
14
6
  */
@@ -27,104 +19,3 @@ export declare class LabChatPanel extends DocumentWidget<ChatWidget, LabChatMode
27
19
  */
28
20
  private _unreadChanged;
29
21
  }
30
- /**
31
- * Sidepanel widget including the chats and the add chat button.
32
- */
33
- export declare class ChatPanel extends SidePanel {
34
- /**
35
- * The constructor of the chat panel.
36
- */
37
- constructor(options: ChatPanel.IOptions);
38
- /**
39
- * Getter and setter of the defaultDirectory.
40
- */
41
- get defaultDirectory(): string;
42
- set defaultDirectory(value: string);
43
- /**
44
- * Add a new widget to the chat panel.
45
- *
46
- * @param model - the model of the chat widget
47
- * @param name - the name of the chat.
48
- */
49
- addChat(model: IChatModel): ChatWidget;
50
- /**
51
- * Update the list of available chats in the default directory.
52
- */
53
- updateChatList: () => Promise<void>;
54
- /**
55
- * Open a chat if it exists in the side panel.
56
- *
57
- * @param path - the path of the chat.
58
- * @returns a boolean, whether the chat existed in the side panel or not.
59
- */
60
- openIfExists(path: string): boolean;
61
- /**
62
- * A message handler invoked on an `'after-show'` message.
63
- */
64
- protected onAfterShow(msg: Message): void;
65
- /**
66
- * Return the index of the chat in the list (-1 if not opened).
67
- *
68
- * @param name - the chat name.
69
- */
70
- private _getChatIndex;
71
- /**
72
- * Expand the chat from its index.
73
- */
74
- private _expandChat;
75
- /**
76
- * Handle `change` events for the HTMLSelect component.
77
- */
78
- private _chatSelected;
79
- /**
80
- * Triggered when a section is toogled. If the section is opened, all others
81
- * sections are closed.
82
- */
83
- private _onExpansionToggled;
84
- private _chatNamesChanged;
85
- private _commands;
86
- private _defaultDirectory;
87
- private _contentsManager;
88
- private _openChat;
89
- private _rmRegistry;
90
- private _themeManager;
91
- private _chatCommandRegistry?;
92
- private _attachmentOpenerRegistry?;
93
- private _inputToolbarFactory?;
94
- private _messageFooterRegistry?;
95
- private _welcomeMessage?;
96
- }
97
- /**
98
- * The chat panel namespace.
99
- */
100
- export declare namespace ChatPanel {
101
- /**
102
- * Options of the constructor of the chat panel.
103
- */
104
- interface IOptions extends SidePanel.IOptions {
105
- commands: CommandRegistry;
106
- contentsManager: Contents.IManager;
107
- rmRegistry: IRenderMimeRegistry;
108
- themeManager: IThemeManager | null;
109
- defaultDirectory: string;
110
- chatCommandRegistry?: IChatCommandRegistry;
111
- attachmentOpenerRegistry?: IAttachmentOpenerRegistry;
112
- inputToolbarFactory?: IInputToolbarRegistryFactory;
113
- messageFooterRegistry?: IMessageFooterRegistry;
114
- welcomeMessage?: string;
115
- }
116
- }
117
- /**
118
- * The chat section namespace.
119
- */
120
- export declare namespace ChatSection {
121
- /**
122
- * Options to build a chat section.
123
- */
124
- interface IOptions extends Panel.IOptions {
125
- commands: CommandRegistry;
126
- defaultDirectory: string;
127
- widget: ChatWidget;
128
- path: string;
129
- }
130
- }
package/lib/widget.js CHANGED
@@ -2,20 +2,9 @@
2
2
  * Copyright (c) Jupyter Development Team.
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
- import { ChatWidget, readIcon } from '@jupyter/chat';
6
- import { PathExt } from '@jupyterlab/coreutils';
7
5
  import { DocumentWidget } from '@jupyterlab/docregistry';
8
- import { addIcon, closeIcon, CommandToolbarButton, HTMLSelect, launchIcon, PanelWithToolbar, ReactWidget, SidePanel, Spinner, ToolbarButton } from '@jupyterlab/ui-components';
9
- import { Signal } from '@lumino/signaling';
10
- import React, { useState } from 'react';
11
- import { CommandIDs, chatFileType } from './token';
12
6
  const MAIN_PANEL_CLASS = 'jp-lab-chat-main-panel';
13
7
  const TITLE_UNREAD_CLASS = 'jp-lab-chat-title-unread';
14
- const SIDEPANEL_CLASS = 'jp-lab-chat-sidepanel';
15
- const ADD_BUTTON_CLASS = 'jp-lab-chat-add';
16
- const OPEN_SELECT_CLASS = 'jp-lab-chat-open';
17
- const SECTION_CLASS = 'jp-lab-chat-section';
18
- const TOOLBAR_CLASS = 'jp-lab-chat-toolbar';
19
8
  /**
20
9
  * DocumentWidget: widget that represents the view or editor for a file type.
21
10
  */
@@ -55,309 +44,3 @@ export class LabChatPanel extends DocumentWidget {
55
44
  return this.context.model;
56
45
  }
57
46
  }
58
- /**
59
- * Sidepanel widget including the chats and the add chat button.
60
- */
61
- export class ChatPanel extends SidePanel {
62
- /**
63
- * The constructor of the chat panel.
64
- */
65
- constructor(options) {
66
- super(options);
67
- /**
68
- * Update the list of available chats in the default directory.
69
- */
70
- this.updateChatList = async () => {
71
- const extension = chatFileType.extensions[0];
72
- this._contentsManager
73
- .get(this._defaultDirectory)
74
- .then((contentModel) => {
75
- const chatsNames = {};
76
- contentModel.content
77
- .filter(f => f.type === 'file' && f.name.endsWith(extension))
78
- .forEach(f => {
79
- chatsNames[PathExt.basename(f.name, extension)] = f.path;
80
- });
81
- this._chatNamesChanged.emit(chatsNames);
82
- })
83
- .catch(e => console.error('Error getting the chat files from drive', e));
84
- };
85
- /**
86
- * Handle `change` events for the HTMLSelect component.
87
- */
88
- this._chatSelected = (event) => {
89
- const select = event.target;
90
- const path = select.value;
91
- const name = select.options[select.selectedIndex].textContent;
92
- if (name === '-') {
93
- return;
94
- }
95
- this._commands.execute(CommandIDs.openChat, {
96
- filepath: path,
97
- inSidePanel: true
98
- });
99
- event.target.selectedIndex = 0;
100
- };
101
- this._chatNamesChanged = new Signal(this);
102
- this.addClass(SIDEPANEL_CLASS);
103
- this._commands = options.commands;
104
- this._contentsManager = options.contentsManager;
105
- this._rmRegistry = options.rmRegistry;
106
- this._themeManager = options.themeManager;
107
- this._defaultDirectory = options.defaultDirectory;
108
- this._chatCommandRegistry = options.chatCommandRegistry;
109
- this._attachmentOpenerRegistry = options.attachmentOpenerRegistry;
110
- this._inputToolbarFactory = options.inputToolbarFactory;
111
- this._messageFooterRegistry = options.messageFooterRegistry;
112
- this._welcomeMessage = options.welcomeMessage;
113
- const addChat = new CommandToolbarButton({
114
- commands: this._commands,
115
- id: CommandIDs.createChat,
116
- args: { inSidePanel: true },
117
- icon: addIcon
118
- });
119
- addChat.addClass(ADD_BUTTON_CLASS);
120
- this.toolbar.addItem('createChat', addChat);
121
- this._openChat = ReactWidget.create(React.createElement(ChatSelect, { chatNamesChanged: this._chatNamesChanged, handleChange: this._chatSelected.bind(this) }));
122
- this._openChat.addClass(OPEN_SELECT_CLASS);
123
- this.toolbar.addItem('openChat', this._openChat);
124
- const content = this.content;
125
- content.expansionToggled.connect(this._onExpansionToggled, this);
126
- }
127
- /**
128
- * Getter and setter of the defaultDirectory.
129
- */
130
- get defaultDirectory() {
131
- return this._defaultDirectory;
132
- }
133
- set defaultDirectory(value) {
134
- if (value === this._defaultDirectory) {
135
- return;
136
- }
137
- this._defaultDirectory = value;
138
- // Update the list of discoverable chat (in default directory)
139
- this.updateChatList();
140
- // Update the sections names.
141
- this.widgets.forEach(w => {
142
- w.defaultDirectory = value;
143
- });
144
- }
145
- /**
146
- * Add a new widget to the chat panel.
147
- *
148
- * @param model - the model of the chat widget
149
- * @param name - the name of the chat.
150
- */
151
- addChat(model) {
152
- // Collapse all chats
153
- const content = this.content;
154
- for (let i = 0; i < this.widgets.length; i++) {
155
- content.collapse(i);
156
- }
157
- // Create the toolbar registry.
158
- let inputToolbarRegistry;
159
- if (this._inputToolbarFactory) {
160
- inputToolbarRegistry = this._inputToolbarFactory.create();
161
- }
162
- // Create a new widget.
163
- const widget = new ChatWidget({
164
- model: model,
165
- rmRegistry: this._rmRegistry,
166
- themeManager: this._themeManager,
167
- chatCommandRegistry: this._chatCommandRegistry,
168
- attachmentOpenerRegistry: this._attachmentOpenerRegistry,
169
- inputToolbarRegistry,
170
- messageFooterRegistry: this._messageFooterRegistry,
171
- welcomeMessage: this._welcomeMessage
172
- });
173
- this.addWidget(new ChatSection({
174
- widget,
175
- commands: this._commands,
176
- path: model.name,
177
- defaultDirectory: this._defaultDirectory
178
- }));
179
- return widget;
180
- }
181
- /**
182
- * Open a chat if it exists in the side panel.
183
- *
184
- * @param path - the path of the chat.
185
- * @returns a boolean, whether the chat existed in the side panel or not.
186
- */
187
- openIfExists(path) {
188
- const index = this._getChatIndex(path);
189
- if (index > -1) {
190
- this._expandChat(index);
191
- }
192
- return index > -1;
193
- }
194
- /**
195
- * A message handler invoked on an `'after-show'` message.
196
- */
197
- onAfterShow(msg) {
198
- var _a;
199
- // Wait for the component to be rendered.
200
- (_a = this._openChat.renderPromise) === null || _a === void 0 ? void 0 : _a.then(() => this.updateChatList());
201
- }
202
- /**
203
- * Return the index of the chat in the list (-1 if not opened).
204
- *
205
- * @param name - the chat name.
206
- */
207
- _getChatIndex(path) {
208
- return this.widgets.findIndex(w => w.path === path);
209
- }
210
- /**
211
- * Expand the chat from its index.
212
- */
213
- _expandChat(index) {
214
- if (!this.widgets[index].isVisible) {
215
- this.content.expand(index);
216
- }
217
- }
218
- /**
219
- * Triggered when a section is toogled. If the section is opened, all others
220
- * sections are closed.
221
- */
222
- _onExpansionToggled(panel, index) {
223
- if (!this.widgets[index].isVisible) {
224
- return;
225
- }
226
- for (let i = 0; i < this.widgets.length; i++) {
227
- if (i !== index) {
228
- panel.collapse(i);
229
- }
230
- }
231
- }
232
- }
233
- /**
234
- * The chat section containing a chat widget.
235
- */
236
- class ChatSection extends PanelWithToolbar {
237
- /**
238
- * Constructor of the chat section.
239
- */
240
- constructor(options) {
241
- var _a;
242
- super(options);
243
- /**
244
- * Change the title when messages are unread.
245
- *
246
- * TODO: fix it upstream in @jupyterlab/ui-components.
247
- * Updating the title create a new Title widget, but does not attach again the
248
- * toolbar. The toolbar is attached only when the title widget is attached the first
249
- * time.
250
- */
251
- this._unreadChanged = (_, unread) => {
252
- this._markAsRead.enabled = unread.length > 0;
253
- // this.title.label = `${unread.length ? '* ' : ''}${this._name}`;
254
- };
255
- this._spinner = new Spinner();
256
- this.addWidget(options.widget);
257
- this.addWidget(this._spinner);
258
- this.addClass(SECTION_CLASS);
259
- this._defaultDirectory = options.defaultDirectory;
260
- this._path = options.path;
261
- this._updateTitle();
262
- this.toolbar.addClass(TOOLBAR_CLASS);
263
- this._markAsRead = new ToolbarButton({
264
- icon: readIcon,
265
- iconLabel: 'Mark chat as read',
266
- className: 'jp-mod-styled',
267
- onClick: () => (this.model.unreadMessages = [])
268
- });
269
- const moveToMain = new ToolbarButton({
270
- icon: launchIcon,
271
- iconLabel: 'Move the chat to the main area',
272
- className: 'jp-mod-styled',
273
- onClick: () => {
274
- this.model.dispose();
275
- options.commands.execute(CommandIDs.openChat, {
276
- filepath: this._path
277
- });
278
- this.dispose();
279
- }
280
- });
281
- const closeButton = new ToolbarButton({
282
- icon: closeIcon,
283
- iconLabel: 'Close the chat',
284
- className: 'jp-mod-styled',
285
- onClick: () => {
286
- this.model.dispose();
287
- this.dispose();
288
- }
289
- });
290
- this.toolbar.addItem('jupyterlabChat-markRead', this._markAsRead);
291
- this.toolbar.addItem('jupyterlabChat-moveMain', moveToMain);
292
- this.toolbar.addItem('jupyterlabChat-close', closeButton);
293
- (_a = this.model.unreadChanged) === null || _a === void 0 ? void 0 : _a.connect(this._unreadChanged);
294
- this._markAsRead.enabled = this.model.unreadMessages.length > 0;
295
- options.widget.node.style.height = '100%';
296
- /**
297
- * Remove the spinner when the chat is ready.
298
- */
299
- const model = this.model;
300
- model.ready.then(() => {
301
- this._spinner.dispose();
302
- });
303
- }
304
- /**
305
- * The path of the chat.
306
- */
307
- get path() {
308
- return this._path;
309
- }
310
- /**
311
- * Set the default directory property.
312
- */
313
- set defaultDirectory(value) {
314
- this._defaultDirectory = value;
315
- this._updateTitle();
316
- }
317
- /**
318
- * The model of the widget.
319
- */
320
- get model() {
321
- return this.widgets[0].model;
322
- }
323
- /**
324
- * Dispose of the resources held by the widget.
325
- */
326
- dispose() {
327
- var _a;
328
- (_a = this.model.unreadChanged) === null || _a === void 0 ? void 0 : _a.disconnect(this._unreadChanged);
329
- super.dispose();
330
- }
331
- /**
332
- * Update the section's title, depending on the default directory and chat file name.
333
- * If the chat file is in the default directory, the section's name is its relative
334
- * path to that default directory. Otherwise, it is it absolute path.
335
- */
336
- _updateTitle() {
337
- const inDefault = this._defaultDirectory
338
- ? !PathExt.relative(this._defaultDirectory, this._path).startsWith('..')
339
- : true;
340
- const pattern = new RegExp(`${chatFileType.extensions[0]}$`, 'g');
341
- this.title.label = (inDefault
342
- ? this._defaultDirectory
343
- ? PathExt.relative(this._defaultDirectory, this._path)
344
- : this._path
345
- : '/' + this._path).replace(pattern, '');
346
- this.title.caption = this._path;
347
- }
348
- }
349
- /**
350
- * A component to select a chat from the drive.
351
- */
352
- function ChatSelect({ chatNamesChanged, handleChange }) {
353
- // An object associating a chat name to its path. Both are purely indicative, the name
354
- // is the section title and the path is used as caption.
355
- const [chatNames, setChatNames] = useState({});
356
- // Update the chat list.
357
- chatNamesChanged.connect((_, chatNames) => {
358
- setChatNames(chatNames);
359
- });
360
- return (React.createElement(HTMLSelect, { onChange: handleChange },
361
- React.createElement("option", { value: "-" }, "Open a chat"),
362
- Object.keys(chatNames).map(name => (React.createElement("option", { value: chatNames[name] }, name)))));
363
- }