Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/auth/permissions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const permissions = shield({
removeArea: isEditor,
addArea: isEditor,
updateArea: isEditor,
updateClimb: isEditor,
updateClimbs: isEditor,
deleteClimbs: isEditor,
bulkImportAreas: isEditor,
Expand Down
10 changes: 10 additions & 0 deletions src/graphql/climb/ClimbMutations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import muid, { MUUID } from 'uuid-mongodb'
import { ContextWithAuth } from '../../types.js'
import { ClimbType } from '../../db/ClimbTypes.js'

const ClimbMutations = {
updateClimbs: async (_, { input }, { dataSources, user }: ContextWithAuth): Promise<string[]> => {
Expand All @@ -11,6 +12,15 @@ const ClimbMutations = {
return await ds.addOrUpdateClimbs(user.uuid, muid.from(parentId), changes)
},

updateClimb: async (_, { input }, { dataSources, user }: ContextWithAuth): Promise<ClimbType | null> => {
const { climbs: ds } = dataSources
const { id, ...changes } = input

if (user?.uuid == null) throw new Error('Missing user uuid')

return await ds.updateClimbById(user.uuid, muid.from(id), changes)
},

deleteClimbs: async (_, { input }, { dataSources, user }: ContextWithAuth): Promise<number> => {
const { climbs: ds } = dataSources

Expand Down
29 changes: 29 additions & 0 deletions src/graphql/schema/ClimbEdit.gql
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ type Mutation {
"""
updateClimbs(input: UpdateClimbsInput): [ID]

"""
Update a single climb by its ID. Unlike updateClimbs, this doesn't require the parent area ID.
"""
updateClimb(input: SingleClimbInput!): Climb

"""
Delete one or more climbs
"""
Expand Down Expand Up @@ -49,6 +54,30 @@ input SingleClimbChangeInput {
experimentalAuthor: ExperimentalAuthorType
}

"""
Input for updating a single climb by its ID. The climb must already exist.
"""
input SingleClimbInput {
"Climb UUID (required)"
id: ID!
name: String
disciplines: DisciplineType
grade: String
leftRightIndex: Int
description: String
location: String
protection: String
"Legacy FA data"
fa: String
"Length in meters"
length: Int
"Number of fixed anchors"
boltsCount: Int
"List of Pitch objects representing individual pitches of a multi-pitch climb"
pitches: [PitchInput]
experimentalAuthor: ExperimentalAuthorType
}

input GradeTypeInput {
vscale: String
yds: String
Expand Down
33 changes: 33 additions & 0 deletions src/model/MutableClimbDataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,39 @@ export default class MutableClimbDataSource extends ClimbDataSource {
}
}

/**
* Update a single climb by its ID. Unlike addOrUpdateClimbs, this doesn't require the parent area ID.
* @param userId User performing the action
* @param climbId The climb's own ID
* @param changes The fields to update
* @returns The updated climb, or null if not found
*/
async updateClimbById (userId: MUUID, climbId: MUUID, changes: Omit<ClimbChangeInputType, 'id'>): Promise<ClimbType | null> {
// Look up the climb to get its parent area ID
const climb = await this.climbModel.findOne({ _id: climbId, _deleting: { $eq: null } }).lean()

if (climb == null) {
throw new GraphQLError(`Climb with id: ${climbId.toUUID().toString()} not found`, {
extensions: {
code: ApolloServerErrorCode.BAD_USER_INPUT
}
})
}

const parentId = climb.metadata.areaRef

// Use existing logic with the climb ID included
const changeWithId: ClimbChangeInputType = {
...changes,
id: climbId.toUUID().toString()
}

await this.addOrUpdateClimbs(userId, parentId, [changeWithId])

// Return the updated climb
return await this.climbModel.findOne({ _id: climbId }).lean()
}

/**
* Delete one or more climbs by climb ID.
* @param userId User performing the action
Expand Down
Loading