Unable to watch loading state of a dbc.Container - plotly-dash

My goal in my multi-page app is to make the page load itself a trigger for a specific page’s callback, but since I don’t think this is possible, I am attempting to watch the loading state of the page’s dbc.Container.
When I run something similar to below, per the docs, I would have expected it to print a dict with the component name and True for the loading state. Instead, it prints None.
Can anyone offer any input on how to achieve this goal? thank you
#dash.callback(
Output("update_message", "children"),
Input('main_container', 'loading_state'),
)
def func(loading_state):
print(loading_state)
def layout():
return dbc.Container([***page contents here], id='main_container', fluid=True)

Related

Problem dropping same file twice in a row

I'm using the Dash Upload component, which in turn uses react-dropzone.
I can drag a file into the component and the corresponding callback will fire.
I can then drag a different file into the component and the callback will fire again.
But, if I drag a file into the component (which fires the callback) and then drag the same file into the component again, the callback does not fire.
There's a demo app in this Gist that demonstrates the behavior.
Searching for similar problems (stack-overflow, github) suggests that this behavior is to be expected because from the browser's point of view nothing has changed. Both of those discussions seem to end up with solutions that involve setting the .value part of some element to '', so that the browser sees the second drop event as a change.
Chriddyp contributed links to the relevant bit of code in Dash and pointed me to the react-dropzone component.
Is there a way to make dropping the file twice in a row work in Dash using react-dropzone?
Thanks!
g.
In Dash, callbacks are invoked every time a property changes. If you upload the same file a second time, the properties (e.g. the file name) are unchanged, and the callback will thus not be invoked. This is expected behavior.
To ensure that a callback is invoked every time, you must ensure that the Input property actually changes. One option would be to add a new property to the Upload component similar to the n_clicks property of buttons, say n_uploads, which is incremented each time a file is uploaded.
The easiest solution for the problem at hand would probably be to use the custom dash uploader instead. Among other things, it supports uploading the same file multiple times.
A bit late answer. I found a solution which is just reset the contents and filename to None in the Output of the callback.
A simple example
import dash
from dash import dcc, html
from dash.dependencies import Input, Output, State
app = dash.Dash(__name__)
app.layout = html.Div([
dcc.Upload(html.Button('Upload File', id='btn_id'), id='upload_id'),
html.P(id='show_id'),
])
#app.callback(
Output('show_id', 'children'),
Output('upload_id', 'contents'),
Output('upload_id', 'filename'),
Input('upload_id', 'contents'),
State('upload_id', 'filename'),
State('btn_id', 'n_clicks'),
)
def uploaded_a_file(contents, filename, n_clicks):
if not contents:
raise dash.exceptions.PreventUpdate
msg = f'Uploaded {filename} for {n_clicks} time.'
return msg, None, None
if __name__ == '__main__':
app.run_server(debug=True)
Another workaround, similar to #aura's, is to replace the upload component entirely with a callback. This strategy can be useful when replacing "contents" would lead to circular callbacks.
See https://github.com/plotly/dash-core-components/issues/816#issuecomment-1032635061

React - Rending JSON as UI objects and allowing any user changes to these UI objects to update the JSON

We have an internal tooling system that uses JSON to specify various actions, tasks etc. I'm making a single page web application to visualise this information. The web application contains a text area for editing/pasting JSON and another area which renders the JSON into UI elements.
So I want to take JSON from the text area and visualize it. But also, I want the user to be able to interact with this render visualization, making changes/configuring options and have it update the JSON immediately. I guess one could call that two-way binding.
While going from JSON -> HTML DOM elements is easy, I'm not sure how to do the reverse and go DOM -> JSON. Let's say we have some JSON
{"task1" : {
"canFail" : true,
"autoRestart" : false,
"connectionPropertys" : {
... }
}
}
I would visualize task1 as some UI element with check boxes for canFail and autoRestart. I want the user to be able to both
edit the JSON "canFail" value to 'true' or 'false' and have that
immediately render (this is easy - just re-render the entire JSON)
check or uncheck the canFail checkbox and have the JSON be
automatically updated (hard part - where I'm stuck)
In React we pass state/properties down the the children, so the component rending the checkbox(es) would only know about canFail or autoRestart... it might not know about "task1". If the checkbox is changed, sure I can have some handler function fire, but it doesn't actually know what key/value in the JSON this corresponds to (e.g. it knows nothing of task1 and there could be multiple task1s).
Interested to know what a good approach would be here to tackle this.
Thanks :)

Changing materials in Forge

