Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🏗️🗃️ UnifiedDataLoader rewrite #1064

Merged
Merged
Show file tree
Hide file tree
Changes from 27 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
83a4939
Removed stale code
the-bay-kay Oct 12, 2023
2963e12
Rewrote unifiedDataLoader into typscript functions
the-bay-kay Oct 12, 2023
36cfff6
Improved TS, generalized getUnifiedData
the-bay-kay Oct 13, 2023
b7abd98
Generalized combinePromises, improved TS
the-bay-kay Oct 13, 2023
e6abae8
Added `types` directory, updated TS
the-bay-kay Oct 19, 2023
1674d46
Added first unifiedDataLoader test
the-bay-kay Oct 20, 2023
8d765d0
Added rudimentary type interfaces for server data
the-bay-kay Oct 20, 2023
0bb95b2
Added types for `/diary/` services!
the-bay-kay Oct 20, 2023
49e1757
Added types for `controlHelper.ts`
the-bay-kay Oct 20, 2023
7dd8ffb
Added tests for combinedPromises
the-bay-kay Oct 24, 2023
1907966
Updated tests, formatted test file using Prettier
the-bay-kay Oct 24, 2023
46c1429
Code format changes to unifiedDataLoader.ts
the-bay-kay Oct 24, 2023
f0da5ea
Updated Object Types
the-bay-kay Oct 26, 2023
3ddf403
Moved services to separate directory
the-bay-kay Oct 27, 2023
ff447d7
Merge branch 'service_rewrite_2023' of https://github.com/e-mission/e…
the-bay-kay Oct 30, 2023
651e983
Ran prettier on serverData, added notes on types
the-bay-kay Oct 30, 2023
772f508
Fixed PromiseResolution checks
the-bay-kay Oct 30, 2023
aa34ac3
Added tests for promise rejection
the-bay-kay Oct 31, 2023
2e5a61e
Ran unifiedDataLoader files through Prettier
the-bay-kay Oct 31, 2023
30c534c
Cleaned out `www/img/` directory
the-bay-kay Oct 31, 2023
9ee44ae
Merge branch 'service_rewrite_2023' into UnifiedDataLoader-rewrite
the-bay-kay Nov 2, 2023
2dc232f
Merge branch 'service_rewrite_2023' into type_interfaces
the-bay-kay Nov 2, 2023
9cf629e
Updated type appearances with prettier
the-bay-kay Nov 2, 2023
063f5b9
Merge branch 'type_interfaces' into UnifiedDataLoader-rewrite
the-bay-kay Nov 2, 2023
8a5ce8b
updated files with prettier
the-bay-kay Nov 2, 2023
0e2448c
Minor fix to index.html, changed by prettier
the-bay-kay Nov 3, 2023
d9285d3
Ran `prettier` on remaining files
the-bay-kay Nov 3, 2023
59503e6
Update www/js/services/unifiedDataLoader.ts
the-bay-kay Nov 6, 2023
9a9cd92
Removed old UnifiedDataLoader
the-bay-kay Nov 6, 2023
2a04319
Merge gitHub change to local repo
the-bay-kay Nov 6, 2023
000f08d
Refactored combinedPromises
the-bay-kay Nov 6, 2023
71bee6f
Prettier cleanup
the-bay-kay Nov 6, 2023
bafdb47
Update www/js/services/unifiedDataLoader.ts
the-bay-kay Nov 7, 2023
99534bf
Merge branch 'service_rewrite_2023' into UnifiedDataLoader-rewrite
shankari Nov 10, 2023
808ab2e
Merge branch 'service_rewrite_2023' into UnifiedDataLoader-rewrite
the-bay-kay Nov 10, 2023
25f7adf
Ran Prettier after merge
the-bay-kay Nov 10, 2023
fa95f97
Fixed imports
the-bay-kay Nov 10, 2023
c2bb442
Merge branch 'service_rewrite_2023' into UnifiedDataLoader-rewrite
the-bay-kay Nov 10, 2023
7e8f07b
Merge cleanup
the-bay-kay Nov 11, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion www/__tests__/commHelper.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { mockLogger } from '../__mocks__/globalMocks';
import { fetchUrlCached } from '../js/commHelper';
import { fetchUrlCached } from '../js/services/commHelper';

