mirror of
https://github.com/lucaspalomodevelop/core.git
synced 2026-03-18 18:44:44 +00:00
dashboard: handle error cases per widget
If any widget failed to import/instantiate/update in the previous logic, this would halt execution for the entire dashboard. This commit takes care of these cases, but it cannot account for asynchronous callbacks executed in the widget logic itself, these should be caught there.
This commit is contained in:
parent
44e3bafce2
commit
c9182e23dc
@ -52,6 +52,11 @@
|
||||
border-radius: 0.5em 0.5em 0.5em 0.5em;
|
||||
}
|
||||
|
||||
.widget-error {
|
||||
margin: 50px;
|
||||
color: #721c24
|
||||
}
|
||||
|
||||
.widget-content {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
@ -137,10 +137,9 @@ class WidgetManager {
|
||||
});
|
||||
|
||||
// Load all modules simultaneously - this shouldn't take long
|
||||
await Promise.all(promises).catch((error) => {
|
||||
console.error('Failed to load widgets', error);
|
||||
null;
|
||||
});
|
||||
const results = await Promise.all(promises.map(p => p.catch(e => e)));
|
||||
const errors = results.filter(result => (result instanceof Error));
|
||||
if (errors.length > 0) console.error('Failed to load one or more widgets:', errors);
|
||||
});
|
||||
}
|
||||
|
||||
@ -153,13 +152,21 @@ class WidgetManager {
|
||||
// restore
|
||||
for (const [id, configuration] of Object.entries(this.widgetConfigurations)) {
|
||||
if (id in this.loadedModules) {
|
||||
this._createGridStackWidget(id, this.loadedModules[id], configuration);
|
||||
try {
|
||||
this._createGridStackWidget(id, this.loadedModules[id], configuration);
|
||||
} catch (error) {
|
||||
console.error('Failed to create widget', id, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// default
|
||||
for (const [identifier, widgetClass] of Object.entries(this.loadedModules)) {
|
||||
this._createGridStackWidget(identifier, widgetClass);
|
||||
try {
|
||||
this._createGridStackWidget(identifier, widgetClass);
|
||||
} catch (error) {
|
||||
console.error('Failed to create widget', identifier, error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -382,18 +389,47 @@ class WidgetManager {
|
||||
* individual widget tick() callbacks are not bound to a master timer,
|
||||
* this has the benefit of making it configurable per widget.
|
||||
*/
|
||||
async _loadDynamicContent() {
|
||||
// map to an array of context-bound _onMarkupRendered functions
|
||||
let fns = Object.values(this.widgetClasses).map((widget) => {
|
||||
return this._onMarkupRendered.bind(this, widget);
|
||||
async _loadDynamicContent() {
|
||||
// map to an array of context-bound _onMarkupRendered functions and their associated widget ids
|
||||
let tasks = Object.entries(this.widgetClasses).map(([id, widget]) => {
|
||||
return {
|
||||
id,
|
||||
func: this._onMarkupRendered.bind(this, widget)
|
||||
};
|
||||
});
|
||||
// convert each _onMarkupRendered(widget) to a promise
|
||||
let promises = fns.map(func => new Promise(resolve => resolve(func())));
|
||||
// fire away
|
||||
await Promise.all(promises).catch((error) => {
|
||||
console.error('Failed to load dynamic content', error);
|
||||
null;
|
||||
|
||||
// Convert each _onMarkupRendered(widget) to a promise
|
||||
let promises = tasks.map(({ id, func }) => ({
|
||||
id,
|
||||
promise: new Promise(resolve => resolve(func()))
|
||||
}));
|
||||
|
||||
// Fire away and handle errors
|
||||
const results = await Promise.all(promises.map(({ id, promise }) =>
|
||||
promise.catch(error => ({ error, id }))
|
||||
));
|
||||
|
||||
const errors = results.filter(result => {
|
||||
if (result && 'error' in result) {
|
||||
return result.error instanceof Error
|
||||
}
|
||||
});
|
||||
|
||||
if (errors.length > 0) {
|
||||
errors.forEach(({ error, id }) => {
|
||||
console.error(`Failed to load content for widget: ${id}, Error:`, error);
|
||||
|
||||
const widget = $(`.widget-${id} > .widget-content > .panel-divider`);
|
||||
widget.nextAll().remove()
|
||||
widget.after(`
|
||||
<div class="widget-error">
|
||||
<i class="fa fa-exclamation-circle text-danger"></i>
|
||||
<br/>
|
||||
Failed to load content
|
||||
</div>
|
||||
`);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Executed for each widget; starts the widget-specific tick routine.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user