Skip to content

Commit

Permalink
Merge pull request #1013 from JGreenlee/fix-extra-pipelinerange-requests
Browse files Browse the repository at this point in the history
🐛 Fix extra pipeline range request every time a trip is labeled + handle network error better
  • Loading branch information
shankari authored Aug 15, 2023
2 parents b2d0a21 + 1f824c9 commit 88bd8e1
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 45 deletions.
25 changes: 14 additions & 11 deletions www/js/diary/LabelTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import LabelListScreen from "./LabelListScreen";
import { createStackNavigator } from "@react-navigation/stack";
import LabelScreenDetails from "./LabelDetailsScreen";
import { NavigationContainer } from "@react-navigation/native";
import { compositeTrips2TimelineMap, populateBasicClasses, populateCompositeTrips } from "./timelineHelper";
import { compositeTrips2TimelineMap, getAllUnprocessedInputs, getLocalUnprocessedInputs, populateBasicClasses, populateCompositeTrips } from "./timelineHelper";
import { fillLocationNamesOfTrip, resetNominatimLimiter } from "./addressNamesHelper";

let labelPopulateFactory, labelsResultMap, notesResultMap, showPlaces;
Expand All @@ -41,8 +41,9 @@ const LabelTab = () => {
const $rootScope = getAngularService('$rootScope');
const $state = getAngularService('$state');
const $ionicPopup = getAngularService('$ionicPopup');
const Logger = getAngularService('Logger');
const Timeline = getAngularService('Timeline');
const DiaryHelper = getAngularService('DiaryHelper');
const CommHelper = getAngularService('CommHelper');
const SurveyOptions = getAngularService('SurveyOptions');
const enbs = getAngularService('EnketoNotesButtonService');

Expand Down Expand Up @@ -99,15 +100,17 @@ const LabelTab = () => {
setDisplayedEntries(entriesToDisplay);
}, [timelineMap, filterInputs]);

function loadTimelineEntries() {
Timeline.getUnprocessedLabels(labelPopulateFactory, enbs).then(([pipelineRange, manualResultMap, enbsResultMap]) => {
if (pipelineRange.end_ts) {
labelsResultMap = manualResultMap;
notesResultMap = enbsResultMap;
console.log("After reading in the label controller, manualResultMap " + JSON.stringify(manualResultMap), manualResultMap);
}
async function loadTimelineEntries() {
try {
const pipelineRange = await CommHelper.getPipelineRangeTs();
[labelsResultMap, notesResultMap] = await getAllUnprocessedInputs(pipelineRange, labelPopulateFactory, enbs);
Logger.log("After reading unprocessedInputs, labelsResultMap =" + JSON.stringify(labelsResultMap)
+ "; notesResultMap = " + JSON.stringify(notesResultMap));
setPipelineRange(pipelineRange);
});
} catch (error) {
Logger.displayError("Error while loading pipeline range", error);
setIsLoading(false);
}
}

// once pipelineRange is set, load the most recent week of data
Expand Down Expand Up @@ -232,7 +235,7 @@ const LabelTab = () => {
const timelineMapRef = useRef(timelineMap);
async function repopulateTimelineEntry(oid: string) {
if (!timelineMap.has(oid)) return console.error("Item with oid: " + oid + " not found in timeline");
const [_, newLabels, newNotes] = await Timeline.getUnprocessedLabels(labelPopulateFactory, enbs);
const [newLabels, newNotes] = await getLocalUnprocessedInputs(pipelineRange, labelPopulateFactory, enbs);
const repopTime = new Date().getTime();
const newEntry = {...timelineMap.get(oid), justRepopulated: repopTime};
populateBasicClasses(newEntry);
Expand Down
3 changes: 2 additions & 1 deletion www/js/diary/list/TimelineScrollList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,8 @@ const TimelineScrollList = ({ listEntries, queriedRange, pipelineRange, loadMore
} else if (listEntries && listEntries.length == 0) {
/* Condition: we've loaded all travel and set `listEntries`, but it's empty. Show 'no travel'. */
return noTravelBanner;
} else {
} else if (listEntries) {
/* Condition: we've successfully loaded and set `listEntries`, so show the list */
return (
<FlashList inverted
data={reversedListEntries}
Expand Down
33 changes: 0 additions & 33 deletions www/js/diary/services.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,39 +129,6 @@ angular.module('emission.main.diary.services', ['emission.plugin.logger',
});
});

timeline.getUnprocessedLabels = function(manualFactory, enbs) {
/*
Because with the confirmed trips, all prior labels have been
incorporated into the trip.
*/
return CommHelper.getPipelineRangeTs().then(function(result) {
const pendingLabelQuery = {key: "write_ts",
startTs: result.end_ts - 10,
endTs: moment().unix() + 10
}
var manualPromises = manualFactory.MANUAL_KEYS.map(function(inp_key) {
return UnifiedDataLoader.getUnifiedMessagesForInterval(
inp_key, pendingLabelQuery).then(manualFactory.extractResult);
});
var enbsPromises = enbs.MANUAL_KEYS.map(function(inp_key) {
return UnifiedDataLoader.getUnifiedMessagesForInterval(
inp_key, pendingLabelQuery).then(enbs.extractResult);
});
const manualConfirmResults = {};
const enbsConfirmResults = {};
return Promise.all([...manualPromises, ...enbsPromises]).then((comboResults) => {
const manualResults = comboResults.slice(0, manualPromises.length);
const enbsResults = comboResults.slice(manualPromises.length);
manualFactory.processManualInputs(manualResults, manualConfirmResults);
enbs.processManualInputs(enbsResults, enbsConfirmResults);
return [result, manualConfirmResults, enbsConfirmResults];
});
}).catch((err) => {
Logger.displayError("while reading confirmed trips", err);
return [{}, {}];
});
};

// DB entries retrieved from the server have '_id', 'metadata', and 'data' fields.
// This function returns a shallow copy of the obj, which flattens the
// 'data' field into the top level, while also including '_id' and 'metadata.key'
Expand Down
63 changes: 63 additions & 0 deletions www/js/diary/timelineHelper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import moment from "moment";
import { getAngularService } from "../angular-react-helper";
import { getFormattedDate, getFormattedDateAbbr, getFormattedTimeRange, isMultiDay } from "./diaryHelper";

Expand Down Expand Up @@ -80,3 +81,65 @@ export function populateCompositeTrips(ctList, showPlaces, labelsFactory, labels
notesFactory.populateInputsAndInferences(ct, notesResultMap);
});
}

const getUnprocessedInputQuery = (pipelineRange) => ({
key: "write_ts",
startTs: pipelineRange.end_ts - 10,
endTs: moment().unix() + 10
});

function getUnprocessedResults(labelsFactory, notesFactory, labelsPromises, notesPromises) {
return Promise.all([...labelsPromises, ...notesPromises]).then((comboResults) => {
const labelsConfirmResults = {};
const notesConfirmResults = {};
const labelResults = comboResults.slice(0, labelsPromises.length);
const notesResults = comboResults.slice(labelsPromises.length);
labelsFactory.processManualInputs(labelResults, labelsConfirmResults);
notesFactory.processManualInputs(notesResults, notesConfirmResults);
return [labelsConfirmResults, notesConfirmResults];
});
}

/**
* @description Gets unprocessed inputs (labels or Enketo responses) that were recorded after the given
* pipeline range and have not yet been pushed to the server.
* @param pipelineRange an object with start_ts and end_ts representing the range of time
* for which travel data has been processed through the pipeline on the server
* @param labelsFactory the Angular factory for processing labels (MultilabelService or
* EnketoTripButtonService)
* @param notesFactory the Angular factory for processing notes (EnketoNotesButtonService)
* @returns Promise an array with 1) results for labels and 2) results for notes
*/
export function getLocalUnprocessedInputs(pipelineRange, labelsFactory, notesFactory) {
const BEMUserCache = window['cordova'].plugins.BEMUserCache;
const tq = getUnprocessedInputQuery(pipelineRange);
const labelsPromises = labelsFactory.MANUAL_KEYS.map((key) =>
BEMUserCache.getMessagesForInterval(key, tq, true).then(labelsFactory.extractResult)
);
const notesPromises = notesFactory.MANUAL_KEYS.map((key) =>
BEMUserCache.getMessagesForInterval(key, tq, true).then(notesFactory.extractResult)
);
return getUnprocessedResults(labelsFactory, notesFactory, labelsPromises, notesPromises);
}

/**
* @description Gets all unprocessed inputs (labels or Enketo responses) that were recorded after the given
* pipeline range, including those on the phone and that and have been pushed to the server but not yet processed.
* @param pipelineRange an object with start_ts and end_ts representing the range of time
* for which travel data has been processed through the pipeline on the server
* @param labelsFactory the Angular factory for processing labels (MultilabelService or
* EnketoTripButtonService)
* @param notesFactory the Angular factory for processing notes (EnketoNotesButtonService)
* @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 labelsPromises = labelsFactory.MANUAL_KEYS.map((key) =>
UnifiedDataLoader.getUnifiedMessagesForInterval(key, tq, true).then(labelsFactory.extractResult)
);
const notesPromises = notesFactory.MANUAL_KEYS.map((key) =>
UnifiedDataLoader.getUnifiedMessagesForInterval(key, tq, true).then(notesFactory.extractResult)
);
return getUnprocessedResults(labelsFactory, notesFactory, labelsPromises, notesPromises);
}

0 comments on commit 88bd8e1

Please sign in to comment.