mockLogger();

Expand Down
157 changes: 157 additions & 0 deletions www/__tests__/unifiedDataLoader.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import { mockLogger } from '../__mocks__/globalMocks';
import { combineWithDedup, combinedPromises } from '../js/services/unifiedDataLoader';
import { ServerData } from '../js/types/serverData';

mockLogger();

const testOne: ServerData<any> = {
data: '',
metadata: {
key: '',
platform: '',
write_ts: 1, // the only value checked by combineWithDedup
time_zone: '',
write_fmt_time: '',
write_local_dt: null,
},
};

const testTwo = JSON.parse(JSON.stringify(testOne));
testTwo.metadata.write_ts = 2;
const testThree = JSON.parse(JSON.stringify(testOne));
testThree.metadata.write_ts = 3;
const testFour = JSON.parse(JSON.stringify(testOne));
testFour.metadata.write_ts = 4;

describe('combineWithDedup can', () => {
it('work with empty arrays', () => {
expect(combineWithDedup([], [])).toEqual([]);
expect(combineWithDedup([], [testOne])).toEqual([testOne]);
expect(combineWithDedup([testOne, testTwo], [])).toEqual([testOne, testTwo]);
});
it('work with arrays of len 1', () => {
expect(combineWithDedup([testOne], [testOne])).toEqual([testOne]);
expect(combineWithDedup([testOne], [testTwo])).toEqual([testOne, testTwo]);
});
it('work with arrays of len > 1', () => {
expect(combineWithDedup([testOne], [testOne, testTwo])).toEqual([testOne, testTwo]);
expect(combineWithDedup([testOne], [testTwo, testTwo])).toEqual([testOne, testTwo]);
expect(combineWithDedup([testOne, testTwo], [testTwo, testTwo])).toEqual([testOne, testTwo]);
expect(combineWithDedup([testOne, testTwo, testThree], [testOne, testTwo])).toEqual([
testOne,
testTwo,
testThree,
]);
});
});

// combinedPromises tests
const promiseGenerator = (values: Array<ServerData<any>>) => {
return Promise.resolve(values);
};
const badPromiseGenerator = (input: string) => {
return Promise.reject(input);
};

it('throws an error on an empty input', async () => {
expect(() => {
combinedPromises([], combineWithDedup);
}).toThrow();
});

it('catches when all promises fails', async () => {
expect(combinedPromises([badPromiseGenerator('')], combineWithDedup)).rejects.toEqual(['']);
expect(
combinedPromises(
[badPromiseGenerator('bad'), badPromiseGenerator('promise')],
combineWithDedup,
),
).rejects.toEqual(['bad', 'promise']);
expect(
combinedPromises(
[badPromiseGenerator('very'), badPromiseGenerator('bad'), badPromiseGenerator('promise')],
combineWithDedup,
),
).rejects.toEqual(['very', 'bad', 'promise']);

expect(
combinedPromises([badPromiseGenerator('bad'), promiseGenerator([testOne])], combineWithDedup),
).resolves.toEqual([testOne]);
expect(
combinedPromises([promiseGenerator([testOne]), badPromiseGenerator('bad')], combineWithDedup),
).resolves.toEqual([testOne]);
});

it('work with arrays of len 1', async () => {
const promiseArrayOne = [promiseGenerator([testOne])];
const promiseArrayTwo = [promiseGenerator([testOne, testTwo])];
const testResultOne = await combinedPromises(promiseArrayOne, combineWithDedup);
const testResultTwo = await combinedPromises(promiseArrayTwo, combineWithDedup);

expect(testResultOne).toEqual([testOne]);
expect(testResultTwo).toEqual([testOne, testTwo]);
});

it('works with arrays of len 2', async () => {
const promiseArrayOne = [promiseGenerator([testOne]), promiseGenerator([testTwo])];
const promiseArrayTwo = [promiseGenerator([testOne, testTwo]), promiseGenerator([testThree])];
const promiseArrayThree = [promiseGenerator([testOne]), promiseGenerator([testTwo, testThree])];
const promiseArrayFour = [
promiseGenerator([testOne, testTwo]),
promiseGenerator([testThree, testFour]),
];
const promiseArrayFive = [
promiseGenerator([testOne, testTwo]),
promiseGenerator([testTwo, testThree]),
];

const testResultOne = await combinedPromises(promiseArrayOne, combineWithDedup);
const testResultTwo = await combinedPromises(promiseArrayTwo, combineWithDedup);
const testResultThree = await combinedPromises(promiseArrayThree, combineWithDedup);
const testResultFour = await combinedPromises(promiseArrayFour, combineWithDedup);
const testResultFive = await combinedPromises(promiseArrayFive, combineWithDedup);

expect(testResultOne).toEqual([testOne, testTwo]);
expect(testResultTwo).toEqual([testOne, testTwo, testThree]);
expect(testResultThree).toEqual([testOne, testTwo, testThree]);
expect(testResultFour).toEqual([testOne, testTwo, testThree, testFour]);
expect(testResultFive).toEqual([testOne, testTwo, testThree]);
});

it('works with arrays of len >= 2', async () => {
const promiseArrayOne = [
promiseGenerator([testOne]),
promiseGenerator([testTwo]),
promiseGenerator([testThree]),
];
const promiseArrayTwo = [
promiseGenerator([testOne]),
promiseGenerator([testTwo]),
promiseGenerator([testTwo]),
];
const promiseArrayThree = [
promiseGenerator([testOne]),
promiseGenerator([testTwo]),
promiseGenerator([testThree, testFour]),
];
const promiseArrayFour = [
promiseGenerator([testOne]),
promiseGenerator([testTwo, testThree]),
promiseGenerator([testFour]),
];

const testResultOne = await combinedPromises(promiseArrayOne, combineWithDedup);
const testResultTwo = await combinedPromises(promiseArrayTwo, combineWithDedup);
const testResultThree = await combinedPromises(promiseArrayThree, combineWithDedup);
const testResultFour = await combinedPromises(promiseArrayFour, combineWithDedup);

expect(testResultOne).toEqual([testOne, testTwo, testThree]);
expect(testResultTwo).toEqual([testOne, testTwo]);
expect(testResultThree).toEqual([testOne, testTwo, testThree, testFour]);
expect(testResultFour).toEqual([testOne, testTwo, testThree, testFour]);
});

/*
TO-DO: Once getRawEnteries can be tested via end-to-end testing, we will be able to
test getUnifiedDataForInterval as well.
*/
Binary file removed www/img/adam.jpg
Binary file not shown.
Binary file removed www/img/avatar_1.png
Binary file not shown.
Binary file removed www/img/banana.png
Binary file not shown.
Binary file removed www/img/ben.png
Binary file not shown.
Binary file removed www/img/cookie.png
Binary file not shown.
Binary file removed www/img/ic_header_gem.png
Binary file not shown.
Binary file removed www/img/ic_header_gold.png
Binary file not shown.
Binary file removed www/img/ic_header_healer.png
Binary file not shown.
Binary file removed www/img/ic_header_mage.png
Binary file not shown.
Binary file removed www/img/ic_header_rogue.png
Binary file not shown.
Binary file removed www/img/ic_header_silver.png
Binary file not shown.
Binary file removed www/img/ic_header_warrior.png
Binary file not shown.
Binary file removed www/img/ic_navigation_black_24dp.png
Binary file not shown.
Binary file removed www/img/icecream.png
Binary file not shown.
Binary file removed www/img/intro/splash_screen_logo.png
Binary file not shown.
Binary file removed www/img/ionic.png
Binary file not shown.
Binary file removed www/img/max.png
Binary file not shown.
Binary file removed www/img/mike.png
Binary file not shown.
Binary file removed www/img/minus.gif
Binary file not shown.
Binary file removed www/img/nileredsea_126b5740_small.png
Binary file not shown.
Binary file removed www/img/pacman.gif
Binary file not shown.
Binary file removed www/img/perry.png
Binary file not shown.
Binary file removed www/img/plus.gif
Binary file not shown.
16 changes: 6 additions & 10 deletions www/index.html
Original file line number Diff line number Diff line change
@@ -1,22 +1,18 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta
name="viewport"
content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no, width=device-width, viewport-fit=cover" />
<meta
http-equiv="Content-Security-Policy"
content="default-src 'self' data: gap: https://ssl.gstatic.com https://api.ionicjs.com https://pro-deploy.ionicjs.com https://nominatim.openstreetmap.org https://raw.githubusercontent.com emission: 'unsafe-eval'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' https://tile.openstreetmap.org 'unsafe-inline' data: 'unsafe-eval'" />
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no, width=device-width, viewport-fit=cover">
<meta http-equiv="Content-Security-Policy" content="default-src 'self' data: gap: https://ssl.gstatic.com https://api.ionicjs.com https://pro-deploy.ionicjs.com https://nominatim.openstreetmap.org https://raw.githubusercontent.com emission: 'unsafe-eval'; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' https://tile.openstreetmap.org 'unsafe-inline' data: 'unsafe-eval'">
<title></title>

<!-- cordova script (this will be a 404 in the browser) -->
<script type="text/javascript" src="cordova.js"></script>
</head>

<body ng-app="emission">
<!-- <ion-nav-view></ion-nav-view> -->
<div id="appRoot" class="fill-container" style="width: 100vw; height: 100vh"></div>
<div id="appRoot" class="fill-container" style="width: 100vw; height: 100vh;"></div>
</body>
<script src="dist/bundle.js"></script>
</html>
3 changes: 1 addition & 2 deletions www/js/config/dynamicConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import i18next from 'i18next';
import { displayError, logDebug, logWarn } from '../plugin/logger';
import { getAngularService } from '../angular-react-helper';
import { fetchUrlCached } from '../commHelper';
import { fetchUrlCached } from '../services/commHelper';
import { storageClear, storageGet, storageSet } from '../plugin/storage';

export const CONFIG_PHONE_UI = 'config/app_ui_config';
Expand Down
2 changes: 1 addition & 1 deletion www/js/control/ControlSyncHelper.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import SettingRow from './SettingRow';
import AlertBar from './AlertBar';
import moment from 'moment';
import { addStatEvent, statKeys } from '../plugin/clientStats';
import { updateUser } from '../commHelper';
import { updateUser } from '../services/commHelper';

