Add original creator to custom content blocks

This commit is contained in:
Ramon Wenger 2021-06-03 17:52:29 +02:00
parent c8edbf9b13
commit 6646b328b7
11 changed files with 98 additions and 30 deletions

View File

@ -1,2 +1,2 @@
nodejs 12.22.1
python 3.8.5
python 3.8.10

View File

@ -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'),
),
]

View File

@ -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),
),
]

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -20,6 +20,11 @@ query ModulesQuery($slug: String, $id: ID) {
contentBlocks {
id
title
originalCreator {
id
fullName
avatarUrl
}
visibleFor {
name
}

View File

@ -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,

View File

@ -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

View File

@ -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:

View File

@ -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)