From a1e6c9284dd0f56c173a9b778c552ae1f452324e Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:48:59 +0100 Subject: [PATCH 1/9] Rename EmissionsRepository to CalculationsRepository, EmissionsData to CalculationData --- .../CalculationsRepository.ts} | 15 ++++---- .../calculations/ICalculationsRepository.ts | 34 +++++++++++++++++++ .../TestCalculationsRepository.ts | 20 +++++++++++ src/data/emissions/IEmissionsRepository.ts | 32 ----------------- src/data/emissions/TestEmissionsRepository.ts | 17 ---------- src/usePopup.ts | 6 ++-- 6 files changed, 66 insertions(+), 58 deletions(-) rename src/data/{emissions/EmissionsRepository.ts => calculations/CalculationsRepository.ts} (64%) create mode 100644 src/data/calculations/ICalculationsRepository.ts create mode 100644 src/data/calculations/TestCalculationsRepository.ts delete mode 100644 src/data/emissions/IEmissionsRepository.ts delete mode 100644 src/data/emissions/TestEmissionsRepository.ts diff --git a/src/data/emissions/EmissionsRepository.ts b/src/data/calculations/CalculationsRepository.ts similarity index 64% rename from src/data/emissions/EmissionsRepository.ts rename to src/data/calculations/CalculationsRepository.ts index 6df39efd..3ae2162e 100644 --- a/src/data/emissions/EmissionsRepository.ts +++ b/src/data/calculations/CalculationsRepository.ts @@ -1,10 +1,13 @@ import { IStorageRepository } from "../storage/IStorageRepository"; -import { EmissionsData, IEmissionsRepository } from "./IEmissionsRepository"; +import { + CalculationData, + ICalculationsRepository, +} from "./ICalculationsRepository"; -export class EmissionsRepository implements IEmissionsRepository { +export class CalculationsRepository implements ICalculationsRepository { remoteDataSource: IStorageRepository = IStorageRepository.instance; - async storeLastCalculation(emissionsData: EmissionsData): Promise { + async storeLastCalculation(emissionsData: CalculationData): Promise { try { await this.remoteDataSource.set({ lastCalculation: JSON.stringify(emissionsData), @@ -14,10 +17,10 @@ export class EmissionsRepository implements IEmissionsRepository { } } - async getLastCalculation(): Promise { + async getLastCalculation(): Promise { try { const data = await this.remoteDataSource.get({ - lastCalculation: JSON.stringify({ + lastCalculation: JSON.stringify({ bytes: 0, emissions: 0, specificEmissions: 0, @@ -26,7 +29,7 @@ export class EmissionsRepository implements IEmissionsRepository { return JSON.parse( data["lastCalculation"] as string - ) as EmissionsData; + ) as CalculationData; } catch (e: unknown) { throw Error(e as string); } diff --git a/src/data/calculations/ICalculationsRepository.ts b/src/data/calculations/ICalculationsRepository.ts new file mode 100644 index 00000000..535fd108 --- /dev/null +++ b/src/data/calculations/ICalculationsRepository.ts @@ -0,0 +1,34 @@ +import { CalculationsRepository } from "./CalculationsRepository"; +import { TestCalculationsRepository } from "./TestCalculationsRepository"; + +export abstract class ICalculationsRepository { + private static _instance: ICalculationsRepository; + static get instance(): ICalculationsRepository { + if (!this._instance) { + switch (process.env.ENV) { + case "development": + this._instance = new CalculationsRepository(); + break; + case "test": + this._instance = new TestCalculationsRepository(); + break; + default: + throw new Error(`Unknown environment: ${process.env.ENV}`); + } + } + + return this._instance; + } + + abstract storeLastCalculation( + emissionsData: CalculationData + ): Promise; + + abstract getLastCalculation(): Promise; +} + +export type CalculationData = { + bytes: number; + emissions: number; + specificEmissions: number; +}; diff --git a/src/data/calculations/TestCalculationsRepository.ts b/src/data/calculations/TestCalculationsRepository.ts new file mode 100644 index 00000000..12ee052a --- /dev/null +++ b/src/data/calculations/TestCalculationsRepository.ts @@ -0,0 +1,20 @@ +import { + CalculationData, + ICalculationsRepository, +} from "./ICalculationsRepository"; + +export class TestCalculationsRepository implements ICalculationsRepository { + private _lastCalculation: CalculationData = { + bytes: 0, + emissions: 0, + specificEmissions: 0, + }; + + async storeLastCalculation(emissionsData: CalculationData): Promise { + this._lastCalculation = emissionsData; + } + + async getLastCalculation(): Promise { + return this._lastCalculation; + } +} diff --git a/src/data/emissions/IEmissionsRepository.ts b/src/data/emissions/IEmissionsRepository.ts deleted file mode 100644 index 78641133..00000000 --- a/src/data/emissions/IEmissionsRepository.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { EmissionsRepository } from "./EmissionsRepository"; -import { TestEmissionsRepository } from "./TestEmissionsRepository"; - -export abstract class IEmissionsRepository { - private static _instance: IEmissionsRepository; - static get instance(): IEmissionsRepository { - if (!this._instance) { - switch (process.env.ENV) { - case "development": - this._instance = new EmissionsRepository(); - break; - case "test": - this._instance = new TestEmissionsRepository(); - break; - default: - throw new Error(`Unknown environment: ${process.env.ENV}`); - } - } - - return this._instance; - } - - abstract storeLastCalculation(emissionsData: EmissionsData): Promise; - - abstract getLastCalculation(): Promise; -} - -export type EmissionsData = { - bytes: number; - emissions: number; - specificEmissions: number; -}; diff --git a/src/data/emissions/TestEmissionsRepository.ts b/src/data/emissions/TestEmissionsRepository.ts deleted file mode 100644 index dcdaf823..00000000 --- a/src/data/emissions/TestEmissionsRepository.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { EmissionsData, IEmissionsRepository } from "./IEmissionsRepository"; - -export class TestEmissionsRepository implements IEmissionsRepository { - private _lastCalculation: EmissionsData = { - bytes: 0, - emissions: 0, - specificEmissions: 0, - }; - - async storeLastCalculation(emissionsData: EmissionsData): Promise { - this._lastCalculation = emissionsData; - } - - async getLastCalculation(): Promise { - return this._lastCalculation; - } -} diff --git a/src/usePopup.ts b/src/usePopup.ts index f0b87bec..88c5d3f7 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -4,14 +4,14 @@ import { calculateAverageSpecificEmissionsHelper } from "./helpers/calculateAver import { calculateCarbon } from "./helpers/calculateCarbon"; import { ISelectedCountriesRepository } from "./data/selected_countries/ISelectedCountriesRepository"; import { useMountEffect } from "./helpers/useOnceAfterFirstMount"; -import { IEmissionsRepository } from "./data/emissions/IEmissionsRepository"; +import { ICalculationsRepository } from "./data/calculations/ICalculationsRepository"; import { IBytesRepository } from "./data/bytes/IBytesRepository"; export const usePopup = () => { const selectedCountriesRepository: ISelectedCountriesRepository = ISelectedCountriesRepository.instance; - const emissionsRepository: IEmissionsRepository = - IEmissionsRepository.instance; + const emissionsRepository: ICalculationsRepository = + ICalculationsRepository.instance; const bytesRepository: IBytesRepository = IBytesRepository.instance; const [totalBytesTransferred, settotalBytesTransferred] = useState(0); From 0cc145912d23df7223975e3170003904fab8ed12 Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 10:55:39 +0100 Subject: [PATCH 2/9] Add selectedCountries to CalculationData --- src/data/calculations/ICalculationsRepository.ts | 2 ++ src/data/calculations/TestCalculationsRepository.ts | 2 ++ src/usePopup.ts | 1 + 3 files changed, 5 insertions(+) diff --git a/src/data/calculations/ICalculationsRepository.ts b/src/data/calculations/ICalculationsRepository.ts index 535fd108..aa3b01a4 100644 --- a/src/data/calculations/ICalculationsRepository.ts +++ b/src/data/calculations/ICalculationsRepository.ts @@ -1,3 +1,4 @@ +import { CountryName } from "../../constants/Countries"; import { CalculationsRepository } from "./CalculationsRepository"; import { TestCalculationsRepository } from "./TestCalculationsRepository"; @@ -31,4 +32,5 @@ export type CalculationData = { bytes: number; emissions: number; specificEmissions: number; + selectedCountries: Map; }; diff --git a/src/data/calculations/TestCalculationsRepository.ts b/src/data/calculations/TestCalculationsRepository.ts index 12ee052a..27cc2101 100644 --- a/src/data/calculations/TestCalculationsRepository.ts +++ b/src/data/calculations/TestCalculationsRepository.ts @@ -1,3 +1,4 @@ +import { CountryName } from "../../constants/Countries"; import { CalculationData, ICalculationsRepository, @@ -8,6 +9,7 @@ export class TestCalculationsRepository implements ICalculationsRepository { bytes: 0, emissions: 0, specificEmissions: 0, + selectedCountries: new Map(), }; async storeLastCalculation(emissionsData: CalculationData): Promise { diff --git a/src/usePopup.ts b/src/usePopup.ts index 88c5d3f7..464ede60 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -146,6 +146,7 @@ export const usePopup = () => { bytes: changes.totalBytesTransferred.newValue, emissions: _emissions, specificEmissions: averageSpecificEmissions, + selectedCountries: selectedCountries, }); } }; From 026c9bbe66dc0ce1cc0d277c0da18e7517ae1a49 Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:23:58 +0100 Subject: [PATCH 3/9] Implement CalculationsRepository to store and retrieve array of CalculationData --- .../calculations/CalculationsRepository.ts | 28 +++++++++++++------ .../calculations/ICalculationsRepository.ts | 4 ++- .../TestCalculationsRepository.ts | 17 ++++++----- src/usePopup.ts | 7 +++-- 4 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/data/calculations/CalculationsRepository.ts b/src/data/calculations/CalculationsRepository.ts index 3ae2162e..3320adf3 100644 --- a/src/data/calculations/CalculationsRepository.ts +++ b/src/data/calculations/CalculationsRepository.ts @@ -9,27 +9,37 @@ export class CalculationsRepository implements ICalculationsRepository { async storeLastCalculation(emissionsData: CalculationData): Promise { try { + const oldCalculations = await this.getAllCalculations(); + const newCalculations = [emissionsData, ...oldCalculations]; await this.remoteDataSource.set({ - lastCalculation: JSON.stringify(emissionsData), + allCalculations: JSON.stringify(newCalculations), }); } catch (e: unknown) { throw Error(e as string); } } - async getLastCalculation(): Promise { + async getAllCalculations(): Promise { try { const data = await this.remoteDataSource.get({ - lastCalculation: JSON.stringify({ - bytes: 0, - emissions: 0, - specificEmissions: 0, - }), + allCalculations: JSON.stringify([]), }); return JSON.parse( - data["lastCalculation"] as string - ) as CalculationData; + data["allCalculations"] as string + ) as CalculationData[]; + } catch (e: unknown) { + throw Error(e as string); + } + } + + async getLastCalculation(): Promise { + try { + const oldCalculations = await this.getAllCalculations(); + if (oldCalculations.length > 0) { + return oldCalculations[0]; + } + return undefined; } catch (e: unknown) { throw Error(e as string); } diff --git a/src/data/calculations/ICalculationsRepository.ts b/src/data/calculations/ICalculationsRepository.ts index aa3b01a4..f920291e 100644 --- a/src/data/calculations/ICalculationsRepository.ts +++ b/src/data/calculations/ICalculationsRepository.ts @@ -25,7 +25,9 @@ export abstract class ICalculationsRepository { emissionsData: CalculationData ): Promise; - abstract getLastCalculation(): Promise; + abstract getLastCalculation(): Promise; + + abstract getAllCalculations(): Promise; } export type CalculationData = { diff --git a/src/data/calculations/TestCalculationsRepository.ts b/src/data/calculations/TestCalculationsRepository.ts index 27cc2101..37f0c61d 100644 --- a/src/data/calculations/TestCalculationsRepository.ts +++ b/src/data/calculations/TestCalculationsRepository.ts @@ -1,22 +1,21 @@ -import { CountryName } from "../../constants/Countries"; import { CalculationData, ICalculationsRepository, } from "./ICalculationsRepository"; export class TestCalculationsRepository implements ICalculationsRepository { - private _lastCalculation: CalculationData = { - bytes: 0, - emissions: 0, - specificEmissions: 0, - selectedCountries: new Map(), - }; + private _allCalculations: CalculationData[] = []; async storeLastCalculation(emissionsData: CalculationData): Promise { - this._lastCalculation = emissionsData; + const tempArray = [emissionsData, ...this._allCalculations]; + this._allCalculations = tempArray; + } + + async getAllCalculations(): Promise { + return this._allCalculations; } async getLastCalculation(): Promise { - return this._lastCalculation; + return this._allCalculations[0]; } } diff --git a/src/usePopup.ts b/src/usePopup.ts index 464ede60..f8ec1ea4 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -169,11 +169,12 @@ export const usePopup = () => { setSelectedCountries(newMap); }); }); + useMountEffect(() => { emissionsRepository.getLastCalculation().then((emissionsData) => { - settotalBytesTransferred(emissionsData.bytes); - setEmissions(emissionsData.emissions); - setAverageSpecificEmissions(emissionsData.specificEmissions); + settotalBytesTransferred(emissionsData?.bytes ?? 0); + setEmissions(emissionsData?.emissions ?? 0); + setAverageSpecificEmissions(emissionsData?.specificEmissions ?? 0); }); }); From 40c524d65ffc25a0b56fd412216a1133463c3745 Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 11:25:45 +0100 Subject: [PATCH 4/9] Rename storeLastCalculation as storeCalculation, emissionsData arg to calculationData --- src/data/calculations/CalculationsRepository.ts | 4 ++-- src/data/calculations/ICalculationsRepository.ts | 4 +--- src/data/calculations/TestCalculationsRepository.ts | 4 ++-- src/usePopup.ts | 12 +++++++----- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/data/calculations/CalculationsRepository.ts b/src/data/calculations/CalculationsRepository.ts index 3320adf3..5bca5e9c 100644 --- a/src/data/calculations/CalculationsRepository.ts +++ b/src/data/calculations/CalculationsRepository.ts @@ -7,10 +7,10 @@ import { export class CalculationsRepository implements ICalculationsRepository { remoteDataSource: IStorageRepository = IStorageRepository.instance; - async storeLastCalculation(emissionsData: CalculationData): Promise { + async storeCalculation(calculationData: CalculationData): Promise { try { const oldCalculations = await this.getAllCalculations(); - const newCalculations = [emissionsData, ...oldCalculations]; + const newCalculations = [calculationData, ...oldCalculations]; await this.remoteDataSource.set({ allCalculations: JSON.stringify(newCalculations), }); diff --git a/src/data/calculations/ICalculationsRepository.ts b/src/data/calculations/ICalculationsRepository.ts index f920291e..e3930f2a 100644 --- a/src/data/calculations/ICalculationsRepository.ts +++ b/src/data/calculations/ICalculationsRepository.ts @@ -21,9 +21,7 @@ export abstract class ICalculationsRepository { return this._instance; } - abstract storeLastCalculation( - emissionsData: CalculationData - ): Promise; + abstract storeCalculation(calculationData: CalculationData): Promise; abstract getLastCalculation(): Promise; diff --git a/src/data/calculations/TestCalculationsRepository.ts b/src/data/calculations/TestCalculationsRepository.ts index 37f0c61d..f0f4cef8 100644 --- a/src/data/calculations/TestCalculationsRepository.ts +++ b/src/data/calculations/TestCalculationsRepository.ts @@ -6,8 +6,8 @@ import { export class TestCalculationsRepository implements ICalculationsRepository { private _allCalculations: CalculationData[] = []; - async storeLastCalculation(emissionsData: CalculationData): Promise { - const tempArray = [emissionsData, ...this._allCalculations]; + async storeCalculation(calculationData: CalculationData): Promise { + const tempArray = [calculationData, ...this._allCalculations]; this._allCalculations = tempArray; } diff --git a/src/usePopup.ts b/src/usePopup.ts index f8ec1ea4..7f4101d8 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -142,7 +142,7 @@ export const usePopup = () => { selectedCountries ); setEmissions(_emissions); - emissionsRepository.storeLastCalculation({ + emissionsRepository.storeCalculation({ bytes: changes.totalBytesTransferred.newValue, emissions: _emissions, specificEmissions: averageSpecificEmissions, @@ -171,10 +171,12 @@ export const usePopup = () => { }); useMountEffect(() => { - emissionsRepository.getLastCalculation().then((emissionsData) => { - settotalBytesTransferred(emissionsData?.bytes ?? 0); - setEmissions(emissionsData?.emissions ?? 0); - setAverageSpecificEmissions(emissionsData?.specificEmissions ?? 0); + emissionsRepository.getLastCalculation().then((calculationData) => { + settotalBytesTransferred(calculationData?.bytes ?? 0); + setEmissions(calculationData?.emissions ?? 0); + setAverageSpecificEmissions( + calculationData?.specificEmissions ?? 0 + ); }); }); From 1a686f77340fd11095f5615211c9c9afd30d94db Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:11:19 +0100 Subject: [PATCH 5/9] Added cacheOngoingCalculation so that ongoing calculations are cached even if extension is closed. Calculations only stored when stop calculation is clicked Rename emissionsRepository to calculationsRepository --- .../calculations/CalculationsRepository.ts | 49 ++++++++++++++++++- .../calculations/ICalculationsRepository.ts | 8 ++- .../TestCalculationsRepository.ts | 21 +++++++- src/data/storage/IStorageRepository.ts | 2 +- src/usePopup.ts | 15 ++++-- 5 files changed, 85 insertions(+), 10 deletions(-) diff --git a/src/data/calculations/CalculationsRepository.ts b/src/data/calculations/CalculationsRepository.ts index 5bca5e9c..d62e717e 100644 --- a/src/data/calculations/CalculationsRepository.ts +++ b/src/data/calculations/CalculationsRepository.ts @@ -19,6 +19,28 @@ export class CalculationsRepository implements ICalculationsRepository { } } + async cacheOngoingCalculation( + calculationData: CalculationData + ): Promise { + try { + await this.remoteDataSource.set({ + ongoingCalculation: JSON.stringify(calculationData), + }); + } catch (e: unknown) { + throw Error(e as string); + } + } + + async clearOngoingCalculation(): Promise { + try { + await this.remoteDataSource.set({ + ongoingCalculation: null, + }); + } catch (e: unknown) { + throw Error(e as string); + } + } + async getAllCalculations(): Promise { try { const data = await this.remoteDataSource.get({ @@ -33,13 +55,36 @@ export class CalculationsRepository implements ICalculationsRepository { } } - async getLastCalculation(): Promise { + async _getOngoingCalculation(): Promise { try { + const data = await this.remoteDataSource.get({ + ongoingCalculation: null, + }); + console.log("data", data); + if (data["ongoingCalculation"] !== null) { + return JSON.parse( + data["ongoingCalculation"] as string + ) as CalculationData; + } + return null; + } catch (e: unknown) { + throw Error(e as string); + } + } + + async getLastCalculation(): Promise { + try { + const ongoingCalculation = await this._getOngoingCalculation(); + if (ongoingCalculation !== null) { + console.log("ongoingCalculation", ongoingCalculation); + return ongoingCalculation; + } const oldCalculations = await this.getAllCalculations(); if (oldCalculations.length > 0) { + console.log("oldCalculations", oldCalculations); return oldCalculations[0]; } - return undefined; + return null; } catch (e: unknown) { throw Error(e as string); } diff --git a/src/data/calculations/ICalculationsRepository.ts b/src/data/calculations/ICalculationsRepository.ts index e3930f2a..678c07ae 100644 --- a/src/data/calculations/ICalculationsRepository.ts +++ b/src/data/calculations/ICalculationsRepository.ts @@ -23,7 +23,13 @@ export abstract class ICalculationsRepository { abstract storeCalculation(calculationData: CalculationData): Promise; - abstract getLastCalculation(): Promise; + abstract cacheOngoingCalculation( + calculationData: CalculationData + ): Promise; + + abstract clearOngoingCalculation(): Promise; + + abstract getLastCalculation(): Promise; abstract getAllCalculations(): Promise; } diff --git a/src/data/calculations/TestCalculationsRepository.ts b/src/data/calculations/TestCalculationsRepository.ts index f0f4cef8..b085f2bc 100644 --- a/src/data/calculations/TestCalculationsRepository.ts +++ b/src/data/calculations/TestCalculationsRepository.ts @@ -5,17 +5,34 @@ import { export class TestCalculationsRepository implements ICalculationsRepository { private _allCalculations: CalculationData[] = []; + private _ongoingCalculation: CalculationData | null = null; async storeCalculation(calculationData: CalculationData): Promise { const tempArray = [calculationData, ...this._allCalculations]; this._allCalculations = tempArray; } + async cacheOngoingCalculation( + calculationData: CalculationData + ): Promise { + this._ongoingCalculation = calculationData; + } + + async clearOngoingCalculation(): Promise { + this._ongoingCalculation = null; + } + async getAllCalculations(): Promise { return this._allCalculations; } - async getLastCalculation(): Promise { - return this._allCalculations[0]; + async getLastCalculation(): Promise { + if (this._ongoingCalculation !== null) { + return this._ongoingCalculation; + } + if (this._allCalculations.length > 0) { + return this._allCalculations[0]; + } + return null; } } diff --git a/src/data/storage/IStorageRepository.ts b/src/data/storage/IStorageRepository.ts index f95dd0f9..4f8757f9 100644 --- a/src/data/storage/IStorageRepository.ts +++ b/src/data/storage/IStorageRepository.ts @@ -1,7 +1,7 @@ import { StorageRepository } from "./StorageRepository"; import { TestStorageRepository } from "./TestStorageRepository"; -export type StorageDataType = string | number; +export type StorageDataType = string | number | null; export abstract class IStorageRepository { private static _instance: IStorageRepository; static get instance(): IStorageRepository { diff --git a/src/usePopup.ts b/src/usePopup.ts index 7f4101d8..c6b6ae14 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -10,7 +10,7 @@ import { IBytesRepository } from "./data/bytes/IBytesRepository"; export const usePopup = () => { const selectedCountriesRepository: ISelectedCountriesRepository = ISelectedCountriesRepository.instance; - const emissionsRepository: ICalculationsRepository = + const calculationsRepository: ICalculationsRepository = ICalculationsRepository.instance; const bytesRepository: IBytesRepository = IBytesRepository.instance; @@ -113,6 +113,13 @@ export const usePopup = () => { } } }); + calculationsRepository.storeCalculation({ + bytes: totalBytesTransferred, + emissions: emissions, + specificEmissions: averageSpecificEmissions, + selectedCountries: selectedCountries, + }); + calculationsRepository.clearOngoingCalculation(); }; const addSelectedCountry = async (country: CountryName) => { @@ -142,7 +149,7 @@ export const usePopup = () => { selectedCountries ); setEmissions(_emissions); - emissionsRepository.storeCalculation({ + calculationsRepository.cacheOngoingCalculation({ bytes: changes.totalBytesTransferred.newValue, emissions: _emissions, specificEmissions: averageSpecificEmissions, @@ -160,7 +167,7 @@ export const usePopup = () => { totalBytesTransferredListener ); }; - }, [selectedCountries, averageSpecificEmissions, emissionsRepository]); + }, [selectedCountries, averageSpecificEmissions, calculationsRepository]); useMountEffect(() => { selectedCountriesRepository @@ -171,7 +178,7 @@ export const usePopup = () => { }); useMountEffect(() => { - emissionsRepository.getLastCalculation().then((calculationData) => { + calculationsRepository.getLastCalculation().then((calculationData) => { settotalBytesTransferred(calculationData?.bytes ?? 0); setEmissions(calculationData?.emissions ?? 0); setAverageSpecificEmissions( From 56d3e77102a30b62227ef8217a14894b87b4b8d2 Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:30:37 +0100 Subject: [PATCH 6/9] Add UI to render calculation history, and button to refresh history --- .../CalculationHistory.tsx | 37 +++++++++++++++++++ src/popup.tsx | 7 ++++ src/usePopup.ts | 16 +++++++- 3 files changed, 59 insertions(+), 1 deletion(-) create mode 100644 src/components/calculation-history/CalculationHistory.tsx diff --git a/src/components/calculation-history/CalculationHistory.tsx b/src/components/calculation-history/CalculationHistory.tsx new file mode 100644 index 00000000..398698de --- /dev/null +++ b/src/components/calculation-history/CalculationHistory.tsx @@ -0,0 +1,37 @@ +import React from "react"; +import { CalculationData } from "../../data/calculations/ICalculationsRepository"; +type CountryDropdownType = { + refreshCalculationHistory: () => void; + calculationHistory: CalculationData[]; +}; +export const CalculationHistory = ({ + refreshCalculationHistory, + calculationHistory, +}: CountryDropdownType) => { + return ( +
+ +
    + {calculationHistory.map((calculation, index) => ( +
  • +

    Bytes: {calculation.bytes}

    +

    Emissions: {calculation.emissions}

    +

    + Specific Emissions: {calculation.specificEmissions} +

    + {/* Render the selected countries */} +
      + {Array.from(calculation.selectedCountries).map( + ([countryName, percentage]) => ( +
    • + {countryName}: {percentage} +
    • + ) + )} +
    +
  • + ))} +
+
+ ); +}; diff --git a/src/popup.tsx b/src/popup.tsx index 92dfed11..c019ff95 100644 --- a/src/popup.tsx +++ b/src/popup.tsx @@ -3,6 +3,7 @@ import { createRoot } from "react-dom/client"; import { CountryDropdown } from "./components/CountryDropdown"; import { usePopup } from "./usePopup"; import { SelectedCountries } from "./components/selected-countries/SelectedCountries"; +import { CalculationHistory } from "./components/calculation-history/CalculationHistory"; export const Popup = () => { const { @@ -15,6 +16,8 @@ export const Popup = () => { averageSpecificEmissions, refreshAndGetSize, stopRecording, + refreshCalculationHistory, + calculationHistory, error, } = usePopup(); @@ -45,6 +48,10 @@ export const Popup = () => { setCountryPercentage={setCountryPercentage} /> + {error &&

{error}

} ); diff --git a/src/usePopup.ts b/src/usePopup.ts index c6b6ae14..11e4c28a 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -4,7 +4,10 @@ import { calculateAverageSpecificEmissionsHelper } from "./helpers/calculateAver import { calculateCarbon } from "./helpers/calculateCarbon"; import { ISelectedCountriesRepository } from "./data/selected_countries/ISelectedCountriesRepository"; import { useMountEffect } from "./helpers/useOnceAfterFirstMount"; -import { ICalculationsRepository } from "./data/calculations/ICalculationsRepository"; +import { + CalculationData, + ICalculationsRepository, +} from "./data/calculations/ICalculationsRepository"; import { IBytesRepository } from "./data/bytes/IBytesRepository"; export const usePopup = () => { @@ -21,6 +24,15 @@ export const usePopup = () => { >(new Map()); const [averageSpecificEmissions, setAverageSpecificEmissions] = useState(0); const [error, setError] = useState(); + const [calculationHistory, setCalculationHistory] = useState< + CalculationData[] + >([]); + + const refreshCalculationHistory = async () => { + const calculationsData = + await calculationsRepository.getAllCalculations(); + setCalculationHistory(calculationsData); + }; const setCountryPercentage = async ( country: CountryName, @@ -197,6 +209,8 @@ export const usePopup = () => { averageSpecificEmissions, refreshAndGetSize, stopRecording, + calculationHistory, + refreshCalculationHistory, error, }; }; From c6fe106dc1c617aef76b5346670516babca9000e Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 12:38:21 +0100 Subject: [PATCH 7/9] Cleanup --- src/components/calculation-history/CalculationHistory.tsx | 1 - src/data/calculations/CalculationsRepository.ts | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/src/components/calculation-history/CalculationHistory.tsx b/src/components/calculation-history/CalculationHistory.tsx index 398698de..adf501a3 100644 --- a/src/components/calculation-history/CalculationHistory.tsx +++ b/src/components/calculation-history/CalculationHistory.tsx @@ -19,7 +19,6 @@ export const CalculationHistory = ({

Specific Emissions: {calculation.specificEmissions}

- {/* Render the selected countries */}
    {Array.from(calculation.selectedCountries).map( ([countryName, percentage]) => ( diff --git a/src/data/calculations/CalculationsRepository.ts b/src/data/calculations/CalculationsRepository.ts index d62e717e..6aee8fcd 100644 --- a/src/data/calculations/CalculationsRepository.ts +++ b/src/data/calculations/CalculationsRepository.ts @@ -60,7 +60,7 @@ export class CalculationsRepository implements ICalculationsRepository { const data = await this.remoteDataSource.get({ ongoingCalculation: null, }); - console.log("data", data); + if (data["ongoingCalculation"] !== null) { return JSON.parse( data["ongoingCalculation"] as string @@ -76,12 +76,10 @@ export class CalculationsRepository implements ICalculationsRepository { try { const ongoingCalculation = await this._getOngoingCalculation(); if (ongoingCalculation !== null) { - console.log("ongoingCalculation", ongoingCalculation); return ongoingCalculation; } const oldCalculations = await this.getAllCalculations(); if (oldCalculations.length > 0) { - console.log("oldCalculations", oldCalculations); return oldCalculations[0]; } return null; From 7b20da3fd89c4b336cf6058cf2e196c6730b87f4 Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 16:46:31 +0100 Subject: [PATCH 8/9] Remove unnecessary try catch in CalculationsRepository since it already exists in StorageRepository, catch in usePopup instead --- .../calculations/CalculationsRepository.ts | 90 +++++++------------ src/usePopup.ts | 20 +++-- 2 files changed, 46 insertions(+), 64 deletions(-) diff --git a/src/data/calculations/CalculationsRepository.ts b/src/data/calculations/CalculationsRepository.ts index 6aee8fcd..2190e2ed 100644 --- a/src/data/calculations/CalculationsRepository.ts +++ b/src/data/calculations/CalculationsRepository.ts @@ -8,83 +8,59 @@ export class CalculationsRepository implements ICalculationsRepository { remoteDataSource: IStorageRepository = IStorageRepository.instance; async storeCalculation(calculationData: CalculationData): Promise { - try { - const oldCalculations = await this.getAllCalculations(); - const newCalculations = [calculationData, ...oldCalculations]; - await this.remoteDataSource.set({ - allCalculations: JSON.stringify(newCalculations), - }); - } catch (e: unknown) { - throw Error(e as string); - } + const oldCalculations = await this.getAllCalculations(); + const newCalculations = [calculationData, ...oldCalculations]; + await this.remoteDataSource.set({ + allCalculations: JSON.stringify(newCalculations), + }); } async cacheOngoingCalculation( calculationData: CalculationData ): Promise { - try { - await this.remoteDataSource.set({ - ongoingCalculation: JSON.stringify(calculationData), - }); - } catch (e: unknown) { - throw Error(e as string); - } + await this.remoteDataSource.set({ + ongoingCalculation: JSON.stringify(calculationData), + }); } async clearOngoingCalculation(): Promise { - try { - await this.remoteDataSource.set({ - ongoingCalculation: null, - }); - } catch (e: unknown) { - throw Error(e as string); - } + await this.remoteDataSource.set({ + ongoingCalculation: null, + }); } async getAllCalculations(): Promise { - try { - const data = await this.remoteDataSource.get({ - allCalculations: JSON.stringify([]), - }); + const data = await this.remoteDataSource.get({ + allCalculations: JSON.stringify([]), + }); - return JSON.parse( - data["allCalculations"] as string - ) as CalculationData[]; - } catch (e: unknown) { - throw Error(e as string); - } + return JSON.parse( + data["allCalculations"] as string + ) as CalculationData[]; } async _getOngoingCalculation(): Promise { - try { - const data = await this.remoteDataSource.get({ - ongoingCalculation: null, - }); + const data = await this.remoteDataSource.get({ + ongoingCalculation: null, + }); - if (data["ongoingCalculation"] !== null) { - return JSON.parse( - data["ongoingCalculation"] as string - ) as CalculationData; - } - return null; - } catch (e: unknown) { - throw Error(e as string); + if (data["ongoingCalculation"] !== null) { + return JSON.parse( + data["ongoingCalculation"] as string + ) as CalculationData; } + return null; } async getLastCalculation(): Promise { - try { - const ongoingCalculation = await this._getOngoingCalculation(); - if (ongoingCalculation !== null) { - return ongoingCalculation; - } - const oldCalculations = await this.getAllCalculations(); - if (oldCalculations.length > 0) { - return oldCalculations[0]; - } - return null; - } catch (e: unknown) { - throw Error(e as string); + const ongoingCalculation = await this._getOngoingCalculation(); + if (ongoingCalculation !== null) { + return ongoingCalculation; + } + const oldCalculations = await this.getAllCalculations(); + if (oldCalculations.length > 0) { + return oldCalculations[0]; } + return null; } } diff --git a/src/usePopup.ts b/src/usePopup.ts index 11e4c28a..c9eeb08e 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -125,13 +125,19 @@ export const usePopup = () => { } } }); - calculationsRepository.storeCalculation({ - bytes: totalBytesTransferred, - emissions: emissions, - specificEmissions: averageSpecificEmissions, - selectedCountries: selectedCountries, - }); - calculationsRepository.clearOngoingCalculation(); + try { + calculationsRepository.storeCalculation({ + bytes: totalBytesTransferred, + emissions: emissions, + specificEmissions: averageSpecificEmissions, + selectedCountries: selectedCountries, + }); + calculationsRepository.clearOngoingCalculation(); + } catch (e: unknown) { + if (e instanceof Error) { + setError(e.message); + } + } }; const addSelectedCountry = async (country: CountryName) => { From 961dfa4c020d2893188cc126836ac9ec32335d04 Mon Sep 17 00:00:00 2001 From: Justin <57725347+juskek@users.noreply.github.com> Date: Thu, 6 Jul 2023 17:15:19 +0100 Subject: [PATCH 9/9] Prevent callback hell in usePopup by using await --- src/usePopup.ts | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/usePopup.ts b/src/usePopup.ts index c9eeb08e..5630426f 100644 --- a/src/usePopup.ts +++ b/src/usePopup.ts @@ -188,21 +188,25 @@ export const usePopup = () => { }, [selectedCountries, averageSpecificEmissions, calculationsRepository]); useMountEffect(() => { - selectedCountriesRepository - .getSelectedCountriesAndPercentages() - .then((newMap) => { - setSelectedCountries(newMap); - }); + const getSelectedCountriesAndSetState = async () => { + const newMap = + await selectedCountriesRepository.getSelectedCountriesAndPercentages(); + setSelectedCountries(newMap); + }; + getSelectedCountriesAndSetState(); }); useMountEffect(() => { - calculationsRepository.getLastCalculation().then((calculationData) => { + const getLastCalculationAndSetState = async () => { + const calculationData = + await calculationsRepository.getLastCalculation(); settotalBytesTransferred(calculationData?.bytes ?? 0); setEmissions(calculationData?.emissions ?? 0); setAverageSpecificEmissions( calculationData?.specificEmissions ?? 0 ); - }); + }; + getLastCalculationAndSetState(); }); return {