1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! The communication module contains all the structs used during communication with the core and/or
//! the client at the end of the UI.
//!
//! For communication with the UI in general the most important struct/type is the [ActionMessage] and
//! [SingleActionMessage]
//!

use std::collections::HashMap;

use actix::Message;
use serde::{Deserialize, Serialize};
use serde_json::Value;

/// This struct contains the structure for a method return
/// It consists of a return code and a single message which can be an error, a success or an info message
/// Is used together with `serde` for serialization and deserialization to and from JSON (mainly)
#[derive(Clone, Deserialize, Serialize, Debug)]
pub struct MethodResult {
    /// The return code of the method
    /// 0 = success
    /// > 0 = error
    pub code: i8,

    /// The message of the method
    /// If there is no message to the client the value can be [serde_json::Value::Null]
    /// For the value, if it is not just informational to functions in the frontend, it is recommended
    /// to use the [ActionMessage] struct/type to assemble a proper response for the UI.
    pub message: Value,
}

/// This contains the structure for a request to a method
///
/// Provided are the method_name. This *can* be useful if you implement multiple methods with the
/// same struct or call a method from multiple methods which, however has slightly different logic
/// depending on which method called it.
///
/// Arguments are supplied as well. This can be ignored when the struct used the derive macro and
/// the arguments were mapped to the struct fields already.
#[derive(Serialize, Deserialize, Debug, Default)]
pub struct MethodCall {
    /// The name of the method that is called
    pub method_name: String,

    /// The list of arguments which are supplied to the method
    pub arguments: HashMap<String, Value>,
}

impl Message for MethodCall {
    type Result = MethodResult;
}

/// # The ActionMessage
///
/// As an extension to the [SingleActionMessage], in case that you want to send multiple messages of
/// the same type, you can also provide the message objects in an array (which is always recommended,
/// even if you send multiple messages of different kinds).
///
/// # Example
///
/// The complete ActionMessage in the JSON format may look like the following:
///
/// ```json
/// [
///   {
///     "error": "An error occurred",
///     "info": "Try to do it different"
///   },
///   {
///     "error": "Another error occurred as well"
///   },
/// ]
/// ```
///
/// And to fulfill the possibilities, here the (recommended) way of sending multiple messages of the
/// same and different kind:
///
/// ```json
/// [
///   {
///     "error": "An error occurred"
///   },
///   {
///     "error": "Another error occurred as well"
///   },
///   {
///     "info": "Try to do it different"
///   },
/// ]
/// ```
///
/// While the lower example is recommended, the upper one may be better if you have to group messages
/// logically, for example in the case that there was an error, but there also might be a solution to
/// that which you want to recommend.
///
pub type ActionMessage = Vec<SingleActionMessage>;

/// # The (shorter) ActionMessage
///
/// The action message is meant to be a format which can be visualized to the user. It has to contain
/// information for the user.
///
/// # Example
///
/// A ActionMessage is supposed to follow the pattern, that an object, keyed by the message type, contains
/// a message as a string. This can be represented in JSON like the following
///
/// ```json
/// {
///   "error": "An error occurred"
/// }
/// ```
///
/// This will show an error message. However a ActionMessage can also contain multiple message types
/// in one object which then looks like the following
///
/// ```json
/// {
///   "error": "An error occurred",
///   "info": "Try to do it different"
/// }
/// ```
///
#[derive(Serialize, Deserialize, Debug)]
pub struct SingleActionMessage {
    /// Defines a error message field
    pub error: Option<String>,

    /// Defines a info message field
    pub info: Option<String>,

    /// Defines a debug message field
    pub debug: Option<String>,

    /// Defines a success message field
    pub success: Option<String>,

    /// Defines a markdown message field
    pub markdown: Option<String>,

    /// Defines a list in the message
    pub list: Option<String>,

    /// Defines a table in the message
    pub table: Option<String>,

    /// Causes the UI to load the following additional JavaScript files.
    /// The files might only be loaded if they were not before!
    pub scripts: Option<Vec<String>>,

    /// Causes the UI to load the following component to the current view
    /// This has to be an HTML tag name. The tag is supposed to be a custom element which renders
    /// the wanted view. For more information on how to best implement a component element take a
    /// look into the [UI Project](https://gitlab.com/y_software/new-home-ui).
    pub component: Option<String>,

    /// Causes the UI to open the following modal
    /// This has to be an HTML tag name. The tag is supposed to be a custom element which renders
    /// the wanted view. For more information on how to best implement a modal element take a look
    /// into the [UI Project](https://gitlab.com/y_software/new-home-ui).
    pub modal: Option<String>,
}