Skip to content

Commit

Permalink
Switch to Toggl v9 API and Report v3 API
Browse files Browse the repository at this point in the history
  • Loading branch information
mcndt committed Mar 4, 2023
1 parent 6c153d4 commit ff6a6a1
Show file tree
Hide file tree
Showing 35 changed files with 1,835 additions and 1,393 deletions.
1 change: 1 addition & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-explicit-any": "off",
"no-prototype-builtins": "off",
"@typescript-eslint/no-empty-function": "off",
"import/no-unresolved": "off",
Expand Down
6 changes: 4 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
},
"editor.rulers": [80],
"editor.tabSize": 2,
"editor.detectIndentation": false,
"editor.detectIndentation": true,
"conventionalCommits.scopes": ["reports", "api"],
"editor.definitionLinkOpensInPeek": true
"editor.definitionLinkOpensInPeek": true,
"editor.guides.highlightActiveIndentation": true,
"editor.indentSize": "tabSize"
}
1 change: 0 additions & 1 deletion decs.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
declare module "toggl-client";
declare module "simple-svelte-autocomplete";
declare module "obsidian";
declare module "env";
1 change: 1 addition & 0 deletions lib/model/Project.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/** @deprecated */
export interface Project {
/**
* The name of the project
Expand Down
151 changes: 151 additions & 0 deletions lib/model/Report-v3.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
export type ProjectId = number;
export type UserId = number;
export type TagId = number;
export type ClientId = number;
export type WorkspaceId = number;
export type TimeEntryId = number;
export type RowNumber = number;
export type DateTimeString = string;

export type SearchTimeEntriesResponseItem = {
user_id: UserId;
username: string;
project_id: ProjectId;
task_id: null;
description: string;
tag_ids: string[];
hourly_rate_in_cents: null;
/**
* Contains a single time entry or an array of time entries, if grouped.
*/
time_entries: [SearchTimeEntry, ...SearchTimeEntry[]];
row_number: RowNumber;
};

type SearchTimeEntry = {
at: DateTimeString;
id: TimeEntryId;
seconds: number;
start: DateTimeString;
stop: DateTimeString;
};

export type TimeEntryStart = {
description: string;
project_id: ProjectId;
tag_ids?: TagId[];
tags?: string[];
};

export type TimeEntry = TimeEntryStart & {
at: DateTimeString;
description: string;
duration: number;
id: TimeEntryId;
project_id: ProjectId | null;
server_deleted_at: Date | null;
start: DateTimeString;
stop: Date | null;
tag_ids: TagId[] | null;
tags: string[] | null;
user_id: UserId;
workspace_id: WorkspaceId;
};

export type ProjectsSummaryResponseItem = {
project_id: ProjectId;
tracked_seconds: number;
user_id: UserId;
};

export type ClientsResponseItem = {
id: ClientId;
wid: WorkspaceId;
archived: boolean;
name: string;
at: DateTimeString;
};

export type ProjectsResponseItem = {
id: ProjectId;
workspace_id: WorkspaceId;
client_id: ClientId | null;
name: string;
is_private: boolean;
active: boolean;
at: DateTimeString;
created_at: DateTimeString;
server_deleted_at: Date | null;
color: string;
rate: null;
rate_last_updated: Date | null;
recurring: boolean;
actual_hours: number;
wid: WorkspaceId;
cid: ClientId | null;
};

export type TagsResponseItem = {
id: TagId;
workspace_id: WorkspaceId;
name: string;
at: DateTimeString;
};

export type EnrichedWithProject<
T extends { project_id: ProjectId },
Y extends ProjectsResponseItem = ProjectsResponseItem,
> = T & {
readonly $project?: Y;
};

export type EnrichedWithTags<T extends { tag_ids: TagId[] }> = T & {
readonly $tags?: TagsResponseItem[];
};

export type EnrichedWithClient<T extends { client_id: ClientId }> = T & {
readonly $client?: ClientsResponseItem;
};

export type SummaryReportResponse = {
groups: SummaryReportResponseGroup[];
};

type SummaryReportResponseGroup = {
id: number | null;
sub_groups: SummaryReportResponseSubGroup[];
};

type SummaryReportResponseSubGroup = {
id: null;
title?: string;
seconds: number;
};

export type DetailedReportResponseItem = {
user_id: UserId;
project_id: ProjectId | null;
task_id: null;
description: string;
tag_ids: TagId[];
time_entries: DetailedReportTimeEntry[];
row_number: RowNumber;
};

type DetailedReportTimeEntry = {
id: TimeEntryId;
seconds: number;
start: DateTimeString;
stop: DateTimeString;
at: DateTimeString;
};

export type SummaryTimeChart = {
seconds: number;
graph: GraphItem[];
resolution: "day" | "week" | "month";
};

