Add module visibility sync mutation
This commit is contained in:
parent
209838dadb
commit
9490ffd443
|
|
@ -0,0 +1,5 @@
|
|||
describe('Survey', () => {
|
||||
it('needs to be implemented', () => {
|
||||
expect(true).to.equal(false);
|
||||
});
|
||||
});
|
||||
|
|
@ -9,15 +9,6 @@
|
|||
|
||||
export default {
|
||||
mixins: [me],
|
||||
|
||||
computed: {
|
||||
currentClassName() {
|
||||
let currentClass = this.me.schoolClasses.find(schoolClass => {
|
||||
return schoolClass.id === this.me.selectedClass.id;
|
||||
});
|
||||
return currentClass ? currentClass.name : this.me.schoolClasses.length ? this.me.schoolClasses[0].name : '';
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
mutation SyncModuleVisibility($input: SyncModuleVisibilityInput!) {
|
||||
syncModuleVisibility(input: $input) {
|
||||
success
|
||||
}
|
||||
}
|
||||
|
|
@ -5,13 +5,13 @@ export default {
|
|||
return {
|
||||
me: {
|
||||
selectedClass: {
|
||||
id: ''
|
||||
id: '',
|
||||
},
|
||||
permissions: [],
|
||||
schoolClasses: [],
|
||||
isTeacher: false
|
||||
isTeacher: false,
|
||||
},
|
||||
showPopover: false
|
||||
showPopover: false,
|
||||
};
|
||||
},
|
||||
|
||||
|
|
@ -21,8 +21,8 @@ export default {
|
|||
return {
|
||||
name: 'topic',
|
||||
params: {
|
||||
topicSlug: this.me.lastTopic.slug
|
||||
}
|
||||
topicSlug: this.me.lastTopic.slug,
|
||||
},
|
||||
};
|
||||
}
|
||||
return '/book/topic/berufliche-grundbildung';
|
||||
|
|
@ -33,15 +33,21 @@ export default {
|
|||
canManageContent() {
|
||||
return this.me.permissions.includes('users.can_manage_school_class_content');
|
||||
},
|
||||
currentClassName() {
|
||||
let currentClass = this.me.schoolClasses.find(schoolClass => {
|
||||
return schoolClass.id === this.me.selectedClass.id;
|
||||
});
|
||||
return currentClass ? currentClass.name : this.me.schoolClasses.length ? this.me.schoolClasses[0].name : '';
|
||||
},
|
||||
},
|
||||
|
||||
apollo: {
|
||||
me: {
|
||||
query: ME_QUERY,
|
||||
update(data) {
|
||||
return this.$getRidOfEdges(data).me;
|
||||
update({me}) {
|
||||
return this.$getRidOfEdges(me);
|
||||
},
|
||||
fetchPolicy: 'cache-first'
|
||||
fetchPolicy: 'cache-first',
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="module-page">
|
||||
<module-navigation/>
|
||||
<module-navigation v-if="showNavigation" />
|
||||
<router-view/>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -11,6 +11,12 @@
|
|||
export default {
|
||||
components: {
|
||||
ModuleNavigation
|
||||
},
|
||||
|
||||
computed: {
|
||||
showNavigation() {
|
||||
return !this.$route.meta.hideNavigation;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -12,16 +12,25 @@
|
|||
<div class="module-visibility__form module-visibility__section">
|
||||
Von
|
||||
<select
|
||||
:value="selectedClassId"
|
||||
class="skillbox-input skillbox-dropdown module-visibility__dropdown"
|
||||
placeholder="Hallo">
|
||||
@change="select($event.target.value)">
|
||||
<option
|
||||
value
|
||||
selected>-</option>
|
||||
value=""
|
||||
selected>-
|
||||
</option>
|
||||
<option
|
||||
:key="schoolClass.id"
|
||||
:value="schoolClass.id"
|
||||
v-for="schoolClass in schoolClasses">{{ schoolClass.name }}
|
||||
</option>
|
||||
</select>
|
||||
für INF2019i übernehmen.
|
||||
für {{ currentClassName }} übernehmen.
|
||||
</div>
|
||||
<div class="module-visibility__section">
|
||||
<a class="button button--primary">Anpassungen übernehmen</a>
|
||||
<a
|
||||
class="button button--primary"
|
||||
@click="sync">Anpassungen übernehmen</a>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -29,11 +38,48 @@
|
|||
<script>
|
||||
import EyeIcon from '@/components/icons/EyeIcon';
|
||||
|
||||
import me from '@/mixins/me';
|
||||
|
||||
import SYNC_VISIBILITY_MUTATION from '@/graphql/gql/mutations/syncModuleVisibility.gql';
|
||||
|
||||
export default {
|
||||
|
||||
mixins: [me],
|
||||
components: {
|
||||
EyeIcon
|
||||
EyeIcon,
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
selectedClassId: '',
|
||||
};
|
||||
},
|
||||
|
||||
computed: {
|
||||
schoolClasses() {
|
||||
return this.me.schoolClasses.filter(schoolClass => schoolClass.id !== this.me.selectedClass.id);
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
select(selectedClassId) {
|
||||
this.selectedClassId = selectedClassId;
|
||||
},
|
||||
sync() {
|
||||
if (this.selectedClassId) {
|
||||
this.$apollo.mutate({
|
||||
mutation: SYNC_VISIBILITY_MUTATION,
|
||||
variables: {
|
||||
input: {
|
||||
module: this.$route.params.slug,
|
||||
templateSchoolClass: this.selectedClassId,
|
||||
schoolClass: this.me.selectedClass.id,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
import Vue from 'vue';
|
||||
// import index from '@/pages/index'
|
||||
import topic from '@/pages/topic';
|
||||
import moduleBase from '@/pages/module-base';
|
||||
import module from '@/pages/module';
|
||||
import rooms from '@/pages/rooms';
|
||||
import room from '@/pages/room';
|
||||
import newRoom from '@/pages/newRoom';
|
||||
|
|
@ -10,7 +7,6 @@ import editRoom from '@/pages/editRoom';
|
|||
import article from '@/pages/article';
|
||||
import instrument from '@/pages/instrument';
|
||||
import instrumentOverview from '@/pages/instrumentOverview';
|
||||
import submissions from '@/pages/submissions';
|
||||
import p404 from '@/pages/p404';
|
||||
import start from '@/pages/start';
|
||||
import submission from '@/pages/studentSubmission';
|
||||
|
|
@ -41,10 +37,11 @@ import onboardingStep1 from '@/pages/onboarding/step1';
|
|||
import onboardingStep2 from '@/pages/onboarding/step2';
|
||||
import onboardingStep3 from '@/pages/onboarding/step3';
|
||||
import settingsPage from '@/pages/moduleSettings';
|
||||
|
||||
import moduleRoutes from './module.routes';
|
||||
import portfolioRoutes from './portfolio.routes';
|
||||
|
||||
import store from '@/store/index';
|
||||
import moduleVisibility from '@/pages/moduleVisibility';
|
||||
|
||||
const ONBOARDING_STEP_1 = 'onboarding-step-1';
|
||||
const ONBOARDING_STEP_2 = 'onboarding-step-2';
|
||||
|
|
@ -54,7 +51,7 @@ const routes = [
|
|||
{
|
||||
path: '/',
|
||||
name: 'home',
|
||||
component: start
|
||||
component: start,
|
||||
},
|
||||
{
|
||||
path: '/login',
|
||||
|
|
@ -62,8 +59,8 @@ const routes = [
|
|||
component: login,
|
||||
meta: {
|
||||
layout: 'public',
|
||||
public: true
|
||||
}
|
||||
public: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/hello',
|
||||
|
|
@ -71,8 +68,8 @@ const routes = [
|
|||
component: hello,
|
||||
meta: {
|
||||
layout: 'public',
|
||||
public: true
|
||||
}
|
||||
public: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/beta-login',
|
||||
|
|
@ -80,27 +77,10 @@ const routes = [
|
|||
component: betaLogin,
|
||||
meta: {
|
||||
layout: 'public',
|
||||
public: true
|
||||
}
|
||||
public: true,
|
||||
},
|
||||
{
|
||||
path: '/module/:slug',
|
||||
component: moduleBase,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: 'module',
|
||||
component: module,
|
||||
meta: {filter: true}
|
||||
},
|
||||
{
|
||||
path: 'submissions/:id',
|
||||
name: 'submissions',
|
||||
component: submissions,
|
||||
meta: {filter: true}
|
||||
}
|
||||
]
|
||||
},
|
||||
...moduleRoutes,
|
||||
{path: '/rooms', name: 'rooms', component: rooms, meta: {filter: true}},
|
||||
{path: '/new-room/', name: 'new-room', component: newRoom},
|
||||
{path: '/edit-room/:id', name: 'edit-room', component: editRoom, props: true},
|
||||
|
|
@ -110,13 +90,13 @@ const routes = [
|
|||
name: 'moduleRoom',
|
||||
component: moduleRoom,
|
||||
props: true,
|
||||
meta: {layout: 'fullScreen'}
|
||||
meta: {layout: 'fullScreen'},
|
||||
},
|
||||
{path: '/article/:slug', name: 'article', component: article, meta: {layout: 'simple'}},
|
||||
{
|
||||
path: '/instruments/',
|
||||
name: 'instrument-overview',
|
||||
component: instrumentOverview
|
||||
component: instrumentOverview,
|
||||
},
|
||||
{path: '/instrument/:slug', name: 'instrument', component: instrument, meta: {layout: 'simple'}},
|
||||
{path: '/submission/:id', name: 'submission', component: submission, meta: {layout: 'simple'}},
|
||||
|
|
@ -134,11 +114,11 @@ const routes = [
|
|||
path: 'old-classes',
|
||||
name: 'old-classes',
|
||||
component: oldClasses,
|
||||
meta: {isProfile: true}
|
||||
meta: {isProfile: true},
|
||||
},
|
||||
{path: 'create-class', name: 'create-class', component: createClass, meta: {layout: 'simple'}},
|
||||
{path: 'show-code', name: 'show-code', component: showCode, meta: {layout: 'simple'}},
|
||||
]
|
||||
],
|
||||
},
|
||||
{path: 'join-class', name: 'join-class', component: joinClass, meta: {layout: 'public'}},
|
||||
{
|
||||
|
|
@ -146,7 +126,7 @@ const routes = [
|
|||
component: surveyPage,
|
||||
name: 'survey',
|
||||
props: true,
|
||||
meta: {layout: 'simple'}
|
||||
meta: {layout: 'simple'},
|
||||
},
|
||||
{
|
||||
path: '/register',
|
||||
|
|
@ -155,7 +135,7 @@ const routes = [
|
|||
meta: {
|
||||
public: true,
|
||||
layout: 'public',
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/check-email',
|
||||
|
|
@ -163,8 +143,8 @@ const routes = [
|
|||
name: 'checkEmail',
|
||||
meta: {
|
||||
public: true,
|
||||
layout: 'public'
|
||||
}
|
||||
layout: 'public',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/verify-email',
|
||||
|
|
@ -172,16 +152,16 @@ const routes = [
|
|||
name: 'emailVerification',
|
||||
meta: {
|
||||
public: true,
|
||||
layout: 'public'
|
||||
}
|
||||
layout: 'public',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/license-activation',
|
||||
component: licenseActivation,
|
||||
name: 'licenseActivation',
|
||||
meta: {
|
||||
layout: 'public'
|
||||
}
|
||||
layout: 'public',
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/forgot-password',
|
||||
|
|
@ -189,13 +169,13 @@ const routes = [
|
|||
name: 'forgotPassword',
|
||||
meta: {
|
||||
layout: 'public',
|
||||
public: true
|
||||
}
|
||||
public: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
path: '/news',
|
||||
component: news,
|
||||
name: 'news'
|
||||
name: 'news',
|
||||
},
|
||||
{
|
||||
path: '/onboarding',
|
||||
|
|
@ -207,7 +187,7 @@ const routes = [
|
|||
name: 'onboarding-start',
|
||||
meta: {
|
||||
layout: 'blank',
|
||||
next: ONBOARDING_STEP_1
|
||||
next: ONBOARDING_STEP_1,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -217,7 +197,7 @@ const routes = [
|
|||
meta: {
|
||||
layout: 'blank',
|
||||
next: ONBOARDING_STEP_2,
|
||||
illustration: 'contents'
|
||||
illustration: 'contents',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -227,7 +207,7 @@ const routes = [
|
|||
meta: {
|
||||
layout: 'blank',
|
||||
next: ONBOARDING_STEP_3,
|
||||
illustration: 'rooms'
|
||||
illustration: 'rooms',
|
||||
},
|
||||
},
|
||||
{
|
||||
|
|
@ -237,30 +217,23 @@ const routes = [
|
|||
meta: {
|
||||
layout: 'blank',
|
||||
next: 'home',
|
||||
illustration: 'portfolio'
|
||||
illustration: 'portfolio',
|
||||
},
|
||||
},
|
||||
]
|
||||
],
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
component: settingsPage
|
||||
},
|
||||
{
|
||||
path: '/visibility',
|
||||
component: moduleVisibility,
|
||||
meta: {
|
||||
layout: 'simple'
|
||||
}
|
||||
component: settingsPage,
|
||||
},
|
||||
{path: '/styleguide', component: styleGuidePage},
|
||||
{
|
||||
path: '*',
|
||||
component: p404,
|
||||
meta: {
|
||||
layout: 'blank'
|
||||
}
|
||||
}
|
||||
layout: 'blank',
|
||||
},
|
||||
},
|
||||
];
|
||||
|
||||
Vue.use(Router);
|
||||
|
|
@ -273,7 +246,7 @@ const router = new Router({
|
|||
return savedPosition;
|
||||
}
|
||||
return {x: 0, y: 0};
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
router.afterEach((to, from) => {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
export const SUBMISSIONS_PAGE = 'submissions';
|
||||
export const MODULE_PAGE = 'module';
|
||||
export const VISIBILITY_PAGE = 'visibility';
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import moduleBase from '@/pages/module-base';
|
||||
import module from '@/pages/module';
|
||||
import submissions from '@/pages/submissions';
|
||||
import moduleVisibility from '@/pages/moduleVisibility';
|
||||
import {MODULE_PAGE, SUBMISSIONS_PAGE, VISIBILITY_PAGE} from '@/router/module.names';
|
||||
|
||||
export default [
|
||||
{
|
||||
path: '/module/:slug',
|
||||
component: moduleBase,
|
||||
children: [
|
||||
{
|
||||
path: '',
|
||||
name: MODULE_PAGE,
|
||||
component: module,
|
||||
meta: {filter: true},
|
||||
},
|
||||
{
|
||||
path: 'submissions/:id',
|
||||
name: SUBMISSIONS_PAGE,
|
||||
component: submissions,
|
||||
meta: {filter: true},
|
||||
},
|
||||
{
|
||||
path: 'visibility',
|
||||
name: VISIBILITY_PAGE,
|
||||
component: moduleVisibility,
|
||||
meta: {
|
||||
layout: 'simple',
|
||||
hideNavigation: true
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
];
|
||||
|
|
@ -24,7 +24,6 @@ from rooms.mutations import RoomMutations
|
|||
from rooms.schema import RoomsQuery, ModuleRoomsQuery
|
||||
from users.schema import AllUsersQuery, UsersQuery
|
||||
from users.mutations import ProfileMutations
|
||||
from registration.mutations_public import RegistrationMutations
|
||||
|
||||
|
||||
class CustomQuery(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, ObjectivesQuery, BookQuery, AssignmentsQuery,
|
||||
|
|
@ -36,7 +35,7 @@ class CustomQuery(UsersQuery, AllUsersQuery, ModuleRoomsQuery, RoomsQuery, Objec
|
|||
|
||||
|
||||
class CustomMutation(BookMutations, RoomMutations, AssignmentMutations, ObjectiveMutations, CoreMutations, PortfolioMutations,
|
||||
ProfileMutations, SurveyMutations, NoteMutations, RegistrationMutations, SpellCheckMutations,
|
||||
ProfileMutations, SurveyMutations, NoteMutations, SpellCheckMutations,
|
||||
CouponMutations, graphene.ObjectType):
|
||||
if settings.DEBUG:
|
||||
debug = graphene.Field(DjangoDebug, name='_debug')
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ class Module(StrictHierarchyPage):
|
|||
def get_child_ids(self):
|
||||
return self.get_children().values_list('id', flat=True)
|
||||
|
||||
def sync_from_school_class(self, school_class_pattern, school_class_to_sync):
|
||||
def sync_from_school_class(self, school_class_template, school_class_to_sync):
|
||||
# import here so we don't get a circular import error
|
||||
from books.models import Chapter, ContentBlock
|
||||
|
||||
|
|
@ -77,12 +77,12 @@ class Module(StrictHierarchyPage):
|
|||
content_block.visible_for.remove(school_class_to_sync)
|
||||
|
||||
# get all content blocks with `hidden for` for class `school_class_pattern`
|
||||
for content_block in school_class_pattern.hidden_content_blocks.intersection(content_block_query):
|
||||
for content_block in school_class_template.hidden_content_blocks.intersection(content_block_query):
|
||||
# add `school_class_to_sync` to these blocks' `hidden for`
|
||||
content_block.hidden_for.add(school_class_to_sync)
|
||||
|
||||
# get all content blocks with `visible for` for class `school_class_pattern`
|
||||
for content_block in school_class_pattern.visible_content_blocks.intersection(content_block_query):
|
||||
for content_block in school_class_template.visible_content_blocks.intersection(content_block_query):
|
||||
# add `school_class_to_sync` to these blocks' `visible for`
|
||||
content_block.visible_for.add(school_class_to_sync)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
from books.schema.mutations.chapter import UpdateChapterVisibility
|
||||
from books.schema.mutations.contentblock import MutateContentBlock, AddContentBlock, DeleteContentBlock
|
||||
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule, UpdateLastTopic
|
||||
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule, SyncModuleVisibility
|
||||
from books.schema.mutations.topic import UpdateLastTopic
|
||||
|
||||
|
||||
class BookMutations(object):
|
||||
|
|
@ -11,3 +12,4 @@ class BookMutations(object):
|
|||
update_last_module = UpdateLastModule.Field()
|
||||
update_last_topic = UpdateLastTopic.Field()
|
||||
update_chapter_visibility = UpdateChapterVisibility.Field()
|
||||
sync_module_visibility = SyncModuleVisibility.Field()
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ from datetime import datetime
|
|||
import graphene
|
||||
from graphene import relay
|
||||
|
||||
from api.utils import get_errors, get_object
|
||||
from books.models import Module, Topic, RecentModule
|
||||
from books.schema.queries import ModuleNode, TopicNode
|
||||
from api.utils import get_object
|
||||
from books.models import Module, RecentModule
|
||||
from books.schema.queries import ModuleNode
|
||||
from users.models import SchoolClass
|
||||
|
||||
|
||||
class UpdateSolutionVisibility(relay.ClientIDMutation):
|
||||
|
|
@ -75,23 +76,30 @@ class UpdateLastModule(relay.ClientIDMutation):
|
|||
return cls(last_module=last_module.module)
|
||||
|
||||
|
||||
class UpdateLastTopic(relay.ClientIDMutation):
|
||||
class SyncModuleVisibility(relay.ClientIDMutation):
|
||||
class Input:
|
||||
# todo: use slug here too
|
||||
id = graphene.ID()
|
||||
module = graphene.String(required=True)
|
||||
template_school_class = graphene.ID(required=True)
|
||||
school_class = graphene.ID(required=True)
|
||||
|
||||
topic = graphene.Field(TopicNode)
|
||||
success = graphene.Boolean()
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
user = info.context.user
|
||||
id = args.get('id')
|
||||
if not user.is_teacher():
|
||||
raise Exception('Permission denied')
|
||||
|
||||
topic = get_object(Topic, id)
|
||||
if not topic:
|
||||
raise Topic.DoesNotExist
|
||||
module_slug = args.get('module')
|
||||
template_id = args.get('template_school_class')
|
||||
school_class_id = args.get('school_class')
|
||||
|
||||
user.last_topic = topic
|
||||
user.save()
|
||||
module = Module.objects.get(slug=module_slug)
|
||||
template = get_object(SchoolClass, template_id)
|
||||
school_class = get_object(SchoolClass, school_class_id)
|
||||
if not template.is_user_in_schoolclass(user) or not school_class.is_user_in_schoolclass(user):
|
||||
raise Exception('Permission denied')
|
||||
|
||||
return cls(topic=topic)
|
||||
module.sync_from_school_class(template, school_class)
|
||||
|
||||
return cls(success=True)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
import graphene
|
||||
from graphene import relay
|
||||
|
||||
from api.utils import get_object
|
||||
from books.models import Topic
|
||||
from books.schema.queries import TopicNode
|
||||
|
||||
|
||||
class UpdateLastTopic(relay.ClientIDMutation):
|
||||
class Input:
|
||||
# todo: use slug here too
|
||||
id = graphene.ID()
|
||||
|
||||
topic = graphene.Field(TopicNode)
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
user = info.context.user
|
||||
id = args.get('id')
|
||||
|
||||
topic = get_object(Topic, id)
|
||||
if not topic:
|
||||
raise Topic.DoesNotExist
|
||||
|
||||
user.last_topic = topic
|
||||
user.save()
|
||||
|
||||
return cls(topic=topic)
|
||||
|
|
@ -34,6 +34,14 @@ CONTENT_BLOCK_QUERY = """
|
|||
}
|
||||
"""
|
||||
|
||||
SYNC_MUTATION = """
|
||||
mutation SyncMutationVisibility($input: SyncModuleVisibilityInput!) {
|
||||
syncModuleVisibility(input: $input) {
|
||||
success
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class CopyVisibilityForClassesTestCase(TestCase):
|
||||
"""
|
||||
|
|
@ -52,7 +60,7 @@ class CopyVisibilityForClassesTestCase(TestCase):
|
|||
"""
|
||||
|
||||
def setUp(self):
|
||||
module = ModuleFactory()
|
||||
module = ModuleFactory(slug='some-module')
|
||||
chapter = Chapter(title='Some Chapter')
|
||||
module.add_child(instance=chapter)
|
||||
create_users()
|
||||
|
|
@ -110,6 +118,36 @@ class CopyVisibilityForClassesTestCase(TestCase):
|
|||
})
|
||||
return result
|
||||
|
||||
def _test_in_sync(self):
|
||||
# the hidden block is hidden for both now
|
||||
hidden_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client, self.hidden_content_block)
|
||||
hidden_for = hidden_result.get('data').get('contentBlock').get('hiddenFor').get('edges')
|
||||
self.assertTrue('template-class' in map(lambda x: x['node']['name'], hidden_for))
|
||||
self.assertTrue('class-to-be-synced' in map(lambda x: x['node']['name'], hidden_for))
|
||||
|
||||
# the other hidden block is hidden for no one now
|
||||
other_hidden_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client,
|
||||
self.other_hidden_content_block)
|
||||
hidden_for = other_hidden_result.get('data').get('contentBlock').get('hiddenFor').get('edges')
|
||||
self.assertEqual(len(hidden_for), 0)
|
||||
|
||||
# the default block is still hidden for no one
|
||||
default_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client, self.default_content_block)
|
||||
hidden_for = default_result.get('data').get('contentBlock').get('hiddenFor').get('edges')
|
||||
self.assertEqual(len(hidden_for), 0)
|
||||
|
||||
# the custom block is visible for both
|
||||
custom_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client, self.custom_content_block)
|
||||
visible_for = custom_result.get('data').get('contentBlock').get('visibleFor').get('edges')
|
||||
self.assertTrue('template-class' in map(lambda x: x['node']['name'], visible_for))
|
||||
self.assertTrue('class-to-be-synced' in map(lambda x: x['node']['name'], visible_for))
|
||||
|
||||
# the other custom block is visible for no one
|
||||
other_custom_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client,
|
||||
self.other_custom_content_block)
|
||||
visible_for = other_custom_result.get('data').get('contentBlock').get('visibleFor').get('edges')
|
||||
self.assertEqual(len(visible_for), 0)
|
||||
|
||||
def test_hidden_for_and_visible_for_set_correctly(self):
|
||||
self.assertEqual(ContentBlock.objects.count(), 5)
|
||||
|
||||
|
|
@ -142,31 +180,14 @@ class CopyVisibilityForClassesTestCase(TestCase):
|
|||
def test_syncs_correctly(self):
|
||||
self.module.sync_from_school_class(self.template_school_class, self.school_class_to_be_synced)
|
||||
|
||||
# the hidden block is hidden for both now
|
||||
hidden_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client, self.hidden_content_block)
|
||||
hidden_for = hidden_result.get('data').get('contentBlock').get('hiddenFor').get('edges')
|
||||
self.assertTrue('template-class' in map(lambda x: x['node']['name'], hidden_for))
|
||||
self.assertTrue('class-to-be-synced' in map(lambda x: x['node']['name'], hidden_for))
|
||||
self._test_in_sync()
|
||||
|
||||
# the other hidden block is hidden for no one now
|
||||
other_hidden_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client,
|
||||
self.other_hidden_content_block)
|
||||
hidden_for = other_hidden_result.get('data').get('contentBlock').get('hiddenFor').get('edges')
|
||||
self.assertEqual(len(hidden_for), 0)
|
||||
|
||||
# the default block is still hidden for no one
|
||||
default_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client, self.default_content_block)
|
||||
hidden_for = default_result.get('data').get('contentBlock').get('hiddenFor').get('edges')
|
||||
self.assertEqual(len(hidden_for), 0)
|
||||
|
||||
# the custom block is visible for both
|
||||
custom_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client, self.custom_content_block)
|
||||
visible_for = custom_result.get('data').get('contentBlock').get('visibleFor').get('edges')
|
||||
self.assertTrue('template-class' in map(lambda x: x['node']['name'], visible_for))
|
||||
self.assertTrue('class-to-be-synced' in map(lambda x: x['node']['name'], visible_for))
|
||||
|
||||
# the other custom block is visible for no one
|
||||
other_custom_result = self._get_result(CONTENT_BLOCK_QUERY, self.teacher_client,
|
||||
self.other_custom_content_block)
|
||||
visible_for = other_custom_result.get('data').get('contentBlock').get('visibleFor').get('edges')
|
||||
self.assertEqual(len(visible_for), 0)
|
||||
def test_mutation(self):
|
||||
self.teacher_client.execute(SYNC_MUTATION, variables={
|
||||
'input': {
|
||||
'module': self.module.slug,
|
||||
'templateSchoolClass': to_global_id('SchoolClassNode', self.template_school_class.pk),
|
||||
'schoolClass': to_global_id('SchoolClassNode', self.school_class_to_be_synced.pk)
|
||||
}
|
||||
})
|
||||
self._test_in_sync()
|
||||
|
|
|
|||
|
|
@ -1,25 +0,0 @@
|
|||
{
|
||||
"schema": {
|
||||
"request": {
|
||||
"url": "http://localhost:8000/graphql",
|
||||
"method": "POST",
|
||||
"postIntrospectionQuery": true,
|
||||
"options": {
|
||||
"headers": {
|
||||
"user-agent": "JS GraphQL"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"endpoints": [
|
||||
{
|
||||
"name": "Default (http://localhost:8000/graphql",
|
||||
"url": "http://localhost:8000/graphql",
|
||||
"options": {
|
||||
"headers": {
|
||||
"user-agent": "JS GraphQL"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
Loading…
Reference in New Issue