Add highlight model to server
This commit is contained in:
parent
4584cb860e
commit
f3dc0e9b09
|
|
@ -10,7 +10,7 @@ from books.utils import are_solutions_enabled_for
|
|||
from core.logger import get_logger
|
||||
from core.mixins import HiddenAndVisibleForMixin
|
||||
from notes.models import ContentBlockBookmark
|
||||
from notes.schema import ContentBlockBookmarkNode
|
||||
from notes.schema import ContentBlockBookmarkNode, HighlightNode
|
||||
from rooms.models import ModuleRoomSlug
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
|
@ -20,7 +20,7 @@ class TextBlockNode(graphene.ObjectType):
|
|||
text = graphene.String()
|
||||
|
||||
def resolve_text(root, info, **kwargs):
|
||||
return root['value']['text']
|
||||
return root["value"]["text"]
|
||||
|
||||
|
||||
class ContentNode(graphene.Union):
|
||||
|
|
@ -30,30 +30,43 @@ class ContentNode(graphene.Union):
|
|||
@classmethod
|
||||
def resolve_type(cls, instance, info):
|
||||
logger.info(instance)
|
||||
if instance['type'] == 'text_block':
|
||||
if instance["type"] == "text_block":
|
||||
return TextBlockNode
|
||||
|
||||
|
||||
def is_solution_and_hidden_for_user(type, user, module):
|
||||
return type == 'solution' and not (are_solutions_enabled_for(user, module) or user.is_teacher())
|
||||
return type == "solution" and not (
|
||||
are_solutions_enabled_for(user, module) or user.is_teacher()
|
||||
)
|
||||
|
||||
|
||||
class ContentBlockNode(DjangoObjectType, HiddenAndVisibleForMixin):
|
||||
mine = graphene.Boolean()
|
||||
bookmarks = graphene.List(ContentBlockBookmarkNode)
|
||||
original_creator = graphene.Field('users.schema.PublicUserNode')
|
||||
original_creator = graphene.Field("users.schema.PublicUserNode")
|
||||
instrument_category = graphene.Field(InstrumentCategoryNode)
|
||||
path = graphene.String()
|
||||
highlights = graphene.List(HighlightNode)
|
||||
|
||||
class Meta:
|
||||
model = ContentBlock
|
||||
only_fields = [
|
||||
'slug', 'title', 'type', 'contents', 'hidden_for', 'visible_for', 'user_created'
|
||||
"slug",
|
||||
"title",
|
||||
"type",
|
||||
"contents",
|
||||
"hidden_for",
|
||||
"visible_for",
|
||||
"user_created",
|
||||
]
|
||||
filter_fields = [
|
||||
'slug', 'title',
|
||||
"slug",
|
||||
"title",
|
||||
]
|
||||
interfaces = (relay.Node, ContentBlockInterface,)
|
||||
interfaces = (
|
||||
relay.Node,
|
||||
ContentBlockInterface,
|
||||
)
|
||||
convert_choices_to_enum = False
|
||||
|
||||
def resolve_mine(parent, info, **kwargs):
|
||||
|
|
@ -64,18 +77,22 @@ class ContentBlockNode(DjangoObjectType, HiddenAndVisibleForMixin):
|
|||
updated_raw_data = []
|
||||
for content in self.contents.raw_data:
|
||||
# only show solutions to teachers and students for whom their teachers have them enabled
|
||||
if is_solution_and_hidden_for_user(content['type'], info.context.user, self.module):
|
||||
logger.debug('Solution is hidden for this user')
|
||||
if is_solution_and_hidden_for_user(
|
||||
content["type"], info.context.user, self.module
|
||||
):
|
||||
logger.debug("Solution is hidden for this user")
|
||||
continue
|
||||
|
||||
if content['type'] == 'content_list_item':
|
||||
if content["type"] == "content_list_item":
|
||||
_values = []
|
||||
for index, list_block in enumerate(content['value']):
|
||||
if is_solution_and_hidden_for_user(list_block['type'], info.context.user, self.module):
|
||||
logger.debug('Solution is hidden for this user')
|
||||
for index, list_block in enumerate(content["value"]):
|
||||
if is_solution_and_hidden_for_user(
|
||||
list_block["type"], info.context.user, self.module
|
||||
):
|
||||
logger.debug("Solution is hidden for this user")
|
||||
continue
|
||||
_values.append(process_module_room_slug_block(list_block))
|
||||
content['value'] = _values
|
||||
content["value"] = _values
|
||||
|
||||
content = process_module_room_slug_block(content)
|
||||
updated_raw_data.append(content)
|
||||
|
|
@ -85,16 +102,18 @@ class ContentBlockNode(DjangoObjectType, HiddenAndVisibleForMixin):
|
|||
|
||||
def resolve_bookmarks(self, info, **kwargs):
|
||||
return ContentBlockBookmark.objects.filter(
|
||||
user=info.context.user,
|
||||
content_block=self
|
||||
user=info.context.user, content_block=self
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def resolve_instrument_category(root: ContentBlock, info, **kwargs):
|
||||
if root.type == ContentBlock.INSTRUMENT:
|
||||
for content in root.contents.raw_data:
|
||||
if content['type'] == 'instrument' or content['type'] == 'basic_knowledge':
|
||||
_id = content['value']['basic_knowledge']
|
||||
if (
|
||||
content["type"] == "instrument"
|
||||
or content["type"] == "basic_knowledge"
|
||||
):
|
||||
_id = content["value"]["basic_knowledge"]
|
||||
instrument = BasicKnowledge.objects.get(id=_id)
|
||||
category = instrument.new_type.category
|
||||
return category
|
||||
|
|
@ -103,17 +122,22 @@ class ContentBlockNode(DjangoObjectType, HiddenAndVisibleForMixin):
|
|||
@staticmethod
|
||||
def resolve_path(root: ContentBlock, info, **kwargs):
|
||||
module = root.get_parent().get_parent()
|
||||
return f'module/{module.slug}#{root.graphql_id}'
|
||||
return f"module/{module.slug}#{root.graphql_id}"
|
||||
|
||||
@staticmethod
|
||||
def resolve_highlights(root: ContentBlock, info, **kwargs):
|
||||
return root.highlights.filter(user=info.context.user)
|
||||
|
||||
|
||||
def process_module_room_slug_block(content):
|
||||
if content['type'] == 'module_room_slug':
|
||||
if content["type"] == "module_room_slug":
|
||||
try:
|
||||
module_room_slug = ModuleRoomSlug.objects.get(
|
||||
title=content['value']['title'])
|
||||
content['value'] = {
|
||||
'title': content['value']['title'],
|
||||
'slug': module_room_slug.slug
|
||||
title=content["value"]["title"]
|
||||
)
|
||||
content["value"] = {
|
||||
"title": content["value"]["title"],
|
||||
"slug": module_room_slug.slug,
|
||||
}
|
||||
except ModuleRoomSlug.DoesNotExist:
|
||||
pass
|
||||
|
|
|
|||
|
|
@ -0,0 +1,52 @@
|
|||
# Generated by Django 4.2.8 on 2024-01-09 15:07
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
dependencies = [
|
||||
("books", "0045_alter_snapshot_objective_groups"),
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
("notes", "0004_auto_20210322_1514"),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name="Highlight",
|
||||
fields=[
|
||||
(
|
||||
"id",
|
||||
models.AutoField(
|
||||
auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name="ID",
|
||||
),
|
||||
),
|
||||
("content_index", models.IntegerField()),
|
||||
("content_uuid", models.UUIDField()),
|
||||
("paragraph_index", models.IntegerField()),
|
||||
("start_position", models.IntegerField()),
|
||||
("selection_length", models.IntegerField()),
|
||||
("text", models.TextField()),
|
||||
("color", models.CharField(max_length=50)),
|
||||
(
|
||||
"content_block",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name="highlights",
|
||||
to="books.contentblock",
|
||||
),
|
||||
),
|
||||
(
|
||||
"user",
|
||||
models.ForeignKey(
|
||||
on_delete=django.db.models.deletion.CASCADE,
|
||||
to=settings.AUTH_USER_MODEL,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
@ -19,26 +19,50 @@ class Bookmark(models.Model):
|
|||
|
||||
class ContentBlockBookmark(Bookmark):
|
||||
uuid = models.UUIDField(unique=False)
|
||||
content_block = models.ForeignKey('books.ContentBlock', on_delete=models.CASCADE)
|
||||
content_block = models.ForeignKey("books.ContentBlock", on_delete=models.CASCADE)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['uuid', 'content_block', 'user'], name='unique_content_bookmark_per_user')
|
||||
models.UniqueConstraint(
|
||||
fields=["uuid", "content_block", "user"],
|
||||
name="unique_content_bookmark_per_user",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class ModuleBookmark(Bookmark):
|
||||
module = models.ForeignKey('books.Module', on_delete=models.CASCADE)
|
||||
module = models.ForeignKey("books.Module", on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class ChapterBookmark(Bookmark):
|
||||
chapter = models.ForeignKey('books.Chapter', on_delete=models.CASCADE)
|
||||
chapter = models.ForeignKey("books.Chapter", on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class InstrumentBookmark(Bookmark):
|
||||
uuid = models.UUIDField(unique=False)
|
||||
instrument = models.ForeignKey('basicknowledge.BasicKnowledge', on_delete=models.CASCADE)
|
||||
instrument = models.ForeignKey(
|
||||
"basicknowledge.BasicKnowledge", on_delete=models.CASCADE
|
||||
)
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['uuid', 'instrument', 'user'], name='unique_instrument_bookmark_per_user')
|
||||
models.UniqueConstraint(
|
||||
fields=["uuid", "instrument", "user"],
|
||||
name="unique_instrument_bookmark_per_user",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
class Highlight(models.Model):
|
||||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
content_block = models.ForeignKey(
|
||||
"books.ContentBlock", on_delete=models.CASCADE, related_name="highlights"
|
||||
)
|
||||
# see highlight.ts for comments
|
||||
content_index = models.IntegerField()
|
||||
content_uuid = models.UUIDField()
|
||||
paragraph_index = models.IntegerField()
|
||||
start_position = models.IntegerField()
|
||||
selection_length = models.IntegerField()
|
||||
text = models.TextField()
|
||||
color = models.CharField(max_length=50)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,14 @@ import graphene
|
|||
from graphene import relay
|
||||
from graphene_django import DjangoObjectType
|
||||
|
||||
from notes.models import Note, ContentBlockBookmark, ModuleBookmark, ChapterBookmark, InstrumentBookmark
|
||||
from notes.models import (
|
||||
Highlight,
|
||||
Note,
|
||||
ContentBlockBookmark,
|
||||
ModuleBookmark,
|
||||
ChapterBookmark,
|
||||
InstrumentBookmark,
|
||||
)
|
||||
|
||||
|
||||
class NoteNode(DjangoObjectType):
|
||||
|
|
@ -36,7 +43,6 @@ class ModuleBookmarkNode(DjangoObjectType):
|
|||
fields = "__all__"
|
||||
|
||||
|
||||
|
||||
class ChapterBookmarkNode(DjangoObjectType):
|
||||
note = graphene.Field(NoteNode)
|
||||
|
||||
|
|
@ -56,3 +62,11 @@ class InstrumentBookmarkNode(DjangoObjectType):
|
|||
fields = "__all__"
|
||||
filter_fields = []
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
|
||||
class HighlightNode(DjangoObjectType):
|
||||
class Meta:
|
||||
model = Highlight
|
||||
fields = "__all__"
|
||||
filter_fields = []
|
||||
interfaces = (relay.Node,)
|
||||
|
|
|
|||
|
|
@ -511,6 +511,7 @@ type ContentBlockNode implements Node & ContentBlockInterface {
|
|||
originalCreator: PublicUserNode
|
||||
instrumentCategory: InstrumentCategoryNode
|
||||
path: String
|
||||
highlights: [HighlightNode]
|
||||
}
|
||||
|
||||
type ContentBlockBookmarkNode implements Node {
|
||||
|
|
@ -616,6 +617,20 @@ type InstrumentCategoryNode implements Node {
|
|||
types: [InstrumentTypeNode]
|
||||
}
|
||||
|
||||
type HighlightNode implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
user: PrivateUserNode!
|
||||
contentBlock: ContentBlockNode!
|
||||
contentIndex: Int!
|
||||
contentUuid: UUID!
|
||||
paragraphIndex: Int!
|
||||
startPosition: Int!
|
||||
selectionLength: Int!
|
||||
text: String!
|
||||
color: String!
|
||||
}
|
||||
|
||||
type SnapshotObjectiveGroupNode implements Node {
|
||||
"""The ID of the object"""
|
||||
id: ID!
|
||||
|
|
|
|||
Loading…
Reference in New Issue