Refactoring

This commit is contained in:
Lorenz Padberg 2023-06-19 11:01:35 +02:00
parent 7ccc771ca7
commit 89ff4af3c8
19 changed files with 135 additions and 88 deletions

View File

@ -14,6 +14,4 @@ import { defineProps } from "vue";
const props = defineProps<{
dueDate: DueDate;
}>();
console.log(props.dueDate);
</script>

View File

@ -23,8 +23,6 @@ const props = defineProps<{
}>();
const courseSession = useCurrentCourseSession();
console.log(props.maxCount);
const dueDates = courseSession.value.duedates.slice(0, props.maxCount);
console.log(courseSession.value.duedates);
</script>

View File

@ -1,9 +1,11 @@
import dayjs from "dayjs";
export const dueDatesTestData = () => {
return [
{
id: 1,
start: "2023-06-14T15:00:00+02:00",
end: "2023-06-14T18:00:00+02:00",
start: dayjs("2023-06-14T15:00:00+02:00"),
end: dayjs("2023-06-14T18:00:00+02:00"),
title: "Präsenzkurs Kickoff",
url: "/course/überbetriebliche-kurse/learn/kickoff/präsenzkurs-kickoff",
course_session: 2,
@ -11,8 +13,8 @@ export const dueDatesTestData = () => {
},
{
id: 2,
start: "2023-06-15T15:00:00+02:00",
end: "2023-06-15T18:00:00+02:00",
start: dayjs("2023-06-15T15:00:00+02:00"),
end: dayjs("2023-06-15T18:00:00+02:00"),
title: "Präsenzkurs Basis",
url: "/course/überbetriebliche-kurse/learn/basis/präsenzkurs-basis",
course_session: 2,
@ -20,8 +22,8 @@ export const dueDatesTestData = () => {
},
{
id: 3,
start: "2023-06-16T15:00:00+02:00",
end: "2023-06-16T18:00:00+02:00",
start: dayjs("2023-06-16T15:00:00+02:00"),
end: dayjs("2023-06-16T18:00:00+02:00"),
title: "Präsenzkurs Fahrzeug",
url: "/course/überbetriebliche-kurse/learn/fahrzeug/präsenzkurs-fahrzeug",
course_session: 2,
@ -29,8 +31,8 @@ export const dueDatesTestData = () => {
},
{
id: 4,
start: "2023-06-16T15:00:00+02:00",
end: "2023-06-16T18:00:00+02:00",
start: dayjs("2023-06-16T15:00:00+02:00"),
end: dayjs("2023-06-16T18:00:00+02:00"),
title: "Präsenzkurs Flugzeuge",
url: "/course/überbetriebliche-kurse/learn/fahrzeug/präsenzkurs-fahrzeug",
course_session: 2,
@ -38,8 +40,8 @@ export const dueDatesTestData = () => {
},
{
id: 5,
start: "2023-07-16T11:00:00+02:00",
end: "2023-07-16T18:00:00+02:00",
start: dayjs("2023-07-16T11:00:00+02:00"),
end: dayjs("2023-07-16T18:00:00+02:00"),
title: "Präsenzkurs Motorräder",
url: "/course/überbetriebliche-kurse/learn/fahrzeug/präsenzkurs-fahrzeug",
course_session: 2,
@ -47,8 +49,8 @@ export const dueDatesTestData = () => {
},
{
id: 6,
start: "2023-08-09T15:00:00+02:00",
end: "2023-08-09T19:00:00+02:00",
start: dayjs("2023-08-09T15:00:00+02:00"),
end: dayjs("2023-08-09T19:00:00+02:00"),
title: "Präsenzkurs Fahrräder",
url: "/course/überbetriebliche-kurse/learn/fahrzeug/präsenzkurs-fahrzeug",
course_session: 2,

View File

@ -1,7 +1,6 @@
export const formatDate = (start_str: string, end_str: string) => {
const start = new Date(start_str);
const end = new Date(end_str);
import type { Dayjs } from "dayjs";
export const formatDate = (start: Dayjs, end: Dayjs) => {
const startDateString = getDateString(start);
const endDateString = getDateString(end);
@ -14,14 +13,10 @@ export const formatDate = (start_str: string, end_str: string) => {
)}`;
};
const getTimeString = (date: Date) => {
return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
const getTimeString = (date: Dayjs) => {
return `${date.format("HH:mm")}`;
};
const getDateString = (date: Date) => {
return date.toLocaleDateString([], {
day: "numeric",
month: "short",
year: "numeric",
});
const getDateString = (date: Dayjs) => {
return `${date.format("DD MMM YYYY")}`;
};

View File

@ -1,6 +1,5 @@
<script setup lang="ts">
import * as d3 from "d3";
import * as log from "loglevel";
import { computed, onMounted } from "vue";
// @ts-ignore
@ -17,7 +16,6 @@ const props = defineProps<{
}>();
onMounted(async () => {
log.debug("LearningPathCircle mounted");
render();
});

View File

@ -10,6 +10,7 @@ import type {
} from "@/types";
import eventBus from "@/utils/eventBus";
import { useLocalStorage } from "@vueuse/core";
import dayjs from "dayjs";
import uniqBy from "lodash/uniqBy";
import log from "loglevel";
import { defineStore } from "pinia";
@ -25,7 +26,6 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
async function loadCourseSessionsData(reload = false) {
log.debug("loadCourseSessionsData called");
allCourseSessions.value = await itGetCached(`/api/course/sessions/`, {
reload: reload,
});
@ -39,6 +39,11 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
reload: reload,
})) as CourseSessionUser[];
cs.users = users;
cs.duedates.forEach((dueDate) => {
dueDate.start = dayjs(dueDate.start);
dueDate.end = dayjs(dueDate.end);
console.log(dueDate);
});
})
);

View File

@ -1,5 +1,6 @@
import type { AssignmentCompletionStatus as AssignmentCompletionStatusGenerated } from "@/gql/graphql";
import type { Circle } from "@/services/circle";
import { Dayjs } from "dayjs";
import type { Component } from "vue";
export type LoginMethod = "local" | "sso";
@ -560,8 +561,8 @@ export interface UserAssignmentCompletionStatus {
export type DueDate = {
id: number;
start: string;
end: string;
start: Dayjs;
end: Dayjs;
title: string;
url: string;
course_session: number | null;

View File

@ -469,9 +469,9 @@ else:
structlog.configure(
processors=shared_processors
+ [
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
+ [
structlog.stdlib.ProcessorFormatter.wrap_for_formatter,
],
context_class=dict,
logger_factory=structlog.stdlib.LoggerFactory(),
wrapper_class=structlog.stdlib.BoundLogger,

View File

@ -102,7 +102,7 @@ class CourseSessionSerializer(serializers.ModelSerializer):
"media_library_url",
"course_url",
"documents",
"duedates"
"duedates",
]

View File

@ -12,13 +12,7 @@ from vbv_lernwelt.learnpath.models import (
@admin.register(DueDate)
class DueDateAdmin(admin.ModelAdmin):
date_hierarchy = "end"
list_display = [
"title",
"course_session",
"start",
"end",
"unset"
]
list_display = ["title", "course_session", "start", "end", "unset"]
list_filter = ["course_session"]
def formfield_for_foreignkey(self, db_field, request, **kwargs):

View File

@ -4,16 +4,20 @@ import structlog
from django.utils import timezone
from factory.django import DjangoModelFactory
from .models import DueDate
from ..assignment.models import Assignment
from ..course.models import CourseSession
from ..learnpath.models import LearningContentAttendanceCourse
from .models import DueDate
logger = structlog.get_logger(__name__)
def get_date(date_string):
return datetime.datetime.strptime(date_string, '%b %d %Y', ).astimezone(timezone.get_current_timezone())
return datetime.datetime.strptime(
date_string,
"%b %d %Y",
).astimezone(timezone.get_current_timezone())
class DueDateFactory(DjangoModelFactory):
@ -26,14 +30,18 @@ class DueDateFactory(DjangoModelFactory):
def generate_events(start=timezone.now()):
for i in range(20):
DueDateFactory(title=f"{i}", start=start + datetime.timedelta(days=i),
end=start + datetime.timedelta(days=i, hours=1))
DueDateFactory(
title=f"{i}",
start=start + datetime.timedelta(days=i),
end=start + datetime.timedelta(days=i, hours=1),
)
def hour_rounder(t):
# Rounds to nearest hour by adding a timedelta hour if minute >= 30
return (t.replace(second=0, microsecond=0, minute=0, hour=t.hour)
+ datetime.timedelta(hours=t.minute // 30))
return t.replace(
second=0, microsecond=0, minute=0, hour=t.hour
) + datetime.timedelta(hours=t.minute // 30)
def create_duedates_for_all_course_sessions():
@ -45,22 +53,33 @@ def create_duedates_for_all_course_sessions():
def create_duedates_for_course_session(course_session: CourseSession):
course = course_session.course
attendance_courses = list(LearningContentAttendanceCourse.objects.descendant_of(course.get_learning_path()))
attendance_courses = list(
LearningContentAttendanceCourse.objects.descendant_of(
course.get_learning_path()
)
)
assignments = list(Assignment.objects.descendant_of(course.get_learning_path()))
contents = attendance_courses + assignments
for content in contents:
if callable(getattr(content, 'get_frontend_url', None)):
if callable(getattr(content, "get_frontend_url", None)):
url = content.get_frontend_url()
duedate, created = DueDate.objects.get_or_create(course_session=course_session,
title=content.title,
url=url,
page=content.specific)
duedate, created = DueDate.objects.get_or_create(
course_session=course_session,
title=content.title,
url=url,
page=content.specific,
)
if created:
pass
logger.info("Created duedate ", duedate=duedate, course_session=course_session, content=content)
logger.info(
"Created duedate ",
duedate=duedate,
course_session=course_session,
content=content,
)
def set_default_times_for_duedates():

View File

@ -1,6 +1,9 @@
import djclick as click
from vbv_lernwelt.duedate.factories import create_duedates_for_all_course_sessions, set_default_times_for_duedates
from vbv_lernwelt.duedate.factories import (
create_duedates_for_all_course_sessions,
set_default_times_for_duedates,
)
@click.command()

View File

@ -1,7 +1,7 @@
# Generated by Django 3.2.13 on 2023-06-14 09:29
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
@ -9,20 +9,40 @@ class Migration(migrations.Migration):
initial = True
dependencies = [
('course', '0004_import_fields'),
("course", "0004_import_fields"),
]
operations = [
migrations.CreateModel(
name='DueDate',
name="DueDate",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('start', models.DateTimeField(db_index=True, null=True)),
('end', models.DateTimeField(db_index=True, null=True)),
('title', models.CharField(default='Termin', max_length=1024)),
('url', models.URLField(blank=True, max_length=1024, null=True)),
('learning_content_id', models.CharField(blank=True, max_length=255, null=True)),
('course_session', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='events', to='course.coursesession')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("start", models.DateTimeField(db_index=True, null=True)),
("end", models.DateTimeField(db_index=True, null=True)),
("title", models.CharField(default="Termin", max_length=1024)),
("url", models.URLField(blank=True, max_length=1024, null=True)),
(
"learning_content_id",
models.CharField(blank=True, max_length=255, null=True),
),
(
"course_session",
models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="events",
to="course.coursesession",
),
),
],
),
]

View File

@ -1,24 +1,29 @@
# Generated by Django 3.2.13 on 2023-06-14 13:00
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wagtailcore', '0083_workflowcontenttype'),
('duedate', '0001_initial'),
("wagtailcore", "0083_workflowcontenttype"),
("duedate", "0001_initial"),
]
operations = [
migrations.RemoveField(
model_name='duedate',
name='learning_content_id',
model_name="duedate",
name="learning_content_id",
),
migrations.AddField(
model_name='duedate',
name='page',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to='wagtailcore.page'),
model_name="duedate",
name="page",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
to="wagtailcore.page",
),
),
]

View File

@ -12,12 +12,12 @@ from vbv_lernwelt.course.models import CourseSession
class DueDate(models.Model):
start = models.DateTimeField(null=True, db_index=True)
end = models.DateTimeField(db_index=True, null=True)
title = models.CharField(default=_('Termin'), max_length=1024)
title = models.CharField(default=_("Termin"), max_length=1024)
url = models.URLField(null=True, blank=True, max_length=1024)
course_session = models.ForeignKey(
'course.CourseSession',
"course.CourseSession",
on_delete=models.CASCADE,
related_name='duedates',
related_name="duedates",
null=True,
blank=True,
)
@ -25,12 +25,12 @@ class DueDate(models.Model):
page = models.ForeignKey(Page, on_delete=models.SET_NULL, null=True, blank=True)
def Meta(self):
ordering = ['start', 'end']
ordering = ["start", "end"]
verbose_name = _("Termin")
def __str__(self):
start_str = self.start.strftime('%Y-%m-%d %H:%M') if self.start else ''
end_str = self.end.strftime('%Y-%m-%d %H:%M') if self.end else ''
start_str = self.start.strftime("%Y-%m-%d %H:%M") if self.start else ""
end_str = self.end.strftime("%Y-%m-%d %H:%M") if self.end else ""
return f"DueDate: {self.title} {start_str} to {end_str}"
@property
@ -44,7 +44,9 @@ class DueDate(models.Model):
return self.end - self.start
@classmethod
def get_users_next_events_qs(cls, user: User, course_session: CourseSession = None, limit=10):
def get_users_next_events_qs(
cls, user: User, course_session: CourseSession = None, limit=10
):
"""
Returns a queryset of all duedates that are relevant for the given user. Ordered nearest start date first.
If course_session is given, only duedates for that course_session are returned.
@ -54,11 +56,14 @@ class DueDate(models.Model):
qs = cls.get_next_duedates_qs()
if course_session:
qs = qs.filter(course_session=course_session, course_session__course_assignment__user=user)
qs = qs.filter(
course_session=course_session,
course_session__course_assignment__user=user,
)
else:
qs = qs.filter(course_session__course_assignment__user=user)
qs = qs.order_by('start')[:limit]
qs = qs.order_by("start")[:limit]
return qs

View File

@ -6,4 +6,4 @@ from vbv_lernwelt.duedate.models import DueDate
class DueDateSerializer(serializers.ModelSerializer):
class Meta:
model = DueDate
fields = '__all__'
fields = "__all__"

View File

@ -34,5 +34,8 @@ class TesDueDatetModel(TestCase):
def generate_duedates(start=timezone.now()):
for i in range(20):
DueDateFactory(title=f"{i}", start=start + datetime.timedelta(days=i),
end=start + datetime.timedelta(days=i, hours=1))
DueDateFactory(
title=f"{i}",
start=start + datetime.timedelta(days=i),
end=start + datetime.timedelta(days=i, hours=1),
)

View File

@ -12,4 +12,4 @@ class TestDueDatetSerializer(TestCase):
duedates = DueDate.objects.all()
result = DueDateSerializer(duedates, many=True).data
assert result[0]['title'] == 'Prüfung Versicherungsvermittler/-in'
assert result[0]["title"] == "Prüfung Versicherungsvermittler/-in"

View File

@ -282,6 +282,7 @@ class LearningContentAttendanceCourse(LearningContent):
"""
Präsenzkurs
"""
parent_page_types = ["learnpath.Circle"]
subpage_types = []