diff --git a/FetchLatLong/config.json b/FetchLatLong/config.json new file mode 100644 index 0000000..783d28f --- /dev/null +++ b/FetchLatLong/config.json @@ -0,0 +1,3 @@ +{ + "exampleConfigProperty": "test" +} diff --git a/FetchLatLong/icon.svg b/FetchLatLong/icon.svg new file mode 100644 index 0000000..6825ccc --- /dev/null +++ b/FetchLatLong/icon.svg @@ -0,0 +1,17 @@ + + + + + + + + + \ No newline at end of file diff --git a/FetchLatLong/manifest.json b/FetchLatLong/manifest.json new file mode 100644 index 0000000..78c5efa --- /dev/null +++ b/FetchLatLong/manifest.json @@ -0,0 +1,31 @@ +{ + "name": "FetchLatLong", + "label": "FetchLatLong", + "type": "widget", + "version": "1.16.0", + "exbVersion": "1.16.0", + "author": "Esri R&D Center Beijing", + "description": "This is a barebones, simple widget. It includes an example of how to use the config file, and it includes a placeholder SVG icon. It intentionally does not include the following so you can use this to start from scratch: i18n translations, a Settings panel, unit tests. See the documentation for more information on how to implement these features.", + "copyright": "", + "license": "http://www.apache.org/licenses/LICENSE-2.0", + "properties": { + "hasSettingPage": false, + "useMapWidget": true + }, + "widgets": [ + { + "uri": "FetchLatLong", + "label": "FetchLatLong", + "thumbnail": "thumbnail.png", + "description": "Select the lat long." + } + ], + "framework": "react", + "translatedLocales": ["en"], + "dataSources": [], + "elements": [] +} + + + + diff --git a/FetchLatLong/src/config.ts b/FetchLatLong/src/config.ts new file mode 100644 index 0000000..780aacf --- /dev/null +++ b/FetchLatLong/src/config.ts @@ -0,0 +1,7 @@ +import { type ImmutableObject } from 'seamless-immutable' + +export interface Config { + exampleConfigProperty: string +} + +export type IMConfig = ImmutableObject diff --git a/FetchLatLong/src/runtime/widget.tsx b/FetchLatLong/src/runtime/widget.tsx new file mode 100644 index 0000000..fbfa6f4 --- /dev/null +++ b/FetchLatLong/src/runtime/widget.tsx @@ -0,0 +1,85 @@ +/** @jsx jsx */ +import { React, jsx, AllWidgetProps } from 'jimu-core' +import { TextInput } from 'jimu-ui' +import { JimuMapViewComponent, JimuMapView } from 'jimu-arcgis' +import Point from 'esri/geometry/Point' +import { throttle } from 'lodash' + +interface State { + latitude: string + longitude: string + scale: number + zoom: number + mapViewReady: boolean +} + +export default class GetLatLongWidget extends React.PureComponent, State> { + mapView: __esri.MapView = null + + constructor(props: AllWidgetProps) { + super(props) + this.state = { + latitude: '', + longitude: '', + scale: 0, + zoom: 0, + mapViewReady: false + } + } + + activeViewChangeHandler = (jimuMapView: JimuMapView) => { + if (jimuMapView) { + this.mapView = jimuMapView.view as __esri.MapView + + // Update when extent changes (zoom, pan) + this.mapView.watch('extent', () => { + this.setCenterState() + }) + + // Pointer move with throttling + this.mapView.on('pointer-move', throttle((evt) => { + const point: Point = this.mapView.toMap({ x: evt.x, y: evt.y }) + if (point) { + this.setCenterState(point) + } + }, 300)) + } + } + + setCenterState = (point?: Point) => { + const centerPoint = point || this.mapView?.center + if (!centerPoint) return + + this.setState({ + latitude: centerPoint.latitude.toFixed(5), + longitude: centerPoint.longitude.toFixed(5), + scale: Math.round(this.mapView.scale), + zoom: this.mapView.zoom, + mapViewReady: true + }) + } + + render() { + const { latitude, longitude, scale, zoom, mapViewReady } = this.state + + return ( +
+ + +
+ + + + + +
+ {mapViewReady ? 'Map View Ready' : 'Waiting for Map Interaction...'} +
+
+
+ ) + } +} diff --git a/FetchLatLong/src/styles.css b/FetchLatLong/src/styles.css new file mode 100644 index 0000000..7a2f66a --- /dev/null +++ b/FetchLatLong/src/styles.css @@ -0,0 +1,24 @@ +.widget-container { + padding: 15px; + background: white; + border-radius: 8px; + box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); + } + + h3 { + font-size: 18px; + margin-bottom: 10px; + } + + .export-button { + margin-top: 10px; + background-color: #0078d4; + color: white; + } + + .table-container { + max-height: 400px; + overflow-y: auto; + border: 1px solid #ddd; + } + \ No newline at end of file diff --git a/FetchLatLong/tests/simple-widget.test.tsx b/FetchLatLong/tests/simple-widget.test.tsx new file mode 100644 index 0000000..e2573e0 --- /dev/null +++ b/FetchLatLong/tests/simple-widget.test.tsx @@ -0,0 +1,14 @@ +import { React } from 'jimu-core' +import _Widget from '../src/runtime/widget' +import { widgetRender, wrapWidget } from 'jimu-for-test' + +const render = widgetRender() +describe('test simple widget', () => { + it('simple test', () => { + const Widget = wrapWidget(_Widget, { + config: { exampleConfigProperty: 'a' } + }) + const { queryByText } = render() + expect(queryByText('exampleConfigProperty: a').tagName).toBe('P') + }) +})