Skip to content

Add location search and improve map interaction#11

Open
swhitt wants to merge 1 commit into
JustDr00py:mainfrom
swhitt:gui-improvements
Open

Add location search and improve map interaction#11
swhitt wants to merge 1 commit into
JustDr00py:mainfrom
swhitt:gui-improvements

Conversation

@swhitt
Copy link
Copy Markdown

@swhitt swhitt commented Dec 28, 2025

  • Location search box using Nominatim - type a place, hit enter
  • Changed selection to Shift+drag so you can still pan the map normally
  • Added gui.py to serve the map in a browser (just run python gui.py)

- Add location search using Nominatim geocoding API
- Change area selection to Shift+drag (allows normal map panning)
- Add gui.py helper script to launch GUI in browser
@qodo-code-review
Copy link
Copy Markdown

PR Compliance Guide 🔍

Below is a summary of compliance checks for this PR:

Security Compliance
🔴
Unintended file exposure

Description: The GUI launcher binds socketserver.TCPServer(("", PORT), Handler) to all network
interfaces and serves files via SimpleHTTPRequestHandler, which can unintentionally expose
maps.html and any other files in the script directory to other machines on the same
network (e.g., anyone who can reach :8000), enabling unauthorized access to local content.

gui.py [24-25]

Referred Code
with socketserver.TCPServer(("", PORT), Handler) as httpd:
    url = f"http://localhost:{PORT}/maps.html"
Ticket Compliance
🎫 No ticket provided
  • Create ticket/issue
Codebase Duplication Compliance
Codebase context is not defined

Follow the guide to enable codebase context checks.

Custom Compliance
🟢
Generic: Comprehensive Audit Trails

Objective: To create a detailed and reliable record of critical system actions for security analysis
and compliance.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Meaningful Naming and Self-Documenting Code

Objective: Ensure all identifiers clearly express their purpose and intent, making code
self-documenting

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Logging Practices

Objective: To ensure logs are useful for debugging and auditing without exposing sensitive
information like PII, PHI, or cardholder data.

Status: Passed

Learn more about managing compliance generic rules or creating your own custom rules

🔴
Generic: Robust Error Handling and Edge Case Management

Objective: Ensure comprehensive error handling that provides meaningful context and graceful
degradation

Status:
Missing fetch checks: searchLocation() does not check response.ok or handle non-JSON/timeout cases before
calling response.json(), which can lead to confusing failures and poor degradation.

Referred Code
try {
    const response = await fetch(
        `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=1`
    );
    const data = await response.json();

    if (!data || data.length === 0) {
        status.textContent = 'Location not found';
        return;
    }

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Secure Error Handling

Objective: To prevent the leakage of sensitive system information through error messages while
providing sufficient detail for internal debugging.

Status:
Leaks error details: The UI displays raw exception text via status.textContent = 'Search failed: ' +
err.message, potentially exposing internal/network error details to end users.

Referred Code
} catch (err) {
    status.textContent = 'Search failed: ' + err.message;
}

Learn more about managing compliance generic rules or creating your own custom rules

Generic: Security-First Input Validation and Data Handling

Objective: Ensure all data inputs are validated, sanitized, and handled securely to prevent
vulnerabilities

Status:
External request policy: The new client-side call to the Nominatim endpoint sends user-provided queries to a third
party without visible consent/configuration or documented usage constraints, which may
violate required security/privacy or third-party API usage policies depending on project
requirements.

