refactor(backend): allow to set selected badge-slot to null (#8421)

* allow to set selected badgeslot to null

Free a specific badge slot by setting it to null

* Update backend/src/schema/resolvers/users.ts

Co-authored-by: Wolfgang Huß <wolle.huss@pjannto.com>

---------

Co-authored-by: Wolfgang Huß <wolle.huss@pjannto.com>
Co-authored-by: Max <maxharz@gmail.com>
This commit is contained in:
Ulf Gebhardt 2025-04-23 18:21:06 +02:00 committed by GitHub
parent 6b40a0dc59
commit 873cd6cd34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 62 additions and 7 deletions

View File

@ -252,6 +252,6 @@ type Mutation {
# Get a JWT Token for the given Email and password # Get a JWT Token for the given Email and password
login(email: String!, password: String!): String! login(email: String!, password: String!): String!
setTrophyBadgeSelected(slot: Int!, badgeId: ID!): User setTrophyBadgeSelected(slot: Int!, badgeId: ID): User
resetTrophyBadgesSelected: User resetTrophyBadgesSelected: User
} }

View File

@ -76,7 +76,7 @@ const updateOnlineStatus = gql`
` `
const setTrophyBadgeSelected = gql` const setTrophyBadgeSelected = gql`
mutation ($slot: Int!, $badgeId: ID!) { mutation ($slot: Int!, $badgeId: ID) {
setTrophyBadgeSelected(slot: $slot, badgeId: $badgeId) { setTrophyBadgeSelected(slot: $slot, badgeId: $badgeId) {
badgeTrophiesCount badgeTrophiesCount
badgeTrophiesSelected { badgeTrophiesSelected {
@ -1294,6 +1294,53 @@ describe('setTrophyBadgeSelected', () => {
}), }),
) )
}) })
describe('set badge to null', () => {
it('returns the user with no badge set on the selected slot', async () => {
await mutate({
mutation: setTrophyBadgeSelected,
variables: { slot: 0, badgeId: 'trophy_bear' },
})
await mutate({
mutation: setTrophyBadgeSelected,
variables: { slot: 5, badgeId: 'trophy_panda' },
})
await expect(
mutate({
mutation: setTrophyBadgeSelected,
variables: { slot: 5, badgeId: null },
}),
).resolves.toEqual(
expect.objectContaining({
data: {
setTrophyBadgeSelected: {
badgeTrophiesCount: 2,
badgeTrophiesSelected: [
{
id: 'trophy_bear',
},
null,
null,
null,
null,
null,
null,
null,
null,
],
badgeTrophiesUnused: [
{
id: 'trophy_panda',
},
],
badgeTrophiesUnusedCount: 1,
},
},
}),
)
})
})
}) })
}) })

View File

@ -404,17 +404,25 @@ export default {
const session = context.driver.session() const session = context.driver.session()
const query = session.writeTransaction(async (transaction) => { const query = session.writeTransaction(async (transaction) => {
const result = await transaction.run( const queryBadge = `
`
MATCH (user:User {id: $userId})<-[:REWARDED]-(badge:Badge {id: $badgeId}) MATCH (user:User {id: $userId})<-[:REWARDED]-(badge:Badge {id: $badgeId})
OPTIONAL MATCH (user)-[badgeRelation:SELECTED]->(badge) OPTIONAL MATCH (user)-[badgeRelation:SELECTED]->(badge)
OPTIONAL MATCH (user)-[slotRelation:SELECTED{slot: $slot}]->(:Badge) OPTIONAL MATCH (user)-[slotRelation:SELECTED{slot: $slot}]->(:Badge)
DELETE badgeRelation, slotRelation DELETE badgeRelation, slotRelation
MERGE (user)-[:SELECTED{slot: toInteger($slot)}]->(badge) MERGE (user)-[:SELECTED{slot: toInteger($slot)}]->(badge)
RETURN user {.*} RETURN user {.*}
`, `
{ userId, badgeId, slot }, const queryNull = `
) MATCH (user:User {id: $userId})
OPTIONAL MATCH (user)-[slotRelation:SELECTED {slot: $slot}]->(:Badge)
DELETE slotRelation
RETURN user {.*}
`
const result = await transaction.run(badgeId ? queryBadge : queryNull, {
userId,
badgeId,
slot,
})
return result.records.map((record) => record.get('user'))[0] return result.records.map((record) => record.get('user'))[0]
}) })
try { try {