From 8e459a0c6b1021a45a4cc041d33b42a2e55f82b9 Mon Sep 17 00:00:00 2001 From: Rishabh Saxena Date: Tue, 19 Jan 2021 12:59:15 +0530 Subject: [PATCH] validate map center and markers (#2488) --- .../LocationSearchControl.tsx | 3 +- .../src/constants/FieldExpectedValue.ts | 1 + app/client/src/constants/WidgetConstants.tsx | 2 + app/client/src/constants/WidgetValidation.ts | 1 + app/client/src/widgets/MapWidget.tsx | 19 +++++++-- app/client/src/workers/validations.ts | 40 ++++++++++++++++++- 6 files changed, 60 insertions(+), 6 deletions(-) diff --git a/app/client/src/components/propertyControls/LocationSearchControl.tsx b/app/client/src/components/propertyControls/LocationSearchControl.tsx index 52f3e27847..89d6178ab4 100644 --- a/app/client/src/components/propertyControls/LocationSearchControl.tsx +++ b/app/client/src/components/propertyControls/LocationSearchControl.tsx @@ -76,6 +76,7 @@ const MapScriptWrapper = (props: MapScriptWrapperProps) => { AddScriptTo.HEAD, ); const [title, setTitle] = useState(""); + return (
{status === ScriptStatus.READY && ( @@ -89,7 +90,7 @@ const MapScriptWrapper = (props: MapScriptWrapperProps) => { { const val = ev.target.value; if (val === "") { diff --git a/app/client/src/constants/FieldExpectedValue.ts b/app/client/src/constants/FieldExpectedValue.ts index 854b13b78b..a41adfe2d1 100644 --- a/app/client/src/constants/FieldExpectedValue.ts +++ b/app/client/src/constants/FieldExpectedValue.ts @@ -99,6 +99,7 @@ const FIELD_VALUES: Record< // onClick: "Function Call", }, MAP_WIDGET: { + mapCenter: "{ lat: number, long: number }", defaultMarkers: "Array<{ lat: number, long: number }>", enableSearch: "boolean", enablePickLocation: "boolean", diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx index 31eea37b1a..3cc4e8cef1 100644 --- a/app/client/src/constants/WidgetConstants.tsx +++ b/app/client/src/constants/WidgetConstants.tsx @@ -88,3 +88,5 @@ export const MAIN_CONTAINER_WIDGET_ID = "0"; export const MAIN_CONTAINER_WIDGET_NAME = "MainContainer"; export const WIDGET_DELETE_UNDO_TIMEOUT = 7000; + +export const DEFAULT_CENTER = { lat: -34.397, lng: 150.644 }; diff --git a/app/client/src/constants/WidgetValidation.ts b/app/client/src/constants/WidgetValidation.ts index 29ea489338..3193be57fd 100644 --- a/app/client/src/constants/WidgetValidation.ts +++ b/app/client/src/constants/WidgetValidation.ts @@ -22,6 +22,7 @@ export const VALIDATION_TYPES = { SELECTED_TAB: "SELECTED_TAB", DEFAULT_OPTION_VALUE: "DEFAULT_OPTION_VALUE", DEFAULT_SELECTED_ROW: "DEFAULT_SELECTED_ROW", + LAT_LONG: "LAT_LONG", }; export type ValidationResponse = { diff --git a/app/client/src/widgets/MapWidget.tsx b/app/client/src/widgets/MapWidget.tsx index a4ba60ffcb..ba35a190a5 100644 --- a/app/client/src/widgets/MapWidget.tsx +++ b/app/client/src/widgets/MapWidget.tsx @@ -10,6 +10,7 @@ import { getAppsmithConfigs } from "configs"; import styled from "styled-components"; import * as Sentry from "@sentry/react"; import withMeta, { WithMeta } from "./MetaHOC"; +import { DEFAULT_CENTER } from "constants/WidgetConstants"; const { google } = getAppsmithConfigs(); @@ -29,7 +30,13 @@ const DisabledContainer = styled.div` } `; -const DefaultCenter = { lat: -34.397, long: 150.644 }; +const DefaultCenter = { ...DEFAULT_CENTER, long: DEFAULT_CENTER.lng }; + +type Center = { + lat: number; + long: number; + [x: string]: any; +}; class MapWidget extends BaseWidget { static getPropertyValidationMap(): WidgetPropertyValidationType { return { @@ -41,7 +48,7 @@ class MapWidget extends BaseWidget { enableCreateMarker: VALIDATION_TYPES.BOOLEAN, allowZoom: VALIDATION_TYPES.BOOLEAN, zoomLevel: VALIDATION_TYPES.NUMBER, - mapCenter: VALIDATION_TYPES.OBJECT, + mapCenter: VALIDATION_TYPES.LAT_LONG, }; } @@ -121,6 +128,10 @@ class MapWidget extends BaseWidget { }); }; + getCenter(): Center { + return this.props.center || this.props.mapCenter || DefaultCenter; + } + getPageView() { return ( <> @@ -148,7 +159,7 @@ class MapWidget extends BaseWidget { isVisible={this.props.isVisible} zoomLevel={this.props.zoomLevel} allowZoom={this.props.allowZoom} - center={this.props.center || this.props.mapCenter || DefaultCenter} + center={this.getCenter()} enableCreateMarker={this.props.enableCreateMarker} selectedMarker={this.props.selectedMarker} updateCenter={this.updateCenter} @@ -159,7 +170,7 @@ class MapWidget extends BaseWidget { updateMarker={this.updateMarker} selectMarker={this.onMarkerClick} unselectMarker={this.unselectMarker} - markers={this.props.markers || []} + markers={this.props.markers} enableDrag={() => { this.disableDrag(false); }} diff --git a/app/client/src/workers/validations.ts b/app/client/src/workers/validations.ts index 10bfbfe418..9b8060627e 100644 --- a/app/client/src/workers/validations.ts +++ b/app/client/src/workers/validations.ts @@ -326,7 +326,12 @@ export const VALIDATORS: Record = { parsed, message: `${WIDGET_TYPE_VALIDATION_ERROR}: Marker Data`, }; - } else if (!every(parsed, (datum) => isObject(datum))) { + } else if ( + !every( + parsed, + (datum) => VALIDATORS[VALIDATION_TYPES.LAT_LONG](datum, props).isValid, + ) + ) { return { isValid: false, parsed: [], @@ -643,4 +648,37 @@ export const VALIDATORS: Record = { parsed: values, }; }, + [VALIDATION_TYPES.LAT_LONG]: (unparsedValue: { + lat?: number; + long?: number; + [x: string]: any; + }): ValidationResponse => { + let value = unparsedValue; + const invalidResponse = { + isValid: false, + parsed: undefined, + message: `${WIDGET_TYPE_VALIDATION_ERROR}: { lat: number, long: number }`, + }; + + if (isString(unparsedValue)) { + try { + value = JSON.parse(unparsedValue); + } catch (e) { + console.error(`Error when parsing string as object`); + } + } + + const { lat, long } = value || {}; + const validLat = typeof lat === "number" && lat <= 90 && lat >= -90; + const validLong = typeof long === "number" && long <= 180 && long >= -180; + + if (!validLat || !validLong) { + return invalidResponse; + } + + return { + isValid: true, + parsed: value, + }; + }, };