diff --git a/app/frontend/package-lock.json b/app/frontend/package-lock.json index e3d4efeb1..250dd02a3 100644 --- a/app/frontend/package-lock.json +++ b/app/frontend/package-lock.json @@ -23,6 +23,7 @@ "keycloak-js": "^21.1.1", "leaflet": "^1.9.4", "leaflet-draw": "^1.0.4", + "leaflet-geosearch": "^4.0.0", "lodash": "^4.17.21", "mitt": "^3.0.0", "moment": "^2.29.4", @@ -592,6 +593,12 @@ "vue": ">= 3.0.0 < 4" } }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz", + "integrity": "sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ==", + "optional": true + }, "node_modules/@humanwhocodes/config-array": { "version": "0.11.10", "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.10.tgz", @@ -3705,6 +3712,15 @@ "resolved": "https://registry.npmjs.org/leaflet-draw/-/leaflet-draw-1.0.4.tgz", "integrity": "sha512-rsQ6saQO5ST5Aj6XRFylr5zvarWgzWnrg46zQ1MEOEIHsppdC/8hnN8qMoFvACsPvTioAuysya/TVtog15tyAQ==" }, + "node_modules/leaflet-geosearch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/leaflet-geosearch/-/leaflet-geosearch-4.0.0.tgz", + "integrity": "sha512-a92VNY9gxyv3oyEDqIWoCNoBllajWRYejztzOSNmpLRtzpA6JtGgy/wwl9tsB8+6Eek1fe+L6+W0MDEOaidbXA==", + "optionalDependencies": { + "@googlemaps/js-api-loader": "^1.16.6", + "leaflet": "^1.6.0" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", diff --git a/app/frontend/package.json b/app/frontend/package.json index 3759ab75c..fc3590af6 100644 --- a/app/frontend/package.json +++ b/app/frontend/package.json @@ -44,6 +44,7 @@ "keycloak-js": "^21.1.1", "leaflet": "^1.9.4", "leaflet-draw": "^1.0.4", + "leaflet-geosearch": "^4.0.0", "lodash": "^4.17.21", "mitt": "^3.0.0", "moment": "^2.29.4", diff --git a/components/package-lock.json b/components/package-lock.json index 0fc29cacb..15e0f0ea4 100644 --- a/components/package-lock.json +++ b/components/package-lock.json @@ -16,6 +16,7 @@ "formiojs": "^4.14.6", "leaflet": "^1.9.4", "leaflet-draw": "^1.0.4", + "leaflet-geosearch": "^4.0.0", "lodash": "^4.17.21", "native-promise-only": "^0.8.1", "path-browserify": "^1.0.1", @@ -24,6 +25,7 @@ "devDependencies": { "@types/chai": "^4.3.1", "@types/ejs": "^3.1.1", + "@types/google.maps": "^3.58.1", "@types/mocha": "^9.1.1", "@types/node": "^16.11.8", "@types/sinon": "^10.0.12", @@ -741,6 +743,12 @@ "resolved": "https://registry.npmjs.org/@formio/vanilla-text-mask/-/vanilla-text-mask-5.1.1.tgz", "integrity": "sha512-7MhrbMypySPi7RLchg0ys7HnS3Wqddbq/btAijKB1nA94TE7AOOLhpZJWcNm3kOlX0Y3nHfoavj/HP7vsvF34Q==" }, + "node_modules/@googlemaps/js-api-loader": { + "version": "1.16.8", + "resolved": "https://registry.npmjs.org/@googlemaps/js-api-loader/-/js-api-loader-1.16.8.tgz", + "integrity": "sha512-CROqqwfKotdO6EBjZO/gQGVTbeDps5V7Mt9+8+5Q+jTg5CRMi3Ii/L9PmV3USROrt2uWxtGzJHORmByxyo9pSQ==", + "optional": true + }, "node_modules/@gulpjs/messages": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@gulpjs/messages/-/messages-1.1.0.tgz", @@ -1013,6 +1021,12 @@ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" }, + "node_modules/@types/google.maps": { + "version": "3.58.1", + "resolved": "https://registry.npmjs.org/@types/google.maps/-/google.maps-3.58.1.tgz", + "integrity": "sha512-X9QTSvGJ0nCfMzYOnaVs/k6/4L+7F5uCS+4iUmkLEls6J9S/Phv+m/i3mDeyc49ZBgwab3EFO1HEoBY7k98EGQ==", + "dev": true + }, "node_modules/@types/json-schema": { "version": "7.0.11", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.11.tgz", @@ -4018,6 +4032,15 @@ "resolved": "https://registry.npmjs.org/leaflet-draw/-/leaflet-draw-1.0.4.tgz", "integrity": "sha512-rsQ6saQO5ST5Aj6XRFylr5zvarWgzWnrg46zQ1MEOEIHsppdC/8hnN8qMoFvACsPvTioAuysya/TVtog15tyAQ==" }, + "node_modules/leaflet-geosearch": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/leaflet-geosearch/-/leaflet-geosearch-4.0.0.tgz", + "integrity": "sha512-a92VNY9gxyv3oyEDqIWoCNoBllajWRYejztzOSNmpLRtzpA6JtGgy/wwl9tsB8+6Eek1fe+L6+W0MDEOaidbXA==", + "optionalDependencies": { + "@googlemaps/js-api-loader": "^1.16.6", + "leaflet": "^1.6.0" + } + }, "node_modules/liftoff": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/liftoff/-/liftoff-5.0.0.tgz", diff --git a/components/package.json b/components/package.json index 8961cee2d..13ce65d7d 100644 --- a/components/package.json +++ b/components/package.json @@ -54,6 +54,7 @@ "formiojs": "^4.14.6", "leaflet": "^1.9.4", "leaflet-draw": "^1.0.4", + "leaflet-geosearch": "^4.0.0", "lodash": "^4.17.21", "native-promise-only": "^0.8.1", "path-browserify": "^1.0.1", @@ -62,6 +63,7 @@ "devDependencies": { "@types/chai": "^4.3.1", "@types/ejs": "^3.1.1", + "@types/google.maps": "^3.58.1", "@types/mocha": "^9.1.1", "@types/node": "^16.11.8", "@types/sinon": "^10.0.12", diff --git a/components/src/components/Map/Component.ts b/components/src/components/Map/Component.ts index 4644c3f94..c3fb06650 100644 --- a/components/src/components/Map/Component.ts +++ b/components/src/components/Map/Component.ts @@ -42,7 +42,7 @@ export default class Component extends (FieldComponent as any) { render() { return super.render( - `
` + `
` ); } @@ -57,13 +57,19 @@ export default class Component extends (FieldComponent as any) { const form = document.getElementsByClassName('formio'); const drawOptions = { - marker: false, - circlemarker: false, - polygon: false, - polyline: false, - circle: false, rectangle: null, + circle: false, + polyline: false, + polygon: false, + circlemarker: false, + marker: false, }; + // marker: false, + // circlemarker: false, + // polygon: false, + // polyline: false, + // circle: false, + // rectangle: null, // set marker type from user choice if (this.component.markerType) { for (const [key, value] of Object.entries(this.component.markerType)) { @@ -85,6 +91,7 @@ export default class Component extends (FieldComponent as any) { center, defaultValue, myLocation, + bcGeocoder, } = this.component; const { readOnly: viewMode } = this.options; @@ -108,6 +115,7 @@ export default class Component extends (FieldComponent as any) { onDrawnItemsChange: this.saveDrawnItems.bind(this), viewMode, myLocation, + bcGeocoder, }); // Load existing data if available diff --git a/components/src/components/Map/editForm/Component.edit.data.ts b/components/src/components/Map/editForm/Component.edit.data.ts index 5a0d9e456..ac89cb0b3 100644 --- a/components/src/components/Map/editForm/Component.edit.data.ts +++ b/components/src/components/Map/editForm/Component.edit.data.ts @@ -21,13 +21,6 @@ export default { 'This will be the value for this field, before user interaction.', input: true, }, - { - label: 'How many Markers per Submission?', - key: 'numPoints', - type: 'simplenumber', - defaultValue: 1, - input: true, - }, { label: 'Default Zoom Level', @@ -113,5 +106,14 @@ export default { input: true, defaultValue: true, }, + { + label: 'Enable BC Address Autocomplete', + description: + 'This allows for the user to enter an address and have results appear in a dropdown. The user can then select the result which fits best and have the map center on that location', + key: 'bcGeocoder', + type: 'simplecheckboxadvanced', + input: true, + defaultValue: true, + }, ], }; diff --git a/components/src/components/Map/services/BCGeocoderProvider.ts b/components/src/components/Map/services/BCGeocoderProvider.ts new file mode 100644 index 000000000..d8cae43b9 --- /dev/null +++ b/components/src/components/Map/services/BCGeocoderProvider.ts @@ -0,0 +1,28 @@ +import { OpenStreetMapProvider } from 'leaflet-geosearch'; +import { EndpointArgument } from 'leaflet-geosearch/dist/providers/provider'; + +export class BCGeocoderProvider extends OpenStreetMapProvider { + endpoint({ query, type }: EndpointArgument): string { + console.log(query); + return this.getUrl(import.meta.env.VITE_CHEFS_GEO_ADDRESS_APIURL, { + addressString: query as string, + }); + } + parse({ data }) { + return data.features + .filter(function (feature) { + if (!feature.geometry.coordinates) return false; + if (feature.properties.fullAddress == 'BC') return false; + return true; + }) + .map(function (feature) { + return { + x: feature.geometry.coordinates[0], + y: feature.geometry.coordinates[1], + label: feature.properties.fullAddress, + matchPrecision: feature.properties.matchPrecision, + raw: feature, + }; + }); + } +} diff --git a/components/src/components/Map/services/MapService.ts b/components/src/components/Map/services/MapService.ts index 360eee268..3cccb849b 100644 --- a/components/src/components/Map/services/MapService.ts +++ b/components/src/components/Map/services/MapService.ts @@ -1,7 +1,10 @@ import * as L from 'leaflet'; +import * as GeoSearch from 'leaflet-geosearch'; +import { BCGeocoderProvider } from '../services/BCGeocoderProvider'; import 'leaflet-draw'; import 'leaflet/dist/leaflet.css'; import 'leaflet-draw/dist/leaflet.draw-src.css'; +import 'leaflet-geosearch/dist/geosearch.css'; const DEFAULT_MAP_LAYER_URL = 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png'; @@ -26,6 +29,7 @@ interface MapServiceOptions { onDrawnItemsChange: (items: any) => void; // Support both single and multiple items viewMode?: boolean; myLocation?: boolean; + bcGeocoder: boolean; } class MapService { @@ -82,6 +86,7 @@ class MapService { readOnlyMap, viewMode, myLocation, + bcGeocoder, } = options; if (drawOptions.rectangle) { @@ -146,6 +151,21 @@ class MapService { myLocationControl.addTo(map); } + if (bcGeocoder) { + const geocoderControl = new (GeoSearch.GeoSearchControl as any)({ + provider: new BCGeocoderProvider(), + style: 'bar', + position: 'bottomleft', + }); + map.addControl(geocoderControl); + map.on('geosearch/showlocation', (e) => { + L.popup() + .setLatLng([(e as any).location.y, (e as any).location.x]) + .setContent(`${(e as any).location.label}`) + .openOn(map); + }); + } + // Add Drawing Controllers if (!readOnlyMap) { if (!viewMode) {