Skip to content
This repository has been archived by the owner on Feb 16, 2023. It is now read-only.

Add a Trusted indicator to the menu bar #279

Closed
wants to merge 4 commits into from
Closed
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
6 changes: 5 additions & 1 deletion packages/notebook-extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,15 @@
"@jupyterlab/docmanager": "^3.2.0",
"@jupyterlab/notebook": "^3.2.0",
"@jupyterlab/translation": "^3.2.0",
"@lumino/algorithm": "^1.6.0",
"@lumino/polling": "^1.6.0",
"@lumino/widgets": "^1.23.0",
"@retrolab/application": "^0.3.13"
"@retrolab/application": "^0.3.13",
"react": "^17.0.2",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@types/react": "^17.0.34",
"rimraf": "~3.0.0",
"typescript": "~4.1.3"
},
Expand Down
34 changes: 33 additions & 1 deletion packages/notebook-extension/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ import { Poll } from '@lumino/polling';

import { Widget } from '@lumino/widgets';

import { TrustedComponent } from './trusted';

/**
* The class for kernel status errors.
*/
Expand Down Expand Up @@ -214,13 +216,43 @@ const kernelStatus: JupyterFrontEndPlugin<void> = {
}
};

/**
* A plugin that adds a Trusted indicator to the menu area
*/
const trusted: JupyterFrontEndPlugin<void> = {
id: '@retrolab/notebook-extension:trusted',
autoStart: true,
requires: [IRetroShell, ITranslator],
activate: (
app: JupyterFrontEnd,
shell: IRetroShell,
translator: ITranslator
): void => {
const onChange = async () => {
const current = shell.currentWidget;
if (!(current instanceof NotebookPanel)) {
return;
}

const notebook = current.content;
await current.context.ready;

const widget = TrustedComponent.create({ notebook, translator });
shell.add(widget, 'menu', { rank: 11_000 });
};

shell.currentChanged.connect(onChange);
}
};

/**
* Export the plugins as default.
*/
const plugins: JupyterFrontEndPlugin<any>[] = [
checkpoints,
kernelLogo,
kernelStatus
kernelStatus,
trusted
];

export default plugins;
101 changes: 101 additions & 0 deletions packages/notebook-extension/src/trusted.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { ReactWidget } from '@jupyterlab/apputils';

import { Notebook, NotebookActions } from '@jupyterlab/notebook';

import { ITranslator } from '@jupyterlab/translation';

import { toArray } from '@lumino/algorithm';

import React, { useEffect, useState } from 'react';

const isTrusted = (notebook: Notebook): boolean => {
const model = notebook.model;
if (!model) {
return false;
}
const cells = toArray(model.cells);

const trusted = cells.reduce((accum, current) => {
if (current.trusted) {
return accum + 1;
} else {
return accum;
}
}, 0);

const total = cells.length;
return trusted === total;
};

/**
* A React component to display the Trusted badge in the menu bar.
* @param notebook The Notebook
* @param translator The Translation service
*/
const TrustedButton = ({
notebook,
translator
}: {
notebook: Notebook;
translator: ITranslator;
}): JSX.Element => {
const trans = translator.load('retrolab');
const [trusted, setTrusted] = useState(isTrusted(notebook));

const checkTrust = () => {
const v = isTrusted(notebook);
setTrusted(v);
};

const trust = async () => {
await NotebookActions.trust(notebook, translator);
checkTrust();
};

useEffect(() => {
notebook.modelContentChanged.connect(checkTrust);
notebook.activeCellChanged.connect(checkTrust);
return () => {
notebook.modelContentChanged.disconnect(checkTrust);
notebook.activeCellChanged.disconnect(checkTrust);
};
});

return (
<button
className={'jp-RetroTrustedStatus'}
style={!trusted ? { cursor: 'pointer' } : { cursor: 'help' }}
onClick={() => !trusted && trust()}
title={
trusted
? trans.__('JavaScript enabled for notebook display')
: trans.__('JavaScript disabled for notebook display')
}
>
{trusted ? trans.__('Trusted') : trans.__('Not Trusted')}
</button>
);
};

/**
* A namespace for TrustedComponent statics.
*/
export namespace TrustedComponent {
/**
* Create a new TrustedComponent
*
* @param notebook The notebook
* @param translator The translator
*/
export const create = ({
notebook,
translator
}: {
notebook: Notebook;
translator: ITranslator;
}): ReactWidget => {
return ReactWidget.create(
<TrustedButton notebook={notebook} translator={translator} />
);
};
}
13 changes: 13 additions & 0 deletions packages/notebook-extension/style/base.css
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,19 @@ body[data-retro='notebooks'] .jp-Notebook.jp-mod-scrollPastEnd::after {
white-space: nowrap;
}

.jp-RetroTrustedStatus {
background: var(--jp-layout-color1);
color: var(--jp-ui-font-color1);
margin-top: 4px;
margin-bottom: 4px;
border: solid 1px var(--jp-border-color2);
cursor: help;
}

.jp-RetroTrustedStatus-not-trusted {
cursor: pointer;
}

/* Mobile View */

body[data-format='mobile'] .jp-RetroCheckpoint {
Expand Down
15 changes: 13 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3387,6 +3387,8 @@
"@lumino/polling" "^1.6.0"
"@lumino/widgets" "^1.23.0"
"@retrolab/application" "^0.3.12"
react "^17.0.2"
react-dom "^17.0.2"

"@retrolab/terminal-extension@file:packages/terminal-extension":
version "0.3.12"
Expand Down Expand Up @@ -3637,6 +3639,15 @@
"@types/scheduler" "*"
csstype "^3.0.2"

"@types/react@^17.0.34":
version "17.0.34"
resolved "https://registry.yarnpkg.com/@types/react/-/react-17.0.34.tgz#797b66d359b692e3f19991b6b07e4b0c706c0102"
integrity sha512-46FEGrMjc2+8XhHXILr+3+/sTe3OfzSPU9YGKILLrUYbQ1CLQC9Daqo1KzENGXAWwrFwiY0l4ZbF20gRvgpWTg==
dependencies:
"@types/prop-types" "*"
"@types/scheduler" "*"
csstype "^3.0.2"

"@types/rimraf@^3.0.0":
version "3.0.0"
resolved "https://registry.yarnpkg.com/@types/rimraf/-/rimraf-3.0.0.tgz#b9d03f090ece263671898d57bb7bb007023ac19f"
Expand Down Expand Up @@ -11408,7 +11419,7 @@ react-base16-styling@^0.8.0:
csstype "^3.0.2"
lodash.curry "^4.1.1"

react-dom@^17.0.1:
react-dom@^17.0.1, react-dom@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-17.0.2.tgz#ecffb6845e3ad8dbfcdc498f0d0a939736502c23"
integrity sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==
Expand Down Expand Up @@ -11474,7 +11485,7 @@ react-transition-group@^2.9.0:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"

react@^17.0.1:
react@^17.0.1, react@^17.0.2:
version "17.0.2"
resolved "https://registry.yarnpkg.com/react/-/react-17.0.2.tgz#d0b5cc516d29eb3eee383f75b62864cfb6800037"
integrity sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==
Expand Down