Refactoring
This commit is contained in:
parent
7ccc771ca7
commit
89ff4af3c8
|
|
@ -14,6 +14,4 @@ import { defineProps } from "vue";
|
|||
const props = defineProps<{
|
||||
dueDate: DueDate;
|
||||
}>();
|
||||
|
||||
console.log(props.dueDate);
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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")}`;
|
||||
};
|
||||
|
|
@ -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();
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class CourseSessionSerializer(serializers.ModelSerializer):
|
|||
"media_library_url",
|
||||
"course_url",
|
||||
"documents",
|
||||
"duedates"
|
||||
"duedates",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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():
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ from vbv_lernwelt.duedate.models import DueDate
|
|||
class DueDateSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = DueDate
|
||||
fields = '__all__'
|
||||
fields = "__all__"
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
)
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -282,6 +282,7 @@ class LearningContentAttendanceCourse(LearningContent):
|
|||
"""
|
||||
Präsenzkurs
|
||||
"""
|
||||
|
||||
parent_page_types = ["learnpath.Circle"]
|
||||
subpage_types = []
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue