-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
docs: UI interfaces and Tauri starter kit
- Loading branch information
Showing
10 changed files
with
261 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# Alerting over events | ||
|
||
Start typing here... |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,5 @@ | ||
# Alerts | ||
|
||
Alerts (based on UI Toasts) are a safety feature for instant notification of an issue that occurred. | ||
|
||
[//]: # (TODO) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,71 @@ | ||
# Command Invoker | ||
|
||
Start typing here... | ||
The command invoker interface abstracts and decouples the functionality of calling commands to the backend. | ||
|
||
## Two types of commands {collapsible="true"} | ||
|
||
It is important to note the difference in the underlying split between types of commands: | ||
|
||
- Pod command (used in the `<PodCommandButton>`): a command that acts like a message to the pod. | ||
These commands are entirely meant as communication to the pod from the GUI. | ||
- Backend command (used in the `<BackendCommandButton>`): a command that triggers auxiliary backend functionality (e.g. | ||
loading procedures, stopping the server, initiating connection, etc.) | ||
|
||
> Despite this, the interface of the Command Invoker has a single method to invoke a command. | ||
> The actual implementation of the difference is done by specifying the name of the function for triggering such | ||
> a pod message command inside the `SerpentaConfig` using the `pod_command_name` field. | ||
{style="note"} | ||
|
||
**Reasoning behind this split:** when developing the DH08 GUI, the initial implementation provided such one command | ||
for sending messages to the pod in the Tauri backend, which acts as simply an intermediary between the pod and the GUI. | ||
Other commands meant to change the state of the backend or trigger different functionality were implemented as separate | ||
Tauri commands. | ||
|
||
## Usage and place in the architecture | ||
|
||
The original GUI used Tauri, and the necessity for such an interface was not apparent at first. | ||
To support Serpenta for different stacks, | ||
the actual implementation of communication to a backend was decoupled from the Serpenta UI kit logic. | ||
|
||
### Implementation in the Tauri Starter Kit | ||
|
||
When creating the provided [Tauri Starter Kit](Tauri-Starter-Kit.md), the implementation of the command invoker is | ||
done by using the Tauri api for commands as done in the real DH08 GUI. | ||
The option to swap it out for a different implementation still exists if desired. | ||
|
||
## Reference | ||
|
||
Below are the TSDoc comments of each method or field part of this interface. | ||
|
||
### Methods | ||
|
||
#### `invokeCommand<T>(...):Promise<T>;` | ||
|
||
Invoke a command given its name/identifier and an object of arguments. | ||
|
||
**Params:** | ||
- commandName: the name/identifier of the command to be executed. | ||
- args: the arguments with which the command will be called. | ||
They are of the type `Record<string, unknown>` because they will take an | ||
object representing the arguments we call the command with. | ||
|
||
**Type params:** | ||
|
||
- T: the return type of the invoked command. | ||
|
||
**Returns:** | ||
a Promise of type T—the return type of the command itself. | ||
|
||
**Example:** | ||
|
||
If we were to call a function (in an arbitrary language) that takes | ||
arguments (width: integer, height: integer, label: string) which returns an integer, | ||
we will call this `invokeCommand` method as: | ||
|
||
```Typescript | ||
const res:number = await invokeCommand<number>("function_name", { | ||
width: 4, | ||
height: 5, | ||
label: "Rectangle" | ||
}); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,66 @@ | ||
# Configuration Interface | ||
|
||
Built to allow for dependency injection, the `<SerpentaShell />` component takes a configuration prop which is set as | ||
context for all its children (recursively). | ||
Built to allow for dependency injection and modularity, the `<SerpentaShell />` component takes a configuration prop | ||
which is set as context for all its children (recursively). | ||
Context in Svelte can be set by a parent component, and all the children nested within have access to it. | ||
|
||
## Interface | ||
|
||
The config itself has a describing interface: | ||
The config itself has the following interface: | ||
|
||
### Properties {collapsible="true"} | ||
|
||
Each of these properties can be accessed by calling the `getSerpentaContext()` command within a component nested | ||
inside the `<SerpentaShell>` one. | ||
|
||
> If the component is not living inside the shell, get context will return an empty object. | ||
> What's more, the context is set with the key "serpenta-context" which shall not appear for any other context within | ||
> If the component is not living inside the shell, get context will return an empty object. | ||
> What's more, the context is set with the key "serpenta-context" which shall not appear for any other context within | ||
> the shell or its children. | ||
| name | type | comments | | ||
|--------------------------|-------------------------------------|-------------------------------------------------------------------------------------| | ||
| `appWindow` | `any` | Interface for controlling the native app window. Used to make the custom title bar. | | ||
| `pod_name` | `string` | The name of the hyperloop pod. Used in the bottom bar. | | ||
| `grand_data_distributor` | `WindowEngine<any>` | | | ||
| `window_engine` | `CommandInvocation` | | | ||
| `grand_charter` | `Writable<Map<string, PlotBuffer>>` | | | ||
| `big_error` | `Writable<ErrorStatus>` | | | ||
| `latest_timestamp` | `Writable<number>` | | | ||
| `generic_command_name` | `string` | | | ||
| `stores.fsm_name` | `string` | | | ||
| name | type | comments | | ||
|--------------------|-------------------------------------|----------------------------------------------------------------------------------------------------------| | ||
| `appWindow` | `any` | Interface for controlling the native app window. Used to make the custom title bar. | | ||
| `pod_name` | `string` | The name of the hyperloop pod. Used in the bottom bar. | | ||
| `data_distributor` | `WindowEngine<any>` | The windowing engine interface, used to spawn a window e.g. containing a chart | | ||
| `window_engine` | `CommandInvocation` | Interface for invoking commands to the app backend. | | ||
| `grand_charter` | `Writable<Map<string, PlotBuffer>>` | A map of all charts used inside the Serpenta UI. | | ||
| `error_status` | `Writable<ErrorStatus>` | Store of a error status: 0 - safe, 1 - warning, 2 - unsafe. Used to light the shell for abnormal status. | | ||
| `latest_timestamp` | `Writable<number>` | The latest timestamp (the current moment) used to paint stale data. | | ||
| `pod_command_name` | `string` | The name of the command that sends a message/command to the pod itself. | | ||
| `fsm_store_name` | `string` | The name of the store that holds the active state of the FSM. | | ||
|
||
## Usage within the UI kit | ||
|
||
All Serpenta components shall get data that shall be configurable from this context by using the following: | ||
|
||
```html | ||
<!-- Component.svelte --> | ||
<!-- AnyComponent.svelte --> | ||
<script lang="ts"> | ||
import { getSerpentaContext } from "$lib"; | ||
import { getSerpentaContext } from "@delft-hyperloop/serpenta"; | ||
const context = getSerpentaContext(); | ||
</script> | ||
``` | ||
|
||
You will have to use this component inside the `<SerpentaShell />` parent component. | ||
When using SvelteKit, this can easily be done by wrapping the entire body of the app within this component inside | ||
the root `+layout.svelte` route: | ||
|
||
```html | ||
<!-- routes/+layout.svelte --> | ||
<script lang="ts"> | ||
import { | ||
SerpentaShell, | ||
defineConfig | ||
} from "@delft-hyperloop/serpenta"; | ||
const config = defineConfig(...); | ||
</script> | ||
|
||
<!-- short for <SerpentaShell config={config}> --> | ||
<SerpentaShell {config} > | ||
<slot /> | ||
</SerpentaShell> | ||
``` | ||
|
||
Now all inner pages will be loaded within the shell component because of the Svelte slots |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,83 @@ | ||
# Data Distributor | ||
|
||
The data distributor interface of the middleware configuration is responsible for distributing the stores where needed, | ||
updating them as necessary. | ||
The data distributor interface of the middleware configuration is responsible for distributing the fsm_store_name where | ||
needed, updating them as necessary. | ||
This object must be start-able, kill-able and have all required methods to update, get and register the fsm store. | ||
|
||
## Usage and place in the architecture | ||
|
||
The Data Distributor was born as an idea when deciding on how to receive data from the pod over to the GUI. | ||
Because a lot of data has to be available anywhere at any time and updated immediately throughout the UI, a system for | ||
managing the income of all new data points and supplying them to any element was necessary. | ||
|
||
This led to the creation of the `Grand Data Distributor`, which functioned as middleware between the Tauri backend | ||
and the frontend of the DH08 GUI. | ||
To allow for dependency injection as previously mentioned in the [architecture article](Architecture.md), | ||
an interface allowing for it was created—the Data Distributor. | ||
|
||
### Implementation in the Tauri Starter Kit | ||
|
||
When creating the provided [Tauri Starter Kit](Tauri-Starter-Kit.md), the implementation of the data distributor is | ||
done by using the Grand Data Distributor implementation used in the real DH08 GUI. | ||
The option to swap it out for a different implementation still exists if desired. | ||
|
||
## Reference | ||
|
||
Below are the TSDoc comments of each method or field part of this interface. | ||
|
||
### Methods | ||
|
||
#### `start(interval: number): void;` | ||
|
||
Start the data distributor middleware. | ||
This function is expected to trigger a repeated data fetching operation with | ||
the frequency determined by the interval parameter. | ||
|
||
**Params:** | ||
- interval: the interval between each fetching | ||
|
||
> This method will be called exactly once when initiating the `<Serpenta Shell/>` | ||
#### `fetchTestOnce(): Promise<void>;` | ||
|
||
Fetch data from the Tauri backend exactly once. | ||
The interface requires such a method for testing purposes. | ||
|
||
#### `kill(): void;` | ||
|
||
Kill the data distributor and stop its operation, clearing any intervals. | ||
This shall free all the memory used by the `DataDistributor` implementing class. | ||
|
||
#### `registerStore<T>(...): void` | ||
|
||
Register a store inside the Data Distributor. | ||
This function will add the store as a member of the distributor's collection and can be retrieved by its name further | ||
in the application. | ||
|
||
**Params:** | ||
|
||
- name: the name of the store | ||
- initial: initial value of the store | ||
- processFunction: the function to process the data | ||
- initialUnits: units of the store | ||
|
||
**Type params:** | ||
|
||
- T: the type of the value inside the Store | ||
|
||
#### `updateStore(...): void;` | ||
|
||
Update a store inside the Data Distributor. | ||
|
||
**Params:** | ||
- name: the name of the store | ||
- style: the style of the store as to what colour it shall become | ||
- units: the units of this store. These do not get changed often but are sent from the config, so they are kept. | ||
- data: the data to update the store with | ||
|
||
#### `getWritable<T>(name: string): Writable<Store<T>>;` | ||
|
||
Gets the writable (value that can be subscribed to in Svelte) given its name. | ||
|
||
**Params:** | ||
- name: the name of the store whose writable will be grabbed. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
# Making own adapter & config | ||
|
||
1. Setup a SvelteKit project | ||
2. install serpenta | ||
3. import the interfaces somewhere and implement them | ||
4. in the root of the project routes put all its child elements within a serpenta shell with a config that uses your | ||
implementations |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,12 @@ | ||
# Tauri Starter Kit Provided | ||
|
||
<primary-label ref="tauri-starter-kit"/> | ||
<primary-label ref="tauri-starter-kit" /> | ||
|
||
Start typing here... | ||
Because a lot of the Serpenta functionality is set up entirely in the backend of the app, | ||
with a frontend being a listener. | ||
As mentioned earlier in the [Tauri Starter Kit article](Tauri-Starter-Kit.md), a UI kit alone won't suffice | ||
to get you started quickly. | ||
|
||
Therefore, we provide a Tauri starter kit that is set up mostly the way the original DH08 GUI is. | ||
|
||
The child topics of this section will document the features provided by the starter Tauri kit. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,46 @@ | ||
# Windowing Engine | ||
|
||
Start typing here... | ||
The windowing engine interface acts as a trigger to allow for the spawning of new windows with information. | ||
This was done to make Serpenta a multi-monitor, | ||
multi-window GUI—elements we consider critical for a safe and efficient mission-critical GUI. | ||
|
||
## External "requirements" for windowing {collapsible="true"} | ||
|
||
Because the original implementation used Tauri, the windowing engine relied on the Tauri window api. | ||
Creating new windows is done by specifying the route of the page which is to be loaded in the new window. | ||
The implementation of the interface was based around this. | ||
|
||
Therefore, you are provided with url and a label when creating a window. | ||
This can still be easily adapted to any implementation. | ||
Extraction of identifying elements (e.g. id) can be done from the url, | ||
which can then be used to determine what data to load even without using separate routes. | ||
|
||
## Usage and place in the architecture | ||
|
||
The windowing feature came very late in the original DH08 GUI, only being created during the starting days of the EHW. | ||
It allows for spawning of additional windows to be put on different monitors for a multi-monitor setup. | ||
|
||
### Implementation in the Tauri Starter Kit | ||
|
||
When creating the provided [Tauri Starter Kit](Tauri-Starter-Kit.md), the implementation of the windowing engine is | ||
done by using the Tauri api for windows as done in the real DH08 GUI. | ||
The option to swap it out for a different implementation still exists if desired. | ||
|
||
## Reference | ||
|
||
Below are the TSDoc comments of each method or field part of this interface. | ||
|
||
### Methods | ||
|
||
#### `spawnWindow(...): void;` | ||
Spawn a window given options of a generic type, url and a label. | ||
|
||
**Params:** | ||
- url: the url of the page that will be loaded in the new window. | ||
- label: the label of the window in the title bar. | ||
- options: options when defining the window. (optional) | ||
|
||
**Type params:** | ||
- OPTION: the type that defines the `options` parameter. | ||
Can be used to determine what additional data can be passed when spawning a window. | ||
|