Add parts for room entry deletion

This commit is contained in:
Ramon Wenger 2018-10-29 18:54:34 +01:00
parent acf59b218b
commit c536a04122
7 changed files with 160 additions and 10 deletions

View File

@ -1,6 +1,6 @@
<template>
<div class="room-entry">
<div class="room-entry__more">
<div class="room-entry__more" v-if="myEntry">
<a @click="showMenu = !showMenu" class="room-entry__more-link">
<ellipses class="room-entry__ellipses"></ellipses>
</a>
@ -28,6 +28,10 @@
</template>
<script>
import DELETE_ROOM_ENTRY_MUTATION from '@/graphql/gql/mutations/deleteRoomEntry.gql';
import ROOM_ENTRIES_QUERY from '@/graphql/gql/roomEntriesQuery.gql';
import ME_QUERY from '@/graphql/gql/meQuery.gql';
import UserWidget from '@/components/UserWidget.vue';
import Ellipses from '@/components/icons/Ellipses.vue';
import WidgetPopover from '@/components/rooms/WidgetPopover';
@ -42,7 +46,29 @@
},
methods: {
deleteRoomEntry() {
deleteRoomEntry(id) {
this.$apollo.mutate({
mutation: DELETE_ROOM_ENTRY_MUTATION,
variables: {
input: {
id
}
},
update(store, {data: {deleteRoomEntry: {success, roomSlug}}}) {
if (success) {
const query = ROOM_ENTRIES_QUERY;
const variables = {slug: roomSlug};
const data = store.readQuery({query, variables});
if (data) {
data.room.roomEntries.edges.splice(data.room.roomEntries.edges.findIndex(edge => edge.node.id === id), 1);
store.writeQuery({query, data, variables});
}
}
}
})
},
editRoomEntry(id){
this.$store.dispatch('editRoomEntry', id);
}
},
@ -70,6 +96,17 @@
}
}
return '';
},
myEntry() {
return this.author.id === this.me.id;
}
},
apollo: {
me() {
return {
query: ME_QUERY
}
}
},
@ -114,20 +151,28 @@
margin-bottom: 10px;
}
&__ellipses {
width: 30px;
fill: $color-darkgrey-1;
}
&__more {
position: absolute;
top: 5px;
top: 10px;
right: 10px;
display: flex;
justify-content: flex-end;
}
&__more-link {
background-color: rgba($color-white, 0.9);
width: 35px;
height: 15px;
border-radius: 15px;
display: flex;
justify-content: center;
}
&__ellipses {
width: 30px;
height: 30px;
fill: $color-darkgrey-1;
margin-top: -7px;
}
&__popover {

View File

@ -0,0 +1,13 @@
mutation DeleteRoomEntry($input: DeleteRoomEntryInput!) {
deleteRoomEntry(input: $input) {
success
errors
roomSlug
}
}
#{
# "input": {
# "id": "Um9vbU5vZGU6MjY="
# }
#}

View File

@ -51,7 +51,9 @@
data() {
return {
rooms: [],
me: {}
me: {
permissions: []
}
}
}
}

View File

@ -32,6 +32,7 @@ class RoomEntryFactory(factory.django.DjangoModelFactory):
subtitle = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(8, 12)))
description = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(20, 30)))
author = factory.Iterator(get_user_model().objects.all())
room = factory.SubFactory(RoomFactory)
contents = wagtail_factories.StreamFieldFactory({
'text_block': TextBlockFactory,

View File

@ -1,9 +1,10 @@
import graphene
from graphene import relay
from graphql_relay import to_global_id
from api.utils import get_object
from rooms.inputs import UpdateRoomArgument, AddRoomArgument, AddRoomEntryArgument
from rooms.models import Room
from rooms.models import Room, RoomEntry
from rooms.schema import RoomNode, RoomEntryNode
from rooms.serializers import RoomSerializer, RoomEntrySerializer
from users.models import SchoolClass
@ -93,8 +94,30 @@ class AddRoomEntry(relay.ClientIDMutation):
return cls(room_entry=None, errors=['{}: {}'.format(key, value) for key, value in serializer.errors.items()])
class DeleteRoomEntry(relay.ClientIDMutation):
class Input:
id = graphene.ID(required=True)
success = graphene.Boolean()
room_slug = graphene.String()
room_id = graphene.ID()
errors = graphene.List(graphene.String)
@classmethod
def mutate_and_get_payload(cls, root, info, **kwargs):
id = kwargs.get('id')
room_entry = get_object(RoomEntry, id)
if room_entry.author.pk != info.context.user.pk:
raise Exception('You are not the owner of this room entry')
room_id = to_global_id('RoomNode', room_entry.room.pk)
room_slug = room_entry.room.slug
room_entry.delete()
return cls(success=True, room_id=room_id, room_slug=room_slug)
class RoomMutations:
update_room = UpdateRoom.Field()
add_room = AddRoom.Field()
delete_room = DeleteRoom.Field()
add_room_entry = AddRoomEntry.Field()
delete_room_entry = DeleteRoomEntry.Field()

View File

View File

@ -0,0 +1,66 @@
from django.test import TestCase, RequestFactory
from graphene.test import Client
from graphql_relay import to_global_id
from api.schema import schema
from core.factories import UserFactory
from rooms.factories import RoomEntryFactory, RoomFactory
from rooms.models import RoomEntry
from users.factories import SchoolClassFactory
from users.services import create_users
class RoomEntryMutationsTestCase(TestCase):
def setUp(self):
self.user = UserFactory(username='aschi')
self.another_user = UserFactory(username='pesche')
s = SchoolClassFactory(users=[self.user, self.another_user])
self.room_entry = RoomEntryFactory(author=self.user, room=RoomFactory(school_class=s))
request = RequestFactory().get('/')
request.user = self.user
self.client = Client(schema=schema, context_value=request)
def test_delete_room_entry(self):
self.assertEqual(RoomEntry.objects.count(), 1)
mutation = '''
mutation DeleteRoomEntry($input: DeleteRoomEntryInput!) {
deleteRoomEntry(input: $input) {
success
errors
}
}
'''
result = self.client.execute(mutation, variables={
'input': {
'id': to_global_id('RoomEntryNode', self.room_entry.pk)
}
})
self.assertIsNone(result.get('errors'))
self.assertEqual(RoomEntry.objects.count(), 0)
def test_delete_room_not_owner(self):
self.assertEqual(RoomEntry.objects.count(), 1)
mutation = '''
mutation DeleteRoomEntry($input: DeleteRoomEntryInput!) {
deleteRoomEntry(input: $input) {
success
errors
}
}
'''
request = RequestFactory().get('/')
request.user = self.another_user
client = Client(schema=schema, context_value=request)
result = client.execute(mutation, variables={
'input': {
'id': to_global_id('RoomEntryNode', self.room_entry.pk)
}
})
self.assertIsNotNone(result.get('errors'))
self.assertEqual(RoomEntry.objects.count(), 1)