Fix problems

This commit is contained in:
Daniel Egger 2023-10-10 15:36:56 +02:00
parent 227e9f317d
commit a3e16dc107
21 changed files with 84 additions and 81 deletions

View File

@ -16,6 +16,7 @@ import { computed, onMounted, reactive } from "vue";
import { useTranslation } from "i18next-vue"; import { useTranslation } from "i18next-vue";
import CoursePreviewBar from "@/components/header/CoursePreviewBar.vue"; import CoursePreviewBar from "@/components/header/CoursePreviewBar.vue";
import { import {
getCockpitUrl,
getCompetenceNaviUrl, getCompetenceNaviUrl,
getLearningPathUrl, getLearningPathUrl,
getMediaCenterUrl, getMediaCenterUrl,
@ -135,7 +136,11 @@ onMounted(() => {
<template v-if="courseSessionsStore.currentCourseSessionHasCockpit"> <template v-if="courseSessionsStore.currentCourseSessionHasCockpit">
<router-link <router-link
data-cy="navigation-cockpit-link" data-cy="navigation-cockpit-link"
:to="`${courseSessionsStore.currentCourseSession.course.slug}/cockpit`" :to="
getCockpitUrl(
courseSessionsStore.currentCourseSession.course.slug
)
"
class="nav-item" class="nav-item"
:class="{ 'nav-item--active': inCockpit() }" :class="{ 'nav-item--active': inCockpit() }"
> >

View File

@ -5,6 +5,7 @@ import type { UserState } from "@/stores/user";
import type { CourseSession } from "@/types"; import type { CourseSession } from "@/types";
import { useRouter } from "vue-router"; import { useRouter } from "vue-router";
import { import {
getCockpitUrl,
getCompetenceNaviUrl, getCompetenceNaviUrl,
getLearningPathUrl, getLearningPathUrl,
getMediaCenterUrl, getMediaCenterUrl,
@ -64,7 +65,7 @@ const courseSessionsStore = useCourseSessionsStore();
<li class="mb-6"> <li class="mb-6">
<button <button
data-cy="navigation-mobile-cockpit-link" data-cy="navigation-mobile-cockpit-link"
@click="clickLink(`${courseSession.course.slug}/cockpit`)" @click="clickLink(getCockpitUrl(courseSession.course.slug))"
> >
{{ $t("cockpit.title") }} {{ $t("cockpit.title") }}
</button> </button>

View File

@ -6,7 +6,7 @@ import { useUserStore } from "@/stores/user";
import type { CourseSession } from "@/types"; import type { CourseSession } from "@/types";
import log from "loglevel"; import log from "loglevel";
import { computed, onMounted } from "vue"; import { computed, onMounted } from "vue";
import { getLearningPathUrl } from "@/utils/utils"; import { getCockpitUrl, getLearningPathUrl } from "@/utils/utils";
log.debug("DashboardPage created"); log.debug("DashboardPage created");
@ -21,7 +21,7 @@ const allDueDates = courseSessionsStore.allDueDates();
const getNextStepLink = (courseSession: CourseSession) => { const getNextStepLink = (courseSession: CourseSession) => {
return computed(() => { return computed(() => {
if (courseSessionsStore.hasCockpit(courseSession)) { if (courseSessionsStore.hasCockpit(courseSession)) {
return `${courseSession.course.slug}/cockpit`; return getCockpitUrl(courseSession.course.slug);
} }
return getLearningPathUrl(courseSession.course.slug); return getLearningPathUrl(courseSession.course.slug);
}); });

View File

@ -61,9 +61,7 @@ function editTask(task: AssignmentEvaluationTask) {
const courseSessionDetailResult = useCourseSessionDetailQuery(); const courseSessionDetailResult = useCourseSessionDetailQuery();
const assignmentDetail = computed(() => { const assignmentDetail = computed(() => {
return courseSessionDetailResult.findAssignmentByAssignmentId( return courseSessionDetailResult.findAssignmentByAssignmentId(props.assignment.id);
props.assignment.id.toString()
);
}); });
const dueDate = computed(() => const dueDate = computed(() =>

View File

@ -33,9 +33,7 @@ const state = reactive({
}); });
const assignmentDetail = computed(() => { const assignmentDetail = computed(() => {
return courseSessionDetailResult.findAssignment( return courseSessionDetailResult.findAssignment(props.learningContentAssignment.id);
props.learningContentAssignment.id.toString()
);
}); });
onMounted(async () => { onMounted(async () => {

View File

@ -25,7 +25,7 @@ onMounted(async () => {
const learningContentAssignment = computed(() => { const learningContentAssignment = computed(() => {
return calcLearningContentAssignments( return calcLearningContentAssignments(
learningPathStore.learningPathForUser(courseSession.value.course.slug, userStore.id) learningPathStore.learningPathForUser(courseSession.value.course.slug, userStore.id)
).filter((lc) => lc.id.toString() === props.assignmentId)[0]; ).filter((lc) => lc.id === props.assignmentId)[0];
}); });
</script> </script>

View File

@ -101,7 +101,7 @@ const loadAttendanceData = async () => {
res.data?.course_session_attendance_course?.attendance_user_list ?? []; res.data?.course_session_attendance_course?.attendance_user_list ?? [];
for (const user of attendanceUserList) { for (const user of attendanceUserList) {
if (!user) continue; if (!user) continue;
state.userPresence.set(user.user_id.toString(), user.status === "PRESENT"); state.userPresence.set(user.user_id, user.status === "PRESENT");
} }
if (attendanceUserList.length !== 0) { if (attendanceUserList.length !== 0) {
state.attendanceSaved = true; state.attendanceSaved = true;
@ -194,12 +194,12 @@ watch(
:disabled="state.attendanceSaved" :disabled="state.attendanceSaved"
:checkbox-item="{ :checkbox-item="{
value: true, value: true,
checked: state.userPresence.get(csu.user_id.toString()) as boolean, checked: state.userPresence.get(csu.user_id) as boolean,
}" }"
@toggle=" @toggle="
state.userPresence.set( state.userPresence.set(
csu.user_id.toString(), csu.user_id,
!state.userPresence.get(csu.user_id.toString()) !state.userPresence.get(csu.user_id)
) )
" "
></ItCheckbox> ></ItCheckbox>

View File

@ -47,7 +47,7 @@ const submittables = computed(() => {
return []; return [];
} }
return learningPath.circles return learningPath.circles
.filter((circle) => props.selectedCircle.toString() == circle.id.toString()) .filter((circle) => props.selectedCircle == circle.id)
.flatMap((circle) => { .flatMap((circle) => {
const learningContents = circle.flatLearningContents.filter( const learningContents = circle.flatLearningContents.filter(
(lc) => (lc) =>

View File

@ -12,7 +12,7 @@ const props = defineProps<{
const courseSessionDetailResult = useCourseSessionDetailQuery(); const courseSessionDetailResult = useCourseSessionDetailQuery();
const courseSessionAttendanceCourse = computed(() => { const courseSessionAttendanceCourse = computed(() => {
return courseSessionDetailResult.findAttendanceCourse(props.content.id.toString()); return courseSessionDetailResult.findAttendanceCourse(props.content.id);
}); });
</script> </script>

View File

@ -26,7 +26,7 @@ const courseSession = useCurrentCourseSession();
const courseSessionDetailResult = useCourseSessionDetailQuery(); const courseSessionDetailResult = useCourseSessionDetailQuery();
const courseSessionEdoniqTest = computed(() => { const courseSessionEdoniqTest = computed(() => {
return courseSessionDetailResult.findEdoniqTest(props.content.id.toString()); return courseSessionDetailResult.findEdoniqTest(props.content.id);
}); });
const queryResult = useQuery({ const queryResult = useQuery({

View File

@ -77,9 +77,7 @@ export const useCompetenceStore = defineStore({
); );
if (circleId) { if (circleId) {
criteria = criteria.filter( criteria = criteria.filter((c) => circleId === c.circle.id);
(c) => circleId.toString() === c.circle.id.toString()
);
} }
return criteria; return criteria;

View File

@ -86,13 +86,13 @@ export const useCourseSessionsStore = defineStore("courseSessions", () => {
function getCourseSessionById(courseSessionId: string) { function getCourseSessionById(courseSessionId: string) {
return allCourseSessions.value.find((cs) => { return allCourseSessions.value.find((cs) => {
return courseSessionId.toString() === cs.id.toString(); return courseSessionId === cs.id;
}); });
} }
function switchCourseSessionById(courseSessionId: string) { function switchCourseSessionById(courseSessionId: string) {
const courseSession = allCourseSessions.value.find((cs) => { const courseSession = allCourseSessions.value.find((cs) => {
return courseSessionId.toString() === cs.id.toString(); return courseSessionId === cs.id;
}); });
if (courseSession) { if (courseSession) {
_switchCourseSession(courseSession); _switchCourseSession(courseSession);

View File

@ -10,7 +10,7 @@ function createCourseUrl(courseSlug: string | undefined, specificSub: string): s
return "/"; return "/";
} }
if (["learn", "media", "competence"].includes(specificSub)) { if (["learn", "media", "competence", "cockpit"].includes(specificSub)) {
return `/course/${courseSlug}/${specificSub}`; return `/course/${courseSlug}/${specificSub}`;
} }
return `/course/${courseSlug}`; return `/course/${courseSlug}`;
@ -28,6 +28,10 @@ export function getLearningPathUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "learn"); return createCourseUrl(courseSlug, "learn");
} }
export function getCockpitUrl(courseSlug: string | undefined): string {
return createCourseUrl(courseSlug, "cockpit");
}
export function getAssignmentTypeTitle(assignmentType: AssignmentType): string { export function getAssignmentTypeTitle(assignmentType: AssignmentType): string {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@ -1,10 +1,16 @@
import {checkNavigationLink, EXPERT_LOGIN, login, PARTICIPANT_LOGIN, visitCoursePage} from "./helpers"; import {
checkNavigationLink,
const openMobileNavigation = () => { EXPERT_LOGIN,
cy.get('[data-cy="navigation-mobile-menu-button"]').click(); login,
} PARTICIPANT_LOGIN,
visitCoursePage,
} from "./helpers";
describe("navigation.cy.js", () => { describe("navigation.cy.js", () => {
const openMobileNavigation = () => {
cy.get('[data-cy="navigation-mobile-menu-button"]').click();
};
beforeEach(() => { beforeEach(() => {
cy.manageCommand("cypress_reset"); cy.manageCommand("cypress_reset");
}); });
@ -24,7 +30,9 @@ describe("navigation.cy.js", () => {
checkNavigationLink("navigation-cockpit-link", "cockpit"); checkNavigationLink("navigation-cockpit-link", "cockpit");
checkNavigationLink("navigation-preview-link", "learn"); checkNavigationLink("navigation-preview-link", "learn");
cy.get('[data-cy="navigation-competence-profile-link"]').should("not.exist"); cy.get('[data-cy="navigation-competence-profile-link"]').should(
"not.exist"
);
cy.get('[data-cy="navigation-learning-path-link"]').should("not.exist"); cy.get('[data-cy="navigation-learning-path-link"]').should("not.exist");
}); });
}); });
@ -60,10 +68,14 @@ describe("navigation.cy.js", () => {
it("should have correct expert navigation", () => { it("should have correct expert navigation", () => {
cy.get('[data-cy="navigation-mobile-cockpit-link"]').should("exist"); cy.get('[data-cy="navigation-mobile-cockpit-link"]').should("exist");
cy.get('[data-cy="navigation-mobile-preview-link"]').should("exist"); cy.get('[data-cy="navigation-mobile-preview-link"]').should("exist");
cy.get('[data-cy="navigation-mobile-competence-profile-link"]').should("not.exist"); cy.get('[data-cy="navigation-mobile-competence-profile-link"]').should(
cy.get('[data-cy="navigation-mobile-learning-path-link"]').should("not.exist"); "not.exist"
}) );
}) cy.get('[data-cy="navigation-mobile-learning-path-link"]').should(
"not.exist"
);
});
});
describe("Participant", () => { describe("Participant", () => {
beforeEach(() => { beforeEach(() => {
@ -73,12 +85,19 @@ describe("navigation.cy.js", () => {
}); });
it("should have correct navigation", () => { it("should have correct navigation", () => {
cy.get('[data-cy="navigation-mobile-cockpit-link"]').should("not.exist"); cy.get('[data-cy="navigation-mobile-cockpit-link"]').should(
cy.get('[data-cy="navigation-mobile-preview-link"]').should("not.exist"); "not.exist"
cy.get('[data-cy="navigation-mobile-competence-profile-link"]').should("exist"); );
cy.get('[data-cy="navigation-mobile-learning-path-link"]').should("exist"); cy.get('[data-cy="navigation-mobile-preview-link"]').should(
"not.exist"
);
cy.get('[data-cy="navigation-mobile-competence-profile-link"]').should(
"exist"
);
cy.get('[data-cy="navigation-mobile-learning-path-link"]').should(
"exist"
);
}); });
}); });
}) });
}); });

View File

@ -1,9 +1,14 @@
import {checkNavigationLink, login, PARTICIPANT_LOGIN, visitCoursePage} from "./helpers"; import {
checkNavigationLink,
login,
PARTICIPANT_LOGIN,
visitCoursePage,
} from "./helpers";
describe("preview.cy.js", () => { describe("preview.cy.js", () => {
beforeEach(() => { beforeEach(() => {
cy.manageCommand("cypress_reset"); cy.manageCommand("cypress_reset");
}) });
describe("Expert / Trainer", () => { describe("Expert / Trainer", () => {
beforeEach(() => { beforeEach(() => {
@ -41,5 +46,5 @@ describe("preview.cy.js", () => {
visitCoursePage("competence"); visitCoursePage("competence");
cy.get('[data-cy="course-preview-bar"]').should("not.exist"); cy.get('[data-cy="course-preview-bar"]').should("not.exist");
}); });
}) });
}); });

View File

@ -24,6 +24,12 @@ def request_assignment_completion_status(request, assignment_id, course_session_
"evaluation_passed", "evaluation_passed",
"learning_content_page_id", "learning_content_page_id",
) )
return Response(status=200, data=qs)
# Convert the learning_content_page_id to a string
data = list(qs) # Evaluate the queryset
for item in data:
item["learning_content_page_id"] = str(item["learning_content_page_id"])
return Response(status=200, data=data)
raise PermissionDenied() raise PermissionDenied()

View File

@ -40,4 +40,4 @@ class UserSerializer(serializers.ModelSerializer):
role=CourseSessionUser.Role.EXPERT, user=obj role=CourseSessionUser.Role.EXPERT, user=obj
) )
return [csu.course_session.id for csu in qs] return [str(csu.course_session.id) for csu in qs]

View File

@ -294,21 +294,6 @@ class CourseSessionUser(models.Model):
] ]
ordering = ["user__last_name", "user__first_name", "user__email"] ordering = ["user__last_name", "user__first_name", "user__email"]
def to_dict(self):
return {
"session_id": self.course_session.id,
"session_title": self.course_session.title,
"user_id": self.user.id,
"first_name": self.user.first_name,
"last_name": self.user.last_name,
"email": self.user.email,
"avatar_url": self.user.avatar_url,
"role": self.role,
"circles": self.expert.all().values(
"id", "title", "slug", "translation_key"
),
}
class CircleDocument(models.Model): class CircleDocument(models.Model):
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)

View File

@ -48,7 +48,7 @@ class CourseCompletionApiTestCase(APITestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response_json), 1) self.assertEqual(len(response_json), 1)
self.assertEqual(response_json[0]["page_id"], learning_content.id) self.assertEqual(response_json[0]["page_id"], str(learning_content.id))
self.assertEqual( self.assertEqual(
response_json[0]["page_type"], "learnpath.LearningContentPlaceholder" response_json[0]["page_type"], "learnpath.LearningContentPlaceholder"
) )
@ -67,7 +67,7 @@ class CourseCompletionApiTestCase(APITestCase):
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response_json), 1) self.assertEqual(len(response_json), 1)
self.assertEqual(response_json[0]["page_id"], learning_content.id) self.assertEqual(response_json[0]["page_id"], str(learning_content.id))
self.assertEqual( self.assertEqual(
response_json[0]["page_type"], "learnpath.LearningContentPlaceholder" response_json[0]["page_type"], "learnpath.LearningContentPlaceholder"
) )
@ -86,7 +86,7 @@ class CourseCompletionApiTestCase(APITestCase):
response_json = response.json() response_json = response.json()
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(len(response_json), 1) self.assertEqual(len(response_json), 1)
self.assertEqual(response_json[0]["page_id"], learning_content.id) self.assertEqual(response_json[0]["page_id"], str(learning_content.id))
self.assertEqual( self.assertEqual(
response_json[0]["page_type"], "learnpath.LearningContentPlaceholder" response_json[0]["page_type"], "learnpath.LearningContentPlaceholder"
) )

View File

@ -40,7 +40,7 @@ class CourseCompletionApiTestCase(APITestCase):
self.assertEqual(len(response.json()), 1) self.assertEqual(len(response.json()), 1)
print(json.dumps(response.json(), indent=4)) print(json.dumps(response.json(), indent=4))
self.assertEqual(response.json()[0]["id"], self.course_session.id) self.assertEqual(response.json()[0]["id"], str(self.course_session.id))
def test_api_superUser_canAccessEveryCourseSession(self): def test_api_superUser_canAccessEveryCourseSession(self):
self.client.login(username="admin", password="test") self.client.login(username="admin", password="test")
@ -50,4 +50,4 @@ class CourseCompletionApiTestCase(APITestCase):
self.assertEqual(len(response.json()), 1) self.assertEqual(len(response.json()), 1)
print(json.dumps(response.json(), indent=4)) print(json.dumps(response.json(), indent=4))
self.assertEqual(response.json()[0]["id"], self.course_session.id) self.assertEqual(response.json()[0]["id"], str(self.course_session.id))

View File

@ -147,22 +147,6 @@ def get_course_sessions(request):
return Response({"error": str(e)}, status=404) return Response({"error": str(e)}, status=404)
@api_view(["GET"])
def get_course_session_users(request, course_session_id):
try:
qs = CourseSessionUser.objects.filter(
course_session_id=course_session_id
).distinct()
user_data = [csu.to_dict() for csu in qs]
return Response(status=200, data=user_data)
except PermissionDenied as e:
raise e
except Exception as e:
logger.error(e)
return Response({"error": str(e)}, status=404)
@api_view(["POST"]) @api_view(["POST"])
def document_upload_start(request): def document_upload_start(request):
serializer = DocumentUploadStartInputSerializer(data=request.data) serializer = DocumentUploadStartInputSerializer(data=request.data)