In my project I'm using Django
- graphene-django (graphQL)
- Apollo
- VueJS
- Vuetify
and for the drag and drop concerns I'm trying to use Vuedraggable
.
I'm actually trying to build a kanban board with columns and cards to move from column to column (Trello like).
The thing is it works well when I don't run any Apollo mutation.
So you can see my initial state :
If I don't do anything apart providing the :list
and group='...'
, it works :
But when I provide a @change="..."
method with an apollo mutation, it doesn't work anymore and it does this :
My Datas are structured like this :
There are multiple stages (New, In Progress, Done) and each of them can have multiple tickets (Stage 1-n Tickets)
stage {
id
name
ticketIds {
id
name
}
}
Here are my sources :
My template (I omitted pure visual things such as styling classes and column header to make it cleaner) :
<template>
<v-row>
<v-col
v-for="stage in helpdeskTicketStages"
:key="stage.id">
<draggable
:list="stage.ticketIds"
@change="changeTicketStage($event, stage)"
group="tickets">
<v-card
v-for="ticket in stage.ticketIds"
:key="ticket.id">
<v-card-title>{{ ticket.name }}</v-card-title>
</v-card>
</draggable>
</v-col>
</v-row>
</template>
My
change
method :
changeTicketStage (event, stage) {
if (event.added) {
this.$apollo.mutate({
mutation: CHANGE_HELPDESK_TICKET_STAGE_MUTATION,
variables: {
ticketId: event.added.element.id,
stageId: stage.id
},
update: (cache, { data: { changeHelpdeskTicketStage } }) => {
console.log('cache : ', cache)
}
})
}
}
The
CHANGE_HELPDESK_TICKET_STAGE_MUTATION
mutation :
const CHANGE_HELPDESK_TICKET_STAGE_MUTATION = gql`
mutation changeHelpdeskTicketStageMutation (
$ticketId: ID!,
$stageId: ID!
) {
changeHelpdeskTicketStage (
ticketId: $ticketId,
stageId: $stageId
) {
id,
isClosed,
stageId {
id
name
}
}
}
`
The graphene-django that is called :
class ChangeHelpdeskTicketStage(graphene.Mutation):
class Arguments:
ticket_id = graphene.ID()
stage_id = graphene.ID()
class Meta:
output = HelpdeskTicketType
def mutate(self, info, **kwargs):
ticket = get_object_or_404(HelpdeskTicket, id=kwargs['ticket_id'])
stage = get_object_or_404(HelpdeskTicketStage, id=kwargs['stage_id'])
ticket.change_stage(stage)
return ticket
The this that is weird is that without mutation, it moves correctly. And when I add the mutation to change it effectively in DB too (which is done correctly) it does this weird 'clone'.
I think the problem is from the apollo cache because, when I print things to console, in the change(...)
method everything is okay :
Indeed, at the end of the change(...)
method, I run :
for (const stage of this.helpdeskTicketStages) {
console.log('name:', stage.name, 'tickets:', stage.ticketIds)
}
which gives to console :
So we can see that it is correct, there is 1 ticket per stage. But it displays 2 tickets in the 'New' stage !
I have added a test button to run the exact same code :
test () {
console.log('----------------- TEST -----------------')
for (const stage of this.helpdeskTicketStages) {
console.log('name:', stage.name, 'tickets:', stage.ticketIds)
}
console.log('----------------- END -----------------')
}
And when we inspect the result in console, we can see :
That there are 2 tickets in 'New' stage and 1 ticket in 'In Progress' stage whereas it should be 1 in each... Of course if I press F5 it runs the query and retrieve the correct information in DB and it corrects the display.
Also in this part :
update: (cache, { data: { changeHelpdeskTicketStage } }) => {
console.log('cache : ', cache)
}
If I inspect the cache we can also see that there are 2 in 'New' and 1 in 'In Progress'.
Can someone tell me why it does this ? I mean when there is no mutation the lists are correctly changed. The mutation should be there just to change it effectively in DB.
Thanks in advance !
Well I finally changed my mind and decided to perform the mutation on the STAGE instead of doing this on the TICKET
so that I can send the source stage and the target stage with their updated list of tickets as result of the mutation. By writing all the question I realized it would be easier that way...
Indeed the result of the mutation is then : [source_stage, target_stage] so the output type is now graphene.List(my_type).
By doing this I don't have to change manually the stage ticketIds manually after the mutation in an update
statement since it updates by itself correctly.