Add recently visited modules to user
This commit is contained in:
parent
991efbe613
commit
e899bbe21b
File diff suppressed because one or more lines are too long
|
|
@ -0,0 +1,26 @@
|
|||
# Generated by Django 2.2.12 on 2020-06-23 09:52
|
||||
|
||||
import datetime
|
||||
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', '0021_auto_20200520_0954'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='RecentModule',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('visited', models.DateTimeField(default=datetime.datetime.now)),
|
||||
('module', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='books.Module')),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
import logging
|
||||
from datetime import datetime
|
||||
|
||||
from django.db import models
|
||||
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList
|
||||
|
|
@ -58,3 +59,12 @@ class Module(StrictHierarchyPage):
|
|||
|
||||
def get_child_ids(self):
|
||||
return self.get_children().values_list('id', flat=True)
|
||||
|
||||
|
||||
class RecentModule(models.Model):
|
||||
module = models.ForeignKey(Module, on_delete=models.CASCADE, related_name='recent_modules')
|
||||
user = models.ForeignKey('users.User', on_delete=models.CASCADE)
|
||||
visited = models.DateTimeField(default=datetime.now)
|
||||
|
||||
class Meta:
|
||||
get_latest_by = 'visited'
|
||||
|
|
|
|||
|
|
@ -1,8 +1,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
|
||||
from books.models import Module, Topic, RecentModule
|
||||
from books.schema.queries import ModuleNode, TopicNode
|
||||
|
||||
|
||||
|
|
@ -47,30 +49,30 @@ class UpdateLastModule(relay.ClientIDMutation):
|
|||
# todo: use slug here too
|
||||
id = graphene.ID()
|
||||
|
||||
module = graphene.Field(ModuleNode)
|
||||
errors = graphene.List(graphene.String)
|
||||
last_module = graphene.Field(ModuleNode)
|
||||
|
||||
@classmethod
|
||||
def mutate_and_get_payload(cls, root, info, **args):
|
||||
user = info.context.user
|
||||
id = args.get('id')
|
||||
|
||||
module = get_object(Module, id)
|
||||
if not module:
|
||||
raise Module.DoesNotExist
|
||||
|
||||
try:
|
||||
user = info.context.user
|
||||
id = args.get('id')
|
||||
same_module = RecentModule.objects.get(user=user, module=module)
|
||||
same_module.visited = datetime.now()
|
||||
same_module.save()
|
||||
return cls(last_module=same_module.module)
|
||||
except RecentModule.DoesNotExist:
|
||||
recent_modules = RecentModule.objects.filter(user=user)
|
||||
while recent_modules.all().count() >= 3:
|
||||
recent_modules.earliest().delete()
|
||||
|
||||
module = get_object(Module, id)
|
||||
if not module:
|
||||
raise Module.DoesNotExist
|
||||
last_module = RecentModule.objects.create(user=user, module=module)
|
||||
|
||||
user.last_module = module
|
||||
user.save()
|
||||
|
||||
return cls(module=module)
|
||||
|
||||
except Module.DoesNotExist:
|
||||
return cls(errors=['Module not found'])
|
||||
|
||||
except Exception as e:
|
||||
errors = ['Error: {}'.format(e)]
|
||||
return cls(errors=errors)
|
||||
return cls(last_module=last_module.module)
|
||||
|
||||
|
||||
class UpdateLastTopic(relay.ClientIDMutation):
|
||||
|
|
@ -93,4 +95,3 @@ class UpdateLastTopic(relay.ClientIDMutation):
|
|||
user.save()
|
||||
|
||||
return cls(topic=topic)
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ from notes.schema import ContentBlockBookmarkNode, ChapterBookmarkNode, ModuleBo
|
|||
from rooms.models import ModuleRoomSlug
|
||||
from surveys.models import Answer
|
||||
from surveys.schema import AnswerNode
|
||||
from ..models import Book, Topic, Module, Chapter, ContentBlock
|
||||
from ..models import Book, Topic, Module, Chapter, ContentBlock, RecentModule
|
||||
|
||||
|
||||
def process_module_room_slug_block(content):
|
||||
|
|
@ -187,6 +187,12 @@ class ModuleNode(DjangoObjectType):
|
|||
.prefetch_related('objectives__objective_progress')
|
||||
|
||||
|
||||
class RecentModuleNode(DjangoObjectType):
|
||||
class Meta:
|
||||
model = RecentModule
|
||||
interfaces = (relay.Node,)
|
||||
|
||||
|
||||
class TopicNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
modules = DjangoFilterConnectionField(ModuleNode)
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ DEFAULT_SCHOOL_ID = 1
|
|||
|
||||
class User(AbstractUser):
|
||||
last_module = models.ForeignKey('books.Module', related_name='+', on_delete=models.SET_NULL, null=True)
|
||||
# recent_modules = models.ManyToManyField('books.Module', related_name='+', through='books.RecentModule')
|
||||
last_topic = models.ForeignKey('books.Topic', related_name='+', on_delete=models.SET_NULL, null=True)
|
||||
avatar_url = models.CharField(max_length=254, blank=True, default='')
|
||||
email = models.EmailField(_('email address'), unique=True)
|
||||
|
|
@ -97,7 +98,6 @@ class User(AbstractUser):
|
|||
user_settings.selected_class = school_class
|
||||
user_settings.save()
|
||||
|
||||
|
||||
@property
|
||||
def full_name(self):
|
||||
return self.get_full_name()
|
||||
|
|
@ -245,7 +245,7 @@ class UserData(models.Model):
|
|||
class License(models.Model):
|
||||
for_role = models.ForeignKey(Role, blank=False, null=True, on_delete=models.CASCADE)
|
||||
licensee = models.ForeignKey(User, blank=False, null=True, on_delete=models.CASCADE)
|
||||
expire_date = models.DateField(blank=False, null=True,)
|
||||
expire_date = models.DateField(blank=False, null=True, )
|
||||
order_id = models.IntegerField(blank=False, null=False, default=-1)
|
||||
raw = models.TextField(default='')
|
||||
|
||||
|
|
@ -255,8 +255,9 @@ class License(models.Model):
|
|||
return self.for_role.key == RoleManager.TEACHER_KEY
|
||||
|
||||
def is_valid(self):
|
||||
return HepClient.is_product_active(datetime(self.expire_date.year, self.expire_date.month, self.expire_date.day),
|
||||
self.for_role.key)
|
||||
return HepClient.is_product_active(
|
||||
datetime(self.expire_date.year, self.expire_date.month, self.expire_date.day),
|
||||
self.for_role.key)
|
||||
|
||||
def __str__(self):
|
||||
return f'License for role: {self.for_role}'
|
||||
|
|
@ -266,4 +267,3 @@ class SchoolClassMember(models.Model):
|
|||
user = models.ForeignKey(User, on_delete=models.CASCADE)
|
||||
school_class = models.ForeignKey(SchoolClass, on_delete=models.CASCADE)
|
||||
active = models.BooleanField(default=True)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ from datetime import datetime
|
|||
|
||||
import graphene
|
||||
from django.db.models import Q
|
||||
from django_filters import FilterSet, OrderingFilter
|
||||
from graphene import relay, ObjectType
|
||||
from graphene_django import DjangoObjectType
|
||||
from graphene_django.filter import DjangoFilterConnectionField
|
||||
|
|
@ -10,7 +11,7 @@ from graphql_relay import to_global_id
|
|||
|
||||
from basicknowledge.models import BasicKnowledge
|
||||
from basicknowledge.queries import InstrumentNode
|
||||
from books.models import Module
|
||||
from books.models import Module, RecentModule
|
||||
from books.schema.queries import ModuleNode
|
||||
from users.models import User, SchoolClass, SchoolClassMember
|
||||
|
||||
|
|
@ -39,6 +40,18 @@ class SchoolClassNode(DjangoObjectType):
|
|||
return self.code
|
||||
|
||||
|
||||
class RecentModuleFilter(FilterSet):
|
||||
class Meta:
|
||||
model = Module
|
||||
fields = ('recent_modules',)
|
||||
|
||||
order_by = OrderingFilter(
|
||||
fields=(
|
||||
('recent_modules__visited', 'visited'),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class UserNode(DjangoObjectType):
|
||||
pk = graphene.Int()
|
||||
permissions = graphene.List(graphene.String)
|
||||
|
|
@ -46,6 +59,7 @@ class UserNode(DjangoObjectType):
|
|||
expiry_date = graphene.String()
|
||||
is_teacher = graphene.Boolean()
|
||||
old_classes = DjangoFilterConnectionField(SchoolClassNode)
|
||||
recent_modules = DjangoFilterConnectionField(ModuleNode, filterset_class=RecentModuleFilter)
|
||||
|
||||
class Meta:
|
||||
model = User
|
||||
|
|
@ -82,6 +96,10 @@ class UserNode(DjangoObjectType):
|
|||
def resolve_old_classes(self, info):
|
||||
return SchoolClass.objects.filter(schoolclassmember__active=False, schoolclassmember__user=self)
|
||||
|
||||
def resolve_recent_modules(self, info, **kwargs):
|
||||
# see https://docs.graphene-python.org/projects/django/en/latest/filtering/
|
||||
return RecentModuleFilter(kwargs).qs.filter(recent_modules__user=self)
|
||||
|
||||
|
||||
class ClassMemberNode(ObjectType):
|
||||
"""
|
||||
|
|
|
|||
Loading…
Reference in New Issue