Refactor Toggl API types

Significant renaming and data type changes to Toggl API types occurred to improve identification and consistency. For example, 'Current' is renamed to 'TimeEntry', 'ProjectClient' is renamed to 'Client', and 'TogglQuery' is renamed to 'TogglReportQuery'. Changes affected multiple sections of the codebase, including routes and DB access.
This commit is contained in:
Joshua Coles 2024-03-02 10:10:30 +00:00
parent 9cfe56b3ce
commit 90457155aa
5 changed files with 38 additions and 29 deletions

View File

@ -1,5 +1,5 @@
use crate::entity::{client, project, time_entry};
use crate::toggl_api::types::{Project, ProjectClient, ReportRow};
use crate::toggl_api::types::{Project, Client, ReportRow};
use sea_orm::sea_query::OnConflict;
use sea_orm::{NotSet, Set};
@ -32,7 +32,7 @@ impl ReportRow {
}
}
impl ProjectClient {
impl Client {
pub fn as_model(&self) -> client::ActiveModel {
client::ActiveModel {
id: Set(self.id),

View File

@ -1,6 +1,6 @@
use crate::toggl_api::TogglApiClient;
use crate::entity::{client, project};
use crate::toggl_api::types::{Project, ProjectClient, TogglQuery};
use crate::toggl_api::types::{Project, Client, TogglReportQuery};
use sea_orm::{DatabaseConnection, EntityTrait, QuerySelect};
use tracing::instrument;
use crate::utils;
@ -42,7 +42,7 @@ pub async fn perform_poll(
.to_string();
let report = client
.full_report(&TogglQuery {
.full_report(&TogglReportQuery {
start_date: Some(today_string.clone()),
end_date: Some(today_string.clone()),
..Default::default()
@ -64,8 +64,8 @@ pub async fn perform_poll(
if new_projects {
let clients = client.fetch_clients().await?;
client::Entity::insert_many(clients.iter().map(ProjectClient::as_model))
.on_conflict(ProjectClient::grafting_conflict_statement())
client::Entity::insert_many(clients.iter().map(Client::as_model))
.on_conflict(Client::grafting_conflict_statement())
.exec(db)
.await?;

View File

@ -12,7 +12,7 @@ use chrono::{NaiveDate};
use serde::Deserialize;
use crate::entity::time_entry::{Entity as TimeEntry};
use crate::toggl_api::TogglApiClient;
use crate::toggl_api::types::{Current, Project, ProjectClient, ReportRow, TogglQuery};
use crate::toggl_api::types::{self, Project, Client, ReportRow, TogglReportQuery};
use crate::{entity, utils};
use crate::entity::time_entry;
@ -20,7 +20,7 @@ use crate::entity::time_entry;
pub async fn report(
Extension(toggl_client): Extension<TogglApiClient>,
Extension(db): Extension<DatabaseConnection>,
Json(query): Json<TogglQuery>,
Json(query): Json<TogglReportQuery>,
) -> utils::Result<Json<Vec<ReportRow>>> {
let report = toggl_client.full_report(&query).await?;
debug!("Returned results: {:?}", report);
@ -73,7 +73,7 @@ pub async fn cache_report(
#[instrument(skip(toggl_client))]
pub async fn current(
Extension(toggl_client): Extension<TogglApiClient>,
) -> utils::Result<Json<Option<Current>>> {
) -> utils::Result<Json<Option<types::TimeEntry>>> {
Ok(toggl_client.fetch_current_time_entry().await.map(Json)?)
}
@ -106,10 +106,10 @@ pub async fn projects(
pub async fn clients(
Extension(db): Extension<DatabaseConnection>,
Extension(toggl_client): Extension<TogglApiClient>,
) -> utils::Result<Json<Vec<ProjectClient>>> {
) -> utils::Result<Json<Vec<Client>>> {
let clients = toggl_client.fetch_clients().await?;
entity::client::Entity::insert_many(clients.iter().map(ProjectClient::as_model))
.on_conflict(ProjectClient::grafting_conflict_statement())
entity::client::Entity::insert_many(clients.iter().map(Client::as_model))
.on_conflict(Client::grafting_conflict_statement())
.exec(&db)
.await?;
@ -161,7 +161,7 @@ pub async fn refresh(
let start_date_query_string = start_date.unwrap_or(end_date_query_string.clone());
let start_date = NaiveDate::parse_from_str(&start_date_query_string, "%Y-%m-%d")?;
let query = TogglQuery {
let query = TogglReportQuery {
start_date: Some(start_date_query_string),
end_date: Some(end_date_query_string),
..Default::default()

View File

@ -10,7 +10,7 @@ use hyper::HeaderMap;
use reqwest::header::HeaderValue;
use tracing::instrument;
use tracing::log::debug;
use crate::toggl_api::types::{Current, Project, ProjectClient, ReportRow, TogglQuery};
use crate::toggl_api::types::{TimeEntry, Project, Client as ProjectClient, ReportRow, TogglReportQuery};
#[derive(Debug, Clone)]
pub struct TogglApiClient {
@ -100,7 +100,7 @@ impl TogglApiClient {
Ok(clients)
}
pub async fn fetch_current_time_entry(&self) -> crate::Result<Option<Current>> {
pub async fn fetch_current_time_entry(&self) -> crate::Result<Option<TimeEntry>> {
let url = format!(
"{base_url}/me/time_entries/current",
base_url = self.base_url
@ -110,14 +110,14 @@ impl TogglApiClient {
.client
.get(url))
.await?
.json::<Option<Current>>()
.json::<Option<TimeEntry>>()
.await?;
Ok(res)
}
fn paginate_filters(original_filters: &TogglQuery, last_row_id: u64) -> TogglQuery {
let mut filters: TogglQuery = original_filters.clone();
fn paginate_filters(original_filters: &TogglReportQuery, last_row_id: u64) -> TogglReportQuery {
let mut filters: TogglReportQuery = original_filters.clone();
filters.first_row_number = Some(last_row_id + 1);
filters
}
@ -125,7 +125,7 @@ impl TogglApiClient {
#[instrument(skip(self, filters))]
pub async fn full_report(
&self,
filters: &TogglQuery,
filters: &TogglReportQuery,
) -> anyhow::Result<Vec<ReportRow>> {
let url = format!(
"{base_url}/workspace/{workspace_id}/search/time_entries",

View File

@ -30,19 +30,28 @@ pub struct ReportRowInnerTimeEntry {
pub at: String,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Current {
pub id: u64,
pub workspace_id: u64,
pub project_id: Option<u64>,
pub task_id: Option<u64>,
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TimeEntry {
pub id: i64,
pub workspace_id: i64,
pub project_id: Option<i64>,
pub task_id: Option<Value>,
pub billable: bool,
pub start: String,
pub stop: Option<String>,
pub duration: i64,
pub description: String,
pub tags: Vec<String>,
pub tag_ids: Vec<u64>,
pub tag_ids: Vec<i64>,
pub at: String,
pub server_deleted_at: Option<String>,
pub user_id: i64,
// Ignored fields
// duronly: bool,
// uid: i64,
// wid: i64,
// pid: Option<i64>,
}
#[derive(Debug, Serialize, Deserialize)]
@ -59,7 +68,7 @@ pub struct Project {
/// Represents a client in Toggl.
#[derive(Debug, Serialize, Deserialize)]
pub struct ProjectClient {
pub struct Client {
/// Indicates whether the client is archived or not.
pub archived: bool,
@ -81,7 +90,7 @@ pub struct ProjectClient {
#[skip_serializing_none]
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct TogglQuery {
pub struct TogglReportQuery {
pub billable: Option<bool>,
pub client_ids: Option<Vec<u64>>,
pub description: Option<String>,
@ -115,7 +124,7 @@ pub struct TogglQuery {
use std::fmt;
impl fmt::Debug for TogglQuery {
impl fmt::Debug for TogglReportQuery {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut ds = f.debug_struct("TogglQuery");