(toggl-portal): Add clients and projects routes

This commit is contained in:
Joshua Coles 2023-11-06 13:48:46 +00:00
parent 6971e4a874
commit 100ef25044
4 changed files with 57 additions and 6 deletions

View File

@ -30,4 +30,5 @@ sea-orm = { version = "0.12", features = [
migration = { path = "./migration" }
chrono = { version = "0.4.31", features = ["serde"] }
futures = "0.3.29"
rucron = "0.1.5"
#tokio-cron-scheduler = "0.9.4"

View File

@ -6,7 +6,7 @@ use axum::http::StatusCode;
use hyper::HeaderMap;
use tracing::instrument;
use tracing::log::debug;
use crate::types::{Current, Project, ReportEntry, TogglQuery};
use crate::types::{Current, Project, ProjectClient, ReportEntry, TogglQuery};
#[derive(Debug, Clone)]
pub struct TogglClient {
@ -67,6 +67,26 @@ impl TogglClient {
Ok(res)
}
pub async fn fetch_clients(&self) -> Result<Vec<ProjectClient>, reqwest::Error> {
let url = format!(
"{base_url}/workspaces/{}/clients",
self.workspace_id,
base_url = self.base_url,
);
let res = self
.client
.get(&url)
.headers(self.headers.clone())
.send()
.await?
.json::<Vec<ProjectClient>>()
.await
.unwrap();
Ok(res)
}
pub async fn get_current(&self) -> Result<Option<Current>, reqwest::Error> {
let url = format!(
"{base_url}/me/time_entries/current",

View File

@ -1,6 +1,6 @@
use crate::client::TogglClient;
use crate::entity::time_entry::{self, Entity as TimeEntry};
use crate::types::{Current, ReportEntry, TogglQuery};
use crate::types::{Current, Project, ProjectClient, ReportEntry, TogglQuery};
use anyhow::anyhow;
use axum::http::StatusCode;
use axum::response::IntoResponse;
@ -50,10 +50,7 @@ pub async fn report(
Ok(Json(report))
}
async fn cache_report(
db: &DatabaseConnection,
models: &Vec<ReportEntry>,
) -> Result<()> {
async fn cache_report(db: &DatabaseConnection, models: &Vec<ReportEntry>) -> Result<()> {
let models = models.iter().flat_map(|entry| entry.as_models());
TimeEntry::insert_many(models)
@ -88,6 +85,14 @@ pub async fn start_time_entry(
Ok((StatusCode::OK, "Ok"))
}
async fn projects(Extension(toggl_client): Extension<TogglClient>) -> Result<Json<Vec<Project>>> {
Ok(Json(toggl_client.fetch_projects().await?))
}
async fn clients(Extension(toggl_client): Extension<TogglClient>) -> Result<Json<Vec<ProjectClient>>> {
Ok(Json(toggl_client.fetch_clients().await?))
}
async fn health(Extension(toggl_client): Extension<TogglClient>) -> Result<&'static str> {
return if toggl_client.check_health().await {
Ok("Ok")
@ -120,6 +125,8 @@ async fn main() -> Result<()> {
.route("/health", get(health))
.route("/current", get(current))
.route("/report", post(report))
.route("/projects", get(projects))
.route("/clients", get(clients))
.route("/start_time_entry", post(start_time_entry))
.layer(Extension(toggl_client))
.layer(Extension(db))

View File

@ -3,6 +3,7 @@ use serde_json::Value;
use serde_with::skip_serializing_none;
use std::collections::HashMap;
use std::option::Option;
use chrono::{DateTime, Utc};
#[derive(Clone, Serialize, Deserialize, Debug)]
pub struct TimeEntry {
@ -56,6 +57,28 @@ pub struct Project {
pub rest: HashMap<String, Value>,
}
/// Represents a client in Toggl.
#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectClient {
/// Indicates whether the client is archived or not.
archived: bool,
/// Represents the timestamp of the last update made to the client.
at: DateTime<Utc>,
/// The unique identifier for the client.
id: i32,
/// The name of the client.
name: String,
/// Indicates the timestamp when the client was deleted. If the client is not deleted, this property will be null.
server_deleted_at: Option<DateTime<Utc>>,
/// The Workspace ID associated with the client.
wid: i32,
}
#[allow(non_snake_case)]
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone, Default)]