Skip to content

Commit

Permalink
Add types to troi controller
Browse files Browse the repository at this point in the history
  • Loading branch information
malte-laukoetter committed Dec 7, 2023
1 parent 3321e6a commit 38432a2
Show file tree
Hide file tree
Showing 10 changed files with 405 additions and 156 deletions.
2 changes: 1 addition & 1 deletion .talismanrc
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ fileignoreconfig:
- filename: app/routes/login.tsx
checksum: 71439f7a400334caeb550ee897753dec4b8d36ded11952b3b81594b745aaa18b
- filename: app/components/troi.client.tsx
checksum: b0e396226c9c6ae3c27ff4f4c1157ecff06e5140b44662ef4264559ec9e33a18
checksum: aab99fc3f4f2284848510075ccfc612122cb572eb56f2e531d78ce42613f52e7
- filename: app/routes/projects.tsx
checksum: 68dde5f568d7d4a01c207d5bc6fb95976b1bfe469ad7614ad71241fce8820130
version: ""
Expand Down
2 changes: 1 addition & 1 deletion app/components/troi.client.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect } from "react";

import TroiController from "../troiController";
import TroiController from "../troi/troiController";
import TroiApiService from "troi-library";

interface Props {
Expand Down
164 changes: 124 additions & 40 deletions app/troiController.js → app/troi/troiController.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,69 @@
import TimeEntryCache, { convertToCacheFormat } from "./utils/TimeEntryCache";
import TimeEntryCache, { convertToCacheFormat } from "../utils/TimeEntryCache";
import {
addDaysToDate,
formatDateToYYYYMMDD,
getWeekDaysFor,
} from "./utils/dateUtils";
import { transformCalendarEvent } from "./utils/transformCalendarEvents";
} from "../utils/dateUtils";
import type { TransformedCalendarEvent } from "../utils/transformCalendarEvents";
import { transformCalendarEvent } from "../utils/transformCalendarEvents";
import type { TimeEntry } from "troi-library";
import type TroiApiService from "troi-library";

const timeEntryCache = new TimeEntryCache();

const intervallInWeeks = 6;
const intervallInDays = intervallInWeeks * 7;

type Project = {
name: string;
id: number;
subproject: number;
};

class TroiApiNotInitializedError extends Error {
constructor(message?: string, options?: ErrorOptions) {
super(message ?? "TroiAPI not initialized", options);
}
}

