shuttle_common/models/
project.rs

1use chrono::{DateTime, Utc};
2use serde::{Deserialize, Serialize};
3use strum::{Display, EnumString};
4
5#[cfg(feature = "display")]
6use crossterm::style::Stylize;
7#[cfg(feature = "display")]
8use std::fmt::Write;
9
10use super::deployment::DeploymentState;
11
12#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
13#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
14#[typeshare::typeshare]
15pub struct ProjectCreateRequest {
16    pub name: String,
17}
18
19#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
20#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
21#[typeshare::typeshare]
22pub struct ProjectResponse {
23    pub id: String,
24    /// Display name
25    pub name: String,
26    /// Project owner
27    pub user_id: String,
28    /// Team project belongs to
29    pub team_id: Option<String>,
30    pub created_at: DateTime<Utc>,
31    pub compute_tier: Option<ComputeTier>,
32    /// State of the current deployment if one exists (something has been deployed).
33    pub deployment_state: Option<DeploymentState>,
34    /// URIs where running deployments can be reached
35    pub uris: Vec<String>,
36}
37
38impl ProjectResponse {
39    #[cfg(feature = "display")]
40    pub fn to_string_colored(&self) -> String {
41        let mut s = String::new();
42        writeln!(&mut s, "{}", "Project info:".bold()).unwrap();
43        writeln!(&mut s, "  Project ID: {}", self.id).unwrap();
44        writeln!(&mut s, "  Project Name: {}", self.name).unwrap();
45        writeln!(&mut s, "  Owner: {}", self.user_id).unwrap();
46        writeln!(
47            &mut s,
48            "  Team: {}",
49            self.team_id.as_deref().unwrap_or("N/A")
50        )
51        .unwrap();
52        writeln!(
53            &mut s,
54            "  Created: {}",
55            self.created_at
56                .to_rfc3339_opts(chrono::SecondsFormat::Secs, true)
57        )
58        .unwrap();
59        writeln!(&mut s, "  URIs:").unwrap();
60        for uri in &self.uris {
61            writeln!(&mut s, "    - {uri}").unwrap();
62        }
63
64        s
65    }
66}
67
68#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)]
69#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
70#[typeshare::typeshare]
71pub struct ProjectListResponse {
72    pub projects: Vec<ProjectResponse>,
73}
74
75/// Set wanted field(s) to Some to update those parts of the project
76#[derive(Debug, Default, Deserialize, Serialize, Clone, PartialEq)]
77#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
78#[typeshare::typeshare]
79pub struct ProjectUpdateRequest {
80    /// Change display name
81    pub name: Option<String>,
82    /// Transfer to other user
83    pub user_id: Option<String>,
84    /// Transfer to a team
85    pub team_id: Option<String>,
86    /// Transfer away from current team
87    pub remove_from_team: Option<bool>,
88    /// Change compute tier
89    pub compute_tier: Option<ComputeTier>,
90}
91
92#[derive(
93    Debug, Default, Clone, Copy, PartialEq, Eq, Display, Serialize, Deserialize, EnumString,
94)]
95#[cfg_attr(feature = "utoipa", derive(utoipa::ToSchema))]
96#[serde(rename_all = "lowercase")]
97#[strum(serialize_all = "lowercase")]
98#[typeshare::typeshare]
99pub enum ComputeTier {
100    #[default]
101    XS,
102    S,
103    M,
104    L,
105    XL,
106    XXL,
107}