diff --git a/src/backend/data/schema.js b/src/backend/data/schema.js index 7003c46f..6efc7ff1 100644 --- a/src/backend/data/schema.js +++ b/src/backend/data/schema.js @@ -456,6 +456,14 @@ const GraphQLListContainer = new GraphQLObjectType({ interfaces: [nodeInterface] }) +const GeoPoint = new GraphQLInputObjectType({ + name: 'GeoPoint', + fields: { + lat: {type: GraphQLFloat}, + lon: {type: GraphQLFloat}, + } +}) + const GraphQLUser = new GraphQLObjectType({ name: 'User', description: 'User of ground control', @@ -554,10 +562,13 @@ const GraphQLUser = new GraphQLObjectType({ intervieweeForCallAssignment: { type: GraphQLPerson, args: { - callAssignmentId: {type: GraphQLString} + callAssignmentId: {type: GraphQLString}, + center: {type: GeoPoint}, + radiusMeters: {type: GraphQLFloat} }, - resolve: async(user, {callAssignmentId}, {rootValue}) => { - + resolve: async( + user, {callAssignmentId, center, radiusMeters}, {rootValue} + ) => { let localCallAssignmentId = fromGlobalId(callAssignmentId) if (localCallAssignmentId.type !== 'CallAssignment') localCallAssignmentId = callAssignmentId @@ -647,6 +658,21 @@ const GraphQLUser = new GraphQLObjectType({ if (userAddress) query = query.whereNot('bsd_people.cons_id', userAddress.cons_id) + // Filter by distance from a geographical point. + // Spatial ref 4326 is WGS 84, in degrees + // Spatial ref 900913 is Google Web Mercator, in meters + if (center && radiusMeters > 0) { + query = query.whereRaw(` + ST_DWithin(bsd_addresses.geom, + ST_Transform( + ST_SetSRID(ST_MakePoint(${center.lon}, ${center.lat}), 4326), + 900913 + ), + ${radiusMeters} + ) + `) + } + log.info(`Running query: ${query}`) let person = await query diff --git a/src/frontend/components/CallAssignment.js b/src/frontend/components/CallAssignment.js index 3ebc24a9..f7f3407c 100644 --- a/src/frontend/components/CallAssignment.js +++ b/src/frontend/components/CallAssignment.js @@ -12,6 +12,7 @@ import SubmitCallSurvey from '../mutations/SubmitCallSurvey' import CallStatsBar from './CallStatsBar' import MutationHandler from './MutationHandler' import {PhoneNumberFormat, PhoneNumberUtil} from 'google-libphonenumber' +import getDefaultRelayParams from '../helpers/getDefaultRelayParams' const phoneUtil = PhoneNumberUtil.getInstance() const SurveyRenderers = { @@ -408,8 +409,24 @@ ${userFirstName}` } } +// Convert the hash parameters 'query[lat]', 'query[lon]', and 'query[miles]' +// into the API arguments for the center and radius of the filter region. +const hashParams = getDefaultRelayParams({ + lat: null, // latitude in degrees north + lon: null, // longitude in degrees east + miles: null // radius in miles +}) +const center = (isFinite(hashParams.lat) && isFinite(hashParams.lon)) ? + {lat: hashParams.lat, lon: hashParams.lon} : null +const radiusMeters = isFinite(hashParams.miles) ? + hashParams.miles * 1609.34 : null + export default Relay.createContainer(CallAssignment, { - initialVariables: { id: '' }, + initialVariables: { + id: '', + center: center, + radiusMeters: radiusMeters + }, fragments: { callAssignment: () => Relay.QL` fragment on CallAssignment { @@ -428,9 +445,11 @@ export default Relay.createContainer(CallAssignment, { fragment on User { id firstName - allCallsMade:callsMade(forAssignmentId:$id) - completedCallsMade:callsMade(forAssignmentId:$id,completed:true) - intervieweeForCallAssignment(callAssignmentId:$id) { + allCallsMade: callsMade(forAssignmentId: $id) + completedCallsMade: callsMade(forAssignmentId: $id, completed: true) + intervieweeForCallAssignment( + callAssignmentId: $id, center: $center, radiusMeters: $radiusMeters + ) { id prefix firstName