Referred Code
async function searchLocation() {
    const query = document.getElementById('searchInput').value.trim();
    const status = document.getElementById('searchStatus');

    if (!query) {
        status.textContent = 'Enter a location to search';
        return;
    }

    status.textContent = 'Searching...';

    try {
        const response = await fetch(
            `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=1`
        );

Learn more about managing compliance generic rules or creating your own custom rules

Compliance status legend 🟢 - Fully Compliant
🟡 - Partial Compliant
🔴 - Not Compliant
⚪ - Requires Further Human Verification
🏷️ - Compliance label

@qodo-code-review
Copy link
Copy Markdown

PR Code Suggestions ✨

Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
High-level
Address reliance on public Nominatim API

The hardcoded dependency on the public Nominatim API is risky due to its strict
usage policy and rate limits. To ensure stability, the suggestion recommends
making the geocoding endpoint configurable or documenting the API's limitations.

Examples:

maps.html [624-626]
                const response = await fetch(
                    `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=1`
                );

Solution Walkthrough:

Before:

// maps.html

async function searchLocation() {
    const query = document.getElementById('searchInput').value.trim();
    // ...
    try {
        const response = await fetch(
            `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=1`
        );
        const data = await response.json();
        // ...
    } catch (err) {
        // ...
    }
}

After:

// maps.html

// Endpoint could be defined at the top of the script or in a config object
const NOMINATIM_ENDPOINT = "https://nominatim.openstreetmap.org/search";

async function searchLocation() {
    const query = document.getElementById('searchInput').value.trim();
    // ...
    try {
        const response = await fetch(
            `${NOMINATIM_ENDPOINT}?q=${encodeURIComponent(query)}&format=json&limit=1`
        );
        const data = await response.json();
        // ...
    } catch (err) {
        // ...
    }
}
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a critical dependency on a public API with a strict usage policy, which could render the new search feature unreliable or non-functional under moderate use, thus impacting the tool's long-term stability.

Medium
General
Add User-Agent header and HTTP status check

Add a User-Agent header to the fetch request to comply with Nominatim API policy
and check response.ok to handle HTTP errors.

maps.html [624-626]

 const response = await fetch(
-                    `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=1`
-                );
+    `https://nominatim.openstreetmap.org/search?q=${encodeURIComponent(query)}&format=json&limit=1`,
+    {
+        headers: {
+            'User-Agent': 'MeshtasticTileGenerator/1.0 (+https://example.com)'
+        }
+    }
+);
+if (!response.ok) {
+    throw new Error(`HTTP error! Status: ${response.status}`);
+}
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: The suggestion correctly adds a User-Agent header, which is required by the Nominatim API policy, and also includes essential HTTP error handling, making the API call more robust and compliant.

Medium
Simplify signal handling for graceful shutdown

Remove the custom SIGINT signal handler and rely on the try...except
KeyboardInterrupt block for a graceful server shutdown.

gui.py [33-39]

 # Handle Ctrl+C gracefully
-signal.signal(signal.SIGINT, lambda *_: sys.exit(0))
-
 try:
     httpd.serve_forever()
 except KeyboardInterrupt:
     pass
  • Apply / Chat
Suggestion importance[1-10]: 7

__

Why: The suggestion correctly identifies that sys.exit(0) prevents a graceful shutdown and proposes removing the redundant signal handler, which is the standard and correct way to handle this.

Medium
Enable address reuse

Set socketserver.TCPServer.allow_reuse_address = True to allow the server to be
restarted immediately without "Address already in use" errors.

gui.py [24]

+socketserver.TCPServer.allow_reuse_address = True
 with socketserver.TCPServer(("", PORT), Handler) as httpd:
  • Apply / Chat
Suggestion importance[1-10]: 6

__

Why: This is a valuable improvement that prevents common "Address already in use" errors during development by allowing the server to restart quickly, enhancing the developer experience.

Low
Possible issue
Prevent crash if API response is missing data

Add a check to ensure result.boundingbox exists before accessing it to prevent a
potential crash if the API response is missing this data.

maps.html [634-639]

 const result = data[0];
+if (!result.boundingbox) {
+    status.textContent = 'Could not determine area for this location.';
+    return;
+}
 const bbox = result.boundingbox; // [south, north, west, east]
 const south = parseFloat(bbox[0]);
 const north = parseFloat(bbox[1]);
 const west = parseFloat(bbox[2]);
 const east = parseFloat(bbox[3]);
  • Apply / Chat
Suggestion importance[1-10]: 8

__

Why: This suggestion correctly identifies a potential crash if the API response is valid but lacks a boundingbox, and it provides a robust check to prevent it, improving application stability.

Medium
  • More

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant