Welcome to the NOVA tutorial! This guide will walk you through the process of building interactive tools for **neutron analysis** using the NOVA platform. You will learn how to create a web application that leverages the NOVA libraries to simplify interaction with the Neutron Data Interpretation Platform (NDIP).
As mentioned in the introduction, all code examples in this tutorial are based on a template application. In this episode, we will create this starting point by cloning a template using the `copier` library. This template provides a basic project structure and pre-configured files that will help us get started quickly with our NOVA project, saving us from setting up everything from scratch.
In this section, we will start using the `nova-galaxy` library to interact with the NDIP platform and run a neutron analysis tool. First, ensure you have set your `GALAXY_URL` and `GALAXY_API_KEY` as environment variables, as explained in the notes at the end of this episode. We also need to add `nova-galaxy` as a project dependency.
# 4. User Interface Best Practices: The MVVM Design Pattern
In this section, we will introduce the Model-View-ViewModel (MVVM) design pattern, a powerful architectural approach for structuring applications, particularly those with user interfaces. We\'ll explore the core principles of MVVM, the roles of each component, and how the NOVA framework simplifies its implementation, making your code more organized, testable, and maintainable.
@@ -16,8 +37,9 @@ Before diving into MVVM, it\'s helpful to understand what a *design pattern* is
MVVM is an architectural design pattern specifically designed for applications with user interfaces (UIs). It aims to separate the UI (the View) from the underlying data and logic (the Model) by introducing an intermediary component called the ViewModel. This separation makes the application more maintainable, testable, and easier to evolve.
The MVVM pattern consists of three core components:

The MVVM pattern consists of three core components:
***Model:** The Model represents the *data* and the *business logic* of the application. It\'s responsible for:
* Data storage (e.g., reading from and writing to a database, a file, or an API).
* Data validation (ensuring the data is in a valid state).
@@ -41,7 +63,7 @@ The MVVM pattern consists of three core components:
* Handling user actions from the View. This might involve validating user input, updating the Model, or triggering other actions in the application.
* Exposing data and commands to the View through *data binding*.
The ViewModel is *UI-specific*. It knows about the View and the data that the View needs, but it doesn\'t know about the specific UI elements that are used to display the data. It also orchestrates the interaction between the View and the Model.
The ViewModel knows about the View and the data that the View needs, but it doesn\'t know about the specific UI elements that are used to display the data. It also orchestrates the interaction between the View and the Model.
*The ViewModel is where we\'ll use `nova-mvvm` to create bindings between the ViewModel and the View, enabling the reactive updates.*
@@ -193,9 +215,8 @@ poetry run app
You should see `Fractal tool finished successfully.` printed to the console, although we have not created a UI yet.
* In `FractalViewModel` in `src/nova_tutorial/view_models/fractal_view_model.py`, modify the `update_fractal_programmatically` function from the previous exercise to use an *invalid* fractal type:
```python
defupdate_fractal_programmatically(new_type:str):
@@ -211,12 +232,18 @@ You should see `Fractal tool finished successfully.` printed to the console, alt
* The "Current fractal type (after attempt):" is still "mandelbrot" indicating the invalid update was rejected.
* The "Current message:" now contains a "Validation Error" message from Pydantic.
* In `src/nova_tutorial/view_models/fractal_view_model.py`, add `print` statements within the `FractalViewModel.__init__` method to print the initial values of `self._fractal_type`, `self._job_status`, and `self._message`.
* Run the application (`poetry run app`). Observe the output in the console. Verify that the initial values are printed as expected.
* Now, modify the `FractalViewModel.__init__` method to change the initial value of `self._message` to "Application starting...". Run the application again and confirm that the printed initial message has changed.
* In `FractalViewModel` in `src/nova_tutorial/view_models/fractal_view_model.py`, after the line `self.fractal_type_bind = binding.new_bind(...)` in `__init__`, add the following lines:
```python
print("Initial fractal type:",self._fractal_type)# Print initial value
@@ -233,6 +260,8 @@ You should see `Fractal tool finished successfully.` printed to the console, alt
* The message "Fractal type updated programmatically to: julia" is printed.
* The final fractal type (after programmatic update) is printed as "julia".
# 5. Web-based User Interface Development with Trame
In this section, we will dive into Trame and the `nova-trame` library to build interactive web-based user interfaces for our NOVA applications. We\'ll explore how `nova-trame` simplifies UI development within the NOVA ecosystem and how to use common layout components.
@@ -165,11 +189,20 @@ poetry run start
You should now see the simple UI. When you click the "Sample Tab 1" and "Sample Tab 2" tabs, you should now see the updated content with the new UI components.
## Exercises
::::::::::::::::::::::::::::::::::::::: challenge
**Explore the `InputField` Component**
Modify the `InputField` component in `SampleTab1` to automatically retrieve the label, hint, and validation rules from a Pydantic model field. Create a simple Pydantic model with a `username` field with a `title`, `description`, and `min_length` constraint.
Combine `GridLayout`, `VBoxLayout`, and `HBoxLayout` components to create a more complex UI layout in `SampleTab2`. Try creating a layout with a header, a sidebar, and a main content area.
1.**Explore the `InputField` Component:** Modify the `InputField` component in `SampleTab1` to automatically retrieve the label, hint, and validation rules from a Pydantic model field. Create a simple Pydantic model with a `username` field with a `title`, `description`, and `min_length` constraint.
2.**Create a Complex Layout:** Combine `GridLayout`, `VBoxLayout`, and `HBoxLayout` components to create a more complex UI layout in `SampleTab2`. Try creating a layout with a header, a sidebar, and a main content area.
3.**Customize Component Appearance:** Experiment with customizing the appearance of the Vuetify components using the various props and styles available. Try changing the color, size, font, and other visual attributes of the components. Refer to Vuetify\'s component documentation for details.
::::::::::::::::::::::::::::::::::::::: challenge
**Customize Component Appearance**
Experiment with customizing the appearance of the Vuetify components using the various props and styles available. Try changing the color, size, font, and other visual attributes of the components. Refer to Vuetify\'s component documentation for details.