Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions packages/notebook-extension/schema/close-tab.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"jupyter.lab.setting-icon": "notebook-ui-components:jupyter",
"jupyter.lab.setting-icon-label": "Jupyter Notebook Close Tab",
"title": "Jupyter Notebook Close Tab",
"description": "Jupyter Notebook Close Tab settings",
"properties": {
"confirmClosingNotebook": {
"type": "boolean",
"title": "Confirm Closing Notebook",
"description": "Whether to show a confirmation dialog when closing and shutting down a notebook",
"default": true
}
},
"additionalProperties": false,
"type": "object"
}
55 changes: 51 additions & 4 deletions packages/notebook-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import {
DOMUtils,
IToolbarWidgetRegistry,
ICommandPalette,
Dialog,
showDialog,
} from '@jupyterlab/apputils';

import { Cell, CodeCell } from '@jupyterlab/cells';
Expand Down Expand Up @@ -231,21 +233,46 @@ const closeTab: JupyterFrontEndPlugin<void> = {
'Add a command to close the browser tab when clicking on "Close and Shut Down".',
autoStart: true,
requires: [IMainMenu],
optional: [ITranslator],
optional: [ITranslator, ISettingRegistry],
activate: (
app: JupyterFrontEnd,
menu: IMainMenu,
translator: ITranslator | null
translator: ITranslator | null,
settingRegistry: ISettingRegistry | null
) => {
const { commands } = app;
translator = translator ?? nullTranslator;
const trans = translator.load('notebook');

let confirmClosing = true; // Default to showing confirmation

const id = 'notebook:close-and-halt';
commands.addCommand(id, {
label: trans.__('Close and Shut Down Notebook'),
label: () => {
// Add ellipsis when confirmation is enabled
return confirmClosing
? trans.__('Close and Shut Down Notebook…')
: trans.__('Close and Shut Down Notebook');
},
execute: async () => {
// Shut the kernel down, without confirmation
if (confirmClosing) {
const result = await showDialog({
title: trans.__('Shut down notebook?'),
body: trans.__(
'The notebook kernel will be shut down. Any unsaved changes will be lost.'
),
buttons: [
Dialog.cancelButton({ label: trans.__('Cancel') }),
Dialog.warnButton({ label: trans.__('Shut Down') }),
],
});

if (!result.button.accept) {
return;
}
}

// Shut the kernel down
await commands.execute('notebook:shutdown-kernel', { activate: false });
window.close();
},
Expand All @@ -256,6 +283,26 @@ const closeTab: JupyterFrontEndPlugin<void> = {
// shut down action for the notebook
rank: 0,
});

// Load settings
if (settingRegistry) {
const loadSettings = settingRegistry.load(closeTab.id);
const updateSettings = (settings: ISettingRegistry.ISettings): void => {
confirmClosing = settings.get('confirmClosingNotebook')
.composite as boolean;
};

Promise.all([loadSettings, app.restored])
.then(([settings]) => {
updateSettings(settings);
settings.changed.connect(updateSettings);
})
.catch((reason: Error) => {
console.error(
`Failed to load settings for ${closeTab.id}: ${reason.message}`
);
});
}
},
};

Expand Down
1 change: 1 addition & 0 deletions tsconfigbase.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
"noUnusedLocals": true,
"preserveWatchOutput": true,
"resolveJsonModule": true,
"skipLibCheck": true,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to add this?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added this because I was encountering build errors locally originating from [encoding.d.ts] (specifically [error TS2315: Type 'Uint8Array' is not generic].

It seems to be a mismatch with the type definitions in that dependency. Enabling skipLibCheck allowed the build to pass. If this change isn't desired for the project configuration, I can revert it
and try to troubleshoot the dependency issue separately

"strict": true,
"strictNullChecks": true,
"target": "ES2018",
Expand Down
Loading