/*
* BEGIN: Simple read/write wrappers
Expand Down
27 changes: 1 addition & 26 deletions www/js/controllers.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,29 +87,4 @@ angular
);
console.log('SplashCtrl invoke finished');
},
)

.controller('ChatsCtrl', function ($scope, Chats) {
// With the new view caching in Ionic, Controllers are only called
// when they are recreated or on app start, instead of every page change.
// To listen for when this page is active (for example, to refresh data),
// listen for the $ionicView.enter event:
//
//$scope.$on('$ionicView.enter', function(e) {
//});

$scope.chats = Chats.all();
$scope.remove = function (chat) {
Chats.remove(chat);
};
})

.controller('ChatDetailCtrl', function ($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})

.controller('AccountCtrl', function ($scope) {
$scope.settings = {
enableFriends: true,
};
});
);
2 changes: 1 addition & 1 deletion www/js/diary/LabelTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import { SurveyOptions } from '../survey/survey';
import { getLabelOptions } from '../survey/multilabel/confirmHelper';
import { displayError } from '../plugin/logger';
import { useTheme } from 'react-native-paper';
import { getPipelineRangeTs } from '../commHelper';
import { getPipelineRangeTs } from '../services/commHelper';

let labelPopulateFactory, labelsResultMap, notesResultMap, showPlaces;
const ONE_DAY = 24 * 60 * 60; // seconds
Expand Down
4 changes: 2 additions & 2 deletions www/js/diary/services.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
'use strict';

import angular from 'angular';
import { getBaseModeByKey, getBaseModeOfLabeledTrip } from './diaryHelper';
import { SurveyOptions } from '../survey/survey';
import { getConfig } from '../config/dynamicConfig';
import { getRawEntries } from '../commHelper';
import { getRawEntries } from '../services/commHelper';
import { getUnifiedDataForInterval } from '../services/unifiedDataLoader';

angular
.module('emission.main.diary.services', ['emission.plugin.logger', 'emission.services'])
Expand Down
11 changes: 5 additions & 6 deletions www/js/diary/timelineHelper.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import moment from 'moment';
import { getAngularService } from '../angular-react-helper';
import { displayError, logDebug } from '../plugin/logger';
import { getBaseModeByKey, getBaseModeOfLabeledTrip } from './diaryHelper';
import { getUnifiedDataForInterval } from '../services/unifiedDataLoader';
import i18next from 'i18next';

const cachedGeojsons = new Map();
Expand Down Expand Up @@ -154,15 +154,14 @@ export function getLocalUnprocessedInputs(pipelineRange, labelsFactory, notesFac
* @returns Promise an array with 1) results for labels and 2) results for notes
*/
export function getAllUnprocessedInputs(pipelineRange, labelsFactory, notesFactory) {
const UnifiedDataLoader = getAngularService('UnifiedDataLoader');
const tq = getUnprocessedInputQuery(pipelineRange);
const getMethod = window['cordova'].plugins.BEMUserCache.getMessagesForInterval;

const labelsPromises = labelsFactory.MANUAL_KEYS.map((key) =>
UnifiedDataLoader.getUnifiedMessagesForInterval(key, tq, true).then(
labelsFactory.extractResult,
),
getUnifiedDataForInterval(key, tq, getMethod).then(labelsFactory.extractResult),
);
const notesPromises = notesFactory.MANUAL_KEYS.map((key) =>
UnifiedDataLoader.getUnifiedMessagesForInterval(key, tq, true).then(notesFactory.extractResult),
getUnifiedDataForInterval(key, tq, getMethod).then(notesFactory.extractResult),
);
return getUnprocessedResults(labelsFactory, notesFactory, labelsPromises, notesPromises);
}
Expand Down
2 changes: 1 addition & 1 deletion www/js/metrics/MetricsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import Carousel from '../components/Carousel';
import DailyActiveMinutesCard from './DailyActiveMinutesCard';
import CarbonTextCard from './CarbonTextCard';
import ActiveMinutesTableCard from './ActiveMinutesTableCard';
import { getAggregateData, getMetrics } from '../commHelper';
import { getAggregateData, getMetrics } from '../services/commHelper';

export const METRIC_LIST = ['duration', 'mean_speed', 'count', 'distance'] as const;

Expand Down
3 changes: 1 addition & 2 deletions www/js/onboarding/SaveQrPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,13 @@ import { View, StyleSheet } from 'react-native';
import { ActivityIndicator, Button, Surface, Text } from 'react-native-paper';
import { registerUserDone, setRegisterUserDone, setSaveQrDone } from './onboardingHelper';
import { AppContext } from '../App';
import { getAngularService } from '../angular-react-helper';
import { displayError, logDebug } from '../plugin/logger';
import { useTranslation } from 'react-i18next';
import QrCode, { shareQR } from '../components/QrCode';
import { onboardingStyles } from './OnboardingStack';
import { preloadDemoSurveyResponse } from './SurveyPage';
import { storageSet } from '../plugin/storage';
import { registerUser } from '../commHelper';
import { registerUser } from '../services/commHelper';
import { resetDataAndRefresh } from '../config/dynamicConfig';
import { markConsented } from '../splash/startprefs';
import i18next from 'i18next';
Expand Down
Loading
Loading