diff --git a/backend/src/db/graphql/mutations.ts b/backend/src/db/graphql/mutations.ts index c49856f2a..4f07e0f1e 100644 --- a/backend/src/db/graphql/mutations.ts +++ b/backend/src/db/graphql/mutations.ts @@ -30,9 +30,10 @@ export const createGroupMutation = gql` actionRadius disabled deleted - owner { - name - } + myRole + # Wolle: owner { + # name + # } } } ` diff --git a/backend/src/models/Group.js b/backend/src/models/Group.js index 53b02fbec..0cec02bf8 100644 --- a/backend/src/models/Group.js +++ b/backend/src/models/Group.js @@ -33,15 +33,17 @@ export default { groupType: { type: 'string', default: 'public' }, actionRadius: { type: 'string', default: 'regional' }, + myRole: { type: 'string', default: 'pending' }, + locationName: { type: 'string', allow: [null] }, wasSeeded: 'boolean', // Wolle: used or needed? - owner: { - type: 'relationship', - relationship: 'OWNS', - target: 'User', - direction: 'in', - }, + // Wolle: owner: { + // type: 'relationship', + // relationship: 'OWNS', + // target: 'User', + // direction: 'in', + // }, // Wolle: followedBy: { // type: 'relationship', // relationship: 'FOLLOWS', diff --git a/backend/src/schema/resolvers/groups.js b/backend/src/schema/resolvers/groups.js index 0ed5d1356..b202c6037 100644 --- a/backend/src/schema/resolvers/groups.js +++ b/backend/src/schema/resolvers/groups.js @@ -18,63 +18,47 @@ import Resolver from './helpers/Resolver' // } export default { - // Wolle: Query: { - // Post: async (object, params, context, resolveInfo) => { - // params = await filterForMutedUsers(params, context) - // params = await maintainPinnedPosts(params) - // return neo4jgraphql(object, params, context, resolveInfo) - // }, - // findPosts: async (object, params, context, resolveInfo) => { - // params = await filterForMutedUsers(params, context) - // return neo4jgraphql(object, params, context, resolveInfo) - // }, - // profilePagePosts: async (object, params, context, resolveInfo) => { - // params = await filterForMutedUsers(params, context) - // return neo4jgraphql(object, params, context, resolveInfo) - // }, - // PostsEmotionsCountByEmotion: async (object, params, context, resolveInfo) => { - // const { postId, data } = params - // const session = context.driver.session() - // const readTxResultPromise = session.readTransaction(async (transaction) => { - // const emotionsCountTransactionResponse = await transaction.run( - // ` - // MATCH (post:Post {id: $postId})<-[emoted:EMOTED {emotion: $data.emotion}]-() - // RETURN COUNT(DISTINCT emoted) as emotionsCount - // `, - // { postId, data }, - // ) - // return emotionsCountTransactionResponse.records.map( - // (record) => record.get('emotionsCount').low, - // ) - // }) - // try { - // const [emotionsCount] = await readTxResultPromise - // return emotionsCount - // } finally { - // session.close() - // } - // }, - // PostsEmotionsByCurrentUser: async (object, params, context, resolveInfo) => { - // const { postId } = params - // const session = context.driver.session() - // const readTxResultPromise = session.readTransaction(async (transaction) => { - // const emotionsTransactionResponse = await transaction.run( - // ` - // MATCH (user:User {id: $userId})-[emoted:EMOTED]->(post:Post {id: $postId}) - // RETURN collect(emoted.emotion) as emotion - // `, - // { userId: context.user.id, postId }, - // ) - // return emotionsTransactionResponse.records.map((record) => record.get('emotion')) - // }) - // try { - // const [emotions] = await readTxResultPromise - // return emotions - // } finally { - // session.close() - // } - // }, - // }, + Query: { + // Wolle: Post: async (object, params, context, resolveInfo) => { + // params = await filterForMutedUsers(params, context) + // // params = await maintainPinnedPosts(params) + // return neo4jgraphql(object, params, context, resolveInfo) + // }, + // Group: async (object, params, context, resolveInfo) => { + // // const { email } = params + // const session = context.driver.session() + // const readTxResultPromise = session.readTransaction(async (txc) => { + // const result = await txc.run( + // ` + // MATCH (user:User {id: $userId})-[:MEMBER_OF]->(group:Group) + // RETURN properties(group) AS inviteCodes + // `, + // { + // userId: context.user.id, + // }, + // ) + // return result.records.map((record) => record.get('inviteCodes')) + // }) + // if (email) { + // try { + // session = context.driver.session() + // const readTxResult = await session.readTransaction((txc) => { + // const result = txc.run( + // ` + // MATCH (user:User)-[:PRIMARY_EMAIL]->(e:EmailAddress {email: $args.email}) + // RETURN user`, + // { args }, + // ) + // return result + // }) + // return readTxResult.records.map((r) => r.get('user').properties) + // } finally { + // session.close() + // } + // } + // return neo4jgraphql(object, args, context, resolveInfo) + // }, + }, Mutation: { CreateGroup: async (_parent, params, context, _resolveInfo) => { const { categoryIds } = params @@ -84,12 +68,14 @@ export default { const writeTxResultPromise = session.writeTransaction(async (transaction) => { const categoriesCypher = CONFIG.CATEGORIES_ACTIVE && categoryIds - ? `WITH group - UNWIND $categoryIds AS categoryId - MATCH (category:Category {id: categoryId}) - MERGE (group)-[:CATEGORIZED]->(category)` + ? ` + WITH group, membership + UNWIND $categoryIds AS categoryId + MATCH (category:Category {id: categoryId}) + MERGE (group)-[:CATEGORIZED]->(category) + ` : '' - const ownercreateGroupTransactionResponse = await transaction.run( + const ownerCreateGroupTransactionResponse = await transaction.run( ` CREATE (group:Group) SET group += $params @@ -97,14 +83,16 @@ export default { SET group.updatedAt = toString(datetime()) WITH group MATCH (owner:User {id: $userId}) - MERGE (group)<-[:OWNS]-(owner) - MERGE (group)<-[:ADMINISTERS]-(owner) + MERGE (owner)-[membership:MEMBER_OF]->(group) + SET membership.createdAt = toString(datetime()) + SET membership.updatedAt = toString(datetime()) + SET membership.role = 'owner' ${categoriesCypher} - RETURN group {.*} + RETURN group {.*, myRole: membership.role} `, { userId: context.user.id, categoryIds, params }, ) - const [group] = ownercreateGroupTransactionResponse.records.map((record) => + const [group] = ownerCreateGroupTransactionResponse.records.map((record) => record.get('group'), ) return group @@ -205,10 +193,10 @@ export default { // Wolle: tags: '-[:TAGGED]->(related:Tag)', categories: '-[:CATEGORIZED]->(related:Category)', }, - hasOne: { - owner: '<-[:OWNS]-(related:User)', - // Wolle: image: '-[:HERO_IMAGE]->(related:Image)', - }, + // hasOne: { + // owner: '<-[:OWNS]-(related:User)', + // // Wolle: image: '-[:HERO_IMAGE]->(related:Image)', + // }, // Wolle: count: { // contributionsCount: // '-[:WROTE]->(related:Post) WHERE NOT related.disabled = true AND NOT related.deleted = true', diff --git a/backend/src/schema/resolvers/groups.spec.js b/backend/src/schema/resolvers/groups.spec.js index 4932c2c5e..17fc4b1da 100644 --- a/backend/src/schema/resolvers/groups.spec.js +++ b/backend/src/schema/resolvers/groups.spec.js @@ -292,9 +292,10 @@ describe('CreateGroup', () => { data: { CreateGroup: { name: 'The Best Group', - owner: { - name: 'TestUser', - }, + myRole: 'owner', + // Wolle: owner: { + // name: 'TestUser', + // }, }, }, errors: undefined, diff --git a/backend/src/schema/types/enum/GroupMemberRole.gql b/backend/src/schema/types/enum/GroupMemberRole.gql new file mode 100644 index 000000000..dacdd4b52 --- /dev/null +++ b/backend/src/schema/types/enum/GroupMemberRole.gql @@ -0,0 +1,6 @@ +enum GroupMemberRole { + pending + usual + admin + owner +} diff --git a/backend/src/schema/types/type/Group.gql b/backend/src/schema/types/type/Group.gql index ee71f3e1f..72ac9b57a 100644 --- a/backend/src/schema/types/type/Group.gql +++ b/backend/src/schema/types/type/Group.gql @@ -39,10 +39,12 @@ type Group { categories: [Category] @relation(name: "CATEGORIZED", direction: "OUT") + myRole: GroupMemberRole # if 'null' then the current user is no member + # Wolle: needed? # socialMedia: [SocialMedia]! @relation(name: "OWNED_BY", direction: "IN") - owner: User @relation(name: "OWNS", direction: "IN") + # Wolle: owner: User @relation(name: "OWNS", direction: "IN") # Wolle: showShoutsPublicly: Boolean # Wolle: sendNotificationEmails: Boolean @@ -129,9 +131,12 @@ input _GroupFilter { AND: [_GroupFilter!] OR: [_GroupFilter!] name_contains: String + slug_contains: String about_contains: String description_contains: String - slug_contains: String + groupType_in: [GroupType!] + actionRadius_in: [GroupActionRadius!] + myRole_in: [GroupMemberRole!] id: ID id_not: ID id_in: [ID!] @@ -161,20 +166,18 @@ input _GroupFilter { # followedBy_none: _GroupFilter # followedBy_single: _GroupFilter # followedBy_every: _GroupFilter - # role_in: [UserRole!] } type Query { Group( id: ID - email: String # admins need to search for a user sometimes name: String slug: String + createdAt: String + updatedAt: String locationName: String about: String description: String - createdAt: String - updatedAt: String first: Int offset: Int orderBy: [_GroupOrdering] diff --git a/backend/src/schema/types/type/MEMBER_OF.gql b/backend/src/schema/types/type/MEMBER_OF.gql new file mode 100644 index 000000000..edda989f6 --- /dev/null +++ b/backend/src/schema/types/type/MEMBER_OF.gql @@ -0,0 +1,5 @@ +type MEMBER_OF { + createdAt: String! + updatedAt: String! + role: GroupMemberRole! +}