From 8fe93ebfeddcff19aa051581ff833a9f455f1345 Mon Sep 17 00:00:00 2001 From: Alejandro Sanchez Date: Wed, 14 Feb 2024 17:35:13 -0800 Subject: [PATCH] PSP-7819 FT: Disposition File - Grey marker appears as Other Interest when the Advanced Filters for IS_DISPOSED is not selected (#3793) * Update typing of map layer * Update map machine state when closing advanced filter * Fix map pin rendering logic to accommodate DISPOSED properties * Test corrections --- .../mapFSM/machineDefinition/mapMachine.ts | 1 + .../maps/leaflet/Layers/util.test.tsx | 233 +++++++++++------- .../components/maps/leaflet/Layers/util.tsx | 22 +- .../maps/leaflet/Markers/SingleMarker.tsx | 23 +- .../properties/map/MapContainer.test.tsx | 1 + .../models/layers/pimsPropertyLocationView.ts | 15 +- 6 files changed, 186 insertions(+), 109 deletions(-) diff --git a/source/frontend/src/components/common/mapFSM/machineDefinition/mapMachine.ts b/source/frontend/src/components/common/mapFSM/machineDefinition/mapMachine.ts index f16acbd44d..bc56bb6af0 100644 --- a/source/frontend/src/components/common/mapFSM/machineDefinition/mapMachine.ts +++ b/source/frontend/src/components/common/mapFSM/machineDefinition/mapMachine.ts @@ -50,6 +50,7 @@ const featureViewStates = { on: { TOGGLE_FILTER: { target: 'browsing', + actions: assign({ showDisposed: () => false }), }, TOGGLE_LAYERS: { target: 'layerControl', diff --git a/source/frontend/src/components/maps/leaflet/Layers/util.test.tsx b/source/frontend/src/components/maps/leaflet/Layers/util.test.tsx index 95e12bbd72..e716e0ae68 100644 --- a/source/frontend/src/components/maps/leaflet/Layers/util.test.tsx +++ b/source/frontend/src/components/maps/leaflet/Layers/util.test.tsx @@ -19,10 +19,12 @@ import { ICluster } from '../../types'; import { createClusterMarker, createPoints, + disposedIcon, getMarkerIcon, otherInterestIcon, - otherInterestIconSelect, + parcelIcon, pointToLayer, + propertyOfInterestIcon, } from './util'; describe('mapUtils tests', () => { describe('pointToLayer function', () => { @@ -34,7 +36,7 @@ describe('mapUtils tests', () => { type: 'Point', coordinates: [1, 2], }, - properties: { ...EmptyPropertyLocation, PROPERTY_ID: '1' }, + properties: { ...EmptyPropertyLocation, PROPERTY_ID: '1', IS_OTHER_INTEREST: true }, }; const latlng: LatLngExpression = { lat: 1, lng: 2 }; @@ -68,6 +70,7 @@ describe('mapUtils tests', () => { expect(pointToLayer(feature, latlng)).toEqual(new Marker(latlng, { icon })); }); }); + describe('createClusterMarker function', () => { it('returns null when passed a feature that is not a cluster', () => { const feature: ICluster = { @@ -83,7 +86,8 @@ describe('mapUtils tests', () => { expect(createClusterMarker(feature, latlng)).toBeNull(); }); }); - describe('getMarkericon function', () => { + + describe('getMarkerIcon function', () => { const feature: ICluster = { id: 1, type: 'Feature', @@ -96,106 +100,163 @@ describe('mapUtils tests', () => { point_count_abbreviated: 100, }, }; - it('returns a default parcel icon', () => { + it(`returns a valid map pin icon for 'Core Inventory'`, () => { expect( getMarkerIcon( { ...feature, - properties: { ...EmptyPropertyLocation, PROPERTY_ID: '1' }, + properties: { ...EmptyPropertyLocation, PROPERTY_ID: '1', IS_OWNED: true }, }, - true, + false, ), - ).toEqual(otherInterestIconSelect); + ).toEqual(parcelIcon); }); - - describe('create points function', () => { - const property: IProperty = { - id: 1, - pid: '000-000-001', - statusId: PropertyStatusTypes.UnderAdmin, - classificationId: PropertyClassificationTypes.CoreOperational, - tenureId: PropertyTenureTypes.HighwayRoad, - dataSourceId: PropertyDataSourceTypes.PAIMS, - dataSourceEffectiveDate: '2021-08-30T18:11:13.883Z', - address: { - streetAddress1: '1243 St', - provinceId: 1, - municipality: '', - postal: '', - }, - regionId: 1, - districtId: 1, - areaUnitId: PropertyAreaUnitTypes.Hectare, - landArea: 0, - landLegalDescription: '', - latitude: 1, - longitude: 2, - isSensitive: false, - }; - it('converts properties to point features', () => { - expect(createPoints([property, property])).toEqual([ + it(`returns a valid map pin icon for 'Property of Interest'`, () => { + expect( + getMarkerIcon( { - geometry: { coordinates: [2, 1], type: 'Point' }, + ...feature, properties: { - PROPERTY_ID: 1, - address: { - streetAddress1: '1243 St', - provinceId: 1, - municipality: '', - postal: '', - }, - areaUnitId: PropertyAreaUnitTypes.Hectare, - classificationId: PropertyClassificationTypes.CoreOperational, - dataSourceId: PropertyDataSourceTypes.PAIMS, - dataSourceEffectiveDate: property.dataSourceEffectiveDate, - districtId: 1, - cluster: false, - id: 1, - isSensitive: false, - latitude: 1, - longitude: 2, - tenureId: PropertyTenureTypes.HighwayRoad, - statusId: PropertyStatusTypes.UnderAdmin, - regionId: 1, - landArea: 0, - landLegalDescription: '', - pid: '000-000-001', + ...EmptyPropertyLocation, + PROPERTY_ID: '1', + IS_PROPERTY_OF_INTEREST: true, }, - type: 'Feature', }, + false, + ), + ).toEqual(propertyOfInterestIcon); + }); + it(`returns a valid map pin icon for 'Other Interest'`, () => { + expect( + getMarkerIcon( + { + ...feature, + properties: { ...EmptyPropertyLocation, PROPERTY_ID: '1', IS_OTHER_INTEREST: true }, + }, + false, + ), + ).toEqual(otherInterestIcon); + }); + it(`returns a valid map pin icon for 'Disposed'`, () => { + expect( + getMarkerIcon( + { + ...feature, + properties: { ...EmptyPropertyLocation, PROPERTY_ID: '1', IS_DISPOSED: true }, + }, + false, + true, + ), + ).toEqual(disposedIcon); + }); + it(`returns null when passed feature is not one of: 'Core Inventory', 'Property of Interest', 'Other Interest' or 'Disposed'`, () => { + expect( + getMarkerIcon( { - geometry: { coordinates: [2, 1], type: 'Point' }, + ...feature, properties: { - PROPERTY_ID: 1, - address: { - streetAddress1: '1243 St', - provinceId: 1, - municipality: '', - postal: '', - }, - areaUnitId: PropertyAreaUnitTypes.Hectare, - classificationId: PropertyClassificationTypes.CoreOperational, - dataSourceId: PropertyDataSourceTypes.PAIMS, - dataSourceEffectiveDate: property.dataSourceEffectiveDate, - districtId: 1, - cluster: false, - id: 1, - isSensitive: false, - latitude: 1, - longitude: 2, - tenureId: PropertyTenureTypes.HighwayRoad, - statusId: PropertyStatusTypes.UnderAdmin, - regionId: 1, - landArea: 0, - landLegalDescription: '', - pid: '000-000-001', + ...EmptyPropertyLocation, + PROPERTY_ID: '1', + IS_OWNED: null, + IS_PROPERTY_OF_INTEREST: null, + IS_OTHER_INTEREST: null, + IS_DISPOSED: null, }, - type: 'Feature', }, - ]); - }); + true, + ), + ).toBeNull(); }); }); + + describe('create points function', () => { + const property: IProperty = { + id: 1, + pid: '000-000-001', + statusId: PropertyStatusTypes.UnderAdmin, + classificationId: PropertyClassificationTypes.CoreOperational, + tenureId: PropertyTenureTypes.HighwayRoad, + dataSourceId: PropertyDataSourceTypes.PAIMS, + dataSourceEffectiveDate: '2021-08-30T18:11:13.883Z', + address: { + streetAddress1: '1243 St', + provinceId: 1, + municipality: '', + postal: '', + }, + regionId: 1, + districtId: 1, + areaUnitId: PropertyAreaUnitTypes.Hectare, + landArea: 0, + landLegalDescription: '', + latitude: 1, + longitude: 2, + isSensitive: false, + }; + it('converts properties to point features', () => { + expect(createPoints([property, property])).toEqual([ + { + geometry: { coordinates: [2, 1], type: 'Point' }, + properties: { + PROPERTY_ID: 1, + address: { + streetAddress1: '1243 St', + provinceId: 1, + municipality: '', + postal: '', + }, + areaUnitId: PropertyAreaUnitTypes.Hectare, + classificationId: PropertyClassificationTypes.CoreOperational, + dataSourceId: PropertyDataSourceTypes.PAIMS, + dataSourceEffectiveDate: property.dataSourceEffectiveDate, + districtId: 1, + cluster: false, + id: 1, + isSensitive: false, + latitude: 1, + longitude: 2, + tenureId: PropertyTenureTypes.HighwayRoad, + statusId: PropertyStatusTypes.UnderAdmin, + regionId: 1, + landArea: 0, + landLegalDescription: '', + pid: '000-000-001', + }, + type: 'Feature', + }, + { + geometry: { coordinates: [2, 1], type: 'Point' }, + properties: { + PROPERTY_ID: 1, + address: { + streetAddress1: '1243 St', + provinceId: 1, + municipality: '', + postal: '', + }, + areaUnitId: PropertyAreaUnitTypes.Hectare, + classificationId: PropertyClassificationTypes.CoreOperational, + dataSourceId: PropertyDataSourceTypes.PAIMS, + dataSourceEffectiveDate: property.dataSourceEffectiveDate, + districtId: 1, + cluster: false, + id: 1, + isSensitive: false, + latitude: 1, + longitude: 2, + tenureId: PropertyTenureTypes.HighwayRoad, + statusId: PropertyStatusTypes.UnderAdmin, + regionId: 1, + landArea: 0, + landLegalDescription: '', + pid: '000-000-001', + }, + type: 'Feature', + }, + ]); + }); + }); + describe('toCqlFilter function', () => { it('by default, joins multiple filters with and and inserts ilike', () => { const cql = toCqlFilterValue({ PID: '12345678', PIN: '54321' }); diff --git a/source/frontend/src/components/maps/leaflet/Layers/util.tsx b/source/frontend/src/components/maps/leaflet/Layers/util.tsx index 09571b24a6..bc4e2c3c63 100644 --- a/source/frontend/src/components/maps/leaflet/Layers/util.tsx +++ b/source/frontend/src/components/maps/leaflet/Layers/util.tsx @@ -178,8 +178,8 @@ export function getMarkerIcon( feature: Supercluster.PointFeature, selected: boolean, showDisposed: boolean = false, -): L.Icon { - if (showDisposed && feature.properties.IS_DISPOSED) { +): L.Icon | null { + if (showDisposed && feature?.properties?.IS_DISPOSED === true) { if (selected) { return disposedIconSelect; } else { @@ -187,7 +187,7 @@ export function getMarkerIcon( } } - if (feature.properties.IS_PROPERTY_OF_INTEREST) { + if (feature?.properties?.IS_PROPERTY_OF_INTEREST === true) { if (selected) { return propertyOfInterestIconSelect; } else { @@ -195,18 +195,22 @@ export function getMarkerIcon( } } - if (feature.properties.IS_OWNED) { + if (feature?.properties?.IS_OWNED === true) { if (selected) { return parcelIconSelect; } return parcelIcon; } - if (selected) { - return otherInterestIconSelect; - } else { - return otherInterestIcon; + if (feature?.properties?.IS_OTHER_INTEREST === true) { + if (selected) { + return otherInterestIconSelect; + } else { + return otherInterestIcon; + } } + + return null; } /** @@ -243,7 +247,7 @@ export const createSingleMarker =

( if (isOwned) { const icon = getMarkerIcon(feature, false); - return new Marker(latlng, { icon }); + return icon ? new Marker(latlng, { icon }) : (null as unknown as Layer); } else { const icon = getNotOwnerMarkerIcon(false); return new Marker(latlng, { icon }); diff --git a/source/frontend/src/components/maps/leaflet/Markers/SingleMarker.tsx b/source/frontend/src/components/maps/leaflet/Markers/SingleMarker.tsx index 98e425a551..945d99de6b 100644 --- a/source/frontend/src/components/maps/leaflet/Markers/SingleMarker.tsx +++ b/source/frontend/src/components/maps/leaflet/Markers/SingleMarker.tsx @@ -33,11 +33,16 @@ const SinglePropertyMarker: React.FC { const mapMachine = useMapStateMachine(); - const isOwned = isPimsFeature(pointFeature); - - const getIcon = () => { + const getIcon = ( + feature: PointFeature< + PIMS_Property_Location_View | PIMS_Property_Boundary_View | PMBC_Feature_Properties + >, + isSelected: boolean, + showDisposed: boolean, + ): L.Icon | null => { + const isOwned = isPimsFeature(feature); if (isOwned) { - return getMarkerIcon(pointFeature, isSelected, mapMachine.showDisposed); + return getMarkerIcon(feature, isSelected, showDisposed); } else { return getNotOwnerMarkerIcon(isSelected); } @@ -75,19 +80,21 @@ const SinglePropertyMarker: React.FC { onMarkerClicked(); }, }} /> - ); + ) : null; }; export default SinglePropertyMarker; diff --git a/source/frontend/src/features/properties/map/MapContainer.test.tsx b/source/frontend/src/features/properties/map/MapContainer.test.tsx index 1f3e29c49c..f3737598a9 100644 --- a/source/frontend/src/features/properties/map/MapContainer.test.tsx +++ b/source/frontend/src/features/properties/map/MapContainer.test.tsx @@ -113,6 +113,7 @@ export const createPimsFeatures = ( ...EmptyPropertyLocation, PROPERTY_ID: x.propertyId ?? null, PID: x.pid ?? null, + IS_OWNED: true, }, }; }), diff --git a/source/frontend/src/models/layers/pimsPropertyLocationView.ts b/source/frontend/src/models/layers/pimsPropertyLocationView.ts index 158d4286d4..da9940c6c0 100644 --- a/source/frontend/src/models/layers/pimsPropertyLocationView.ts +++ b/source/frontend/src/models/layers/pimsPropertyLocationView.ts @@ -33,9 +33,10 @@ export interface PIMS_Property_Location_View { readonly SURVEY_PLAN_NUMBER: string | null; readonly ENCUMBRANCE_REASON: string | null; readonly IS_SENSITIVE: string | null; - readonly IS_OWNED: string | null; - readonly IS_PROPERTY_OF_INTEREST: string | null; - readonly IS_DISPOSED: string | null; + readonly IS_OWNED: boolean | null; + readonly IS_PROPERTY_OF_INTEREST: boolean | null; + readonly IS_DISPOSED: boolean | null; + readonly IS_OTHER_INTEREST: boolean | null; readonly IS_VISIBLE_TO_OTHER_AGENCIES: string | null; readonly ZONING: string | null; readonly ZONING_POTENTIAL: string | null; @@ -76,6 +77,7 @@ export const EmptyPropertyLocation: PIMS_Property_Location_View = { IS_OWNED: null, IS_PROPERTY_OF_INTEREST: null, IS_DISPOSED: null, + IS_OTHER_INTEREST: null, IS_VISIBLE_TO_OTHER_AGENCIES: null, ZONING: null, ZONING_POTENTIAL: null, @@ -116,9 +118,10 @@ export interface PIMS_Property_Boundary_View { readonly SURVEY_PLAN_NUMBER: string | null; readonly ENCUMBRANCE_REASON: string | null; readonly IS_SENSITIVE: string | null; - readonly IS_OWNED: string | null; - readonly IS_PROPERTY_OF_INTEREST: string | null; - readonly IS_DISPOSED: string | null; + readonly IS_OWNED: boolean | null; + readonly IS_PROPERTY_OF_INTEREST: boolean | null; + readonly IS_DISPOSED: boolean | null; + readonly IS_OTHER_INTEREST: boolean | null; readonly IS_VISIBLE_TO_OTHER_AGENCIES: string | null; readonly ZONING: string | null; readonly ZONING_POTENTIAL: string | null;