use serde::{Deserialize, Serialize};
use super::common::{Gid, ResourceRef, StatusColor, UserRef};
use super::project::Project;
use super::status_update::StatusUpdateRef;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Portfolio {
pub gid: Gid,
pub name: String,
pub color: Option<String>,
pub owner: Option<UserRef>,
pub workspace: Option<ResourceRef>,
pub current_status_update: Option<StatusUpdateRef>,
pub created_at: Option<String>,
pub created_by: Option<UserRef>,
pub permalink_url: Option<String>,
#[serde(default)]
pub public: bool,
}
impl Portfolio {
pub fn status_color(&self) -> StatusColor {
self.current_status_update
.as_ref()
.and_then(|s| s.status_type)
.unwrap_or_default()
}
}
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "resource_type", rename_all = "snake_case")]
pub enum PortfolioItem {
Project(Box<Project>),
Portfolio(Box<Portfolio>),
}
impl PortfolioItem {
pub fn gid(&self) -> &str {
match self {
Self::Project(p) => &p.gid,
Self::Portfolio(p) => &p.gid,
}
}
pub fn name(&self) -> &str {
match self {
Self::Project(p) => &p.name,
Self::Portfolio(p) => &p.name,
}
}
pub fn status_color(&self) -> StatusColor {
match self {
Self::Project(p) => p.status_color(),
Self::Portfolio(p) => p.status_color(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct PortfolioItemRef {
pub gid: Gid,
pub resource_type: String,
pub name: Option<String>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_portfolio() {
let json = r#"{
"gid": "123",
"name": "My Portfolio",
"color": "light-blue",
"public": true
}"#;
let portfolio: Portfolio = serde_json::from_str(json).unwrap();
assert_eq!(portfolio.gid, "123");
assert_eq!(portfolio.name, "My Portfolio");
assert!(portfolio.public);
}
#[test]
fn test_deserialize_portfolio_item_project() {
let json = r#"{
"resource_type": "project",
"gid": "456",
"name": "Project A"
}"#;
let item: PortfolioItem = serde_json::from_str(json).unwrap();
assert!(matches!(item, PortfolioItem::Project(_)));
assert_eq!(item.gid(), "456");
assert_eq!(item.name(), "Project A");
}
#[test]
fn test_deserialize_portfolio_item_portfolio() {
let json = r#"{
"resource_type": "portfolio",
"gid": "789",
"name": "Nested Portfolio"
}"#;
let item: PortfolioItem = serde_json::from_str(json).unwrap();
assert!(matches!(item, PortfolioItem::Portfolio(_)));
assert_eq!(item.gid(), "789");
}
#[test]
fn test_portfolio_status_color() {
let json = r#"{
"gid": "123",
"name": "My Portfolio",
"current_status_update": {
"gid": "456",
"status_type": "yellow"
}
}"#;
let portfolio: Portfolio = serde_json::from_str(json).unwrap();
assert_eq!(portfolio.status_color(), StatusColor::Yellow);
}
}