import Component from "../components/component.js";
-
+import froca from "../services/froca.js";
+import { t } from "../services/i18n.js";
+import toastService from "../services/toast.js";
/**
* This is the base widget for all other widgets.
@@ -66,6 +68,21 @@ class BasicWidget extends Component {
return this;
}
+ /**
+ * Conditionally adds the given components as children to this component.
+ *
+ * @param {boolean} condition whether to add the components.
+ * @param {...any} components the components to be added as children to this component provided the condition is truthy.
+ * @returns self for chaining.
+ */
+ optChild(condition, ...components) {
+ if (condition) {
+ return this.child(...components);
+ } else {
+ return this;
+ }
+ }
+
id(id) {
this.attrs.id = id;
return this;
@@ -76,11 +93,34 @@ class BasicWidget extends Component {
return this;
}
+ /**
+ * Sets the CSS attribute of the given name to the given value.
+ *
+ * @param {string} name the name of the CSS attribute to set (e.g. `padding-left`).
+ * @param {string} value the value of the CSS attribute to set (e.g. `12px`).
+ * @returns self for chaining.
+ */
css(name, value) {
this.attrs.style += `${name}: ${value};`;
return this;
}
+ /**
+ * Sets the CSS attribute of the given name to the given value, but only if the condition provided is truthy.
+ *
+ * @param {boolean} condition `true` in order to apply the CSS, `false` to ignore it.
+ * @param {string} name the name of the CSS attribute to set (e.g. `padding-left`).
+ * @param {string} value the value of the CSS attribute to set (e.g. `12px`).
+ * @returns self for chaining.
+ */
+ optCss(condition, name, value) {
+ if (condition) {
+ return this.css(name, value);
+ }
+
+ return this;
+ }
+
contentSized() {
this.css("contain", "none");
@@ -109,7 +149,11 @@ class BasicWidget extends Component {
}
render() {
- this.doRender();
+ try {
+ this.doRender();
+ } catch (e) {
+ this.logRenderingError(e);
+ }
this.$widget.attr('data-component-id', this.componentId);
this.$widget
@@ -147,6 +191,39 @@ class BasicWidget extends Component {
return this.$widget;
}
+ logRenderingError(e) {
+ console.log("Got issue in widget ", this);
+ console.error(e);
+
+ let noteId = this._noteId;
+ if (this._noteId) {
+ froca.getNote(noteId, true).then((note) => {
+ toastService.showPersistent({
+ title: t("toast.widget-error.title"),
+ icon: "alert",
+ message: t("toast.widget-error.message-custom", {
+ id: noteId,
+ title: note.title,
+ message: e.message
+ })
+ });
+ });
+ return;
+ }
+
+ toastService.showPersistent({
+ title: t("toast.widget-error.title"),
+ icon: "alert",
+ message: t("toast.widget-error.message-unknown", {
+ message: e.message
+ })
+ });
+ }
+
+ /**
+ * Indicates if the widget is enabled. Widgets are enabled by default. Generally setting this to `false` will cause the widget not to be displayed, however it will still be available on the DOM but hidden.
+ * @returns whether the widget is enabled.
+ */
isEnabled() {
return true;
}
@@ -222,7 +299,7 @@ export default BasicWidget;
diff --git a/docs/frontend_api/widgets_note_context_aware_widget.js.html b/docs/frontend_api/widgets_note_context_aware_widget.js.html
index e9f707f32..bbc72f6a3 100644
--- a/docs/frontend_api/widgets_note_context_aware_widget.js.html
+++ b/docs/frontend_api/widgets_note_context_aware_widget.js.html
@@ -76,6 +76,11 @@ class NoteContextAwareWidget extends BasicWidget {
}
/**
+ * Indicates if the widget is enabled. Widgets are enabled by default. Generally setting this to `false` will cause the widget not to be displayed, however it will still be available on the DOM but hidden.
+ *
+ * <p>
+ * If the widget is not enabled, it will not receive `refreshWithNote` updates.
+ *
* @returns {boolean} true when an active note exists
*/
isEnabled() {
@@ -85,7 +90,17 @@ class NoteContextAwareWidget extends BasicWidget {
async refresh() {
if (this.isEnabled()) {
this.toggleInt(true);
- await this.refreshWithNote(this.note);
+
+ try {
+ await this.refreshWithNote(this.note);
+ } catch (e) {
+ // Ignore errors when user is refreshing or navigating away.
+ if (e === "rejected by browser") {
+ return;
+ }
+
+ throw e;
+ }
}
else {
this.toggleInt(false);
@@ -164,7 +179,7 @@ export default NoteContextAwareWidget;
diff --git a/docs/frontend_api/widgets_right_panel_widget.js.html b/docs/frontend_api/widgets_right_panel_widget.js.html
index cf98c0aa5..cb63ea9fd 100644
--- a/docs/frontend_api/widgets_right_panel_widget.js.html
+++ b/docs/frontend_api/widgets_right_panel_widget.js.html
@@ -27,6 +27,8 @@
import NoteContextAwareWidget from "./note_context_aware_widget.js";
+import toastService from "../services/toast.js";
+import { t } from "../services/i18n.js";
const WIDGET_TPL = `
<div class="card widget">
@@ -82,7 +84,9 @@ class RightPanelWidget extends NoteContextAwareWidget {
this.$buttons.append(buttonWidget.render());
}
- this.initialized = this.doRenderBody();
+ this.initialized = this.doRenderBody().catch(e => {
+ this.logRenderingError(e);
+ });
}
/**
@@ -111,7 +115,7 @@ export default RightPanelWidget;
diff --git a/src/public/app/widgets/basic_widget.js b/src/public/app/widgets/basic_widget.js
index 33ade4cb4..54b0b92a7 100644
--- a/src/public/app/widgets/basic_widget.js
+++ b/src/public/app/widgets/basic_widget.js
@@ -194,7 +194,7 @@ class BasicWidget extends Component {
/**
* Indicates if the widget is enabled. Widgets are enabled by default. Generally setting this to `false` will cause the widget not to be displayed, however it will still be available on the DOM but hidden.
- * @returns
+ * @returns whether the widget is enabled.
*/
isEnabled() {
return true;
diff --git a/src/public/app/widgets/note_context_aware_widget.js b/src/public/app/widgets/note_context_aware_widget.js
index 06e6219e4..014775210 100644
--- a/src/public/app/widgets/note_context_aware_widget.js
+++ b/src/public/app/widgets/note_context_aware_widget.js
@@ -48,7 +48,7 @@ class NoteContextAwareWidget extends BasicWidget {
}
/**
- * @inheritdoc
+ * Indicates if the widget is enabled. Widgets are enabled by default. Generally setting this to `false` will cause the widget not to be displayed, however it will still be available on the DOM but hidden.
*
*
* If the widget is not enabled, it will not receive `refreshWithNote` updates.