Metadata-Version: 2.3
Name: smoothglue_django_map
Version: 1.1.0
Summary: Enhance your development with SmoothGlue™, Map component for providing backend related map APIs.
License: Proprietary
Keywords: Interoperability,API Integration,Edge Computing,Application Framework,Data-Driven Development,Map
Author: SmoothGlue
Maintainer: BrainGu
Maintainer-email: smoothglue@braingu.com
Requires-Python: >= 3.12
Classifier: License :: Other/Proprietary License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Requires-Dist: django (>=3.2)
Requires-Dist: smoothglue-django-core (>=1.5.3,<2.0.0)
Project-URL: Homepage, https://braingu.com/solutions/smoothglue/
Description-Content-Type: text/markdown

# SmoothGlue Django Map

A Django app that provides admin-configurable REST APIs for map imagery, terrain providers, and logical entity grouping. Site admins can manage base layers, terrain sources, and group templates (e.g., "Parade Formation") available to frontend map clients without any code changes.

Designed for deployments across diverse networks, including air-gapped environments where public imagery and terrain services are unavailable. When no providers are configured, frontends fall back to Cesium's bundled NaturalEarth imagery and WGS84 Ellipsoid terrain.

## Features

- **Imagery Layers** — Configure map base-layer providers (ArcGIS, Bing, OpenStreetMap, Cesium Ion, and more) via the Django admin.
- **Terrain Layers** — Configure terrain providers (Ellipsoid, Cesium Ion, Cesium Terrain, ArcGIS, Google, VR-TheWorld) via the Django admin.
- **Entity Groups** — Group multiple map entities into logical clusters (e.g., Parade Formations) for synchronized frontend operations like multi-drag-and-drop.
- **Group Types** — Admin-configurable templates defining standardized nomenclature and iconography for entity groups.
- **Cesium Ion Support** — Both imagery and terrain layers support Ion asset IDs for loading layers through the Cesium Ion API.
- **Default Layer** — Mark one imagery layer and one terrain layer as the default. The app enforces a single default per layer type automatically.
- **Filterable REST API** — Read-only list endpoints with filtering by `is_active`, `is_default`, and `provider_type`.
- **Air-Gap Safe** — Ellipsoid terrain (WGS84) requires no network access and is the default terrain provider type.

## API Endpoints

| Endpoint                      | Description                                          |
| ----------------------------- | ---------------------------------------------------- |
| `GET /image-layers/`          | List active imagery layers                           |
| `GET /terrain-layers/`        | List active terrain layers                           |
| `GET /entity-group-types/`    | List active group templates                          |
| `GET /entity-groups/`         | List active entity groups                            |
| `POST /entity-groups/`        | Create a new entity group                            |
| `DELETE /entity-groups/<id>/` | Dissolve an entity group (keeps underlying entities) |

List endpoints support query parameters for filtering:

```
GET /image-layers/?is_default=true
GET /terrain-layers/?provider_type=Cesium+Ion
GET /entity-group-types/?is_active=true
```

### Response Example

```json
{
  "id": "e6227ca5-9e8a-4793-9e63-d8ffa6e858b7",
  "name": "World Imagery",
  "url": "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer",
  "provider_type": "ArcGis Map Server",
  "ion_asset_id": null,
  "sort_order": 1,
  "is_active": true,
  "is_default": true
}
```

### Orphaned Entity Cleanup (Required Integration)

Because `EntityGroup` models map generic entities from consuming applications by storing their IDs in a `JSONField`, the database cannot rely on standard foreign key `CASCADE` deletions. If an entity is deleted in your consuming application, its ID will become orphaned inside the map group, potentially causing frontend mapping errors.

To prevent this, the package exports a cleanup utility: `remove_entities_from_groups`. You should trigger this utility inside your app's DRF ViewSet or via a Django post_delete signal whenever a mappable entity is destroyed.

Example using a DRF ViewSet:

```Python
from rest_framework import viewsets
from smoothglue.map.utils.entity_group import remove_entities_from_groups

class MyAppEntityViewSet(viewsets.ModelViewSet):
    # ... queryset and serializer ...

    def perform_destroy(self, instance):
        # 1. Clean up the map package groups first
        remove_entities_from_groups(instance.id, auto_dissolve=True)

        # 2. Execute standard deletion
        super().perform_destroy(instance)
```

(Note: auto_dissolve=True automatically deletes any map group that falls below 2 members after the cleanup).

## Installation

### Install the Package

```bash
pip install smoothglue-django-map
```

### Configure Django

Add the app to `INSTALLED_APPS` in your `settings.py`:

```python
INSTALLED_APPS = [
    "smoothglue.map",
    ...,
]
```

Include the URL routes in your `urls.py`:

```python
urlpatterns = [
    path("", include("smoothglue.map.urls")),
    ...,
]
```

Run migrations:

```bash
python manage.py migrate
```

Optionally load the bundled fixtures to seed default imagery and terrain layers:

```bash
python manage.py loaddata imagerylayer
python manage.py loaddata terrainlayer
```

## Development

### Set Up Virtual Environment

This project uses [Poetry](https://python-poetry.org/) for dependency management.

1. Install Poetry if you haven't already.
2. Run `poetry install` to create a virtual environment and install dependencies.

### Management Commands

- **makemigrations.py** — Generate migrations for the `map` app.
- **migrate.py** — Apply pending migrations.
- **loadtests.py** — Run all tests (`python3.12 loadtests.py`).
- **loaddata.py** — Load fixture data (`python3.12 loaddata.py smoothglue/map/fixtures/imagerylayer.json`).
- **djangoshell.py** — Open a Django shell aware of the app.
- **boot_django.py** — Bootstraps a standalone Django environment via `settings.configure()`. Used by the other scripts.

### Building

```bash
poetry build
```

This creates source and wheel distributions in the `dist/` directory.

