Add proof of concept implementation for the profile filter
This commit is contained in:
parent
c84b25cc32
commit
dd1d1ff6fe
|
|
@ -356,6 +356,7 @@ type CircleObjectType implements CoursePageInterface {
|
||||||
frontend_url: String!
|
frontend_url: String!
|
||||||
course: CourseObjectType
|
course: CourseObjectType
|
||||||
learning_sequences: [LearningSequenceObjectType!]!
|
learning_sequences: [LearningSequenceObjectType!]!
|
||||||
|
profiles: [String]!
|
||||||
}
|
}
|
||||||
|
|
||||||
type LearningSequenceObjectType implements CoursePageInterface {
|
type LearningSequenceObjectType implements CoursePageInterface {
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,7 @@ export const COURSE_QUERY = graphql(`
|
||||||
circles {
|
circles {
|
||||||
description
|
description
|
||||||
goals
|
goals
|
||||||
|
profiles
|
||||||
...CoursePageFields
|
...CoursePageFields
|
||||||
learning_sequences {
|
learning_sequences {
|
||||||
icon
|
icon
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ import {
|
||||||
useCourseDataWithCompletion,
|
useCourseDataWithCompletion,
|
||||||
useCurrentCourseSession,
|
useCurrentCourseSession,
|
||||||
} from "@/composables";
|
} from "@/composables";
|
||||||
import CourseSessionDueDatesList from "@/components/dueDates/CourseSessionDueDatesList.vue";
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
courseSlug: string;
|
courseSlug: string;
|
||||||
|
|
@ -33,6 +32,8 @@ const course = computed(() => lpQueryResult.course.value);
|
||||||
|
|
||||||
const courseSession = useCurrentCourseSession();
|
const courseSession = useCurrentCourseSession();
|
||||||
|
|
||||||
|
const filter = ref("");
|
||||||
|
|
||||||
const { inProgressCirclesCount, circlesCount } = useCourseCircleProgress(
|
const { inProgressCirclesCount, circlesCount } = useCourseCircleProgress(
|
||||||
lpQueryResult.circles
|
lpQueryResult.circles
|
||||||
);
|
);
|
||||||
|
|
@ -66,10 +67,15 @@ const changeViewType = (viewType: ViewType) => {
|
||||||
|
|
||||||
<!-- Right -->
|
<!-- Right -->
|
||||||
<div v-if="!useMobileLayout" class="flex-grow">
|
<div v-if="!useMobileLayout" class="flex-grow">
|
||||||
<CourseSessionDueDatesList
|
<p>Zulassungsprofil</p>
|
||||||
:course-session-id="courseSession.id"
|
<div>
|
||||||
:max-count="2"
|
<button class="btn-primary" @click="filter = 'nonlife'">Nichtleben</button>
|
||||||
></CourseSessionDueDatesList>
|
<button class="btn-secondary" @click="filter = 'life'">Leben</button>
|
||||||
|
<button class="btn-secondary" @click="filter = 'sick'">
|
||||||
|
Krankenzusatzversicherung
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<p><a href="#" @click="filter = ''">Alle anzeigen (Allbranche)</a></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -101,6 +107,7 @@ const changeViewType = (viewType: ViewType) => {
|
||||||
<LearningPathPathView
|
<LearningPathPathView
|
||||||
:learning-path="learningPath"
|
:learning-path="learningPath"
|
||||||
:use-mobile-layout="useMobileLayout"
|
:use-mobile-layout="useMobileLayout"
|
||||||
|
:filter="filter"
|
||||||
:next-learning-content="lpQueryResult.nextLearningContent.value"
|
:next-learning-content="lpQueryResult.nextLearningContent.value"
|
||||||
></LearningPathPathView>
|
></LearningPathPathView>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,11 @@ import LearningPathCircleColumn from "@/pages/learningPath/learningPathPage/Lear
|
||||||
import LearningPathScrollButton from "@/pages/learningPath/learningPathPage/LearningPathScrollButton.vue";
|
import LearningPathScrollButton from "@/pages/learningPath/learningPathPage/LearningPathScrollButton.vue";
|
||||||
import { useScroll } from "@vueuse/core";
|
import { useScroll } from "@vueuse/core";
|
||||||
import { ref } from "vue";
|
import { ref } from "vue";
|
||||||
import type { LearningContentWithCompletion, LearningPathType } from "@/types";
|
import type {
|
||||||
|
LearningContentWithCompletion,
|
||||||
|
LearningPathType,
|
||||||
|
TopicType,
|
||||||
|
} from "@/types";
|
||||||
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
import LoadingSpinner from "@/components/ui/LoadingSpinner.vue";
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
|
|
@ -12,6 +16,7 @@ const props = defineProps<{
|
||||||
useMobileLayout: boolean;
|
useMobileLayout: boolean;
|
||||||
hideButtons?: boolean;
|
hideButtons?: boolean;
|
||||||
overrideCircleUrlBase?: string;
|
overrideCircleUrlBase?: string;
|
||||||
|
filter?: string;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const scrollIncrement = 600;
|
const scrollIncrement = 600;
|
||||||
|
|
@ -33,6 +38,14 @@ const scrollLeft = () => scrollLearnPathDiagram(-scrollIncrement);
|
||||||
const scrollLearnPathDiagram = (offset: number) => {
|
const scrollLearnPathDiagram = (offset: number) => {
|
||||||
x.value += offset;
|
x.value += offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const filterCircles = (topic: TopicType) => {
|
||||||
|
// return [];
|
||||||
|
if (props.filter) {
|
||||||
|
return topic.circles.filter((circle) => circle.profiles.indexOf(props.filter) > -1);
|
||||||
|
}
|
||||||
|
return topic.circles;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
|
@ -65,7 +78,7 @@ const scrollLearnPathDiagram = (offset: number) => {
|
||||||
</p>
|
</p>
|
||||||
<div class="flex flex-row pt-6">
|
<div class="flex flex-row pt-6">
|
||||||
<LearningPathCircleColumn
|
<LearningPathCircleColumn
|
||||||
v-for="(circle, circleIndex) in topic.circles"
|
v-for="(circle, circleIndex) in filterCircles(topic)"
|
||||||
:key="circle.id"
|
:key="circle.id"
|
||||||
:circle="circle"
|
:circle="circle"
|
||||||
:next-learning-content="props.nextLearningContent"
|
:next-learning-content="props.nextLearningContent"
|
||||||
|
|
|
||||||
|
|
@ -285,6 +285,10 @@ class CourseSessionUser(models.Model):
|
||||||
)
|
)
|
||||||
optional_attendance = models.BooleanField(default=False)
|
optional_attendance = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
chosen_profile = models.ForeignKey(
|
||||||
|
"learnpath.CourseProfile", on_delete=models.SET_NULL, blank=True, null=True
|
||||||
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
constraints = [
|
constraints = [
|
||||||
UniqueConstraint(
|
UniqueConstraint(
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import random
|
||||||
|
|
||||||
import graphene
|
import graphene
|
||||||
import structlog
|
import structlog
|
||||||
from graphene_django import DjangoObjectType
|
from graphene_django import DjangoObjectType
|
||||||
|
|
@ -299,14 +301,12 @@ class CircleObjectType(DjangoObjectType):
|
||||||
learning_sequences = graphene.List(
|
learning_sequences = graphene.List(
|
||||||
graphene.NonNull(LearningSequenceObjectType), required=True
|
graphene.NonNull(LearningSequenceObjectType), required=True
|
||||||
)
|
)
|
||||||
|
profiles = graphene.List(graphene.String, required=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Circle
|
model = Circle
|
||||||
interfaces = (CoursePageInterface,)
|
interfaces = (CoursePageInterface,)
|
||||||
fields = [
|
fields = ["description", "goals"]
|
||||||
"description",
|
|
||||||
"goals",
|
|
||||||
]
|
|
||||||
|
|
||||||
def resolve_learning_sequences(self: Circle, info, **kwargs):
|
def resolve_learning_sequences(self: Circle, info, **kwargs):
|
||||||
circle_descendants = None
|
circle_descendants = None
|
||||||
|
|
@ -335,6 +335,10 @@ class CircleObjectType(DjangoObjectType):
|
||||||
if descendant.specific_class == LearningSequence
|
if descendant.specific_class == LearningSequence
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def resolve_profiles(self, info, **kwargs):
|
||||||
|
choices = ["life", "nonlife", "sick"]
|
||||||
|
return [random.choice(choices)]
|
||||||
|
|
||||||
|
|
||||||
class TopicObjectType(DjangoObjectType):
|
class TopicObjectType(DjangoObjectType):
|
||||||
circles = graphene.List(graphene.NonNull(CircleObjectType), required=True)
|
circles = graphene.List(graphene.NonNull(CircleObjectType), required=True)
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,16 @@ class Topic(CourseBasePage):
|
||||||
return f"{self.title}"
|
return f"{self.title}"
|
||||||
|
|
||||||
|
|
||||||
|
class CourseProfile(models.Model):
|
||||||
|
title = models.CharField(max_length=255)
|
||||||
|
|
||||||
|
|
||||||
|
class CourseProfileToCircle(models.Model):
|
||||||
|
# this connects the course profile to a circle, because a circle can be in multiple profiles
|
||||||
|
# todo: to we even need a through model?
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Circle(CourseBasePage):
|
class Circle(CourseBasePage):
|
||||||
parent_page_types = ["learnpath.LearningPath"]
|
parent_page_types = ["learnpath.LearningPath"]
|
||||||
subpage_types = [
|
subpage_types = [
|
||||||
|
|
@ -95,6 +105,17 @@ class Circle(CourseBasePage):
|
||||||
|
|
||||||
goals = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)
|
goals = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES_WITH_HEADER)
|
||||||
|
|
||||||
|
profiles = models.ManyToManyField(CourseProfile, related_name="circles")
|
||||||
|
|
||||||
|
# profile = models.ForeignKey(
|
||||||
|
# ApprovalProfile,
|
||||||
|
# null=True,
|
||||||
|
# blank=True,
|
||||||
|
# on_delete=models.SET_NULL,
|
||||||
|
# related_name="circles",
|
||||||
|
# help_text="Zulassungsprofil",
|
||||||
|
# )
|
||||||
|
|
||||||
content_panels = Page.content_panels + [
|
content_panels = Page.content_panels + [
|
||||||
FieldPanel("description"),
|
FieldPanel("description"),
|
||||||
FieldPanel("goals"),
|
FieldPanel("goals"),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue