-
Notifications
You must be signed in to change notification settings - Fork 3
The UI allows the user to authenticate. Once successfully authenticated, the user is shown a list of all sessions currently in the system. A session represents the current state of a model canvas. Once a session is selected, the user is taken to the CanvasScreen, which allows them to edit the canvas elements collaboratively with any other user who has selected the same session. There is currently no concept of ownership over a session, and no way to disallow a user from viewing or editing a session.
All communication with the Firebase database is handled through the FirebaseManager and FirebaseDataModel, found in the data/ directory.
The entry point for the application is found in index.tsx, which simply creates an App component and displays the relevant screen.
See LoginScreen and FirebaseManager for information about authentication. The only authentication available currently is through a Google account. Once the user is authenticated, show them the SessionSelectScreen which contains all of the session IDs and allows the chance to select one.
The Canvas uses Konva and thus the HTML5 Canvas component. This allows smooth user interaction as well as many utilities for drawing shapes, particularly lines and arrows. When a user selects a session, they are brought to a Canvas representing the current state of that model. The canvas is updated in real-time with any changes made by collaborating users. The CanvasScreen also contains a Toolbar component which allows the user to switch between modes as well as providing the commands listed in the "commands" section of this page.
The canvas starts empty and subscribes to the component list for the selected session through the FirebaseDataModel. This is handled by the CanvasScreen component's state. When new data becomes available or the user interacts with a component, the CanvasScreen passes the component list as props to a child object of BaseCanvas. The type of canvas depends on the mode - i.e. it could be a MoveModeCanvas, EditModeCanvas, etc. Each subclass has behaviours unique to that mode.
Components are stored in the state as UiData types (e.g. StockUiData) which contains the raw information about the component and methods for making any computations necessary for rendering. The corresponding React elements (e.g. Stock) contain only the information necessary for React to render the component. We use helper class ComponentCollection to store all the components which provides extra utilities such as filtering components, showing lists of all components including/excluding inner model components, etc.
A sub-model is a saved model from the model library which is imported as a snapshot and cannot be edited other than by using Identify mode (see below). A sub-model is saved as a StaticModelUiData which appears at first as an empty square, until it has its Components list populated by querying the database. When the query is complete, it prepends the static model's component ID to each inner component similar to a URL, for example if static model with ID 12 has a component with ID 13, that component is stored as 12/13. All the components are then rendered onto the screen surrounded by the square containing the sub-model components.
Identification is the only mechanism by which users may connect between the outer model and inner models, or between two inner models. Identification declares two components to be the "same", e.g. With an SIR model for disease spread, and an SVI model for vaccination dynamics, we would identify stocks S and I since they are meant to represent the same quantities. When 2 stocks are identified, it is represented as a Substitution. While rendering, Substitutions are applied such that and connection or flow from/to the substituted component are visually redirected to the substituting component, i.e. the substituted component "disappears" and its arrows get moved to its substitution.
Scenarios are stored as a ScenarioUiData, but since they do not inherit VisibleComponent they have no corresponding Scenario object for rendering. When the "scenarios" button is clicked, a box appears showing the names of all ScenarioUiData components of this model, as well as a special case called "baseline" where all parameters have default values. When the user clicks on an edit icon for any scenario except baseline, another box appears showing all of the parameters of this model and allows the user to override them. In the Scenario menu the user may also select a scenario by clicking its associated checkbox. This means that any subsequent calls to interpret the model by the current user will use the parameters specified in that scenario.
Call to the backend server requesting the Julia code representing the model. The code will be downloaded as a text file via the user's browser.
Get the data for this model from the Firebase server, stringify it, and save it via the browser as a text file. No calls to the backend server are made.
This option will open another menu which provides all of the different options for model interpretation. Currently, the only option is to interpret using ODE semantics, however as features are added to StockFlow.jl and the backend is upgraded to support them, we hope to add more options in the near future.
When the user clicks on one of the semantic options (e.g. ODE), a request is made to the backend with the model ID as well as the name of the scenario to be run. The model will be interpreted by the backend server and results sent back as a .png graph and saved via the browser. While results are pending, the icon for the "run" button changes to a spinning progress wheel and the backend is repeatedly polled. The backend responds either asking the user to wait longer, or with a binary blob of the .png file to be downloaded.
Publish a snapshot of the current model to the model library so that it can be imported into other models as a sub-model in the future. When the user presses this button, a box appears asking the user to name the sub-model. If that name already exists, the existing model is overwritten and the changes will be reflected in any models that use it as a sub-model. See the Database section for more information on how published models are stored.
Import a published model. This will appear on screen as a sub-model and can only interact with outer model components by using Identify mode (see the "identification" section for more). When the user clicks this button, a box appears with the names of all the models in the library and allows the user to select one or more.
Show a box containing the help instructions.
Go back to the session selection screen.