Add original creator to custom content blocks
This commit is contained in:
parent
c8edbf9b13
commit
6646b328b7
|
|
@ -1,2 +1,2 @@
|
|||
nodejs 12.22.1
|
||||
python 3.8.5
|
||||
python 3.8.10
|
||||
|
|
|
|||
|
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 2.2.23 on 2021-06-03 13:05
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('books', '0029_auto_20210511_1301'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='contentblock',
|
||||
name='original_creator',
|
||||
field=models.ForeignKey(default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='snapshot',
|
||||
name='objective_groups',
|
||||
field=models.ManyToManyField(related_name='_snapshot_objective_groups_+', through='books.ObjectiveGroupSnapshot', to='objectives.ObjectiveGroup'),
|
||||
),
|
||||
]
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
# Generated by Django 2.2.23 on 2021-06-03 13:06
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('books', '0030_auto_20210603_1305'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='contentblock',
|
||||
name='original_creator',
|
||||
field=models.ForeignKey(blank=True, default=None, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL),
|
||||
),
|
||||
]
|
||||
|
|
@ -42,6 +42,7 @@ class ContentBlock(StrictHierarchyPage):
|
|||
# blocks with owner are hidden by default, need to be shown for each class
|
||||
visible_for = models.ManyToManyField(SchoolClass, related_name='visible_content_blocks')
|
||||
user_created = models.BooleanField(default=False)
|
||||
original_creator = models.ForeignKey(User, null=True, blank=True, default=None, on_delete=models.SET_NULL)
|
||||
|
||||
bookmarks = models.ManyToManyField(User, through=ContentBlockBookmark, related_name='bookmarked_content_blocks')
|
||||
|
||||
|
|
@ -133,7 +134,8 @@ class ContentBlockSnapshot(ContentBlock):
|
|||
contents=self.contents,
|
||||
type=self.type,
|
||||
title=self.title,
|
||||
owner=owner
|
||||
owner=owner,
|
||||
original_creator=self.original_creator
|
||||
)
|
||||
self.add_sibling(instance=cb, pos='right')
|
||||
# some wagtail magic
|
||||
|
|
|
|||
|
|
@ -59,7 +59,8 @@ class SnapshotManager(models.Manager):
|
|||
snapshot=snapshot,
|
||||
contents=content_block.contents,
|
||||
type=content_block.type,
|
||||
title=content_block.title
|
||||
title=content_block.title,
|
||||
original_creator=content_block.owner
|
||||
)
|
||||
content_block.add_sibling(instance=new_content_block, pos='right')
|
||||
revision = new_content_block.save_revision()
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ def is_solution_and_hidden_for_user(type, user, module):
|
|||
class ContentBlockNode(DjangoObjectType, HiddenAndVisibleForMixin):
|
||||
mine = graphene.Boolean()
|
||||
bookmarks = graphene.List(ContentBlockBookmarkNode)
|
||||
original_creator = graphene.Field('users.schema.PublicUserNode')
|
||||
|
||||
class Meta:
|
||||
model = ContentBlock
|
||||
|
|
|
|||
|
|
@ -20,6 +20,11 @@ query ModulesQuery($slug: String, $id: ID) {
|
|||
contentBlocks {
|
||||
id
|
||||
title
|
||||
originalCreator {
|
||||
id
|
||||
fullName
|
||||
avatarUrl
|
||||
}
|
||||
visibleFor {
|
||||
name
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,6 +121,8 @@ class CreateSnapshotTestCase(SkillboxTestCase):
|
|||
school_class_name in [school_class['name'] for school_class in
|
||||
custom_objective.get('visibleFor')])
|
||||
|
||||
return module
|
||||
|
||||
def _compare_content_blocks(self, content_blocks):
|
||||
self.assertEqual(len(content_blocks), 4)
|
||||
first, second, third, fourth = content_blocks
|
||||
|
|
@ -203,7 +205,10 @@ class CreateSnapshotTestCase(SkillboxTestCase):
|
|||
}
|
||||
})
|
||||
self.assertIsNone(result.get('errors'))
|
||||
self._test_module_visibility(client, school_class_name)
|
||||
module = self._test_module_visibility(client, school_class_name)
|
||||
original_creator = module['chapters'][0]['contentBlocks'][2].get('originalCreator')
|
||||
self.assertIsNotNone(original_creator)
|
||||
self.assertEqual(original_creator.get('id'), to_global_id('PublicUserNode', self.teacher.pk))
|
||||
|
||||
def test_display_snapshot_module(self):
|
||||
self.snapshot = Snapshot.objects.create_snapshot(module=self.module, school_class=self.skillbox_class,
|
||||
|
|
|
|||
|
|
@ -8,14 +8,13 @@ from graphene_django.filter import DjangoFilterConnectionField
|
|||
from api.utils import get_object, get_by_id_or_slug
|
||||
from rooms.models import Room, RoomEntry, ModuleRoomSlug
|
||||
from users.models import SchoolClass
|
||||
from users.schema import UserNode
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RoomEntryNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
author = UserNode()
|
||||
author = graphene.Field('users.schema.PublicUserNode')
|
||||
|
||||
class Meta:
|
||||
model = RoomEntry
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ class TeamNode(DjangoObjectType):
|
|||
interfaces = (relay.Node,)
|
||||
|
||||
pk = graphene.Int()
|
||||
members = graphene.List('users.schema.UserNode')
|
||||
members = graphene.List('users.schema.PublicUserNode')
|
||||
|
||||
def resolve_pk(self, *args, **kwargs):
|
||||
return self.id
|
||||
|
|
@ -68,7 +68,28 @@ class RecentModuleFilter(FilterSet):
|
|||
)
|
||||
|
||||
|
||||
class UserNode(DjangoObjectType):
|
||||
class PublicUserNode(DjangoObjectType):
|
||||
is_me = graphene.Boolean()
|
||||
full_name = graphene.String(required=True)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
only_fields = ['full_name', 'first_name', 'last_name', 'avatar_url']
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
@staticmethod
|
||||
def resolve_is_me(parent: User, info, **kwargs):
|
||||
return info.context.user.pk == parent.pk
|
||||
|
||||
class PrivateUserNode(DjangoObjectType):
|
||||
class Meta:
|
||||
model = User
|
||||
filter_fields = ['username', 'email']
|
||||
only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module',
|
||||
'last_topic', 'avatar_url',
|
||||
'selected_class', 'expiry_date', 'onboarding_visited', 'team']
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
pk = graphene.Int()
|
||||
permissions = graphene.List(graphene.String)
|
||||
selected_class = graphene.Field(SchoolClassNode)
|
||||
|
|
@ -77,15 +98,6 @@ class UserNode(DjangoObjectType):
|
|||
old_classes = DjangoFilterConnectionField(SchoolClassNode)
|
||||
recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter)
|
||||
team = graphene.Field(TeamNode)
|
||||
is_me = graphene.Boolean()
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
filter_fields = ['username', 'email']
|
||||
only_fields = ['username', 'email', 'first_name', 'last_name', 'school_classes', 'last_module',
|
||||
'last_topic', 'avatar_url',
|
||||
'selected_class', 'expiry_date', 'onboarding_visited', 'team']
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
def resolve_pk(self, info, **kwargs):
|
||||
return self.id
|
||||
|
|
@ -121,16 +133,13 @@ class UserNode(DjangoObjectType):
|
|||
def resolve_team(self, info, **kwargs):
|
||||
return self.team
|
||||
|
||||
def resolve_is_me(self, info, **kwargs):
|
||||
return info.context.user.pk == self.pk
|
||||
|
||||
|
||||
class ClassMemberNode(ObjectType):
|
||||
"""
|
||||
We need to build this ourselves, because we want the active property on the node, because providing it on the
|
||||
Connection or Edge for a UserNodeConnection is difficult.
|
||||
"""
|
||||
user = graphene.Field(UserNode)
|
||||
user = graphene.Field('users.schema.PublicUserNode')
|
||||
active = graphene.Boolean()
|
||||
first_name = graphene.String()
|
||||
last_name = graphene.String()
|
||||
|
|
@ -138,7 +147,7 @@ class ClassMemberNode(ObjectType):
|
|||
id = graphene.ID()
|
||||
|
||||
def resolve_id(self, *args):
|
||||
return to_global_id('UserNode', self.user.pk)
|
||||
return to_global_id('PublicUserNode', self.user.pk)
|
||||
|
||||
def resolve_active(self, *args):
|
||||
return self.active
|
||||
|
|
@ -157,8 +166,8 @@ class ClassMemberNode(ObjectType):
|
|||
|
||||
|
||||
class UsersQuery(object):
|
||||
me = graphene.Field(UserNode)
|
||||
all_users = DjangoFilterConnectionField(UserNode)
|
||||
me = graphene.Field(PrivateUserNode)
|
||||
all_users = DjangoFilterConnectionField(PrivateUserNode)
|
||||
my_activity = DjangoFilterConnectionField(ModuleNode)
|
||||
my_instrument_activity = DjangoFilterConnectionField(InstrumentNode)
|
||||
|
||||
|
|
@ -179,8 +188,8 @@ class UsersQuery(object):
|
|||
|
||||
|
||||
class AllUsersQuery(object):
|
||||
me = graphene.Field(UserNode)
|
||||
all_users = DjangoFilterConnectionField(UserNode)
|
||||
me = graphene.Field(PrivateUserNode)
|
||||
all_users = DjangoFilterConnectionField(PrivateUserNode)
|
||||
|
||||
def resolve_all_users(self, info, **kwargs):
|
||||
if not info.context.user.is_superuser:
|
||||
|
|
|
|||
|
|
@ -39,11 +39,11 @@ class JoinSchoolClassTest(TestCase):
|
|||
]
|
||||
create_users(user_data)
|
||||
teacher = User.objects.get(username='emily.sands')
|
||||
self.teacher_id = to_global_id('UserNode', teacher.pk)
|
||||
self.teacher_id = to_global_id('PublicUserNode', teacher.pk)
|
||||
student = User.objects.get(username='adam.groff')
|
||||
self.student_id = to_global_id('UserNode', student.pk)
|
||||
self.student_id = to_global_id('PublicUserNode', student.pk)
|
||||
other_student = User.objects.get(username='eric.effiong')
|
||||
self.other_student_id = to_global_id('UserNode', other_student.pk)
|
||||
self.other_student_id = to_global_id('PublicUserNode', other_student.pk)
|
||||
|
||||
school_class = SchoolClass.objects.get(name=self.school_class_name)
|
||||
self.school_class_id = to_global_id('SchoolClassNode', school_class.pk)
|
||||
|
|
@ -115,7 +115,7 @@ class JoinSchoolClassTest(TestCase):
|
|||
result = self.client.execute(self.mutation, variables={
|
||||
'input': {
|
||||
'schoolClass': to_global_id('SchoolClassNode', school_class.id),
|
||||
'member': to_global_id('UserNode', student.id),
|
||||
'member': to_global_id('PublicUserNode', student.id),
|
||||
'active': False
|
||||
}
|
||||
}, context=self.teacher_context)
|
||||
|
|
|
|||
Loading…
Reference in New Issue