export type GraphItem = {
seconds: number;
};
6 changes: 6 additions & 0 deletions lib/model/Report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ https://github.com/toggl/toggl_api_docs/blob/master/reports.md#successful-respon
https://github.com/toggl/toggl_api_docs/blob/master/reports/detailed.md#response
*/

/** @deprecated */
export interface Report<T> {
/** total time in milliseconds for the selected report. */
total_grand?: number;
Expand Down Expand Up @@ -32,6 +33,7 @@ export interface Report<T> {

/**
* Object returned by the /reports/api/v2/details endpoint.
* @deprecated
*/
export interface Detailed {
id: any;
Expand All @@ -58,6 +60,7 @@ export interface Detailed {

/**
* Object returned by the /reports/api/v2/summary endpoint
* @deprecated
*/
export interface Summary {
id?: number;
Expand All @@ -67,17 +70,20 @@ export interface Summary {
items?: any[];
}

/** @deprecated */
export interface SummaryTitle {
project: string;
hex_color: string;
client: string;
}

/** @deprecated */
export interface TotalCurrency {
currency?: string;
amount?: number;
}

/** @deprecated */
export interface Error {
/** the general message of the occurred error */
message: string;
Expand Down
1 change: 1 addition & 0 deletions lib/model/Tag.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/**
* @deprecated
* Workspace-associated tag from the Toggl API.
*/
export interface Tag {
Expand Down
13 changes: 10 additions & 3 deletions lib/model/TimeEntry.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Object to request start of new timers.
* @deprecated
*/
export interface TimeEntryStart {
/**
Expand All @@ -9,17 +9,20 @@ export interface TimeEntryStart {
/**
* The id of the project to start the new time entry on
*/
pid: number;
project_id: number;
/**
* a list of tag names (optional)
*/
tags?: string[];
tag_ids?: string[];
}

/**
* Time entry data from the Toggl Track API.
*/

/**
* @deprecated
*/
export interface TimeEntry extends TimeEntryStart {
/**
* time entry id
Expand Down Expand Up @@ -47,4 +50,8 @@ export interface TimeEntry extends TimeEntryStart {
* project color in hex format
*/
project_hex_color?: string;
/**
* Workspace id
*/
workspace_id: number;
}
24 changes: 24 additions & 0 deletions lib/stores/clients.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { ClientsResponseItem } from "lib/model/Report-v3";
import { get, writable } from "svelte/store";

const clients = writable<ClientsResponseItem[]>([]);

export const setClients = clients.set;

export const Clients = { subscribe: clients.subscribe };

export function getClientIds(item: (string | number)[]): number[] {
const clients = get(Clients);

return item
.map((item) => {
if (typeof item === "number") {
return item;
}
const client = clients.find(
(client) => client.name.toLowerCase() === item.toLowerCase(),
);
return client.id ?? null;
})
.filter((id) => id !== null) as number[];
}
41 changes: 41 additions & 0 deletions lib/stores/currentTimer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type {
EnrichedWithProject,
EnrichedWithTags,
TimeEntry,
} from "lib/model/Report-v3";
import { derived, writable } from "svelte/store";

import { Projects } from "./projects";
import { Tags } from "./tags";

const currentTimer = writable<TimeEntry>(null);

export const setCurrentTimer = currentTimer.set;

const enrichedCurrentTimer = derived(
[currentTimer, Projects, Tags],
([$currentTimer, $projects, $tags]): EnrichedWithProject<
EnrichedWithTags<typeof $currentTimer>,
typeof $projects[number]
> => {
if (!$currentTimer) return null;

const project = $projects.find(
(project) => project.id === $currentTimer.project_id,
);

const tags = $currentTimer.tag_ids.map((tagId) =>
$tags.find((tag) => tag.id === tagId),
);

return {
...$currentTimer,
$project: project,
$tags: tags.some((tag) => tag === undefined) ? undefined : tags,
};
},
);

export const CurrentTimer = {
subscribe: enrichedCurrentTimer.subscribe,
};
29 changes: 29 additions & 0 deletions lib/stores/dailySummary.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import type {
EnrichedWithProject,
ProjectsSummaryResponseItem,
} from "lib/model/Report-v3";
import { derived, writable } from "svelte/store";

import { Projects } from "./projects";

const summaryItems = writable<ProjectsSummaryResponseItem[]>([]);

export const setDailySummaryItems = summaryItems.set;

export const DailySummary = derived(
[summaryItems, Projects],
([$summaryItems, $projects]) => {
const summary = {
projects_breakdown: $summaryItems.map(
(item): EnrichedWithProject<typeof item> => ({
...item,
$project:
$projects.find((project) => project.id === item.project_id) ?? null,
}),
),
total_seconds: $summaryItems.reduce((a, b) => a + b.tracked_seconds, 0),
};

return summary;
},
);
Loading

0 comments on commit ff6a6a1

Please sign in to comment.