diff --git a/museum_map/server/api/__init__.py b/museum_map/server/api/__init__.py index abccde3..2177c70 100644 --- a/museum_map/server/api/__init__.py +++ b/museum_map/server/api/__init__.py @@ -8,12 +8,13 @@ from museum_map.__about__ import __tables__, __version__ from museum_map.models import db_session -from museum_map.server.api import floor_topics, floors, picks, rooms +from museum_map.server.api import floor_topics, floors, items, picks, rooms logger = logging.getLogger(__name__) router = APIRouter(prefix="/api") router.include_router(floors.router) router.include_router(floor_topics.router) +router.include_router(items.router) router.include_router(picks.router) router.include_router(rooms.router) diff --git a/museum_map/server/api/floors.py b/museum_map/server/api/floors.py index 0ee5ae9..fb83f87 100644 --- a/museum_map/server/api/floors.py +++ b/museum_map/server/api/floors.py @@ -18,6 +18,7 @@ async def get_floors(dbsession: Annotated[AsyncSession, Depends(db_session)]): """Retrieve all floors.""" query = ( select(Floor) + .order_by(Floor.level) .options(selectinload(Floor.rooms)) .options(selectinload(Floor.samples)) .options(selectinload(Floor.topics)) diff --git a/museum_map/server/api/items.py b/museum_map/server/api/items.py new file mode 100644 index 0000000..d12004e --- /dev/null +++ b/museum_map/server/api/items.py @@ -0,0 +1,23 @@ +"""Routes for accessing the item data.""" +import logging +from typing import Annotated + +from fastapi import APIRouter, Depends, Query +from sqlalchemy import select +from sqlalchemy.ext.asyncio import AsyncSession +from sqlalchemy.orm import selectinload + +from museum_map.models import Item, ItemModel, db_session + +router = APIRouter(prefix="/items") +logger = logging.getLogger(__name__) + + +@router.get("/", response_model=list[ItemModel]) +async def get_items( + iid: Annotated[list[int] | None, Query()], + dbsession: Annotated[AsyncSession, Depends(db_session)], +): + """Retrieve items.""" + query = select(Item).filter(Item.id.in_(iid)).options(selectinload(Item.group)).options(selectinload(Item.room)) + return (await dbsession.execute(query)).scalars() diff --git a/museum_map/server/api/rooms.py b/museum_map/server/api/rooms.py index c40eb9a..1c44974 100644 --- a/museum_map/server/api/rooms.py +++ b/museum_map/server/api/rooms.py @@ -14,10 +14,10 @@ @router.get("/", response_model=list[RoomModel]) -async def get_floors( +async def get_rooms( dbsession: Annotated[AsyncSession, Depends(db_session)], rid: Annotated[list[int] | None, Query()] = None ): - """Retrieve all floors.""" + """Retrieve rooms.""" query = ( select(Room) .options(selectinload(Room.group)) diff --git a/museum_map/server/frontend/src/routes/Floor.svelte b/museum_map/server/frontend/src/routes/Floor.svelte index bfd564d..9699b92 100644 --- a/museum_map/server/frontend/src/routes/Floor.svelte +++ b/museum_map/server/frontend/src/routes/Floor.svelte @@ -9,11 +9,11 @@ import Thumbnail from "../components/Thumbnail.svelte"; import { floors, - fetchRooms, - busyCounter, + floorTopics, + currentFloor, + rooms, + currentRooms, localPreferences, - loadTopics, - loadItems, matchingFloors, matchingRooms, tracker, @@ -41,7 +41,7 @@ class FloorScene extends Phaser.Scene { floor: Floor; - roomObjects: MapObject[]; + roomObjects: MapObject[] = []; baseMap: Phaser.GameObjects.Image; zoom: number; cameraPosition: { x: number; y: number }; @@ -60,7 +60,7 @@ this.zoom = 1; this.baseMap = this.add.image(0, 0, "basemap"); this.baseMap.setOrigin(0, 0); - loadRooms(this.floor.rooms).then((rooms) => { + /*loadRooms(this.floor.rooms).then((rooms) => { busyCounter.start(); $matchingRooms = get(matchingRooms); for (let room of rooms) { @@ -126,7 +126,7 @@ } this.scaleObjects(false, false); busyCounter.stop(); - }); + });*/ this.cameraPosition = { x: -this.game.canvas.width / 2 + this.baseMap.width / 2, @@ -393,6 +393,7 @@ let game: Phaser.Game | null = null; + /* const currentFloor = derived( [location, floors], ([location, floors]) => { @@ -409,12 +410,12 @@ return null; }, null - ); + );*/ const previousFloor = derived( [currentFloor, floors], ([currentFloor, floors]) => { - if (currentFloor) { + if (currentFloor && floors) { let previousFloor = null; for (const floor of floors) { if (floor === currentFloor) { @@ -431,7 +432,7 @@ const nextFloor = derived( [currentFloor, floors], ([currentFloor, floors]) => { - if (currentFloor) { + if (currentFloor && floors) { let found = false; for (const floor of floors) { if (found) { @@ -447,9 +448,65 @@ } } ); + // The floor topics as a floor.id -> topic dictionary + const topicsDict = derived( + floorTopics, + (floorTopics) => { + if (floorTopics) { + tick().then(() => { + if (floorListElement) { + const currentElement = floorListElement.querySelector( + ".current-floor" + ) as HTMLElement; + if (currentElement) { + currentElement.scrollIntoView(); + } + } + }); + + const topicsDict: { [x: number]: FloorTopic[] } = {}; + for (let floorTopic of floorTopics) { + if (topicsDict[floorTopic.floor]) { + topicsDict[floorTopic.floor].push(floorTopic); + } else { + topicsDict[floorTopic.floor] = [floorTopic]; + } + } + return topicsDict; + } + return {}; + }, + {} + ); + + const searchedFloors = derived( + [floors, matchingFloors], + ([floors, matchingFloors]) => { + if (floors) { + return floors.map((floor) => { + return [floor, false]; + }); + } + return []; + }, + [] + ); + + const searchedRooms = derived( + [currentRooms, matchingRooms], + ([currentRooms, matchingRooms]) => { + if (currentRooms) { + return currentRooms.map((room) => { + return [room, false]; + }); + } + return []; + }, + [] + ); const currentFloorUnsubscribe = currentFloor.subscribe((currentFloor) => { - if (currentFloor && game) { + /*if (currentFloor && game) { if (!game.scene.getScene("floor-" + currentFloor.id)) { game.scene.add( "floor-" + currentFloor.id, @@ -479,7 +536,7 @@ } }); } - } + }*/ }); const matchingRoomsUnsubscribe = matchingRooms.subscribe((matchingRooms) => { @@ -498,83 +555,6 @@ } }); - const rooms = derived( - currentFloor, - (currentFloor, set) => { - if (currentFloor) { - loadRooms(currentFloor.rooms).then((rooms) => { - set(rooms); - }); - } else { - set([]); - } - }, - [] as Room[] - ); - - const topics = derived( - floors, - (floors, set) => { - if (floors) { - let topicIds = [] as string[]; - for (const floor of floors) { - topicIds = topicIds.concat( - (floor.relationships.topics.data as JsonApiObjectReference[]).map( - (rel) => { - return rel.id; - } - ) - ); - } - loadTopics(topicIds).then((topics) => { - const topicsMap = {} as { [x: string]: JsonApiObject[] }; - for (const floor of floors) { - topicIds = ( - floor.relationships.topics.data as JsonApiObjectReference[] - ).map((rel) => { - return rel.id; - }); - topicsMap[floor.id] = topics.filter((topic) => { - return topicIds.indexOf(topic.id) >= 0; - }); - } - set(topicsMap); - if (floorListElement) { - tick().then(() => { - const currentElement = floorListElement.querySelector( - ".current-floor" - ) as HTMLElement; - if (currentElement) { - currentElement.scrollIntoView(); - } - }); - } - }); - } - }, - {} as { [x: string]: JsonApiObject[] } - ); - - const searchedFloors = derived( - [floors, matchingFloors], - ([floors, matchingFloors]) => { - return floors.map((floor: JsonApiObject) => { - return [floor, matchingFloors.indexOf(floor.id) >= 0]; - }); - }, - [] as [JsonApiObject, boolean][] - ); - - const searchedRooms = derived( - [rooms, matchingRooms], - ([rooms, matchingRooms]) => { - return rooms.map((room) => { - return [room, matchingRooms.indexOf(room.id) >= 0]; - }); - }, - [] as [JsonApiObject, boolean][] - ); - onMount(() => { document.body.addEventListener("mousemove", (ev: MouseEvent) => { mousePosition.x = ev.pageX; @@ -609,10 +589,10 @@
{ tracker.log({ action: "mouseenter", - params: { object: "previous-floor", floor: $previousFloor.id }, + params: { object: "previous-floor", floor: $previousFloor?.id }, }); }} on:mouseleave={() => { tracker.log({ action: "mouseleave", - params: { object: "previous-floor", floor: $previousFloor.id }, + params: { object: "previous-floor", floor: $previousFloor?.id }, }); }} on:focus={() => { tracker.log({ action: "focus", - params: { object: "previous-floor", floor: $previousFloor.id }, + params: { object: "previous-floor", floor: $previousFloor?.id }, }); }} on:blur={() => { tracker.log({ action: "blur", - params: { object: "previous-floor", floor: $previousFloor.id }, + params: { object: "previous-floor", floor: $previousFloor?.id }, }); - }}>⇧ {$previousFloor.attributes.label}⇧ {$previousFloor.label} {:else}   @@ -704,7 +684,7 @@ { @@ -745,17 +725,17 @@ }} > ⇒ {floor.attributes.label}⇒ {floor.label} - {#if $topics[floor.id]} - {#each $topics[floor.id] as topic} + {#if $topicsDict[floor.id]} + {#each $topicsDict[floor.id] as topic} {topic.attributes.label}{topic.label} {/each} {/if} @@ -819,7 +799,7 @@

- {$hoverRoom.attributes.label} + {$hoverRoom.label}