Skip to main content

hmd_profile_todo/
lib.rs

1use hmd_core::{
2    BlockDescriptor, MetadataField, MetadataFieldKind, ProfileDescriptor, ReferenceRule,
3    ReferenceValueKind,
4};
5use schemars::{schema_for, JsonSchema};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
9#[serde(rename_all = "snake_case")]
10pub enum TaskStatus {
11    Todo,
12    Doing,
13    Blocked,
14    Review,
15    Done,
16    Cancelled,
17}
18
19#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
20pub struct TaskMeta {
21    pub id: String,
22    pub title: String,
23    pub status: TaskStatus,
24    pub priority: Option<String>,
25    pub labels: Option<Vec<String>>,
26    pub milestone: Option<String>,
27    pub depends_on: Option<Vec<String>>,
28}
29
30#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
31pub struct CheckMeta {
32    pub id: Option<String>,
33    pub title: Option<String>,
34    pub status: Option<TaskStatus>,
35}
36
37#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
38pub struct MilestoneMeta {
39    pub id: String,
40    pub title: String,
41    pub due: Option<String>,
42}
43
44#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
45pub struct DependencyMeta {
46    pub from: String,
47    pub to: String,
48    pub kind: Option<String>,
49}
50
51#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
52pub struct LabelMeta {
53    pub id: String,
54    pub color: Option<String>,
55}
56
57#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
58#[serde(rename_all = "camelCase")]
59pub struct TodoProfileSchema {
60    pub task: Option<TaskMeta>,
61    pub check: Option<CheckMeta>,
62    pub milestone: Option<MilestoneMeta>,
63    pub dependency: Option<DependencyMeta>,
64    pub label: Option<LabelMeta>,
65}
66
67const TASK_STATUSES: &[&str] = &["todo", "doing", "blocked", "review", "done", "cancelled"];
68
69const TASK_FIELDS: &[MetadataField] = &[
70    MetadataField::required("id", MetadataFieldKind::String),
71    MetadataField::required("title", MetadataFieldKind::String),
72    MetadataField::required_enum("status", TASK_STATUSES),
73    MetadataField::optional("priority", MetadataFieldKind::String),
74    MetadataField::optional("labels", MetadataFieldKind::StringArray),
75    MetadataField::optional("milestone", MetadataFieldKind::String),
76    MetadataField::optional("depends_on", MetadataFieldKind::StringArray),
77];
78const CHECK_FIELDS: &[MetadataField] = &[
79    MetadataField::optional("id", MetadataFieldKind::String),
80    MetadataField::optional("title", MetadataFieldKind::String),
81    MetadataField::optional_enum("status", TASK_STATUSES),
82];
83const MILESTONE_FIELDS: &[MetadataField] = &[
84    MetadataField::required("id", MetadataFieldKind::String),
85    MetadataField::required("title", MetadataFieldKind::String),
86    MetadataField::optional("due", MetadataFieldKind::String),
87];
88const DEPENDENCY_FIELDS: &[MetadataField] = &[
89    MetadataField::required("from", MetadataFieldKind::String),
90    MetadataField::required("to", MetadataFieldKind::String),
91    MetadataField::optional("kind", MetadataFieldKind::String),
92];
93const LABEL_FIELDS: &[MetadataField] = &[
94    MetadataField::required("id", MetadataFieldKind::String),
95    MetadataField::optional("color", MetadataFieldKind::String),
96];
97
98const BLOCKS: &[BlockDescriptor] = &[
99    BlockDescriptor {
100        block_type: "task",
101        schema_id: "https://hmd.dev/schemas/todo@0.1/task.schema.json",
102        fields: TASK_FIELDS,
103        allowed_child_block_types: None,
104    },
105    BlockDescriptor {
106        block_type: "check",
107        schema_id: "https://hmd.dev/schemas/todo@0.1/check.schema.json",
108        fields: CHECK_FIELDS,
109        allowed_child_block_types: None,
110    },
111    BlockDescriptor {
112        block_type: "milestone",
113        schema_id: "https://hmd.dev/schemas/todo@0.1/milestone.schema.json",
114        fields: MILESTONE_FIELDS,
115        allowed_child_block_types: None,
116    },
117    BlockDescriptor {
118        block_type: "dependency",
119        schema_id: "https://hmd.dev/schemas/todo@0.1/dependency.schema.json",
120        fields: DEPENDENCY_FIELDS,
121        allowed_child_block_types: None,
122    },
123    BlockDescriptor {
124        block_type: "label",
125        schema_id: "https://hmd.dev/schemas/todo@0.1/label.schema.json",
126        fields: LABEL_FIELDS,
127        allowed_child_block_types: None,
128    },
129];
130
131const REFERENCE_RULES: &[ReferenceRule] = &[ReferenceRule {
132    block_type: "task",
133    field: "depends_on",
134    target_block_type: "task",
135    value_kind: ReferenceValueKind::StringArray,
136}];
137
138pub const PROFILE: ProfileDescriptor = ProfileDescriptor {
139    id: "todo@0.1",
140    name: "todo",
141    version: "0.1",
142    source: "official",
143    blocks: BLOCKS,
144    reference_rules: REFERENCE_RULES,
145};
146
147pub fn descriptor() -> ProfileDescriptor {
148    PROFILE
149}
150
151pub fn register_profile() -> ProfileDescriptor {
152    descriptor()
153}
154
155pub fn json_schema() -> serde_json::Value {
156    serde_json::to_value(schema_for!(TodoProfileSchema)).expect("serializes schema")
157}