diff --git a/backend/src/constants/groups.js b/backend/src/constants/groups.js
index 64ffeaa59..e9c941a89 100644
--- a/backend/src/constants/groups.js
+++ b/backend/src/constants/groups.js
@@ -1,3 +1,3 @@
// this file is duplicated in `backend/src/constants/group.js` and `webapp/constants/group.js`
export const DESCRIPTION_WITHOUT_HTML_LENGTH_MIN = 100 // with removed HTML tags
-export const DESCRIPTION_EXCERPT_HTML_LENGTH = 120 // with removed HTML tags
+export const DESCRIPTION_EXCERPT_HTML_LENGTH = 250 // with removed HTML tags
diff --git a/backend/src/db/graphql/groups.js b/backend/src/db/graphql/groups.js
index 623f467a4..e388b2cd9 100644
--- a/backend/src/db/graphql/groups.js
+++ b/backend/src/db/graphql/groups.js
@@ -2,171 +2,202 @@ import gql from 'graphql-tag'
// ------ mutations
-export const createGroupMutation = gql`
- mutation (
- $id: ID
- $name: String!
- $slug: String
- $about: String
- $description: String!
- $groupType: GroupType!
- $actionRadius: GroupActionRadius!
- $categoryIds: [ID]
- $locationName: String
- ) {
- CreateGroup(
- id: $id
- name: $name
- slug: $slug
- about: $about
- description: $description
- groupType: $groupType
- actionRadius: $actionRadius
- categoryIds: $categoryIds
- locationName: $locationName
+export const createGroupMutation = () => {
+ return gql`
+ mutation (
+ $id: ID
+ $name: String!
+ $slug: String
+ $about: String
+ $description: String!
+ $groupType: GroupType!
+ $actionRadius: GroupActionRadius!
+ $categoryIds: [ID]
+ $locationName: String # empty string '' sets it to null
) {
- id
- name
- slug
- createdAt
- updatedAt
- disabled
- deleted
- about
- description
- groupType
- actionRadius
- categories {
+ CreateGroup(
+ id: $id
+ name: $name
+ slug: $slug
+ about: $about
+ description: $description
+ groupType: $groupType
+ actionRadius: $actionRadius
+ categoryIds: $categoryIds
+ locationName: $locationName
+ ) {
id
- slug
name
- icon
+ slug
+ createdAt
+ updatedAt
+ disabled
+ deleted
+ about
+ description
+ descriptionExcerpt
+ groupType
+ actionRadius
+ categories {
+ id
+ slug
+ name
+ icon
+ }
+ locationName
+ location {
+ name
+ nameDE
+ nameEN
+ }
+ myRole
}
- # locationName # test this as result
- myRole
}
- }
-`
+ `
+}
-export const updateGroupMutation = gql`
- mutation (
- $id: ID!
- $name: String
- $slug: String
- $about: String
- $description: String
- $actionRadius: GroupActionRadius
- $categoryIds: [ID]
- $avatar: ImageInput
- $locationName: String
- ) {
- UpdateGroup(
- id: $id
- name: $name
- slug: $slug
- about: $about
- description: $description
- actionRadius: $actionRadius
- categoryIds: $categoryIds
- avatar: $avatar
- locationName: $locationName
+export const updateGroupMutation = () => {
+ return gql`
+ mutation (
+ $id: ID!
+ $name: String
+ $slug: String
+ $about: String
+ $description: String
+ $actionRadius: GroupActionRadius
+ $categoryIds: [ID]
+ $avatar: ImageInput
+ $locationName: String # empty string '' sets it to null
) {
- id
- name
- slug
- createdAt
- updatedAt
- disabled
- deleted
- about
- description
- groupType
- actionRadius
- categories {
+ UpdateGroup(
+ id: $id
+ name: $name
+ slug: $slug
+ about: $about
+ description: $description
+ actionRadius: $actionRadius
+ categoryIds: $categoryIds
+ avatar: $avatar
+ locationName: $locationName
+ ) {
id
- slug
name
- icon
+ slug
+ createdAt
+ updatedAt
+ disabled
+ deleted
+ about
+ description
+ descriptionExcerpt
+ groupType
+ actionRadius
+ categories {
+ id
+ slug
+ name
+ icon
+ }
+ # avatar # test this as result
+ locationName
+ location {
+ name
+ nameDE
+ nameEN
+ }
+ myRole
}
- # avatar # test this as result
- # locationName # test this as result
- myRole
}
- }
-`
+ `
+}
-export const joinGroupMutation = gql`
- mutation ($groupId: ID!, $userId: ID!) {
- JoinGroup(groupId: $groupId, userId: $userId) {
- id
- name
- slug
- myRoleInGroup
+export const joinGroupMutation = () => {
+ return gql`
+ mutation ($groupId: ID!, $userId: ID!) {
+ JoinGroup(groupId: $groupId, userId: $userId) {
+ id
+ name
+ slug
+ myRoleInGroup
+ }
}
- }
-`
+ `
+}
-export const leaveGroupMutation = gql`
- mutation ($groupId: ID!, $userId: ID!) {
- LeaveGroup(groupId: $groupId, userId: $userId) {
- id
- name
- slug
- myRoleInGroup
+export const leaveGroupMutation = () => {
+ return gql`
+ mutation ($groupId: ID!, $userId: ID!) {
+ LeaveGroup(groupId: $groupId, userId: $userId) {
+ id
+ name
+ slug
+ myRoleInGroup
+ }
}
- }
-`
+ `
+}
-export const changeGroupMemberRoleMutation = gql`
- mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
- ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
- id
- name
- slug
- myRoleInGroup
+export const changeGroupMemberRoleMutation = () => {
+ return gql`
+ mutation ($groupId: ID!, $userId: ID!, $roleInGroup: GroupMemberRole!) {
+ ChangeGroupMemberRole(groupId: $groupId, userId: $userId, roleInGroup: $roleInGroup) {
+ id
+ name
+ slug
+ myRoleInGroup
+ }
}
- }
-`
+ `
+}
// ------ queries
-export const groupQuery = gql`
- query ($isMember: Boolean, $id: ID, $slug: String) {
- Group(isMember: $isMember, id: $id, slug: $slug) {
- id
- name
- slug
- createdAt
- updatedAt
- disabled
- deleted
- about
- description
- descriptionExcerpt
- groupType
- actionRadius
- categories {
+export const groupQuery = () => {
+ return gql`
+ query ($isMember: Boolean, $id: ID, $slug: String) {
+ Group(isMember: $isMember, id: $id, slug: $slug) {
id
- slug
name
- icon
+ slug
+ createdAt
+ updatedAt
+ disabled
+ deleted
+ about
+ description
+ descriptionExcerpt
+ groupType
+ actionRadius
+ categories {
+ id
+ slug
+ name
+ icon
+ }
+ avatar {
+ url
+ }
+ locationName
+ location {
+ name
+ nameDE
+ nameEN
+ }
+ myRole
}
- avatar {
- url
- }
- # locationName # test this as result
- myRole
}
- }
-`
+ `
+}
-export const groupMembersQuery = gql`
- query ($id: ID!) {
- GroupMembers(id: $id) {
- id
- name
- slug
- myRoleInGroup
+export const groupMembersQuery = () => {
+ return gql`
+ query ($id: ID!) {
+ GroupMembers(id: $id) {
+ id
+ name
+ slug
+ myRoleInGroup
+ }
}
- }
-`
+ `
+}
diff --git a/backend/src/db/seed.js b/backend/src/db/seed.js
index 632aa8f4d..d693f9905 100644
--- a/backend/src/db/seed.js
+++ b/backend/src/db/seed.js
@@ -305,7 +305,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
authenticatedUser = await peterLustig.toJson()
await Promise.all([
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'g0',
name: 'Investigative Journalism',
@@ -313,27 +313,28 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
description: `
English:
This group is hidden.
What is our group for?
This group was created to allow investigative journalists to share and collaborate.
How does it work?
Here you can internally share posts and comments about them.
Deutsch:
Diese Gruppe ist verborgen.
Wofür ist unsere Gruppe?
Diese Gruppe wurde geschaffen, um investigativen Journalisten den Austausch und die Zusammenarbeit zu ermöglichen.
Wie funktioniert das?
Hier könnt ihr euch intern über Beiträge und Kommentare zu ihnen austauschen.
`,
groupType: 'hidden',
actionRadius: 'global',
- categoryIds: ['cat6', 'cat9', 'cat14'],
+ categoryIds: ['cat6', 'cat12', 'cat16'],
+ locationName: 'Hamburg, Germany',
},
}),
])
await Promise.all([
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g0',
userId: 'u2',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g0',
userId: 'u4',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g0',
userId: 'u6',
@@ -342,7 +343,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
])
await Promise.all([
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g0',
userId: 'u2',
@@ -350,7 +351,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
},
}),
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g0',
userId: 'u4',
@@ -362,7 +363,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
authenticatedUser = await jennyRostock.toJson()
await Promise.all([
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'g1',
name: 'School For Citizens',
@@ -370,41 +371,42 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
description: `English
Our goal
Only those who enjoy learning and do not lose their curiosity can obtain a good education for life and continue to learn with joy throughout their lives.
Curiosity
For this we need a school that takes up the curiosity of the children, the people, and satisfies it through a lot of experience.
Deutsch
Unser Ziel
Nur wer Spaß am Lernen hat und seine Neugier nicht verliert, kann gute Bildung für's Leben erlangen und sein ganzes Leben mit Freude weiter lernen.
Neugier
Dazu benötigen wir eine Schule, die die Neugier der Kinder, der Menschen, aufnimmt und durch viel Erfahrung befriedigt.
`,
groupType: 'closed',
actionRadius: 'national',
- categoryIds: ['cat7', 'cat9', 'cat16'],
+ categoryIds: ['cat8', 'cat14'],
+ locationName: 'France',
},
}),
])
await Promise.all([
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g1',
userId: 'u1',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g1',
userId: 'u2',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g1',
userId: 'u5',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g1',
userId: 'u6',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g1',
userId: 'u7',
@@ -413,7 +415,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
])
await Promise.all([
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g1',
userId: 'u1',
@@ -421,7 +423,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
},
}),
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g1',
userId: 'u5',
@@ -429,7 +431,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
},
}),
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g1',
userId: 'u6',
@@ -441,7 +443,7 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
authenticatedUser = await bobDerBaumeister.toJson()
await Promise.all([
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'g2',
name: 'Yoga Practice',
@@ -449,41 +451,41 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
description: `What Is yoga?
Yoga is not just about practicing asanas. It's about how we do it.
And practicing asanas doesn't have to be yoga, it can be more athletic than yogic.
What makes practicing asanas yogic?
The important thing is:
`,
groupType: 'public',
actionRadius: 'interplanetary',
- categoryIds: ['cat3', 'cat13', 'cat16'],
+ categoryIds: ['cat4', 'cat5', 'cat17'],
},
}),
])
await Promise.all([
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g2',
userId: 'u3',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g2',
userId: 'u4',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g2',
userId: 'u5',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g2',
userId: 'u6',
},
}),
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'g2',
userId: 'u7',
@@ -492,31 +494,31 @@ const languages = ['de', 'en', 'es', 'fr', 'it', 'pt', 'pl']
])
await Promise.all([
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g2',
userId: 'u3',
+ roleInGroup: 'usual',
+ },
+ }),
+ mutate({
+ mutation: changeGroupMemberRoleMutation(),
+ variables: {
+ groupId: 'g2',
+ userId: 'u4',
roleInGroup: 'pending',
},
}),
mutate({
- mutation: changeGroupMemberRoleMutation,
- variables: {
- groupId: 'g2',
- userId: 'u4',
- roleInGroup: 'usual',
- },
- }),
- mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g2',
userId: 'u5',
- roleInGroup: 'usual',
+ roleInGroup: 'admin',
},
}),
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'g2',
userId: 'u6',
diff --git a/backend/src/middleware/permissionsMiddleware.js b/backend/src/middleware/permissionsMiddleware.js
index 8f3d6947a..be03e979e 100644
--- a/backend/src/middleware/permissionsMiddleware.js
+++ b/backend/src/middleware/permissionsMiddleware.js
@@ -82,7 +82,7 @@ const isAllowedToChangeGroupSettings = rule({
}
})
-const isAllowedSeeingMembersOfGroup = rule({
+const isAllowedSeeingGroupMembers = rule({
cache: 'no_cache',
})(async (_parent, args, { user, driver }) => {
if (!(user && user.id)) return false
@@ -284,7 +284,7 @@ export default shield(
statistics: allow,
currentUser: allow,
Group: isAuthenticated,
- GroupMembers: isAllowedSeeingMembersOfGroup,
+ GroupMembers: isAllowedSeeingGroupMembers,
Post: allow,
profilePagePosts: allow,
Comment: allow,
diff --git a/backend/src/middleware/slugifyMiddleware.spec.js b/backend/src/middleware/slugifyMiddleware.spec.js
index edb6b64eb..c600d0e52 100644
--- a/backend/src/middleware/slugifyMiddleware.spec.js
+++ b/backend/src/middleware/slugifyMiddleware.spec.js
@@ -51,6 +51,7 @@ beforeEach(async () => {
await Factory.build('category', {
id: 'cat9',
name: 'Democracy & Politics',
+ slug: 'democracy-politics',
icon: 'university',
})
authenticatedUser = await admin.toJson()
@@ -79,7 +80,7 @@ describe('slugifyMiddleware', () => {
it('generates a slug based on name', async () => {
await expect(
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -93,13 +94,14 @@ describe('slugifyMiddleware', () => {
actionRadius: 'national',
},
},
+ errors: undefined,
})
})
it('generates a slug based on given slug', async () => {
await expect(
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
...variables,
slug: 'the-group',
@@ -111,6 +113,7 @@ describe('slugifyMiddleware', () => {
slug: 'the-group',
},
},
+ errors: undefined,
})
})
})
@@ -118,7 +121,7 @@ describe('slugifyMiddleware', () => {
describe('if slug exists', () => {
beforeEach(async () => {
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
...variables,
name: 'Pre-Existing Group',
@@ -131,7 +134,7 @@ describe('slugifyMiddleware', () => {
it('chooses another slug', async () => {
await expect(
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
...variables,
name: 'Pre-Existing Group',
@@ -144,6 +147,7 @@ describe('slugifyMiddleware', () => {
slug: 'pre-existing-group-1',
},
},
+ errors: undefined,
})
})
@@ -152,7 +156,7 @@ describe('slugifyMiddleware', () => {
try {
await expect(
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
...variables,
name: 'Pre-Existing Group',
@@ -194,7 +198,7 @@ describe('slugifyMiddleware', () => {
beforeEach(async () => {
createGroupResult = await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
name: 'The Best Group',
slug: 'the-best-group',
@@ -213,7 +217,7 @@ describe('slugifyMiddleware', () => {
it('has the new slug', async () => {
await expect(
mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: createGroupResult.data.CreateGroup.id,
name: 'My Best Group',
@@ -231,6 +235,7 @@ describe('slugifyMiddleware', () => {
myRole: 'owner',
},
},
+ errors: undefined,
})
})
})
@@ -239,7 +244,7 @@ describe('slugifyMiddleware', () => {
it('has the new slug', async () => {
await expect(
mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: createGroupResult.data.CreateGroup.id,
slug: 'my-best-group',
@@ -257,6 +262,7 @@ describe('slugifyMiddleware', () => {
myRole: 'owner',
},
},
+ errors: undefined,
})
})
})
@@ -265,7 +271,7 @@ describe('slugifyMiddleware', () => {
describe('if new slug exists in another group', () => {
beforeEach(async () => {
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
name: 'Pre-Existing Group',
slug: 'pre-existing-group',
@@ -282,7 +288,7 @@ describe('slugifyMiddleware', () => {
it('has unique slug "*-1"', async () => {
await expect(
mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: createGroupResult.data.CreateGroup.id,
name: 'Pre-Existing Group',
@@ -300,6 +306,7 @@ describe('slugifyMiddleware', () => {
myRole: 'owner',
},
},
+ errors: undefined,
})
})
})
@@ -309,7 +316,7 @@ describe('slugifyMiddleware', () => {
try {
await expect(
mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: createGroupResult.data.CreateGroup.id,
slug: 'pre-existing-group',
@@ -368,6 +375,7 @@ describe('slugifyMiddleware', () => {
slug: 'i-am-a-brand-new-post',
},
},
+ errors: undefined,
})
})
@@ -386,6 +394,7 @@ describe('slugifyMiddleware', () => {
slug: 'the-post',
},
},
+ errors: undefined,
})
})
})
@@ -422,6 +431,7 @@ describe('slugifyMiddleware', () => {
slug: 'pre-existing-post-1',
},
},
+ errors: undefined,
})
})
@@ -504,6 +514,7 @@ describe('slugifyMiddleware', () => {
slug: 'i-am-a-user',
},
},
+ errors: undefined,
})
})
@@ -522,6 +533,7 @@ describe('slugifyMiddleware', () => {
slug: 'the-user',
},
},
+ errors: undefined,
})
})
})
@@ -546,6 +558,7 @@ describe('slugifyMiddleware', () => {
slug: 'i-am-a-user-1',
},
},
+ errors: undefined,
})
})
diff --git a/backend/src/schema/index.js b/backend/src/schema/index.js
index 612487147..06e150c86 100644
--- a/backend/src/schema/index.js
+++ b/backend/src/schema/index.js
@@ -20,6 +20,7 @@ export default makeAugmentedSchema({
'FILED',
'REVIEWED',
'Report',
+ 'Group',
],
},
mutation: false,
diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js
index 2f7ed4588..2617bd43e 100644
--- a/backend/src/schema/resolvers/groups.js
+++ b/backend/src/schema/resolvers/groups.js
@@ -9,7 +9,7 @@ import Resolver, {
convertObjectToCypherMapLiteral,
} from './helpers/Resolver'
import { mergeImage } from './images/images'
-import createOrUpdateLocations from './users/location'
+import { createOrUpdateLocations } from './users/location'
export default {
Query: {
@@ -86,6 +86,7 @@ export default {
CreateGroup: async (_parent, params, context, _resolveInfo) => {
const { categoryIds } = params
delete params.categoryIds
+ params.locationName = params.locationName === '' ? null : params.locationName
if (CONFIG.CATEGORIES_ACTIVE && (!categoryIds || categoryIds.length < CATEGORIES_MIN)) {
throw new UserInputError('Too view categories!')
}
@@ -137,7 +138,8 @@ export default {
})
try {
const group = await writeTxResultPromise
- await createOrUpdateLocations(params.id, params.locationName, session)
+ // TODO: put in a middleware, see "UpdateGroup", "UpdateUser"
+ await createOrUpdateLocations('Group', params.id, params.locationName, session)
return group
} catch (error) {
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
@@ -149,9 +151,11 @@ export default {
},
UpdateGroup: async (_parent, params, context, _resolveInfo) => {
const { categoryIds } = params
- const { id: groupId, avatar: avatarInput } = params
delete params.categoryIds
+ const { id: groupId, avatar: avatarInput } = params
delete params.avatar
+ params.locationName = params.locationName === '' ? null : params.locationName
+
if (CONFIG.CATEGORIES_ACTIVE && categoryIds) {
if (categoryIds.length < CATEGORIES_MIN) {
throw new UserInputError('Too view categories!')
@@ -210,7 +214,8 @@ export default {
})
try {
const group = await writeTxResultPromise
- await createOrUpdateLocations(params.id, params.locationName, session)
+ // TODO: put in a middleware, see "CreateGroup", "UpdateUser"
+ await createOrUpdateLocations('Group', params.id, params.locationName, session)
return group
} catch (error) {
if (error.code === 'Neo.ClientError.Schema.ConstraintValidationFailed')
diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js
index b4653edaf..d707440a4 100644
--- a/backend/src/schema/resolvers/groups.spec.js
+++ b/backend/src/schema/resolvers/groups.spec.js
@@ -55,18 +55,18 @@ const seedBasicsAndClearAuthentication = async () => {
},
)
await Promise.all([
- neode.create('Category', {
- id: 'cat9',
- name: 'Democracy & Politics',
- slug: 'democracy-politics',
- icon: 'university',
- }),
neode.create('Category', {
id: 'cat4',
name: 'Environment & Nature',
slug: 'environment-nature',
icon: 'tree',
}),
+ neode.create('Category', {
+ id: 'cat9',
+ name: 'Democracy & Politics',
+ slug: 'democracy-politics',
+ icon: 'university',
+ }),
neode.create('Category', {
id: 'cat15',
name: 'Consumption & Sustainability',
@@ -156,7 +156,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
// public-group
authenticatedUser = await usualMemberUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'public-group',
name: 'The Best Group',
@@ -168,14 +168,14 @@ const seedComplexScenarioAndClearAuthentication = async () => {
},
})
await mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-closed-group',
},
})
await mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-hidden-group',
@@ -184,7 +184,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
// closed-group
authenticatedUser = await ownerMemberUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'closed-group',
name: 'Uninteresting Group',
@@ -198,7 +198,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
// hidden-group
authenticatedUser = await adminMemberUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
@@ -211,7 +211,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
})
// 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'admin-member-user',
@@ -219,7 +219,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'second-owner-member-user',
@@ -227,7 +227,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'admin-member-user',
@@ -235,7 +235,7 @@ const seedComplexScenarioAndClearAuthentication = async () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'second-owner-member-user',
@@ -277,13 +277,13 @@ describe('in mode', () => {
groupType: 'public',
actionRadius: 'regional',
categoryIds,
- // locationName, // test this as result
+ locationName: 'Hamburg, Germany',
}
})
describe('unauthenticated', () => {
it('throws authorization error', async () => {
- const { errors } = await mutate({ mutation: createGroupMutation, variables })
+ const { errors } = await mutate({ mutation: createGroupMutation(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -294,43 +294,50 @@ describe('in mode', () => {
})
it('creates a group', async () => {
- await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
- {
- data: {
- CreateGroup: {
- name: 'The Best Group',
- slug: 'the-group',
- about: 'We will change the world!',
- description: 'Some description' + descriptionAdditional100,
- groupType: 'public',
- actionRadius: 'regional',
- },
+ await expect(
+ mutate({ mutation: createGroupMutation(), variables }),
+ ).resolves.toMatchObject({
+ data: {
+ CreateGroup: {
+ name: 'The Best Group',
+ slug: 'the-group',
+ about: 'We will change the world!',
+ description: 'Some description' + descriptionAdditional100,
+ descriptionExcerpt: 'Some description' + descriptionAdditional100,
+ groupType: 'public',
+ actionRadius: 'regional',
+ locationName: 'Hamburg, Germany',
+ location: expect.objectContaining({
+ name: 'Hamburg',
+ nameDE: 'Hamburg',
+ nameEN: 'Hamburg',
+ }),
},
- errors: undefined,
},
- )
+ errors: undefined,
+ })
})
it('assigns the authenticated user as owner', async () => {
- await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
- {
- data: {
- CreateGroup: {
- name: 'The Best Group',
- myRole: 'owner',
- },
+ await expect(
+ mutate({ mutation: createGroupMutation(), variables }),
+ ).resolves.toMatchObject({
+ data: {
+ CreateGroup: {
+ name: 'The Best Group',
+ myRole: 'owner',
},
- errors: undefined,
},
- )
+ errors: undefined,
+ })
})
it('has "disabled" and "deleted" default to "false"', async () => {
- await expect(mutate({ mutation: createGroupMutation, variables })).resolves.toMatchObject(
- {
- data: { CreateGroup: { disabled: false, deleted: false } },
- },
- )
+ await expect(
+ mutate({ mutation: createGroupMutation(), variables }),
+ ).resolves.toMatchObject({
+ data: { CreateGroup: { disabled: false, deleted: false } },
+ })
})
describe('description', () => {
@@ -338,7 +345,7 @@ describe('in mode', () => {
describe('less then 100 chars', () => {
it('throws error: "Description too short!"', async () => {
const { errors } = await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
...variables,
description:
@@ -361,7 +368,7 @@ describe('in mode', () => {
it('has new categories', async () => {
await expect(
mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
...variables,
categoryIds: ['cat4', 'cat27'],
@@ -386,7 +393,7 @@ describe('in mode', () => {
describe('by "categoryIds: null"', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: { ...variables, categoryIds: null },
})
expect(errors[0]).toHaveProperty('message', 'Too view categories!')
@@ -396,7 +403,7 @@ describe('in mode', () => {
describe('by "categoryIds: []"', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: { ...variables, categoryIds: [] },
})
expect(errors[0]).toHaveProperty('message', 'Too view categories!')
@@ -407,7 +414,7 @@ describe('in mode', () => {
describe('four', () => {
it('throws error: "Too many categories!"', async () => {
const { errors } = await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: { ...variables, categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'] },
})
expect(errors[0]).toHaveProperty('message', 'Too many categories!')
@@ -430,7 +437,7 @@ describe('in mode', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
- const { errors } = await query({ query: groupQuery, variables: {} })
+ const { errors } = await query({ query: groupQuery(), variables: {} })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -464,7 +471,7 @@ describe('in mode', () => {
)
authenticatedUser = await otherUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'others-group',
name: 'Uninteresting Group',
@@ -477,7 +484,7 @@ describe('in mode', () => {
})
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
@@ -489,7 +496,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'second-hidden-group',
name: 'Second Investigative Journalism Group',
@@ -501,7 +508,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'second-hidden-group',
userId: 'current-user',
@@ -509,7 +516,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'third-hidden-group',
name: 'Third Investigative Journalism Group',
@@ -521,7 +528,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'third-hidden-group',
userId: 'current-user',
@@ -530,7 +537,7 @@ describe('in mode', () => {
})
authenticatedUser = await user.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'my-group',
name: 'The Best Group',
@@ -539,6 +546,7 @@ describe('in mode', () => {
groupType: 'public',
actionRadius: 'regional',
categoryIds,
+ locationName: 'Hamburg, Germany',
},
})
})
@@ -546,25 +554,38 @@ describe('in mode', () => {
describe('query groups', () => {
describe('in general finds only listed groups – no hidden groups where user is none or pending member', () => {
describe('without any filters', () => {
- it('finds all listed groups', async () => {
- const result = await query({ query: groupQuery, variables: {} })
+ it('finds all listed groups – including the set descriptionExcerpts and locations', async () => {
+ const result = await query({ query: groupQuery(), variables: {} })
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
id: 'my-group',
slug: 'the-best-group',
+ descriptionExcerpt: 'Some description' + descriptionAdditional100,
+ locationName: 'Hamburg, Germany',
+ location: expect.objectContaining({
+ name: 'Hamburg',
+ nameDE: 'Hamburg',
+ nameEN: 'Hamburg',
+ }),
myRole: 'owner',
}),
expect.objectContaining({
id: 'others-group',
slug: 'uninteresting-group',
+ descriptionExcerpt: 'We love it like it is!?' + descriptionAdditional100,
+ locationName: null,
+ location: null,
myRole: null,
}),
expect.objectContaining({
id: 'third-hidden-group',
slug: 'third-investigative-journalism-group',
+ descriptionExcerpt: 'We research …' + descriptionAdditional100,
myRole: 'usual',
+ locationName: null,
+ location: null,
}),
]),
},
@@ -579,7 +600,9 @@ describe('in mode', () => {
})
it('has set categories', async () => {
- await expect(query({ query: groupQuery, variables: {} })).resolves.toMatchObject({
+ await expect(
+ query({ query: groupQuery(), variables: {} }),
+ ).resolves.toMatchObject({
data: {
Group: expect.arrayContaining([
expect.objectContaining({
@@ -613,7 +636,7 @@ describe('in mode', () => {
describe('with given id', () => {
describe("id = 'my-group'", () => {
it('finds only the listed group with this id', async () => {
- const result = await query({ query: groupQuery, variables: { id: 'my-group' } })
+ const result = await query({ query: groupQuery(), variables: { id: 'my-group' } })
expect(result).toMatchObject({
data: {
Group: [
@@ -633,7 +656,7 @@ describe('in mode', () => {
describe("id = 'third-hidden-group'", () => {
it("finds only the hidden group where I'm 'usual' member", async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { id: 'third-hidden-group' },
})
expect(result).toMatchObject({
@@ -655,7 +678,7 @@ describe('in mode', () => {
describe("id = 'second-hidden-group'", () => {
it("finds no hidden group where I'm 'pending' member", async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { id: 'second-hidden-group' },
})
expect(result.data.Group.length).toBe(0)
@@ -665,7 +688,7 @@ describe('in mode', () => {
describe("id = 'hidden-group'", () => {
it("finds no hidden group where I'm not(!) a member at all", async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { id: 'hidden-group' },
})
expect(result.data.Group.length).toBe(0)
@@ -677,7 +700,7 @@ describe('in mode', () => {
describe("slug = 'the-best-group'", () => {
it('finds only the listed group with this slug', async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { slug: 'the-best-group' },
})
expect(result).toMatchObject({
@@ -699,7 +722,7 @@ describe('in mode', () => {
describe("slug = 'third-investigative-journalism-group'", () => {
it("finds only the hidden group where I'm 'usual' member", async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { slug: 'third-investigative-journalism-group' },
})
expect(result).toMatchObject({
@@ -721,7 +744,7 @@ describe('in mode', () => {
describe("slug = 'second-investigative-journalism-group'", () => {
it("finds no hidden group where I'm 'pending' member", async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { slug: 'second-investigative-journalism-group' },
})
expect(result.data.Group.length).toBe(0)
@@ -731,7 +754,7 @@ describe('in mode', () => {
describe("slug = 'investigative-journalism-group'", () => {
it("finds no hidden group where I'm not(!) a member at all", async () => {
const result = await query({
- query: groupQuery,
+ query: groupQuery(),
variables: { slug: 'investigative-journalism-group' },
})
expect(result.data.Group.length).toBe(0)
@@ -741,7 +764,7 @@ describe('in mode', () => {
describe('isMember = true', () => {
it('finds only listed groups where user is member', async () => {
- const result = await query({ query: groupQuery, variables: { isMember: true } })
+ const result = await query({ query: groupQuery(), variables: { isMember: true } })
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
@@ -765,7 +788,7 @@ describe('in mode', () => {
describe('isMember = false', () => {
it('finds only listed groups where user is not(!) member', async () => {
- const result = await query({ query: groupQuery, variables: { isMember: false } })
+ const result = await query({ query: groupQuery(), variables: { isMember: false } })
expect(result).toMatchObject({
data: {
Group: expect.arrayContaining([
@@ -798,7 +821,7 @@ describe('in mode', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'not-existing-group',
userId: 'current-user',
@@ -840,7 +863,7 @@ describe('in mode', () => {
// public-group
authenticatedUser = await ownerOfClosedGroupUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'closed-group',
name: 'Uninteresting Group',
@@ -853,7 +876,7 @@ describe('in mode', () => {
})
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
@@ -866,7 +889,7 @@ describe('in mode', () => {
})
authenticatedUser = await user.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'public-group',
name: 'The Best Group',
@@ -884,7 +907,7 @@ describe('in mode', () => {
it('has "usual" as membership role', async () => {
await expect(
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-closed-group',
@@ -907,7 +930,7 @@ describe('in mode', () => {
it('has still "owner" as membership role', async () => {
await expect(
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'current-user',
@@ -932,7 +955,7 @@ describe('in mode', () => {
it('has "pending" as membership role', async () => {
await expect(
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'closed-group',
userId: 'current-user',
@@ -955,7 +978,7 @@ describe('in mode', () => {
it('has still "owner" as membership role', async () => {
await expect(
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'closed-group',
userId: 'owner-of-closed-group',
@@ -979,7 +1002,7 @@ describe('in mode', () => {
describe('joined by "owner-of-closed-group"', () => {
it('throws authorization error', async () => {
const { errors } = await query({
- query: joinGroupMutation,
+ query: joinGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-of-closed-group',
@@ -994,7 +1017,7 @@ describe('in mode', () => {
it('has still "owner" as membership role', async () => {
await expect(
mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-of-hidden-group',
@@ -1030,7 +1053,7 @@ describe('in mode', () => {
variables = {
id: 'not-existing-group',
}
- const { errors } = await query({ query: groupMembersQuery, variables })
+ const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -1091,7 +1114,7 @@ describe('in mode', () => {
// public-group
authenticatedUser = await user.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'public-group',
name: 'The Best Group',
@@ -1103,14 +1126,14 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-closed-group',
},
})
await mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'public-group',
userId: 'owner-of-hidden-group',
@@ -1119,7 +1142,7 @@ describe('in mode', () => {
// closed-group
authenticatedUser = await ownerOfClosedGroupUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'closed-group',
name: 'Uninteresting Group',
@@ -1131,14 +1154,14 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: joinGroupMutation,
+ mutation: joinGroupMutation(),
variables: {
groupId: 'closed-group',
userId: 'current-user',
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'owner-of-hidden-group',
@@ -1148,7 +1171,7 @@ describe('in mode', () => {
// hidden-group
authenticatedUser = await ownerOfHiddenGroupUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'hidden-group',
name: 'Investigative Journalism Group',
@@ -1161,7 +1184,7 @@ describe('in mode', () => {
})
// 'JoinGroup' mutation does not work in hidden groups so we join them by 'ChangeGroupMemberRole' through the owner
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'pending-user',
@@ -1169,7 +1192,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'current-user',
@@ -1177,7 +1200,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'hidden-group',
userId: 'owner-of-closed-group',
@@ -1203,7 +1226,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1236,7 +1259,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1269,7 +1292,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1312,7 +1335,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1345,7 +1368,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1377,7 +1400,7 @@ describe('in mode', () => {
})
it('throws authorization error', async () => {
- const { errors } = await query({ query: groupMembersQuery, variables })
+ const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -1388,7 +1411,7 @@ describe('in mode', () => {
})
it('throws authorization error', async () => {
- const { errors } = await query({ query: groupMembersQuery, variables })
+ const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -1410,7 +1433,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1447,7 +1470,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1484,7 +1507,7 @@ describe('in mode', () => {
it('finds all members', async () => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables,
})
expect(result).toMatchObject({
@@ -1520,7 +1543,7 @@ describe('in mode', () => {
})
it('throws authorization error', async () => {
- const { errors } = await query({ query: groupMembersQuery, variables })
+ const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -1531,7 +1554,7 @@ describe('in mode', () => {
})
it('throws authorization error', async () => {
- const { errors } = await query({ query: groupMembersQuery, variables })
+ const { errors } = await query({ query: groupMembersQuery(), variables })
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
})
})
@@ -1552,7 +1575,7 @@ describe('in mode', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'not-existing-group',
userId: 'current-user',
@@ -1596,7 +1619,7 @@ describe('in mode', () => {
it('has role usual', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -1634,7 +1657,7 @@ describe('in mode', () => {
it('has role admin', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -1669,7 +1692,7 @@ describe('in mode', () => {
it('has role owner', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -1711,7 +1734,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1737,7 +1760,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1755,7 +1778,7 @@ describe('in mode', () => {
it('has role owner still', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -1786,7 +1809,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1809,7 +1832,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1832,7 +1855,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1865,7 +1888,7 @@ describe('in mode', () => {
it('has role owner', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -1890,7 +1913,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1913,7 +1936,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1930,7 +1953,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1953,7 +1976,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1970,7 +1993,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -1993,7 +2016,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2010,7 +2033,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2043,7 +2066,7 @@ describe('in mode', () => {
it('has role admin', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -2069,7 +2092,7 @@ describe('in mode', () => {
it('has role usual again', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -2100,7 +2123,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2117,7 +2140,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2140,7 +2163,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2157,7 +2180,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2180,7 +2203,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2197,7 +2220,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2230,7 +2253,7 @@ describe('in mode', () => {
it('has role usual', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -2256,7 +2279,7 @@ describe('in mode', () => {
it('has role usual again', async () => {
await expect(
mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
}),
).resolves.toMatchObject({
@@ -2287,7 +2310,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2310,7 +2333,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2333,7 +2356,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables,
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
@@ -2352,7 +2375,7 @@ describe('in mode', () => {
// closed-group
authenticatedUser = await ownerMemberUser.toJson()
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'pending-member-user',
@@ -2360,7 +2383,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'usual-member-user',
@@ -2368,7 +2391,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'admin-member-user',
@@ -2376,7 +2399,7 @@ describe('in mode', () => {
},
})
await mutate({
- mutation: changeGroupMemberRoleMutation,
+ mutation: changeGroupMemberRoleMutation(),
variables: {
groupId: 'closed-group',
userId: 'second-owner-member-user',
@@ -2394,7 +2417,7 @@ describe('in mode', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
groupId: 'not-existing-group',
userId: 'current-user',
@@ -2409,7 +2432,7 @@ describe('in mode', () => {
describe('here "closed-group" for example', () => {
const memberInGroup = async (userId, groupId) => {
const result = await query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables: {
id: groupId,
},
@@ -2433,7 +2456,7 @@ describe('in mode', () => {
authenticatedUser = await pendingMemberUser.toJson()
await expect(
mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'pending-member-user',
@@ -2460,7 +2483,7 @@ describe('in mode', () => {
authenticatedUser = await usualMemberUser.toJson()
await expect(
mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'usual-member-user',
@@ -2487,7 +2510,7 @@ describe('in mode', () => {
authenticatedUser = await adminMemberUser.toJson()
await expect(
mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'admin-member-user',
@@ -2511,7 +2534,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
authenticatedUser = await ownerMemberUser.toJson()
const { errors } = await mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'owner-member-user',
@@ -2525,7 +2548,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
authenticatedUser = await secondOwnerMemberUser.toJson()
const { errors } = await mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'second-owner-member-user',
@@ -2539,7 +2562,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
authenticatedUser = await noMemberUser.toJson()
const { errors } = await mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'none-member-user',
@@ -2553,7 +2576,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
authenticatedUser = await ownerMemberUser.toJson()
const { errors } = await mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'usual-member-user',
@@ -2567,7 +2590,7 @@ describe('in mode', () => {
it('throws authorization error', async () => {
authenticatedUser = await usualMemberUser.toJson()
const { errors } = await mutate({
- mutation: leaveGroupMutation,
+ mutation: leaveGroupMutation(),
variables: {
...variables,
userId: 'admin-member-user',
@@ -2593,7 +2616,7 @@ describe('in mode', () => {
describe('unauthenticated', () => {
it('throws authorization error', async () => {
const { errors } = await mutate({
- query: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: 'my-group',
slug: 'my-best-group',
@@ -2604,23 +2627,34 @@ describe('in mode', () => {
})
describe('authenticated', () => {
- let otherUser
+ let noMemberUser
beforeAll(async () => {
- otherUser = await Factory.build(
+ noMemberUser = await Factory.build(
'user',
{
- id: 'other-user',
- name: 'Other TestUser',
+ id: 'none-member-user',
+ name: 'None Member TestUser',
},
{
- email: 'test2@example.org',
+ email: 'none-member-user@example.org',
password: '1234',
},
)
- authenticatedUser = await otherUser.toJson()
+ usualMemberUser = await Factory.build(
+ 'user',
+ {
+ id: 'usual-member-user',
+ name: 'Usual Member TestUser',
+ },
+ {
+ email: 'usual-member-user@example.org',
+ password: '1234',
+ },
+ )
+ authenticatedUser = await noMemberUser.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'others-group',
name: 'Uninteresting Group',
@@ -2633,7 +2667,7 @@ describe('in mode', () => {
})
authenticatedUser = await user.toJson()
await mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables: {
id: 'my-group',
name: 'The Best Group',
@@ -2642,6 +2676,15 @@ describe('in mode', () => {
groupType: 'public',
actionRadius: 'regional',
categoryIds,
+ locationName: 'Berlin, Germany',
+ },
+ })
+ await mutate({
+ mutation: changeGroupMemberRoleMutation(),
+ variables: {
+ groupId: 'my-group',
+ userId: 'usual-member-user',
+ roleInGroup: 'usual',
},
})
})
@@ -2652,35 +2695,170 @@ describe('in mode', () => {
authenticatedUser = await user.toJson()
})
- it('has set the settings', async () => {
- await expect(
- mutate({
- mutation: updateGroupMutation,
- variables: {
- id: 'my-group',
- name: 'The New Group For Our Country',
- about: 'We will change the land!',
- description: 'Some country relevant description' + descriptionAdditional100,
- actionRadius: 'national',
- // avatar, // test this as result
- // locationName, // test this as result
+ describe('all standard settings – excluding location', () => {
+ it('has updated the settings', async () => {
+ await expect(
+ mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ name: 'The New Group For Our Country',
+ about: 'We will change the land!',
+ description: 'Some country relevant description' + descriptionAdditional100,
+ actionRadius: 'national',
+ // avatar, // test this as result
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: {
+ UpdateGroup: {
+ id: 'my-group',
+ name: 'The New Group For Our Country',
+ slug: 'the-new-group-for-our-country', // changing the slug is tested in the slugifyMiddleware
+ about: 'We will change the land!',
+ description: 'Some country relevant description' + descriptionAdditional100,
+ descriptionExcerpt:
+ 'Some country relevant description' + descriptionAdditional100,
+ actionRadius: 'national',
+ // avatar, // test this as result
+ myRole: 'owner',
+ },
},
- }),
- ).resolves.toMatchObject({
- data: {
- UpdateGroup: {
- id: 'my-group',
- name: 'The New Group For Our Country',
- slug: 'the-new-group-for-our-country', // changing the slug is tested in the slugifyMiddleware
- about: 'We will change the land!',
- description: 'Some country relevant description' + descriptionAdditional100,
- actionRadius: 'national',
- // avatar, // test this as result
- // locationName, // test this as result
- myRole: 'owner',
- },
- },
- errors: undefined,
+ errors: undefined,
+ })
+ })
+ })
+
+ describe('location', () => {
+ describe('"locationName" is undefined – shall not change location', () => {
+ it('has left locaton unchanged as "Berlin"', async () => {
+ await expect(
+ mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: {
+ UpdateGroup: {
+ id: 'my-group',
+ locationName: 'Berlin, Germany',
+ location: expect.objectContaining({
+ name: 'Berlin',
+ nameDE: 'Berlin',
+ nameEN: 'Berlin',
+ }),
+ myRole: 'owner',
+ },
+ },
+ errors: undefined,
+ })
+ })
+ })
+
+ describe('"locationName" is null – shall change location "Berlin" to unset location', () => {
+ it('has updated the location to unset location', async () => {
+ await expect(
+ mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ locationName: null,
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: {
+ UpdateGroup: {
+ id: 'my-group',
+ locationName: null,
+ location: null,
+ myRole: 'owner',
+ },
+ },
+ errors: undefined,
+ })
+ })
+ })
+
+ describe('change unset location to "Paris"', () => {
+ it('has updated the location to "Paris"', async () => {
+ await expect(
+ mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ locationName: 'Paris, France',
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: {
+ UpdateGroup: {
+ id: 'my-group',
+ locationName: 'Paris, France',
+ location: expect.objectContaining({
+ name: 'Paris',
+ nameDE: 'Paris',
+ nameEN: 'Paris',
+ }),
+ myRole: 'owner',
+ },
+ },
+ errors: undefined,
+ })
+ })
+ })
+
+ describe('change location "Paris" to "Hamburg"', () => {
+ it('has updated the location to "Hamburg"', async () => {
+ await expect(
+ mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ locationName: 'Hamburg, Germany',
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: {
+ UpdateGroup: {
+ id: 'my-group',
+ locationName: 'Hamburg, Germany',
+ location: expect.objectContaining({
+ name: 'Hamburg',
+ nameDE: 'Hamburg',
+ nameEN: 'Hamburg',
+ }),
+ myRole: 'owner',
+ },
+ },
+ errors: undefined,
+ })
+ })
+ })
+
+ describe('"locationName" is empty string – shall change location "Hamburg" to unset location ', () => {
+ it('has updated the location to unset', async () => {
+ await expect(
+ mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ locationName: '', // empty string '' sets it to null
+ },
+ }),
+ ).resolves.toMatchObject({
+ data: {
+ UpdateGroup: {
+ id: 'my-group',
+ locationName: null,
+ location: null,
+ myRole: 'owner',
+ },
+ },
+ errors: undefined,
+ })
+ })
})
})
@@ -2689,7 +2867,7 @@ describe('in mode', () => {
describe('less then 100 chars', () => {
it('throws error: "Description too short!"', async () => {
const { errors } = await mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: 'my-group',
description:
@@ -2712,7 +2890,7 @@ describe('in mode', () => {
it('has new categories', async () => {
await expect(
mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: 'my-group',
categoryIds: ['cat4', 'cat27'],
@@ -2738,7 +2916,7 @@ describe('in mode', () => {
describe('by "categoryIds: []"', () => {
it('throws error: "Too view categories!"', async () => {
const { errors } = await mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: 'my-group',
categoryIds: [],
@@ -2752,7 +2930,7 @@ describe('in mode', () => {
describe('four', () => {
it('throws error: "Too many categories!"', async () => {
const { errors } = await mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: 'my-group',
categoryIds: ['cat9', 'cat4', 'cat15', 'cat27'],
@@ -2764,20 +2942,36 @@ describe('in mode', () => {
})
})
- describe('as no(!) owner', () => {
+ describe('as "usual-member-user" member, no(!) owner', () => {
it('throws authorization error', async () => {
- authenticatedUser = await otherUser.toJson()
+ authenticatedUser = await usualMemberUser.toJson()
const { errors } = await mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables: {
id: 'my-group',
name: 'The New Group For Our Country',
about: 'We will change the land!',
description: 'Some country relevant description' + descriptionAdditional100,
actionRadius: 'national',
- categoryIds: ['cat4', 'cat27'], // test this as result
- // avatar, // test this as result
- // locationName, // test this as result
+ categoryIds: ['cat4', 'cat27'],
+ },
+ })
+ expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
+ })
+ })
+
+ describe('as "none-member-user"', () => {
+ it('throws authorization error', async () => {
+ authenticatedUser = await noMemberUser.toJson()
+ const { errors } = await mutate({
+ mutation: updateGroupMutation(),
+ variables: {
+ id: 'my-group',
+ name: 'The New Group For Our Country',
+ about: 'We will change the land!',
+ description: 'Some country relevant description' + descriptionAdditional100,
+ actionRadius: 'national',
+ categoryIds: ['cat4', 'cat27'],
},
})
expect(errors[0]).toHaveProperty('message', 'Not Authorized!')
diff --git a/backend/src/schema/resolvers/users.js b/backend/src/schema/resolvers/users.js
index 12f00ffb6..1ce3b986f 100644
--- a/backend/src/schema/resolvers/users.js
+++ b/backend/src/schema/resolvers/users.js
@@ -4,7 +4,7 @@ import { UserInputError, ForbiddenError } from 'apollo-server'
import { mergeImage, deleteImage } from './images/images'
import Resolver from './helpers/Resolver'
import log from './helpers/databaseLogger'
-import createOrUpdateLocations from './users/location'
+import { createOrUpdateLocations } from './users/location'
const neode = getNeode()
@@ -139,9 +139,10 @@ export default {
return blockedUser.toJson()
},
UpdateUser: async (_parent, params, context, _resolveInfo) => {
- const { termsAndConditionsAgreedVersion } = params
const { avatar: avatarInput } = params
delete params.avatar
+ params.locationName = params.locationName === '' ? null : params.locationName
+ const { termsAndConditionsAgreedVersion } = params
if (termsAndConditionsAgreedVersion) {
const regEx = new RegExp(/^[0-9]+\.[0-9]+\.[0-9]+$/g)
if (!regEx.test(termsAndConditionsAgreedVersion)) {
@@ -169,7 +170,8 @@ export default {
})
try {
const user = await writeTxResultPromise
- await createOrUpdateLocations(params.id, params.locationName, session)
+ // TODO: put in a middleware, see "CreateGroup", "UpdateGroup"
+ await createOrUpdateLocations('User', params.id, params.locationName, session)
return user
} catch (error) {
throw new UserInputError(error.message)
diff --git a/backend/src/schema/resolvers/users.spec.js b/backend/src/schema/resolvers/users.spec.js
index d8fce3b29..87226ec4d 100644
--- a/backend/src/schema/resolvers/users.spec.js
+++ b/backend/src/schema/resolvers/users.spec.js
@@ -161,7 +161,7 @@ describe('UpdateUser', () => {
$id: ID!
$name: String
$termsAndConditionsAgreedVersion: String
- $locationName: String
+ $locationName: String # empty string '' sets it to null
) {
UpdateUser(
id: $id
@@ -174,6 +174,11 @@ describe('UpdateUser', () => {
termsAndConditionsAgreedVersion
termsAndConditionsAgreedAt
locationName
+ location {
+ name
+ nameDE
+ nameEN
+ }
}
}
`
@@ -289,11 +294,39 @@ describe('UpdateUser', () => {
expect(errors[0]).toHaveProperty('message', 'Invalid version format!')
})
- it('supports updating location', async () => {
- variables = { ...variables, locationName: 'Hamburg, New Jersey, United States' }
- await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
- data: { UpdateUser: { locationName: 'Hamburg, New Jersey, United States' } },
- errors: undefined,
+ describe('supports updating location', () => {
+ describe('change location to "Hamburg, New Jersey, United States"', () => {
+ it('has updated location to "Hamburg, New Jersey, United States"', async () => {
+ variables = { ...variables, locationName: 'Hamburg, New Jersey, United States' }
+ await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
+ data: {
+ UpdateUser: {
+ locationName: 'Hamburg, New Jersey, United States',
+ location: expect.objectContaining({
+ name: 'Hamburg',
+ nameDE: 'Hamburg',
+ nameEN: 'Hamburg',
+ }),
+ },
+ },
+ errors: undefined,
+ })
+ })
+ })
+
+ describe('change location to unset location', () => {
+ it('has updated location to unset location', async () => {
+ variables = { ...variables, locationName: '' }
+ await expect(mutate({ mutation: updateUserMutation, variables })).resolves.toMatchObject({
+ data: {
+ UpdateUser: {
+ locationName: null,
+ location: null,
+ },
+ },
+ errors: undefined,
+ })
+ })
})
})
})
diff --git a/backend/src/schema/resolvers/users/location.js b/backend/src/schema/resolvers/users/location.js
index affd3267e..9d8a11f89 100644
--- a/backend/src/schema/resolvers/users/location.js
+++ b/backend/src/schema/resolvers/users/location.js
@@ -1,6 +1,5 @@
import request from 'request'
import { UserInputError } from 'apollo-server'
-import isEmpty from 'lodash/isEmpty'
import Debug from 'debug'
import asyncForEach from '../../../helpers/asyncForEach'
import CONFIG from '../../../config'
@@ -62,77 +61,86 @@ const createLocation = async (session, mapboxData) => {
})
}
-const createOrUpdateLocations = async (userId, locationName, session) => {
- if (isEmpty(locationName)) {
- return
- }
- const res = await fetch(
- `https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
- locationName,
- )}.json?access_token=${CONFIG.MAPBOX_TOKEN}&types=region,place,country&language=${locales.join(
- ',',
- )}`,
- )
+export const createOrUpdateLocations = async (nodeLabel, nodeId, locationName, session) => {
+ if (locationName === undefined) return
- debug(res)
+ let locationId
- if (!res || !res.features || !res.features[0]) {
- throw new UserInputError('locationName is invalid')
- }
+ if (locationName !== null) {
+ const res = await fetch(
+ `https://api.mapbox.com/geocoding/v5/mapbox.places/${encodeURIComponent(
+ locationName,
+ )}.json?access_token=${
+ CONFIG.MAPBOX_TOKEN
+ }&types=region,place,country&language=${locales.join(',')}`,
+ )
- let data
+ debug(res)
- res.features.forEach((item) => {
- if (item.matching_place_name === locationName) {
- data = item
+ if (!res || !res.features || !res.features[0]) {
+ throw new UserInputError('locationName is invalid')
}
- })
- if (!data) {
- data = res.features[0]
- }
- if (!data || !data.place_type || !data.place_type.length) {
- throw new UserInputError('locationName is invalid')
- }
+ let data
- if (data.place_type.length > 1) {
- data.id = 'region.' + data.id.split('.')[1]
- }
- await createLocation(session, data)
-
- let parent = data
-
- if (data.context) {
- await asyncForEach(data.context, async (ctx) => {
- await createLocation(session, ctx)
- await session.writeTransaction((transaction) => {
- return transaction.run(
- `
- MATCH (parent:Location {id: $parentId}), (child:Location {id: $childId})
- MERGE (child)<-[:IS_IN]-(parent)
- RETURN child.id, parent.id
- `,
- {
- parentId: parent.id,
- childId: ctx.id,
- },
- )
- })
- parent = ctx
+ res.features.forEach((item) => {
+ if (item.matching_place_name === locationName) {
+ data = item
+ }
})
+ if (!data) {
+ data = res.features[0]
+ }
+
+ if (!data || !data.place_type || !data.place_type.length) {
+ throw new UserInputError('locationName is invalid')
+ }
+
+ if (data.place_type.length > 1) {
+ data.id = 'region.' + data.id.split('.')[1]
+ }
+ await createLocation(session, data)
+
+ let parent = data
+
+ if (data.context) {
+ await asyncForEach(data.context, async (ctx) => {
+ await createLocation(session, ctx)
+ await session.writeTransaction((transaction) => {
+ return transaction.run(
+ `
+ MATCH (parent:Location {id: $parentId}), (child:Location {id: $childId})
+ MERGE (child)<-[:IS_IN]-(parent)
+ RETURN child.id, parent.id
+ `,
+ {
+ parentId: parent.id,
+ childId: ctx.id,
+ },
+ )
+ })
+ parent = ctx
+ })
+ }
+
+ locationId = data.id
+ } else {
+ locationId = 'non-existent-id'
}
- // delete all current locations from user and add new location
+
+ // delete all current locations from node and add new location
await session.writeTransaction((transaction) => {
return transaction.run(
`
- MATCH (user:User {id: $userId})-[relationship:IS_IN]->(location:Location)
- DETACH DELETE relationship
- WITH user
- MATCH (location:Location {id: $locationId})
- MERGE (user)-[:IS_IN]->(location)
- RETURN location.id, user.id
- `,
- { userId: userId, locationId: data.id },
+ MATCH (node:${nodeLabel} {id: $nodeId})
+ OPTIONAL MATCH (node)-[relationship:IS_IN]->(:Location)
+ DELETE relationship
+ WITH node
+ MATCH (location:Location {id: $locationId})
+ MERGE (node)-[:IS_IN]->(location)
+ RETURN location.id, node.id
+ `,
+ { nodeId, locationId },
)
})
}
@@ -147,5 +155,3 @@ export const queryLocations = async ({ place, lang }) => {
}
return res.features
}
-
-export default createOrUpdateLocations
diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql
index 084145d1c..9f9b18da5 100644
--- a/backend/src/schema/types/type/Group.gql
+++ b/backend/src/schema/types/type/Group.gql
@@ -33,8 +33,8 @@ type Group {
groupType: GroupType!
actionRadius: GroupActionRadius!
- location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
locationName: String
+ location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT")
@@ -95,7 +95,7 @@ type Mutation {
actionRadius: GroupActionRadius!
categoryIds: [ID]
# avatar: ImageInput # a group can not be created with an avatar
- locationName: String # test this as result
+ locationName: String # empty string '' sets it to null
): Group
UpdateGroup(
@@ -108,7 +108,7 @@ type Mutation {
actionRadius: GroupActionRadius
categoryIds: [ID]
avatar: ImageInput # test this as result
- locationName: String # test this as result
+ locationName: String # empty string '' sets it to null
): Group
# DeleteGroup(id: ID!): Group
diff --git a/backend/src/schema/types/type/User.gql b/backend/src/schema/types/type/User.gql
index 2861b0fda..fdab73d17 100644
--- a/backend/src/schema/types/type/User.gql
+++ b/backend/src/schema/types/type/User.gql
@@ -33,8 +33,8 @@ type User {
invitedBy: User @relation(name: "INVITED", direction: "IN")
invited: [User] @relation(name: "INVITED", direction: "OUT")
- location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
locationName: String
+ location: Location @cypher(statement: "MATCH (this)-[:IS_IN]->(l:Location) RETURN l")
about: String
socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN")
@@ -212,7 +212,7 @@ type Mutation {
email: String
slug: String
avatar: ImageInput
- locationName: String
+ locationName: String # empty string '' sets it to null
about: String
termsAndConditionsAgreedVersion: String
termsAndConditionsAgreedAt: String
diff --git a/webapp/components/Button/JoinLeaveButton.vue b/webapp/components/Button/JoinLeaveButton.vue
index 993631065..9bcb5042a 100644
--- a/webapp/components/Button/JoinLeaveButton.vue
+++ b/webapp/components/Button/JoinLeaveButton.vue
@@ -1,6 +1,6 @@
diff --git a/webapp/pages/group/create.vue b/webapp/pages/group/create.vue
index 27204c71f..c72d45c75 100644
--- a/webapp/pages/group/create.vue
+++ b/webapp/pages/group/create.vue
@@ -41,7 +41,7 @@ export default {
}
try {
await this.$apollo.mutate({
- mutation: createGroupMutation,
+ mutation: createGroupMutation(),
variables,
})
this.$toast.success(this.$t('group.groupCreated'))
diff --git a/webapp/pages/group/edit/_id.vue b/webapp/pages/group/edit/_id.vue
index c60300a3a..159a88b61 100644
--- a/webapp/pages/group/edit/_id.vue
+++ b/webapp/pages/group/edit/_id.vue
@@ -56,7 +56,7 @@ export default {
Group: [group],
},
} = await client.query({
- query: groupQuery,
+ query: groupQuery(), // "this.$i18n" is undefined here, so we use default lang
variables: { id },
})
if (group.myRole !== 'owner') {
diff --git a/webapp/pages/group/edit/_id/index.vue b/webapp/pages/group/edit/_id/index.vue
index 85b775e78..27e216464 100644
--- a/webapp/pages/group/edit/_id/index.vue
+++ b/webapp/pages/group/edit/_id/index.vue
@@ -37,7 +37,7 @@ export default {
}
try {
await this.$apollo.mutate({
- mutation: updateGroupMutation,
+ mutation: updateGroupMutation(),
variables,
})
this.$toast.success(this.$t('group.group-updated'))
diff --git a/webapp/pages/group/edit/_id/members.vue b/webapp/pages/group/edit/_id/members.vue
index 970aac106..2f9e2b442 100644
--- a/webapp/pages/group/edit/_id/members.vue
+++ b/webapp/pages/group/edit/_id/members.vue
@@ -28,7 +28,7 @@ export default {
async groupMembersQueryList() {
try {
const response = await this.$apollo.query({
- query: groupMembersQuery,
+ query: groupMembersQuery(),
variables: { id: this.group.id },
})
this.responseGroupMembersQuery = response.data.GroupMembers
diff --git a/webapp/pages/index.vue b/webapp/pages/index.vue
index 729edc415..2b142648e 100644
--- a/webapp/pages/index.vue
+++ b/webapp/pages/index.vue
@@ -38,7 +38,6 @@
v-tooltip="{
content: $t('contribution.newPost'),
placement: 'left',
- delay: { show: 500 },
}"
class="post-add-button"
icon="plus"
diff --git a/webapp/pages/my-groups.vue b/webapp/pages/my-groups.vue
index 18bdda59e..1792a3c88 100644
--- a/webapp/pages/my-groups.vue
+++ b/webapp/pages/my-groups.vue
@@ -40,11 +40,12 @@ export default {
async groupListQuery() {
try {
const response = await this.$apollo.query({
- query: groupQuery,
+ query: groupQuery(this.$i18n),
})
this.responseGroupListQuery = response.data.Group
} catch (error) {
this.responseGroupListQuery = []
+ this.$toast.error(error.message)
} finally {
this.pending = false
}
diff --git a/webapp/pages/post/_id/_slug/index.vue b/webapp/pages/post/_id/_slug/index.vue
index ff5c9a498..724704f67 100644
--- a/webapp/pages/post/_id/_slug/index.vue
+++ b/webapp/pages/post/_id/_slug/index.vue
@@ -46,7 +46,6 @@
-
diff --git a/webapp/pages/profile/_id/_slug.vue b/webapp/pages/profile/_id/_slug.vue
index b4ed11e79..668c271d6 100644
--- a/webapp/pages/profile/_id/_slug.vue
+++ b/webapp/pages/profile/_id/_slug.vue
@@ -120,7 +120,6 @@
v-tooltip="{
content: $t('contribution.newPost'),
placement: 'left',
- delay: { show: 500 },
}"
:path="{ name: 'post-create' }"
class="profile-post-add-button"
@@ -238,7 +237,7 @@ export default {
followedByCountStartValue: 0,
followedByCount: followListVisibleCount,
followingCount: followListVisibleCount,
- updateUserMutation: updateUserMutation(),
+ updateUserMutation,
}
},
computed: {
diff --git a/webapp/pages/terms-and-conditions-confirm.vue b/webapp/pages/terms-and-conditions-confirm.vue
index 30b4db6ef..5eef8ce66 100644
--- a/webapp/pages/terms-and-conditions-confirm.vue
+++ b/webapp/pages/terms-and-conditions-confirm.vue
@@ -25,6 +25,7 @@ import { VERSION } from '~/constants/terms-and-conditions-version.js'
import { updateUserMutation } from '~/graphql/User.js'
export default {
+ name: 'TermsAndConditionsConfirm',
layout: 'default',
head() {
return {
diff --git a/webapp/plugins/v-tooltip.js b/webapp/plugins/v-tooltip.js
index 77d0ac1b8..73681e9b3 100644
--- a/webapp/plugins/v-tooltip.js
+++ b/webapp/plugins/v-tooltip.js
@@ -3,7 +3,7 @@ import VTooltip from 'v-tooltip'
Vue.use(VTooltip, {
defaultDelay: {
- show: 500,
+ show: 1500,
hide: 50,
},
defaultOffset: 2,