use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use super::core::{Issue, Plugin, PluginResult};
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct AnalyticsQuery {
pub date_range: Option<DateRange>,
pub statuses: Vec<String>,
pub tags: Vec<String>,
pub assignees: Vec<String>,
pub sprints: Vec<u32>,
pub include_deleted: bool,
pub limit: Option<usize>,
pub offset: Option<usize>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DateRange {
pub start: String,
pub end: String,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum MetricType {
Velocity,
LeadTime,
CycleTime,
Throughput,
WIP,
BlockedRatio,
EffortAccuracy,
StatusDistribution,
TagDistribution,
AssigneeWorkload,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MetricValue {
pub metric: MetricType,
pub value: f64,
pub unit: String,
pub breakdown: Option<HashMap<String, f64>>,
pub trend: Option<Trend>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Trend {
pub change: f64,
pub change_percent: f64,
pub direction: TrendDirection,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum TrendDirection {
Up,
Down,
Stable,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ReportType {
Burndown,
BurnUp,
VelocityTrend,
CumulativeFlow,
LeadTimeTrend,
TagDistribution,
AssigneeWorkload,
SprintSummary,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Report {
pub report_type: ReportType,
pub title: String,
pub generated_at: String,
pub data_points: Vec<DataPoint>,
pub summary: HashMap<String, serde_json::Value>,
pub metadata: HashMap<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DataPoint {
pub label: String,
pub values: HashMap<String, f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
pub enum ExportFormat {
Json,
Csv,
Markdown,
Html,
Custom(String),
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct IssueSnapshot {
pub issue: Issue,
pub snapshot_time: String,
pub status_at_time: String,
pub sprint_at_time: Option<u32>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Sprint {
pub number: u32,
pub name: Option<String>,
pub start_date: String,
pub end_date: String,
pub goal: Option<String>,
pub committed_effort: u32,
pub completed_effort: u32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatusTransition {
pub issue_id: String,
pub from_status: String,
pub to_status: String,
pub timestamp: String,
pub by_user: Option<String>,
}
pub trait AnalyticsPlugin: Plugin {
fn query_issues(&mut self, query: &AnalyticsQuery) -> PluginResult<Vec<Issue>>;
fn compute_metric(
&mut self,
metric: MetricType,
range: &DateRange,
) -> PluginResult<MetricValue>;
fn generate_report(
&mut self,
report_type: ReportType,
range: &DateRange,
) -> PluginResult<Report>;
fn export(
&mut self,
format: ExportFormat,
query: &AnalyticsQuery,
) -> PluginResult<Vec<u8>>;
fn available_metrics(&self) -> Vec<MetricType> {
vec![
MetricType::Velocity,
MetricType::LeadTime,
MetricType::CycleTime,
MetricType::Throughput,
MetricType::WIP,
]
}
fn available_reports(&self) -> Vec<ReportType> {
vec![
ReportType::Burndown,
ReportType::VelocityTrend,
]
}
fn available_formats(&self) -> Vec<ExportFormat> {
vec![
ExportFormat::Json,
ExportFormat::Csv,
]
}
fn get_snapshots(
&mut self,
_range: &DateRange,
) -> PluginResult<Vec<IssueSnapshot>> {
Ok(vec![])
}
fn get_transitions(
&mut self,
_range: &DateRange,
) -> PluginResult<Vec<StatusTransition>> {
Ok(vec![])
}
fn get_sprints(&mut self) -> PluginResult<Vec<Sprint>> {
Ok(vec![])
}
}