From 8a89bed0ac146885a7410cfe7288376644e55ceb Mon Sep 17 00:00:00 2001 From: Christian Cueni Date: Wed, 10 Apr 2024 11:00:38 +0200 Subject: [PATCH] WIP: Fix typecheck --- .../dashboard/AssignmentSummary.vue | 10 +- .../dashboard/CompetenceSummary.vue | 9 +- .../src/components/dashboard/CoursePanel.vue | 27 +++-- .../dashboard/MentorCompetenceSummary.vue | 5 +- .../dashboard/MentorMenteeCount.vue | 3 +- .../dashboard/MentorOpenTasksCount.vue | 3 +- .../FeedbackSubmissionProgress.vue | 2 +- client/src/gql/gql.ts | 16 +-- client/src/gql/graphql.ts | 31 ++++-- client/src/gql/schema.graphql | 104 ++++++++++-------- client/src/gql/typenames.ts | 1 + client/src/graphql/queries.ts | 42 +++++++ client/src/pages/SettingsPage.vue | 2 +- .../cockpit/documentPage/DocumentPage.vue | 2 +- client/src/pages/dashboard/DashboardPage.vue | 11 +- .../circlePage/DocumentSection.vue | 2 +- .../blocks/DocumentListBlock.vue | 2 +- .../blocks/EdoniqTestBlock.vue | 2 +- .../pages/onboarding/vv/CheckoutAddress.vue | 2 +- client/src/router/index.ts | 5 +- client/src/services/entities.ts | 2 +- client/src/services/files.ts | 2 +- client/src/services/learningMentees.ts | 2 +- client/src/stores/completion.ts | 2 +- client/src/stores/mediaLibrary.ts | 2 +- client/src/stores/notifications.ts | 2 +- client/src/stores/user.ts | 2 +- server/vbv_lernwelt/course/graphql/types.py | 1 + .../vbv_lernwelt/dashboard/graphql/queries.py | 3 +- .../dashboard/graphql/types/dashboard.py | 33 +++--- 30 files changed, 207 insertions(+), 125 deletions(-) diff --git a/client/src/components/dashboard/AssignmentSummary.vue b/client/src/components/dashboard/AssignmentSummary.vue index 27839360..5ea3c887 100644 --- a/client/src/components/dashboard/AssignmentSummary.vue +++ b/client/src/components/dashboard/AssignmentSummary.vue @@ -1,6 +1,7 @@ diff --git a/client/src/components/dashboard/CompetenceSummary.vue b/client/src/components/dashboard/CompetenceSummary.vue index 8de08f99..2c8c287c 100644 --- a/client/src/components/dashboard/CompetenceSummary.vue +++ b/client/src/components/dashboard/CompetenceSummary.vue @@ -1,5 +1,6 @@ diff --git a/client/src/components/dashboard/CoursePanel.vue b/client/src/components/dashboard/CoursePanel.vue index ec096663..b6498cd6 100644 --- a/client/src/components/dashboard/CoursePanel.vue +++ b/client/src/components/dashboard/CoursePanel.vue @@ -17,36 +17,41 @@ const mentorWidgets = [ const progressWidgets = ["CompetenceWidget", "CompetenceCertificateWidget"]; const props = defineProps<{ - courseConfig: DashboardCourseConfigType; + courseConfig: DashboardCourseConfigType | undefined; }>(); -const courseSlug = computed(() => props.courseConfig?.course_slug); -const courseName = computed(() => props.courseConfig?.course_title); +const courseSlug = computed(() => props.courseConfig?.course_slug ?? ""); +const courseName = computed(() => props.courseConfig?.course_title ?? ""); const numberOfMentorWidgets = computed(() => { - return props.courseConfig.widgets.filter((widget) => mentorWidgets.includes(widget)) - .length; + return ( + props.courseConfig?.widgets?.filter((widget) => mentorWidgets.includes(widget)) + .length ?? 0 + ); }); const numberOfProgressWidgets = computed(() => { - return props.courseConfig.widgets.filter((widget) => progressWidgets.includes(widget)) - .length; + return ( + props.courseConfig?.widgets?.filter((widget) => progressWidgets.includes(widget)) + .length ?? 0 + ); }); function hasWidget(widget: WidgetType) { - return props.courseConfig.widgets.includes(widget); + return props.courseConfig?.widgets?.includes(widget) ?? false; } function buttonLink(): string { if (props.courseConfig?.role_key === "Member") { return getLearningPathUrl(props.courseConfig?.course_slug); } else if (props.courseConfig?.role_key === "Expert") { - return "btn-secondary"; + return "linktocockpit"; } else if (props.courseConfig?.role_key === "Supervisor") { - return "btn-secondary"; + return "linktocockpit"; } + return getLearningPathUrl(props.courseConfig?.course_slug); } function hasActionButton(): boolean { - return props.courseConfig.role_key !== "MentorUK"; + return props.courseConfig?.role_key !== "MentorUK"; } diff --git a/client/src/components/dashboard/MentorCompetenceSummary.vue b/client/src/components/dashboard/MentorCompetenceSummary.vue index 1de419b6..c750eb7a 100644 --- a/client/src/components/dashboard/MentorCompetenceSummary.vue +++ b/client/src/components/dashboard/MentorCompetenceSummary.vue @@ -1,7 +1,8 @@ diff --git a/client/src/pages/learningPath/circlePage/DocumentSection.vue b/client/src/pages/learningPath/circlePage/DocumentSection.vue index b1df0aac..a0540334 100644 --- a/client/src/pages/learningPath/circlePage/DocumentSection.vue +++ b/client/src/pages/learningPath/circlePage/DocumentSection.vue @@ -35,7 +35,7 @@ const courseSession = useCurrentCourseSession(); const circleDocumentsResultData = ref([]); async function fetchDocuments() { - const result = await fetchCourseSessionDocuments(courseSession.value?.id); + const result: any = await fetchCourseSessionDocuments(courseSession.value?.id); if (result.length > 0) { circleDocumentsResultData.value = result; } else { diff --git a/client/src/pages/learningPath/learningContentPage/blocks/DocumentListBlock.vue b/client/src/pages/learningPath/learningContentPage/blocks/DocumentListBlock.vue index 9e14634f..9379086b 100644 --- a/client/src/pages/learningPath/learningContentPage/blocks/DocumentListBlock.vue +++ b/client/src/pages/learningPath/learningContentPage/blocks/DocumentListBlock.vue @@ -22,7 +22,7 @@ const documents = ref([]); onMounted(async () => { log.debug("DocumentListBlock mounted"); - const response = await itGetCached(`/api/course/page/${props.content.slug}/`); + const response: any = await itGetCached(`/api/course/page/${props.content.slug}/`); documents.value = response.documents; }); diff --git a/client/src/pages/learningPath/learningContentPage/blocks/EdoniqTestBlock.vue b/client/src/pages/learningPath/learningContentPage/blocks/EdoniqTestBlock.vue index 6178a35d..c1bf2529 100644 --- a/client/src/pages/learningPath/learningContentPage/blocks/EdoniqTestBlock.vue +++ b/client/src/pages/learningPath/learningContentPage/blocks/EdoniqTestBlock.vue @@ -64,7 +64,7 @@ async function startTest() { extendedTimeTest.value = true; } - const response = await itPost("/api/core/edoniq-test/redirect/", { + const response: any = await itPost("/api/core/edoniq-test/redirect/", { learning_content_id: props.content.id, extended_time_test: extendedTimeTest.value, }); diff --git a/client/src/pages/onboarding/vv/CheckoutAddress.vue b/client/src/pages/onboarding/vv/CheckoutAddress.vue index 40875d10..6fabc32d 100644 --- a/client/src/pages/onboarding/vv/CheckoutAddress.vue +++ b/client/src/pages/onboarding/vv/CheckoutAddress.vue @@ -202,7 +202,7 @@ const executePayment = () => { redirect_url: fullHost, address: address.value, product: props.courseType, - }).then((res) => { + }).then((res: any) => { console.log("Going to next page", res.next_step_url); window.location.href = res.next_step_url; }); diff --git a/client/src/router/index.ts b/client/src/router/index.ts index ae99241c..f4d2cd26 100644 --- a/client/src/router/index.ts +++ b/client/src/router/index.ts @@ -12,6 +12,7 @@ import { } from "@/router/guards"; import { addToHistory } from "@/router/history"; import { onboardingRedirect } from "@/router/onboarding"; +import type { RouteLocationNormalized } from "vue-router"; import { createRouter, createWebHistory } from "vue-router"; const router = createRouter({ @@ -404,10 +405,10 @@ router.beforeEach( async function ignoreGuardsForHomeRoute( to: RouteLocationNormalized, from: RouteLocationNormalized, - guard: NavigationGuardNext + guard: any ) { if (to.name !== "home") { - return await guard(to, from); + return await guard(to); } } diff --git a/client/src/services/entities.ts b/client/src/services/entities.ts index c87548c4..3ca68a71 100644 --- a/client/src/services/entities.ts +++ b/client/src/services/entities.ts @@ -16,7 +16,7 @@ export function useEntities() { const countries: Ref = ref([]); const organisations: Ref = ref([]); - itGetCached("/api/core/entities/").then((res) => { + itGetCached("/api/core/entities/").then((res: any) => { countries.value = res.countries; organisations.value = res.organisations; }); diff --git a/client/src/services/files.ts b/client/src/services/files.ts index 169461ff..ec7ad5ce 100644 --- a/client/src/services/files.ts +++ b/client/src/services/files.ts @@ -84,7 +84,7 @@ export async function uploadCircleDocument( throw new Error("No file selected"); } - const startData = await startFileUpload(data, courseSessionId); + const startData: any = await startFileUpload(data, courseSessionId); await uploadFile(startData, data.file); const response = itPost(`/api/core/file/finish/`, { diff --git a/client/src/services/learningMentees.ts b/client/src/services/learningMentees.ts index 7dcee7d8..6550056f 100644 --- a/client/src/services/learningMentees.ts +++ b/client/src/services/learningMentees.ts @@ -69,7 +69,7 @@ export const useLearningMentees = ( error.value = null; itGet(`/api/mentor/${courseSessionId}/summary`) - .then((response) => { + .then((response: any) => { summary.value = response; }) .catch((err) => (error.value = err)) diff --git a/client/src/stores/completion.ts b/client/src/stores/completion.ts index 374a466e..22c46681 100644 --- a/client/src/stores/completion.ts +++ b/client/src/stores/completion.ts @@ -46,7 +46,7 @@ export const useCompletionStore = defineStore({ } if (courseSessionId) { - const completionData = await itPost("/api/course/completion/mark/", { + const completionData: any = await itPost("/api/course/completion/mark/", { page_id: page.id, completion_status: page.completion_status, course_session_id: courseSessionId, diff --git a/client/src/stores/mediaLibrary.ts b/client/src/stores/mediaLibrary.ts index 11e5fb6d..e417b8d6 100644 --- a/client/src/stores/mediaLibrary.ts +++ b/client/src/stores/mediaLibrary.ts @@ -21,7 +21,7 @@ export const useMediaLibraryStore = defineStore({ return this.mediaLibraryPage; } log.debug("load mediaLibraryPageData"); - const mediaLibraryPageData = await itGet(`/api/course/page/${slug}/`); + const mediaLibraryPageData: any = await itGet(`/api/course/page/${slug}/`); if (!mediaLibraryPageData) { throw `No mediaLibraryPageData found with: ${slug}`; diff --git a/client/src/stores/notifications.ts b/client/src/stores/notifications.ts index 9c23676f..8c0a4476 100644 --- a/client/src/stores/notifications.ts +++ b/client/src/stores/notifications.ts @@ -27,7 +27,7 @@ export const useNotificationsStore = defineStore("notifications", () => { } async function updateUnreadCount() { - const data = await itGet("/notifications/api/unread_count/"); + const data: any = await itGet("/notifications/api/unread_count/"); hasUnread.value = data.unread_count !== 0; } diff --git a/client/src/stores/user.ts b/client/src/stores/user.ts index 548c1f51..602c5eb8 100644 --- a/client/src/stores/user.ts +++ b/client/src/stores/user.ts @@ -155,7 +155,7 @@ export const useUserStore = defineStore({ }); }, async fetchUser() { - const data = await itGetCached("/api/core/me/"); + const data: any = await itGetCached("/api/core/me/"); this.$state = data; this.loggedIn = true; await setLocale(data.language); diff --git a/server/vbv_lernwelt/course/graphql/types.py b/server/vbv_lernwelt/course/graphql/types.py index 1e55dbd8..b4eee50a 100644 --- a/server/vbv_lernwelt/course/graphql/types.py +++ b/server/vbv_lernwelt/course/graphql/types.py @@ -95,6 +95,7 @@ class CourseConfigurationObjectType(DjangoObjectType): "enable_circle_documents", "enable_learning_mentor", "enable_competence_certificates", + "is_uk", ) diff --git a/server/vbv_lernwelt/dashboard/graphql/queries.py b/server/vbv_lernwelt/dashboard/graphql/queries.py index d41a46af..d2c2067a 100644 --- a/server/vbv_lernwelt/dashboard/graphql/queries.py +++ b/server/vbv_lernwelt/dashboard/graphql/queries.py @@ -12,6 +12,7 @@ from vbv_lernwelt.course.models import Course, CourseSession, CourseSessionUser from vbv_lernwelt.course_session_group.models import CourseSessionGroup from vbv_lernwelt.dashboard.graphql.types.competence import competences from vbv_lernwelt.dashboard.graphql.types.dashboard import ( + BaseStatisticsType, CourseProgressType, CourseStatisticsType, DashboardConfigType, @@ -33,7 +34,7 @@ class DashboardQuery(graphene.ObjectType): ) mentor_course_statistics = graphene.Field( - CourseStatisticsType, course_id=graphene.ID(required=True) + BaseStatisticsType, course_id=graphene.ID(required=True) ) course_progress = graphene.Field( diff --git a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py index 46caa92f..83f33993 100644 --- a/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py +++ b/server/vbv_lernwelt/dashboard/graphql/types/dashboard.py @@ -87,16 +87,32 @@ class CourseProgressType(graphene.ObjectType): assignment = graphene.Field(ProgressDashboardAssignmentType, required=False) -class CourseStatisticsType(graphene.ObjectType): +class BaseStatisticsType(graphene.ObjectType): _id = graphene.ID(required=True) course_id = graphene.ID(required=True) course_title = graphene.String(required=True) course_slug = graphene.String(required=True) + course_session_selection_ids = graphene.List(graphene.ID, required=True) course_session_properties = graphene.Field( StatisticsCourseSessionPropertiesType, required=True ) - course_session_selection_ids = graphene.List(graphene.ID, required=True) user_selection_ids = graphene.List(graphene.ID, required=False) + assignments = graphene.Field(AssignmentsStatisticsType, required=True) + + def resolve_assignments(root, _info) -> AssignmentsStatisticsType: + user_selection_ids = ( + [str(user) for user in root.user_selection_ids] + if root.user_selection_ids + else None + ) # noqa + return assignments( + course_id=root.course_id, + course_session_selection_ids=root.course_session_selection_ids, + user_selection_ids=user_selection_ids, + ) + + +class CourseStatisticsType(BaseStatisticsType): course_session_selection_metrics = graphene.Field( StatisticsCourseSessionsSelectionMetricType, required=True ) @@ -104,7 +120,6 @@ class CourseStatisticsType(graphene.ObjectType): AttendanceDayPresencesStatisticsType, required=True ) feedback_responses = graphene.Field(FeedbackStatisticsResponsesType, required=True) - assignments = graphene.Field(AssignmentsStatisticsType, required=True) competences = graphene.Field(CompetencesStatisticsType, required=True) def resolve_attendance_day_presences( @@ -145,18 +160,6 @@ class CourseStatisticsType(graphene.ObjectType): ), ) - def resolve_assignments(root, _info) -> AssignmentsStatisticsType: - user_selection_ids = ( - [str(user) for user in root.user_selection_ids] - if root.user_selection_ids - else None - ) # noqa - return assignments( - course_id=root.course_id, - course_session_selection_ids=root.course_session_selection_ids, - user_selection_ids=user_selection_ids, - ) - def resolve_course_session_selection_metrics( root, info ) -> StatisticsCourseSessionsSelectionMetricType: