Add 'Leave Team' action
This commit is contained in:
parent
a43dffc7f7
commit
9582773378
|
|
@ -28,11 +28,16 @@
|
||||||
v-for="member in activeMembers">
|
v-for="member in activeMembers">
|
||||||
<span class="member-item__name">{{ fullName(member) }}</span>
|
<span class="member-item__name">{{ fullName(member) }}</span>
|
||||||
<span class="member-item__role">{{ role(member) }}</span>
|
<span class="member-item__role">{{ role(member) }}</span>
|
||||||
<!-- <a-->
|
<a
|
||||||
<!-- class="member-item__action simple-list__action"-->
|
class="member-item__action simple-list__action"
|
||||||
<!-- data-cy="remove-from-class"-->
|
data-cy="leave-group"
|
||||||
<!-- v-if="teacher"-->
|
v-if="member.isMe"
|
||||||
<!-- @click="$emit('remove', member)">Deaktivieren</a>-->
|
@click="$emit('leave')">Verlassen</a>
|
||||||
|
<!-- <a-->
|
||||||
|
<!-- class="member-item__action simple-list__action"-->
|
||||||
|
<!-- data-cy="remove-from-class"-->
|
||||||
|
<!-- v-if="teacher"-->
|
||||||
|
<!-- @click="$emit('remove', member)">Deaktivieren</a>-->
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<!-- <template v-if="inactiveMembers.length">-->
|
<!-- <template v-if="inactiveMembers.length">-->
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
fragment TeamParts on TeamNode {
|
||||||
|
name
|
||||||
|
code
|
||||||
|
id
|
||||||
|
members {
|
||||||
|
firstName
|
||||||
|
lastName
|
||||||
|
id
|
||||||
|
isMe
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
#import "gql/fragments/teamParts.gql"
|
||||||
mutation CreateTeamMutation($input: CreateTeamInput!) {
|
mutation CreateTeamMutation($input: CreateTeamInput!) {
|
||||||
createTeam(input: $input) {
|
createTeam(input: $input) {
|
||||||
success
|
success
|
||||||
team {
|
team {
|
||||||
name
|
...TeamParts
|
||||||
code
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
|
#import "gql/fragments/teamParts.gql"
|
||||||
mutation JoinTeamMutation($input: JoinTeamInput!) {
|
mutation JoinTeamMutation($input: JoinTeamInput!) {
|
||||||
joinTeam(input: $input) {
|
joinTeam(input: $input) {
|
||||||
success
|
success
|
||||||
team {
|
team {
|
||||||
name
|
...TeamParts
|
||||||
code
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
mutation LeaveTeam {
|
||||||
|
leaveTeam {
|
||||||
|
success
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,16 +1,10 @@
|
||||||
#import "../fragments/userParts.gql"
|
#import "../fragments/userParts.gql"
|
||||||
|
#import "../fragments/teamParts.gql"
|
||||||
query MeQuery {
|
query MeQuery {
|
||||||
me {
|
me {
|
||||||
...UserParts
|
...UserParts
|
||||||
team {
|
team {
|
||||||
name
|
...TeamParts
|
||||||
code
|
|
||||||
id
|
|
||||||
members {
|
|
||||||
firstName
|
|
||||||
lastName
|
|
||||||
id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
isTeacher
|
isTeacher
|
||||||
permissions
|
permissions
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
import ME_QUERY from 'gql/queries/meQuery';
|
||||||
|
|
||||||
|
const addTeam = (store, team) => {
|
||||||
|
const query = ME_QUERY;
|
||||||
|
const data = store.readQuery({query});
|
||||||
|
store.writeQuery({
|
||||||
|
query,
|
||||||
|
data: {
|
||||||
|
...data,
|
||||||
|
me: {
|
||||||
|
...data.me,
|
||||||
|
team: team,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export default addTeam;
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
export default {
|
|
||||||
methods: {
|
|
||||||
addTeam(store, team) {
|
|
||||||
// todo
|
|
||||||
throw new Error('NotImplemented');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
@ -13,18 +13,17 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import addTeamMixin from '@/mixins/add-team';
|
|
||||||
|
|
||||||
import JoinForm from '@/components/profile/JoinForm';
|
import JoinForm from '@/components/profile/JoinForm';
|
||||||
|
|
||||||
import CREATE_TEAM_MUTATION from '@/graphql/gql/mutations/createTeam.gql';
|
import CREATE_TEAM_MUTATION from '@/graphql/gql/mutations/createTeam.gql';
|
||||||
import {MY_TEAM} from '@/router/me.names';
|
import {MY_TEAM} from '@/router/me.names';
|
||||||
|
import ME_QUERY from 'gql/queries/meQuery';
|
||||||
|
import addTeam from '@/helpers/add-team';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [addTeamMixin],
|
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
JoinForm
|
JoinForm,
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
|
@ -37,7 +36,7 @@
|
||||||
this.name = event.target.value;
|
this.name = event.target.value;
|
||||||
this.error = '';
|
this.error = '';
|
||||||
// todo: pass error to component
|
// todo: pass error to component
|
||||||
throw new Error('NotImplemented');
|
// throw new Error('NotImplemented');
|
||||||
},
|
},
|
||||||
createTeam(name) {
|
createTeam(name) {
|
||||||
this.$apollo.mutate({
|
this.$apollo.mutate({
|
||||||
|
|
@ -48,7 +47,8 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: (store, {data: {createTeam: {team}}}) => {
|
update: (store, {data: {createTeam: {team}}}) => {
|
||||||
this.addTeam(store, team);
|
addTeam(store, team);
|
||||||
|
|
||||||
this.$router.push({
|
this.$router.push({
|
||||||
name: MY_TEAM,
|
name: MY_TEAM,
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -12,10 +12,10 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import JOIN_TEAM_MUTATION from '@/graphql/gql/mutations/joinTeam.gql';
|
import JOIN_TEAM_MUTATION from '@/graphql/gql/mutations/joinTeam.gql';
|
||||||
import ME_QUERY from '@/graphql/gql/queries/meQuery.gql';
|
|
||||||
|
|
||||||
import JoinForm from '@/components/profile/JoinForm';
|
import JoinForm from '@/components/profile/JoinForm';
|
||||||
import {MY_TEAM} from '@/router/me.names';
|
import {MY_TEAM} from '@/router/me.names';
|
||||||
|
import addTeam from '@/helpers/add-team';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
|
|
@ -49,18 +49,7 @@
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
update: (store, {data: {joinTeam: {team}}}) => {
|
update: (store, {data: {joinTeam: {team}}}) => {
|
||||||
const query = ME_QUERY;
|
addTeam(store, team);
|
||||||
const data = store.readQuery({query});
|
|
||||||
store.writeQuery({
|
|
||||||
query,
|
|
||||||
data: {
|
|
||||||
...data,
|
|
||||||
me: {
|
|
||||||
...data.me,
|
|
||||||
team: team,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
this.$router.push({name: MY_TEAM});
|
this.$router.push({name: MY_TEAM});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
:name="me.team.name"
|
:name="me.team.name"
|
||||||
title="Mein Team"
|
title="Mein Team"
|
||||||
@edit="editTeamName"
|
@edit="editTeamName"
|
||||||
|
@leave="leaveTeam"
|
||||||
/>
|
/>
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
|
|
@ -36,6 +37,8 @@
|
||||||
import {CREATE_TEAM, JOIN_TEAM, SHOW_TEAM_CODE} from '@/router/me.names';
|
import {CREATE_TEAM, JOIN_TEAM, SHOW_TEAM_CODE} from '@/router/me.names';
|
||||||
import me from '@/mixins/me';
|
import me from '@/mixins/me';
|
||||||
import GroupList from '@/components/profile/GroupList';
|
import GroupList from '@/components/profile/GroupList';
|
||||||
|
import LEAVE_TEAM_MUTATION from 'gql/mutations/me/leaveTeam.gql';
|
||||||
|
import addTeam from '@/helpers/add-team';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
mixins: [me],
|
mixins: [me],
|
||||||
|
|
@ -50,16 +53,24 @@
|
||||||
name: CREATE_TEAM,
|
name: CREATE_TEAM,
|
||||||
},
|
},
|
||||||
showCodeRoute: {
|
showCodeRoute: {
|
||||||
name: SHOW_TEAM_CODE
|
name: SHOW_TEAM_CODE,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
editTeamName() {
|
editTeamName() {
|
||||||
this.$store.dispatch('editTeamName');
|
this.$store.dispatch('editTeamName');
|
||||||
}
|
},
|
||||||
}
|
leaveTeam() {
|
||||||
|
this.$apollo.mutate({
|
||||||
|
mutation: LEAVE_TEAM_MUTATION,
|
||||||
|
update(store, {data: {leaveTeam: {success}}}) {
|
||||||
|
addTeam(store, null);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -388,6 +388,7 @@ type CustomMutation {
|
||||||
createTeam(input: CreateTeamInput!): CreateTeamPayload
|
createTeam(input: CreateTeamInput!): CreateTeamPayload
|
||||||
joinTeam(input: JoinTeamInput!): JoinTeamPayload
|
joinTeam(input: JoinTeamInput!): JoinTeamPayload
|
||||||
updateTeam(input: UpdateTeamInput!): UpdateTeamPayload
|
updateTeam(input: UpdateTeamInput!): UpdateTeamPayload
|
||||||
|
leaveTeam: LeaveTeam
|
||||||
addProject(input: AddProjectInput!): AddProjectPayload
|
addProject(input: AddProjectInput!): AddProjectPayload
|
||||||
updateProject(input: UpdateProjectInput!): UpdateProjectPayload
|
updateProject(input: UpdateProjectInput!): UpdateProjectPayload
|
||||||
deleteProject(input: DeleteProjectInput!): DeleteProjectPayload
|
deleteProject(input: DeleteProjectInput!): DeleteProjectPayload
|
||||||
|
|
@ -614,6 +615,10 @@ type JoinTeamPayload {
|
||||||
clientMutationId: String
|
clientMutationId: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type LeaveTeam {
|
||||||
|
success: Boolean
|
||||||
|
}
|
||||||
|
|
||||||
type Logout {
|
type Logout {
|
||||||
success: Boolean
|
success: Boolean
|
||||||
}
|
}
|
||||||
|
|
@ -1436,6 +1441,7 @@ type UserNode implements Node {
|
||||||
isTeacher: Boolean
|
isTeacher: Boolean
|
||||||
oldClasses(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection
|
oldClasses(offset: Int, before: String, after: String, first: Int, last: Int, name: String): SchoolClassNodeConnection
|
||||||
recentModules(offset: Int, before: String, after: String, first: Int, last: Int, recentModules: [ID], orderBy: String): ModuleNodeConnection
|
recentModules(offset: Int, before: String, after: String, first: Int, last: Int, recentModules: [ID], orderBy: String): ModuleNodeConnection
|
||||||
|
isMe: Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserNodeConnection {
|
type UserNodeConnection {
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ from users.serializers import PasswordSerialzer, AvatarUrlSerializer
|
||||||
|
|
||||||
logger = get_logger(__name__)
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class CodeNotFoundException(Exception):
|
class CodeNotFoundException(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
@ -281,6 +282,17 @@ class JoinTeam(TeacherOnlyMutation):
|
||||||
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CNV = Code Not Valid
|
raise CodeNotFoundException('[CNV] Code ist nicht gültig') # CNV = Code Not Valid
|
||||||
|
|
||||||
|
|
||||||
|
class LeaveTeam(graphene.Mutation):
|
||||||
|
success = graphene.Boolean()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def mutate(cls, root, info, **kwargs):
|
||||||
|
user = info.context.user
|
||||||
|
user.team = None
|
||||||
|
user.save()
|
||||||
|
return cls(success=True)
|
||||||
|
|
||||||
|
|
||||||
class UpdateOnboardingProgress(graphene.Mutation):
|
class UpdateOnboardingProgress(graphene.Mutation):
|
||||||
success = graphene.Boolean()
|
success = graphene.Boolean()
|
||||||
|
|
||||||
|
|
@ -306,3 +318,4 @@ class ProfileMutations:
|
||||||
create_team = CreateTeam.Field()
|
create_team = CreateTeam.Field()
|
||||||
join_team = JoinTeam.Field()
|
join_team = JoinTeam.Field()
|
||||||
update_team = UpdateTeam.Field()
|
update_team = UpdateTeam.Field()
|
||||||
|
leave_team = LeaveTeam.Field()
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,7 @@ class UserNode(DjangoObjectType):
|
||||||
old_classes = DjangoFilterConnectionField(SchoolClassNode)
|
old_classes = DjangoFilterConnectionField(SchoolClassNode)
|
||||||
recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter)
|
recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter)
|
||||||
team = graphene.Field(TeamNode)
|
team = graphene.Field(TeamNode)
|
||||||
|
is_me = graphene.Boolean()
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = User
|
model = User
|
||||||
|
|
@ -120,6 +121,9 @@ class UserNode(DjangoObjectType):
|
||||||
def resolve_team(self, info, **kwargs):
|
def resolve_team(self, info, **kwargs):
|
||||||
return self.team
|
return self.team
|
||||||
|
|
||||||
|
def resolve_is_me(self, info, **kwargs):
|
||||||
|
return info.context.user.pk == self.pk
|
||||||
|
|
||||||
|
|
||||||
class ClassMemberNode(ObjectType):
|
class ClassMemberNode(ObjectType):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ from api.schema import schema
|
||||||
from api.utils import get_graphql_mutation
|
from api.utils import get_graphql_mutation
|
||||||
from core.factories import TeacherFactory, UserFactory
|
from core.factories import TeacherFactory, UserFactory
|
||||||
from users.factories import TeamFactory
|
from users.factories import TeamFactory
|
||||||
from users.models import Team
|
from users.models import Team, User
|
||||||
|
|
||||||
ME_QUERY = """
|
ME_QUERY = """
|
||||||
query MeQuery {
|
query MeQuery {
|
||||||
|
|
@ -23,6 +23,7 @@ ME_QUERY = """
|
||||||
CREATE_TEAM_MUTATION = get_graphql_mutation('createTeam.gql')
|
CREATE_TEAM_MUTATION = get_graphql_mutation('createTeam.gql')
|
||||||
JOIN_TEAM_MUTATION = get_graphql_mutation('joinTeam.gql')
|
JOIN_TEAM_MUTATION = get_graphql_mutation('joinTeam.gql')
|
||||||
UPDATE_TEAM_MUTATION = get_graphql_mutation('updateTeam.gql')
|
UPDATE_TEAM_MUTATION = get_graphql_mutation('updateTeam.gql')
|
||||||
|
LEAVE_TEAM_MUTATION = get_graphql_mutation('me/leaveTeam.gql')
|
||||||
|
|
||||||
|
|
||||||
class TeamTest(TestCase):
|
class TeamTest(TestCase):
|
||||||
|
|
@ -169,3 +170,19 @@ class TeamTest(TestCase):
|
||||||
result = self.client.execute(JOIN_TEAM_MUTATION, context=context, variables=variables)
|
result = self.client.execute(JOIN_TEAM_MUTATION, context=context, variables=variables)
|
||||||
self.permission_error(result)
|
self.permission_error(result)
|
||||||
self.assertIsNone(self.student.team)
|
self.assertIsNone(self.student.team)
|
||||||
|
|
||||||
|
def test_leave_team(self):
|
||||||
|
self.student.team = self.team
|
||||||
|
self.student.save()
|
||||||
|
student_before = User.objects.get(pk=self.student.pk)
|
||||||
|
self.assertIsNotNone(student_before.team)
|
||||||
|
context = Context(user=student_before)
|
||||||
|
result = self.client.execute(LEAVE_TEAM_MUTATION, context=context)
|
||||||
|
self.no_error(result)
|
||||||
|
leave_team = result.get('data').get('leaveTeam')
|
||||||
|
success = leave_team.get('success')
|
||||||
|
self.assertTrue(success)
|
||||||
|
|
||||||
|
student_after = User.objects.get(pk=self.student.pk)
|
||||||
|
self.assertIsNone(student_after.team)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue