use chrono::{DateTime, Utc};
use clap::ValueEnum;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, ValueEnum)]
#[serde(rename_all = "lowercase")]
pub enum ResourceType {
Docs,
Article,
Video,
Repo,
Crate,
Book,
Spec,
Tool,
}
impl ResourceType {
pub fn label(self) -> &'static str {
match self {
ResourceType::Docs => "docs",
ResourceType::Article => "article",
ResourceType::Video => "video",
ResourceType::Repo => "repo",
ResourceType::Crate => "crate",
ResourceType::Book => "book",
ResourceType::Spec => "spec",
ResourceType::Tool => "tool",
}
}
}
impl std::fmt::Display for ResourceType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.label())
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Resource {
#[serde(default = "Uuid::new_v4")]
pub uuid: Uuid,
pub title: String,
#[serde(default)]
pub resource_type: Option<ResourceType>,
#[serde(default)]
pub url: Option<String>,
#[serde(default)]
pub description: Option<String>,
#[serde(default)]
pub tags: Vec<String>,
pub created_at: DateTime<Utc>,
#[serde(default)]
pub updated_at: Option<DateTime<Utc>>,
#[serde(default)]
pub deleted_at: Option<DateTime<Utc>>,
}
impl Resource {
pub fn new(title: String) -> Self {
Self {
uuid: Uuid::new_v4(),
title,
resource_type: None,
url: None,
description: None,
tags: Vec::new(),
created_at: Utc::now(),
updated_at: Some(Utc::now()),
deleted_at: None,
}
}
pub fn touch(&mut self) {
self.updated_at = Some(Utc::now());
}
pub fn soft_delete(&mut self) {
self.deleted_at = Some(Utc::now());
self.touch();
}
pub fn is_deleted(&self) -> bool {
self.deleted_at.is_some()
}
}