pamoja_dashboard/source.rs
1//! The single seam between the dashboard and whatever produces its data.
2//!
3//! A real node and the [`Mock`](crate::Mock) both implement [`StateSource`], so the
4//! serving layer never knows which it is talking to. What you design and debug against
5//! the mock on a laptop is exactly what ships against real sensors.
6
7use crate::command::{Command, CommandError};
8use crate::state::State;
9
10/// Produces the current [`State`] snapshot whenever the dashboard asks for one.
11///
12/// The serving layer calls [`snapshot`](StateSource::snapshot) to answer `GET /state`
13/// and again on each live-update tick, so an implementation should return the latest
14/// view of the node cheaply. It takes `&mut self` so a source may advance internal
15/// state (a mock its clock, a real node its smoothing) as it is polled.
16pub trait StateSource {
17 /// Returns the node's current state snapshot.
18 ///
19 /// # Returns
20 ///
21 /// The latest language-neutral [`State`] to render.
22 fn snapshot(&mut self) -> State;
23
24 /// Switches a named view, for development and debugging only.
25 ///
26 /// The serving layer calls this when a request carries a `?scenario=` parameter,
27 /// so a single running dev server can be flipped through every state the UI must
28 /// handle. A real node has nothing to switch, so the default ignores the request.
29 ///
30 /// # Arguments
31 ///
32 /// * `key` - the requested view's identifier.
33 ///
34 /// # Returns
35 ///
36 /// `true` if the source switched to `key`, `false` if it does not recognize it.
37 fn select(&mut self, key: &str) -> bool {
38 let _ = key;
39 false
40 }
41
42 /// Carries out an authenticated control command, changing the node's state.
43 ///
44 /// The serving layer calls this only after a command has been authenticated, so an
45 /// implementation may act on it directly. A read-only source rejects every command,
46 /// which is the default.
47 ///
48 /// # Arguments
49 ///
50 /// * `command` - the action to carry out.
51 ///
52 /// # Returns
53 ///
54 /// `Ok(())` once the command has been applied; its effect shows in the next snapshot.
55 ///
56 /// # Errors
57 ///
58 /// Returns a [`CommandError`] if the source does not support the command, the target
59 /// is unknown, or the action is not allowed.
60 fn command(&mut self, command: &Command) -> Result<(), CommandError> {
61 let _ = command;
62 Err(CommandError::Unsupported)
63 }
64}