Thanks for all the feedback! I really appreciate it. I think I will at least implement a POC to illustrate the concept I have in mind. Maybe as a TemplatePlugin to start with as I haven't looked into the UIPlugin at all so far. I think that would make my intentions a bit more clear and hopefully also inspire further dialogue.
What do you think of the time-series db concept? Would that be useful for other features than the dashboard? I'm a bit concerned about SD wear for RPi users.
I have made a quick and dirty POC based on FreeBoard.io now. This is just to illustrate some of the concepts from my original post.
This first video shows how to add a custom data source and create a basic dashboard from scratch. The data source is in this case a small web service that exposes some PSUtil metrics over a rest interface on localhost but It can in theory be another plugin or the OctoPrint API (shown in the next video). I also created a couple of widgets from the data source and arranged them as a dashboard.
This custom dashboard can be saved and loaded programatically but I haven't implemented that yet.
And here is the third and final video where I load an existing dashboard that connects to the Printer, Job and Connection endpoints of the OctoPrint API. It also contains a set of host widgets from the first video. I also show how the user can re-arrange the dashboard(s) to their taste.
I have made some progress and more or less settled on using Packery for the layout. I've experimented some more and I now have the bits and pieces I think I need to stitch this together.
I haven't made any actual widgets yet (except a webcam and some dummies) but I can at least create a new dashboard, add widgets thru both UI and settings, It is now possible to rearrange the widgets using drag&drop and the layout is persisted in the backend across devices/sessions. It is also possible to set widget sizes at creation time.
One thing I thought might be a useful. It's more of an extension on the "Drill-down" dashboards. Have you thought about drilling-up?
There are many users of octoprint that run multiple printers, so it would be of use to have a basic dashboard (% complete, ETA, etc) for each printer on one single dashboard page. You could click on a printer displayed to be taken to the actual octoprint instance and dashboard for the printer selected.
Thanks for the feedback! I hadn't thought of that but I think that could work out of the box if i succeed with this (and add a hyperlink to widgets). Since one data source type is JSON you could just connect widgets to the API of another OctoPrint server to get the available metrics out of it.
I have created a custom knockout binding handler "appendWidget" like this:
ko.bindingHandlers.appendWidget = {
init: function(element, valueAccessor) {
$grid.append( element ).packery( 'appended', element );
//Make it draggable
var draggie = new Draggabilly( element );
$grid.packery( 'bindDraggabillyEvents', draggie );
}
};
I think this is the right approach when injecting DOM elements and it almost works. The widgets are injected to the DOM and bound to the grid as expected. The problem is that i get a knockout error right after that:
packed_core.js?b00f909b:16147 Could not bind view model DashViewModel to target #tab_plugin_dash : Error: Unable to process binding "foreach: function(){return settingsViewModel.settings.plugins.dash.dashboards }"
Message: You cannot apply bindings multiple times to the same element.
Hi @Stefan_Cohen,
I checked out your sourcecode and received a different message:
Could not bind view model DashViewModel to target #tab_plugin_dash : ReferenceError: Unable to process binding "foreach: function(){return settingsViewModel.settings.plugins.dash.dashboards }"
Message: Unable to process binding "foreach: function(){return widgets }"
Message: Unable to process binding "attr: function(){return {'widget-id':id} }"
Message: id is not defined
hmm..I think the problem is the $grid-element append, because you append into the foreach-section new elements by your own and this is what KO doesn't like.
If I put the grid identifier above the foreach-loops it works...kind of...in my case it adds three widgets and then I receive again an error-message.
Sometimes you might want to run custom post-processing logic on the DOM elements generated by your templates. For example, if you’re using a JavaScript widgets library such as jQuery UI, you might want to intercept your templates’ output so that you can run jQuery UI commands on it to transform some of the rendered elements into date pickers, sliders, or anything else.
Generally, the best way to perform such post-processing on DOM elements is to write a custom binding,
What kind of problem do you have with the "afterrender" approach? Because this sound like the right solution. You modify needed attributes via template that jquery needs (widget-id).