Create ModuleFilters dynamically

This commit is contained in:
Lorenz Padberg 2023-08-07 16:18:58 +02:00
parent b5705cc991
commit aa095ac7ea
8 changed files with 132 additions and 21 deletions

View File

@ -2,7 +2,7 @@
<div> <div>
<div class="container"> <div class="container">
<div class="radio-group"> <div class="radio-group">
<div v-for="(category, index) in firstLevelCategories" :key="index" class="radio-item"> <div class="radio-item" v-for="(category, index) in firstLevelCategories" :key="index" >
<input <input
type="radio" type="radio"
:value="category" :value="category"
@ -10,13 +10,14 @@
v-model="selectedCategory" v-model="selectedCategory"
@change="filterModules" @change="filterModules"
/> />
<label :for="'category-' + index">{{ category }}</label> <label :for="'category-' + index">{{ category.name }}</label>
</div> </div>
</div> </div>
<div class="dropdown-container"> <div class="dropdown-container">
<select id="lernfeld-select" v-model="selectedLernfeld" @change="filterModules"> <select id="lernfeld-select" v-model="selectedLernfeld" @change="filterModules">
<option v-for="(lernfeld, index) in lernfeldOptions" :value="lernfeld" :key="index"> <option :value="lernfeld" v-for="(lernfeld, index) in lernfeldOptions" :key="index">
{{ lernfeld }} {{ lernfeld.name }}
</option> </option>
</select> </select>
</div> </div>
@ -36,28 +37,63 @@
<script setup lang="ts"> <script setup lang="ts">
import {computed, ref} from "vue"; import {computed, ref} from "vue";
import ModuleTeaser from "@/components/modules/ModuleTeaser.vue"; import ModuleTeaser from "@/components/modules/ModuleTeaser.vue";
import gql from "graphql-tag";
import {useQuery} from "@vue/apollo-composable";
const props = defineProps<{ const props = defineProps<{
modules: []; modules: [];
}>(); }>();
const selectedCategory = ref(null);
console.log("modules", props.modules)
const {result: moduleCategoriesResult} = useQuery(gql`
query ModuleCategoriesQuery {
moduleCategories {
name
id
}
}
`);
const lernfeldOptions = ['Alle Lernfelder', 'Lernfeld 1', 'Lernfeld 2', 'Lernfeld 3', 'Lernfeld 4', 'Lernfeld 5']; const nullCategory = {
const selectedLernfeld = ref('Alle Lernfelder'); name: '---',
id: null,
};
const selectedCategory = ref(nullCategory);
const firstLevelCategories = computed(() => { const firstLevelCategories = computed(() => {
return ["Alle Lehrjahre", "1. Lehrjahr", "2. Lehrjahr", "3. Lehrjahr",]; return [nullCategory, ...moduleCategoriesResult.value?.moduleCategories || []];
}); });
const {result: moduleCategoryTypesResult} = useQuery(gql`
query ModuleCategoryTypesQuery {
moduleCategoryTypes {
name
id
}
}
`);
const nullLernfeld = {
name: '---',
id: null,
};
const selectedLernfeld = ref(nullLernfeld);
const lernfeldOptions = computed(() => {
return [nullLernfeld, ...moduleCategoryTypesResult.value?.moduleCategoryTypes || []];
});
let filteredModules = computed(() => { let filteredModules = computed(() => {
return filterModules(); return filterModules();
}); });
// "$flavor.textInstrumentFilterShowAll"
function filterModules() { function filterModules() {
let filteredModules = props.modules; let filteredModules = props.modules;
@ -66,16 +102,16 @@
} }
// filter by Lehrjahr // filter by Lehrjahr
if (selectedCategory.value !== 'Alle Lehrjahre') { if (selectedCategory.value.name !== '---') {
filteredModules = filteredModules.filter((module) => { filteredModules = filteredModules.filter((module) => {
return module.categoryName.includes(selectedCategory.value); return module.categoryName.includes(selectedCategory.value.name);
}); });
} }
//filter by Lernfeld //filter by Lernfeld
if (selectedLernfeld.value !== 'Alle Lernfelder') { if (selectedLernfeld.value.name !== '---') {
filteredModules = filteredModules.filter((module) => { filteredModules = filteredModules.filter((module) => {
return module.categoryTypeName.includes(selectedLernfeld.value); return module.categoryTypeName.includes(selectedLernfeld.value.name);
}); });
} }

View File

@ -42,8 +42,8 @@ class Module(StrictHierarchyPage):
verbose_name_plural = "Module" verbose_name_plural = "Module"
meta_title = models.CharField(max_length=255, help_text="e.g. 'Intro' or 'Modul 1'") meta_title = models.CharField(max_length=255, help_text="e.g. 'Intro' or 'Modul 1'")
category = models.ForeignKey(ModuleCategory, on_delete=models.SET_NULL, null=True) category = models.ForeignKey(ModuleCategory, on_delete=models.SET_NULL, blank=True, null=True)
category_type = models.ForeignKey(ModuleType, on_delete=models.SET_NULL, null=True) category_type = models.ForeignKey(ModuleType, on_delete=models.SET_NULL, blank=True, null=True)
hero_image = models.ForeignKey( hero_image = models.ForeignKey(

View File

@ -34,6 +34,8 @@ class ModuleNode(DjangoObjectType):
"hero_image", "hero_image",
"hero_source", "hero_source",
"topic", "topic",
"category_name",
"category_type_name",
] ]
filter_fields = { filter_fields = {
"slug": ["exact", "icontains", "in"], "slug": ["exact", "icontains", "in"],
@ -52,6 +54,8 @@ class ModuleNode(DjangoObjectType):
snapshots = graphene.List("books.schema.nodes.SnapshotNode") snapshots = graphene.List("books.schema.nodes.SnapshotNode")
objective_groups = graphene.List(ObjectiveGroupNode) objective_groups = graphene.List(ObjectiveGroupNode)
assignments = graphene.List(AssignmentNode) assignments = graphene.List(AssignmentNode)
category_name = graphene.String()
category_type_name = graphene.String()
def resolve_chapters(self, info, **kwargs): def resolve_chapters(self, info, **kwargs):
return Chapter.get_by_parent(self) return Chapter.get_by_parent(self)
@ -115,7 +119,6 @@ class ModuleNode(DjangoObjectType):
def resolve_assignments(parent: Module, info, **kwargs): def resolve_assignments(parent: Module, info, **kwargs):
return parent.assignments.all() return parent.assignments.all()
class RecentModuleNode(DjangoObjectType): class RecentModuleNode(DjangoObjectType):
class Meta: class Meta:
model = RecentModule model = RecentModule

View File

@ -0,0 +1,15 @@
from graphene import relay
from graphene import relay
from graphene_django import DjangoObjectType
from books.models import ModuleType
class ModuleCategoryTypeNode(DjangoObjectType):
class Meta:
model = ModuleType
interfaces = (relay.Node,)
only_fields = [
"id",
"name",
]

View File

@ -7,7 +7,9 @@ from core.logger import get_logger
from .connections import TopicConnection, ModuleConnection from .connections import TopicConnection, ModuleConnection
from .nodes import ContentBlockNode, ChapterNode, ModuleNode, NotFoundFailure, SnapshotNode, \ from .nodes import ContentBlockNode, ChapterNode, ModuleNode, NotFoundFailure, SnapshotNode, \
TopicOr404Node TopicOr404Node
from ..models import Book, Topic, Module, Chapter, Snapshot from .nodes.module_category import ModuleCategoryNode
from .nodes.module_category_type import ModuleCategoryTypeNode
from ..models import Book, Topic, Module, Chapter, Snapshot, ModuleCategory, ModuleType
logger = get_logger(__name__) logger = get_logger(__name__)
@ -25,6 +27,12 @@ class BookQuery(object):
modules = relay.ConnectionField(ModuleConnection) modules = relay.ConnectionField(ModuleConnection)
chapters = DjangoFilterConnectionField(ChapterNode) chapters = DjangoFilterConnectionField(ChapterNode)
module_category = graphene.Field(ModuleCategoryNode, id=graphene.ID(required=True))
module_categories = graphene.List(ModuleCategoryNode)
module_category_type= graphene.Field(ModuleCategoryTypeNode, id=graphene.ID(required=True))
module_category_types = graphene.List(ModuleCategoryTypeNode)
def resolve_books(self, *args, **kwargs): def resolve_books(self, *args, **kwargs):
return Book.objects.filter(**kwargs).live() return Book.objects.filter(**kwargs).live()
@ -70,3 +78,43 @@ class BookQuery(object):
except Topic.DoesNotExist: except Topic.DoesNotExist:
return NotFoundFailure return NotFoundFailure
return None return None
def resolve_module_category(self, info, **kwargs):
id = kwargs.get('id')
try:
if id is not None:
module_category = get_object(Module, id)
return module_category
except Module.DoesNotExist:
return None
def resolve_module_categories(self, *args, **kwargs):
return ModuleCategory.objects.filter(**kwargs)
def resolve_module_category_type(self, info, **kwargs):
id = kwargs.get('id')
try:
if id is not None:
module_category_type = get_object(Module, id)
return module_category_type
except Module.DoesNotExist:
return None
def resolve_module_category_types(self, *args, **kwargs):
return ModuleType.objects.filter(**kwargs)
class ModuleTypeQuery(graphene.ObjectType):
node = relay.Node.Field()
name = graphene.String()
id = graphene.ID()

View File

@ -236,7 +236,7 @@ interface ChapterInterface {
title: String title: String
} }
type ChapterNode implements Node & ChapterInterface { type ChapterNode implements Node, ChapterInterface {
title: String title: String
slug: String! slug: String!
description: String description: String
@ -306,7 +306,7 @@ interface ContentBlockInterface {
type: String type: String
} }
type ContentBlockNode implements Node & ContentBlockInterface { type ContentBlockNode implements Node, ContentBlockInterface {
title: String title: String
slug: String! slug: String!
hiddenFor: [SchoolClassNode] hiddenFor: [SchoolClassNode]
@ -621,6 +621,11 @@ type ModuleBookmarkNode {
module: ModuleNode! module: ModuleNode!
} }
type ModuleCategoryNode implements Node {
id: ID!
name: String!
}
type ModuleConnection { type ModuleConnection {
pageInfo: PageInfo! pageInfo: PageInfo!
edges: [ModuleEdge]! edges: [ModuleEdge]!
@ -660,6 +665,8 @@ type ModuleNode implements ModuleInterface {
myContentBookmarks(offset: Int, before: String, after: String, first: Int, last: Int): ContentBlockBookmarkNodeConnection myContentBookmarks(offset: Int, before: String, after: String, first: Int, last: Int): ContentBlockBookmarkNodeConnection
myChapterBookmarks(offset: Int, before: String, after: String, first: Int, last: Int): ChapterBookmarkNodeConnection myChapterBookmarks(offset: Int, before: String, after: String, first: Int, last: Int): ChapterBookmarkNodeConnection
snapshots: [SnapshotNode] snapshots: [SnapshotNode]
categoryName: String
categoryTypeName: String
} }
type ModuleNodeConnection { type ModuleNodeConnection {
@ -928,6 +935,8 @@ type Query {
topics(before: String, after: String, first: Int, last: Int): TopicConnection topics(before: String, after: String, first: Int, last: Int): TopicConnection
modules(before: String, after: String, first: Int, last: Int): ModuleConnection modules(before: String, after: String, first: Int, last: Int): ModuleConnection
chapters(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection chapters(offset: Int, before: String, after: String, first: Int, last: Int, slug: String, title: String): ChapterNodeConnection
moduleCategory(id: ID!): ModuleCategoryNode
moduleCategories: [ModuleCategoryNode]
objectiveGroup(id: ID!): ObjectiveGroupNode objectiveGroup(id: ID!): ObjectiveGroupNode
objectiveGroups(offset: Int, before: String, after: String, first: Int, last: Int, title: String, module_Slug: String): ObjectiveGroupNodeConnection objectiveGroups(offset: Int, before: String, after: String, first: Int, last: Int, title: String, module_Slug: String): ObjectiveGroupNodeConnection
roomEntry(id: ID, slug: String): RoomEntryNode roomEntry(id: ID, slug: String): RoomEntryNode
@ -1013,7 +1022,7 @@ type SnapshotChangesNode {
newContentBlocks: Int! newContentBlocks: Int!
} }
type SnapshotChapterNode implements Node & ChapterInterface { type SnapshotChapterNode implements Node, ChapterInterface {
id: ID! id: ID!
description: String description: String
title: String title: String
@ -1022,7 +1031,7 @@ type SnapshotChapterNode implements Node & ChapterInterface {
titleHidden: Boolean titleHidden: Boolean
} }
type SnapshotContentBlockNode implements Node & ContentBlockInterface { type SnapshotContentBlockNode implements Node, ContentBlockInterface {
id: ID! id: ID!
title: String title: String
contents: GenericStreamFieldType contents: GenericStreamFieldType