update importhub to support rooms and projects
This commit is contained in:
parent
a1ef8716f6
commit
99b16512e6
1 changed files with 28 additions and 9 deletions
|
@ -1,9 +1,11 @@
|
||||||
import hashlib
|
import hashlib
|
||||||
|
from typing import Literal, Optional
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.management.base import BaseCommand
|
from django.core.management.base import BaseCommand
|
||||||
|
from django.utils.text import slugify
|
||||||
from pydantic import BaseModel, Field, PositiveInt
|
from pydantic import BaseModel, Field, PositiveInt
|
||||||
from shapely import Point
|
from shapely import Point
|
||||||
from shapely.geometry import shape
|
from shapely.geometry import shape
|
||||||
|
@ -11,6 +13,7 @@ from shapely.geometry import shape
|
||||||
from c3nav.api.utils import NonEmptyStr
|
from c3nav.api.utils import NonEmptyStr
|
||||||
from c3nav.mapdata.models import Area, LocationGroup, LocationSlug, MapUpdate, Space
|
from c3nav.mapdata.models import Area, LocationGroup, LocationSlug, MapUpdate, Space
|
||||||
from c3nav.mapdata.models.geometry.space import POI
|
from c3nav.mapdata.models.geometry.space import POI
|
||||||
|
from c3nav.mapdata.models.locations import LocationRedirect
|
||||||
from c3nav.mapdata.models.report import Report
|
from c3nav.mapdata.models.report import Report
|
||||||
from c3nav.mapdata.utils.cache.changes import changed_geometries
|
from c3nav.mapdata.utils.cache.changes import changed_geometries
|
||||||
|
|
||||||
|
@ -22,15 +25,15 @@ class HubImportItem(BaseModel):
|
||||||
type: NonEmptyStr
|
type: NonEmptyStr
|
||||||
id: UUID
|
id: UUID
|
||||||
slug: NonEmptyStr = Field(pattern=r'^[-a-zA-Z0-9_]+$')
|
slug: NonEmptyStr = Field(pattern=r'^[-a-zA-Z0-9_]+$')
|
||||||
name: NonEmptyStr | dict[NonEmptyStr, NonEmptyStr]
|
name: NonEmptyStr | dict[NonEmptyStr, NonEmptyStr] = None
|
||||||
is_official: bool
|
is_official: bool = False
|
||||||
description: dict[NonEmptyStr, NonEmptyStr | None]
|
description: dict[NonEmptyStr, str | None]
|
||||||
public_url: NonEmptyStr = Field(pattern=r'^https://')
|
public_url: NonEmptyStr = Field(pattern=r'^https://')
|
||||||
parent_id: UUID | None
|
parent_id: UUID | None = None
|
||||||
children: list[NonEmptyStr] | None
|
children: list[NonEmptyStr] | None = []
|
||||||
floor: PositiveInt | None
|
floor: PositiveInt | None
|
||||||
location: tuple[float, float] | None
|
location: tuple[float, float] | None
|
||||||
polygons: tuple[list[tuple[float, float]]] | None
|
polygons: tuple[list[tuple[float, float]]] | None = None
|
||||||
|
|
||||||
|
|
||||||
class Command(BaseCommand):
|
class Command(BaseCommand):
|
||||||
|
@ -56,7 +59,8 @@ class Command(BaseCommand):
|
||||||
report.notify_reviewers()
|
report.notify_reviewers()
|
||||||
|
|
||||||
def do_import(self, data):
|
def do_import(self, data):
|
||||||
items: list[HubImportItem] = [HubImportItem.model_validate(item) for item in data if item["type"] == "assembly"]
|
items: list[HubImportItem] = [HubImportItem.model_validate(item) for item in data
|
||||||
|
if item["type"] in ("assembly", "room", "project")]
|
||||||
items_by_id = {item.id: item for item in items}
|
items_by_id = {item.id: item for item in items}
|
||||||
|
|
||||||
spaces_for_level = {}
|
spaces_for_level = {}
|
||||||
|
@ -76,6 +80,9 @@ class Command(BaseCommand):
|
||||||
for item in items:
|
for item in items:
|
||||||
item.slug = item.slug.lower().replace('_', '-')
|
item.slug = item.slug.lower().replace('_', '-')
|
||||||
|
|
||||||
|
if item.type == "project":
|
||||||
|
item.polygons = None
|
||||||
|
|
||||||
if item.polygons is None and item.location is None:
|
if item.polygons is None and item.location is None:
|
||||||
print(f"SKIPPING: {item.slug} / {item.id} has no polygon or location")
|
print(f"SKIPPING: {item.slug} / {item.id} has no polygon or location")
|
||||||
continue
|
continue
|
||||||
|
@ -84,6 +91,10 @@ class Command(BaseCommand):
|
||||||
print(f"SKIPPING: {item.slug} / {item.id} has no floor")
|
print(f"SKIPPING: {item.slug} / {item.id} has no floor")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
if item.is_official:
|
||||||
|
print(f"SKIPPING: {item.slug} / {item.id} because it is official")
|
||||||
|
continue
|
||||||
|
|
||||||
import_tag = f"hub:{item.id}"
|
import_tag = f"hub:{item.id}"
|
||||||
|
|
||||||
# determine geometry
|
# determine geometry
|
||||||
|
@ -125,9 +136,15 @@ class Command(BaseCommand):
|
||||||
result = locations_so_far.pop(import_tag, None)
|
result = locations_so_far.pop(import_tag, None)
|
||||||
result: Area | POI | None
|
result: Area | POI | None
|
||||||
|
|
||||||
old_result = None
|
old_result = None # only used if the type needs to be changed
|
||||||
|
|
||||||
if result is not None:
|
if result is None:
|
||||||
|
occupied_by = LocationSlug.objects.filter(slug=item.id).first()
|
||||||
|
if occupied_by:
|
||||||
|
print(f"SKIPPING (nonexisting): {item.slug} / {item.id} UUID already occupied by {occupied_by.get_child()}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif result is not None:
|
||||||
# already exists
|
# already exists
|
||||||
if not isinstance(result, target_type):
|
if not isinstance(result, target_type):
|
||||||
# need to change from POI to Area or inverted
|
# need to change from POI to Area or inverted
|
||||||
|
@ -313,6 +330,8 @@ class Command(BaseCommand):
|
||||||
result.groups.set(old_group_ids)
|
result.groups.set(old_group_ids)
|
||||||
for slug in old_redirect_slugs:
|
for slug in old_redirect_slugs:
|
||||||
result.redirects.create(slug=slug)
|
result.redirects.create(slug=slug)
|
||||||
|
if not result.redirects.filter(slug=item.id).exists():
|
||||||
|
result.redirects.create(slug=item.id)
|
||||||
if is_new:
|
if is_new:
|
||||||
result.groups.set(new_group_ids)
|
result.groups.set(new_group_ids)
|
||||||
else:
|
else:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue