Skip to main content

kaizen/feedback/
types.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2use clap::ValueEnum;
3use serde::{Deserialize, Serialize};
4use std::fmt;
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ValueEnum)]
7#[serde(rename_all = "lowercase")]
8pub enum FeedbackLabel {
9    Good,
10    Bad,
11    Interesting,
12    Bug,
13    Regression,
14}
15
16impl FeedbackLabel {
17    pub fn from_str_opt(s: &str) -> Option<Self> {
18        match s {
19            "good" => Some(Self::Good),
20            "bad" => Some(Self::Bad),
21            "interesting" => Some(Self::Interesting),
22            "bug" => Some(Self::Bug),
23            "regression" => Some(Self::Regression),
24            _ => None,
25        }
26    }
27
28    pub fn to_db_str(&self) -> &str {
29        match self {
30            Self::Good => "good",
31            Self::Bad => "bad",
32            Self::Interesting => "interesting",
33            Self::Bug => "bug",
34            Self::Regression => "regression",
35        }
36    }
37}
38
39impl fmt::Display for FeedbackLabel {
40    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
41        write!(f, "{}", self.to_db_str())
42    }
43}
44
45/// Score in range 1..=5.
46#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
47pub struct FeedbackScore(pub u8);
48
49impl FeedbackScore {
50    /// Returns `None` if `v` is not in 1..=5.
51    pub fn new(v: u8) -> Option<Self> {
52        if (1..=5).contains(&v) {
53            Some(Self(v))
54        } else {
55            None
56        }
57    }
58}
59
60#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
61pub struct FeedbackRecord {
62    pub id: String,
63    pub session_id: String,
64    pub score: Option<FeedbackScore>,
65    pub label: Option<FeedbackLabel>,
66    pub note: Option<String>,
67    pub created_at_ms: u64,
68}