diff --git a/schema.graphqls b/schema.graphqls index 9c2b390..54a2de4 100644 --- a/schema.graphqls +++ b/schema.graphqls @@ -6,6 +6,7 @@ scalar DateTime type System { id: ID! name: String! + initialRegion: Region routes: [Route!] route(id: ID): Route stops: [Stop!] @@ -16,6 +17,11 @@ type System { parkingSystem: ParkingSystem } +type Region { + topLeft: Coordinates! + bottomRight: Coordinates! +} + type ParkingSystem { systemId: ID! parkingStructures: [ParkingStructure!] diff --git a/src/entities/InterchangeSystem.ts b/src/entities/InterchangeSystem.ts index 3bd7e3f..d183f23 100644 --- a/src/entities/InterchangeSystem.ts +++ b/src/entities/InterchangeSystem.ts @@ -19,6 +19,7 @@ import { InMemoryExternalSourceETARepository } from "../repositories/shuttle/eta import { ETAGetterRepository } from "../repositories/shuttle/eta/ETAGetterRepository"; import { InMemorySelfUpdatingETARepository } from "../repositories/shuttle/eta/InMemorySelfUpdatingETARepository"; import { BaseInMemoryETARepository } from "../repositories/shuttle/eta/BaseInMemoryETARepository"; +import { IRegion } from "./SharedEntities"; export interface InterchangeSystemBuilderArguments { name: string; @@ -49,6 +50,12 @@ export interface InterchangeSystemBuilderArguments { * at a stop, in latitude/longitude degrees. */ shuttleStopArrivalDegreeDelta: number; + + /** + * The initial map region to display when the app first loads + * this system. Represents a center coordinate and span. + */ + initialRegion?: IRegion; } export class InterchangeSystem { @@ -62,6 +69,7 @@ export class InterchangeSystem { public notificationRepository: NotificationRepository, public parkingTimedDataLoader: TimedApiBasedRepositoryLoader | null, public parkingRepository: ParkingGetterSetterRepository | null, + public initialRegion: IRegion | null, ) { } @@ -96,6 +104,7 @@ export class InterchangeSystem { notificationRepository, timedParkingLoader, parkingRepository, + args.initialRegion ?? null, ); } @@ -205,6 +214,7 @@ export class InterchangeSystem { notificationRepository, timedParkingLoader, parkingRepository, + args.initialRegion ?? null, ); } diff --git a/src/entities/SharedEntities.ts b/src/entities/SharedEntities.ts index 67aa03e..af7b090 100644 --- a/src/entities/SharedEntities.ts +++ b/src/entities/SharedEntities.ts @@ -11,3 +11,8 @@ export interface ICoordinates { longitude: number; } +export interface IRegion { + topLeft: ICoordinates; + bottomRight: ICoordinates; +} + diff --git a/src/index.ts b/src/index.ts index 7340b04..f18a4f3 100644 --- a/src/index.ts +++ b/src/index.ts @@ -25,6 +25,10 @@ const supportedSystems: InterchangeSystemBuilderArguments[] = [ name: "Chapman University", useSelfUpdatingEtas: true, shuttleStopArrivalDegreeDelta: 0.001, + initialRegion: { + topLeft: { latitude: 33.85733, longitude: -117.89553 }, + bottomRight: { latitude: 33.73970, longitude: -117.81878 }, + }, } ] diff --git a/src/resolvers/SystemResolvers.ts b/src/resolvers/SystemResolvers.ts index 27d46c9..538dea0 100644 --- a/src/resolvers/SystemResolvers.ts +++ b/src/resolvers/SystemResolvers.ts @@ -83,6 +83,14 @@ export const SystemResolvers: Resolvers = { const shuttles = await system.shuttleRepository.getShuttles(); return shuttles.slice().sort((a, b) => a.name.localeCompare(b.name)); }, + initialRegion: async (parent, _args, contextValue, _info) => { + const system = contextValue.findSystemById(parent.id); + if (!system) { + return null; + } + + return system.initialRegion; + }, parkingSystem: async (parent, _args, contextValue, _info) => { const system = contextValue.findSystemById(parent.id); if (!system) { diff --git a/src/resolvers/__tests__/SystemResolverTests.test.ts b/src/resolvers/__tests__/SystemResolverTests.test.ts index 822ae4d..aafe377 100644 --- a/src/resolvers/__tests__/SystemResolverTests.test.ts +++ b/src/resolvers/__tests__/SystemResolverTests.test.ts @@ -35,6 +35,37 @@ describe("SystemResolvers", () => { }); } + describe("initialRegion", () => { + const query = ` + query GetSystemInitialRegion($systemId: ID!) { + system(id: $systemId) { + initialRegion { + topLeft { + latitude + longitude + } + bottomRight { + latitude + longitude + } + } + } + } + `; + + it("returns the initial region for the system", async () => { + const response = await getResponseFromQueryNeedingSystemId(query); + + assert(response.body.kind === "single"); + expect(response.body.singleResult.errors).toBeUndefined(); + const initialRegion = (response.body.singleResult.data as any).system.initialRegion; + expect(initialRegion).toEqual({ + topLeft: { latitude: 33.85733, longitude: -117.89553 }, + bottomRight: { latitude: 33.7397, longitude: -117.81878 }, + }); + }); + }); + describe("routes", () => { const query = ` query GetSystemRoutes($systemId: ID!) { diff --git a/testHelpers/apolloTestServerHelpers.ts b/testHelpers/apolloTestServerHelpers.ts index 6f32883..a4e65dc 100644 --- a/testHelpers/apolloTestServerHelpers.ts +++ b/testHelpers/apolloTestServerHelpers.ts @@ -26,6 +26,10 @@ const systemInfoForTesting: InterchangeSystemBuilderArguments = { parkingSystemId: ChapmanApiBasedParkingRepositoryLoader.id, useSelfUpdatingEtas: false, shuttleStopArrivalDegreeDelta: 0.001, + initialRegion: { + topLeft: { latitude: 33.85733, longitude: -117.89553 }, + bottomRight: { latitude: 33.73970, longitude: -117.81878 }, + }, }; export function buildSystemForTesting() {