Rename ModuleCategory -> ModuleLevel

This commit is contained in:
Lorenz Padberg 2023-08-21 14:22:28 +02:00
parent 0648497d50
commit 0b1954c570
18 changed files with 111 additions and 101 deletions

View File

@ -2,9 +2,9 @@
<div class="module-filter">
<div class="module-filter__filterselection">
<Dropdown class="module-filter__dropdown"
:selected-item="selectedCategory"
:items="firstLevelCategories"
@update:selectedItem="newItem => selectedCategory = newItem"
:selected-item="selectedLevel"
:items="levelOptions"
@update:selectedItem="newItem => selectedLevel = newItem"
></Dropdown>
<Dropdown
@ -14,9 +14,9 @@
@update:selectedItem="newItem => selectedLernfeld = newItem"
></Dropdown>
<pill-radio-buttons :selectableItems="languageOptions"
:defaultSelectedItem="initialLanguage"
class="module-filter__language-selection"
@update:selectedItem="item => selectedLanguage = item"/>
:defaultSelectedItem="initialLanguage"
class="module-filter__language-selection"
@update:selectedItem="item => selectedLanguage = item"/>
</div>
<div class="topic__modules">
@ -58,9 +58,9 @@
const selectedLanguage = ref(initialLanguage)
const {result: moduleCategoriesResult} = useQuery(gql`
query ModuleCategoriesQuery {
moduleCategories {
const {result: moduleLevelsResult} = useQuery(gql`
query ModuleLevelsQuery {
moduleLevels {
name
id
}
@ -71,12 +71,12 @@
name: '---',
id: null,
};
let defaultCategory = loadDefaultCategory(props.me);
let defaultLevel = loadDefaultLevel(props.me);
let selectedCategory = ref(defaultCategory);
let selectedLevel = ref(defaultLevel);
const firstLevelCategories = computed(() => {
return [nullCategory, ...moduleCategoriesResult.value?.moduleCategories || []];
const levelOptions = computed(() => {
return [nullCategory, ...moduleLevelsResult.value?.moduleLevels || []];
});
const nullLernfeld = {
@ -104,8 +104,8 @@
return filterModules();
});
function loadDefaultCategory(me) {
return me?.lastModuleCategory || nullCategory;
function loadDefaultLevel(me) {
return me?.lastModuleLevel || nullCategory;
}
@ -113,14 +113,14 @@
let filteredModules = props.modules;
if (selectedCategory.value === null) {
if (selectedLevel.value === null) {
return props.modules;
}
// filter by Lehrjahr
if (selectedCategory.value.name !== '---') {
if (selectedLevel.value.name !== '---') {
filteredModules = filteredModules.filter((module) => {
return module.category?.id == selectedCategory.value.id;
return module.level?.id == selectedLevel.value.id;
});
}
@ -130,8 +130,8 @@
return module.categoryType?.id == selectedLernfeld.value.id;
});
}
updateLastModuleCategory(selectedCategory.value);
filteredModules = filterByLanguage(selectedLanguage.value, filteredModules);
updateLastModuleLevel(selectedLevel.value);
filteredModules = filterByLanguage(selectedLanguage.value, filteredModules);
return filteredModules;
}
@ -142,24 +142,23 @@
}
function updateLastModuleCategory(moduleCategory: Object) {
console.log(moduleCategory);
function updateLastModuleLevel(moduleLevel: Object) {
const {mutate: updateLastModuleCategory} = useMutation(gql`
mutation ($input: UpdateLastModuleCategoryInput!){updateLastModuleCategory(input: $input) {
const {mutate: updateLastModuleLevel} = useMutation(gql`
mutation ($input: UpdateLastModuleLevelInput!){updateLastModuleLevel(input: $input) {
clientMutationId
user {
username
lastModuleCategory {
lastModuleLevel {
name
id
}
}
}}`);
updateLastModuleCategory({
updateLastModuleLevel({
input: {
id: moduleCategory.id,
id: moduleLevel.id,
},
});

View File

@ -18,7 +18,7 @@
{{ teaser }}
</p>
<div class="module-teaser__pills">
<pill :text="category?.name"></pill>
<pill :text="level?.name"></pill>
<pill :text="categoryType?.name"></pill>
</div>
</div>
@ -30,7 +30,7 @@
export default {
components: {Pill},
props: ['metaTitle', 'title', 'teaser', 'id', 'slug', 'heroImage', 'category', 'categoryType'],
props: ['metaTitle', 'title', 'teaser', 'id', 'slug', 'heroImage', 'level', 'categoryType'],
computed: {

View File

@ -9,7 +9,7 @@ fragment ModuleParts on ModuleNode {
heroSource
solutionsEnabled
inEditMode @client
category {
level {
id
name
}

View File

@ -10,7 +10,7 @@ fragment UserParts on PrivateUserNode {
avatarUrl
expiryDate
readOnly
lastModuleCategory {
lastModuleLevel {
id
name
}

View File

@ -14,7 +14,7 @@ export interface Me {
team: any;
lastTopic: any;
readOnly: boolean;
lastModuleCategory: any;
lastModuleLevel: any;
}
export interface MeQuery {
@ -45,7 +45,7 @@ const defaultMe: MeQuery = {
team: null,
readOnly: false,
lastTopic: undefined,
lastModuleCategory: undefined,
lastModuleLevel: undefined,
},
};
@ -80,8 +80,8 @@ const getCurrentClassName = (me: Me) => {
return currentClass ? currentClass.name : me.schoolClasses.length ? me.schoolClasses[0].name : '';
};
const getLastModuleCategory = (me: Me) => {
return me.lastModuleCategory;
const getLastModuleLevel = (me: Me) => {
return me.lastModuleLevel;
}
const getMe = () => {
@ -134,9 +134,9 @@ const meMixin = {
// @ts-ignore
return getCurrentClassName(this.$data.me);
},
lastModuleCategory(): any {
lastModuleLevel(): any {
// @ts-ignore
return getLastModuleCategory(this.$data.me);
return getLastModuleLevel(this.$data.me);
}
},

View File

@ -1,4 +1,4 @@
from .models.module import Module, ModuleCategory, ModuleType
from .models.module import Module, ModuleLevel, ModuleType
def analyze_module_meta_titles():
all_nodes = []
@ -19,14 +19,14 @@ def analyze_module_meta_titles():
def create_default_categories():
for lehrjahr in range(1,4):
module_category, created = ModuleCategory.objects.get_or_create(name=f"{lehrjahr}. Lehrjahr")
module_category, created = ModuleLevel.objects.get_or_create(name=f"{lehrjahr}. Lehrjahr")
for type in range(1, 10):
ModuleType.objects.get_or_create(name=f"Lernfeld {type}")
def categorize_modules():
for category in ModuleCategory.objects.all():
for category in ModuleLevel.objects.all():
modules = Module.objects.filter(category__isnull=True, meta_title__icontains=category.name)
print(f"{category.name}: {modules.count()}")
modules.update(category=category)
@ -39,10 +39,10 @@ def categorize_modules():
def uncategorize_modules():
ModuleType.objects.all().delete()
ModuleCategory.objects.all().delete()
ModuleLevel.objects.all().delete()
def delete_unused_categories():
for category in ModuleCategory.objects.all():
for category in ModuleLevel.objects.all():
if not category.module_set.exists():
category.delete()

View File

@ -28,7 +28,7 @@ from books.blocks import (
SurveyBlock,
VideoBlock,
)
from books.models import Book, Chapter, ContentBlock, Module, TextBlock, Topic, ModuleCategory, ModuleType
from books.models import Book, Chapter, ContentBlock, Module, TextBlock, Topic, ModuleLevel, ModuleType
from core.factories import (
BasePageFactory,
DummyImageFactory,
@ -201,9 +201,9 @@ class VideoBlockFactory(wagtail_factories.StructBlockFactory):
class Meta:
model = VideoBlock
class ModuleCategoryFactory(factory.DjangoModelFactory):
class ModuleLevelFactory(factory.DjangoModelFactory):
class Meta:
model = ModuleCategory
model = ModuleLevel
name = '1. Lehrjahr'

View File

@ -9,19 +9,19 @@ from core.wagtail_utils import StrictHierarchyPage, get_default_settings
from users.models import SchoolClass
from django.utils.text import slugify
class ModuleCategory(models.Model):
class ModuleLevel(models.Model):
name = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.name
class Meta:
verbose_name_plural = _("module categories")
verbose_name = _("module category")
verbose_name_plural = _("module Levels")
verbose_name = _("module level")
def default_category():
return ModuleCategory.objects.first().pk
return ModuleLevel.objects.first().pk
class ModuleType(models.Model):
@ -42,7 +42,7 @@ class Module(StrictHierarchyPage):
verbose_name_plural = "Module"
meta_title = models.CharField(max_length=255, help_text="e.g. 'Intro' or 'Modul 1'")
category = models.ForeignKey(ModuleCategory, on_delete=models.SET_NULL, blank=True, null=True)
level = models.ForeignKey(ModuleLevel, on_delete=models.SET_NULL, blank=True, null=True)
category_type = models.ForeignKey(ModuleType, on_delete=models.SET_NULL, blank=True, null=True)
@ -62,12 +62,10 @@ class Module(StrictHierarchyPage):
solutions_enabled_for = models.ManyToManyField(SchoolClass)
# TODO: Filter category_type by category
content_panels = [
FieldPanel("title", classname="full title"),
FieldPanel("meta_title", classname="full title"),
FieldPanel("category"),
FieldPanel("level"),
FieldPanel("category_type"),
FieldPanel("hero_image"),
FieldPanel("hero_source"),
@ -161,12 +159,6 @@ class Module(StrictHierarchyPage):
def get_admin_display_title(self):
return f"{self.meta_title} - {self.title}"
@property
def category_name(self) -> str:
return self.category.name if self.category else ""
@property
def category_type_name(self) -> str:
return self.category_type.name if self.category_type else ""
class RecentModule(models.Model):

View File

@ -1,7 +1,7 @@
from books.schema.mutations.chapter import UpdateChapterVisibility
from books.schema.mutations.contentblock import DuplicateContentBlock, MutateContentBlock, AddContentBlock, \
DeleteContentBlock
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule, SyncModuleVisibility, UpdateLastModuleCategory
from books.schema.mutations.module import UpdateSolutionVisibility, UpdateLastModule, SyncModuleVisibility, UpdateLastModuleLevel
from books.schema.mutations.snapshot import CreateSnapshot, ApplySnapshot, ShareSnapshot, UpdateSnapshot, DeleteSnapshot
from books.schema.mutations.topic import UpdateLastTopic
@ -14,7 +14,7 @@ class BookMutations(object):
update_solution_visibility = UpdateSolutionVisibility.Field()
update_last_module = UpdateLastModule.Field()
update_last_topic = UpdateLastTopic.Field()
update_last_module_category = UpdateLastModuleCategory.Field()
update_last_module_level = UpdateLastModuleLevel.Field()
update_chapter_visibility = UpdateChapterVisibility.Field()
sync_module_visibility = SyncModuleVisibility.Field()
create_snapshot = CreateSnapshot.Field()

View File

@ -3,7 +3,7 @@ from django.utils import timezone
from graphene import relay
from api.utils import get_object
from books.models import Module, RecentModule, ModuleCategory
from books.models import Module, RecentModule, ModuleLevel
from books.schema.nodes import ModuleNode
from users.models import SchoolClass, User
from users.schema import PrivateUserNode
@ -105,7 +105,7 @@ class SyncModuleVisibility(relay.ClientIDMutation):
return cls(success=True)
class UpdateLastModuleCategory(relay.ClientIDMutation):
class UpdateLastModuleLevel(relay.ClientIDMutation):
class Input:
id = graphene.ID()
@ -115,8 +115,8 @@ class UpdateLastModuleCategory(relay.ClientIDMutation):
def mutate_and_get_payload(cls, root, info, **args):
user = info.context.user
id = args.get('id')
module_category = get_object(ModuleCategory, id)
module_level = get_object(ModuleLevel, id)
User.objects.filter(pk=user.id).update(last_module_category_id=module_category.id)
User.objects.filter(pk=user.id).update(last_module_level_id=module_level.id)
return cls(user=user)

View File

@ -6,10 +6,10 @@ from graphene_django.filter import DjangoFilterConnectionField
from assignments.models import StudentSubmission
from assignments.schema.types import AssignmentNode, StudentSubmissionNode
from books.models import Module, Chapter, ContentBlock, RecentModule, ModuleCategory, ModuleType
from books.models import Module, Chapter, ContentBlock, RecentModule, ModuleLevel, ModuleType
from books.schema.interfaces.module import ModuleInterface
from books.schema.nodes.chapter import ChapterNode
from books.schema.nodes.module_category import ModuleCategoryNode
from books.schema.nodes.module_category import ModuleLevelNode
from books.schema.nodes.module_category_type import ModuleCategoryTypeNode
from notes.models import ModuleBookmark, ContentBlockBookmark, ChapterBookmark
from notes.schema import (
@ -36,7 +36,7 @@ class ModuleNode(DjangoObjectType):
"hero_image",
"hero_source",
"topic",
"category",
"level",
"category_type",
]
filter_fields = {
@ -56,7 +56,7 @@ class ModuleNode(DjangoObjectType):
snapshots = graphene.List("books.schema.nodes.SnapshotNode")
objective_groups = graphene.List(ObjectiveGroupNode)
assignments = graphene.List(AssignmentNode)
category = graphene.Field(ModuleCategoryNode)
category = graphene.Field(ModuleLevelNode)
category_type = graphene.Field(ModuleCategoryTypeNode)
def resolve_chapters(self, info, **kwargs):
@ -111,7 +111,7 @@ class ModuleNode(DjangoObjectType):
return parent.objective_groups.all().prefetch_related("hidden_for")
def resolve_category(self, info, **kwargs):
return ModuleCategory.objects.get(pk=self.category_id) if self.category_id else None
return ModuleLevel.objects.get(pk=self.category_id) if self.category_id else None
def resolve_category_type(self, info, **kwargs):
return ModuleType.objects.get(pk=self.category_type_id) if self.category_type_id else None

View File

@ -2,12 +2,12 @@ from graphene import relay
from graphene import relay
from graphene_django import DjangoObjectType
from books.models import ModuleCategory
from books.models import ModuleLevel
class ModuleCategoryNode(DjangoObjectType):
class ModuleLevelNode(DjangoObjectType):
class Meta:
model = ModuleCategory
model = ModuleLevel
interfaces = (relay.Node,)
only_fields = [
"id",

View File

@ -7,9 +7,9 @@ from core.logger import get_logger
from .connections import TopicConnection, ModuleConnection
from .nodes import ContentBlockNode, ChapterNode, ModuleNode, NotFoundFailure, SnapshotNode, \
TopicOr404Node
from .nodes.module_category import ModuleCategoryNode
from .nodes.module_category import ModuleLevelNode
from .nodes.module_category_type import ModuleCategoryTypeNode
from ..models import Book, Topic, Module, Chapter, Snapshot, ModuleCategory, ModuleType
from ..models import Book, Topic, Module, Chapter, Snapshot, ModuleLevel, ModuleType
logger = get_logger(__name__)
@ -27,8 +27,8 @@ class BookQuery(object):
modules = relay.ConnectionField(ModuleConnection)
chapters = DjangoFilterConnectionField(ChapterNode)
module_category = graphene.Field(ModuleCategoryNode, id=graphene.ID(required=True))
module_categories = graphene.List(ModuleCategoryNode)
module_level = graphene.Field(ModuleLevelNode, id=graphene.ID(required=True))
module_levels = graphene.List(ModuleLevelNode)
module_category_type= graphene.Field(ModuleCategoryTypeNode, id=graphene.ID(required=True))
module_category_types = graphene.List(ModuleCategoryTypeNode)
@ -80,18 +80,17 @@ class BookQuery(object):
return None
def resolve_module_category(self, info, **kwargs):
id = kwargs.get('id')
def resolve_module_level(self, info, **kwargs):
module_level_id = kwargs.get('id')
try:
if id is not None:
module_category = get_object(Module, id)
return module_category
if module_level_id is not None:
return get_object(Module, module_level_id)
except Module.DoesNotExist:
return None
def resolve_module_categories(self, *args, **kwargs):
return ModuleCategory.objects.filter(**kwargs)
def resolve_module_levels(self, *args, **kwargs):
return ModuleLevel.objects.filter(**kwargs)
def resolve_module_category_type(self, info, **kwargs):
id = kwargs.get('id')

View File

@ -5,7 +5,7 @@ from graphql_relay import to_global_id
from api.schema import schema
from api.utils import get_object
from books.models import ContentBlock, Chapter
from books.factories import ModuleFactory, ModuleCategoryFactory
from books.factories import ModuleFactory, ModuleLevelFactory
from core.factories import UserFactory
from users.models import User
@ -122,26 +122,26 @@ class NewContentBlockMutationTest(TestCase):
self.assertEqual(content.get('type'), 'image_url_block')
self.assertEqual(content.get('value'), {'url': '/test.png'})
def test_updateLastModuleCategory(self):
def test_updateLastModuleLevel(self):
self.assertIsNone(self.user.last_module_category, None)
moduleCategory = ModuleCategoryFactory(name='1. Lehrjahr')
moduleCategory1 = ModuleCategoryFactory(name='2. Lehrjahr')
moduleLevel= ModuleLevelFactory(name='1. Lehrjahr')
moduleLevel1 = ModuleLevelFactory(name='2. Lehrjahr')
mutation = """
mutation ($input: UpdateLastModuleCategoryInput!){updateLastModuleCategory(input: $input) {
mutation ($input: UpdateLastModuleLevelInput!){updateLastModuleLevel(input: $input) {
clientMutationId
user {
username
lastModuleCategory {
lastModuleLevel {
name
id
}
}
}}
"""
result = self.client.execute(mutation, variables={"input": {"id": moduleCategory1.id}})
result = self.client.execute(mutation, variables={"input": {"id": moduleLevel1.id}})
self.assertIsNone(result.get('errors'))
updated_user = User.objects.get(id=self.user.id)
self.assertEqual(updated_user.last_module_category.name, moduleCategory1.name)
self.assertEqual(updated_user.last_module_category.name, moduleLevel1.name)

View File

@ -5,19 +5,19 @@ from wagtail.contrib.modeladmin.options import (
)
from wagtail import hooks
from .models.module import ModuleCategory, ModuleType, Module
from .models.module import ModuleLevel, ModuleType, Module
from django.utils.translation import gettext_lazy as _
class ModuleAdmin(ModelAdmin):
model = Module
list_display = ("title", "meta_title", "category", "category_type")
list_display = ("title", "meta_title", "level", "category_type")
search_fields = ("title", "meta_title")
list_filter = ("category", "category_type")
list_filter = ("level", "category_type")
class ModuleCategoryAdmin(ModelAdmin):
model = ModuleCategory
class ModuleLevelAdmin(ModelAdmin):
model = ModuleLevel
list_display = ("name",)
ordering = ("name",)
@ -33,7 +33,7 @@ class InstrumentGroup(ModelAdminGroup):
menu_label = _("Modules")
items = (
ModuleAdmin,
ModuleCategoryAdmin,
ModuleLevelAdmin,
ModuleTypeAdmin,
)

View File

@ -0,0 +1,20 @@
# Generated by Django 3.2.16 on 2023-08-21 12:07
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('books', '0048_auto_20230821_0922'),
('users', '0033_alter_license_isbn'),
]
operations = [
migrations.AddField(
model_name='user',
name='last_module_level',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='books.modulelevel'),
),
]

View File

@ -33,7 +33,7 @@ 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_module_category = models.ForeignKey('books.ModuleCategory', related_name='+', on_delete=models.SET_NULL, null=True)
last_module_level = models.ForeignKey('books.ModuleLevel', related_name='+', on_delete=models.SET_NULL, null=True)
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)

View File

@ -11,7 +11,7 @@ from graphql_relay import to_global_id
from api.types import FailureNode
from books.models import Module
from books.schema.nodes import ModuleCategoryNode
from books.schema.nodes import ModuleLevelNode
from books.schema.queries import ModuleNode
from users.models import SchoolClass, SchoolClassMember, Team, User
@ -104,7 +104,7 @@ class PrivateUserNode(DjangoObjectType):
"onboarding_visited",
"team",
"read_only",
"last_module_category"
"last_module_level"
]
interfaces = (relay.Node,)