diff --git a/app/app.ts b/app/app.ts index 05f844c04..9f8302f50 100644 --- a/app/app.ts +++ b/app/app.ts @@ -3,7 +3,7 @@ import 'bootstrap'; import 'bootstrap/dist/css/bootstrap.min.css'; -import { getByID, addWarningHandler } from '../src/utils'; +import { getByID, logger } from '../src/utils'; import { Dataset, Structure } from '../src/dataset'; import { version, DefaultVisualizer, Settings } from '../src/index'; @@ -35,7 +35,7 @@ export class ChemiscopeApp { versionDisplay.innerText = `version ${version()}`; // handle warnings - addWarningHandler((message) => displayWarning(message)); + logger.addHandler('warn', (message) => displayWarning(message as string)); // when the window is resized, change the size available to the info // widget diff --git a/python/chemiscope/sphinx/static/chemiscope-sphinx.css b/python/chemiscope/sphinx/static/chemiscope-sphinx.css index f91f44f87..3be634942 100644 --- a/python/chemiscope/sphinx/static/chemiscope-sphinx.css +++ b/python/chemiscope/sphinx/static/chemiscope-sphinx.css @@ -1,9 +1,6 @@ -.chemiscope-sphinx-warning { +.chemiscope-sphinx-log { display: none; flex-wrap: wrap; - border: 1px solid #f0ad4e; - background-color: #fcf8e3; - color: #8a6d3b; padding: 15px; border-radius: 4px; margin-bottom: 20px; @@ -24,6 +21,28 @@ } } +.chemiscope-sphinx-log.warning { + border: 1px solid #f0ad4e; + background-color: #fcf8e3; + color: #8a6d3b; +} + +.chemiscope-sphinx-log.error { + border: 1px solid #d9534f; + background-color: #f2dede; + color: #a94442; + + .error-backtrace { + background-color: #f5d6d6; + border: 1px solid #d9534f; + border-radius: 4px; + padding: 10px; + margin-top: 10px; + white-space: pre-wrap; + overflow-x: auto; + } +} + .chemiscope-sphinx-spinner img { width: 2em; height: 2em; diff --git a/python/chemiscope/sphinx/static/chemiscope-sphinx.html b/python/chemiscope/sphinx/static/chemiscope-sphinx.html index fd3eaf2e2..448886052 100644 --- a/python/chemiscope/sphinx/static/chemiscope-sphinx.html +++ b/python/chemiscope/sphinx/static/chemiscope-sphinx.html @@ -11,12 +11,22 @@ -
+

+ + +
+

+

+    
+
+
diff --git a/python/chemiscope/sphinx/static/chemiscope-sphinx.js b/python/chemiscope/sphinx/static/chemiscope-sphinx.js index 2c93b818b..87676329c 100644 --- a/python/chemiscope/sphinx/static/chemiscope-sphinx.js +++ b/python/chemiscope/sphinx/static/chemiscope-sphinx.js @@ -13,8 +13,10 @@ const VISUALISER_MODE = { * Asynchronously loads the Chemiscope visualization for the dataset */ async function loadChemiscopeSphinx(divId, filePath, visualizerMode = VISUALISER_MODE.DEFAULT) { - // Handle warnings - Chemiscope.addWarningHandler((message) => displayWarning(divId, message)); + // Handle warnings and errors + Chemiscope.logger.addHandler('warning', (message) => displayWarning(divId, message)); + Chemiscope.logger.addHandler('error', (error) => displayError(divId, error)); + // Display loading toggleLoadingVisible(divId, true); @@ -37,12 +39,15 @@ async function loadChemiscopeSphinx(divId, filePath, visualizerMode = VISUALISER // Load widget const visualiser = getVisualizer(visualizerMode); await visualiser.load(config, dataset); - } catch (error) { - // Display errors - console.error(error); - displayWarning(divId, error); - } finally { - // Hide loading + } + + // Display errors + catch (error) { + Chemiscope.logger.error(error); + } + + // Hide loading + finally { toggleLoadingVisible(divId, false); } } @@ -176,3 +181,20 @@ function displayWarning(divId, message) { display.style.display = 'none'; }, 4000); } + +function displayError(divId, error) { + const errorElement = document.getElementById(`${divId}-error-display`); + const messageElement = errorElement.querySelector('.error-message'); + const backtraceElement = errorElement.querySelector('.error-backtrace'); + + // Set the error message + messageElement.textContent = error.toString(); + + // Extract and set the backtrace (stack trace) if available + if (error.stack) { + backtraceElement.textContent = error.stack; + } + + // Show the error element + errorElement.style.display = 'flex'; +} diff --git a/python/jupyter/src/widget.css b/python/jupyter/src/widget.css index 44a9c2036..09f2003ae 100644 --- a/python/jupyter/src/widget.css +++ b/python/jupyter/src/widget.css @@ -88,3 +88,29 @@ html { .chemiscope-meta-and-map .chemiscope-info *::part(chsp-slider) { display: none; } + +.chemiscope-sphinx-warning { + display: none; + flex-wrap: wrap; + border: 1px solid #f0ad4e; + background-color: #fcf8e3; + color: #8a6d3b; + padding: 15px; + border-radius: 4px; + margin-bottom: 20px; + + button { + position: relative; + float: right; + font-size: 3em; + line-height: 1; + color: inherit; + text-shadow: none; + background-color: transparent; + border: 0; + } + + p { + flex: 1; + } +} diff --git a/python/jupyter/src/widget.ts b/python/jupyter/src/widget.ts index 49628733f..5ef8aba7d 100644 --- a/python/jupyter/src/widget.ts +++ b/python/jupyter/src/widget.ts @@ -1,7 +1,7 @@ import { DOMWidgetView } from '@jupyter-widgets/base'; import Plausible from 'plausible-tracker'; -import { addWarningHandler, generateGUID, getByID } from '../../../src/utils'; +import { logger, generateGUID, getByID } from '../../../src/utils'; // Import the CSS import './widget.css'; @@ -92,15 +92,20 @@ export class ChemiscopeView extends ChemiscopeBaseView { // and then inserting this.el inside the HTML document. const element = this.el; - addWarningHandler((message) => { + logger.addHandler('warn', (message) => { const display = getByID(`${this.guid}-warning-display`, element); display.style.display = 'block'; - display.getElementsByTagName('p')[0].innerText = message; + display.getElementsByTagName('p')[0].innerText = message as string; + }); + logger.addHandler('error', (e) => { + const display = getByID(`${this.guid}-error-display`, element); + display.style.display = 'block'; + display.getElementsByTagName('p')[0].innerText = e.toString(); }); element.innerHTML = `
-