mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
move distanceToMe onto Location (#8464)
This commit is contained in:
parent
21f343b8cf
commit
f8864a779c
@ -14,6 +14,7 @@ type Location {
|
|||||||
lat: Float
|
lat: Float
|
||||||
lng: Float
|
lng: Float
|
||||||
parent: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
parent: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
||||||
|
distanceToMe: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
# This is not smart - we need one location for everything - use the same type everywhere!
|
# This is not smart - we need one location for everything - use the same type everywhere!
|
||||||
|
|||||||
@ -50,7 +50,6 @@ type User {
|
|||||||
|
|
||||||
locationName: String
|
locationName: String
|
||||||
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
|
||||||
distanceToMe: Int
|
|
||||||
about: String
|
about: String
|
||||||
socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")
|
socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")
|
||||||
|
|
||||||
|
|||||||
@ -483,6 +483,9 @@ export default shield(
|
|||||||
email: or(isMyOwn, isAdmin),
|
email: or(isMyOwn, isAdmin),
|
||||||
emailNotificationSettings: isMyOwn,
|
emailNotificationSettings: isMyOwn,
|
||||||
},
|
},
|
||||||
|
Location: {
|
||||||
|
distanceToMe: isAuthenticated,
|
||||||
|
},
|
||||||
Report: isModerator,
|
Report: isModerator,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import Factory, { cleanDatabase } from '@db/factories'
|
|||||||
import { getNeode, getDriver } from '@db/neo4j'
|
import { getNeode, getDriver } from '@db/neo4j'
|
||||||
import createServer from '@src/server'
|
import createServer from '@src/server'
|
||||||
|
|
||||||
let mutate, authenticatedUser
|
let query, mutate, authenticatedUser
|
||||||
|
|
||||||
const driver = getDriver()
|
const driver = getDriver()
|
||||||
const neode = getNeode()
|
const neode = getNeode()
|
||||||
@ -25,6 +25,7 @@ beforeAll(async () => {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
query = createTestClient(server).query
|
||||||
mutate = createTestClient(server).mutate
|
mutate = createTestClient(server).mutate
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -93,3 +94,209 @@ describe('resolvers', () => {
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const distanceToMeQuery = gql`
|
||||||
|
query ($id: ID!) {
|
||||||
|
User(id: $id) {
|
||||||
|
location {
|
||||||
|
distanceToMe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
let user, myPlaceUser, otherPlaceUser, noCordsPlaceUser, noPlaceUser
|
||||||
|
|
||||||
|
describe('distanceToMe', () => {
|
||||||
|
beforeEach(async () => {
|
||||||
|
const Hamburg = await Factory.build('location', {
|
||||||
|
id: 'region.5127278006398860',
|
||||||
|
name: 'Hamburg',
|
||||||
|
type: 'region',
|
||||||
|
lng: 10.0,
|
||||||
|
lat: 53.55,
|
||||||
|
nameES: 'Hamburgo',
|
||||||
|
nameFR: 'Hambourg',
|
||||||
|
nameIT: 'Amburgo',
|
||||||
|
nameEN: 'Hamburg',
|
||||||
|
namePT: 'Hamburgo',
|
||||||
|
nameDE: 'Hamburg',
|
||||||
|
nameNL: 'Hamburg',
|
||||||
|
namePL: 'Hamburg',
|
||||||
|
nameRU: 'Гамбург',
|
||||||
|
})
|
||||||
|
const Germany = await Factory.build('location', {
|
||||||
|
id: 'country.10743216036480410',
|
||||||
|
name: 'Germany',
|
||||||
|
type: 'country',
|
||||||
|
namePT: 'Alemanha',
|
||||||
|
nameDE: 'Deutschland',
|
||||||
|
nameES: 'Alemania',
|
||||||
|
nameNL: 'Duitsland',
|
||||||
|
namePL: 'Niemcy',
|
||||||
|
nameFR: 'Allemagne',
|
||||||
|
nameIT: 'Germania',
|
||||||
|
nameEN: 'Germany',
|
||||||
|
nameRU: 'Германия',
|
||||||
|
})
|
||||||
|
const Paris = await Factory.build('location', {
|
||||||
|
id: 'region.9397217726497330',
|
||||||
|
name: 'Paris',
|
||||||
|
type: 'region',
|
||||||
|
lng: 2.35183,
|
||||||
|
lat: 48.85658,
|
||||||
|
nameES: 'París',
|
||||||
|
nameFR: 'Paris',
|
||||||
|
nameIT: 'Parigi',
|
||||||
|
nameEN: 'Paris',
|
||||||
|
namePT: 'Paris',
|
||||||
|
nameDE: 'Paris',
|
||||||
|
nameNL: 'Parijs',
|
||||||
|
namePL: 'Paryż',
|
||||||
|
nameRU: 'Париж',
|
||||||
|
})
|
||||||
|
|
||||||
|
user = await Factory.build('user', {
|
||||||
|
id: 'user',
|
||||||
|
role: 'user',
|
||||||
|
})
|
||||||
|
await user.relateTo(Hamburg, 'isIn')
|
||||||
|
|
||||||
|
myPlaceUser = await Factory.build('user', {
|
||||||
|
id: 'myPlaceUser',
|
||||||
|
role: 'user',
|
||||||
|
})
|
||||||
|
await myPlaceUser.relateTo(Hamburg, 'isIn')
|
||||||
|
|
||||||
|
otherPlaceUser = await Factory.build('user', {
|
||||||
|
id: 'otherPlaceUser',
|
||||||
|
role: 'user',
|
||||||
|
})
|
||||||
|
await otherPlaceUser.relateTo(Paris, 'isIn')
|
||||||
|
|
||||||
|
noCordsPlaceUser = await Factory.build('user', {
|
||||||
|
id: 'noCordsPlaceUser',
|
||||||
|
role: 'user',
|
||||||
|
})
|
||||||
|
await noCordsPlaceUser.relateTo(Germany, 'isIn')
|
||||||
|
|
||||||
|
noPlaceUser = await Factory.build('user', {
|
||||||
|
id: 'noPlaceUser',
|
||||||
|
role: 'user',
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('query the field', () => {
|
||||||
|
describe('for self user', () => {
|
||||||
|
it('returns 0', async () => {
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
const targetUser = await user.toJson()
|
||||||
|
await expect(
|
||||||
|
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
User: [
|
||||||
|
{
|
||||||
|
location: {
|
||||||
|
distanceToMe: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('for myPlaceUser', () => {
|
||||||
|
it('returns 0', async () => {
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
const targetUser = await myPlaceUser.toJson()
|
||||||
|
await expect(
|
||||||
|
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
User: [
|
||||||
|
{
|
||||||
|
location: {
|
||||||
|
distanceToMe: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('for otherPlaceUser', () => {
|
||||||
|
it('returns a number', async () => {
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
const targetUser = await otherPlaceUser.toJson()
|
||||||
|
await expect(
|
||||||
|
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
User: [
|
||||||
|
{
|
||||||
|
location: {
|
||||||
|
distanceToMe: 746,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('for noCordsPlaceUser', () => {
|
||||||
|
it('returns null', async () => {
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
const targetUser = await noCordsPlaceUser.toJson()
|
||||||
|
await expect(
|
||||||
|
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
User: [
|
||||||
|
{
|
||||||
|
location: {
|
||||||
|
distanceToMe: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('for noPlaceUser', () => {
|
||||||
|
it('returns null location', async () => {
|
||||||
|
authenticatedUser = await user.toJson()
|
||||||
|
const targetUser = await noPlaceUser.toJson()
|
||||||
|
await expect(
|
||||||
|
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
||||||
|
).resolves.toEqual(
|
||||||
|
expect.objectContaining({
|
||||||
|
data: {
|
||||||
|
User: [
|
||||||
|
{
|
||||||
|
location: null,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
errors: undefined,
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-return */
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-call */
|
||||||
|
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
||||||
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
/* eslint-disable @typescript-eslint/no-unsafe-argument */
|
||||||
import { UserInputError } from 'apollo-server'
|
import { UserInputError } from 'apollo-server'
|
||||||
@ -20,6 +23,31 @@ export default {
|
|||||||
'nameRU',
|
'nameRU',
|
||||||
],
|
],
|
||||||
}),
|
}),
|
||||||
|
distanceToMe: async (parent, _params, context, _resolveInfo) => {
|
||||||
|
const session = context.driver.session()
|
||||||
|
|
||||||
|
const query = session.readTransaction(async (transaction) => {
|
||||||
|
const result = await transaction.run(
|
||||||
|
`
|
||||||
|
MATCH (loc:Location {id: $parent.id})
|
||||||
|
MATCH (me:User {id: $user.id})-[:IS_IN]->(meLoc:Location)
|
||||||
|
WITH
|
||||||
|
point({latitude: loc.lat, longitude: loc.lng}) as locPoint,
|
||||||
|
point({latitude: meLoc.lat, longitude: meLoc.lng}) as mePoint
|
||||||
|
RETURN round(point.distance(locPoint, mePoint) / 1000) as distance
|
||||||
|
`,
|
||||||
|
{ parent, user: context.user },
|
||||||
|
)
|
||||||
|
|
||||||
|
return result.records.map((record) => record.get('distance'))[0]
|
||||||
|
})
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await query
|
||||||
|
} finally {
|
||||||
|
await session.close()
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
Query: {
|
Query: {
|
||||||
queryLocations: async (_object, args, _context, _resolveInfo) => {
|
queryLocations: async (_object, args, _context, _resolveInfo) => {
|
||||||
|
|||||||
@ -660,202 +660,6 @@ const emailNotificationSettingsMutation = gql`
|
|||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
const distanceToMeQuery = gql`
|
|
||||||
query ($id: ID!) {
|
|
||||||
User(id: $id) {
|
|
||||||
distanceToMe
|
|
||||||
}
|
|
||||||
}
|
|
||||||
`
|
|
||||||
let myPlaceUser, otherPlaceUser, noCordsPlaceUser, noPlaceUser
|
|
||||||
|
|
||||||
describe('distanceToMe', () => {
|
|
||||||
beforeEach(async () => {
|
|
||||||
const Hamburg = await Factory.build('location', {
|
|
||||||
id: 'region.5127278006398860',
|
|
||||||
name: 'Hamburg',
|
|
||||||
type: 'region',
|
|
||||||
lng: 10.0,
|
|
||||||
lat: 53.55,
|
|
||||||
nameES: 'Hamburgo',
|
|
||||||
nameFR: 'Hambourg',
|
|
||||||
nameIT: 'Amburgo',
|
|
||||||
nameEN: 'Hamburg',
|
|
||||||
namePT: 'Hamburgo',
|
|
||||||
nameDE: 'Hamburg',
|
|
||||||
nameNL: 'Hamburg',
|
|
||||||
namePL: 'Hamburg',
|
|
||||||
nameRU: 'Гамбург',
|
|
||||||
})
|
|
||||||
const Germany = await Factory.build('location', {
|
|
||||||
id: 'country.10743216036480410',
|
|
||||||
name: 'Germany',
|
|
||||||
type: 'country',
|
|
||||||
namePT: 'Alemanha',
|
|
||||||
nameDE: 'Deutschland',
|
|
||||||
nameES: 'Alemania',
|
|
||||||
nameNL: 'Duitsland',
|
|
||||||
namePL: 'Niemcy',
|
|
||||||
nameFR: 'Allemagne',
|
|
||||||
nameIT: 'Germania',
|
|
||||||
nameEN: 'Germany',
|
|
||||||
nameRU: 'Германия',
|
|
||||||
})
|
|
||||||
const Paris = await Factory.build('location', {
|
|
||||||
id: 'region.9397217726497330',
|
|
||||||
name: 'Paris',
|
|
||||||
type: 'region',
|
|
||||||
lng: 2.35183,
|
|
||||||
lat: 48.85658,
|
|
||||||
nameES: 'París',
|
|
||||||
nameFR: 'Paris',
|
|
||||||
nameIT: 'Parigi',
|
|
||||||
nameEN: 'Paris',
|
|
||||||
namePT: 'Paris',
|
|
||||||
nameDE: 'Paris',
|
|
||||||
nameNL: 'Parijs',
|
|
||||||
namePL: 'Paryż',
|
|
||||||
nameRU: 'Париж',
|
|
||||||
})
|
|
||||||
|
|
||||||
user = await Factory.build('user', {
|
|
||||||
id: 'user',
|
|
||||||
role: 'user',
|
|
||||||
})
|
|
||||||
await user.relateTo(Hamburg, 'isIn')
|
|
||||||
|
|
||||||
myPlaceUser = await Factory.build('user', {
|
|
||||||
id: 'myPlaceUser',
|
|
||||||
role: 'user',
|
|
||||||
})
|
|
||||||
await myPlaceUser.relateTo(Hamburg, 'isIn')
|
|
||||||
|
|
||||||
otherPlaceUser = await Factory.build('user', {
|
|
||||||
id: 'otherPlaceUser',
|
|
||||||
role: 'user',
|
|
||||||
})
|
|
||||||
await otherPlaceUser.relateTo(Paris, 'isIn')
|
|
||||||
|
|
||||||
noCordsPlaceUser = await Factory.build('user', {
|
|
||||||
id: 'noCordsPlaceUser',
|
|
||||||
role: 'user',
|
|
||||||
})
|
|
||||||
await noCordsPlaceUser.relateTo(Germany, 'isIn')
|
|
||||||
|
|
||||||
noPlaceUser = await Factory.build('user', {
|
|
||||||
id: 'noPlaceUser',
|
|
||||||
role: 'user',
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('query the field', () => {
|
|
||||||
describe('for self user', () => {
|
|
||||||
it('returns null', async () => {
|
|
||||||
authenticatedUser = await user.toJson()
|
|
||||||
const targetUser = await user.toJson()
|
|
||||||
await expect(
|
|
||||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
User: [
|
|
||||||
{
|
|
||||||
distanceToMe: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
errors: undefined,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('for myPlaceUser', () => {
|
|
||||||
it('returns 0', async () => {
|
|
||||||
authenticatedUser = await user.toJson()
|
|
||||||
const targetUser = await myPlaceUser.toJson()
|
|
||||||
await expect(
|
|
||||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
User: [
|
|
||||||
{
|
|
||||||
distanceToMe: 0,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
errors: undefined,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('for otherPlaceUser', () => {
|
|
||||||
it('returns a number', async () => {
|
|
||||||
authenticatedUser = await user.toJson()
|
|
||||||
const targetUser = await otherPlaceUser.toJson()
|
|
||||||
await expect(
|
|
||||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
User: [
|
|
||||||
{
|
|
||||||
distanceToMe: 746,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
errors: undefined,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('for noCordsPlaceUser', () => {
|
|
||||||
it('returns null', async () => {
|
|
||||||
authenticatedUser = await user.toJson()
|
|
||||||
const targetUser = await noCordsPlaceUser.toJson()
|
|
||||||
await expect(
|
|
||||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
User: [
|
|
||||||
{
|
|
||||||
distanceToMe: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
errors: undefined,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('for noPlaceUser', () => {
|
|
||||||
it('returns null', async () => {
|
|
||||||
authenticatedUser = await user.toJson()
|
|
||||||
const targetUser = await noPlaceUser.toJson()
|
|
||||||
await expect(
|
|
||||||
query({ query: distanceToMeQuery, variables: { id: targetUser.id } }),
|
|
||||||
).resolves.toEqual(
|
|
||||||
expect.objectContaining({
|
|
||||||
data: {
|
|
||||||
User: [
|
|
||||||
{
|
|
||||||
distanceToMe: null,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
errors: undefined,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
describe('emailNotificationSettings', () => {
|
describe('emailNotificationSettings', () => {
|
||||||
beforeEach(async () => {
|
beforeEach(async () => {
|
||||||
user = await Factory.build('user', {
|
user = await Factory.build('user', {
|
||||||
|
|||||||
@ -467,36 +467,6 @@ export default {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
User: {
|
User: {
|
||||||
distanceToMe: async (parent, _params, context, _resolveInfo) => {
|
|
||||||
// is it myself?
|
|
||||||
if (parent.id === context.user.id) {
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = context.driver.session()
|
|
||||||
|
|
||||||
const query = session.readTransaction(async (transaction) => {
|
|
||||||
const result = await transaction.run(
|
|
||||||
`
|
|
||||||
MATCH (user:User {id: $parent.id})-[:IS_IN]->(userLoc:Location)
|
|
||||||
MATCH (me:User {id: $user.id})-[:IS_IN]->(meLoc:Location)
|
|
||||||
WITH
|
|
||||||
point({latitude: userLoc.lat, longitude: userLoc.lng}) as userPoint,
|
|
||||||
point({latitude: meLoc.lat, longitude: meLoc.lng}) as mePoint
|
|
||||||
RETURN round(point.distance(userPoint, mePoint) / 1000) as distance
|
|
||||||
`,
|
|
||||||
{ parent, user: context.user },
|
|
||||||
)
|
|
||||||
|
|
||||||
return result.records.map((record) => record.get('distance'))[0]
|
|
||||||
})
|
|
||||||
|
|
||||||
try {
|
|
||||||
return await query
|
|
||||||
} finally {
|
|
||||||
session.close()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
emailNotificationSettings: async (parent, _params, _context, _resolveInfo) => {
|
emailNotificationSettings: async (parent, _params, _context, _resolveInfo) => {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user