We are currently making the client retrieve the object states when the page loads (which will cause the 'pending' objects in the model to turn into different colors). Then we poll for changes to update the coloring (Firstly: pending object gets colored when the viewer loads, and then we keep polling to check and change state again, to make Forge render those in a different color and store their old color/material. When the polling received a change that an object should no longer be colored, it tells Forge to use the old color/material again.
The problem:
We've found out what the problem is, but we couldn't find out how to fix it. The problem is that changing materials in Forge doesn't work after startup anymore, it only works in the first ~3 seconds or so (the materials were used to show the colors).
However, setting overlays works even after the first ~3 seconds, (showing overlays instead of materials to show the colors).
This is not what we want to achieve. This looks unoptimized, because overlays will be shown through everything.
The materials, however, seem to be 'locked', as in, they cannot be changed anymore after the first ~3 seconds. It seems like they aren't refreshed or something
In the examples, we found they used viewer.impl.invalidate(true) to refresh the Forge viewer, but that doesn't do anything after ~3 seconds.
We've also tried every combination of viewer.impl.invalidate(true, true, true) as well as setting material.needsUpdate to true, as well as trying to re-render the entire scene.
We also found this: https://github.com/mrdoob/three.js/issues/790, but we couldn't find a good way to do that in Forge, we tried viewer.requestSilentRender() but that didn't do anything either.
Anyway, we've tried everything we could come up with and could find online to make the materials work, but nothing made a difference.
We are looking to find someone that's more experienced with how Forge works that can see what the material code is doing wrong.
As for the content, here is all the code you will need to understand what is happening:
DROPBOX LINK
And here is a small part of the "index.html" file that sets the color:
try
{
viewer.restoreAllColorOverlays(); //for materials instead of overlays: viewer.restoreAllColorMaterials();
$.each(colors, function(color, selectionIds)
{
viewer.setColorOverlay(selectionIds, color); //for materials instead of overlays: viewer.setColorMaterial(selectionIds, color);
});
}
catch(error)
{
console.error(error);
}
I have no idea how you implement your app, so I only tell what I found in your codes. If you want to resolve the issue you addressed, you can consider providing a reproducible case demonstrating that, I will gladly pass it to our dev team. Those following items should be in the reproducible case:
A short exact description of what you are trying to achieve. The behavior you observe versus what you expect, and why this is a problem.
A complete yet minimal sample source model to run a test in.
A complete yet minimal Forge app that can be run and debugged with a simple procedure to analyze its behavior lives in the sample model.
A complete yet minimal pure three.js app that can be run and demonstrated the shader effect you want. Note. Forge Viewer is using r71 three.js.
Detailed step-by-step instructions for reproducing the issue, e.g. which element to pick, what command to launch etc.
If your reproducible case could not be posted here publicly, please send it to the forge.help#autodesk.com and remove sensitive data or information before you send.
=== Something I found in your codes:
I found here are some wrong types and missing actions in your ColorMaterial extension. The color property of an material should the a type of the THREE.Color. Here is my modification:
Autodesk.Viewing.Viewer3D.prototype.setColorMaterial = function(objectIds, color)
{
if( !(color instanceof THREE.Color) ) throw 'Invalid argument: Color';
var material = new THREE.MeshPhongMaterial
({
color: color,
opacity: 0.8,
transparent: true
});
viewer.impl.matman().addMaterial( 'ColorMaterial-' + new Date().getTime(), material, true );
// ...........
};
Its' result is here:
In the ColorOverlay extension, The type of material color property is also wrong, it should be a type of THREE.Color, too. Changing it into THREE.Color should work fine. In addition, overlay is covers on 3D objects, so you should call viewer.hide() with your setColorOverlay() together. Otherwise, it won't look like a transparent object.
Without hidding 3D object of the wall:
hide 3D object of the wall:

Where is the uri of the new window, in create-web-view?

According to the documentation, the create-new-window signal is called when a webkit is creating a new window. I've been trying to override this to handle <a target='_blank' links in PyGTK webkit browser. In a subclass of WebView I have:
...
self.connect("create-web-view", self.newWin)
...
def newWin(view, frame, data):
print view.get_property('uri')
print frame.get_property('uri')
print data.get_property('uri')
It is called when a new-window link is clicked, but for some reason all of these objects show the same url, the terminal prints out the current page url three times. How can I find the url that is supposed to be passed to a new window?
Thanks to ptomato, I found a solution. Setting the signal to this function works:
...
self.connect("new-window-policy-decision-requested", self.newWin) #requires webkit 1.1.4
...
def newWin(self, view, frame, request, nav_action, policy_decision):
"""
Calls the default browser on external link requests.
"""
functiontoviewurl(request.get_uri())
# According to the documentation: http://webkitgtk.org/reference/webkitgtk/stable/webkitgtk-webkitwebview.html#WebKitWebView-new-window-policy-decision-requested
# call ignore on the policy decision, then return true (that is, we handled it).
policy_decision.ignore()
return True
You can't intercept the creation of a new window by catching that signal - by that time, the browser has already decided it will create a new window. Instead, connect to new-window-policy-decision-requested and get the URI from the request parameter.

What is eager loading?

What is eager loading? I code in PHP/JS but a more generalised answer will be just fine.
I saw a lot of questions regarding Java & Ruby, but i don't know any of these languages, and I find it hard to read code. I don't know whats supposed to do in the first place
There are three levels:
Eager loading: you do everything when asked. Classic example is when you multiply two matrices. You do all the calculations. That's eager loading;
Lazy loading: you only do a calculation when required. In the previous example, you don't do any calculations until you access an element of the result matrix; and
Over-eager loading: this is where you try and anticipate what the user will ask for and preload it.
I hope that makes sense in the context you're seeing it.
Let me give you a "Webby" example.
Imagine a page with rollover images like for menu items or navigation. There are three ways the image loading could work on this page:
Load every single image required before you render the page (eager);
Load only the displayed images on page load and load the others if/when they are required (lazy); and
Load only the displayed images on page load. After the page has loaded preload the other images in the background in case you need them (over-eager).
Make sense?
It's the opposite of lazy loading, which defers initialization of an object until the object is needed. Eager loading initializes an object upon creation.
If you imagine you have object called person who has a name, a date of birth and number of less critical details, lets say favourite colour, favourite tv program.
To lazy load this class you would initalise it reading in perhaps from a database all the core more frequently used details (say name and date of birth) and only read in the less used details when / if they are needed, eager loading is the opposite, i.e. you load in all the details at the same time.
The benifits of lazy loading are often citied as effiecency, however if objects aren't that complex or efficency isn't a concern eager loading may be used
Eager loading is also used in Angular 8. It just means that the instant the application is loaded inside the browser we automatically, instantly get all the code inside a particular module, for example, say you just created an Auth Module with a Signin and Signup component to it that gets imported into an App Module.
In contrast, there is lazy loading, which is when we tell the App Module which has the Auth Module loaded into it, to only load the Auth Module at a certain point in time such as when a user goes to a certain route.