diff --git a/src/js/src/app.ts b/src/js/src/app.ts index 58eb40b..b7e709d 100644 --- a/src/js/src/app.ts +++ b/src/js/src/app.ts @@ -17,7 +17,10 @@ $SD.onConnected(() => { store.patchState({ [StateKey.globalSettings]: settings, }); - KimaiApi.config(settings.backendProviderConfig["kimai"]); + // Initial settings are undefined + if (settings?.backendProviderConfig?.["kimai"]) { + KimaiApi.config(settings.backendProviderConfig["kimai"]); + } } ); }); diff --git a/src/js/src/lib/action/tracker-action.ts b/src/js/src/lib/action/tracker-action.ts index 8cd55cf..e7b5b47 100644 --- a/src/js/src/lib/action/tracker-action.ts +++ b/src/js/src/lib/action/tracker-action.ts @@ -48,11 +48,9 @@ export function initTrackerAction(store: Store) { }); async function getApi() { - const { - backendProviderConfig: { - ["kimai"]: { url, user, token }, - }, - } = await store.once(StateKey.globalSettings); - return KimaiApi.config({ url, user, token }).get(); + const globalSettings = await store.once(StateKey.globalSettings); + const apiConfig = + globalSettings?.backendProviderConfig?.["kimai"] ?? KimaiApi.emptyConfig; + return KimaiApi.config(apiConfig).get(); } } diff --git a/src/js/src/lib/api/kimai-api-tracker-connector.ts b/src/js/src/lib/api/kimai-api-tracker-connector.ts index 49efe13..225309e 100644 --- a/src/js/src/lib/api/kimai-api-tracker-connector.ts +++ b/src/js/src/lib/api/kimai-api-tracker-connector.ts @@ -55,11 +55,19 @@ export class KimaiApiTrackerConnector implements ApiTrackerConnector { } async onRequestWorkedToday() { - this.#tracker.workedToday = await this.getWorkedToday({ - projectId: this.settings(this.#tracker)!.projectId, - activityId: this.settings(this.#tracker)!.activityId, - }); - this.#tracker.render(); + const projectId = this.settings(this.#tracker)?.projectId; + const activityId = this.settings(this.#tracker)?.activityId; + if (projectId && activityId) { + try { + this.#tracker.workedToday = await this.getWorkedToday({ + projectId, + activityId, + }); + this.#tracker.render(); + } catch (e) { + /* empty */ + } + } } connect(tracker: Tracker) { diff --git a/src/js/src/lib/api/kimai-api.ts b/src/js/src/lib/api/kimai-api.ts index b83d4d7..1530b43 100644 --- a/src/js/src/lib/api/kimai-api.ts +++ b/src/js/src/lib/api/kimai-api.ts @@ -17,8 +17,14 @@ type ApiConfig = { export class KimaiApi { static instance: KimaiApi | null = null; + static emptyConfig = { + url: "", + user: "", + token: "", + }; + static config(c: ApiConfig) { - KimaiApi.get().config = c; + KimaiApi.get().config = c ?? KimaiApi.emptyConfig; return KimaiApi; } @@ -62,10 +68,23 @@ export class KimaiApi { } as RequestInit; // eslint-disable-line } + assertValidConfig() { + if (!this.#user) { + throw new Error("Invalid config. User must not be empty."); + } + if (!this.#baseUrl) { + throw new Error("Invalid config. BaseUrl must not be empty."); + } + if (!this.#token) { + throw new Error("Invalid config. Token must not be empty."); + } + } + async startTracking({ projectId, activityId, }: KimaiBackendProviderPluginConfig): Promise> { + this.assertValidConfig(); const url = `${this.#baseUrl}api/timesheets`; const body = { begin: format(new Date(), "yyyy-MM-dd'T'HH:mm:ss"), @@ -82,6 +101,7 @@ export class KimaiApi { } async stopTracking(id: number) { + this.assertValidConfig(); const url = `${this.#baseUrl}api/timesheets/${id}/stop`; const options = { ...this.fetchOptions, @@ -91,11 +111,13 @@ export class KimaiApi { } async getProjects() { + this.assertValidConfig(); const url = `${this.#baseUrl}api/projects`; return tryFetch(url, this.fetchOptions); } async getActivities(projectId: number) { + this.assertValidConfig(); const params = new URLSearchParams({ project: String(projectId), }); @@ -107,6 +129,7 @@ export class KimaiApi { projectId: number, activityId: number ): Promise> { + this.assertValidConfig(); if (!projectId || !activityId) { return { success: false,