export default class TroiController {
async init(troiApi, willStartLoadingCallback, finishedLoadingCallback) {
private _troiApi?: TroiApiService;
private _startLoadingCallback?: () => unknown;
private _stopLoadingCallback?: () => unknown;
private currentWeek = getWeekDaysFor(new Date());
private _cacheBottomBorder: Date = addDaysToDate(
this.currentWeek[0],
-intervallInDays,
);
private _cacheTopBorder: Date = addDaysToDate(
this.currentWeek[4],
intervallInDays,
);
private _projects?: Project[];

async init(
troiApi: TroiApiService,
willStartLoadingCallback: () => unknown,
finishedLoadingCallback: () => unknown,
) {
this._troiApi = troiApi;
this._startLoadingCallback = willStartLoadingCallback;
this._stopLoadingCallback = finishedLoadingCallback;

const currentWeek = getWeekDaysFor(new Date());
this._cacheBottomBorder = addDaysToDate(currentWeek[0], -intervallInDays);
this._cacheTopBorder = addDaysToDate(currentWeek[4], intervallInDays);

this._projects = await this._troiApi
.makeRequest({
url: "/calculationPositions",
params: {
clientId: this._troiApi.getClientId(),
favoritesOnly: true,
clientId: (await this._troiApi.getClientId()).toString(),
favoritesOnly: true.toString(),
},
})
.then((response) =>
response.map((obj) => {
(response as any).map((obj: unknown) => {
return {
name: obj.DisplayPath,
id: obj.Id,
subproject: obj.Subproject.id,
name: (obj as any).DisplayPath,
id: (obj as any).Id,
subproject: (obj as any).Subproject.id,
};
}),
);
Expand All @@ -50,29 +79,37 @@ export default class TroiController {
// TODO: remove
// quick fix when clientId or employeeId is undefined
_verifyTroiApiCredentials() {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}

if (
this._troiApi.clientId == undefined ||
this._troiApi.employeeId == undefined
) {
console.log(
"clientId:",
this._troiApi.clientId,
this._troiApi?.clientId,
"employeeId:",
this._troiApi.employeeId,
this._troiApi?.employeeId,
);
alert("An error in Troi occured, please reload track-your-time!");
return false;
}
return true;
}

async _loadEntriesBetween(startDate, endDate) {
async _loadEntriesBetween(startDate: Date, endDate: Date) {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}

// TODO: remove quick fix
if (!this._verifyTroiApiCredentials) {
return;
}

for (const project of this._projects) {
for (const project of this._projects ?? []) {
console.log(
"employeeId",
this._troiApi.employeeId,
Expand All @@ -89,7 +126,11 @@ export default class TroiController {
}
}

async _loadCalendarEventsBetween(startDate, endDate) {
async _loadCalendarEventsBetween(startDate: Date, endDate: Date) {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}

// TODO: remove quick fix
if (!this._verifyTroiApiCredentials) {
return;
Expand All @@ -111,7 +152,11 @@ export default class TroiController {
});
}

async _loadEntriesAndEventsBetween(startDate, endDate) {
async _loadEntriesAndEventsBetween(startDate: Date, endDate: Date) {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}

// might be quick fix for not loading time entries if employeeId is undefined
if (this._troiApi.employeeId == undefined) {
return;
Expand All @@ -121,10 +166,13 @@ export default class TroiController {
await this._loadCalendarEventsBetween(startDate, endDate);

this._cacheBottomBorder = new Date(
Math.min(new Date(this._cacheBottomBorder), startDate),
Math.min(
new Date(this._cacheBottomBorder).getDate(),
startDate.getDate(),
),
);
this._cacheTopBorder = new Date(
Math.max(new Date(this._cacheTopBorder), endDate),
Math.max(new Date(this._cacheTopBorder).getDate(), endDate.getDate()),
);
}

Expand All @@ -134,8 +182,11 @@ export default class TroiController {
return this._projects;
}

getTimesAndEventsFor(week) {
let timesAndEventsOfWeek = [];
getTimesAndEventsFor(week: Date[]) {
let timesAndEventsOfWeek: {
hours: number;
events: TransformedCalendarEvent[];
}[] = [];

week.forEach((date) => {
timesAndEventsOfWeek.push({
Expand All @@ -147,50 +198,63 @@ export default class TroiController {
return timesAndEventsOfWeek;
}

getEventsFor(date) {
getEventsFor(date: Date) {
return timeEntryCache.getEventsFor(date);
}

// CRUD Functions for entries

// CRUD Functions for entries

async getEntriesFor(date) {
async getEntriesFor(date: Date) {
if (date > this._cacheTopBorder) {
this._startLoadingCallback();
this._startLoadingCallback?.();
const fetchStartDate = getWeekDaysFor(date)[0];
const fetchEndDate = addDaysToDate(fetchStartDate, intervallInDays - 3);

await this._loadEntriesAndEventsBetween(fetchStartDate, fetchEndDate);
this._stopLoadingCallback();
this._stopLoadingCallback?.();
}

if (date < this._cacheBottomBorder) {
this._startLoadingCallback();
this._startLoadingCallback?.();
const fetchEndDate = getWeekDaysFor(date)[4];
const fetchStartDate = addDaysToDate(fetchEndDate, -intervallInDays + 3);

await this._loadEntriesAndEventsBetween(fetchStartDate, fetchEndDate);
this._stopLoadingCallback();
this._stopLoadingCallback?.();
}

return timeEntryCache.getEntriesFor(date);
}

async addEntry(date, project, hours, description, successCallback) {
async addEntry(
date: Date,
project: Project,
hours: number,
description: string,
successCallback: () => unknown,
) {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}
// TODO: remove quick fix
if (!this._verifyTroiApiCredentials) {
return;
}
const troiFormattedSelectedDate = convertToCacheFormat(date);
const result = await this._troiApi.postTimeEntry(
const result = (await this._troiApi.postTimeEntry(
project.id,
troiFormattedSelectedDate,
hours,
description,
);
)) as {
Name: string;
Quantity: string;
Id: number;
};

const entry = {
const entry: TimeEntry = {
date: troiFormattedSelectedDate,
description: result.Name,
hours: Number(result.Quantity),
Expand All @@ -200,31 +264,51 @@ export default class TroiController {
timeEntryCache.addEntry(project, entry, successCallback);
}

async deleteEntry(entry, projectId, successCallback) {
async deleteEntry(
entry: TimeEntry,
projectId: number,
successCallback: () => unknown,
) {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}
// TODO: remove quick fix
if (!this._verifyTroiApiCredentials) {
return;
}
let result = await this._troiApi.deleteTimeEntryViaServerSideProxy(
let result = (await this._troiApi.deleteTimeEntryViaServerSideProxy(
entry.id,
);
)) as {
ok: boolean;
};
if (result.ok) {
timeEntryCache.deleteEntry(entry, projectId, successCallback);
}
}

async updateEntry(project, entry, successCallback) {
async updateEntry(
project: Project,
entry: TimeEntry,
successCallback: () => unknown,
) {
if (this._troiApi === undefined) {
throw new TroiApiNotInitializedError();
}
// TODO: remove quick fix
if (!this._verifyTroiApiCredentials) {
return;
}
const result = await this._troiApi.updateTimeEntry(
const result = (await this._troiApi.updateTimeEntry(
project.id,
entry.date,
entry.hours,
entry.description,
entry.id,
);
)) as {
Name: string;
Quantity: string;
Id: number;
};

const updatedEntry = {
date: entry.date,
Expand Down
Loading

0 comments on commit 38432a2

Please sign in to comment.