Skip to content

Commit

Permalink
update the section name and discovered chats in left panel
Browse files Browse the repository at this point in the history
  • Loading branch information
brichet committed Oct 24, 2024
1 parent 63205b5 commit 170f9ed
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 59 deletions.
4 changes: 2 additions & 2 deletions packages/jupyterlab-collaborative-chat/src/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export interface ICollaborativeChatConfig extends IConfig {
/**
* The default directory where to create and look for chat.
*/
defaultDirectory: string;
defaultDirectory?: string;
}

/**
Expand Down Expand Up @@ -78,7 +78,7 @@ export interface IWidgetConfig {
* A signal emitting when the configuration for the chats has changed.
*/
export interface IConfigChanged
extends ISignal<IWidgetConfig, Partial<IConfig>> {}
extends ISignal<IWidgetConfig, Partial<ICollaborativeChatConfig>> {}

/**
* Command ids.
Expand Down
96 changes: 66 additions & 30 deletions packages/jupyterlab-collaborative-chat/src/widget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
ChatWidget,
IAutocompletionRegistry,
IChatModel,
IConfig,
readIcon
} from '@jupyter/chat';
import { ICollaborativeDrive } from '@jupyter/docprovider';
Expand Down Expand Up @@ -107,6 +106,7 @@ export class ChatPanel extends SidePanel {
this._drive = options.drive;
this._rmRegistry = options.rmRegistry;
this._themeManager = options.themeManager;
this._defaultDirectory = options.defaultDirectory;
this._autocompletionRegistry = options.autocompletionRegistry;

const addChat = new CommandToolbarButton({
Expand All @@ -133,15 +133,21 @@ export class ChatPanel extends SidePanel {
}

/**
* Getter and setter of the config, propagated to all the chat widgets.
* Getter and setter of the defaultDirectory.
*/
get config(): IConfig {
return this._config;
get defaultDirectory(): string {
return this._defaultDirectory;
}
set config(value: Partial<IConfig>) {
this._config = { ...this._config, ...value };
set defaultDirectory(value: string) {
if (value === this._defaultDirectory) {
return;
}
this._defaultDirectory = value;
// Update the list of discoverable chat (in default directory)
this.updateChatList();
// Update the sections names.
this.widgets.forEach(w => {
(w as ChatSection).model.config = value;
(w as ChatSection).defaultDirectory = value;
});
}

Expand All @@ -151,15 +157,15 @@ export class ChatPanel extends SidePanel {
* @param model - the model of the chat widget
* @param name - the name of the chat.
*/
addChat(model: IChatModel, name: string, path: string): void {
addChat(model: IChatModel, path: string): void {
// Collapse all chats
const content = this.content as AccordionPanel;
for (let i = 0; i < this.widgets.length; i++) {
content.collapse(i);
}

// Set the id of the model.
model.name = name;
// Set the name of the model.
model.name = path;

// Create a new widget.
const widget = new ChatWidget({
Expand All @@ -168,25 +174,32 @@ export class ChatPanel extends SidePanel {
themeManager: this._themeManager,
autocompletionRegistry: this._autocompletionRegistry
});

this.addWidget(
new ChatSection({ name, widget, commands: this._commands, path })
new ChatSection({
widget,
commands: this._commands,
path,
defaultDirectory: this._defaultDirectory
})
);
}

/**
* Update the list of available chats in the root directory of the drive.
* Update the list of available chats in the default directory.
*/
updateChatNames = async (): Promise<void> => {
updateChatList = async (): Promise<void> => {
const extension = chatFileType.extensions[0];
const defaultDirectory = this._defaultDirectory || '';
this._drive
.get('.')
.get(defaultDirectory)
.then(contentModel => {
const chatsNames: { [name: string]: string } = {};
(contentModel.content as any[])
.filter(f => f.type === 'file' && f.name.endsWith(extension))
.forEach(
f => (chatsNames[PathExt.basename(f.name, extension)] = f.name)
);
.forEach(f => {
chatsNames[PathExt.basename(f.name, extension)] = f.path;
});

this._chatNamesChanged.emit(chatsNames);
})
Expand All @@ -212,7 +225,7 @@ export class ChatPanel extends SidePanel {
*/
protected onAfterShow(msg: Message): void {
// Wait for the component to be rendered.
this._openChat.renderPromise?.then(() => this.updateChatNames());
this._openChat.renderPromise?.then(() => this.updateChatList());
}

/**
Expand Down Expand Up @@ -272,7 +285,7 @@ export class ChatPanel extends SidePanel {
this
);
private _commands: CommandRegistry;
private _config: IConfig = {};
private _defaultDirectory: string;
private _drive: ICollaborativeDrive;
private _openChat: ReactWidget;
private _rmRegistry: IRenderMimeRegistry;
Expand All @@ -292,6 +305,7 @@ export namespace ChatPanel {
drive: ICollaborativeDrive;
rmRegistry: IRenderMimeRegistry;
themeManager: IThemeManager | null;
defaultDirectory: string;
autocompletionRegistry?: IAutocompletionRegistry;
}
}
Expand All @@ -305,11 +319,13 @@ class ChatSection extends PanelWithToolbar {
*/
constructor(options: ChatSection.IOptions) {
super(options);

this.addWidget(options.widget);

this.addClass(SECTION_CLASS);
this._name = options.name;
this._defaultDirectory = options.defaultDirectory;
this._path = options.path;
this.title.label = this._name;
this.title.caption = this._path;
this._updateTitle();
this.toolbar.addClass(TOOLBAR_CLASS);

this._markAsRead = new ToolbarButton({
Expand All @@ -326,7 +342,7 @@ class ChatSection extends PanelWithToolbar {
onClick: () => {
this.model.dispose();
options.commands.execute(CommandIDs.openChat, {
filepath: `${this._name}${chatFileType.extensions[0]}`
filepath: this._path
});
this.dispose();
}
Expand All @@ -346,8 +362,6 @@ class ChatSection extends PanelWithToolbar {
this.toolbar.addItem('collaborativeChat-moveMain', moveToMain);
this.toolbar.addItem('collaborativeChat-close', closeButton);

this.addWidget(options.widget);

this.model.unreadChanged?.connect(this._unreadChanged);

this._markAsRead.enabled = this.model.unreadMessages.length > 0;
Expand All @@ -363,10 +377,11 @@ class ChatSection extends PanelWithToolbar {
}

/**
* The name of the chat.
* Set the default directory property.
*/
get name(): string {
return this._name;
set defaultDirectory(value: string) {
this._defaultDirectory = value;
this._updateTitle();
}

/**
Expand All @@ -384,6 +399,27 @@ class ChatSection extends PanelWithToolbar {
super.dispose();
}

/**
* Update the section's title, depending on the default directory and chat file name.
* If the chat file is in the default directory, the section's name is its relative
* path to that default directory. Otherwise, it is it absolute path.
*/
private _updateTitle(): void {
const inDefault = this._defaultDirectory
? !PathExt.relative(this._defaultDirectory, this._path).startsWith('..')
: true;

const pattern = new RegExp(`${chatFileType.extensions[0]}$`, 'g');
this.title.label = (
inDefault
? this._defaultDirectory
? PathExt.relative(this._defaultDirectory, this._path)
: this._path
: '/' + this._path
).replace(pattern, '');
this.title.caption = this._path;
}

/**
* Change the title when messages are unread.
*
Expand All @@ -397,7 +433,7 @@ class ChatSection extends PanelWithToolbar {
// this.title.label = `${unread.length ? '* ' : ''}${this._name}`;
};

private _name: string;
private _defaultDirectory: string;
private _markAsRead: ToolbarButton;
private _path: string;
}
Expand All @@ -411,7 +447,7 @@ export namespace ChatSection {
*/
export interface IOptions extends Panel.IOptions {
commands: CommandRegistry;
name: string;
defaultDirectory: string;
widget: ChatWidget;
path: string;
}
Expand Down
2 changes: 1 addition & 1 deletion python/jupyterlab-collaborative-chat/schema/factory.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"defaultDirectory": {
"description": "Default directory where to create and look for chat.",
"type": "string",
"default": ".",
"default": "",
"readOnly": false
},
"toolbar": {
Expand Down
43 changes: 17 additions & 26 deletions python/jupyterlab-collaborative-chat/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,7 @@ const docFactories: JupyterFrontEndPlugin<IChatFactory> = {
if (
drive &&
previousDirectory &&
previousDirectory !== currentDirectory &&
previousDirectory !== '.'
previousDirectory !== currentDirectory
) {
drive
.get(previousDirectory)
Expand Down Expand Up @@ -176,12 +175,7 @@ const docFactories: JupyterFrontEndPlugin<IChatFactory> = {
};

// Create the new directory if necessary.
if (
drive &&
currentDirectory &&
previousDirectory !== currentDirectory &&
currentDirectory !== '.'
) {
if (drive && currentDirectory && previousDirectory !== currentDirectory) {
drive.get(currentDirectory, { content: false }).catch(() => {
drive
.newUntitled({
Expand Down Expand Up @@ -378,7 +372,7 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
}
// Add the default directory to the path.
filepath = PathExt.join(
widgetConfig.config.defaultDirectory || '.',
widgetConfig.config.defaultDirectory || '',
filepath
);
}
Expand Down Expand Up @@ -546,14 +540,7 @@ const chatCommands: JupyterFrontEndPlugin<void> = {
});

// Add a chat widget to the side panel.
chatPanel.addChat(
chat,
PathExt.join(
PathExt.dirname(model.path),
PathExt.basename(model.name, chatFileType.extensions[0])
),
model.path
);
chatPanel.addChat(chat, model.path);
} else {
// The chat is opened in the main area
commands.execute('docmanager:open', {
Expand Down Expand Up @@ -605,24 +592,21 @@ const chatPanel: JupyterFrontEndPlugin<ChatPanel> = {
description: 'The chat panel widget.',
autoStart: true,
provides: IChatPanel,
requires: [ICollaborativeDrive, IRenderMimeRegistry],
optional: [
IAutocompletionRegistry,
ILayoutRestorer,
INotebookTracker,
IThemeManager
],
requires: [IChatFactory, ICollaborativeDrive, IRenderMimeRegistry],
optional: [IAutocompletionRegistry, ILayoutRestorer, IThemeManager],
activate: (
app: JupyterFrontEnd,
factory: IChatFactory,
drive: ICollaborativeDrive,
rmRegistry: IRenderMimeRegistry,
autocompletionRegistry: IAutocompletionRegistry,
restorer: ILayoutRestorer | null,
notebookTracker: INotebookTracker,
themeManager: IThemeManager | null
): ChatPanel => {
const { commands } = app;

const defaultDirectory = factory.widgetConfig.config.defaultDirectory || '';

/**
* Add Chat widget to left sidebar
*/
Expand All @@ -631,12 +615,19 @@ const chatPanel: JupyterFrontEndPlugin<ChatPanel> = {
drive,
rmRegistry,
themeManager,
defaultDirectory,
autocompletionRegistry
});
chatPanel.id = 'JupyterCollaborationChat:sidepanel';
chatPanel.title.icon = chatIcon;
chatPanel.title.caption = 'Jupyter Chat'; // TODO: i18n/

factory.widgetConfig.configChanged.connect((_, config) => {
if (config.defaultDirectory) {
chatPanel.defaultDirectory = config.defaultDirectory;
}
});

app.shell.add(chatPanel, 'left', {
rank: 2000
});
Expand All @@ -653,7 +644,7 @@ const chatPanel: JupyterFrontEndPlugin<ChatPanel> = {
if (emission.schema_id === schemaID) {
const action = emission.action as string;
if (actions.includes(action)) {
chatPanel.updateChatNames();
chatPanel.updateChatList();
}
}
});
Expand Down

0 comments on commit 170f9ed

Please sign in to comment.