import type { ValidationState } from '../../common/static-wrappers/interfaces/validation-interface'; import type { GeoJSON } from './../../data/geo'; import { Prop, toNative } from 'vue-facing-decorator'; import PowerduckState from '../../app/powerduck-state'; import TsxComponent, { Component } from '../../app/vuetsx'; import BoundingBox from '../../data/bounding-box'; import FlexContainer from '../form/flex-container'; import FlexFormItem from '../form/form-item-flex'; import FormItemWrapper from '../form/form-item-wrapper'; import OpenStreetMap from '../open-street-map/open-street-map'; import GeoJsonEditor from './geo-json'; import NumericInput, { NumericInputMode } from './numeric-input'; interface GpsInputArgs { gpsModel: { latitude: number; longitude: number; geoJSON?: GeoJSON }; hasGeoJsonInput?: boolean; mandatory?: boolean; showClearValueButton?: boolean; validationStateLatitude: ValidationState; validationStateLongitude: ValidationState; disabled?: boolean; } @Component class GpsInputComponent extends TsxComponent implements GpsInputArgs { @Prop() gpsModel: { latitude: number; longitude: number; geoJSON?: GeoJSON }; @Prop() hasGeoJsonInput?: boolean; @Prop() mandatory?: boolean = true; @Prop() showClearValueButton!: boolean; @Prop() validationStateLatitude: ValidationState; @Prop() validationStateLongitude: ValidationState; @Prop() disabled?: boolean; handleMapInitComplete(leaflet) { leaflet?.on('contextmenu', (e) => { if (this.disabled) { return; } const coord = e.latlng; // QA_AT-11: Leaflet emits ~15-decimal floats. Round BOTH axes to 6 // decimals at the point of the model write so the bound NumericInputs // display and store exactly 6 decimals IMMEDIATELY — this map // right-click path bypasses both the NumericInput typing-time clamp // (DOM onInput only) and the `changed`-callback blur-time round. this.gpsModel.latitude = BoundingBox.roundCoord(coord.lat); this.gpsModel.longitude = BoundingBox.roundCoord(coord.lng); this.$nextTick(() => { this.$forceUpdate(); }); }); } render(h) { return (
{ // QA_AT-24: NumericInput string-truncates while typing // (via maxDecimals={6}). QA_AT-11: route the blur-time round // through the shared `BoundingBox.roundCoord` (same 6-dec // rule as the map-click path above and the server's // GpsHelper.roundCoord) — defence-in-depth for non-input // paths (programmatic centroid prefills, paste). this.gpsModel.latitude = BoundingBox.roundCoord(e); }} /> { // QA_AT-24 / QA_AT-11: see latitude comment — same shared // `BoundingBox.roundCoord` 6-decimal net. this.gpsModel.longitude = BoundingBox.roundCoord(e); }} /> {this.hasGeoJsonInput && ( { this.gpsModel.geoJSON = e; }} /> )}
{ this.handleMapInitComplete(map); }} />
); } } const GpsInput = toNative(GpsInputComponent); export default GpsInput;