Skip to content

Commit

Permalink
Update personio extension
Browse files Browse the repository at this point in the history
- Merge pull request raycast#26 from marcjulianschwarz/25-attendance-month-bug
- fix bug by caching individual attendance combinations
- cache values (raycast#24)
- add month selection for attendances command
  • Loading branch information
Boosteblume committed Apr 9, 2024
1 parent bea2bdd commit db6b3ba
Show file tree
Hide file tree
Showing 9 changed files with 394 additions and 206 deletions.
198 changes: 0 additions & 198 deletions extensions/personio/src/api.tsx

This file was deleted.

87 changes: 87 additions & 0 deletions extensions/personio/src/api/api.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import axios from "axios";
import { getPreferenceValues, popToRoot, showHUD, showToast, Toast } from "@raycast/api";
import { cache } from "./cache";

export const BASE_URL = "https://api.personio.de/v1";

export async function getTokenFromAPI() {
const url = BASE_URL + "/auth";
const payload = {
client_secret: getPreferenceValues().clientSecret,
client_id: getPreferenceValues().clientId,
};
const headers = {
accept: "application/json",
"content-type": "application/json",
};

const res = await axios.post(url, payload, { headers });
const data = res.data;
const token = data.data.token;

return token;
}

// this function uses the secrets to get a short-lived (one day) token
export async function getPersonioToken(caching = true) {
if (!caching) {
return await getTokenFromAPI();
}

const cacheDataToken = cache.get("personioToken");

if (cacheDataToken) {
return cacheDataToken;
} else {
const token = await getTokenFromAPI();
cache.set("personioToken", token, 23 * 60); // let the token expire after 23 hours
return token;
}
}

export async function addTime(
employeeNumber: number,
date: string,
start_time: string,
end_time: string,
break_time: number,
token: string,
) {
const url = BASE_URL + "/company/attendances";

const payload = {
attendances: [
{
employee: employeeNumber,
date: date,
start_time: start_time,
end_time: end_time,
break: break_time,
},
],
};

const headers = {
accept: "application/json",
"content-type": "application/json",
authorization: "Bearer " + token,
};

try {
axios.post(url, payload, { headers });
await showHUD("Time Tracked 🎉");
popToRoot();
} catch (error) {
if (axios.isAxiosError(error) && error.stack) {
if (error.stack.includes("IncomingMessage.handleStreamEnd")) {
console.log("Caught the specific error: IncomingMessage.handleStreamEnd");
await showToast({ style: Toast.Style.Failure, title: "That didn't work!" });
} else {
// Handle other errors
console.log("Some other Axios error occurred", error);
}
} else {
console.log("An error occurred that is not an Axios error", error);
}
}
}
106 changes: 106 additions & 0 deletions extensions/personio/src/api/attendances.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { showToast, Toast } from "@raycast/api";
import axios from "axios";
import { cache } from "./cache";
import { BASE_URL } from "./api";

interface AttendancePeriodJSON {
id: number;
type: string;
attributes: {
employee: number;
date: string;
start_time: string;
end_time: string;
break: number;
comment: string;
updated_at: string;
status: string;
project: number;
is_holiday: boolean;
is_on_time_off: boolean;
};
}

export interface AttendancePeriod {
id: number;
employee: number;
date: string;
start_time: string;
end_time: string;
break: number;
comment: string;
updated_at: string;
status: string;
project: number;
is_holiday: boolean;
is_on_time_off: boolean;
}

function daysInMonth(year: number, month: number) {
return new Date(year, month, 0).getDate();
}

export async function getAttendancesAPI(
employeeNumber: number,
token: string,
currentYear: string,
selectedMonth: string,
): Promise<AttendancePeriod[]> {
const maxDays = daysInMonth(parseInt(currentYear), parseInt(selectedMonth));

const url =
BASE_URL +
"/company/attendances?employees[]=" +
employeeNumber +
`&start_date=${currentYear}-${selectedMonth}-01&end_date=${currentYear}-${selectedMonth}-${maxDays}&includePending=true`;
const headers = {
accept: "application/json",
authorization: "Bearer " + token,
};

try {
const res = await axios.get(url, { headers });
const data = res.data.data as AttendancePeriodJSON[];
const attendances = data.map((a) => ({
id: a.id,
employee: a.attributes.employee,
date: a.attributes.date,
start_time: a.attributes.start_time,
end_time: a.attributes.end_time,
break: a.attributes.break,
comment: a.attributes.comment,
updated_at: a.attributes.updated_at,
status: a.attributes.status,
project: a.attributes.project,
is_holiday: a.attributes.is_holiday,
is_on_time_off: a.attributes.is_on_time_off,
}));
await showToast({
title: "Loaded Attendances",
message: `${attendances.length} Attendances in 2024 loaded successfully!`,
});
return attendances;
} catch (error) {
await showToast({ style: Toast.Style.Failure, title: "That didn't work!", message: "Unfortunate!" });
console.error(error);
return [];
}
}

export async function getAttendances(
employeeNumber: number,
token: string,
currentYear: string,
selectedMonth: string,
) {
const key = employeeNumber.toString() + currentYear + selectedMonth;
const attendances = cache.get(key);

if (attendances) {
return JSON.parse(attendances) as AttendancePeriod[];
} else {
const attendances = await getAttendancesAPI(employeeNumber, token, currentYear, selectedMonth);
cache.set(key, JSON.stringify(attendances), 23 * 60);
return attendances;
}
}
Loading

0 comments on commit db6b3ba

Please sign in to comment.