From 5105a703c66a78c9aafcb7c1d30f3bf06bf20bb5 Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Thu, 12 Dec 2024 12:53:15 -0800 Subject: [PATCH 1/7] Simplify handle_WHATS_HERE_FEATURE before adding Offline flow --- app/src/state/sagas/map.ts | 150 ++++++++++--------------------------- 1 file changed, 40 insertions(+), 110 deletions(-) diff --git a/app/src/state/sagas/map.ts b/app/src/state/sagas/map.ts index 721a42ccf..e6cf2d936 100644 --- a/app/src/state/sagas/map.ts +++ b/app/src/state/sagas/map.ts @@ -67,7 +67,7 @@ import { handle_IAPP_TABLE_ROWS_GET_ONLINE } from './map/online'; import { selectUserSettings } from 'state/reducers/userSettings'; -import { ACTIVITY_GEOJSON_SOURCE_KEYS, selectMap } from 'state/reducers/map'; +import { ACTIVITY_GEOJSON_SOURCE_KEYS, MapState, selectMap } from 'state/reducers/map'; import { InvasivesAPI_Call } from 'hooks/useInvasivesApi'; import { TRACKING_SAGA_HANDLERS } from 'state/sagas/map/tracking'; import WhatsHere from 'state/actions/whatsHere/WhatsHere'; @@ -80,8 +80,10 @@ import { RootState } from 'state/reducers/rootReducer'; import TileCache from 'state/actions/cache/TileCache'; import { LAYER_ELIGIBILITY_UPDATE } from 'state/sagas/map/layer-eligibility'; import { RECORD_COLOURS } from 'constants/colors'; -import { PayloadAction } from '@reduxjs/toolkit'; +import { Action, PayloadAction } from '@reduxjs/toolkit'; import { IRemoveFilter, IUpdateFilter } from 'state/actions/userSettings/RecordSet'; +import { selectNetworkState } from 'state/reducers/network'; +import UserRecord from 'interfaces/UserRecord'; function* handle_USER_SETTINGS_GET_INITIAL_STATE_SUCCESS(action) { yield put({ type: MAP_INIT_REQUEST, payload: {} }); @@ -113,123 +115,53 @@ function* refetchServerBoundaries() { } function* handle_WHATS_HERE_FEATURE(action) { - let mapState = yield select(selectMap); - - let layersLoading = true; - while (layersLoading) { - mapState = yield select(selectMap); - - const toggledOnActivityLayers = mapState.layers.filter((layer) => { - return layer.layerState.mapToggle && layer.type === RecordSetType.Activity; - }); - - const activityLayersLoading = toggledOnActivityLayers.filter((layer) => { - return layer.loading; - }); - - const toggledOnIAPPLayers = mapState.layers.filter((layer) => { - return layer.layerState.mapToggle && layer.type === RecordSetType.IAPP; - }); - - const IAPPLayersLoading = toggledOnIAPPLayers.filter((layer) => { - return layer.loading; - }); - - if (activityLayersLoading.length === 0 && IAPPLayersLoading.length === 0) { - layersLoading = false; - } else { - const actionsToTake = []; - if (activityLayersLoading.length > 0) { - actionsToTake.push( - activityLayersLoading.map((layer) => { - return ACTIVITIES_GET_IDS_FOR_RECORDSET_SUCCESS; - }) - ); - } - if (IAPPLayersLoading.length > 0) { - actionsToTake.push( - IAPPLayersLoading.map((layer) => { - return IAPP_GET_IDS_FOR_RECORDSET_SUCCESS; - }) - ); - } - yield all(actionsToTake.map((action) => take(action))); - } - } - if (mapState.MapMode === 'VECTOR_ENDPOINT') { + const { MapMode, activitiesGeoJSONDict, IAPPGeoJSONDict } = yield select(selectMap); + if (MapMode === 'VECTOR_ENDPOINT') { // get all the toggled on recordsets + const tableFilters = [ + { + id: '0.81778552637744651712083357942', + filterType: 'spatialFilterDrawn', + operator: 'CONTAINED IN', + filter: '0.652479498272151712093656568', + geojson: action.payload + } + ]; const activitiesfilterObj = { selectColumns: ['activity_id'], - tableFilters: [ - { - id: '0.81778552637744651712083357942', - filterType: 'spatialFilterDrawn', - operator: 'CONTAINED IN', - filter: '0.652479498272151712093656568', - geojson: action.payload - } - ], + tableFilters, limit: 200000 }; - - const activitiesNetworkReturn = yield InvasivesAPI_Call('POST', `/api/v2/activities/`, { - filterObjects: [activitiesfilterObj] - }); - - let activitiesServerIDList = []; - if (activitiesNetworkReturn.data.result || activitiesNetworkReturn.data?.data?.result) { - const list = activitiesNetworkReturn.data?.data?.result - ? activitiesNetworkReturn.data?.data?.result - : activitiesNetworkReturn.data?.result; - activitiesServerIDList = list.map((row) => { - return row.activity_id; - }); - } - const iappfilterObj = { selectColumns: ['site_id'], - tableFilters: [ - { - id: '0.81778552637744651712083357942', - filterType: 'spatialFilterDrawn', - operator: 'CONTAINED IN', - filter: '0.652479498272151712093656568', - geojson: action.payload - } - ], + tableFilters, limit: 200000 }; + const [activitiesNetworkReturn, iappNetworkReturn] = yield all([ + call(InvasivesAPI_Call, 'POST', `/api/v2/activities/`, { + filterObjects: [activitiesfilterObj] + }), + call(InvasivesAPI_Call, 'POST', `/api/v2/iapp/`, { + filterObjects: [iappfilterObj] + }) + ]); - const iappNetworkReturn = yield InvasivesAPI_Call('POST', `/api/v2/iapp/`, { - filterObjects: [iappfilterObj] - }); - - let iappServerIDList = []; + const activityReturn = activitiesNetworkReturn?.data?.data?.result ?? activitiesNetworkReturn?.data?.result ?? []; + const activitiesServerIDList: string[] = activityReturn.map((row: UserRecord) => row.activity_id); - if (iappNetworkReturn.data.result || iappNetworkReturn.data?.data?.result) { - const list = iappNetworkReturn.data?.data?.result - ? iappNetworkReturn.data?.data?.result - : iappNetworkReturn.data?.result; - iappServerIDList = list.map((row) => { - return row.site_id; - }); - } + const iappReturn = iappNetworkReturn?.data?.data?.result ?? iappNetworkReturn?.data?.result ?? []; + const iappServerIDList: string[] = iappReturn.map((row: Record) => row.site_id); yield put(WhatsHere.server_filtered_ids_fetched(activitiesServerIDList, iappServerIDList)); - } - - if (mapState.MapMode !== 'VECTOR_ENDPOINT') { - if (!mapState.activitiesGeoJSONDict) { + } else { + if (!activitiesGeoJSONDict) { yield take(ACTIVITIES_GEOJSON_GET_SUCCESS); } - mapState = yield select(selectMap); - if (!mapState.IAPPGeoJSONDict) { + if (!IAPPGeoJSONDict) { yield take(IAPP_GEOJSON_GET_SUCCESS); } - - yield put(WhatsHere.map_init_get_activity()); - yield put(WhatsHere.map_init_get_poi()); + yield all([put(WhatsHere.map_init_get_activity()), put(WhatsHere.map_init_get_poi())]); } } @@ -317,8 +249,10 @@ function* handle_WHATS_HERE_PAGE_POI(action) { yield put(WhatsHere.iapp_rows_request()); } -function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST(action) { +function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST() { const mapState = yield select(selectMap); + const { connected } = yield select(selectNetworkState); + if (mapState.MapMode === 'VECTOR_ENDPOINT') { const startRecord = mapState?.whatsHere?.ActivityLimit * (mapState?.whatsHere?.ActivityPage + 1) - mapState?.whatsHere?.ActivityLimit; @@ -341,7 +275,7 @@ function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST(action) { yield put(WhatsHere.activity_rows_success([])); return; } - + console.log('Whats Here search', filterObject); const networkReturn = yield InvasivesAPI_Call('POST', `/api/v2/activities/`, { filterObjects: [filterObject] }); @@ -359,11 +293,8 @@ function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST(action) { }; }); yield put(WhatsHere.activity_rows_success(mappedToWhatsHereColumns)); - } - - if (mapState.MapMode !== 'VECTOR_ENDPOINT') { + } else { try { - const mapState = yield select(selectMap); const startRecord = mapState?.whatsHere?.ActivityLimit * (mapState?.whatsHere?.ActivityPage + 1) - mapState?.whatsHere?.ActivityLimit; @@ -842,9 +773,8 @@ function* handle_MAP_TOGGLE_GEOJSON_CACHE(action) { location.reload(); } -function* handle_WHATS_HERE_SERVER_FILTERED_IDS_FETCHED(action) { - yield put(WhatsHere.iapp_rows_request()); - yield put(WhatsHere.activity_rows_request()); +function* handle_WHATS_HERE_SERVER_FILTERED_IDS_FETCHED() { + yield all([put(WhatsHere.iapp_rows_request()), put(WhatsHere.activity_rows_request())]); } function* handle_RECORDSET_ROTATE_COLOUR(action: PayloadAction) { From 5b266324e10a391e4ab43a7a5fb00b0030368105 Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Mon, 16 Dec 2024 08:44:08 -0800 Subject: [PATCH 2/7] Add activity_id as description to shape, fix getBoundingBoxFromRecordsetFilters --- app/src/utils/getBoundingBoxFromRecordsetFilters.ts | 10 +++++----- app/src/utils/record-cache/localforage-cache.ts | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/src/utils/getBoundingBoxFromRecordsetFilters.ts b/app/src/utils/getBoundingBoxFromRecordsetFilters.ts index 1094755d8..788b9a517 100644 --- a/app/src/utils/getBoundingBoxFromRecordsetFilters.ts +++ b/app/src/utils/getBoundingBoxFromRecordsetFilters.ts @@ -23,12 +23,12 @@ const getBoundingBoxFromRecordsetFilters = async (recordSet: UserRecordSet): Pro body: JSON.stringify({ filterObjects: [filterObj] }) }).then((data) => data.json()); - const [minX, minY, maxX, maxY] = bbox(parse(data.bbox)); + const [minLongitude, minLatitude, maxLongitude, maxLatitude] = bbox(parse(data.bbox)); return { - minLatitude: minY, - maxLatitude: maxY, - minLongitude: minX, - maxLongitude: maxX + minLatitude: minLatitude, + maxLatitude: maxLongitude, + minLongitude: minLongitude, + maxLongitude: maxLatitude }; }; diff --git a/app/src/utils/record-cache/localforage-cache.ts b/app/src/utils/record-cache/localforage-cache.ts index fb95c1d7e..33d793e1c 100644 --- a/app/src/utils/record-cache/localforage-cache.ts +++ b/app/src/utils/record-cache/localforage-cache.ts @@ -123,7 +123,7 @@ class LocalForageRecordCacheService extends RecordCacheService { const label = data.short_id; const features = data.geometry ?? []; features.forEach((feature: Feature) => { - feature.properties = { name: label }; + feature.properties = { name: label, description: id }; centroidArr.push(centroid(feature)); geoJsonArr.push(feature); }); From 1cfba0343c081af1210a594c3f55c183ff2f7c29 Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:06:27 -0800 Subject: [PATCH 3/7] add bboxToPolygon --- app/src/utils/bboxToPolygon.ts | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 app/src/utils/bboxToPolygon.ts diff --git a/app/src/utils/bboxToPolygon.ts b/app/src/utils/bboxToPolygon.ts new file mode 100644 index 000000000..689940a61 --- /dev/null +++ b/app/src/utils/bboxToPolygon.ts @@ -0,0 +1,28 @@ +import { Feature, Polygon } from '@turf/helpers'; + +/** + * @desc Takes bounding from recordset metadata and convert into a Geojson Polygon + * @param bbox Cached bounding box + * @returns {Feature} Geojson Bounding box + */ +function bboxToPolygon(bbox: Record): Feature { + const { minLatitude, minLongitude, maxLatitude, maxLongitude } = bbox; + return { + type: 'Feature', + geometry: { + type: 'Polygon', + coordinates: [ + [ + [minLongitude, minLatitude], + [minLongitude, maxLatitude], + [maxLongitude, maxLatitude], + [maxLongitude, minLatitude], + [minLongitude, minLatitude] + ] + ] + }, + properties: {} + }; +} + +export default bboxToPolygon; From 101f7eb3361b74728510980f2621d7f93ff1eacd Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:07:05 -0800 Subject: [PATCH 4/7] add fallback empty array when idlist missing --- app/src/state/sagas/map/dataAccess.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/state/sagas/map/dataAccess.ts b/app/src/state/sagas/map/dataAccess.ts index b2aa53dee..67b2e07a2 100644 --- a/app/src/state/sagas/map/dataAccess.ts +++ b/app/src/state/sagas/map/dataAccess.ts @@ -120,7 +120,7 @@ export function* handle_ACTIVITIES_GET_IDS_FOR_RECORDSET_REQUEST(action) { type: ACTIVITIES_GET_IDS_FOR_RECORDSET_SUCCESS, payload: { recordSetID: action.payload.recordSetID, - IDList: recordSet.cachedMetadata.idList, + IDList: recordSet.cachedMetadata.idList ?? [], tableFiltersHash: action.payload.tableFiltersHash } }); From 453af2195d88bc21cf91d0e11994b4b88cf1a911 Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:09:16 -0800 Subject: [PATCH 5/7] destructure turf.js, add Offline flow to WHATS_HERE sagas, remove smells --- app/src/state/sagas/map.ts | 173 ++++++++++++++++++++++--------------- 1 file changed, 102 insertions(+), 71 deletions(-) diff --git a/app/src/state/sagas/map.ts b/app/src/state/sagas/map.ts index e6cf2d936..b99f222ca 100644 --- a/app/src/state/sagas/map.ts +++ b/app/src/state/sagas/map.ts @@ -1,4 +1,5 @@ -import * as turf from '@turf/turf'; +import { bboxPolygon, Feature, buffer } from '@turf/turf'; +import booleanIntersects from '@turf/boolean-intersects'; import { all, call, debounce, fork, put, select, take, takeEvery, takeLatest } from 'redux-saga/effects'; import { getSearchCriteriaFromFilters } from '../../utils/miscYankedFromComponents'; import { @@ -7,7 +8,6 @@ import { ACTIVITIES_GEOJSON_REFETCH_ONLINE, ACTIVITIES_GET_IDS_FOR_RECORDSET_ONLINE, ACTIVITIES_GET_IDS_FOR_RECORDSET_REQUEST, - ACTIVITIES_GET_IDS_FOR_RECORDSET_SUCCESS, ACTIVITIES_TABLE_ROWS_GET_ONLINE, ACTIVITIES_TABLE_ROWS_GET_REQUEST, ACTIVITY_UPDATE_GEO_REQUEST, @@ -21,7 +21,6 @@ import { IAPP_GEOJSON_GET_SUCCESS, IAPP_GET_IDS_FOR_RECORDSET_ONLINE, IAPP_GET_IDS_FOR_RECORDSET_REQUEST, - IAPP_GET_IDS_FOR_RECORDSET_SUCCESS, IAPP_TABLE_ROWS_GET_ONLINE, IAPP_TABLE_ROWS_GET_REQUEST, INIT_SERVER_BOUNDARIES_GET, @@ -67,12 +66,12 @@ import { handle_IAPP_TABLE_ROWS_GET_ONLINE } from './map/online'; import { selectUserSettings } from 'state/reducers/userSettings'; -import { ACTIVITY_GEOJSON_SOURCE_KEYS, MapState, selectMap } from 'state/reducers/map'; +import { ACTIVITY_GEOJSON_SOURCE_KEYS, selectMap } from 'state/reducers/map'; import { InvasivesAPI_Call } from 'hooks/useInvasivesApi'; import { TRACKING_SAGA_HANDLERS } from 'state/sagas/map/tracking'; import WhatsHere from 'state/actions/whatsHere/WhatsHere'; import Prompt from 'state/actions/prompts/Prompt'; -import { RecordSetType, UserRecordSet } from 'interfaces/UserRecordSet'; +import { RecordSetType, UserRecordCacheStatus, UserRecordSet } from 'interfaces/UserRecordSet'; import UserSettings from 'state/actions/userSettings/UserSettings'; import { SortFilter } from 'interfaces/filterParams'; import Activity from 'state/actions/activity/Activity'; @@ -80,10 +79,13 @@ import { RootState } from 'state/reducers/rootReducer'; import TileCache from 'state/actions/cache/TileCache'; import { LAYER_ELIGIBILITY_UPDATE } from 'state/sagas/map/layer-eligibility'; import { RECORD_COLOURS } from 'constants/colors'; -import { Action, PayloadAction } from '@reduxjs/toolkit'; +import { PayloadAction } from '@reduxjs/toolkit'; import { IRemoveFilter, IUpdateFilter } from 'state/actions/userSettings/RecordSet'; -import { selectNetworkState } from 'state/reducers/network'; +import { selectNetworkConnected, selectNetworkState } from 'state/reducers/network'; import UserRecord from 'interfaces/UserRecord'; +import { MOBILE } from 'state/build-time-config'; +import { RecordCacheServiceFactory } from 'utils/record-cache/context'; +import bboxToPolygon from 'utils/bboxToPolygon'; function* handle_USER_SETTINGS_GET_INITIAL_STATE_SUCCESS(action) { yield put({ type: MAP_INIT_REQUEST, payload: {} }); @@ -114,46 +116,66 @@ function* refetchServerBoundaries() { yield put({ type: INIT_SERVER_BOUNDARIES_GET, payload: { data: shapes } }); } -function* handle_WHATS_HERE_FEATURE(action) { +function* handle_WHATS_HERE_FEATURE(whatsHereFeature: PayloadAction) { const { MapMode, activitiesGeoJSONDict, IAPPGeoJSONDict } = yield select(selectMap); - if (MapMode === 'VECTOR_ENDPOINT') { - // get all the toggled on recordsets - const tableFilters = [ - { - id: '0.81778552637744651712083357942', - filterType: 'spatialFilterDrawn', - operator: 'CONTAINED IN', - filter: '0.652479498272151712093656568', - geojson: action.payload - } - ]; - - const activitiesfilterObj = { - selectColumns: ['activity_id'], - tableFilters, - limit: 200000 - }; - const iappfilterObj = { - selectColumns: ['site_id'], - tableFilters, - limit: 200000 - }; - const [activitiesNetworkReturn, iappNetworkReturn] = yield all([ - call(InvasivesAPI_Call, 'POST', `/api/v2/activities/`, { - filterObjects: [activitiesfilterObj] - }), - call(InvasivesAPI_Call, 'POST', `/api/v2/iapp/`, { - filterObjects: [iappfilterObj] - }) - ]); - - const activityReturn = activitiesNetworkReturn?.data?.data?.result ?? activitiesNetworkReturn?.data?.result ?? []; - const activitiesServerIDList: string[] = activityReturn.map((row: UserRecord) => row.activity_id); + const { connected } = yield select(selectNetworkState); - const iappReturn = iappNetworkReturn?.data?.data?.result ?? iappNetworkReturn?.data?.result ?? []; - const iappServerIDList: string[] = iappReturn.map((row: Record) => row.site_id); + if (MapMode === 'VECTOR_ENDPOINT') { + if (connected) { + // get all the toggled on recordsets + const tableFilters = [ + { + id: '0.81778552637744651712083357942', + filterType: 'spatialFilterDrawn', + operator: 'CONTAINED IN', + filter: '0.652479498272151712093656568', + geojson: whatsHereFeature.payload + } + ]; - yield put(WhatsHere.server_filtered_ids_fetched(activitiesServerIDList, iappServerIDList)); + const activitiesfilterObj = { + selectColumns: ['activity_id'], + tableFilters, + limit: 200000 + }; + const iappfilterObj = { + selectColumns: ['site_id'], + tableFilters, + limit: 200000 + }; + const [activitiesNetworkReturn, iappNetworkReturn] = yield all([ + call(InvasivesAPI_Call, 'POST', `/api/v2/activities/`, { + filterObjects: [activitiesfilterObj] + }), + call(InvasivesAPI_Call, 'POST', `/api/v2/iapp/`, { + filterObjects: [iappfilterObj] + }) + ]); + + const activityReturn = activitiesNetworkReturn?.data?.data?.result ?? activitiesNetworkReturn?.data?.result ?? []; + const activitiesServerIDList: string[] = activityReturn.map((row: UserRecord) => row.activity_id); + + const iappReturn = iappNetworkReturn?.data?.data?.result ?? iappNetworkReturn?.data?.result ?? []; + const iappServerIDList: string[] = iappReturn.map((row: Record) => row.site_id); + yield put(WhatsHere.server_filtered_ids_fetched(activitiesServerIDList, iappServerIDList)); + } else { + // Get IDs from Offline Caches + const { recordSets } = yield select(selectUserSettings); + const recordSetsInBoundingBox = Object.keys(recordSets).filter((set) => { + const { bbox, status } = recordSets[set].cacheMetadata; + const recordSetIsCached = status === UserRecordCacheStatus.CACHED; + return recordSetIsCached && bbox && booleanIntersects(whatsHereFeature.payload, bboxToPolygon(bbox)); + }); + const overlappingRecords: string[] = []; + recordSetsInBoundingBox.flatMap((set) => + recordSets[set].cacheMetadata.cachedGeoJson.data.features.forEach((shape: Feature) => { + if (booleanIntersects(whatsHereFeature.payload, shape)) { + overlappingRecords.push(shape?.properties?.description); + } + }) + ); + yield put(WhatsHere.server_filtered_ids_fetched(overlappingRecords, [])); + } } else { if (!activitiesGeoJSONDict) { yield take(ACTIVITIES_GEOJSON_GET_SUCCESS); @@ -251,14 +273,13 @@ function* handle_WHATS_HERE_PAGE_POI(action) { function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST() { const mapState = yield select(selectMap); - const { connected } = yield select(selectNetworkState); + const connected = yield select(selectNetworkConnected); if (mapState.MapMode === 'VECTOR_ENDPOINT') { - const startRecord = - mapState?.whatsHere?.ActivityLimit * (mapState?.whatsHere?.ActivityPage + 1) - mapState?.whatsHere?.ActivityLimit; - const endRecord = mapState?.whatsHere?.ActivityLimit * (mapState?.whatsHere?.ActivityPage + 1); - const slicedIDs = mapState.whatsHere.ActivityIDs.slice(startRecord, endRecord); - + const { whatsHere } = mapState; + const startRecord = whatsHere.ActivityLimit * (whatsHere.ActivityPage + 1) - whatsHere.ActivityLimit; + const endRecord = whatsHere.ActivityLimit * (whatsHere.ActivityPage + 1); + const slicedIDs = whatsHere.ActivityIDs.slice(startRecord, endRecord); const filterObject = { selectColumns: [ 'activity_id', @@ -275,21 +296,33 @@ function* handle_WHATS_HERE_ACTIVITY_ROWS_REQUEST() { yield put(WhatsHere.activity_rows_success([])); return; } - console.log('Whats Here search', filterObject); - const networkReturn = yield InvasivesAPI_Call('POST', `/api/v2/activities/`, { - filterObjects: [filterObject] - }); - const mappedToWhatsHereColumns = networkReturn.data.result.map((activityRecord) => { + let records: UserRecord[]; + if (MOBILE && !connected) { + const service = yield RecordCacheServiceFactory.getPlatformInstance(); + records = yield service.fetchPaginatedCachedRecords( + whatsHere.ActivityIDs, + whatsHere.ActivityPage, + whatsHere.ActivityLimit + ); + } else { + const networkReturn = yield InvasivesAPI_Call('POST', `/api/v2/activities/`, { + filterObjects: [filterObject] + }); + records = networkReturn.data.result; + } + const mappedToWhatsHereColumns = records.map((activityRecord) => { + // Differenciate the Cached records from the API called ones + const shortHand = activityRecord.activity_payload ? activityRecord.activity_payload : activityRecord; return { id: activityRecord.activity_id, short_id: activityRecord.short_id, activity_type: activityRecord.activity_type, jurisdiction_code: activityRecord.jurisdiction_display, species_code: activityRecord.map_symbol, - reported_area: activityRecord.activity_payload.form_data.activity_data.reported_area, - geometry: activityRecord.activity_payload.geometry?.[0], - created: new Date(activityRecord.activity_payload.form_data.activity_data.activity_date_time).toDateString() + reported_area: shortHand.form_data.activity_data.reported_area, + geometry: shortHand.geometry?.[0], + created: new Date(shortHand.form_data.activity_data.activity_date_time).toDateString() }; }); yield put(WhatsHere.activity_rows_success(mappedToWhatsHereColumns)); @@ -452,20 +485,18 @@ function* handle_RECORD_SET_TO_EXCEL_REQUEST(action) { } } -function* handle_WHATS_HERE_SORT_FILTER_UPDATE(action) { - switch (action.payload.recordType) { - case RecordSetType.IAPP: - yield put(WhatsHere.iapp_rows_request()); - break; - default: - yield put(WhatsHere.activity_rows_request()); - break; +function* handle_WHATS_HERE_SORT_FILTER_UPDATE(record: PayloadAction>) { + const { recordType } = record.payload; + if (recordType === RecordSetType.IAPP) { + yield put(WhatsHere.iapp_rows_request()); + } else if (recordType === RecordSetType.Activity) { + yield put(WhatsHere.activity_rows_request()); } } function* handle_MAP_LABEL_EXTENT_FILTER_REQUEST(action) { const bbox = [action.payload.minX, action.payload.minY, action.payload.maxX, action.payload.maxY]; - const bounds = turf.bboxPolygon(bbox as any); + const bounds = bboxPolygon(bbox as any); yield put({ type: MAP_LABEL_EXTENT_FILTER_SUCCESS, @@ -477,7 +508,7 @@ function* handle_MAP_LABEL_EXTENT_FILTER_REQUEST(action) { function* handle_IAPP_EXTENT_FILTER_REQUEST(action) { const bbox = [action.payload.minX, action.payload.minY, action.payload.maxX, action.payload.maxY]; - const bounds = turf.bboxPolygon(bbox as any); + const bounds = bboxPolygon(bbox as any); yield put({ type: IAPP_EXTENT_FILTER_SUCCESS, @@ -735,9 +766,9 @@ function* handle_CUSTOM_LAYER_DRAWN(actions) { function* handle_MAP_ON_SHAPE_CREATE(action) { const callback = (width: number) => { - const newGeo = turf.buffer(action.payload.geometry, width / 10000); + const newGeo = buffer(action.payload.geometry, width / 10000) ?? action.payload; if (appModeUrl && /Activity/.test(appModeUrl) && !whatsHereToggle) { - return [{ type: ACTIVITY_UPDATE_GEO_REQUEST, payload: { geometry: [newGeo ? newGeo : action.payload] } }]; + return [{ type: ACTIVITY_UPDATE_GEO_REQUEST, payload: { geometry: [newGeo] } }]; } }; const appModeUrl = yield select((state: any) => state.AppMode.url); @@ -769,7 +800,7 @@ function* handle_MAP_ON_SHAPE_UPDATE(action) { } } -function* handle_MAP_TOGGLE_GEOJSON_CACHE(action) { +function handle_MAP_TOGGLE_GEOJSON_CACHE(action) { location.reload(); } From d0ba7aa4b3e94d3680248606af23ee9e83cae6fa Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:09:57 -0800 Subject: [PATCH 6/7] Add types to WhatsHere.server_filtered_ids_fetched --- app/src/state/actions/whatsHere/WhatsHere.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/state/actions/whatsHere/WhatsHere.ts b/app/src/state/actions/whatsHere/WhatsHere.ts index b3054573d..114e6adf2 100644 --- a/app/src/state/actions/whatsHere/WhatsHere.ts +++ b/app/src/state/actions/whatsHere/WhatsHere.ts @@ -29,7 +29,7 @@ class WhatsHere { static readonly page_activity = createAction<{ page: number; limit: number }>(`${this.PREFIX}/page_activity`); static readonly server_filtered_ids_fetched = createAction( `${this.PREFIX}/server_filtered_ids_fetched`, - (activities, iapp) => ({ + (activities: string[], iapp: string[]) => ({ payload: { activities, iapp } }) ); From 3dfbf6ae9b6d082ebdd5925603b995f6338c14c7 Mon Sep 17 00:00:00 2001 From: LocalNewsTV <62873746+LocalNewsTV@users.noreply.github.com> Date: Mon, 16 Dec 2024 13:10:55 -0800 Subject: [PATCH 7/7] Condense Sagas and integrate Offline for WhatsHere --- app/src/state/reducers/map.ts | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/app/src/state/reducers/map.ts b/app/src/state/reducers/map.ts index 5227cbd2e..1e60d0e8a 100644 --- a/app/src/state/reducers/map.ts +++ b/app/src/state/reducers/map.ts @@ -532,34 +532,22 @@ function createMapReducer(configuration: AppConfig): (MapState, AnyAction) => Ma } else if (WhatsHere.server_filtered_ids_fetched.match(action)) { draftState.whatsHere.serverActivityIDs = action.payload.activities; draftState.whatsHere.serverIAPPIDs = action.payload.iapp; - const toggledOnActivityLayers = draftState.layers.filter( - (layer) => layer.type === RecordSetType.Activity && layer.layerState.mapToggle + ({ type, layerState }) => type === RecordSetType.Activity && layerState.mapToggle ); const toggledOnIAPPLayers = draftState.layers.filter( - (layer) => layer.type === RecordSetType.IAPP && layer.layerState.mapToggle + ({ type, layerState }) => type === RecordSetType.IAPP && layerState.mapToggle ); + const localActivityIDs = toggledOnActivityLayers.flatMap( + (layer) => layer.IDList ?? layer?.layerState?.cacheMetadata?.idList ?? [] + ); + const localIappIds = toggledOnIAPPLayers.flatMap((layer) => layer.IDList ?? layer?.cacheMetadata?.idList ?? []); + const iappIds = localIappIds.filter((l) => draftState.whatsHere.serverIAPPIDs.includes(l)); + const activityIds = localActivityIDs.filter((l) => draftState.whatsHere.serverActivityIDs.includes(l)); - let localActivityIDs = []; - - toggledOnActivityLayers.forEach((layer) => { - localActivityIDs = localActivityIDs.concat(layer.IDList); - }); - - let localIAPPIDs = []; - - toggledOnIAPPLayers.forEach((layer) => { - localIAPPIDs = localIAPPIDs.concat(layer.IDList); - }); - - const iappIDs = []; - const activityIDs = []; - localIAPPIDs.forEach((l) => draftState.whatsHere.serverIAPPIDs.includes(l) && iappIDs.push(l)); - localActivityIDs.forEach((l) => draftState.whatsHere.serverActivityIDs.includes(l) && activityIDs.push(l)); - - draftState.whatsHere.ActivityIDs = Array.from(new Set(activityIDs)); - draftState.whatsHere.IAPPIDs = Array.from(new Set(iappIDs)); + draftState.whatsHere.ActivityIDs = Array.from(new Set(activityIds)); + draftState.whatsHere.IAPPIDs = Array.from(new Set(iappIds)); } else if (WhatsHere.sort_filter_update.match(action)) { if (action.payload.type === RecordSetType.IAPP) { draftState.whatsHere.IAPPPage = 0; @@ -758,8 +746,6 @@ function createMapReducer(configuration: AppConfig): (MapState, AnyAction) => Ma if (draftState.MapMode === 'VECTOR_ENDPOINT') { draftState.layers[index].loading = false; } - - //if (draftState.activitiesGeoJSON?.features?.length > 0) { if (draftState.MapMode !== 'VECTOR_ENDPOINT' && draftState.activitiesGeoJSONDict !== undefined) { GeoJSONFilterSetForLayer( draftState,